@sdk-it/typescript 0.42.1 → 0.44.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 +154 -179
- package/dist/index.js.map +4 -4
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/emitters/interface.d.ts +1 -1
- package/dist/lib/emitters/interface.d.ts.map +1 -1
- package/dist/lib/emitters/zod.d.ts.map +1 -1
- package/dist/lib/generate.d.ts.map +1 -1
- package/dist/lib/pagination-emit.d.ts +3 -0
- package/dist/lib/pagination-emit.d.ts.map +1 -0
- package/dist/lib/response-shape.d.ts +22 -0
- package/dist/lib/response-shape.d.ts.map +1 -0
- package/dist/lib/sdk.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { readdir } from "node:fs/promises";
|
|
|
4
4
|
import { join as join2 } from "node:path";
|
|
5
5
|
import { npmRunPathEnv } from "npm-run-path";
|
|
6
6
|
import { camelcase as camelcase6, spinalcase as spinalcase4 } from "stringcase";
|
|
7
|
-
import {
|
|
7
|
+
import { pascalcase as pascalcase5, toLitObject as toLitObject2 } from "@sdk-it/core";
|
|
8
8
|
import {
|
|
9
9
|
createWriterProxy,
|
|
10
10
|
getFolderExports,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
cleanFiles,
|
|
15
15
|
readWriteMetadata,
|
|
16
16
|
sanitizeTag as sanitizeTag4,
|
|
17
|
-
|
|
17
|
+
security,
|
|
18
18
|
toIR
|
|
19
19
|
} from "@sdk-it/spec";
|
|
20
20
|
|
|
@@ -117,7 +117,7 @@ function createTool2(entry, operation) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
// packages/typescript/src/lib/agent/utils.txt
|
|
120
|
-
var utils_default = "function coerceContext(context?: any) {\n if (!context) {\n throw new Error('Context is required');\n }\n return context as {\n client: any\n };\n}\n/**\n * Takes a Zod object schema and makes all optional properties nullable as well.\n * This is useful for APIs where optional fields can be explicitly set to null.\n *\n * @param schema - The Zod object schema to transform\n * @returns A new Zod schema with optional properties made nullable\n */\nfunction makeOptionalPropsNullable<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n) {\n const shape = schema.shape;\n const newShape = {} as Record<string, z.
|
|
120
|
+
var utils_default = "function coerceContext(context?: any) {\n if (!context) {\n throw new Error('Context is required');\n }\n return context as {\n client: any\n };\n}\n/**\n * Takes a Zod object schema and makes all optional properties nullable as well.\n * This is useful for APIs where optional fields can be explicitly set to null.\n *\n * @param schema - The Zod object schema to transform\n * @returns A new Zod schema with optional properties made nullable\n */\nfunction makeOptionalPropsNullable<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n) {\n const shape = schema.shape;\n const newShape = {} as Record<string, z.ZodType>;\n\n for (const [key, value] of Object.entries(shape)) {\n if (value instanceof z.ZodOptional) {\n // Make optional properties also nullable\n newShape[key] = value.unwrap().nullable().optional();\n } else {\n // Keep non-optional properties as they are\n newShape[key] = value;\n }\n }\n\n return z.object(newShape);\n}";
|
|
121
121
|
|
|
122
122
|
// packages/typescript/src/lib/client.ts
|
|
123
123
|
import { toLitObject } from "@sdk-it/core";
|
|
@@ -182,7 +182,7 @@ var ZodEmitter = class {
|
|
|
182
182
|
return `${base}${this.#suffixes(defaultValue, required, nullable)}`;
|
|
183
183
|
}
|
|
184
184
|
case "boolean":
|
|
185
|
-
return `${schema["x-zod-type"] === "coerce-boolean" ? "z.
|
|
185
|
+
return `${schema["x-zod-type"] === "coerce-boolean" ? "z.union([z.boolean(), z.stringbool()])" : "z.boolean()"}${this.#suffixes(schema.default, required, nullable)}`;
|
|
186
186
|
case "object":
|
|
187
187
|
return `${this.#object(schema)}${this.#suffixes(JSON.stringify(schema.default), required, nullable)}`;
|
|
188
188
|
// required always
|
|
@@ -238,16 +238,16 @@ var ZodEmitter = class {
|
|
|
238
238
|
if (oneOfSchemas.length === 1) {
|
|
239
239
|
return `${oneOfSchemas[0]}${appendOptional(required)}`;
|
|
240
240
|
}
|
|
241
|
-
return `z.
|
|
241
|
+
return `z.xor([${oneOfSchemas.join(", ")}])${appendOptional(required)}`;
|
|
242
242
|
}
|
|
243
243
|
enum(type, values) {
|
|
244
244
|
if (values.length === 1) {
|
|
245
245
|
return `z.literal(${values.join(", ")})`;
|
|
246
246
|
}
|
|
247
|
-
if (
|
|
248
|
-
return `z.
|
|
247
|
+
if (values.every((value) => String(value).startsWith('"'))) {
|
|
248
|
+
return `z.enum([${values.join(", ")}])`;
|
|
249
249
|
}
|
|
250
|
-
return `z.
|
|
250
|
+
return `z.literal([${values.join(", ")}])`;
|
|
251
251
|
}
|
|
252
252
|
/**
|
|
253
253
|
* Handle a `string` schema with possible format keywords (JSON Schema).
|
|
@@ -258,6 +258,8 @@ var ZodEmitter = class {
|
|
|
258
258
|
base = "z.custom<Blob>()";
|
|
259
259
|
return base;
|
|
260
260
|
}
|
|
261
|
+
const coerced = schema["x-zod-type"] === "coerce-string";
|
|
262
|
+
const withFormat = (format) => coerced ? `${base}.pipe(${format})` : format;
|
|
261
263
|
switch (schema.format) {
|
|
262
264
|
case "date-time":
|
|
263
265
|
case "datetime":
|
|
@@ -266,30 +268,38 @@ var ZodEmitter = class {
|
|
|
266
268
|
} else if (schema["x-zod-type"] === "date") {
|
|
267
269
|
base = "z.date()";
|
|
268
270
|
} else {
|
|
269
|
-
base
|
|
271
|
+
base = withFormat("z.iso.datetime({ offset: true })");
|
|
270
272
|
}
|
|
271
273
|
break;
|
|
272
274
|
case "date":
|
|
273
|
-
base
|
|
275
|
+
base = withFormat("z.iso.date()");
|
|
274
276
|
break;
|
|
275
277
|
case "time":
|
|
276
|
-
base
|
|
278
|
+
base = withFormat(
|
|
279
|
+
"z.string().regex(/^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d(\\.\\d+)?)?(Z|[+-]([01]\\d|2[0-3]):[0-5]\\d)?$/)"
|
|
280
|
+
);
|
|
277
281
|
break;
|
|
278
282
|
case "email":
|
|
279
|
-
base
|
|
283
|
+
base = withFormat("z.email()");
|
|
280
284
|
break;
|
|
281
285
|
case "uuid":
|
|
282
|
-
base
|
|
286
|
+
base = withFormat("z.guid()");
|
|
283
287
|
break;
|
|
284
288
|
case "url":
|
|
285
289
|
case "uri":
|
|
286
|
-
base
|
|
290
|
+
base = withFormat("z.url()");
|
|
287
291
|
break;
|
|
288
292
|
case "ipv4":
|
|
289
|
-
base
|
|
293
|
+
base = withFormat("z.ipv4()");
|
|
290
294
|
break;
|
|
291
295
|
case "ipv6":
|
|
292
|
-
base
|
|
296
|
+
base = withFormat("z.ipv6()");
|
|
297
|
+
break;
|
|
298
|
+
case "cidrv4":
|
|
299
|
+
base = withFormat("z.cidrv4()");
|
|
300
|
+
break;
|
|
301
|
+
case "cidrv6":
|
|
302
|
+
base = withFormat("z.cidrv6()");
|
|
293
303
|
break;
|
|
294
304
|
case "phone":
|
|
295
305
|
base += " /* or add .regex(...) for phone formats */";
|
|
@@ -298,9 +308,6 @@ var ZodEmitter = class {
|
|
|
298
308
|
case "binary":
|
|
299
309
|
base = "z.custom<Blob>()";
|
|
300
310
|
break;
|
|
301
|
-
case "int64":
|
|
302
|
-
base += " /* or z.bigint() if your app can handle it */";
|
|
303
|
-
break;
|
|
304
311
|
default:
|
|
305
312
|
break;
|
|
306
313
|
}
|
|
@@ -312,17 +319,8 @@ var ZodEmitter = class {
|
|
|
312
319
|
* rather than a boolean toggling `minimum`/`maximum`.
|
|
313
320
|
*/
|
|
314
321
|
#number(schema) {
|
|
315
|
-
let
|
|
316
|
-
|
|
317
|
-
if (schema.format === "int64") {
|
|
318
|
-
base = schema["x-zod-type"] === "coerce-bigint" ? "z.coerce.bigint()" : "z.bigint()";
|
|
319
|
-
if (schema.default !== void 0) {
|
|
320
|
-
defaultValue = `BigInt(${schema.default})`;
|
|
321
|
-
}
|
|
322
|
-
} else {
|
|
323
|
-
base = schema["x-zod-type"] === "coerce-number" ? "z.coerce.number()" : "z.number()";
|
|
324
|
-
}
|
|
325
|
-
if (schema.type === "integer" && schema.format !== "int64") {
|
|
322
|
+
let base = schema["x-zod-type"] === "coerce-number" ? "z.coerce.number()" : "z.number()";
|
|
323
|
+
if (schema.type === "integer") {
|
|
326
324
|
base += ".int()";
|
|
327
325
|
}
|
|
328
326
|
if (typeof schema.exclusiveMinimum === "number") {
|
|
@@ -332,15 +330,15 @@ var ZodEmitter = class {
|
|
|
332
330
|
base += `.lt(${schema.exclusiveMaximum})`;
|
|
333
331
|
}
|
|
334
332
|
if (typeof schema.minimum === "number") {
|
|
335
|
-
base +=
|
|
333
|
+
base += `.min(${schema.minimum})`;
|
|
336
334
|
}
|
|
337
335
|
if (typeof schema.maximum === "number") {
|
|
338
|
-
base +=
|
|
336
|
+
base += `.max(${schema.maximum})`;
|
|
339
337
|
}
|
|
340
338
|
if (typeof schema.multipleOf === "number") {
|
|
341
339
|
base += `.refine((val) => Number.isInteger(val / ${schema.multipleOf}), "Must be a multiple of ${schema.multipleOf}")`;
|
|
342
340
|
}
|
|
343
|
-
return { base, defaultValue };
|
|
341
|
+
return { base, defaultValue: schema.default };
|
|
344
342
|
}
|
|
345
343
|
handle(schema, required) {
|
|
346
344
|
if (isRef(schema)) {
|
|
@@ -402,7 +400,8 @@ function toZod(schema, required) {
|
|
|
402
400
|
|
|
403
401
|
// packages/typescript/src/lib/client.ts
|
|
404
402
|
var client_default = (spec) => {
|
|
405
|
-
const
|
|
403
|
+
const callableString = `z.custom<() => string | Promise<string>>((value) => typeof value === 'function')`;
|
|
404
|
+
const baseUrlSchema = `z.union([z.string(),${callableString},])${spec.servers.length ? ".default(servers[0])" : ""}`;
|
|
406
405
|
const defaultHeaders = `{${spec.options.filter((value) => value.in === "header").map(
|
|
407
406
|
(value) => `'${value.name}': options['${value["x-optionName"] ?? value.name}']`
|
|
408
407
|
).join(",\n")}}`;
|
|
@@ -419,13 +418,15 @@ var client_default = (spec) => {
|
|
|
419
418
|
...globalOptions,
|
|
420
419
|
...globalOptions["'token'"] ? {
|
|
421
420
|
"'token'": {
|
|
422
|
-
schema: `z.union([z.string(),
|
|
423
|
-
.transform(async (token) => {
|
|
421
|
+
schema: `z.union([z.string(),${callableString},]).optional()
|
|
422
|
+
.transform(async (token, ctx) => {
|
|
424
423
|
if (!token) return undefined;
|
|
425
|
-
|
|
426
|
-
|
|
424
|
+
const value = typeof token === 'function' ? await token() : token;
|
|
425
|
+
if (typeof value !== 'string') {
|
|
426
|
+
ctx.addIssue({ code: 'custom', message: 'token must resolve to a string' });
|
|
427
|
+
return z.NEVER;
|
|
427
428
|
}
|
|
428
|
-
return \`Bearer \${
|
|
429
|
+
return \`Bearer \${value}\`;
|
|
429
430
|
}).describe('Bearer token for authentication. Can be a string or a function that returns a string.')`
|
|
430
431
|
}
|
|
431
432
|
} : {},
|
|
@@ -433,15 +434,17 @@ var client_default = (spec) => {
|
|
|
433
434
|
schema: `fetchType.describe('Custom fetch implementation. Defaults to globalThis.fetch.')`
|
|
434
435
|
},
|
|
435
436
|
baseUrl: {
|
|
436
|
-
schema: `${baseUrlSchema}.transform(async (baseUrl) => {
|
|
437
|
-
|
|
438
|
-
|
|
437
|
+
schema: `${baseUrlSchema}.transform(async (baseUrl, ctx) => {
|
|
438
|
+
const value = typeof baseUrl === 'function' ? await baseUrl() : baseUrl;
|
|
439
|
+
if (typeof value !== 'string') {
|
|
440
|
+
ctx.addIssue({ code: 'custom', message: 'baseUrl must resolve to a string' });
|
|
441
|
+
return z.NEVER;
|
|
439
442
|
}
|
|
440
|
-
return
|
|
443
|
+
return value;
|
|
441
444
|
}).describe('Base URL of the API server. Can be a string or a function that returns a string.')`
|
|
442
445
|
},
|
|
443
446
|
headers: {
|
|
444
|
-
schema: `z.record(z.string()).optional().describe('Default headers to include in all requests.')`
|
|
447
|
+
schema: `z.record(z.string(), z.string()).optional().describe('Default headers to include in all requests.')`
|
|
445
448
|
},
|
|
446
449
|
skipValidation: {
|
|
447
450
|
schema: `z.boolean().optional().describe('Skip request input validation. Client options and TypeScript types still enforce correct usage.')`
|
|
@@ -478,7 +481,9 @@ export class ${spec.name} {
|
|
|
478
481
|
input: z.input<(typeof schemas)[E]['schema']>,
|
|
479
482
|
options?: { signal?: AbortSignal; headers?: HeadersInit },
|
|
480
483
|
) {
|
|
481
|
-
return request(this, endpoint, input, options).then(function unwrap(
|
|
484
|
+
return request(this, endpoint, input, options).then(function unwrap(
|
|
485
|
+
it: unknown,
|
|
486
|
+
) {
|
|
482
487
|
if (it instanceof APIResponse) {
|
|
483
488
|
return it.data as InferData<E>;
|
|
484
489
|
}
|
|
@@ -614,7 +619,7 @@ export async function prepare<const E extends keyof typeof schemas>(
|
|
|
614
619
|
};
|
|
615
620
|
|
|
616
621
|
// packages/typescript/src/lib/emitters/interface.ts
|
|
617
|
-
import { followRef as followRef2, isRef as isRef2, parseRef as parseRef2, pascalcase as pascalcase2 } from "@sdk-it/core";
|
|
622
|
+
import { followRef as followRef2, isRef as isRef2, parseRef as parseRef2, pascalcase as pascalcase2, resolveRef } from "@sdk-it/core";
|
|
618
623
|
import { isPrimitiveSchema as isPrimitiveSchema2, sanitizeTag as sanitizeTag2 } from "@sdk-it/spec";
|
|
619
624
|
var TypeScriptEmitter = class {
|
|
620
625
|
#spec;
|
|
@@ -692,7 +697,23 @@ var TypeScriptEmitter = class {
|
|
|
692
697
|
return allOfTypes.length > 1 ? `${allOfTypes.join(" & ")}` : allOfTypes[0];
|
|
693
698
|
}
|
|
694
699
|
oneOf(schemas, required) {
|
|
695
|
-
const
|
|
700
|
+
const isBareString = (s) => {
|
|
701
|
+
const r = resolveRef(this.#spec, s);
|
|
702
|
+
return r.type === "string" && !r.enum && !r.const && !r.format;
|
|
703
|
+
};
|
|
704
|
+
const isStringLiteral = (s) => {
|
|
705
|
+
const r = resolveRef(this.#spec, s);
|
|
706
|
+
return Array.isArray(r.enum) && r.enum.every((v) => typeof v === "string") || typeof r.const === "string";
|
|
707
|
+
};
|
|
708
|
+
const hasStringLiteral = schemas.some(isStringLiteral);
|
|
709
|
+
const seen = /* @__PURE__ */ new Set();
|
|
710
|
+
const oneOfTypes = [];
|
|
711
|
+
for (const sub of schemas) {
|
|
712
|
+
const part = hasStringLiteral && isBareString(sub) ? "(string & {})" : this.handle(sub, true);
|
|
713
|
+
if (seen.has(part)) continue;
|
|
714
|
+
seen.add(part);
|
|
715
|
+
oneOfTypes.push(part);
|
|
716
|
+
}
|
|
696
717
|
return appendOptional2(
|
|
697
718
|
oneOfTypes.length > 1 ? `${oneOfTypes.join(" | ")}` : oneOfTypes[0],
|
|
698
719
|
required
|
|
@@ -723,9 +744,6 @@ var TypeScriptEmitter = class {
|
|
|
723
744
|
case "byte":
|
|
724
745
|
type = "Blob";
|
|
725
746
|
break;
|
|
726
|
-
case "int64":
|
|
727
|
-
type = "bigint";
|
|
728
|
-
break;
|
|
729
747
|
default:
|
|
730
748
|
type = "string";
|
|
731
749
|
}
|
|
@@ -734,9 +752,8 @@ var TypeScriptEmitter = class {
|
|
|
734
752
|
/**
|
|
735
753
|
* Handle number/integer types with formats
|
|
736
754
|
*/
|
|
737
|
-
number(
|
|
738
|
-
|
|
739
|
-
return appendOptional2(type, required);
|
|
755
|
+
number(_schema, required) {
|
|
756
|
+
return appendOptional2("number", required);
|
|
740
757
|
}
|
|
741
758
|
handle(schema, required) {
|
|
742
759
|
if (isRef2(schema)) {
|
|
@@ -784,7 +801,7 @@ function appendOptional2(type, isRequired) {
|
|
|
784
801
|
import { merge, template } from "lodash-es";
|
|
785
802
|
import { join } from "node:path";
|
|
786
803
|
import { camelcase as camelcase4, spinalcase as spinalcase2 } from "stringcase";
|
|
787
|
-
import { followRef as followRef3, isEmpty as isEmpty2, isRef as isRef3, resolveRef, sortArray } from "@sdk-it/core";
|
|
804
|
+
import { followRef as followRef3, isEmpty as isEmpty2, isRef as isRef3, resolveRef as resolveRef2, sortArray } from "@sdk-it/core";
|
|
788
805
|
import {
|
|
789
806
|
forEachOperation as forEachOperation3
|
|
790
807
|
} from "@sdk-it/spec";
|
|
@@ -804,6 +821,69 @@ import {
|
|
|
804
821
|
// packages/typescript/src/lib/import-utilities.ts
|
|
805
822
|
import { removeDuplicates } from "@sdk-it/core";
|
|
806
823
|
|
|
824
|
+
// packages/typescript/src/lib/pagination-emit.ts
|
|
825
|
+
function describe(p) {
|
|
826
|
+
switch (p.type) {
|
|
827
|
+
case "offset":
|
|
828
|
+
return {
|
|
829
|
+
className: "OffsetPagination",
|
|
830
|
+
items: p.items,
|
|
831
|
+
hasMore: p.hasMore,
|
|
832
|
+
statusCode: p.statusCode,
|
|
833
|
+
sameInputNames: p.limitParamName === "limit" && p.offsetParamName === "offset",
|
|
834
|
+
initialOverride: `limit: input.${p.limitParamName}, offset: input.${p.offsetParamName}`,
|
|
835
|
+
nextPageMapping: `${p.offsetParamName}: nextPageParams.offset, ${p.limitParamName}: nextPageParams.limit`
|
|
836
|
+
};
|
|
837
|
+
case "cursor":
|
|
838
|
+
return {
|
|
839
|
+
className: "CursorPagination",
|
|
840
|
+
items: p.items,
|
|
841
|
+
hasMore: p.hasMore,
|
|
842
|
+
statusCode: p.statusCode,
|
|
843
|
+
sameInputNames: p.cursorParamName === "cursor",
|
|
844
|
+
initialOverride: `cursor: input.${p.cursorParamName}`,
|
|
845
|
+
nextPageMapping: `${p.cursorParamName}: nextPageParams.cursor`
|
|
846
|
+
};
|
|
847
|
+
case "page":
|
|
848
|
+
return {
|
|
849
|
+
className: "Pagination",
|
|
850
|
+
items: p.items,
|
|
851
|
+
hasMore: p.hasMore,
|
|
852
|
+
statusCode: p.statusCode,
|
|
853
|
+
sameInputNames: p.pageNumberParamName === "page" && p.pageSizeParamName === "pageSize",
|
|
854
|
+
initialOverride: `page: input.${p.pageNumberParamName}, pageSize: input.${p.pageSizeParamName}`,
|
|
855
|
+
nextPageMapping: `${p.pageNumberParamName}: nextPageParams.page, ${p.pageSizeParamName}: nextPageParams.pageSize`
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
throw new Error(
|
|
859
|
+
`Unknown pagination type: ${p.type}`
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
function paginationOperation(pagination) {
|
|
863
|
+
const shape = describe(pagination);
|
|
864
|
+
const initialParams = shape.sameInputNames ? "input" : `{...input, ${shape.initialOverride}}`;
|
|
865
|
+
const nextPageParams = shape.sameInputNames ? "...nextPageParams" : shape.nextPageMapping;
|
|
866
|
+
return `{
|
|
867
|
+
const pagination = new ${shape.className}(${initialParams}, async (nextPageParams, requestOptions) => {
|
|
868
|
+
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
869
|
+
const result = await dispatcher.send(
|
|
870
|
+
this.toRequest({...input, ${nextPageParams}}),
|
|
871
|
+
this.output,
|
|
872
|
+
requestOptions?.signal ?? options.signal,
|
|
873
|
+
);
|
|
874
|
+
if (result.status !== ${shape.statusCode}) { throw result; }
|
|
875
|
+
return {
|
|
876
|
+
data: result.data.${shape.items},
|
|
877
|
+
meta: {
|
|
878
|
+
hasMore: Boolean(result.data.${shape.hasMore}),
|
|
879
|
+
},
|
|
880
|
+
};
|
|
881
|
+
}, { signal: options.signal });
|
|
882
|
+
await pagination.getNextPage();
|
|
883
|
+
return pagination
|
|
884
|
+
}}`;
|
|
885
|
+
}
|
|
886
|
+
|
|
807
887
|
// packages/typescript/src/lib/status-map.ts
|
|
808
888
|
var status_map_default = {
|
|
809
889
|
"200": "Ok",
|
|
@@ -868,7 +948,7 @@ function toEndpoint(groupName, spec, specOperation, operation) {
|
|
|
868
948
|
signal?: AbortSignal;
|
|
869
949
|
interceptors: Interceptor[];
|
|
870
950
|
fetch: z.infer<typeof fetchType>;
|
|
871
|
-
})${specOperation["x-pagination"] ? paginationOperation(specOperation) : normalOperation()}`
|
|
951
|
+
})${specOperation["x-pagination"] ? paginationOperation(specOperation["x-pagination"]) : normalOperation()}`
|
|
872
952
|
);
|
|
873
953
|
}
|
|
874
954
|
return { schemas };
|
|
@@ -880,92 +960,11 @@ function normalOperation() {
|
|
|
880
960
|
},
|
|
881
961
|
}`;
|
|
882
962
|
}
|
|
883
|
-
function paginationOperation(operation) {
|
|
884
|
-
const pagination = operation["x-pagination"];
|
|
885
|
-
const data = `result.data`;
|
|
886
|
-
const returnValue = `pagination`;
|
|
887
|
-
if (pagination.type === "offset") {
|
|
888
|
-
const sameInputNames = pagination.limitParamName === "limit" && pagination.offsetParamName === "offset";
|
|
889
|
-
const initialParams = sameInputNames ? "input" : `{...input, limit: input.${pagination.limitParamName}, offset: input.${pagination.offsetParamName}}`;
|
|
890
|
-
const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.offsetParamName}: nextPageParams.offset, ${pagination.limitParamName}: nextPageParams.limit`;
|
|
891
|
-
const logic = `const pagination = new OffsetPagination(${initialParams}, async (nextPageParams, requestOptions) => {
|
|
892
|
-
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
893
|
-
const result = await dispatcher.send(
|
|
894
|
-
this.toRequest({...input, ${nextPageParams}}),
|
|
895
|
-
this.output,
|
|
896
|
-
requestOptions?.signal ?? options.signal,
|
|
897
|
-
);
|
|
898
|
-
return {
|
|
899
|
-
data: ${data}.${pagination.items},
|
|
900
|
-
meta: {
|
|
901
|
-
hasMore: Boolean(${data}.${pagination.hasMore}),
|
|
902
|
-
},
|
|
903
|
-
};
|
|
904
|
-
}, { signal: options.signal });
|
|
905
|
-
await pagination.getNextPage();
|
|
906
|
-
return ${returnValue}
|
|
907
|
-
`;
|
|
908
|
-
return `{${logic}}}`;
|
|
909
|
-
}
|
|
910
|
-
if (pagination.type === "cursor") {
|
|
911
|
-
const sameInputNames = pagination.cursorParamName === "cursor";
|
|
912
|
-
const initialParams = sameInputNames ? "input" : `{...input, cursor: input.${pagination.cursorParamName}}`;
|
|
913
|
-
const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.cursorParamName}: nextPageParams.cursor`;
|
|
914
|
-
const logic = `
|
|
915
|
-
const pagination = new CursorPagination(${initialParams}, async (nextPageParams, requestOptions) => {
|
|
916
|
-
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
917
|
-
const result = await dispatcher.send(
|
|
918
|
-
this.toRequest({...input, ${nextPageParams}}),
|
|
919
|
-
this.output,
|
|
920
|
-
requestOptions?.signal ?? options.signal,
|
|
921
|
-
);
|
|
922
|
-
return {
|
|
923
|
-
data: ${data}.${pagination.items},
|
|
924
|
-
meta: {
|
|
925
|
-
hasMore: Boolean(${data}.${pagination.hasMore}),
|
|
926
|
-
},
|
|
927
|
-
};
|
|
928
|
-
}, { signal: options.signal });
|
|
929
|
-
await pagination.getNextPage();
|
|
930
|
-
return ${returnValue}
|
|
931
|
-
`;
|
|
932
|
-
return `{${logic}}}`;
|
|
933
|
-
}
|
|
934
|
-
if (pagination.type === "page") {
|
|
935
|
-
const sameInputNames = pagination.pageNumberParamName === "page" && pagination.pageSizeParamName === "pageSize";
|
|
936
|
-
const initialParams = sameInputNames ? "input" : `{...input, page: input.${pagination.pageNumberParamName}, pageSize: input.${pagination.pageSizeParamName}}`;
|
|
937
|
-
const nextPageParams = sameInputNames ? "...nextPageParams" : `${pagination.pageNumberParamName}: nextPageParams.page, ${pagination.pageSizeParamName}: nextPageParams.pageSize`;
|
|
938
|
-
const logic = `
|
|
939
|
-
const pagination = new Pagination(${initialParams}, async (nextPageParams, requestOptions) => {
|
|
940
|
-
const dispatcher = new Dispatcher(options.interceptors, options.fetch);
|
|
941
|
-
const result = await dispatcher.send(
|
|
942
|
-
this.toRequest({...input, ${nextPageParams}}),
|
|
943
|
-
this.output,
|
|
944
|
-
requestOptions?.signal ?? options.signal,
|
|
945
|
-
);
|
|
946
|
-
return {
|
|
947
|
-
data: ${data}.${pagination.items},
|
|
948
|
-
meta: {
|
|
949
|
-
hasMore: Boolean(${data}.${pagination.hasMore}),
|
|
950
|
-
},
|
|
951
|
-
};
|
|
952
|
-
}, { signal: options.signal });
|
|
953
|
-
await pagination.getNextPage();
|
|
954
|
-
return ${returnValue}
|
|
955
|
-
`;
|
|
956
|
-
return `{${logic}}}`;
|
|
957
|
-
}
|
|
958
|
-
return normalOperation();
|
|
959
|
-
}
|
|
960
963
|
function toHttpOutput(spec, operationName, status, response, withGenerics = true) {
|
|
961
964
|
const typeScriptDeserialzer = new TypeScriptEmitter(spec);
|
|
962
965
|
const interfaceName = pascalcase3(sanitizeTag3(response["x-response-name"]));
|
|
963
966
|
if (!isEmpty(response.content)) {
|
|
964
|
-
const contentTypeResult = fromContentType(
|
|
965
|
-
spec,
|
|
966
|
-
typeScriptDeserialzer,
|
|
967
|
-
response
|
|
968
|
-
);
|
|
967
|
+
const contentTypeResult = fromContentType(typeScriptDeserialzer, response);
|
|
969
968
|
if (!contentTypeResult) {
|
|
970
969
|
throw new Error(
|
|
971
970
|
`No recognizable content type for response ${status} in operation ${operationName}`
|
|
@@ -993,7 +992,7 @@ function toHttpOutput(spec, operationName, status, response, withGenerics = true
|
|
|
993
992
|
}
|
|
994
993
|
return [];
|
|
995
994
|
}
|
|
996
|
-
function fromContentType(
|
|
995
|
+
function fromContentType(typeScriptDeserialzer, response) {
|
|
997
996
|
if ((response.headers ?? {})["Transfer-Encoding"]) {
|
|
998
997
|
return streamedOutput();
|
|
999
998
|
}
|
|
@@ -1011,9 +1010,10 @@ function fromContentType(spec, typeScriptDeserialzer, response) {
|
|
|
1011
1010
|
};
|
|
1012
1011
|
}
|
|
1013
1012
|
if (parseJsonContentType(type)) {
|
|
1013
|
+
const schema = response.content[type].schema;
|
|
1014
1014
|
return {
|
|
1015
1015
|
parser: "buffered",
|
|
1016
|
-
responseSchema:
|
|
1016
|
+
responseSchema: schema ? typeScriptDeserialzer.handle(schema, true) : "void"
|
|
1017
1017
|
};
|
|
1018
1018
|
}
|
|
1019
1019
|
if (isSseContentType(type)) {
|
|
@@ -1077,7 +1077,7 @@ var endpoints_default = "type DispatchReturn<E extends keyof typeof schemas> = A
|
|
|
1077
1077
|
|
|
1078
1078
|
// packages/typescript/src/lib/generator.ts
|
|
1079
1079
|
function coearceRequestInput(spec, operation, type) {
|
|
1080
|
-
let objectSchema =
|
|
1080
|
+
let objectSchema = resolveRef2(
|
|
1081
1081
|
spec,
|
|
1082
1082
|
operation.requestBody.content[type].schema
|
|
1083
1083
|
);
|
|
@@ -1326,25 +1326,25 @@ function operationSchema(ir, operation, type) {
|
|
|
1326
1326
|
}
|
|
1327
1327
|
|
|
1328
1328
|
// packages/typescript/src/lib/http/dispatcher.txt
|
|
1329
|
-
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(
|
|
1329
|
+
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\n// Bare z.custom (no predicate) on purpose: Request/Response from another\n// realm (undici vs global fetch) fail instanceof checks. The output is\n// typed as a Promise directly \u2014 zod 4 deprecated z.promise.\nexport const fetchType = z\n .function({\n input: [z.custom<Request>()],\n output: z.custom<Promise<Response>>(),\n })\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 if (isTypeOf(outputType.type, APIResponse)) {\n if (response.status === outputType.type.status) {\n parser = outputType.parser;\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 Extract<Unionize<T>, SuccessfulResponse<unknown>>;\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 | undefined,\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";
|
|
1330
1330
|
|
|
1331
1331
|
// packages/typescript/src/lib/http/interceptors.txt
|
|
1332
1332
|
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";
|
|
1333
1333
|
|
|
1334
1334
|
// packages/typescript/src/lib/http/parse-response.txt
|
|
1335
|
-
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
|
|
1335
|
+
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 // Statuses that, per the HTTP spec, carry no message body. These responses\n // usually omit Content-Type entirely, so this must run before the guard below.\n if (\n response.status === 204 ||\n response.status === 205 ||\n response.status === 304\n ) {\n return null;\n }\n\n const contentType = response.headers.get("Content-Type");\n if (!contentType) {\n throw new Error("Content-Type header is missing");\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';
|
|
1336
1336
|
|
|
1337
1337
|
// packages/typescript/src/lib/http/parser.txt
|
|
1338
|
-
var parser_default = "import { z } from 'zod';\n\nexport class ParseError<T extends z.ZodType
|
|
1338
|
+
var parser_default = "import { z } from 'zod';\n\nexport class ParseError<T extends z.ZodType> extends Error {\n public data: z.core.$ZodFlattenedError<z.output<T>, z.core.$ZodIssue>;\n constructor(\n data: z.core.$ZodFlattenedError<z.output<T>, z.core.$ZodIssue>,\n ) {\n super('Validation failed');\n this.name = 'ParseError';\n this.data = data;\n }\n}\n\nexport function parseInput<T extends z.ZodType>(\n schema: T,\n input: unknown,\n): z.infer<T> {\n const result = schema.safeParse(input);\n if (!result.success) {\n const error = z.flattenError(result.error, (issue) => issue);\n throw new ParseError<T>(error);\n }\n return result.data as z.infer<T>;\n}\n";
|
|
1339
1339
|
|
|
1340
1340
|
// packages/typescript/src/lib/http/request.txt
|
|
1341
|
-
var request_default = "type Init = Omit<RequestInit, 'headers'> & { headers: Headers };\nexport type RequestConfig = { init: Init; url: URL };\nexport type Method =\n | 'GET'\n | 'POST'\n | 'PUT'\n | 'PATCH'\n | 'DELETE'\n | 'HEAD'\n | 'OPTIONS';\nexport type ContentType =\n | 'xml'\n | 'json'\n | 'urlencoded'\n | 'multipart'\n | 'formdata';\nexport type HeadersInit = [string, string][] | Record<string, string>;\nexport type Endpoint =\n | `${ContentType} ${Method} ${string}`\n | `${Method} ${string}`;\n\nexport type BodyInit =\n | ArrayBuffer\n | Blob\n | FormData\n | URLSearchParams\n | null\n | string;\n\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ntype Input = Record<string, any>;\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n protected input: Input;\n protected props: Props;\n\n constructor(input: Input, props: Props) {\n this.input = input;\n this.props = props;\n }\n\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(path: string): Serialized {\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n const url = new URL(template(path, params), `local://`);\n\n const headers =
|
|
1341
|
+
var request_default = "type Init = Omit<RequestInit, 'headers'> & { headers: Headers };\nexport type RequestConfig = { init: Init; url: URL };\nexport type Method =\n | 'GET'\n | 'POST'\n | 'PUT'\n | 'PATCH'\n | 'DELETE'\n | 'HEAD'\n | 'OPTIONS';\nexport type ContentType =\n | 'xml'\n | 'json'\n | 'urlencoded'\n | 'multipart'\n | 'formdata';\nexport type HeadersInit = [string, string][] | Record<string, string>;\nexport type Endpoint =\n | `${ContentType} ${Method} ${string}`\n | `${Method} ${string}`;\n\nexport type BodyInit =\n | ArrayBuffer\n | Blob\n | FormData\n | URLSearchParams\n | null\n | string;\n\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ntype Input = Record<string, any>;\n\n// Validated inputs can carry Date (coerce-date) values; String(new Date())\n// yields a local-time RFC 2822 string, so serialize Dates as ISO 8601.\nfunction toWireValue(value: any): string {\n return value instanceof Date ? value.toISOString() : String(value);\n}\n\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n protected input: Input;\n protected props: Props;\n\n constructor(input: Input, props: Props) {\n this.input = input;\n this.props = props;\n }\n\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(path: string): Serialized {\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n const url = new URL(template(path, params), `local://`);\n\n const headers: Record<string, string> = { ...this.getHeaders() };\n for (const header of this.props.inputHeaders) {\n const value = this.input[header];\n if (value !== undefined) {\n headers[header] = toWireValue(value);\n }\n }\n\n for (const key of this.props.inputQuery) {\n const value = this.input[key];\n if (value !== undefined) {\n if (Array.isArray(value)) {\n for (const item of value) {\n url.searchParams.append(key, toWireValue(item));\n }\n } else {\n url.searchParams.set(key, toWireValue(value));\n }\n }\n }\n\n return {\n body: this.getBody(),\n url,\n headers,\n };\n }\n}\n\ninterface Serialized {\n body: BodyInit | null;\n headers: Record<string, string>;\n url: URL;\n}\n\nclass JsonSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body: Record<string, any> = {};\n if (\n this.props.inputBody.length === 1 &&\n this.props.inputBody[0] === '$body'\n ) {\n return JSON.stringify(this.input.$body);\n }\n\n for (const prop of this.props.inputBody) {\n body[prop] = this.input[prop];\n }\n return JSON.stringify(body);\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n }\n}\n\nclass UrlencodedSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new URLSearchParams();\n for (const prop of this.props.inputBody) {\n body.set(prop, toWireValue(this.input[prop]));\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n };\n }\n}\n\nclass EmptySerializer extends Serializer {\n getBody(): BodyInit | null {\n return null;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nclass FormDataSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new FormData();\n for (const prop of this.props.inputBody) {\n body.append(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {\n Accept: 'application/json',\n };\n }\n}\n\nexport function json(input: Input, props: Props) {\n return new JsonSerializer(input, props);\n}\nexport function urlencoded(input: Input, props: Props) {\n return new UrlencodedSerializer(input, props);\n}\nexport function empty(input: Input, props: Props) {\n return new EmptySerializer(input, props);\n}\nexport function formdata(input: Input, props: Props) {\n return new FormDataSerializer(input, props);\n}\n\nexport function toRequest<T extends Endpoint>(\n endpoint: T,\n serializer: Serializer,\n): RequestConfig {\n const [method, path] = endpoint.split(' ');\n const input = serializer.serialize(path);\n return {\n url: input.url,\n init: {\n method: method,\n headers: new Headers(input.headers),\n body: method === 'GET' ? undefined : input.body,\n },\n };\n}\n";
|
|
1342
1342
|
|
|
1343
1343
|
// packages/typescript/src/lib/http/response.txt
|
|
1344
|
-
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
|
|
1344
|
+
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(\n status: number,\n headers: Headers,\n data?: unknown,\n ): 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";
|
|
1345
1345
|
|
|
1346
1346
|
// packages/typescript/src/lib/http/sse.txt
|
|
1347
|
-
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';
|
|
1347
|
+
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 (err) {\n console.warn("sse stream error", err);\n }\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';
|
|
1348
1348
|
|
|
1349
1349
|
// packages/typescript/src/lib/paginations/cursor-pagination.txt
|
|
1350
1350
|
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";
|
|
@@ -1768,7 +1768,7 @@ function expandServerUrls(servers) {
|
|
|
1768
1768
|
|
|
1769
1769
|
// packages/typescript/src/lib/typescript-snippet.ts
|
|
1770
1770
|
import { camelcase as camelcase5, spinalcase as spinalcase3 } from "stringcase";
|
|
1771
|
-
import { isEmpty as isEmpty4, pascalcase as pascalcase4, resolveRef as
|
|
1771
|
+
import { isEmpty as isEmpty4, pascalcase as pascalcase4, resolveRef as resolveRef4 } from "@sdk-it/core";
|
|
1772
1772
|
import "@sdk-it/readme";
|
|
1773
1773
|
import {
|
|
1774
1774
|
forEachOperation as forEachOperation5,
|
|
@@ -1777,7 +1777,7 @@ import {
|
|
|
1777
1777
|
} from "@sdk-it/spec";
|
|
1778
1778
|
|
|
1779
1779
|
// packages/typescript/src/lib/emitters/snippet.ts
|
|
1780
|
-
import { followRef as followRef5, isRef as isRef5, resolveRef as
|
|
1780
|
+
import { followRef as followRef5, isRef as isRef5, resolveRef as resolveRef3 } from "@sdk-it/core";
|
|
1781
1781
|
var SnippetEmitter = class {
|
|
1782
1782
|
spec;
|
|
1783
1783
|
generatedRefs = /* @__PURE__ */ new Set();
|
|
@@ -1786,12 +1786,12 @@ var SnippetEmitter = class {
|
|
|
1786
1786
|
this.spec = spec;
|
|
1787
1787
|
}
|
|
1788
1788
|
object(schema) {
|
|
1789
|
-
const schemaObj =
|
|
1789
|
+
const schemaObj = resolveRef3(this.spec, schema);
|
|
1790
1790
|
const result = {};
|
|
1791
1791
|
const properties = schemaObj.properties || {};
|
|
1792
1792
|
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
1793
1793
|
const isRequired = (schemaObj.required ?? []).includes(propName);
|
|
1794
|
-
const resolvedProp =
|
|
1794
|
+
const resolvedProp = resolveRef3(this.spec, propSchema);
|
|
1795
1795
|
if (isRequired || resolvedProp.example !== void 0 || resolvedProp.default !== void 0) {
|
|
1796
1796
|
result[propName] = this.handle(propSchema);
|
|
1797
1797
|
}
|
|
@@ -1804,7 +1804,7 @@ var SnippetEmitter = class {
|
|
|
1804
1804
|
return result;
|
|
1805
1805
|
}
|
|
1806
1806
|
array(schema) {
|
|
1807
|
-
const schemaObj =
|
|
1807
|
+
const schemaObj = resolveRef3(this.spec, schema);
|
|
1808
1808
|
const itemsSchema = schemaObj.items;
|
|
1809
1809
|
if (!itemsSchema) {
|
|
1810
1810
|
return [];
|
|
@@ -1916,7 +1916,7 @@ var SnippetEmitter = class {
|
|
|
1916
1916
|
if (isRef5(schemaOrRef)) {
|
|
1917
1917
|
return this.ref(schemaOrRef.$ref);
|
|
1918
1918
|
}
|
|
1919
|
-
const schema =
|
|
1919
|
+
const schema = resolveRef3(this.spec, schemaOrRef);
|
|
1920
1920
|
if (schema.example !== void 0) {
|
|
1921
1921
|
return schema.example;
|
|
1922
1922
|
}
|
|
@@ -1981,7 +1981,7 @@ var TypeScriptSnippet = class {
|
|
|
1981
1981
|
let payload = "{}";
|
|
1982
1982
|
if (!isEmpty4(operation.requestBody)) {
|
|
1983
1983
|
const contentTypes = Object.keys(operation.requestBody.content || {});
|
|
1984
|
-
const schema =
|
|
1984
|
+
const schema = resolveRef4(
|
|
1985
1985
|
this.#spec,
|
|
1986
1986
|
operation.requestBody.content[contentTypes[0]].schema
|
|
1987
1987
|
);
|
|
@@ -2694,31 +2694,6 @@ function availablePaginationTypes(spec) {
|
|
|
2694
2694
|
}
|
|
2695
2695
|
|
|
2696
2696
|
// packages/typescript/src/lib/generate.ts
|
|
2697
|
-
function security(spec) {
|
|
2698
|
-
const security2 = spec.security || [];
|
|
2699
|
-
const components = spec.components || {};
|
|
2700
|
-
const securitySchemes = components.securitySchemes || {};
|
|
2701
|
-
const paths = Object.values(spec.paths ?? {});
|
|
2702
|
-
const options = securityToOptions2(spec, security2, securitySchemes);
|
|
2703
|
-
for (const it of paths) {
|
|
2704
|
-
for (const method of methods) {
|
|
2705
|
-
const operation = it[method];
|
|
2706
|
-
if (!operation) {
|
|
2707
|
-
continue;
|
|
2708
|
-
}
|
|
2709
|
-
Object.assign(
|
|
2710
|
-
options,
|
|
2711
|
-
securityToOptions2(
|
|
2712
|
-
spec,
|
|
2713
|
-
operation.security || [],
|
|
2714
|
-
securitySchemes,
|
|
2715
|
-
"input"
|
|
2716
|
-
)
|
|
2717
|
-
);
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
return options;
|
|
2721
|
-
}
|
|
2722
2697
|
async function generate(openapi, settings) {
|
|
2723
2698
|
const spec = toIR(
|
|
2724
2699
|
{
|
|
@@ -2901,7 +2876,7 @@ ${utils_default}`
|
|
|
2901
2876
|
},
|
|
2902
2877
|
dependencies: {
|
|
2903
2878
|
"fast-content-type-parse": "^3.0.0",
|
|
2904
|
-
zod: "^3.
|
|
2879
|
+
zod: "^4.3.0"
|
|
2905
2880
|
}
|
|
2906
2881
|
},
|
|
2907
2882
|
null,
|