@typespec/openapi3
Version:
TypeSpec library for emitting OpenAPI 3.0 and OpenAPI 3.1 from the TypeSpec REST protocol binding and converting OpenAPI3 to TypeSpec
125 lines • 4.74 kB
JavaScript
import { attachExtensions } from "./attach-extensions.js";
export async function resolveSSEModule() {
const [streams, events, sse] = await Promise.all([
tryImportStreams(),
tryImportEvents(),
tryImportSSE(),
]);
if (streams === undefined || events === undefined || sse === undefined) {
return undefined;
}
return {
isSSEStream: (program, type) => {
if (type.kind !== "Model")
return false;
// Check if this is a stream - we rely on contentType filtering in the caller
const streamOf = streams.getStreamOf(program, type);
return !!streamOf;
},
getSSEStreamType: (program, type) => {
if (type.kind !== "Model")
return undefined;
return streams.getStreamOf(program, type);
},
attachSSEItemSchema: (program, options, streamType, emitObject, getSchemaForType) => {
// Check if the stream type is a union with @events decorator
if (streamType.kind !== "Union")
return;
const isEventsUnion = events.isEvents(program, streamType);
if (!isEventsUnion)
return;
// Get event definitions
const [eventDefinitions, diagnostics] = events.unsafe_getEventDefinitions(program, streamType);
if (diagnostics && diagnostics.length) {
// TODO: Handle diagnostics
return;
}
if (!eventDefinitions || eventDefinitions.length === 0)
return;
// Build the itemSchema structure
// The itemSchema should have a oneOf with all event variants
const oneOfSchemas = [];
for (const eventDef of eventDefinitions) {
const variant = eventDef.root;
const eventType = eventDef.eventType;
const payloadType = eventDef.payloadType;
const payloadContentType = eventDef.payloadContentType || "application/json";
// Check if this is a terminal event
const isTerminal = sse.isTerminalEvent(program, variant);
// Build the oneOf variant schema
const variantSchema = {
properties: {
data: {
contentMediaType: payloadContentType,
},
},
};
if (isTerminal) {
// If the variant type is a string literal, use it as const
if (variant.type.kind === "String") {
variantSchema.properties.data.const = variant.type.value;
variantSchema.properties.data.contentMediaType =
payloadContentType;
}
}
else {
// For non-terminal events, add the event type
if (eventType) {
variantSchema.properties.event = {
const: eventType,
};
}
// Add contentSchema for the payload
variantSchema.properties.data.contentSchema =
getSchemaForType(payloadType);
}
// Attach any extensions from the union variant
attachExtensions(program, variant, variantSchema);
oneOfSchemas.push(variantSchema);
}
// Set the itemSchema with the base structure and oneOf
emitObject.itemSchema = {
type: "object",
properties: {
event: {
type: "string",
},
data: {
type: "string",
},
},
required: ["event"],
oneOf: oneOfSchemas,
};
},
};
}
async function tryImportStreams() {
try {
const module = await import("@typespec/streams");
return module;
}
catch {
return undefined;
}
}
async function tryImportEvents() {
try {
const eventsModule = await import("@typespec/events");
const experimentalModule = await import("@typespec/events/experimental");
return { ...eventsModule, ...experimentalModule };
}
catch {
return undefined;
}
}
async function tryImportSSE() {
try {
const module = await import("@typespec/sse");
return module;
}
catch {
return undefined;
}
}
//# sourceMappingURL=sse-module.js.map