diff --git a/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/ExampleEndpointFactory.ts b/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/ExampleEndpointFactory.ts index de214f06683..6316dfe8985 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/ExampleEndpointFactory.ts +++ b/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/ExampleEndpointFactory.ts @@ -111,7 +111,10 @@ export class ExampleEndpointFactory { if (example != null) { if (endpoint.response?.type === "json") { responseExamples.push([undefined, EndpointResponseExample.withoutStreaming(example)]); - } else if (endpoint.response?.type === "streamingJson") { + } else if ( + endpoint.response?.type === "streamingJson" || + endpoint.response?.type === "streamingSse" + ) { responseExamples.push([undefined, EndpointResponseExample.withStreaming([example])]); } } @@ -131,7 +134,10 @@ export class ExampleEndpointFactory { if (example != null) { if (endpoint.response?.type === "json") { responseExamples.push([exampleId, EndpointResponseExample.withoutStreaming(example)]); - } else if (endpoint.response?.type === "streamingJson") { + } else if ( + endpoint.response?.type === "streamingJson" || + endpoint.response?.type === "streamingSse" + ) { responseExamples.push([exampleId, EndpointResponseExample.withStreaming([example])]); } } @@ -493,7 +499,7 @@ function getResponseSchema(response: ResponseWithExample | null | undefined): Sc if (response == null) { return undefined; } - if (response.type !== "json" && response.type !== "streamingJson") { + if (response.type !== "json" && response.type !== "streamingJson" && response.type !== "streamingSse") { return { type: "unsupported" }; } return { type: "present", schema: response.schema, examples: response.fullExamples ?? [] }; diff --git a/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/endpoint/convertResponse.ts b/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/endpoint/convertResponse.ts index 0eec3bd61cc..2e41fa65272 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/endpoint/convertResponse.ts +++ b/packages/cli/api-importers/openapi/openapi-ir-parser/src/openapi/v3/converters/endpoint/convertResponse.ts @@ -171,15 +171,14 @@ function convertResolvedResponse({ return ResponseWithExample.streamingSse({ description: resolvedResponse.description, responseProperty: undefined, - schema: convertSchemaWithExampleToSchema( - convertSchema( - textEventStreamObject.schema, - false, - context, - responseBreadcrumbs, - source, - namespace - ) + fullExamples: textEventStreamObject.examples, + schema: convertSchema( + textEventStreamObject.schema, + false, + context, + responseBreadcrumbs, + source, + namespace ), source }); @@ -209,15 +208,14 @@ function convertResolvedResponse({ return ResponseWithExample.streamingSse({ description: resolvedResponse.description, responseProperty: undefined, - schema: convertSchemaWithExampleToSchema( - convertSchema( - jsonMediaObject.schema, - false, - context, - responseBreadcrumbs, - source, - namespace - ) + fullExamples: jsonMediaObject.examples, + schema: convertSchema( + jsonMediaObject.schema, + false, + context, + responseBreadcrumbs, + source, + namespace ), source }); diff --git a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/switchboard.json b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/switchboard.json index df185a8d563..72baea8c09d 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/switchboard.json +++ b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/switchboard.json @@ -2101,6 +2101,27 @@ service: "root.SessionsEventsRequestUnprocessableEntityError", "root.SessionsEventsRequestInternalServerError", ], + "examples": [ + { + "path-parameters": { + "id": "6aac6f73-bd89-4a76-ab32-5a6c422e8b0b", + }, + "response": { + "stream": [ + { + "data": { + "code": "code", + "event": "event", + "message": "message", + }, + "event": "error", + "id": 1, + "retry": 1, + }, + ], + }, + }, + ], "method": "GET", "pagination": undefined, "path": "/sessions/{id}/events", @@ -2771,6 +2792,18 @@ service: - root.SessionsEventsRequestNotFoundError - root.SessionsEventsRequestUnprocessableEntityError - root.SessionsEventsRequestInternalServerError + examples: + - path-parameters: + id: 6aac6f73-bd89-4a76-ab32-5a6c422e8b0b + response: + stream: + - event: error + data: + code: code + event: event + message: message + id: 1 + retry: 1 audiences: - public source: diff --git a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/x-fern-streaming-with-sse.json b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/x-fern-streaming-with-sse.json index 59b19cf5096..437e6f6ba86 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/x-fern-streaming-with-sse.json +++ b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-docs/x-fern-streaming-with-sse.json @@ -51,6 +51,18 @@ "create": { "auth": false, "docs": undefined, + "examples": [ + { + "request": { + "prompt": "prompt", + }, + "response": { + "stream": [ + "string", + ], + }, + }, + ], "method": "POST", "pagination": undefined, "path": "/completions/chat", @@ -103,6 +115,12 @@ docs: Success! type: string format: sse + examples: + - request: + prompt: prompt + response: + stream: + - string source: openapi: ../openapi.yml ", diff --git a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/switchboard.json b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/switchboard.json index 4fb7796bd9c..c996cdd3971 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/switchboard.json +++ b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/switchboard.json @@ -3082,20 +3082,17 @@ "generatedRequestName": "SessionsEventsRequest", "response": { "description": "OK", + "fullExamples": [], "schema": { "value": { - "commonProperties": [], "description": "Each oneOf object in the array represents one possible Server Sent Events (SSE) message, serialized as UTF-8 text according to the SSE specification.", "discriminantProperty": "event", "generatedName": "SessionsEventsResponse", "title": "Server Sent Events", "schemas": { "status": { - "allOf": [], "properties": [ { - "conflict": {}, - "generatedName": "sessionsEventsResponseStatusData", "key": "data", "schema": { "generatedName": "SessionsEventsResponseStatusData", @@ -3107,55 +3104,59 @@ "type": "reference" }, "audiences": [], + "conflict": {}, + "generatedName": "sessionsEventsResponseStatusData", "readonly": false }, { - "conflict": {}, - "generatedName": "sessionsEventsResponseStatusId", "key": "id", "schema": { "generatedName": "sessionsEventsResponseStatusId", "title": "Event status", "value": { - "description": "The event ID.", + "generatedName": "SessionsEventsResponseStatusId", "schema": { "type": "int" }, - "generatedName": "SessionsEventsResponseStatusId", + "description": "The event ID.", "groupName": [], "type": "primitive" }, "groupName": [], "type": "optional" }, - "audiences": [] + "audiences": [], + "conflict": {}, + "generatedName": "sessionsEventsResponseStatusId" }, { - "conflict": {}, - "generatedName": "sessionsEventsResponseStatusRetry", "key": "retry", "schema": { "generatedName": "sessionsEventsResponseStatusRetry", "title": "Event status", "value": { - "description": "The retry time in milliseconds.", + "generatedName": "SessionsEventsResponseStatusRetry", "schema": { "type": "int" }, - "generatedName": "SessionsEventsResponseStatusRetry", + "description": "The retry time in milliseconds.", "groupName": [], "type": "primitive" }, "groupName": [], "type": "optional" }, - "audiences": [] + "audiences": [], + "conflict": {}, + "generatedName": "sessionsEventsResponseStatusRetry" } ], - "allOfPropertyConflicts": [], "generatedName": "SessionsEventsResponseStatus", "title": "Event status", + "allOf": [], + "allOfPropertyConflicts": [], "groupName": [], + "fullExamples": [], "additionalProperties": false, "source": { "file": "../openapi.yml", @@ -3164,11 +3165,8 @@ "type": "object" }, "error": { - "allOf": [], "properties": [ { - "conflict": {}, - "generatedName": "sessionsEventsResponseErrorData", "key": "data", "schema": { "generatedName": "SessionsEventsResponseErrorData", @@ -3180,55 +3178,59 @@ "type": "reference" }, "audiences": [], + "conflict": {}, + "generatedName": "sessionsEventsResponseErrorData", "readonly": false }, { - "conflict": {}, - "generatedName": "sessionsEventsResponseErrorId", "key": "id", "schema": { "generatedName": "sessionsEventsResponseErrorId", "title": "Event error", "value": { - "description": "The event ID.", + "generatedName": "SessionsEventsResponseErrorId", "schema": { "type": "int" }, - "generatedName": "SessionsEventsResponseErrorId", + "description": "The event ID.", "groupName": [], "type": "primitive" }, "groupName": [], "type": "optional" }, - "audiences": [] + "audiences": [], + "conflict": {}, + "generatedName": "sessionsEventsResponseErrorId" }, { - "conflict": {}, - "generatedName": "sessionsEventsResponseErrorRetry", "key": "retry", "schema": { "generatedName": "sessionsEventsResponseErrorRetry", "title": "Event error", "value": { - "description": "The retry time in milliseconds.", + "generatedName": "SessionsEventsResponseErrorRetry", "schema": { "type": "int" }, - "generatedName": "SessionsEventsResponseErrorRetry", + "description": "The retry time in milliseconds.", "groupName": [], "type": "primitive" }, "groupName": [], "type": "optional" }, - "audiences": [] + "audiences": [], + "conflict": {}, + "generatedName": "sessionsEventsResponseErrorRetry" } ], - "allOfPropertyConflicts": [], "generatedName": "SessionsEventsResponseError", "title": "Event error", + "allOf": [], + "allOfPropertyConflicts": [], "groupName": [], + "fullExamples": [], "additionalProperties": false, "source": { "file": "../openapi.yml", @@ -3237,6 +3239,7 @@ "type": "object" } }, + "commonProperties": [], "groupName": [], "source": { "file": "../openapi.yml", @@ -3313,7 +3316,86 @@ "authed": false, "method": "GET", "path": "/sessions/{id}/events", - "examples": [], + "examples": [ + { + "pathParameters": [ + { + "name": "id", + "value": { + "value": { + "value": "6aac6f73-bd89-4a76-ab32-5a6c422e8b0b", + "type": "string" + }, + "type": "primitive" + } + } + ], + "queryParameters": [], + "headers": [], + "response": { + "value": [ + { + "value": { + "value": { + "event": { + "value": { + "value": "error", + "type": "string" + }, + "type": "primitive" + }, + "data": { + "properties": { + "code": { + "value": { + "value": "code", + "type": "string" + }, + "type": "primitive" + }, + "event": { + "value": { + "value": "event", + "type": "string" + }, + "type": "primitive" + }, + "message": { + "value": { + "value": "message", + "type": "string" + }, + "type": "primitive" + } + }, + "type": "object" + }, + "id": { + "value": { + "value": 1, + "type": "int" + }, + "type": "primitive" + }, + "retry": { + "value": { + "value": 1, + "type": "int" + }, + "type": "primitive" + } + }, + "type": "discriminated" + }, + "type": "oneOf" + } + ], + "type": "withStreaming" + }, + "codeSamples": [], + "type": "full" + } + ], "source": { "file": "../openapi.yml", "type": "openapi" diff --git a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/x-fern-streaming-with-sse.json b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/x-fern-streaming-with-sse.json index 18f017255d5..7eaf9776ef7 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/x-fern-streaming-with-sse.json +++ b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi-ir/x-fern-streaming-with-sse.json @@ -40,11 +40,12 @@ }, "response": { "description": "Success!", + "fullExamples": [], "schema": { + "generatedName": "ChatCompletionsCreateResponse", "schema": { "type": "string" }, - "generatedName": "ChatCompletionsCreateResponse", "groupName": [], "type": "primitive" }, @@ -59,7 +60,39 @@ "authed": false, "method": "POST", "path": "/completions/chat", - "examples": [], + "examples": [ + { + "pathParameters": [], + "queryParameters": [], + "headers": [], + "request": { + "properties": { + "prompt": { + "value": { + "value": "prompt", + "type": "string" + }, + "type": "primitive" + } + }, + "type": "object" + }, + "response": { + "value": [ + { + "value": { + "value": "string", + "type": "string" + }, + "type": "primitive" + } + ], + "type": "withStreaming" + }, + "codeSamples": [], + "type": "full" + } + ], "source": { "file": "../openapi.yml", "type": "openapi" diff --git a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/switchboard.json b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/switchboard.json index 6eb7e548a62..5908573f6e9 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/switchboard.json +++ b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/switchboard.json @@ -1993,6 +1993,27 @@ service: "root.UnprocessableEntityError", "root.InternalServerError", ], + "examples": [ + { + "path-parameters": { + "id": "6aac6f73-bd89-4a76-ab32-5a6c422e8b0b", + }, + "response": { + "stream": [ + { + "data": { + "code": "code", + "event": "event", + "message": "message", + }, + "event": "error", + "id": 1, + "retry": 1, + }, + ], + }, + }, + ], "method": "GET", "pagination": undefined, "path": "/sessions/{id}/events", @@ -2663,6 +2684,18 @@ service: - root.NotFoundError - root.UnprocessableEntityError - root.InternalServerError + examples: + - path-parameters: + id: 6aac6f73-bd89-4a76-ab32-5a6c422e8b0b + response: + stream: + - event: error + data: + code: code + event: event + message: message + id: 1 + retry: 1 audiences: - public source: diff --git a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/x-fern-streaming-with-sse.json b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/x-fern-streaming-with-sse.json index 59b19cf5096..437e6f6ba86 100644 --- a/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/x-fern-streaming-with-sse.json +++ b/packages/cli/api-importers/openapi/openapi-ir-to-fern-tests/src/__test__/__snapshots__/openapi/x-fern-streaming-with-sse.json @@ -51,6 +51,18 @@ "create": { "auth": false, "docs": undefined, + "examples": [ + { + "request": { + "prompt": "prompt", + }, + "response": { + "stream": [ + "string", + ], + }, + }, + ], "method": "POST", "pagination": undefined, "path": "/completions/chat", @@ -103,6 +115,12 @@ docs: Success! type: string format: sse + examples: + - request: + prompt: prompt + response: + stream: + - string source: openapi: ../openapi.yml ", diff --git a/packages/cli/api-importers/openapi/openapi-ir/fern/definition/parseIr.yml b/packages/cli/api-importers/openapi/openapi-ir/fern/definition/parseIr.yml index 09ec060d9c8..40a6d2a6b5c 100644 --- a/packages/cli/api-importers/openapi/openapi-ir/fern/definition/parseIr.yml +++ b/packages/cli/api-importers/openapi/openapi-ir/fern/definition/parseIr.yml @@ -112,7 +112,7 @@ types: file: finalIr.FileResponse json: JsonResponseWithExample text: finalIr.TextResponse - streamingSse: finalIr.JsonResponse + streamingSse: JsonResponseWithExample streamingText: finalIr.TextResponse streamingJson: type: JsonResponseWithExample diff --git a/packages/cli/api-importers/openapi/openapi-ir/src/sdk/api/resources/parseIr/types/ResponseWithExample.ts b/packages/cli/api-importers/openapi/openapi-ir/src/sdk/api/resources/parseIr/types/ResponseWithExample.ts index 34280af8f90..baf4059d08f 100644 --- a/packages/cli/api-importers/openapi/openapi-ir/src/sdk/api/resources/parseIr/types/ResponseWithExample.ts +++ b/packages/cli/api-importers/openapi/openapi-ir/src/sdk/api/resources/parseIr/types/ResponseWithExample.ts @@ -27,7 +27,7 @@ export declare namespace ResponseWithExample { type: "text"; } - interface StreamingSse extends FernOpenapiIr.JsonResponse, _Utils { + interface StreamingSse extends FernOpenapiIr.JsonResponseWithExample, _Utils { type: "streamingSse"; } @@ -47,7 +47,7 @@ export declare namespace ResponseWithExample { file: (value: FernOpenapiIr.FileResponse) => _Result; json: (value: FernOpenapiIr.JsonResponseWithExample) => _Result; text: (value: FernOpenapiIr.TextResponse) => _Result; - streamingSse: (value: FernOpenapiIr.JsonResponse) => _Result; + streamingSse: (value: FernOpenapiIr.JsonResponseWithExample) => _Result; streamingText: (value: FernOpenapiIr.TextResponse) => _Result; streamingJson: (value: FernOpenapiIr.JsonResponseWithExample) => _Result; _other: (value: { type: string }) => _Result; @@ -94,7 +94,7 @@ export const ResponseWithExample = { }; }, - streamingSse: (value: FernOpenapiIr.JsonResponse): FernOpenapiIr.ResponseWithExample.StreamingSse => { + streamingSse: (value: FernOpenapiIr.JsonResponseWithExample): FernOpenapiIr.ResponseWithExample.StreamingSse => { return { ...value, type: "streamingSse", diff --git a/packages/cli/api-importers/openapi/openapi-ir/src/sdk/serialization/resources/parseIr/types/ResponseWithExample.ts b/packages/cli/api-importers/openapi/openapi-ir/src/sdk/serialization/resources/parseIr/types/ResponseWithExample.ts index a6d778c5a20..07a5080f8a6 100644 --- a/packages/cli/api-importers/openapi/openapi-ir/src/sdk/serialization/resources/parseIr/types/ResponseWithExample.ts +++ b/packages/cli/api-importers/openapi/openapi-ir/src/sdk/serialization/resources/parseIr/types/ResponseWithExample.ts @@ -8,7 +8,6 @@ import * as core from "../../../../core"; import { FileResponse } from "../../finalIr/types/FileResponse"; import { JsonResponseWithExample } from "./JsonResponseWithExample"; import { TextResponse } from "../../finalIr/types/TextResponse"; -import { JsonResponse } from "../../finalIr/types/JsonResponse"; export const ResponseWithExample: core.serialization.Schema< serializers.ResponseWithExample.Raw, @@ -18,7 +17,7 @@ export const ResponseWithExample: core.serialization.Schema< file: FileResponse, json: JsonResponseWithExample, text: TextResponse, - streamingSse: JsonResponse, + streamingSse: JsonResponseWithExample, streamingText: TextResponse, streamingJson: JsonResponseWithExample, }) @@ -65,7 +64,7 @@ export declare namespace ResponseWithExample { type: "text"; } - interface StreamingSse extends JsonResponse.Raw { + interface StreamingSse extends JsonResponseWithExample.Raw { type: "streamingSse"; } diff --git a/packages/cli/cli/versions.yml b/packages/cli/cli/versions.yml index e29058c9734..64db9050dcc 100644 --- a/packages/cli/cli/versions.yml +++ b/packages/cli/cli/versions.yml @@ -1,3 +1,11 @@ +- changelogEntry: + - summary: | + The Fern CLI now supports generating examples for streaming SSE (server-sent-event) + endpoints. + type: fix + irVersion: 53 + version: 0.46.3 + - changelogEntry: - summary: | The Fern CLI now supports parsing a `logo` option from your frontmatter. If