@bagelink/sdk 1.12.47 → 1.12.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -60,6 +60,24 @@ function extractSSEEventTypes(operation) {
60
60
  }
61
61
  return types.size > 0 ? Array.from(types).sort() : void 0;
62
62
  }
63
+ function extractSSEEventSchemas(operation) {
64
+ const responses = operation.responses || {};
65
+ for (const [statusCode, response] of Object.entries(responses)) {
66
+ if (!statusCode.startsWith("2")) continue;
67
+ if ("$ref" in response) continue;
68
+ const eventStream = response.content?.["text/event-stream"];
69
+ const schemas = eventStream?.["x-event-schemas"];
70
+ if (schemas && Object.keys(schemas).length > 0) {
71
+ return Object.fromEntries(
72
+ Object.entries(schemas).map(([event, ref]) => [
73
+ event,
74
+ ref.replace(/^#\/components\/schemas\//, "")
75
+ ])
76
+ );
77
+ }
78
+ }
79
+ return void 0;
80
+ }
63
81
  function extractSSEEventInfo(operation) {
64
82
  const description = operation.description || "";
65
83
  const eventInfos = [];
@@ -397,6 +415,7 @@ const functionsInventory = {};
397
415
  const pathOperations = [];
398
416
  const streamEventTypes = {};
399
417
  const streamEventInfo = {};
418
+ const streamEventSchemas = {};
400
419
  function collectTypeForImportStatement(typeName) {
401
420
  typeName = typeName.trim().replace("[]", "");
402
421
  if (typeName.includes("|")) {
@@ -603,6 +622,8 @@ function generateStreamFunction(method, path, formattedPath, allParams, requestB
603
622
  * .on('${t}', (data) => console.log(data))`).join("") : "\n * .on('message', (data) => console.log(data))";
604
623
  const typeAnnotation = eventTypes?.length ? `StreamController<${streamTypeName}>` : "StreamController";
605
624
  const pathForUrl = formattedPath.startsWith("`") ? formattedPath.slice(1, -1) : formattedPath.slice(1, -1);
625
+ const streamParams = allParams ? `${allParams}, options?: SSEStreamOptions` : `options?: SSEStreamOptions`;
626
+ const regularParams = allParams;
606
627
  if (method === "post") {
607
628
  return `{
608
629
  /**
@@ -616,14 +637,14 @@ function generateStreamFunction(method, path, formattedPath, allParams, requestB
616
637
  * // Close stream when needed
617
638
  * stream.close()
618
639
  */
619
- stream: (${allParams}, options?: SSEStreamOptions): ${typeAnnotation} => {
640
+ stream: (${streamParams}): ${typeAnnotation} => {
620
641
  const url = \`\${${baseUrlRef}}${pathForUrl}\`
621
642
  return createSSEStreamPost<${streamTypeName}>(url, ${bodyVar}, options)
622
643
  },
623
644
  /**
624
645
  * Regular POST request (non-streaming)
625
646
  */
626
- post: async (${allParams}): Promise<AxiosResponse<any>> => {
647
+ post: async (${regularParams}): Promise<AxiosResponse<any>> => {
627
648
  return axios.post(${formattedPath}, ${bodyVar})
628
649
  }
629
650
  }`;
@@ -640,14 +661,14 @@ function generateStreamFunction(method, path, formattedPath, allParams, requestB
640
661
  * // Close stream when needed
641
662
  * stream.close()
642
663
  */
643
- stream: (${allParams}, options?: SSEStreamOptions): ${typeAnnotation} => {
664
+ stream: (${streamParams}): ${typeAnnotation} => {
644
665
  const url = \`\${${baseUrlRef}}${pathForUrl}\`
645
666
  return createSSEStream<${streamTypeName}>(url, options)
646
667
  },
647
668
  /**
648
669
  * Regular GET request (non-streaming)
649
670
  */
650
- get: async (${allParams}): Promise<AxiosResponse<any>> => {
671
+ get: async (${regularParams}): Promise<AxiosResponse<any>> => {
651
672
  return axios.get(${formattedPath})
652
673
  }
653
674
  }`;
@@ -751,10 +772,15 @@ function generateFunctionForOperation(method, path, operation) {
751
772
  if (isStream) {
752
773
  const eventTypes = extractSSEEventTypes(operation);
753
774
  const eventInfo = extractSSEEventInfo(operation);
775
+ const eventSchemas = extractSSEEventSchemas(operation);
754
776
  const streamTypeName = generateStreamTypeName(path);
755
777
  if (eventInfo?.length) {
756
778
  streamEventInfo[streamTypeName] = eventInfo;
757
779
  }
780
+ if (eventSchemas && Object.keys(eventSchemas).length > 0) {
781
+ streamEventSchemas[streamTypeName] = eventSchemas;
782
+ Object.values(eventSchemas).forEach((tsType) => collectTypeForImportStatement(tsType));
783
+ }
758
784
  return functionComment + generateStreamFunction(
759
785
  method,
760
786
  path,
@@ -878,6 +904,7 @@ function generateStreamEventTypeDefinitions() {
878
904
  typeDefs += "// ============================================================================\n\n";
879
905
  for (const [typeName, events] of Object.entries(streamEventTypes)) {
880
906
  const eventInfo = streamEventInfo[typeName];
907
+ const eventSchemas = streamEventSchemas[typeName];
881
908
  typeDefs += `/**
882
909
  * Event types for ${typeName.replace("StreamEvents", "")} stream
883
910
  `;
@@ -895,7 +922,22 @@ function generateStreamEventTypeDefinitions() {
895
922
  `;
896
923
  typeDefs += `export interface ${typeName} {
897
924
  `;
898
- if (eventInfo?.length) {
925
+ if (eventSchemas && Object.keys(eventSchemas).length > 0) {
926
+ for (const event of events) {
927
+ const tsType = eventSchemas[event];
928
+ if (tsType) {
929
+ typeDefs += ` /** ${event} event \u2014 payload shape defined by ${tsType} */
930
+ `;
931
+ typeDefs += ` ${event}: ${tsType}
932
+ `;
933
+ } else {
934
+ typeDefs += ` /** ${event} event data */
935
+ `;
936
+ typeDefs += ` ${event}: any
937
+ `;
938
+ }
939
+ }
940
+ } else if (eventInfo?.length) {
899
941
  for (const info of eventInfo) {
900
942
  typeDefs += ` /**
901
943
  * ${info.description || info.name}
@@ -1976,6 +2018,7 @@ exports.createSSEStream = createSSEStream;
1976
2018
  exports.createSSEStreamPost = createSSEStreamPost;
1977
2019
  exports.dereference = dereference;
1978
2020
  exports.extractSSEEventInfo = extractSSEEventInfo;
2021
+ exports.extractSSEEventSchemas = extractSSEEventSchemas;
1979
2022
  exports.extractSSEEventTypes = extractSSEEventTypes;
1980
2023
  exports.formatAPIErrorMessage = formatAPIErrorMessage;
1981
2024
  exports.formatFieldErrors = formatFieldErrors;
package/dist/index.d.cts CHANGED
@@ -480,6 +480,17 @@ interface SSEEventTypeInfo {
480
480
  * @returns Array of event types or undefined
481
481
  */
482
482
  declare function extractSSEEventTypes(operation: OperationObject): string[] | undefined;
483
+ /**
484
+ * Extracts typed schema refs from the x-event-schemas OpenAPI extension.
485
+ *
486
+ * Server sets this via sse_openapi_response(event_types={"created": MyModel}).
487
+ * Returns a map of { event_name: TypeScript type name } derived from the $ref,
488
+ * e.g. { "connection_created": "ConferenceConnectionOut" }.
489
+ *
490
+ * @param operation - The OpenAPI operation object
491
+ * @returns Map of event name → TS type name, or undefined if not present
492
+ */
493
+ declare function extractSSEEventSchemas(operation: OperationObject): Record<string, string> | undefined;
483
494
  /**
484
495
  * Extracts detailed SSE event information including field definitions
485
496
  *
@@ -790,5 +801,5 @@ declare function createOptionsGetter<T>(fetchFn: () => Promise<T[]>, mapFn?: (it
790
801
  value: string;
791
802
  }[]>;
792
803
 
793
- export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
804
+ export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventSchemas, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
794
805
  export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
package/dist/index.d.mts CHANGED
@@ -480,6 +480,17 @@ interface SSEEventTypeInfo {
480
480
  * @returns Array of event types or undefined
481
481
  */
482
482
  declare function extractSSEEventTypes(operation: OperationObject): string[] | undefined;
483
+ /**
484
+ * Extracts typed schema refs from the x-event-schemas OpenAPI extension.
485
+ *
486
+ * Server sets this via sse_openapi_response(event_types={"created": MyModel}).
487
+ * Returns a map of { event_name: TypeScript type name } derived from the $ref,
488
+ * e.g. { "connection_created": "ConferenceConnectionOut" }.
489
+ *
490
+ * @param operation - The OpenAPI operation object
491
+ * @returns Map of event name → TS type name, or undefined if not present
492
+ */
493
+ declare function extractSSEEventSchemas(operation: OperationObject): Record<string, string> | undefined;
483
494
  /**
484
495
  * Extracts detailed SSE event information including field definitions
485
496
  *
@@ -790,5 +801,5 @@ declare function createOptionsGetter<T>(fetchFn: () => Promise<T[]>, mapFn?: (it
790
801
  value: string;
791
802
  }[]>;
792
803
 
793
- export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
804
+ export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventSchemas, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
794
805
  export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
package/dist/index.d.ts CHANGED
@@ -480,6 +480,17 @@ interface SSEEventTypeInfo {
480
480
  * @returns Array of event types or undefined
481
481
  */
482
482
  declare function extractSSEEventTypes(operation: OperationObject): string[] | undefined;
483
+ /**
484
+ * Extracts typed schema refs from the x-event-schemas OpenAPI extension.
485
+ *
486
+ * Server sets this via sse_openapi_response(event_types={"created": MyModel}).
487
+ * Returns a map of { event_name: TypeScript type name } derived from the $ref,
488
+ * e.g. { "connection_created": "ConferenceConnectionOut" }.
489
+ *
490
+ * @param operation - The OpenAPI operation object
491
+ * @returns Map of event name → TS type name, or undefined if not present
492
+ */
493
+ declare function extractSSEEventSchemas(operation: OperationObject): Record<string, string> | undefined;
483
494
  /**
484
495
  * Extracts detailed SSE event information including field definitions
485
496
  *
@@ -790,5 +801,5 @@ declare function createOptionsGetter<T>(fetchFn: () => Promise<T[]>, mapFn?: (it
790
801
  value: string;
791
802
  }[]>;
792
803
 
793
- export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
804
+ export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventSchemas, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, _default as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
794
805
  export type { ApiConfig, ApiRequestState, BaseParameterObject, CallbackObject, CallbacksObject, ComponentsObject, ContactObject, ContentObject, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, FastAPIErrorResponse, FastAPIValidationError, HeaderObject, HeadersObject, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterLocation, ParameterObject, ParameterStyle, ParsedError, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, RequestInterceptor, ResponseInterceptor, ResponseMetadata, ResponseObject, ResponsesObject, SSEEventTypeInfo, SSEStreamOptions, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, StreamEventMap, TableToTypeMapping, Tables, TagObject, TypeFormatT, Unwrap, Unwrapped, UploadOptions, User, XmlObject };
package/dist/index.mjs CHANGED
@@ -54,6 +54,24 @@ function extractSSEEventTypes(operation) {
54
54
  }
55
55
  return types.size > 0 ? Array.from(types).sort() : void 0;
56
56
  }
57
+ function extractSSEEventSchemas(operation) {
58
+ const responses = operation.responses || {};
59
+ for (const [statusCode, response] of Object.entries(responses)) {
60
+ if (!statusCode.startsWith("2")) continue;
61
+ if ("$ref" in response) continue;
62
+ const eventStream = response.content?.["text/event-stream"];
63
+ const schemas = eventStream?.["x-event-schemas"];
64
+ if (schemas && Object.keys(schemas).length > 0) {
65
+ return Object.fromEntries(
66
+ Object.entries(schemas).map(([event, ref]) => [
67
+ event,
68
+ ref.replace(/^#\/components\/schemas\//, "")
69
+ ])
70
+ );
71
+ }
72
+ }
73
+ return void 0;
74
+ }
57
75
  function extractSSEEventInfo(operation) {
58
76
  const description = operation.description || "";
59
77
  const eventInfos = [];
@@ -391,6 +409,7 @@ const functionsInventory = {};
391
409
  const pathOperations = [];
392
410
  const streamEventTypes = {};
393
411
  const streamEventInfo = {};
412
+ const streamEventSchemas = {};
394
413
  function collectTypeForImportStatement(typeName) {
395
414
  typeName = typeName.trim().replace("[]", "");
396
415
  if (typeName.includes("|")) {
@@ -597,6 +616,8 @@ function generateStreamFunction(method, path, formattedPath, allParams, requestB
597
616
  * .on('${t}', (data) => console.log(data))`).join("") : "\n * .on('message', (data) => console.log(data))";
598
617
  const typeAnnotation = eventTypes?.length ? `StreamController<${streamTypeName}>` : "StreamController";
599
618
  const pathForUrl = formattedPath.startsWith("`") ? formattedPath.slice(1, -1) : formattedPath.slice(1, -1);
619
+ const streamParams = allParams ? `${allParams}, options?: SSEStreamOptions` : `options?: SSEStreamOptions`;
620
+ const regularParams = allParams;
600
621
  if (method === "post") {
601
622
  return `{
602
623
  /**
@@ -610,14 +631,14 @@ function generateStreamFunction(method, path, formattedPath, allParams, requestB
610
631
  * // Close stream when needed
611
632
  * stream.close()
612
633
  */
613
- stream: (${allParams}, options?: SSEStreamOptions): ${typeAnnotation} => {
634
+ stream: (${streamParams}): ${typeAnnotation} => {
614
635
  const url = \`\${${baseUrlRef}}${pathForUrl}\`
615
636
  return createSSEStreamPost<${streamTypeName}>(url, ${bodyVar}, options)
616
637
  },
617
638
  /**
618
639
  * Regular POST request (non-streaming)
619
640
  */
620
- post: async (${allParams}): Promise<AxiosResponse<any>> => {
641
+ post: async (${regularParams}): Promise<AxiosResponse<any>> => {
621
642
  return axios.post(${formattedPath}, ${bodyVar})
622
643
  }
623
644
  }`;
@@ -634,14 +655,14 @@ function generateStreamFunction(method, path, formattedPath, allParams, requestB
634
655
  * // Close stream when needed
635
656
  * stream.close()
636
657
  */
637
- stream: (${allParams}, options?: SSEStreamOptions): ${typeAnnotation} => {
658
+ stream: (${streamParams}): ${typeAnnotation} => {
638
659
  const url = \`\${${baseUrlRef}}${pathForUrl}\`
639
660
  return createSSEStream<${streamTypeName}>(url, options)
640
661
  },
641
662
  /**
642
663
  * Regular GET request (non-streaming)
643
664
  */
644
- get: async (${allParams}): Promise<AxiosResponse<any>> => {
665
+ get: async (${regularParams}): Promise<AxiosResponse<any>> => {
645
666
  return axios.get(${formattedPath})
646
667
  }
647
668
  }`;
@@ -745,10 +766,15 @@ function generateFunctionForOperation(method, path, operation) {
745
766
  if (isStream) {
746
767
  const eventTypes = extractSSEEventTypes(operation);
747
768
  const eventInfo = extractSSEEventInfo(operation);
769
+ const eventSchemas = extractSSEEventSchemas(operation);
748
770
  const streamTypeName = generateStreamTypeName(path);
749
771
  if (eventInfo?.length) {
750
772
  streamEventInfo[streamTypeName] = eventInfo;
751
773
  }
774
+ if (eventSchemas && Object.keys(eventSchemas).length > 0) {
775
+ streamEventSchemas[streamTypeName] = eventSchemas;
776
+ Object.values(eventSchemas).forEach((tsType) => collectTypeForImportStatement(tsType));
777
+ }
752
778
  return functionComment + generateStreamFunction(
753
779
  method,
754
780
  path,
@@ -872,6 +898,7 @@ function generateStreamEventTypeDefinitions() {
872
898
  typeDefs += "// ============================================================================\n\n";
873
899
  for (const [typeName, events] of Object.entries(streamEventTypes)) {
874
900
  const eventInfo = streamEventInfo[typeName];
901
+ const eventSchemas = streamEventSchemas[typeName];
875
902
  typeDefs += `/**
876
903
  * Event types for ${typeName.replace("StreamEvents", "")} stream
877
904
  `;
@@ -889,7 +916,22 @@ function generateStreamEventTypeDefinitions() {
889
916
  `;
890
917
  typeDefs += `export interface ${typeName} {
891
918
  `;
892
- if (eventInfo?.length) {
919
+ if (eventSchemas && Object.keys(eventSchemas).length > 0) {
920
+ for (const event of events) {
921
+ const tsType = eventSchemas[event];
922
+ if (tsType) {
923
+ typeDefs += ` /** ${event} event \u2014 payload shape defined by ${tsType} */
924
+ `;
925
+ typeDefs += ` ${event}: ${tsType}
926
+ `;
927
+ } else {
928
+ typeDefs += ` /** ${event} event data */
929
+ `;
930
+ typeDefs += ` ${event}: any
931
+ `;
932
+ }
933
+ }
934
+ } else if (eventInfo?.length) {
893
935
  for (const info of eventInfo) {
894
936
  typeDefs += ` /**
895
937
  * ${info.description || info.name}
@@ -1962,4 +2004,4 @@ function createOptionsGetter(fetchFn, mapFn) {
1962
2004
  };
1963
2005
  }
1964
2006
 
1965
- export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, index as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
2007
+ export { ApiResponse, Bagel, StreamController, createOptionsGetter, createSSEStream, createSSEStreamPost, dereference, extractSSEEventInfo, extractSSEEventSchemas, extractSSEEventTypes, formatAPIErrorMessage, formatFieldErrors, getPath, isReferenceObject, isSSEStream, isSchemaObject, index as openAPI, parseApiError, unwrap, useApiRequest, useCancellableRequest, wrapApiForDirectReturn };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/sdk",
3
3
  "type": "module",
4
- "version": "1.12.47",
4
+ "version": "1.12.51",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -1,8 +1,4 @@
1
- /* eslint-disable ts/strict-boolean-expressions */
2
- /* eslint-disable ts/no-unnecessary-condition */
3
- /* eslint-disable jsdoc/check-param-names */
4
- /* eslint-disable ts/no-non-null-assertion */
5
- /* eslint-disable prefer-destructuring */
1
+
6
2
  import type { SSEEventTypeInfo } from './streamDetector'
7
3
  import type {
8
4
  OperationObject as OpenAPIOperation,
@@ -14,7 +10,7 @@ import type {
14
10
  ReferenceObject,
15
11
  SchemaObject,
16
12
  } from './types'
17
- import { isSSEStream, extractSSEEventTypes, extractSSEEventInfo } from './streamDetector'
13
+ import { isSSEStream, extractSSEEventTypes, extractSSEEventInfo, extractSSEEventSchemas } from './streamDetector'
18
14
  import { dereference, isReferenceObject } from './types/utils'
19
15
  import {
20
16
  cleanPath,
@@ -63,6 +59,7 @@ const functionsInventory: Record<string, string> = {}
63
59
  const pathOperations: PathOperation[] = []
64
60
  const streamEventTypes: Record<string, string[]> = {} // Track stream endpoints and their event types
65
61
  const streamEventInfo: Record<string, SSEEventTypeInfo[]> = {} // Track detailed event info for type generation
62
+ const streamEventSchemas: Record<string, Record<string, string>> = {} // Track typed schemas: streamTypeName → {event → TSType}
66
63
 
67
64
  /**
68
65
  * Collects non-primitive types for import statements
@@ -448,6 +445,9 @@ function generateStreamFunction(
448
445
  ? formattedPath.slice(1, -1) // Remove backticks to get the content
449
446
  : formattedPath.slice(1, -1) // Remove quotes to get the content
450
447
 
448
+ const streamParams = allParams ? `${allParams}, options?: SSEStreamOptions` : `options?: SSEStreamOptions`
449
+ const regularParams = allParams
450
+
451
451
  if (method === 'post') {
452
452
  return `{
453
453
  /**
@@ -461,14 +461,14 @@ function generateStreamFunction(
461
461
  * // Close stream when needed
462
462
  * stream.close()
463
463
  */
464
- stream: (${allParams}, options?: SSEStreamOptions): ${typeAnnotation} => {
464
+ stream: (${streamParams}): ${typeAnnotation} => {
465
465
  const url = \`\${${baseUrlRef}}${pathForUrl}\`
466
466
  return createSSEStreamPost<${streamTypeName}>(url, ${bodyVar}, options)
467
467
  },
468
468
  /**
469
469
  * Regular POST request (non-streaming)
470
470
  */
471
- post: async (${allParams}): Promise<AxiosResponse<any>> => {
471
+ post: async (${regularParams}): Promise<AxiosResponse<any>> => {
472
472
  return axios.post(${formattedPath}, ${bodyVar})
473
473
  }
474
474
  }`
@@ -485,14 +485,14 @@ function generateStreamFunction(
485
485
  * // Close stream when needed
486
486
  * stream.close()
487
487
  */
488
- stream: (${allParams}, options?: SSEStreamOptions): ${typeAnnotation} => {
488
+ stream: (${streamParams}): ${typeAnnotation} => {
489
489
  const url = \`\${${baseUrlRef}}${pathForUrl}\`
490
490
  return createSSEStream<${streamTypeName}>(url, options)
491
491
  },
492
492
  /**
493
493
  * Regular GET request (non-streaming)
494
494
  */
495
- get: async (${allParams}): Promise<AxiosResponse<any>> => {
495
+ get: async (${regularParams}): Promise<AxiosResponse<any>> => {
496
496
  return axios.get(${formattedPath})
497
497
  }
498
498
  }`
@@ -677,12 +677,18 @@ function generateFunctionForOperation(
677
677
  if (isStream) {
678
678
  const eventTypes = extractSSEEventTypes(operation)
679
679
  const eventInfo = extractSSEEventInfo(operation)
680
+ const eventSchemas = extractSSEEventSchemas(operation)
680
681
 
681
- // Store detailed event info for type generation
682
+ // Store detailed event info and typed schemas for type generation
682
683
  const streamTypeName = generateStreamTypeName(path)
683
684
  if (eventInfo?.length) {
684
685
  streamEventInfo[streamTypeName] = eventInfo
685
686
  }
687
+ if (eventSchemas && Object.keys(eventSchemas).length > 0) {
688
+ streamEventSchemas[streamTypeName] = eventSchemas
689
+ // Collect schema type names for import statements
690
+ Object.values(eventSchemas).forEach(tsType => collectTypeForImportStatement(tsType))
691
+ }
686
692
 
687
693
  return functionComment + generateStreamFunction(
688
694
  method,
@@ -895,11 +901,11 @@ function generateStreamEventTypeDefinitions(): string {
895
901
 
896
902
  for (const [typeName, events] of Object.entries(streamEventTypes)) {
897
903
  const eventInfo = streamEventInfo[typeName]
904
+ const eventSchemas = streamEventSchemas[typeName] // {event_name: "TSTypeName"} or undefined
898
905
 
899
906
  typeDefs += `/**\n * Event types for ${typeName.replace('StreamEvents', '')} stream\n`
900
907
  typeDefs += ` * Events: ${events.map(e => `"${e}"`).join(', ')}\n`
901
908
 
902
- // Add event descriptions if available
903
909
  if (eventInfo?.length) {
904
910
  typeDefs += ` *\n`
905
911
  for (const info of eventInfo) {
@@ -910,20 +916,28 @@ function generateStreamEventTypeDefinitions(): string {
910
916
  typeDefs += ` */\n`
911
917
  typeDefs += `export interface ${typeName} {\n`
912
918
 
913
- // Generate event type definitions with field information if available
914
- if (eventInfo?.length) {
919
+ if (eventSchemas && Object.keys(eventSchemas).length > 0) {
920
+ // Fully typed: each event maps to its Pydantic model's TypeScript type
921
+ for (const event of events) {
922
+ const tsType = eventSchemas[event]
923
+ if (tsType) {
924
+ typeDefs += ` /** ${event} event — payload shape defined by ${tsType} */\n`
925
+ typeDefs += ` ${event}: ${tsType}\n`
926
+ } else {
927
+ typeDefs += ` /** ${event} event data */\n`
928
+ typeDefs += ` ${event}: any\n`
929
+ }
930
+ }
931
+ } else if (eventInfo?.length) {
932
+ // Field-level info from markdown docs but no schema refs
915
933
  for (const info of eventInfo) {
916
934
  typeDefs += ` /**\n * ${info.description || info.name}\n`
917
-
918
935
  if (info.fields?.length) {
919
- info.fields.forEach((field) => {
936
+ info.fields.forEach(field => {
920
937
  typeDefs += ` * - \`${field.name}\`: ${field.description || 'Field data'}\n`
921
938
  })
922
939
  }
923
-
924
940
  typeDefs += ` */\n`
925
-
926
- // Generate interface for this event
927
941
  if (info.fields?.length) {
928
942
  typeDefs += ` ${info.name}: {\n`
929
943
  for (const field of info.fields) {
@@ -936,7 +950,7 @@ function generateStreamEventTypeDefinitions(): string {
936
950
  }
937
951
  }
938
952
  } else {
939
- // Fallback: simple event list without field info
953
+ // Fallback: no type info at all
940
954
  for (const event of events) {
941
955
  typeDefs += ` /** ${event} event data */\n`
942
956
  typeDefs += ` ${event}: any\n`
@@ -122,6 +122,36 @@ export function extractSSEEventTypes(operation: OpenAPIOperation): string[] | un
122
122
  return types.size > 0 ? Array.from(types).sort() : undefined
123
123
  }
124
124
 
125
+ /**
126
+ * Extracts typed schema refs from the x-event-schemas OpenAPI extension.
127
+ *
128
+ * Server sets this via sse_openapi_response(event_types={"created": MyModel}).
129
+ * Returns a map of { event_name: TypeScript type name } derived from the $ref,
130
+ * e.g. { "connection_created": "ConferenceConnectionOut" }.
131
+ *
132
+ * @param operation - The OpenAPI operation object
133
+ * @returns Map of event name → TS type name, or undefined if not present
134
+ */
135
+ export function extractSSEEventSchemas(operation: OpenAPIOperation): Record<string, string> | undefined {
136
+ const responses = operation.responses || {}
137
+ for (const [statusCode, response] of Object.entries(responses)) {
138
+ if (!statusCode.startsWith('2')) continue
139
+ if ('$ref' in response) continue
140
+ const eventStream = (response as any).content?.['text/event-stream']
141
+ const schemas = eventStream?.['x-event-schemas'] as Record<string, string> | undefined
142
+ if (schemas && Object.keys(schemas).length > 0) {
143
+ // Convert $ref paths like "#/components/schemas/MyModel" → "MyModel"
144
+ return Object.fromEntries(
145
+ Object.entries(schemas).map(([event, ref]) => [
146
+ event,
147
+ ref.replace(/^#\/components\/schemas\//, ''),
148
+ ])
149
+ )
150
+ }
151
+ }
152
+ return undefined
153
+ }
154
+
125
155
  /**
126
156
  * Extracts detailed SSE event information including field definitions
127
157
  *