@sdk-it/typescript 0.39.0 → 0.41.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 +169 -59
- package/dist/index.js.map +3 -3
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/emitters/zod.d.ts.map +1 -1
- package/dist/lib/generate.d.ts +3 -1
- package/dist/lib/generate.d.ts.map +1 -1
- package/dist/lib/generator.d.ts.map +1 -1
- package/dist/lib/options.d.ts +1 -0
- package/dist/lib/options.d.ts.map +1 -1
- package/dist/lib/sdk.d.ts +1 -1
- package/dist/lib/sdk.d.ts.map +1 -1
- package/dist/lib/server-urls.d.ts +3 -0
- package/dist/lib/server-urls.d.ts.map +1 -0
- package/dist/lib/status-map.d.ts.map +1 -1
- package/dist/lib/typescript-snippet.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/connect.d.ts +0 -1
- package/dist/connect.d.ts.map +0 -1
- package/dist/global.d.js +0 -1
- package/dist/global.d.js.map +0 -7
- package/dist/lib/connect.d.ts +0 -162
- package/dist/lib/connect.d.ts.map +0 -1
- package/dist/lib/readme-generator.d.ts +0 -8
- package/dist/lib/readme-generator.d.ts.map +0 -1
- package/dist/lib/statusMap.d.ts +0 -2
- package/dist/lib/statusMap.d.ts.map +0 -1
- package/dist/lib/utils.d.ts +0 -17
- package/dist/lib/utils.d.ts.map +0 -1
- package/dist/lib/watcher.d.ts +0 -2
- package/dist/lib/watcher.d.ts.map +0 -1
- package/dist/src/index.js +0 -5
- package/dist/src/index.js.map +0 -7
- package/dist/src/lib/agent/ai-sdk.js +0 -60
- package/dist/src/lib/agent/ai-sdk.js.map +0 -7
- package/dist/src/lib/agent/openai-agents.js +0 -42
- package/dist/src/lib/agent/openai-agents.js.map +0 -7
- package/dist/src/lib/client.js +0 -152
- package/dist/src/lib/client.js.map +0 -7
- package/dist/src/lib/emitters/interface.js +0 -169
- package/dist/src/lib/emitters/interface.js.map +0 -7
- package/dist/src/lib/emitters/snippet.js +0 -191
- package/dist/src/lib/emitters/snippet.js.map +0 -7
- package/dist/src/lib/emitters/zod.js +0 -271
- package/dist/src/lib/emitters/zod.js.map +0 -7
- package/dist/src/lib/generate.js +0 -382
- package/dist/src/lib/generate.js.map +0 -7
- package/dist/src/lib/generator.js +0 -268
- package/dist/src/lib/generator.js.map +0 -7
- package/dist/src/lib/import-utilities.js +0 -56
- package/dist/src/lib/import-utilities.js.map +0 -7
- package/dist/src/lib/options.js +0 -3
- package/dist/src/lib/options.js.map +0 -7
- package/dist/src/lib/readme/prop.emitter.js +0 -283
- package/dist/src/lib/readme/prop.emitter.js.map +0 -7
- package/dist/src/lib/readme/readme.js +0 -105
- package/dist/src/lib/readme/readme.js.map +0 -7
- package/dist/src/lib/sdk.js +0 -236
- package/dist/src/lib/sdk.js.map +0 -7
- package/dist/src/lib/status-map.js +0 -28
- package/dist/src/lib/status-map.js.map +0 -7
- package/dist/src/lib/style.js +0 -1
- package/dist/src/lib/style.js.map +0 -7
- package/dist/src/lib/typescript-snippet.js +0 -738
- package/dist/src/lib/typescript-snippet.js.map +0 -7
package/dist/index.js
CHANGED
|
@@ -172,8 +172,10 @@ var ZodEmitter = class {
|
|
|
172
172
|
*/
|
|
173
173
|
normal(type, schema, required = false, nullable = false) {
|
|
174
174
|
switch (type) {
|
|
175
|
-
case "string":
|
|
176
|
-
|
|
175
|
+
case "string": {
|
|
176
|
+
const defaultVal = (schema["x-zod-type"] === "date" || schema["x-zod-type"] === "coerce-date") && schema.default ? `new Date(${JSON.stringify(schema.default)})` : JSON.stringify(schema.default);
|
|
177
|
+
return `${this.string(schema)}${this.#suffixes(defaultVal, required, nullable)}`;
|
|
178
|
+
}
|
|
177
179
|
case "number":
|
|
178
180
|
case "integer": {
|
|
179
181
|
const { base, defaultValue } = this.#number(schema);
|
|
@@ -259,10 +261,16 @@ var ZodEmitter = class {
|
|
|
259
261
|
switch (schema.format) {
|
|
260
262
|
case "date-time":
|
|
261
263
|
case "datetime":
|
|
262
|
-
|
|
264
|
+
if (schema["x-zod-type"] === "coerce-date") {
|
|
265
|
+
base = "z.coerce.date()";
|
|
266
|
+
} else if (schema["x-zod-type"] === "date") {
|
|
267
|
+
base = "z.date()";
|
|
268
|
+
} else {
|
|
269
|
+
base = "z.string().datetime()";
|
|
270
|
+
}
|
|
263
271
|
break;
|
|
264
272
|
case "date":
|
|
265
|
-
base = "z.
|
|
273
|
+
base = "z.string().date()";
|
|
266
274
|
break;
|
|
267
275
|
case "time":
|
|
268
276
|
base = "z.string() /* optionally add .regex(...) for HH:MM:SS format */";
|
|
@@ -305,14 +313,16 @@ var ZodEmitter = class {
|
|
|
305
313
|
*/
|
|
306
314
|
#number(schema) {
|
|
307
315
|
let defaultValue = schema.default;
|
|
308
|
-
let base
|
|
316
|
+
let base;
|
|
309
317
|
if (schema.format === "int64") {
|
|
310
|
-
base = "z.bigint()";
|
|
318
|
+
base = schema["x-zod-type"] === "coerce-bigint" ? "z.coerce.bigint()" : "z.bigint()";
|
|
311
319
|
if (schema.default !== void 0) {
|
|
312
320
|
defaultValue = `BigInt(${schema.default})`;
|
|
313
321
|
}
|
|
322
|
+
} else {
|
|
323
|
+
base = schema["x-zod-type"] === "coerce-number" ? "z.coerce.number()" : "z.number()";
|
|
314
324
|
}
|
|
315
|
-
if (schema.
|
|
325
|
+
if (schema.type === "integer" && schema.format !== "int64") {
|
|
316
326
|
base += ".int()";
|
|
317
327
|
}
|
|
318
328
|
if (typeof schema.exclusiveMinimum === "number") {
|
|
@@ -415,17 +425,20 @@ var client_default = (spec) => {
|
|
|
415
425
|
token = await Promise.resolve(token());
|
|
416
426
|
}
|
|
417
427
|
return \`Bearer \${token}\`;
|
|
418
|
-
})`
|
|
428
|
+
}).describe('Bearer token for authentication. Can be a string or a function that returns a string.')`
|
|
419
429
|
}
|
|
420
430
|
} : {},
|
|
421
431
|
fetch: {
|
|
422
|
-
schema:
|
|
432
|
+
schema: `fetchType.describe('Custom fetch implementation. Defaults to globalThis.fetch.')`
|
|
423
433
|
},
|
|
424
434
|
baseUrl: {
|
|
425
|
-
schema: spec.servers.length ? `z.enum(servers).default(servers[0])` :
|
|
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.')`
|
|
426
436
|
},
|
|
427
437
|
headers: {
|
|
428
|
-
schema:
|
|
438
|
+
schema: `z.record(z.string()).optional().describe('Default headers to include in all requests.')`
|
|
439
|
+
},
|
|
440
|
+
skipValidation: {
|
|
441
|
+
schema: `z.boolean().optional().describe('Skip request input validation. Client options and TypeScript types still enforce correct usage.')`
|
|
429
442
|
}
|
|
430
443
|
};
|
|
431
444
|
return `import z from 'zod';
|
|
@@ -453,6 +466,7 @@ export class ${spec.name} {
|
|
|
453
466
|
this.options = options;
|
|
454
467
|
}
|
|
455
468
|
|
|
469
|
+
/** Sends a request and returns the unwrapped response data. Delegates to the standalone {@link request} function. */
|
|
456
470
|
async request<const E extends keyof typeof schemas>(
|
|
457
471
|
endpoint: E,
|
|
458
472
|
input: z.input<(typeof schemas)[E]['schema']>,
|
|
@@ -466,32 +480,13 @@ export class ${spec.name} {
|
|
|
466
480
|
});
|
|
467
481
|
}
|
|
468
482
|
|
|
483
|
+
/** Builds a ready-to-send request without sending it. Delegates to the standalone {@link prepare} function. */
|
|
469
484
|
async prepare<const E extends keyof typeof schemas>(
|
|
470
485
|
endpoint: E,
|
|
471
486
|
input: z.input<(typeof schemas)[E]['schema']>,
|
|
472
487
|
options?: { headers?: HeadersInit },
|
|
473
|
-
)
|
|
474
|
-
|
|
475
|
-
}> {
|
|
476
|
-
const clientOptions = await optionsSchema.parseAsync(this.options);
|
|
477
|
-
const route = schemas[endpoint];
|
|
478
|
-
const interceptors = [
|
|
479
|
-
createHeadersInterceptor(
|
|
480
|
-
await this.defaultHeaders(),
|
|
481
|
-
options?.headers ?? {},
|
|
482
|
-
),
|
|
483
|
-
createBaseUrlInterceptor(clientOptions.baseUrl),
|
|
484
|
-
];
|
|
485
|
-
const parsedInput = parseInput(route.schema, input);
|
|
486
|
-
|
|
487
|
-
let config = route.toRequest(parsedInput as never);
|
|
488
|
-
for (const interceptor of interceptors) {
|
|
489
|
-
if (interceptor.before) {
|
|
490
|
-
config = await interceptor.before(config);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
const prepared = { ...config, parse: (response: Response) => parse(route.output, response, (d) => d) as never };
|
|
494
|
-
return prepared as any;
|
|
488
|
+
) {
|
|
489
|
+
return prepare(this, endpoint, input, options);
|
|
495
490
|
}
|
|
496
491
|
|
|
497
492
|
async defaultHeaders() {
|
|
@@ -516,34 +511,89 @@ export class ${spec.name} {
|
|
|
516
511
|
|
|
517
512
|
}
|
|
518
513
|
|
|
514
|
+
/**
|
|
515
|
+
* Sends a validated request using the client's configuration and returns the parsed response.
|
|
516
|
+
* Merges the client's default inputs and headers before sending.
|
|
517
|
+
* Throws \`APIError\` on non-ok responses.
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* \`\`\`ts
|
|
521
|
+
* const result = await request(client, 'GET /users', { limit: 10 });
|
|
522
|
+
* \`\`\`
|
|
523
|
+
*/
|
|
519
524
|
export async function request<const E extends keyof typeof schemas>(
|
|
520
525
|
client: ${spec.name},
|
|
521
526
|
endpoint: E,
|
|
522
527
|
input: z.input<(typeof schemas)[E]['schema']>,
|
|
523
|
-
|
|
528
|
+
requestOptions?: { signal?: AbortSignal; headers?: HeadersInit },
|
|
524
529
|
): Promise<Awaited<ReturnType<(typeof schemas)[E]['dispatch']>>> {
|
|
525
530
|
const route = schemas[endpoint];
|
|
531
|
+
const options = await optionsSchema.parseAsync(client.options);
|
|
526
532
|
const withDefaultInputs = Object.assign(
|
|
527
533
|
{},
|
|
528
|
-
|
|
534
|
+
${defaultInputs},
|
|
529
535
|
input,
|
|
530
536
|
);
|
|
531
|
-
const parsedInput = parseInput(route.schema, withDefaultInputs);
|
|
532
|
-
const clientOptions = await optionsSchema.parseAsync(client.options);
|
|
537
|
+
const parsedInput = options.skipValidation ? withDefaultInputs : parseInput(route.schema, withDefaultInputs);
|
|
533
538
|
const result = await route.dispatch(parsedInput as never, {
|
|
534
|
-
fetch:
|
|
539
|
+
fetch: options.fetch,
|
|
535
540
|
interceptors: [
|
|
536
541
|
createHeadersInterceptor(
|
|
537
|
-
|
|
538
|
-
|
|
542
|
+
{ ...${defaultHeaders}, ...options.headers },
|
|
543
|
+
requestOptions?.headers ?? {},
|
|
539
544
|
),
|
|
540
|
-
createBaseUrlInterceptor(
|
|
545
|
+
createBaseUrlInterceptor(options.baseUrl),
|
|
541
546
|
],
|
|
542
|
-
signal:
|
|
547
|
+
signal: requestOptions?.signal,
|
|
543
548
|
});
|
|
544
549
|
return result as Awaited<ReturnType<(typeof schemas)[E]['dispatch']>>;
|
|
545
550
|
}
|
|
546
551
|
|
|
552
|
+
/**
|
|
553
|
+
* Builds a validated \`RequestConfig\` (url + init) with a \`parse\` function attached, without sending.
|
|
554
|
+
* Use when you need control over the fetch call \u2014 framework integration (Next.js, SvelteKit),
|
|
555
|
+
* custom retry/logging, request batching, or testing.
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* \`\`\`ts
|
|
559
|
+
* const { url, init, parse } = await prepare(client, 'GET /users', { limit: 10 });
|
|
560
|
+
* const response = await fetch(new Request(url, init));
|
|
561
|
+
* const result = await parse(response);
|
|
562
|
+
* \`\`\`
|
|
563
|
+
*/
|
|
564
|
+
export async function prepare<const E extends keyof typeof schemas>(
|
|
565
|
+
client: ${spec.name},
|
|
566
|
+
endpoint: E,
|
|
567
|
+
input: z.input<(typeof schemas)[E]['schema']>,
|
|
568
|
+
requestOptions?: { headers?: HeadersInit },
|
|
569
|
+
): Promise<RequestConfig & {
|
|
570
|
+
parse: (response: Response) => ReturnType<typeof parse>;
|
|
571
|
+
}> {
|
|
572
|
+
const route = schemas[endpoint];
|
|
573
|
+
const options = await optionsSchema.parseAsync(client.options);
|
|
574
|
+
const withDefaultInputs = Object.assign(
|
|
575
|
+
{},
|
|
576
|
+
${defaultInputs},
|
|
577
|
+
input,
|
|
578
|
+
);
|
|
579
|
+
const parsedInput = options.skipValidation ? withDefaultInputs : parseInput(route.schema, withDefaultInputs);
|
|
580
|
+
const interceptors = [
|
|
581
|
+
createHeadersInterceptor(
|
|
582
|
+
{ ...${defaultHeaders}, ...options.headers },
|
|
583
|
+
requestOptions?.headers ?? {},
|
|
584
|
+
),
|
|
585
|
+
createBaseUrlInterceptor(options.baseUrl),
|
|
586
|
+
];
|
|
587
|
+
|
|
588
|
+
let config = route.toRequest(parsedInput as never);
|
|
589
|
+
for (const interceptor of interceptors) {
|
|
590
|
+
if (interceptor.before) {
|
|
591
|
+
config = await interceptor.before(config);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return { ...config, parse: (response: Response) => parse(route.output as never, response, (d) => d) as never } as any;
|
|
595
|
+
}
|
|
596
|
+
|
|
547
597
|
|
|
548
598
|
`;
|
|
549
599
|
};
|
|
@@ -652,7 +702,7 @@ var TypeScriptEmitter = class {
|
|
|
652
702
|
case "date-time":
|
|
653
703
|
case "datetime":
|
|
654
704
|
case "date":
|
|
655
|
-
type = "
|
|
705
|
+
type = "string";
|
|
656
706
|
break;
|
|
657
707
|
case "binary":
|
|
658
708
|
case "byte":
|
|
@@ -728,6 +778,8 @@ import {
|
|
|
728
778
|
import { camelcase as camelcase3 } from "stringcase";
|
|
729
779
|
import { isEmpty, pascalcase as pascalcase3 } from "@sdk-it/core";
|
|
730
780
|
import {
|
|
781
|
+
isBinaryContentType,
|
|
782
|
+
isSseContentType,
|
|
731
783
|
isStreamingContentType,
|
|
732
784
|
isTextContentType,
|
|
733
785
|
parseJsonContentType,
|
|
@@ -754,6 +806,7 @@ var status_map_default = {
|
|
|
754
806
|
"412": "PreconditionFailed",
|
|
755
807
|
"413": "PayloadTooLarge",
|
|
756
808
|
"410": "Gone",
|
|
809
|
+
"415": "UnsupportedMediaType",
|
|
757
810
|
"422": "UnprocessableEntity",
|
|
758
811
|
"429": "TooManyRequests",
|
|
759
812
|
"500": "InternalServerError",
|
|
@@ -928,16 +981,31 @@ function fromContentType(spec, typeScriptDeserialzer, response) {
|
|
|
928
981
|
if ((response.headers ?? {})["Transfer-Encoding"]) {
|
|
929
982
|
return streamedOutput();
|
|
930
983
|
}
|
|
984
|
+
const hasContentDisposition = hasHeader(response, "Content-Disposition");
|
|
931
985
|
for (const type in response.content) {
|
|
932
|
-
|
|
986
|
+
const isStreaming = isStreamingContentType(type);
|
|
987
|
+
const isBinary = isBinaryContentType(type) || isStreaming && hasContentDisposition;
|
|
988
|
+
if (isStreaming && !hasContentDisposition) {
|
|
933
989
|
return streamedOutput();
|
|
934
990
|
}
|
|
991
|
+
if (isBinary) {
|
|
992
|
+
return {
|
|
993
|
+
parser: "buffered",
|
|
994
|
+
responseSchema: response.content[type].schema ? typeScriptDeserialzer.handle(response.content[type].schema, true) : "Blob"
|
|
995
|
+
};
|
|
996
|
+
}
|
|
935
997
|
if (parseJsonContentType(type)) {
|
|
936
998
|
return {
|
|
937
999
|
parser: "buffered",
|
|
938
1000
|
responseSchema: response.content[type].schema ? typeScriptDeserialzer.handle(response.content[type].schema, true) : "void"
|
|
939
1001
|
};
|
|
940
1002
|
}
|
|
1003
|
+
if (isSseContentType(type)) {
|
|
1004
|
+
return {
|
|
1005
|
+
parser: "sse",
|
|
1006
|
+
responseSchema: "SSEListener"
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
941
1009
|
if (isTextContentType(type)) {
|
|
942
1010
|
return {
|
|
943
1011
|
parser: "buffered",
|
|
@@ -947,6 +1015,11 @@ function fromContentType(spec, typeScriptDeserialzer, response) {
|
|
|
947
1015
|
}
|
|
948
1016
|
return streamedOutput();
|
|
949
1017
|
}
|
|
1018
|
+
function hasHeader(response, name) {
|
|
1019
|
+
const headers = response.headers ?? {};
|
|
1020
|
+
const target = name.toLowerCase();
|
|
1021
|
+
return Object.keys(headers).some((key) => key.toLowerCase() === target);
|
|
1022
|
+
}
|
|
950
1023
|
function streamedOutput() {
|
|
951
1024
|
return {
|
|
952
1025
|
parser: "chunked",
|
|
@@ -1108,6 +1181,7 @@ ${allSchemas.map((it) => it.use).join(",\n")}
|
|
|
1108
1181
|
`import * as outputs from '${config.makeImport("../outputs/index")}';`,
|
|
1109
1182
|
`import { toRequest, json, urlencoded, empty, formdata, type HeadersInit } from '${config.makeImport("../http/request")}';`,
|
|
1110
1183
|
`import { chunked, buffered } from "${config.makeImport("../http/parse-response")}";`,
|
|
1184
|
+
`import { sse } from "${config.makeImport("../http/sse")}";`,
|
|
1111
1185
|
`import * as ${camelcase4(name)} from '../inputs/${config.makeImport(spinalcase2(name))}';`,
|
|
1112
1186
|
`import { createBaseUrlInterceptor, createHeadersInterceptor, type Interceptor } from '${config.makeImport("../http/interceptors")}';`,
|
|
1113
1187
|
`import { Dispatcher, fetchType, type InstanceType } from '${config.makeImport("../http/dispatcher")}';`,
|
|
@@ -1236,13 +1310,13 @@ function operationSchema(ir, operation, type) {
|
|
|
1236
1310
|
}
|
|
1237
1311
|
|
|
1238
1312
|
// packages/typescript/src/lib/http/dispatcher.txt
|
|
1239
|
-
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
|
|
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[], 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 apiresponse = (output || APIResponse).create(\n response.status,\n response.headers,\n mapper((await parser(response)) as ResponseData<T>),\n );\n\n return apiresponse as RebindSuccessPayload<Extract<InstanceType<T>, SuccessfulResponse<unknown>>, R>;\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[], 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 return await parse(\n outputs,\n response,\n mapper ?? ((data: ResponseData<T>) => data as unknown as R),\n );\n }\n}\n";
|
|
1240
1314
|
|
|
1241
1315
|
// packages/typescript/src/lib/http/interceptors.txt
|
|
1242
1316
|
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";
|
|
1243
1317
|
|
|
1244
1318
|
// packages/typescript/src/lib/http/parse-response.txt
|
|
1245
|
-
var parse_response_default = 'import { parse } from "fast-content-type-parse";\n\nasync function handleChunkedResponse(response: Response, contentType: string) {\n const { type } = parse(contentType);\n\n switch (type) {\n case "application/json": {\n let buffer = "";\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return JSON.parse(buffer);\n }\n case "text/html":\n case "text/plain": {\n let buffer = "";\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return buffer;\n }\n default:\n return response.body;\n }\n}\n\nexport function chunked(response: Response) {\n return response.body!;\n}\n\nexport async function buffered(response: Response) {\n const contentType = response.headers.get("Content-Type");\n if (!contentType) {\n throw new Error("Content-Type header is missing");\n }\n\n if (response.status === 204) {\n return null;\n }\n\n const { type } = parse(contentType);\n
|
|
1319
|
+
var parse_response_default = 'import { parse } from "fast-content-type-parse";\n\nfunction isBinaryContentType(contentType: string) {\n const type = contentType.toLowerCase();\n if (type.startsWith("image/")) {\n return true;\n }\n if (type.startsWith("audio/")) {\n return true;\n }\n if (type.startsWith("video/")) {\n return true;\n }\n switch (type) {\n case "application/pdf":\n case "application/zip":\n case "application/gzip":\n case "application/x-7z-compressed":\n case "application/x-tar":\n case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":\n case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":\n case "application/vnd.openxmlformats-officedocument.presentationml.presentation":\n case "application/vnd.ms-excel":\n case "application/vnd.ms-powerpoint":\n case "application/msword":\n case "application/octet-stream":\n return true;\n default:\n return false;\n }\n}\n\nasync function handleChunkedResponse(response: Response, contentType: string) {\n const { type } = parse(contentType);\n\n switch (type) {\n case "application/json": {\n let buffer = "";\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return JSON.parse(buffer);\n }\n case "text/html":\n case "text/plain": {\n let buffer = "";\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return buffer;\n }\n default:\n return response.body;\n }\n}\n\nexport function chunked(response: Response) {\n return response.body!;\n}\n\nexport async function buffered(response: Response) {\n const contentType = response.headers.get("Content-Type");\n if (!contentType) {\n throw new Error("Content-Type header is missing");\n }\n\n if (response.status === 204) {\n return null;\n }\n\n const { type } = parse(contentType);\n if (isBinaryContentType(type)) {\n return response.blob();\n }\n if (type.startsWith("text/")) {\n return response.text();\n }\n switch (type) {\n case "application/json":\n return response.json();\n case "application/xml":\n return response.text();\n case "application/x-www-form-urlencoded": {\n const text = await response.text();\n return Object.fromEntries(new URLSearchParams(text));\n }\n case "multipart/form-data":\n return response.formData();\n default:\n throw new Error(`Unsupported content type: ${contentType}`);\n }\n}\n';
|
|
1246
1320
|
|
|
1247
1321
|
// packages/typescript/src/lib/http/parser.txt
|
|
1248
1322
|
var parser_default = "import { z } from 'zod';\n\nexport class ParseError<T extends z.ZodType<any, any, any>> extends Error {\n public data: z.typeToFlattenedError<T, z.ZodIssue>;\n constructor(data: z.typeToFlattenedError<T, z.ZodIssue>) {\n super('Validation failed');\n this.name = 'ParseError';\n this.data = data;\n }\n}\n\nexport function parseInput<T extends z.ZodType<any, any, any>>(\n schema: T,\n input: unknown,\n): z.infer<T> {\n const result = schema.safeParse(input);\n if (!result.success) {\n const error = result.error.flatten((issue) => issue);\n throw new ParseError(error);\n }\n return result.data as z.infer<T>;\n}\n";
|
|
@@ -1253,6 +1327,9 @@ var request_default = "type Init = Omit<RequestInit, 'headers'> & { headers: Hea
|
|
|
1253
1327
|
// packages/typescript/src/lib/http/response.txt
|
|
1254
1328
|
var response_default = "export class APIResponse<Body = unknown, Status extends number = number> {\n static readonly status: number;\n readonly status: Status;\n data: Body;\n readonly headers: Headers;\n\n constructor(status: Status, headers: Headers, data: Body) {\n this.status = status;\n this.headers = headers;\n this.data = data;\n }\n\n static create<Body = unknown>(status: number, headers: Headers, data: Body) {\n return new this(status, headers, data);\n }\n}\n\nexport class APIError<Body, Status extends number = number> extends APIResponse<\n Body,\n Status\n> {\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(status, headers, data);\n }\n}\n\n// 2xx Success\nexport class Ok<T> extends APIResponse<T, 200> {\n static override readonly status = 200 as const;\n constructor(headers: Headers, data: T) {\n super(Ok.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\n\nexport class Created<T> extends APIResponse<T, 201> {\n static override status = 201 as const;\n constructor(headers: Headers, data: T) {\n super(Created.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class Accepted<T> extends APIResponse<T, 202> {\n static override status = 202 as const;\n constructor(headers: Headers, data: T) {\n super(Accepted.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class NoContent extends APIResponse<never, 204> {\n static override status = 204 as const;\n constructor(headers: Headers) {\n super(NoContent.status, headers, null as never);\n }\n static override create(status: number, headers: Headers): NoContent {\n return new this(headers);\n }\n}\n\n// 4xx Client Errors\nexport class BadRequest<T> extends APIError<T, 400> {\n static override status = 400 as const;\n constructor(headers: Headers, data: T) {\n super(BadRequest.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class Unauthorized<T = { message: string }> extends APIError<T, 401> {\n static override status = 401 as const;\n constructor(headers: Headers, data: T) {\n super(Unauthorized.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class PaymentRequired<T = { message: string }> extends APIError<T, 402> {\n static override status = 402 as const;\n constructor(headers: Headers, data: T) {\n super(PaymentRequired.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class Forbidden<T = { message: string }> extends APIError<T, 403> {\n static override status = 403 as const;\n constructor(headers: Headers, data: T) {\n super(Forbidden.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class NotFound<T = { message: string }> extends APIError<T, 404> {\n static override status = 404 as const;\n constructor(headers: Headers, data: T) {\n super(NotFound.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class MethodNotAllowed<T = { message: string }> extends APIError<\n T,\n 405\n> {\n static override status = 405 as const;\n constructor(headers: Headers, data: T) {\n super(MethodNotAllowed.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class NotAcceptable<T = { message: string }> extends APIError<T, 406> {\n static override status = 406 as const;\n constructor(headers: Headers, data: T) {\n super(NotAcceptable.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class Conflict<T = { message: string }> extends APIError<T, 409> {\n static override status = 409 as const;\n constructor(headers: Headers, data: T) {\n super(Conflict.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class Gone<T = { message: string }> extends APIError<T, 410> {\n static override status = 410 as const;\n constructor(headers: Headers, data: T) {\n super(Gone.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class PreconditionFailed<T = { message: string }> extends APIError<\n T,\n 412\n> {\n static override status = 412 as const;\n constructor(headers: Headers, data: T) {\n super(PreconditionFailed.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class UnprocessableEntity<\n T = { message: string; errors?: Record<string, string[]> },\n> extends APIError<T, 422> {\n static override status = 422 as const;\n constructor(headers: Headers, data: T) {\n super(UnprocessableEntity.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class TooManyRequests<\n T = { message: string; retryAfter?: string },\n> extends APIError<T, 429> {\n static override status = 429 as const;\n constructor(headers: Headers, data: T) {\n super(TooManyRequests.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class PayloadTooLarge<T = { message: string }> extends APIError<T, 413> {\n static override status = 413 as const;\n constructor(headers: Headers, data: T) {\n super(PayloadTooLarge.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class UnsupportedMediaType<T = { message: string }> extends APIError<\n T,\n 415\n> {\n static override status = 415 as const;\n constructor(headers: Headers, data: T) {\n super(UnsupportedMediaType.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\n\n// 5xx Server Errors\nexport class InternalServerError<T = { message: string }> extends APIError<\n T,\n 500\n> {\n static override status = 500 as const;\n constructor(headers: Headers, data: T) {\n super(InternalServerError.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class NotImplemented<T = { message: string }> extends APIError<T, 501> {\n static override status = 501 as const;\n constructor(headers: Headers, data: T) {\n super(NotImplemented.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class BadGateway<T = { message: string }> extends APIError<T, 502> {\n static override status = 502 as const;\n constructor(headers: Headers, data: T) {\n super(BadGateway.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class ServiceUnavailable<\n T = { message: string; retryAfter?: string },\n> extends APIError<T, 503> {\n static override status = 503 as const;\n constructor(headers: Headers, data: T) {\n super(ServiceUnavailable.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\nexport class GatewayTimeout<T = { message: string }> extends APIError<T, 504> {\n static override status = 504 as const;\n constructor(headers: Headers, data: T) {\n super(GatewayTimeout.status, headers, data);\n }\n static override create<T>(status: number, headers: Headers, data: T) {\n return new this(headers, data);\n }\n}\n\nexport type ClientError =\n | BadRequest<unknown>\n | Unauthorized<unknown>\n | PaymentRequired<unknown>\n | Forbidden<unknown>\n | NotFound<unknown>\n | MethodNotAllowed<unknown>\n | NotAcceptable<unknown>\n | Conflict<unknown>\n | Gone<unknown>\n | PreconditionFailed<unknown>\n | PayloadTooLarge<unknown>\n | UnsupportedMediaType<unknown>\n | UnprocessableEntity<unknown>\n | TooManyRequests<unknown>;\n\nexport type ServerError =\n | InternalServerError<unknown>\n | NotImplemented<unknown>\n | BadGateway<unknown>\n | ServiceUnavailable<unknown>\n | GatewayTimeout<unknown>;\n\nexport type ProblematicResponse = ClientError | ServerError;\n\nexport type SuccessfulResponse<T = unknown> =\n | Ok<T>\n | Created<T>\n | Accepted<T>\n | NoContent;\n\nexport type RebindSuccessPayload<Resp, New> =\n Resp extends Ok<infer _>\n ? Ok<New>\n : Resp extends Created<infer _>\n ? Created<New>\n : Resp extends Accepted<infer _>\n ? Accepted<New>\n : Resp extends NoContent\n ? NoContent\n : Resp extends SuccessfulResponse<infer _>\n ? APIResponse<New, Resp['status']>\n : never;\n";
|
|
1255
1329
|
|
|
1330
|
+
// packages/typescript/src/lib/http/sse.txt
|
|
1331
|
+
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
|
+
|
|
1256
1333
|
// packages/typescript/src/lib/paginations/cursor-pagination.txt
|
|
1257
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";
|
|
1258
1335
|
|
|
@@ -1647,6 +1724,32 @@ ${l}`));
|
|
|
1647
1724
|
return markdown.join("\n\n");
|
|
1648
1725
|
}
|
|
1649
1726
|
|
|
1727
|
+
// packages/typescript/src/lib/server-urls.ts
|
|
1728
|
+
function expandServerUrls(servers) {
|
|
1729
|
+
return servers.flatMap((server) => {
|
|
1730
|
+
const variables = server.variables;
|
|
1731
|
+
if (!variables || Object.keys(variables).length === 0) {
|
|
1732
|
+
return [server.url];
|
|
1733
|
+
}
|
|
1734
|
+
const entries = Object.entries(variables);
|
|
1735
|
+
const valueSets = entries.map(([, variable]) => {
|
|
1736
|
+
const enumValues = variable.enum?.map(String);
|
|
1737
|
+
return enumValues?.length ? enumValues : [String(variable.default)];
|
|
1738
|
+
});
|
|
1739
|
+
const combinations = valueSets.reduce(
|
|
1740
|
+
(acc, values) => acc.flatMap((combo) => values.map((v) => [...combo, v])),
|
|
1741
|
+
[[]]
|
|
1742
|
+
);
|
|
1743
|
+
return combinations.map((combo) => {
|
|
1744
|
+
let url = server.url;
|
|
1745
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1746
|
+
url = url.replaceAll(`{${entries[i][0]}}`, combo[i]);
|
|
1747
|
+
}
|
|
1748
|
+
return url;
|
|
1749
|
+
});
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1650
1753
|
// packages/typescript/src/lib/typescript-snippet.ts
|
|
1651
1754
|
import { camelcase as camelcase5, spinalcase as spinalcase3 } from "stringcase";
|
|
1652
1755
|
import { isEmpty as isEmpty4, pascalcase as pascalcase4, resolveRef as resolveRef3 } from "@sdk-it/core";
|
|
@@ -2000,7 +2103,7 @@ var TypeScriptSnippet = class {
|
|
|
2000
2103
|
}
|
|
2001
2104
|
client() {
|
|
2002
2105
|
const options = {
|
|
2003
|
-
baseUrl: this.#spec.servers
|
|
2106
|
+
baseUrl: expandServerUrls(this.#spec.servers ?? [])[0] ?? "http://localhost:3000"
|
|
2004
2107
|
};
|
|
2005
2108
|
const authOptions = this.#authentication();
|
|
2006
2109
|
if (!isEmpty4(authOptions)) {
|
|
@@ -2041,7 +2144,7 @@ ${client.use}`;
|
|
|
2041
2144
|
const hasServers = Boolean(
|
|
2042
2145
|
this.#spec.servers && this.#spec.servers.length > 0
|
|
2043
2146
|
);
|
|
2044
|
-
const baseUrl = this.#spec.servers
|
|
2147
|
+
const baseUrl = expandServerUrls(this.#spec.servers ?? [])[0] || "https://api.example.com";
|
|
2045
2148
|
const authOptions = this.#authentication();
|
|
2046
2149
|
const hasApiKey = !isEmpty4(authOptions);
|
|
2047
2150
|
sections.push("### Configuration Options");
|
|
@@ -2457,7 +2560,7 @@ ${client.use}`;
|
|
|
2457
2560
|
);
|
|
2458
2561
|
sections.push("");
|
|
2459
2562
|
const bearerAuthClient = this.#constructClient({
|
|
2460
|
-
[optionName]: "
|
|
2563
|
+
[optionName]: "test_51234567890abcdef1234567890abcdef"
|
|
2461
2564
|
});
|
|
2462
2565
|
sections.push(createCodeBlock("typescript", [bearerAuthClient.use]));
|
|
2463
2566
|
sections.push("");
|
|
@@ -2466,7 +2569,7 @@ ${client.use}`;
|
|
|
2466
2569
|
sections.push(`${headingLevel} ${apiKeyHeading}`);
|
|
2467
2570
|
sections.push("");
|
|
2468
2571
|
const apiKeyAuthClient = this.#constructClient({
|
|
2469
|
-
[optionName]: "
|
|
2572
|
+
[optionName]: "test_api_key_1234567890abcdef1234567890abcdef"
|
|
2470
2573
|
});
|
|
2471
2574
|
sections.push(createCodeBlock("typescript", [apiKeyAuthClient.use]));
|
|
2472
2575
|
sections.push("");
|
|
@@ -2475,7 +2578,7 @@ ${client.use}`;
|
|
|
2475
2578
|
sections.push(`${headingLevel} ${queryParamHeading}`);
|
|
2476
2579
|
sections.push("");
|
|
2477
2580
|
const queryParamAuthClient = this.#constructClient({
|
|
2478
|
-
[optionName]: "
|
|
2581
|
+
[optionName]: "test_qp_key_1234567890abcdef1234567890abcdef"
|
|
2479
2582
|
});
|
|
2480
2583
|
sections.push(
|
|
2481
2584
|
createCodeBlock("typescript", [queryParamAuthClient.use])
|
|
@@ -2486,7 +2589,7 @@ ${client.use}`;
|
|
|
2486
2589
|
sections.push(`${headingLevel} ${genericAuthHeading}`);
|
|
2487
2590
|
sections.push("");
|
|
2488
2591
|
const genericAuthClient = this.#constructClient({
|
|
2489
|
-
[optionName]: "
|
|
2592
|
+
[optionName]: "test_auth_token_1234567890abcdef1234567890abcdef"
|
|
2490
2593
|
});
|
|
2491
2594
|
sections.push(createCodeBlock("typescript", [genericAuthClient.use]));
|
|
2492
2595
|
sections.push("");
|
|
@@ -2513,7 +2616,7 @@ ${client.use}`;
|
|
|
2513
2616
|
if (!isEmpty4(authOptions)) {
|
|
2514
2617
|
const [primaryAuth] = authOptions;
|
|
2515
2618
|
const authOptionName = primaryAuth["x-optionName"] ?? primaryAuth.name;
|
|
2516
|
-
initialClientOptions[authOptionName] = "
|
|
2619
|
+
initialClientOptions[authOptionName] = "YOUR_PRODUCTION_TOKEN";
|
|
2517
2620
|
}
|
|
2518
2621
|
const initialClientSetup = this.#constructClient(initialClientOptions);
|
|
2519
2622
|
const configurationUpdateCode = [
|
|
@@ -2527,9 +2630,7 @@ ${client.use}`;
|
|
|
2527
2630
|
if (!isEmpty4(authOptions)) {
|
|
2528
2631
|
const [primaryAuth] = authOptions;
|
|
2529
2632
|
const authOptionName = primaryAuth["x-optionName"] ?? primaryAuth.name;
|
|
2530
|
-
configurationUpdateCode.push(
|
|
2531
|
-
` ${authOptionName}: 'staging_sk_abcdef1234567890'`
|
|
2532
|
-
);
|
|
2633
|
+
configurationUpdateCode.push(` ${authOptionName}: 'YOUR_STAGING_TOKEN'`);
|
|
2533
2634
|
}
|
|
2534
2635
|
configurationUpdateCode.push("});");
|
|
2535
2636
|
sections.push(createCodeBlock("typescript", configurationUpdateCode));
|
|
@@ -2634,7 +2735,7 @@ async function generate(openapi, settings) {
|
|
|
2634
2735
|
makeImport
|
|
2635
2736
|
});
|
|
2636
2737
|
const clientName = pascalcase5((settings.name || "client").trim());
|
|
2637
|
-
const packageName = settings.name ? `@${spinalcase4(settings.name.trim().toLowerCase())}/sdk` : "sdk";
|
|
2738
|
+
const packageName = settings.packageName ?? (settings.name ? `@${spinalcase4(settings.name.trim().toLowerCase())}/sdk` : "sdk");
|
|
2638
2739
|
const inputs = toInputs(groups, commonZod, makeImport);
|
|
2639
2740
|
const models = serializeModels(spec);
|
|
2640
2741
|
await settings.writer(output, {
|
|
@@ -2647,10 +2748,12 @@ async function generate(openapi, settings) {
|
|
|
2647
2748
|
"response.ts": response_default,
|
|
2648
2749
|
"parser.ts": parser_default,
|
|
2649
2750
|
"request.ts": request_default,
|
|
2751
|
+
"sse.ts": sse_default,
|
|
2650
2752
|
"dispatcher.ts": `import z from 'zod';
|
|
2651
2753
|
import { type Interceptor } from '${makeImport("../http/interceptors")}';
|
|
2652
2754
|
import { type RequestConfig } from '${makeImport("../http/request")}';
|
|
2653
2755
|
import { buffered } from '${makeImport("./parse-response")}';
|
|
2756
|
+
import { type SSEListener } from '${makeImport("./sse")}';
|
|
2654
2757
|
import { APIError, APIResponse, type SuccessfulResponse, type RebindSuccessPayload } from '${makeImport("./response")}';
|
|
2655
2758
|
|
|
2656
2759
|
${template2(dispatcher_default, {})()}`,
|
|
@@ -2661,7 +2764,7 @@ ${template2(dispatcher_default, {})()}`,
|
|
|
2661
2764
|
await settings.writer(output, {
|
|
2662
2765
|
"client.ts": client_default({
|
|
2663
2766
|
name: clientName,
|
|
2664
|
-
servers: (spec.servers ?? [])
|
|
2767
|
+
servers: expandServerUrls(spec.servers ?? []),
|
|
2665
2768
|
options: security(spec),
|
|
2666
2769
|
makeImport
|
|
2667
2770
|
}),
|
|
@@ -2821,6 +2924,7 @@ ${utils_default}`
|
|
|
2821
2924
|
output,
|
|
2822
2925
|
env: npmRunPathEnv()
|
|
2823
2926
|
});
|
|
2927
|
+
return { packageName };
|
|
2824
2928
|
}
|
|
2825
2929
|
function serializeModels(spec) {
|
|
2826
2930
|
const filesMap = {};
|
|
@@ -2834,12 +2938,18 @@ function serializeModels(spec) {
|
|
|
2834
2938
|
continue;
|
|
2835
2939
|
}
|
|
2836
2940
|
const folder = isResponseBody ? "outputs" : "models";
|
|
2837
|
-
|
|
2941
|
+
const isSse = schema["x-sse"];
|
|
2942
|
+
let typeContent = isSse ? "SSEListener" : "ReadableStream";
|
|
2838
2943
|
if (!stream) {
|
|
2839
2944
|
const serializer = new TypeScriptEmitter(spec);
|
|
2840
2945
|
typeContent = serializer.handle(schema, true);
|
|
2841
2946
|
}
|
|
2947
|
+
const imports = [];
|
|
2948
|
+
if (isSse) {
|
|
2949
|
+
imports.push(`import type { SSEListener } from '../http/sse.ts';`);
|
|
2950
|
+
}
|
|
2842
2951
|
const fileContent = [
|
|
2952
|
+
...imports,
|
|
2843
2953
|
`
|
|
2844
2954
|
${schema.description ? `
|
|
2845
2955
|
/**
|