@sdk-it/typescript 0.42.0 → 0.43.0

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.js CHANGED
@@ -255,7 +255,7 @@ var ZodEmitter = class {
255
255
  string(schema) {
256
256
  let base = schema["x-zod-type"] === "coerce-string" ? "z.coerce.string()" : "z.string()";
257
257
  if (schema.contentEncoding === "binary") {
258
- base = "z.instanceof(Blob)";
258
+ base = "z.custom<Blob>()";
259
259
  return base;
260
260
  }
261
261
  switch (schema.format) {
@@ -296,7 +296,7 @@ var ZodEmitter = class {
296
296
  break;
297
297
  case "byte":
298
298
  case "binary":
299
- base = "z.instanceof(Blob)";
299
+ base = "z.custom<Blob>()";
300
300
  break;
301
301
  case "int64":
302
302
  base += " /* or z.bigint() if your app can handle it */";
@@ -402,6 +402,7 @@ function toZod(schema, required) {
402
402
 
403
403
  // packages/typescript/src/lib/client.ts
404
404
  var client_default = (spec) => {
405
+ const baseUrlSchema = `z.union([z.string(),z.function().returns(z.union([z.string(), z.promise(z.string())])),])${spec.servers.length ? ".default(servers[0])" : ""}`;
405
406
  const defaultHeaders = `{${spec.options.filter((value) => value.in === "header").map(
406
407
  (value) => `'${value.name}': options['${value["x-optionName"] ?? value.name}']`
407
408
  ).join(",\n")}}`;
@@ -432,7 +433,12 @@ var client_default = (spec) => {
432
433
  schema: `fetchType.describe('Custom fetch implementation. Defaults to globalThis.fetch.')`
433
434
  },
434
435
  baseUrl: {
435
- schema: spec.servers.length ? `z.enum(servers).default(servers[0]).describe('Base URL of the API server.')` : `z.string().describe('Base URL of the API server.')`
436
+ schema: `${baseUrlSchema}.transform(async (baseUrl) => {
437
+ if (typeof baseUrl === 'function') {
438
+ return Promise.resolve(baseUrl());
439
+ }
440
+ return baseUrl;
441
+ }).describe('Base URL of the API server. Can be a string or a function that returns a string.')`
436
442
  },
437
443
  headers: {
438
444
  schema: `z.record(z.string()).optional().describe('Default headers to include in all requests.')`
@@ -484,7 +490,7 @@ export class ${spec.name} {
484
490
  async prepare<const E extends keyof typeof schemas>(
485
491
  endpoint: E,
486
492
  input: z.input<(typeof schemas)[E]['schema']>,
487
- options?: { headers?: HeadersInit },
493
+ options?: { signal?: AbortSignal; headers?: HeadersInit },
488
494
  ) {
489
495
  return prepare(this, endpoint, input, options);
490
496
  }
@@ -565,7 +571,7 @@ export async function prepare<const E extends keyof typeof schemas>(
565
571
  client: ${spec.name},
566
572
  endpoint: E,
567
573
  input: z.input<(typeof schemas)[E]['schema']>,
568
- requestOptions?: { headers?: HeadersInit },
574
+ requestOptions?: { signal?: AbortSignal; headers?: HeadersInit },
569
575
  ): Promise<RequestConfig & {
570
576
  parse: (response: Response) => ReturnType<typeof parse>;
571
577
  }> {
@@ -586,6 +592,15 @@ export async function prepare<const E extends keyof typeof schemas>(
586
592
  ];
587
593
 
588
594
  let config = route.toRequest(parsedInput as never);
595
+ if (requestOptions?.signal) {
596
+ config = {
597
+ ...config,
598
+ init: {
599
+ ...config.init,
600
+ signal: requestOptions.signal,
601
+ },
602
+ };
603
+ }
589
604
  for (const interceptor of interceptors) {
590
605
  if (interceptor.before) {
591
606
  config = await interceptor.before(config);
@@ -599,7 +614,7 @@ export async function prepare<const E extends keyof typeof schemas>(
599
614
  };
600
615
 
601
616
  // packages/typescript/src/lib/emitters/interface.ts
602
- import { followRef as followRef2, isRef as isRef2, parseRef as parseRef2, pascalcase as pascalcase2 } from "@sdk-it/core";
617
+ import { followRef as followRef2, isRef as isRef2, parseRef as parseRef2, pascalcase as pascalcase2, resolveRef } from "@sdk-it/core";
603
618
  import { isPrimitiveSchema as isPrimitiveSchema2, sanitizeTag as sanitizeTag2 } from "@sdk-it/spec";
604
619
  var TypeScriptEmitter = class {
605
620
  #spec;
@@ -677,7 +692,23 @@ var TypeScriptEmitter = class {
677
692
  return allOfTypes.length > 1 ? `${allOfTypes.join(" & ")}` : allOfTypes[0];
678
693
  }
679
694
  oneOf(schemas, required) {
680
- const oneOfTypes = schemas.map((sub) => this.handle(sub, true));
695
+ const isBareString = (s) => {
696
+ const r = resolveRef(this.#spec, s);
697
+ return r.type === "string" && !r.enum && !r.const && !r.format;
698
+ };
699
+ const isStringLiteral = (s) => {
700
+ const r = resolveRef(this.#spec, s);
701
+ return Array.isArray(r.enum) && r.enum.every((v) => typeof v === "string") || typeof r.const === "string";
702
+ };
703
+ const hasStringLiteral = schemas.some(isStringLiteral);
704
+ const seen = /* @__PURE__ */ new Set();
705
+ const oneOfTypes = [];
706
+ for (const sub of schemas) {
707
+ const part = hasStringLiteral && isBareString(sub) ? "(string & {})" : this.handle(sub, true);
708
+ if (seen.has(part)) continue;
709
+ seen.add(part);
710
+ oneOfTypes.push(part);
711
+ }
681
712
  return appendOptional2(
682
713
  oneOfTypes.length > 1 ? `${oneOfTypes.join(" | ")}` : oneOfTypes[0],
683
714
  required
@@ -769,7 +800,7 @@ function appendOptional2(type, isRequired) {
769
800
  import { merge, template } from "lodash-es";
770
801
  import { join } from "node:path";
771
802
  import { camelcase as camelcase4, spinalcase as spinalcase2 } from "stringcase";
772
- import { followRef as followRef3, isEmpty as isEmpty2, isRef as isRef3, resolveRef, sortArray } from "@sdk-it/core";
803
+ import { followRef as followRef3, isEmpty as isEmpty2, isRef as isRef3, resolveRef as resolveRef2, sortArray } from "@sdk-it/core";
773
804
  import {
774
805
  forEachOperation as forEachOperation3
775
806
  } from "@sdk-it/spec";
@@ -789,6 +820,69 @@ import {
789
820
  // packages/typescript/src/lib/import-utilities.ts
790
821
  import { removeDuplicates } from "@sdk-it/core";
791
822
 
823
+ // packages/typescript/src/lib/pagination-emit.ts
824
+ function describe(p) {
825
+ switch (p.type) {
826
+ case "offset":
827
+ return {
828
+ className: "OffsetPagination",
829
+ items: p.items,
830
+ hasMore: p.hasMore,
831
+ statusCode: p.statusCode,
832
+ sameInputNames: p.limitParamName === "limit" && p.offsetParamName === "offset",
833
+ initialOverride: `limit: input.${p.limitParamName}, offset: input.${p.offsetParamName}`,
834
+ nextPageMapping: `${p.offsetParamName}: nextPageParams.offset, ${p.limitParamName}: nextPageParams.limit`
835
+ };
836
+ case "cursor":
837
+ return {
838
+ className: "CursorPagination",
839
+ items: p.items,
840
+ hasMore: p.hasMore,
841
+ statusCode: p.statusCode,
842
+ sameInputNames: p.cursorParamName === "cursor",
843
+ initialOverride: `cursor: input.${p.cursorParamName}`,
844
+ nextPageMapping: `${p.cursorParamName}: nextPageParams.cursor`
845
+ };
846
+ case "page":
847
+ return {
848
+ className: "Pagination",
849
+ items: p.items,
850
+ hasMore: p.hasMore,
851
+ statusCode: p.statusCode,
852
+ sameInputNames: p.pageNumberParamName === "page" && p.pageSizeParamName === "pageSize",
853
+ initialOverride: `page: input.${p.pageNumberParamName}, pageSize: input.${p.pageSizeParamName}`,
854
+ nextPageMapping: `${p.pageNumberParamName}: nextPageParams.page, ${p.pageSizeParamName}: nextPageParams.pageSize`
855
+ };
856
+ }
857
+ throw new Error(
858
+ `Unknown pagination type: ${p.type}`
859
+ );
860
+ }
861
+ function paginationOperation(pagination) {
862
+ const shape = describe(pagination);
863
+ const initialParams = shape.sameInputNames ? "input" : `{...input, ${shape.initialOverride}}`;
864
+ const nextPageParams = shape.sameInputNames ? "...nextPageParams" : shape.nextPageMapping;
865
+ return `{
866
+ const pagination = new ${shape.className}(${initialParams}, async (nextPageParams, requestOptions) => {
867
+ const dispatcher = new Dispatcher(options.interceptors, options.fetch);
868
+ const result = await dispatcher.send(
869
+ this.toRequest({...input, ${nextPageParams}}),
870
+ this.output,
871
+ requestOptions?.signal ?? options.signal,
872
+ );
873
+ if (result.status !== ${shape.statusCode}) { throw result; }
874
+ return {
875
+ data: result.data.${shape.items},
876
+ meta: {
877
+ hasMore: Boolean(result.data.${shape.hasMore}),
878
+ },
879
+ };
880
+ }, { signal: options.signal });
881
+ await pagination.getNextPage();
882
+ return pagination
883
+ }}`;
884
+ }
885
+
792
886
  // packages/typescript/src/lib/status-map.ts
793
887
  var status_map_default = {
794
888
  "200": "Ok",
@@ -853,7 +947,7 @@ function toEndpoint(groupName, spec, specOperation, operation) {
853
947
  signal?: AbortSignal;
854
948
  interceptors: Interceptor[];
855
949
  fetch: z.infer<typeof fetchType>;
856
- })${specOperation["x-pagination"] ? paginationOperation(specOperation) : normalOperation()}`
950
+ })${specOperation["x-pagination"] ? paginationOperation(specOperation["x-pagination"]) : normalOperation()}`
857
951
  );
858
952
  }
859
953
  return { schemas };
@@ -865,82 +959,6 @@ function normalOperation() {
865
959
  },
866
960
  }`;
867
961
  }
868
- function paginationOperation(operation) {
869
- const pagination = operation["x-pagination"];
870
- const data = `result.data`;
871
- const returnValue = `pagination`;
872
- if (pagination.type === "offset") {
873
- const sameInputNames = pagination.limitParamName === "limit" && pagination.offsetParamName === "offset";
874
- const initialParams = sameInputNames ? "input" : `{...input, limit: input.${pagination.limitParamName}, offset: input.${pagination.offsetParamName}}`;
875
- const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.offsetParamName}: nextPageParams.offset, ${pagination.limitParamName}: nextPageParams.limit`;
876
- const logic = `const pagination = new OffsetPagination(${initialParams}, async (nextPageParams) => {
877
- const dispatcher = new Dispatcher(options.interceptors, options.fetch);
878
- const result = await dispatcher.send(
879
- this.toRequest({...input, ${nextPageParams}}),
880
- this.output,
881
- options.signal,
882
- );
883
- return {
884
- data: ${data}.${pagination.items},
885
- meta: {
886
- hasMore: Boolean(${data}.${pagination.hasMore}),
887
- },
888
- };
889
- });
890
- await pagination.getNextPage();
891
- return ${returnValue}
892
- `;
893
- return `{${logic}}}`;
894
- }
895
- if (pagination.type === "cursor") {
896
- const sameInputNames = pagination.cursorParamName === "cursor";
897
- const initialParams = sameInputNames ? "input" : `{...input, cursor: input.${pagination.cursorParamName}}`;
898
- const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.cursorParamName}: nextPageParams.cursor`;
899
- const logic = `
900
- const pagination = new CursorPagination(${initialParams}, async (nextPageParams) => {
901
- const dispatcher = new Dispatcher(options.interceptors, options.fetch);
902
- const result = await dispatcher.send(
903
- this.toRequest({...input, ${nextPageParams}}),
904
- this.output,
905
- options.signal,
906
- );
907
- return {
908
- data: ${data}.${pagination.items},
909
- meta: {
910
- hasMore: Boolean(${data}.${pagination.hasMore}),
911
- },
912
- };
913
- });
914
- await pagination.getNextPage();
915
- return ${returnValue}
916
- `;
917
- return `{${logic}}}`;
918
- }
919
- if (pagination.type === "page") {
920
- const sameInputNames = pagination.pageNumberParamName === "page" && pagination.pageSizeParamName === "pageSize";
921
- const initialParams = sameInputNames ? "input" : `{...input, page: input.${pagination.pageNumberParamName}, pageSize: input.${pagination.pageSizeParamName}}`;
922
- const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.pageNumberParamName}: nextPageParams.page, ${pagination.pageSizeParamName}: nextPageParams.pageSize`;
923
- const logic = `
924
- const pagination = new Pagination(${initialParams}, async (nextPageParams) => {
925
- const dispatcher = new Dispatcher(options.interceptors, options.fetch);
926
- const result = await dispatcher.send(
927
- this.toRequest({...input, ${nextPageParams}}),
928
- this.output,
929
- options.signal,
930
- );
931
- return {
932
- data: ${data}.${pagination.items},
933
- meta: {
934
- hasMore: Boolean(${data}.${pagination.hasMore}),
935
- },
936
- };
937
- });
938
- return ${returnValue}
939
- `;
940
- return `{${logic}}}`;
941
- }
942
- return normalOperation();
943
- }
944
962
  function toHttpOutput(spec, operationName, status, response, withGenerics = true) {
945
963
  const typeScriptDeserialzer = new TypeScriptEmitter(spec);
946
964
  const interfaceName = pascalcase3(sanitizeTag3(response["x-response-name"]));
@@ -1061,7 +1079,7 @@ var endpoints_default = "type DispatchReturn<E extends keyof typeof schemas> = A
1061
1079
 
1062
1080
  // packages/typescript/src/lib/generator.ts
1063
1081
  function coearceRequestInput(spec, operation, type) {
1064
- let objectSchema = resolveRef(
1082
+ let objectSchema = resolveRef2(
1065
1083
  spec,
1066
1084
  operation.requestBody.content[type].schema
1067
1085
  );
@@ -1310,7 +1328,7 @@ function operationSchema(ir, operation, type) {
1310
1328
  }
1311
1329
 
1312
1330
  // packages/typescript/src/lib/http/dispatcher.txt
1313
- var dispatcher_default = "export type Unionize<T> = T extends [infer Single extends OutputType]\n ? InstanceType<Single>\n : T extends readonly [...infer Tuple extends OutputType[]]\n ? { [I in keyof Tuple]: InstanceType<Tuple[I]> }[number]\n : never;\n\nexport type InstanceType<T> =\n T extends Type<infer U>\n ? U\n : T extends { type: Type<infer U> }\n ? U\n : T extends Array<unknown>\n ? Unionize<T>\n : never;\n\ntype ResponseData<T extends OutputType[]> =\n Extract<InstanceType<T>, SuccessfulResponse> extends SuccessfulResponse<\n infer P\n >\n ? P\n : unknown;\n\ntype ResponseMapper<T extends OutputType[], R> = (data: ResponseData<T>) => R;\n\nexport interface Type<T> {\n new (...args: any[]): T;\n}\nexport type Parser = (\n response: Response,\n) => Promise<unknown> | ReadableStream<any> | SSEListener;\nexport type OutputType =\n | Type<APIResponse>\n | { parser: Parser; type: Type<APIResponse> };\n\nexport const fetchType = z\n .function()\n .args(z.instanceof(Request))\n .returns(z.promise(z.instanceof(Response)))\n .optional();\n\nexport async function parse<T extends OutputType[]>(\n outputs: T,\n response: Response,\n): Promise<Extract<Unionize<T>, SuccessfulResponse<unknown>>>;\nexport async function parse<T extends OutputType[], R>(\n outputs: T,\n response: Response,\n mapper: ResponseMapper<T, R>,\n): Promise<RebindSuccessPayload<Extract<Unionize<T>, SuccessfulResponse<unknown>>, R>>;\nexport async function parse<T extends OutputType[], R = ResponseData<T>>(\n outputs: T,\n response: Response,\n mapper?: ResponseMapper<T, R>,\n) {\n let output: typeof APIResponse | null = null;\n let parser: Parser = buffered;\n for (const outputType of outputs) {\n if ('parser' in outputType) {\n parser = outputType.parser;\n if (isTypeOf(outputType.type, APIResponse)) {\n if (response.status === outputType.type.status) {\n output = outputType.type;\n break;\n }\n }\n } else if (isTypeOf(outputType, APIResponse)) {\n if (response.status === outputType.status) {\n output = outputType;\n break;\n }\n }\n }\n\n if (response.ok) {\n const data = (await parser(response)) as ResponseData<T>;\n const mapped = mapper ? mapper(data) : data;\n const apiresponse = (output || APIResponse).create(\n response.status,\n response.headers,\n mapped,\n );\n\n return apiresponse as any;\n }\n\n throw (output || APIError).create(\n response.status,\n response.headers,\n await parser(response),\n );\n}\n\nexport function isTypeOf<T extends Type<APIResponse>>(\n instance: any,\n baseType: T,\n): instance is T {\n if (instance === baseType) {\n return true;\n }\n const prototype = Object.getPrototypeOf(instance);\n if (prototype === null) {\n return false;\n }\n return isTypeOf(prototype, baseType);\n}\n\nexport class Dispatcher {\n #interceptors: Interceptor[] = [];\n #fetch: z.infer<typeof fetchType>;\n constructor(interceptors: Interceptor[], fetch?: z.infer<typeof fetchType>) {\n this.#interceptors = interceptors;\n this.#fetch = fetch;\n }\n\n async send<T extends OutputType[]>(\n config: RequestConfig,\n outputs: T,\n signal?: AbortSignal,\n ): Promise<Extract<Unionize<T>, SuccessfulResponse<unknown>>>;\n async send<T extends OutputType[], R>(\n config: RequestConfig,\n outputs: T,\n signal?: AbortSignal,\n mapper?: ResponseMapper<T, R>,\n ): Promise<RebindSuccessPayload<Extract<Unionize<T>, SuccessfulResponse<unknown>>, R>>;\n async send<T extends OutputType[], R = ResponseData<T>>(\n config: RequestConfig,\n outputs: T,\n signal?: AbortSignal,\n mapper?: ResponseMapper<T, R>,\n ) {\n for (const interceptor of this.#interceptors) {\n if (interceptor.before) {\n config = await interceptor.before(config);\n }\n }\n\n let response = await (this.#fetch ?? fetch)(\n new Request(config.url, config.init),\n {\n ...config.init,\n signal: signal,\n },\n );\n\n for (let i = this.#interceptors.length - 1; i >= 0; i--) {\n const interceptor = this.#interceptors[i];\n if (interceptor.after) {\n response = await interceptor.after(response.clone());\n }\n }\n\n if (mapper) {\n return await parse(outputs, response, mapper);\n }\n return await parse(outputs, response);\n }\n}\n";
1331
+ var dispatcher_default = "export type Unionize<T> = T extends [infer Single extends OutputType]\n ? InstanceType<Single>\n : T extends readonly [...infer Tuple extends OutputType[]]\n ? { [I in keyof Tuple]: InstanceType<Tuple[I]> }[number]\n : never;\n\nexport type InstanceType<T> =\n T extends Type<infer U>\n ? U\n : T extends { type: Type<infer U> }\n ? U\n : T extends Array<unknown>\n ? Unionize<T>\n : never;\n\ntype ResponseData<T extends OutputType[]> =\n Extract<InstanceType<T>, SuccessfulResponse> extends SuccessfulResponse<\n infer P\n >\n ? P\n : unknown;\n\ntype ResponseMapper<T extends OutputType[], R> = (data: ResponseData<T>) => R;\n\nexport interface Type<T> {\n new (...args: any[]): T;\n}\nexport type Parser = (\n response: Response,\n) => Promise<unknown> | ReadableStream<any> | SSEListener;\nexport type OutputType =\n | Type<APIResponse>\n | { parser: Parser; type: Type<APIResponse> };\n\nexport const fetchType = z\n .function()\n .args(z.custom<Request>())\n .returns(z.promise(z.custom<Response>()))\n .optional();\n\nexport async function parse<T extends OutputType[]>(\n outputs: T,\n response: Response,\n): Promise<Extract<Unionize<T>, SuccessfulResponse<unknown>>>;\nexport async function parse<T extends OutputType[], R>(\n outputs: T,\n response: Response,\n mapper: ResponseMapper<T, R>,\n): Promise<RebindSuccessPayload<Extract<Unionize<T>, SuccessfulResponse<unknown>>, R>>;\nexport async function parse<T extends OutputType[], R = ResponseData<T>>(\n outputs: T,\n response: Response,\n mapper?: ResponseMapper<T, R>,\n) {\n let output: typeof APIResponse | null = null;\n let parser: Parser = buffered;\n for (const outputType of outputs) {\n if ('parser' in outputType) {\n parser = outputType.parser;\n if (isTypeOf(outputType.type, APIResponse)) {\n if (response.status === outputType.type.status) {\n output = outputType.type;\n break;\n }\n }\n } else if (isTypeOf(outputType, APIResponse)) {\n if (response.status === outputType.status) {\n output = outputType;\n break;\n }\n }\n }\n\n if (response.ok) {\n const data = (await parser(response)) as ResponseData<T>;\n const mapped = mapper ? mapper(data) : data;\n const apiresponse = (output || APIResponse).create(\n response.status,\n response.headers,\n mapped,\n );\n\n return apiresponse as any;\n }\n\n throw (output || APIError).create(\n response.status,\n response.headers,\n await parser(response),\n );\n}\n\nexport function isTypeOf<T extends Type<APIResponse>>(\n instance: any,\n baseType: T,\n): instance is T {\n if (instance === baseType) {\n return true;\n }\n const prototype = Object.getPrototypeOf(instance);\n if (prototype === null) {\n return false;\n }\n return isTypeOf(prototype, baseType);\n}\n\nexport class Dispatcher {\n #interceptors: Interceptor[] = [];\n #fetch: z.infer<typeof fetchType>;\n constructor(interceptors: Interceptor[], fetch?: z.infer<typeof fetchType>) {\n this.#interceptors = interceptors;\n this.#fetch = fetch;\n }\n\n async send<T extends OutputType[]>(\n config: RequestConfig,\n outputs: T,\n signal?: AbortSignal,\n ): Promise<Extract<Unionize<T>, SuccessfulResponse<unknown>>>;\n async send<T extends OutputType[], R>(\n config: RequestConfig,\n outputs: T,\n signal?: AbortSignal,\n mapper?: ResponseMapper<T, R>,\n ): Promise<RebindSuccessPayload<Extract<Unionize<T>, SuccessfulResponse<unknown>>, R>>;\n async send<T extends OutputType[], R = ResponseData<T>>(\n config: RequestConfig,\n outputs: T,\n signal?: AbortSignal,\n mapper?: ResponseMapper<T, R>,\n ) {\n for (const interceptor of this.#interceptors) {\n if (interceptor.before) {\n config = await interceptor.before(config);\n }\n }\n\n const init = signal === undefined ? config.init : { ...config.init, signal };\n\n let response = await (this.#fetch ?? fetch)(new Request(config.url, init));\n\n for (let i = this.#interceptors.length - 1; i >= 0; i--) {\n const interceptor = this.#interceptors[i];\n if (interceptor.after) {\n response = await interceptor.after(response.clone());\n }\n }\n\n if (mapper) {\n return await parse(outputs, response, mapper);\n }\n return await parse(outputs, response);\n }\n}\n";
1314
1332
 
1315
1333
  // packages/typescript/src/lib/http/interceptors.txt
1316
1334
  var interceptors_default = "export interface Interceptor {\n before?: (config: RequestConfig) => Promise<RequestConfig> | RequestConfig;\n after?: (response: Response) => Promise<Response> | Response;\n}\n\nexport const createHeadersInterceptor = (\n headers: Record<string, string | undefined>,\n requestHeaders: HeadersInit,\n):Interceptor => {\n return {\n before({init, url}) {\n // Priority Levels\n // 1. Headers Input\n // 2. Request Headers\n // 3. Default Headers\n\n for (const [key, value] of new Headers(requestHeaders)) {\n // Only set the header if it doesn't already exist and has a value\n // even though these headers are passed at operation level\n // still they are lower priority compared to the headers input\n if (value !== undefined && !init.headers.has(key)) {\n init.headers.set(key, value);\n }\n }\n\n for (const [key, value] of Object.entries(headers)) {\n // Only set the header if it doesn't already exist and has a value\n if (value !== undefined && !init.headers.has(key)) {\n init.headers.set(key, value);\n }\n }\n\n return {init, url};\n },\n };\n};\n\nexport const createBaseUrlInterceptor = (baseUrl: string): Interceptor => {\n return {\n before({ init, url }) {\n if (url.protocol === 'local:') {\n return {\n init,\n url: new URL(url.href.replace('local://', baseUrl))\n };\n }\n return { init, url };\n },\n };\n};\n\nexport const logInterceptor: Interceptor = {\n before({ url, init }) {\n console.log('Request:', { url, init });\n return { url, init };\n },\n after(response) {\n console.log('Response:', response);\n return response;\n },\n};\n\n/**\n * Creates an interceptor that logs detailed information about requests and responses.\n * @param options Configuration options for the logger\n * @returns An interceptor object with before and after handlers\n */\nexport const createDetailedLogInterceptor = (options?: {\n logLevel?: 'debug' | 'info' | 'warn' | 'error';\n includeRequestBody?: boolean;\n includeResponseBody?: boolean;\n}) => {\n const logLevel = options?.logLevel || 'info';\n const includeRequestBody = options?.includeRequestBody || false;\n const includeResponseBody = options?.includeResponseBody || false;\n\n return {\n async before(request: Request) {\n const logData = {\n url: request.url,\n method: request.method,\n contentType: request.headers.get('Content-Type'),\n headers: Object.fromEntries([...request.headers.entries()]),\n };\n\n console[logLevel]('\u{1F680} Outgoing Request:', logData);\n\n if (includeRequestBody) {\n try {\n // Clone the request to avoid consuming the body stream\n const clonedRequest = request.clone();\n if (clonedRequest.headers.get('Content-Type')?.includes('application/json')) {\n const body = await clonedRequest.json().catch(() => null);\n console[logLevel]('Request Body:', body);\n } else {\n const body = await clonedRequest.text().catch(() => null);\n console[logLevel]('Request Body:', body);\n }\n } catch (error) {\n console.error('Could not log request body:', error);\n }\n }\n\n return request;\n },\n\n async after(response: Response) {\n const logData = {\n status: response.status,\n statusText: response.statusText,\n url: response.url,\n headers: Object.fromEntries([...response.headers.entries()]),\n };\n\n console[logLevel]('\u{1F4E5} Incoming Response:', logData);\n\n if (includeResponseBody && response.body) {\n try {\n // Clone the response to avoid consuming the body stream\n const clonedResponse = response.clone();\n if (clonedResponse.headers.get('Content-Type')?.includes('application/json')) {\n const body = await clonedResponse.json().catch(() => null);\n console[logLevel]('Response Body:', body);\n } else {\n const body = await clonedResponse.text().catch(() => null);\n if (body) {\n console[logLevel]('Response Body:', body.substring(0, 500) + (body.length > 500 ? '...' : ''));\n } else {\n console[logLevel]('No response body');\n }\n }\n } catch (error) {\n console.error('Could not log response body:', error);\n }\n }\n\n return response;\n },\n };\n};\n";
@@ -1331,13 +1349,13 @@ var response_default = "export class APIResponse<Body = unknown, Status extends
1331
1349
  var sse_default = 'export type SSEListener = (eventType: string) => AsyncIterable<string>;\n\nexport function sse(response: Response): SSEListener {\n const subscribers = new Map<\n string,\n { queue: string[]; resolve: (() => void) | null }\n >();\n let started = false;\n let streamDone = false;\n\n function dispatch(eventType: string, data: string) {\n const sub = subscribers.get(eventType);\n if (sub) {\n sub.queue.push(data);\n sub.resolve?.();\n sub.resolve = null;\n }\n }\n\n function endAll() {\n streamDone = true;\n for (const sub of subscribers.values()) {\n sub.resolve?.();\n }\n }\n\n function startReading() {\n if (started) return;\n started = true;\n const decoder = new TextDecoder();\n let buffer = "";\n\n (async () => {\n try {\n for await (const value of response.body!) {\n buffer += decoder.decode(value, { stream: true });\n const parts = buffer.split("\\n\\n");\n buffer = parts.pop()!;\n\n for (const part of parts) {\n if (!part.trim()) continue;\n let eventType = "message";\n let data = "";\n for (const line of part.split("\\n")) {\n if (line.startsWith("event:")) {\n eventType = line.slice(6).trim();\n } else if (line.startsWith("data:")) {\n data += (data ? "\\n" : "") + line.slice(5).trim();\n }\n }\n if (data) dispatch(eventType, data);\n }\n }\n } catch {}\n endAll();\n })();\n }\n\n return function listen(eventType: string): AsyncIterable<string> {\n if (!subscribers.has(eventType)) {\n subscribers.set(eventType, { queue: [], resolve: null });\n }\n const sub = subscribers.get(eventType)!;\n startReading();\n\n return {\n [Symbol.asyncIterator]() {\n return {\n async next(): Promise<IteratorResult<string>> {\n while (sub.queue.length === 0) {\n if (streamDone) return { value: undefined as any, done: true };\n const { promise, resolve } = Promise.withResolvers<void>();\n sub.resolve = resolve;\n await promise;\n }\n return { value: sub.queue.shift()!, done: false };\n },\n async return(): Promise<IteratorResult<string>> {\n return { value: undefined as any, done: true };\n },\n };\n },\n };\n };\n}\n';
1332
1350
 
1333
1351
  // packages/typescript/src/lib/paginations/cursor-pagination.txt
1334
- var cursor_pagination_default = "type CursorPaginationParams = {\n cursor?: string;\n};\n\ninterface CursorMetadata extends Metadata {\n nextCursor?: string;\n}\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationResult<T, M extends CursorMetadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<T, M extends CursorMetadata> = (\n input: CursorPaginationParams,\n) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class CursorPagination<T, M extends CursorMetadata> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: CursorPaginationParams;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M>;\n\n constructor(\n initialParams: PartialNullable<CursorPaginationParams>,\n fetchFn: FetchFn<T, M>,\n ) {\n this.#fetchFn = fetchFn;\n this.#params = {\n cursor: initialParams.cursor ?? undefined,\n };\n }\n\n async getNextPage() {\n const result = await this.#fetchFn(this.#params);\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n cursor: result.meta.nextCursor,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter() {\n if (!this.#currentPage) {\n yield await this.getNextPage();\n }\n\n while (this.hasMore) {\n yield await this.getNextPage();\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n\ntype PartialNullable<T> = {\n [K in keyof T]?: T[K] | null;\n};\n";
1352
+ var cursor_pagination_default = "type CursorPaginationParams = {\n cursor?: string;\n};\n\ninterface CursorMetadata extends Metadata {\n nextCursor?: string;\n}\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationRequestOptions = {\n signal?: AbortSignal;\n};\n\ntype PaginationResult<T, M extends CursorMetadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<T, M extends CursorMetadata> = (\n input: CursorPaginationParams,\n requestOptions?: PaginationRequestOptions,\n) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class CursorPagination<T, M extends CursorMetadata> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: CursorPaginationParams;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M>;\n readonly #requestOptions: PaginationRequestOptions;\n\n constructor(\n initialParams: PartialNullable<CursorPaginationParams>,\n fetchFn: FetchFn<T, M>,\n requestOptions: PaginationRequestOptions = {},\n ) {\n this.#fetchFn = fetchFn;\n this.#requestOptions = requestOptions;\n this.#params = {\n cursor: initialParams.cursor ?? undefined,\n };\n }\n\n async getNextPage(requestOptions?: PaginationRequestOptions) {\n const result = await this.#fetchFn(this.#params, {\n ...this.#requestOptions,\n ...requestOptions,\n });\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n cursor: result.meta.nextCursor,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter(requestOptions?: PaginationRequestOptions) {\n if (!this.#currentPage) {\n yield await this.getNextPage(requestOptions);\n }\n\n while (this.hasMore) {\n yield await this.getNextPage(requestOptions);\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n\ntype PartialNullable<T> = {\n [K in keyof T]?: T[K] | null;\n};\n";
1335
1353
 
1336
1354
  // packages/typescript/src/lib/paginations/offset-pagination.txt
1337
- var offset_pagination_default = "type OffsetPaginationParams = {\n offset: number;\n limit: number;\n};\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationResult<T, M extends Metadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<T, M extends Metadata> = (\n input: OffsetPaginationParams,\n) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class OffsetPagination<T, M extends Metadata> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: OffsetPaginationParams;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M>;\n\n constructor(\n initialParams: Partial<OffsetPaginationParams>,\n fetchFn: FetchFn<T, M>,\n ) {\n this.#fetchFn = fetchFn;\n this.#params = {\n limit: initialParams.limit ?? 0,\n offset: initialParams.offset ?? 0,\n };\n }\n\n async getNextPage() {\n const result = await this.#fetchFn(this.#params);\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n offset: this.#params.offset + this.#params.limit,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter() {\n if (!this.#currentPage) {\n yield await this.getNextPage();\n }\n\n while (this.hasMore) {\n yield await this.getNextPage();\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n\n reset(params?: Partial<OffsetPaginationParams>) {\n this.#meta = null;\n this.#currentPage = null;\n if (params) {\n this.#params = { ...this.#params, ...params };\n } else {\n this.#params.offset = 0;\n }\n return this;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n";
1355
+ var offset_pagination_default = "type OffsetPaginationParams = {\n offset: number;\n limit: number;\n};\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationRequestOptions = {\n signal?: AbortSignal;\n};\n\ntype PaginationResult<T, M extends Metadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<T, M extends Metadata> = (\n input: OffsetPaginationParams,\n requestOptions?: PaginationRequestOptions,\n) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class OffsetPagination<T, M extends Metadata> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: OffsetPaginationParams;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M>;\n readonly #requestOptions: PaginationRequestOptions;\n\n constructor(\n initialParams: Partial<OffsetPaginationParams>,\n fetchFn: FetchFn<T, M>,\n requestOptions: PaginationRequestOptions = {},\n ) {\n this.#fetchFn = fetchFn;\n this.#requestOptions = requestOptions;\n this.#params = {\n limit: initialParams.limit ?? 0,\n offset: initialParams.offset ?? 0,\n };\n }\n\n async getNextPage(requestOptions?: PaginationRequestOptions) {\n const result = await this.#fetchFn(this.#params, {\n ...this.#requestOptions,\n ...requestOptions,\n });\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n offset: this.#params.offset + this.#params.limit,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter(requestOptions?: PaginationRequestOptions) {\n if (!this.#currentPage) {\n yield await this.getNextPage(requestOptions);\n }\n\n while (this.hasMore) {\n yield await this.getNextPage(requestOptions);\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n\n reset(params?: Partial<OffsetPaginationParams>) {\n this.#meta = null;\n this.#currentPage = null;\n if (params) {\n this.#params = { ...this.#params, ...params };\n } else {\n this.#params.offset = 0;\n }\n return this;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n";
1338
1356
 
1339
1357
  // packages/typescript/src/lib/paginations/page-pagination.txt
1340
- var page_pagination_default = "type InferPage<T> = T extends Page<infer U> ? U : never;\ntype PaginationParams<P extends number | bigint, S extends number | bigint> = {\n page?: P;\n pageSize?: S;\n};\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationResult<T, M extends Metadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> = (input: Partial<PaginationParams<P, S>>) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class Pagination<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: PaginationParams<P, S>;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M, P, S>;\n\n constructor(\n initialParams: Partial<PaginationParams<P, S>>,\n fetchFn: FetchFn<T, M, P, S>,\n ) {\n this.#fetchFn = fetchFn;\n this.#params = { ...initialParams, page: initialParams.page };\n }\n\n async getNextPage() {\n const result = await this.#fetchFn(this.#params);\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n page: ((this.#params.page as number) || 0 + 1) as never,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter() {\n if (!this.#currentPage) {\n yield await this.getNextPage();\n }\n\n while (this.hasMore) {\n yield await this.getNextPage();\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n";
1358
+ var page_pagination_default = "type InferPage<T> = T extends Page<infer U> ? U : never;\ntype PaginationParams<P extends number | bigint, S extends number | bigint> = {\n page?: P;\n pageSize?: S;\n};\n\ninterface Metadata {\n hasMore?: boolean;\n}\n\ntype PaginationRequestOptions = {\n signal?: AbortSignal;\n};\n\ntype PaginationResult<T, M extends Metadata> = {\n data: T[];\n meta: M;\n};\n\ntype FetchFn<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> = (\n input: Partial<PaginationParams<P, S>>,\n requestOptions?: PaginationRequestOptions,\n) => Promise<PaginationResult<T, M>>;\n\n/**\n * @experimental\n */\nexport class Pagination<\n T,\n M extends Metadata,\n P extends number | bigint,\n S extends number | bigint,\n> {\n #meta: PaginationResult<T, M>['meta'] | null = null;\n #params: PaginationParams<P, S>;\n #currentPage: Page<T> | null = null;\n readonly #fetchFn: FetchFn<T, M, P, S>;\n readonly #requestOptions: PaginationRequestOptions;\n\n constructor(\n initialParams: Partial<PaginationParams<P, S>>,\n fetchFn: FetchFn<T, M, P, S>,\n requestOptions: PaginationRequestOptions = {},\n ) {\n this.#fetchFn = fetchFn;\n this.#requestOptions = requestOptions;\n this.#params = { ...initialParams, page: initialParams.page };\n }\n\n async getNextPage(requestOptions?: PaginationRequestOptions) {\n const result = await this.#fetchFn(this.#params, {\n ...this.#requestOptions,\n ...requestOptions,\n });\n this.#currentPage = new Page(result.data);\n this.#meta = result.meta;\n this.#params = {\n ...this.#params,\n page: (((this.#params.page as number) || 0) + 1) as never,\n };\n return this;\n }\n\n getCurrentPage() {\n if (!this.#currentPage) {\n throw new Error(\n 'No page data available. Please call getNextPage() first.',\n );\n }\n return this.#currentPage;\n }\n\n get hasMore() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta.hasMore;\n }\n\n async *[Symbol.asyncIterator]() {\n for await (const page of this.iter()) {\n yield page.getCurrentPage();\n }\n }\n\n async *iter(requestOptions?: PaginationRequestOptions) {\n if (!this.#currentPage) {\n yield await this.getNextPage(requestOptions);\n }\n\n while (this.hasMore) {\n yield await this.getNextPage(requestOptions);\n }\n }\n\n get metadata() {\n if (!this.#meta) {\n throw new Error(\n 'No meta data available. Please call getNextPage() first.',\n );\n }\n return this.#meta;\n }\n}\n\nclass Page<T> {\n data: T[];\n constructor(data: T[]) {\n this.data = data;\n }\n}\n";
1341
1359
 
1342
1360
  // packages/typescript/src/lib/readme/readme.ts
1343
1361
  import { isEmpty as isEmpty3 } from "@sdk-it/core";
@@ -1752,7 +1770,7 @@ function expandServerUrls(servers) {
1752
1770
 
1753
1771
  // packages/typescript/src/lib/typescript-snippet.ts
1754
1772
  import { camelcase as camelcase5, spinalcase as spinalcase3 } from "stringcase";
1755
- import { isEmpty as isEmpty4, pascalcase as pascalcase4, resolveRef as resolveRef3 } from "@sdk-it/core";
1773
+ import { isEmpty as isEmpty4, pascalcase as pascalcase4, resolveRef as resolveRef4 } from "@sdk-it/core";
1756
1774
  import "@sdk-it/readme";
1757
1775
  import {
1758
1776
  forEachOperation as forEachOperation5,
@@ -1761,7 +1779,7 @@ import {
1761
1779
  } from "@sdk-it/spec";
1762
1780
 
1763
1781
  // packages/typescript/src/lib/emitters/snippet.ts
1764
- import { followRef as followRef5, isRef as isRef5, resolveRef as resolveRef2 } from "@sdk-it/core";
1782
+ import { followRef as followRef5, isRef as isRef5, resolveRef as resolveRef3 } from "@sdk-it/core";
1765
1783
  var SnippetEmitter = class {
1766
1784
  spec;
1767
1785
  generatedRefs = /* @__PURE__ */ new Set();
@@ -1770,12 +1788,12 @@ var SnippetEmitter = class {
1770
1788
  this.spec = spec;
1771
1789
  }
1772
1790
  object(schema) {
1773
- const schemaObj = resolveRef2(this.spec, schema);
1791
+ const schemaObj = resolveRef3(this.spec, schema);
1774
1792
  const result = {};
1775
1793
  const properties = schemaObj.properties || {};
1776
1794
  for (const [propName, propSchema] of Object.entries(properties)) {
1777
1795
  const isRequired = (schemaObj.required ?? []).includes(propName);
1778
- const resolvedProp = resolveRef2(this.spec, propSchema);
1796
+ const resolvedProp = resolveRef3(this.spec, propSchema);
1779
1797
  if (isRequired || resolvedProp.example !== void 0 || resolvedProp.default !== void 0) {
1780
1798
  result[propName] = this.handle(propSchema);
1781
1799
  }
@@ -1788,7 +1806,7 @@ var SnippetEmitter = class {
1788
1806
  return result;
1789
1807
  }
1790
1808
  array(schema) {
1791
- const schemaObj = resolveRef2(this.spec, schema);
1809
+ const schemaObj = resolveRef3(this.spec, schema);
1792
1810
  const itemsSchema = schemaObj.items;
1793
1811
  if (!itemsSchema) {
1794
1812
  return [];
@@ -1900,7 +1918,7 @@ var SnippetEmitter = class {
1900
1918
  if (isRef5(schemaOrRef)) {
1901
1919
  return this.ref(schemaOrRef.$ref);
1902
1920
  }
1903
- const schema = resolveRef2(this.spec, schemaOrRef);
1921
+ const schema = resolveRef3(this.spec, schemaOrRef);
1904
1922
  if (schema.example !== void 0) {
1905
1923
  return schema.example;
1906
1924
  }
@@ -1965,7 +1983,7 @@ var TypeScriptSnippet = class {
1965
1983
  let payload = "{}";
1966
1984
  if (!isEmpty4(operation.requestBody)) {
1967
1985
  const contentTypes = Object.keys(operation.requestBody.content || {});
1968
- const schema = resolveRef3(
1986
+ const schema = resolveRef4(
1969
1987
  this.#spec,
1970
1988
  operation.requestBody.content[contentTypes[0]].schema
1971
1989
  );
@@ -2035,22 +2053,25 @@ var TypeScriptSnippet = class {
2035
2053
  switch (pagination.type) {
2036
2054
  case "page":
2037
2055
  return {
2038
- content: `const result = ${this.#toRequest(entry, payload)}`,
2039
- footer: `for await (const page of result) {
2056
+ content: `const controller = new AbortController();
2057
+ const result = await ${camelcase5(this.#clientName)}.request('${entry.method.toUpperCase()} ${entry.path}', ${payload}, { signal: controller.signal });`,
2058
+ footer: `for await (const page of result.iter({ signal: controller.signal })) {
2040
2059
  console.log(page);
2041
2060
  }`
2042
2061
  };
2043
2062
  case "offset":
2044
2063
  return {
2045
- content: `const result = ${this.#toRequest(entry, payload)}`,
2046
- footer: `for await (const page of result) {
2064
+ content: `const controller = new AbortController();
2065
+ const result = await ${camelcase5(this.#clientName)}.request('${entry.method.toUpperCase()} ${entry.path}', ${payload}, { signal: controller.signal });`,
2066
+ footer: `for await (const page of result.iter({ signal: controller.signal })) {
2047
2067
  console.log(page);
2048
2068
  }`
2049
2069
  };
2050
2070
  case "cursor":
2051
2071
  return {
2052
- content: `const result = ${this.#toRequest(entry, payload)}`,
2053
- footer: `for await (const page of result) {
2072
+ content: `const controller = new AbortController();
2073
+ const result = await ${camelcase5(this.#clientName)}.request('${entry.method.toUpperCase()} ${entry.path}', ${payload}, { signal: controller.signal });`,
2074
+ footer: `for await (const page of result.iter({ signal: controller.signal })) {
2054
2075
  console.log(page);
2055
2076
  }`
2056
2077
  };
@@ -2156,7 +2177,7 @@ ${client.use}`;
2156
2177
  );
2157
2178
  if (hasServers) {
2158
2179
  sections.push(
2159
- "| `baseUrl` | `string` | No | API base URL (default: `" + baseUrl + "`) |"
2180
+ "| `baseUrl` | `string | (() => string | Promise<string>)` | No | API base URL (default: `" + baseUrl + "`) |"
2160
2181
  );
2161
2182
  }
2162
2183
  for (const authOption of authOptions) {
@@ -2230,10 +2251,10 @@ ${client.use}`;
2230
2251
  "",
2231
2252
  "// Check if more pages exist",
2232
2253
  "if (result.hasMore) {",
2233
- " await result.getNextPage();",
2254
+ " await result.getNextPage({ signal: controller.signal });",
2234
2255
  "}",
2235
2256
  "",
2236
- "// Or iterate through all pages automatically",
2257
+ "// Or iterate through all pages with cancellable page fetches",
2237
2258
  paginationExample.footer
2238
2259
  ])
2239
2260
  );
@@ -2897,12 +2918,9 @@ ${utils_default}`
2897
2918
  skipLibCheck: true,
2898
2919
  skipDefaultLibCheck: true,
2899
2920
  target: "ESNext",
2900
- module: "ESNext",
2901
2921
  noEmit: true,
2902
- strict: true,
2903
2922
  allowImportingTsExtensions: true,
2904
2923
  verbatimModuleSyntax: true,
2905
- baseUrl: ".",
2906
2924
  moduleResolution: "bundler"
2907
2925
  },
2908
2926
  include: ["**/*.ts"]