UNPKG

@lokalise/api-contracts

Version:
139 lines 5.34 kB
/** * @deprecated Use `defineApiContract` with `sseResponse()` or `anyOfResponses()` instead. This function will be removed in a future version. * @example * ```typescript * // SSE-only Before (deprecated): * const contract = buildSseContract({ * method: 'get', * pathResolver: () => '/stream', * serverSentEventSchemas: { event: eventSchema }, * }) * * // SSE-only After (recommended): * const contract = defineApiContract({ * method: 'get', * pathResolver: () => '/stream', * responsesByStatusCode: { 200: sseResponse({ event: eventSchema }) }, * }) * * // Dual-mode Before (deprecated): * const contract = buildSseContract({ * method: 'post', * pathResolver: () => '/stream', * requestBodySchema: bodySchema, * successResponseBodySchema: jsonSchema, * serverSentEventSchemas: { chunk: chunkSchema }, * }) * * // Dual-mode After (recommended): * const contract = defineApiContract({ * method: 'post', * pathResolver: () => '/stream', * requestBodySchema: bodySchema, * responsesByStatusCode: { * 200: anyOfResponses([sseResponse({ chunk: chunkSchema }), jsonSchema]), * }, * }) * ``` * * Builds SSE (Server-Sent Events) and dual-mode contracts. * * This builder supports two contract types: * * **SSE-only contracts**: Pure streaming endpoints that only return SSE events. * Use these for real-time notifications, live feeds, or any endpoint that only streams data. * * **Dual-mode contracts**: Hybrid endpoints that support both synchronous JSON responses * AND SSE streaming from the same URL. The response mode is determined by the client's * `Accept` header (`application/json` for sync, `text/event-stream` for SSE). * This is ideal for AI/LLM APIs (like OpenAI) where clients can choose between * getting the full response at once or streaming it token-by-token. * * The contract type is automatically determined based on the presence of `successResponseBodySchema`: * * | `successResponseBodySchema` | `requestBodySchema` | Result | * |----------------------------|---------------------|--------| * | ❌ | ❌ | SSE-only GET | * | ❌ | ✅ | SSE-only POST/PUT/PATCH | * | ✅ | ❌ | Dual-mode GET | * | ✅ | ✅ | Dual-mode POST/PUT/PATCH | * * @example * ```typescript * // SSE-only: Pure streaming endpoint (e.g., live notifications) * const notificationsStream = buildSseContract({ * pathResolver: () => '/api/notifications/stream', * requestPathParamsSchema: z.object({}), * requestQuerySchema: z.object({ userId: z.string().optional() }), * requestHeaderSchema: z.object({}), * serverSentEventSchemas: { * notification: z.object({ id: z.string(), message: z.string() }), * }, * }) * * // Dual-mode: Same endpoint supports both JSON and SSE (e.g., OpenAI-style API) * // - Accept: application/json → returns { reply, usage } immediately * // - Accept: text/event-stream → streams chunk events, then done event * const chatCompletion = buildSseContract({ * method: 'POST', * pathResolver: () => '/api/chat/completions', * requestPathParamsSchema: z.object({}), * requestQuerySchema: z.object({}), * requestHeaderSchema: z.object({}), * requestBodySchema: z.object({ message: z.string() }), * successResponseBodySchema: z.object({ reply: z.string(), usage: z.object({ tokens: z.number() }) }), * serverSentEventSchemas: { * chunk: z.object({ delta: z.string() }), * done: z.object({ usage: z.object({ total: z.number() }) }), * }, * }) * ``` */ // Helper to build base contract fields // biome-ignore lint/suspicious/noExplicitAny: Config union type function buildBaseFields(config, hasBody) { return { pathResolver: config.pathResolver, requestPathParamsSchema: config.requestPathParamsSchema, requestQuerySchema: config.requestQuerySchema, requestHeaderSchema: config.requestHeaderSchema, requestBodySchema: hasBody ? config.requestBodySchema : undefined, serverSentEventSchemas: config.serverSentEventSchemas, metadata: config.metadata, description: config.description, summary: config.summary, tags: config.tags, }; } // Helper to determine method function determineMethod(config) { return config.method; } // Implementation export function buildSseContract(config) { const hasSyncResponseBody = 'successResponseBodySchema' in config && config.successResponseBodySchema !== undefined; const hasBody = 'requestBodySchema' in config && config.requestBodySchema !== undefined; const base = buildBaseFields(config, hasBody); if (hasSyncResponseBody) { // Dual-mode contract return { ...base, method: determineMethod(config), successResponseBodySchema: config .successResponseBodySchema, responseHeaderSchema: config.responseHeaderSchema, responseBodySchemasByStatusCode: config .responseBodySchemasByStatusCode, isDualMode: true, }; } // SSE-only contract return { ...base, method: determineMethod(config), responseBodySchemasByStatusCode: config .responseBodySchemasByStatusCode, isSSE: true, }; } //# sourceMappingURL=sseContractBuilders.js.map