@sdk-it/typescript 0.22.1 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15,24 +15,295 @@ import {
15
15
  augmentSpec,
16
16
  cleanFiles,
17
17
  readWriteMetadata,
18
- sanitizeTag as sanitizeTag4
18
+ sanitizeTag as sanitizeTag4,
19
+ securityToOptions as securityToOptions2
19
20
  } from "@sdk-it/spec";
20
21
 
21
22
  // packages/typescript/src/lib/client.ts
22
23
  import { toLitObject } from "@sdk-it/core";
24
+
25
+ // packages/typescript/src/lib/emitters/zod.ts
26
+ import { followRef, isRef, parseRef, pascalcase } from "@sdk-it/core";
27
+ import { isPrimitiveSchema, sanitizeTag } from "@sdk-it/spec";
28
+ var ZodEmitter = class {
29
+ #generatedRefs = /* @__PURE__ */ new Set();
30
+ #spec;
31
+ #onRef;
32
+ constructor(spec, onRef) {
33
+ this.#spec = spec;
34
+ this.#onRef = onRef;
35
+ }
36
+ #object(schema) {
37
+ const properties = schema.properties || {};
38
+ const propEntries = Object.entries(properties).map(([key, propSchema]) => {
39
+ const isRequired = (schema.required ?? []).includes(key);
40
+ return `'${key}': ${this.handle(propSchema, isRequired)}`;
41
+ });
42
+ let additionalProps = "";
43
+ if (schema.additionalProperties) {
44
+ if (typeof schema.additionalProperties === "object") {
45
+ const addPropZod = this.handle(schema.additionalProperties, true);
46
+ additionalProps = `.catchall(${addPropZod})`;
47
+ } else if (schema.additionalProperties === true) {
48
+ additionalProps = `.catchall(z.unknown())`;
49
+ }
50
+ }
51
+ return `z.object({${propEntries.join(", ")}})${additionalProps}`;
52
+ }
53
+ #array(schema, required = false) {
54
+ const { items } = schema;
55
+ if (!items) {
56
+ return `z.array(z.unknown())${appendOptional(required)}`;
57
+ }
58
+ if (Array.isArray(items)) {
59
+ const tupleItems = items.map((sub) => this.handle(sub, true));
60
+ const base = `z.tuple([${tupleItems.join(", ")}])`;
61
+ return `${base}${appendOptional(required)}`;
62
+ }
63
+ const itemsSchema = this.handle(items, true);
64
+ return `z.array(${itemsSchema})${this.#suffixes(JSON.stringify(schema.default), required, false)}`;
65
+ }
66
+ #suffixes = (defaultValue, required, nullable) => {
67
+ return `${nullable ? ".nullable()" : ""}${appendDefault(defaultValue)}${appendOptional(required)}`;
68
+ };
69
+ /**
70
+ * Convert a basic type (string | number | boolean | object | array, etc.) to Zod.
71
+ * We'll also handle .optional() if needed.
72
+ */
73
+ normal(type, schema, required = false, nullable = false) {
74
+ switch (type) {
75
+ case "string":
76
+ return `${this.string(schema)}${this.#suffixes(JSON.stringify(schema.default), required, nullable)}`;
77
+ case "number":
78
+ case "integer": {
79
+ const { base, defaultValue } = this.#number(schema);
80
+ return `${base}${this.#suffixes(defaultValue, required, nullable)}`;
81
+ }
82
+ case "boolean":
83
+ return `z.boolean()${this.#suffixes(schema.default, required, nullable)}`;
84
+ case "object":
85
+ return `${this.#object(schema)}${this.#suffixes(JSON.stringify(schema.default), required, nullable)}`;
86
+ // required always
87
+ case "array":
88
+ return this.#array(schema, required);
89
+ case "null":
90
+ return `z.null()${appendOptional(required)}`;
91
+ default:
92
+ return `z.unknown()${appendOptional(required)}`;
93
+ }
94
+ }
95
+ #ref($ref, required) {
96
+ const schemaName = pascalcase(sanitizeTag(parseRef($ref).model));
97
+ const schema = followRef(this.#spec, $ref);
98
+ if (isPrimitiveSchema(schema)) {
99
+ const result = this.handle(schema, required);
100
+ this.#onRef?.(schemaName, result);
101
+ return result;
102
+ }
103
+ if (this.#generatedRefs.has(schemaName)) {
104
+ return schemaName;
105
+ }
106
+ this.#generatedRefs.add(schemaName);
107
+ this.#onRef?.(schemaName, this.handle(schema, required));
108
+ return schemaName;
109
+ }
110
+ #toIntersection(schemas) {
111
+ const [left, ...right] = schemas;
112
+ if (!right.length) {
113
+ return left;
114
+ }
115
+ return `z.intersection(${left}, ${this.#toIntersection(right)})`;
116
+ }
117
+ allOf(schemas, required) {
118
+ const allOfSchemas = schemas.map((sub) => this.handle(sub, true));
119
+ if (allOfSchemas.length === 0) {
120
+ return `z.unknown()`;
121
+ }
122
+ if (allOfSchemas.length === 1) {
123
+ return `${allOfSchemas[0]}${appendOptional(required)}`;
124
+ }
125
+ return `${this.#toIntersection(allOfSchemas)}${appendOptional(required)}`;
126
+ }
127
+ anyOf(schemas, required) {
128
+ const anyOfSchemas = schemas.map((sub) => this.handle(sub, true));
129
+ if (anyOfSchemas.length === 1) {
130
+ return `${anyOfSchemas[0]}${appendOptional(required)}`;
131
+ }
132
+ return `z.union([${anyOfSchemas.join(", ")}])${appendOptional(required)}`;
133
+ }
134
+ oneOf(schemas, required) {
135
+ const oneOfSchemas = schemas.map((sub) => this.handle(sub, true));
136
+ if (oneOfSchemas.length === 1) {
137
+ return `${oneOfSchemas[0]}${appendOptional(required)}`;
138
+ }
139
+ return `z.union([${oneOfSchemas.join(", ")}])${appendOptional(required)}`;
140
+ }
141
+ enum(type, values) {
142
+ if (values.length === 1) {
143
+ return `z.literal(${values.join(", ")})`;
144
+ }
145
+ if (type === "integer") {
146
+ return `z.union([${values.map((val) => `z.literal(${val})`).join(", ")}])`;
147
+ }
148
+ return `z.enum([${values.join(", ")}])`;
149
+ }
150
+ /**
151
+ * Handle a `string` schema with possible format keywords (JSON Schema).
152
+ */
153
+ string(schema) {
154
+ let base = "z.string()";
155
+ if (schema.contentEncoding === "binary") {
156
+ base = "z.instanceof(Blob)";
157
+ return base;
158
+ }
159
+ switch (schema.format) {
160
+ case "date-time":
161
+ case "datetime":
162
+ base = "z.coerce.date()";
163
+ break;
164
+ case "date":
165
+ base = "z.coerce.date() /* or z.string() if you want raw date strings */";
166
+ break;
167
+ case "time":
168
+ base = "z.string() /* optionally add .regex(...) for HH:MM:SS format */";
169
+ break;
170
+ case "email":
171
+ base = "z.string().email()";
172
+ break;
173
+ case "uuid":
174
+ base = "z.string().uuid()";
175
+ break;
176
+ case "url":
177
+ case "uri":
178
+ base = "z.string().url()";
179
+ break;
180
+ case "ipv4":
181
+ base = 'z.string().ip({version: "v4"})';
182
+ break;
183
+ case "ipv6":
184
+ base = 'z.string().ip({version: "v6"})';
185
+ break;
186
+ case "phone":
187
+ base = "z.string() /* or add .regex(...) for phone formats */";
188
+ break;
189
+ case "byte":
190
+ case "binary":
191
+ base = "z.instanceof(Blob)";
192
+ break;
193
+ case "int64":
194
+ base = "z.string() /* or z.bigint() if your app can handle it */";
195
+ break;
196
+ default:
197
+ break;
198
+ }
199
+ return base;
200
+ }
201
+ /**
202
+ * Handle number/integer constraints from OpenAPI/JSON Schema.
203
+ * In 3.1, exclusiveMinimum/Maximum hold the actual numeric threshold,
204
+ * rather than a boolean toggling `minimum`/`maximum`.
205
+ */
206
+ #number(schema) {
207
+ let defaultValue = schema.default;
208
+ let base = "z.number()";
209
+ if (schema.format === "int64") {
210
+ base = "z.bigint()";
211
+ if (schema.default !== void 0) {
212
+ defaultValue = `BigInt(${schema.default})`;
213
+ }
214
+ }
215
+ if (schema.format === "int32") {
216
+ base += ".int()";
217
+ }
218
+ if (typeof schema.exclusiveMinimum === "number") {
219
+ base += `.gt(${schema.exclusiveMinimum})`;
220
+ }
221
+ if (typeof schema.exclusiveMaximum === "number") {
222
+ base += `.lt(${schema.exclusiveMaximum})`;
223
+ }
224
+ if (typeof schema.minimum === "number") {
225
+ base += schema.format === "int64" ? `.min(BigInt(${schema.minimum}))` : `.min(${schema.minimum})`;
226
+ }
227
+ if (typeof schema.maximum === "number") {
228
+ base += schema.format === "int64" ? `.max(BigInt(${schema.maximum}))` : `.max(${schema.maximum})`;
229
+ }
230
+ if (typeof schema.multipleOf === "number") {
231
+ base += `.refine((val) => Number.isInteger(val / ${schema.multipleOf}), "Must be a multiple of ${schema.multipleOf}")`;
232
+ }
233
+ return { base, defaultValue };
234
+ }
235
+ handle(schema, required) {
236
+ if (isRef(schema)) {
237
+ return `${this.#ref(schema.$ref, true)}${appendOptional(required)}`;
238
+ }
239
+ if (schema.allOf && Array.isArray(schema.allOf)) {
240
+ return this.allOf(schema.allOf ?? [], required);
241
+ }
242
+ if (schema.anyOf && Array.isArray(schema.anyOf)) {
243
+ return this.anyOf(schema.anyOf ?? [], required);
244
+ }
245
+ if (schema.oneOf && Array.isArray(schema.oneOf) && schema.oneOf.length) {
246
+ return this.oneOf(schema.oneOf ?? [], required);
247
+ }
248
+ if (schema.enum && Array.isArray(schema.enum)) {
249
+ const enumVals = schema.enum.map((val) => JSON.stringify(val));
250
+ const defaultValue = enumVals.includes(JSON.stringify(schema.default)) ? JSON.stringify(schema.default) : void 0;
251
+ return `${this.enum(schema.type, enumVals)}${this.#suffixes(defaultValue, required, false)}`;
252
+ }
253
+ const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
254
+ if (!types.length) {
255
+ return `z.unknown()${appendOptional(required)}`;
256
+ }
257
+ if ("nullable" in schema && schema.nullable) {
258
+ types.push("null");
259
+ } else if (schema.default === null) {
260
+ types.push("null");
261
+ }
262
+ if (types.length > 1) {
263
+ const realTypes = types.filter((t) => t !== "null");
264
+ if (realTypes.length === 1 && types.includes("null")) {
265
+ return this.normal(realTypes[0], schema, required, true);
266
+ }
267
+ const subSchemas = types.map((t) => this.normal(t, schema, false));
268
+ return `z.union([${subSchemas.join(", ")}])${appendOptional(required)}`;
269
+ }
270
+ return this.normal(types[0], schema, required, false);
271
+ }
272
+ };
273
+ function appendOptional(isRequired) {
274
+ return isRequired ? "" : ".optional()";
275
+ }
276
+ function appendDefault(defaultValue) {
277
+ return defaultValue !== void 0 || typeof defaultValue !== "undefined" ? `.default(${defaultValue})` : "";
278
+ }
279
+ function toZod(schema, required) {
280
+ const emitter = new ZodEmitter({});
281
+ const schemaStr = emitter.handle(schema, required ?? false);
282
+ if (schema["x-prefix"]) {
283
+ const prefix = schema["x-prefix"];
284
+ if (required === false) {
285
+ return schemaStr + `.transform((val) => (val ? \`${prefix}\${val}\` : undefined))`;
286
+ } else {
287
+ return schemaStr + `.transform((val) => \`${prefix}\${val}\`)`;
288
+ }
289
+ }
290
+ return schemaStr;
291
+ }
292
+
293
+ // packages/typescript/src/lib/client.ts
23
294
  var client_default = (spec, style) => {
24
- const optionsEntries = Object.entries(spec.options).map(
25
- ([key, value]) => [`'${key}'`, value]
26
- );
27
- const defaultHeaders = `{${optionsEntries.filter(([, value]) => value.in === "header").map(
28
- ([key, value]) => `${key}: this.options[${value.optionName ? `'${value.optionName}'` : key}]`
295
+ const defaultHeaders = `{${spec.options.filter((value) => value.in === "header").map(
296
+ (value) => `'${value.name}': this.options['${value["x-optionName"] ?? value.name}']`
29
297
  ).join(",\n")}}`;
30
- const defaultInputs = `{${optionsEntries.filter(([, value]) => value.in === "input").map(
31
- ([key, value]) => `${key}: this.options[${value.optionName ? `'${value.optionName}'` : key}]`
298
+ const defaultInputs = `{${spec.options.filter((value) => value.in === "input").map(
299
+ (value) => `'${value.name}': this.options['${value["x-optionName"] ?? value.name}']`
32
300
  ).join(",\n")}}`;
33
301
  const specOptions = {
34
302
  ...Object.fromEntries(
35
- optionsEntries.map(([key, value]) => [value.optionName ?? key, value])
303
+ spec.options.map((value) => [
304
+ `'${value["x-optionName"] ?? value.name}'`,
305
+ { schema: toZod(value.schema, value.required) }
306
+ ])
36
307
  ),
37
308
  fetch: {
38
309
  schema: "fetchType"
@@ -145,8 +416,8 @@ export class ${spec.name} {
145
416
  };
146
417
 
147
418
  // packages/typescript/src/lib/emitters/interface.ts
148
- import { followRef, isRef, parseRef, pascalcase } from "@sdk-it/core";
149
- import { isPrimitiveSchema, sanitizeTag } from "@sdk-it/spec";
419
+ import { followRef as followRef2, isRef as isRef2, parseRef as parseRef2, pascalcase as pascalcase2 } from "@sdk-it/core";
420
+ import { isPrimitiveSchema as isPrimitiveSchema2, sanitizeTag as sanitizeTag2 } from "@sdk-it/spec";
150
421
  var TypeScriptEmitter = class {
151
422
  #spec;
152
423
  constructor(spec) {
@@ -198,381 +469,160 @@ var TypeScriptEmitter = class {
198
469
  case "integer":
199
470
  return this.number(schema, required);
200
471
  case "boolean":
201
- return appendOptional("boolean", required);
472
+ return appendOptional2("boolean", required);
202
473
  case "object":
203
474
  return this.object(schema, required);
204
475
  case "array":
205
- return this.#array(schema, required);
206
- case "null":
207
- return "null";
208
- default:
209
- console.warn(`Unknown type: ${type}`);
210
- return appendOptional("any", required);
211
- }
212
- }
213
- #ref($ref, required) {
214
- const schemaName = pascalcase(sanitizeTag(parseRef($ref).model));
215
- const schema = followRef(this.#spec, $ref);
216
- if (isPrimitiveSchema(schema)) {
217
- return this.handle(schema, required);
218
- }
219
- return `models.${appendOptional(schemaName, required)}`;
220
- }
221
- allOf(schemas) {
222
- const allOfTypes = schemas.map((sub) => this.handle(sub, true));
223
- return allOfTypes.length > 1 ? `${allOfTypes.join(" & ")}` : allOfTypes[0];
224
- }
225
- oneOf(schemas, required) {
226
- const oneOfTypes = schemas.map((sub) => this.handle(sub, true));
227
- return appendOptional(
228
- oneOfTypes.length > 1 ? `${oneOfTypes.join(" | ")}` : oneOfTypes[0],
229
- required
230
- );
231
- }
232
- anyOf(schemas, required) {
233
- return this.oneOf(schemas, required);
234
- }
235
- enum(values, required) {
236
- const enumValues = values.map((val) => typeof val === "string" ? `'${val}'` : `${val}`).join(" | ");
237
- return appendOptional(enumValues, required);
238
- }
239
- /**
240
- * Handle string type with formats
241
- */
242
- string(schema, required) {
243
- let type;
244
- if (schema.contentEncoding === "binary") {
245
- return appendOptional("Blob", required);
246
- }
247
- switch (schema.format) {
248
- case "date-time":
249
- case "datetime":
250
- case "date":
251
- type = "Date";
252
- break;
253
- case "binary":
254
- case "byte":
255
- type = "Blob";
256
- break;
257
- case "int64":
258
- type = "bigint";
259
- break;
260
- default:
261
- type = "string";
262
- }
263
- return appendOptional(type, required);
264
- }
265
- /**
266
- * Handle number/integer types with formats
267
- */
268
- number(schema, required) {
269
- const type = schema.format === "int64" ? "bigint" : "number";
270
- return appendOptional(type, required);
271
- }
272
- handle(schema, required) {
273
- if (isRef(schema)) {
274
- return this.#ref(schema.$ref, required);
275
- }
276
- if (schema.allOf && Array.isArray(schema.allOf)) {
277
- return this.allOf(schema.allOf);
278
- }
279
- if (schema.anyOf && Array.isArray(schema.anyOf)) {
280
- return this.anyOf(schema.anyOf, required);
281
- }
282
- if (schema.oneOf && Array.isArray(schema.oneOf)) {
283
- return this.oneOf(schema.oneOf, required);
284
- }
285
- if (schema.enum && Array.isArray(schema.enum)) {
286
- return this.enum(schema.enum, required);
287
- }
288
- if (schema.const) {
289
- return this.enum([schema.const], true);
290
- }
291
- const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
292
- if (!types.length) {
293
- if ("properties" in schema) {
294
- return this.object(schema, required);
295
- }
296
- return appendOptional("any", required);
297
- }
298
- if (types.length > 1) {
299
- const realTypes = types.filter((t) => t !== "null");
300
- if (realTypes.length === 1 && types.includes("null")) {
301
- const tsType = this.normal(realTypes[0], schema, false);
302
- return appendOptional(`${tsType} | null`, required);
303
- }
304
- const typeResults = types.map((t) => this.normal(t, schema, false));
305
- return appendOptional(typeResults.join(" | "), required);
306
- }
307
- return this.normal(types[0], schema, required);
308
- }
309
- };
310
- function appendOptional(type, isRequired) {
311
- return isRequired ? type : `${type} | undefined`;
312
- }
313
-
314
- // packages/typescript/src/lib/generator.ts
315
- import { merge, template } from "lodash-es";
316
- import { join } from "node:path";
317
- import { camelcase as camelcase2, spinalcase } from "stringcase";
318
- import { followRef as followRef4, isEmpty as isEmpty2, isRef as isRef4, resolveRef } from "@sdk-it/core";
319
- import { forEachOperation } from "@sdk-it/spec";
320
-
321
- // packages/typescript/src/lib/emitters/zod.ts
322
- import { followRef as followRef2, isRef as isRef2, parseRef as parseRef2, pascalcase as pascalcase2 } from "@sdk-it/core";
323
- import { isPrimitiveSchema as isPrimitiveSchema2, sanitizeTag as sanitizeTag2 } from "@sdk-it/spec";
324
- var ZodEmitter = class {
325
- #generatedRefs = /* @__PURE__ */ new Set();
326
- #spec;
327
- #onRef;
328
- constructor(spec, onRef) {
329
- this.#spec = spec;
330
- this.#onRef = onRef;
331
- }
332
- /**
333
- * Handle objects (properties, additionalProperties).
334
- */
335
- object(schema) {
336
- const properties = schema.properties || {};
337
- const propEntries = Object.entries(properties).map(([key, propSchema]) => {
338
- const isRequired = (schema.required ?? []).includes(key);
339
- return `'${key}': ${this.handle(propSchema, isRequired)}`;
340
- });
341
- let additionalProps = "";
342
- if (schema.additionalProperties) {
343
- if (typeof schema.additionalProperties === "object") {
344
- const addPropZod = this.handle(schema.additionalProperties, true);
345
- additionalProps = `.catchall(${addPropZod})`;
346
- } else if (schema.additionalProperties === true) {
347
- additionalProps = `.catchall(z.unknown())`;
348
- }
349
- }
350
- return `z.object({${propEntries.join(", ")}})${additionalProps}`;
351
- }
352
- #array(schema, required = false) {
353
- const { items } = schema;
354
- if (!items) {
355
- return `z.array(z.unknown())${appendOptional2(required)}`;
356
- }
357
- if (Array.isArray(items)) {
358
- const tupleItems = items.map((sub) => this.handle(sub, true));
359
- const base = `z.tuple([${tupleItems.join(", ")}])`;
360
- return `${base}${appendOptional2(required)}`;
361
- }
362
- const itemsSchema = this.handle(items, true);
363
- return `z.array(${itemsSchema})${this.#suffixes(JSON.stringify(schema.default), required, false)}`;
364
- }
365
- #suffixes = (defaultValue, required, nullable) => {
366
- return `${nullable ? ".nullable()" : ""}${appendDefault(defaultValue)}${appendOptional2(required)}`;
367
- };
368
- /**
369
- * Convert a basic type (string | number | boolean | object | array, etc.) to Zod.
370
- * We'll also handle .optional() if needed.
371
- */
372
- normal(type, schema, required = false, nullable = false) {
373
- switch (type) {
374
- case "string":
375
- return `${this.string(schema)}${this.#suffixes(JSON.stringify(schema.default), required, nullable)}`;
376
- case "number":
377
- case "integer": {
378
- const { base, defaultValue } = this.number(schema);
379
- return `${base}${this.#suffixes(defaultValue, required, nullable)}`;
380
- }
381
- case "boolean":
382
- return `z.boolean()${this.#suffixes(schema.default, required, nullable)}`;
383
- case "object":
384
- return `${this.object(schema)}${this.#suffixes(JSON.stringify(schema.default), required, nullable)}`;
385
- case "array":
386
- return this.#array(schema, required);
387
- case "null":
388
- return `z.null()${appendOptional2(required)}`;
389
- default:
390
- return `z.unknown()${appendOptional2(required)}`;
391
- }
392
- }
393
- #ref($ref, required) {
394
- const schemaName = pascalcase2(sanitizeTag2(parseRef2($ref).model));
395
- const schema = followRef2(this.#spec, $ref);
396
- if (isPrimitiveSchema2(schema)) {
397
- const result = this.handle(schema, required);
398
- this.#onRef?.(schemaName, result);
399
- return result;
400
- }
401
- if (this.#generatedRefs.has(schemaName)) {
402
- return schemaName;
403
- }
404
- this.#generatedRefs.add(schemaName);
405
- this.#onRef?.(schemaName, this.handle(schema, required));
406
- return schemaName;
407
- }
408
- #toIntersection(schemas) {
409
- const [left, ...right] = schemas;
410
- if (!right.length) {
411
- return left;
412
- }
413
- return `z.intersection(${left}, ${this.#toIntersection(right)})`;
414
- }
415
- allOf(schemas, required) {
416
- const allOfSchemas = schemas.map((sub) => this.handle(sub, true));
417
- if (allOfSchemas.length === 0) {
418
- return `z.unknown()`;
419
- }
420
- if (allOfSchemas.length === 1) {
421
- return `${allOfSchemas[0]}${appendOptional2(required)}`;
476
+ return this.#array(schema, required);
477
+ case "null":
478
+ return "null";
479
+ default:
480
+ console.warn(`Unknown type: ${type}`);
481
+ return appendOptional2("any", required);
422
482
  }
423
- return `${this.#toIntersection(allOfSchemas)}${appendOptional2(required)}`;
424
483
  }
425
- anyOf(schemas, required) {
426
- const anyOfSchemas = schemas.map((sub) => this.handle(sub, true));
427
- if (anyOfSchemas.length === 1) {
428
- return `${anyOfSchemas[0]}${appendOptional2(required)}`;
484
+ #ref($ref, required) {
485
+ const schemaName = pascalcase2(sanitizeTag2(parseRef2($ref).model));
486
+ const schema = followRef2(this.#spec, $ref);
487
+ if (isPrimitiveSchema2(schema)) {
488
+ return this.handle(schema, required);
429
489
  }
430
- return `z.union([${anyOfSchemas.join(", ")}])${appendOptional2(required)}`;
490
+ return `models.${appendOptional2(schemaName, required)}`;
491
+ }
492
+ allOf(schemas) {
493
+ const allOfTypes = schemas.map((sub) => this.handle(sub, true));
494
+ return allOfTypes.length > 1 ? `${allOfTypes.join(" & ")}` : allOfTypes[0];
431
495
  }
432
496
  oneOf(schemas, required) {
433
- const oneOfSchemas = schemas.map((sub) => this.handle(sub, true));
434
- if (oneOfSchemas.length === 1) {
435
- return `${oneOfSchemas[0]}${appendOptional2(required)}`;
436
- }
437
- return `z.union([${oneOfSchemas.join(", ")}])${appendOptional2(required)}`;
497
+ const oneOfTypes = schemas.map((sub) => this.handle(sub, true));
498
+ return appendOptional2(
499
+ oneOfTypes.length > 1 ? `${oneOfTypes.join(" | ")}` : oneOfTypes[0],
500
+ required
501
+ );
438
502
  }
439
- enum(type, values) {
440
- if (values.length === 1) {
441
- return `z.literal(${values.join(", ")})`;
442
- }
443
- if (type === "integer") {
444
- return `z.union([${values.map((val) => `z.literal(${val})`).join(", ")}])`;
445
- }
446
- return `z.enum([${values.join(", ")}])`;
503
+ anyOf(schemas, required) {
504
+ return this.oneOf(schemas, required);
505
+ }
506
+ enum(values, required) {
507
+ const enumValues = values.map((val) => typeof val === "string" ? `'${val}'` : `${val}`).join(" | ");
508
+ return appendOptional2(enumValues, required);
447
509
  }
448
510
  /**
449
- * Handle a `string` schema with possible format keywords (JSON Schema).
511
+ * Handle string type with formats
450
512
  */
451
- string(schema) {
452
- let base = "z.string()";
513
+ string(schema, required) {
514
+ let type;
453
515
  if (schema.contentEncoding === "binary") {
454
- base = "z.instanceof(Blob)";
455
- return base;
516
+ return appendOptional2("Blob", required);
456
517
  }
457
518
  switch (schema.format) {
458
519
  case "date-time":
459
520
  case "datetime":
460
- base = "z.coerce.date()";
461
- break;
462
521
  case "date":
463
- base = "z.coerce.date() /* or z.string() if you want raw date strings */";
464
- break;
465
- case "time":
466
- base = "z.string() /* optionally add .regex(...) for HH:MM:SS format */";
467
- break;
468
- case "email":
469
- base = "z.string().email()";
470
- break;
471
- case "uuid":
472
- base = "z.string().uuid()";
473
- break;
474
- case "url":
475
- case "uri":
476
- base = "z.string().url()";
477
- break;
478
- case "ipv4":
479
- base = 'z.string().ip({version: "v4"})';
480
- break;
481
- case "ipv6":
482
- base = 'z.string().ip({version: "v6"})';
483
- break;
484
- case "phone":
485
- base = "z.string() /* or add .regex(...) for phone formats */";
522
+ type = "Date";
486
523
  break;
487
- case "byte":
488
524
  case "binary":
489
- base = "z.instanceof(Blob)";
525
+ case "byte":
526
+ type = "Blob";
490
527
  break;
491
528
  case "int64":
492
- base = "z.string() /* or z.bigint() if your app can handle it */";
529
+ type = "bigint";
493
530
  break;
494
531
  default:
495
- break;
532
+ type = "string";
496
533
  }
497
- return base;
534
+ return appendOptional2(type, required);
498
535
  }
499
536
  /**
500
- * Handle number/integer constraints from OpenAPI/JSON Schema.
501
- * In 3.1, exclusiveMinimum/Maximum hold the actual numeric threshold,
502
- * rather than a boolean toggling `minimum`/`maximum`.
537
+ * Handle number/integer types with formats
503
538
  */
504
- number(schema) {
505
- let defaultValue = schema.default;
506
- let base = "z.number()";
507
- if (schema.format === "int64") {
508
- base = "z.bigint()";
509
- if (schema.default !== void 0) {
510
- defaultValue = `BigInt(${schema.default})`;
511
- }
512
- }
513
- if (schema.format === "int32") {
514
- base += ".int()";
515
- }
516
- if (typeof schema.exclusiveMinimum === "number") {
517
- base += `.gt(${schema.exclusiveMinimum})`;
518
- }
519
- if (typeof schema.exclusiveMaximum === "number") {
520
- base += `.lt(${schema.exclusiveMaximum})`;
521
- }
522
- if (typeof schema.minimum === "number") {
523
- base += schema.format === "int64" ? `.min(BigInt(${schema.minimum}))` : `.min(${schema.minimum})`;
524
- }
525
- if (typeof schema.maximum === "number") {
526
- base += schema.format === "int64" ? `.max(BigInt(${schema.maximum}))` : `.max(${schema.maximum})`;
527
- }
528
- if (typeof schema.multipleOf === "number") {
529
- base += `.refine((val) => Number.isInteger(val / ${schema.multipleOf}), "Must be a multiple of ${schema.multipleOf}")`;
530
- }
531
- return { base, defaultValue };
539
+ number(schema, required) {
540
+ const type = schema.format === "int64" ? "bigint" : "number";
541
+ return appendOptional2(type, required);
532
542
  }
533
543
  handle(schema, required) {
534
544
  if (isRef2(schema)) {
535
- return `${this.#ref(schema.$ref, true)}${appendOptional2(required)}`;
545
+ return this.#ref(schema.$ref, required);
536
546
  }
537
547
  if (schema.allOf && Array.isArray(schema.allOf)) {
538
- return this.allOf(schema.allOf ?? [], required);
548
+ return this.allOf(schema.allOf);
539
549
  }
540
550
  if (schema.anyOf && Array.isArray(schema.anyOf)) {
541
- return this.anyOf(schema.anyOf ?? [], required);
551
+ return this.anyOf(schema.anyOf, required);
542
552
  }
543
- if (schema.oneOf && Array.isArray(schema.oneOf) && schema.oneOf.length) {
544
- return this.oneOf(schema.oneOf ?? [], required);
553
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
554
+ return this.oneOf(schema.oneOf, required);
545
555
  }
546
556
  if (schema.enum && Array.isArray(schema.enum)) {
547
- const enumVals = schema.enum.map((val) => JSON.stringify(val));
548
- const defaultValue = enumVals.includes(JSON.stringify(schema.default)) ? JSON.stringify(schema.default) : void 0;
549
- return `${this.enum(schema.type, enumVals)}${this.#suffixes(defaultValue, required, false)}`;
557
+ return this.enum(schema.enum, required);
558
+ }
559
+ if (schema.const) {
560
+ return this.enum([schema.const], true);
550
561
  }
551
562
  const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
552
563
  if (!types.length) {
553
- return `z.unknown()${appendOptional2(required)}`;
554
- }
555
- if ("nullable" in schema && schema.nullable) {
556
- types.push("null");
557
- } else if (schema.default === null) {
558
- types.push("null");
564
+ if ("properties" in schema) {
565
+ return this.object(schema, required);
566
+ }
567
+ return appendOptional2("any", required);
559
568
  }
560
569
  if (types.length > 1) {
561
570
  const realTypes = types.filter((t) => t !== "null");
562
571
  if (realTypes.length === 1 && types.includes("null")) {
563
- return this.normal(realTypes[0], schema, required, true);
572
+ const tsType = this.normal(realTypes[0], schema, false);
573
+ return appendOptional2(`${tsType} | null`, required);
564
574
  }
565
- const subSchemas = types.map((t) => this.normal(t, schema, false));
566
- return `z.union([${subSchemas.join(", ")}])${appendOptional2(required)}`;
575
+ const typeResults = types.map((t) => this.normal(t, schema, false));
576
+ return appendOptional2(typeResults.join(" | "), required);
567
577
  }
568
- return this.normal(types[0], schema, required, false);
578
+ return this.normal(types[0], schema, required);
569
579
  }
570
580
  };
571
- function appendOptional2(isRequired) {
572
- return isRequired ? "" : ".optional()";
581
+ function appendOptional2(type, isRequired) {
582
+ return isRequired ? type : `${type} | undefined`;
573
583
  }
574
- function appendDefault(defaultValue) {
575
- return defaultValue !== void 0 || typeof defaultValue !== "undefined" ? `.default(${defaultValue})` : "";
584
+
585
+ // packages/typescript/src/lib/generator.ts
586
+ import { merge, template } from "lodash-es";
587
+ import { join } from "node:path";
588
+ import { camelcase as camelcase2, spinalcase } from "stringcase";
589
+ import { followRef as followRef3, isEmpty as isEmpty2, isRef as isRef3, resolveRef } from "@sdk-it/core";
590
+ import { forEachOperation } from "@sdk-it/spec";
591
+
592
+ // packages/typescript/src/lib/import-utilities.ts
593
+ import { removeDuplicates } from "@sdk-it/core";
594
+ function mergeImports(...imports) {
595
+ const merged = {};
596
+ for (const it of imports) {
597
+ merged[it.moduleSpecifier] = merged[it.moduleSpecifier] ?? {
598
+ moduleSpecifier: it.moduleSpecifier,
599
+ defaultImport: it.defaultImport,
600
+ namespaceImport: it.namespaceImport,
601
+ namedImports: []
602
+ };
603
+ for (const named of it.namedImports) {
604
+ if (!merged[it.moduleSpecifier].namedImports.some(
605
+ (x) => x.name === named.name
606
+ )) {
607
+ merged[it.moduleSpecifier].namedImports.push(named);
608
+ }
609
+ }
610
+ }
611
+ return Object.values(merged);
612
+ }
613
+ function importsToString(...imports) {
614
+ return imports.map((it) => {
615
+ if (it.defaultImport) {
616
+ return `import ${it.defaultImport} from '${it.moduleSpecifier}'`;
617
+ }
618
+ if (it.namespaceImport) {
619
+ return `import * as ${it.namespaceImport} from '${it.moduleSpecifier}'`;
620
+ }
621
+ if (it.namedImports) {
622
+ return `import {${removeDuplicates(it.namedImports, (it2) => it2.name).map((n) => `${n.isTypeOnly ? "type" : ""} ${n.name}`).join(", ")}} from '${it.moduleSpecifier}'`;
623
+ }
624
+ throw new Error(`Invalid import ${JSON.stringify(it)}`);
625
+ });
576
626
  }
577
627
 
578
628
  // packages/typescript/src/lib/sdk.ts
@@ -613,75 +663,6 @@ var status_map_default = {
613
663
  "504": "GatewayTimeout"
614
664
  };
615
665
 
616
- // packages/typescript/src/lib/utils.ts
617
- import { followRef as followRef3, isRef as isRef3, removeDuplicates } from "@sdk-it/core";
618
- function securityToOptions(spec, security2, securitySchemes, staticIn) {
619
- securitySchemes ??= {};
620
- const options = {};
621
- for (const it of security2) {
622
- const [name] = Object.keys(it);
623
- if (!name) {
624
- continue;
625
- }
626
- const schema = isRef3(securitySchemes[name]) ? followRef3(spec, securitySchemes[name].$ref) : securitySchemes[name];
627
- if (schema.type === "http") {
628
- options["authorization"] = {
629
- in: staticIn ?? "header",
630
- schema: "z.string().optional().transform((val) => (val ? `Bearer ${val}` : undefined))",
631
- optionName: "token"
632
- };
633
- continue;
634
- }
635
- if (schema.type === "apiKey") {
636
- if (!schema.in) {
637
- throw new Error(`apiKey security schema must have an "in" field`);
638
- }
639
- if (!schema.name) {
640
- throw new Error(`apiKey security schema must have a "name" field`);
641
- }
642
- options[schema.name] = {
643
- in: staticIn ?? schema.in,
644
- schema: "z.string().optional()"
645
- };
646
- continue;
647
- }
648
- }
649
- return options;
650
- }
651
- function mergeImports(...imports) {
652
- const merged = {};
653
- for (const it of imports) {
654
- merged[it.moduleSpecifier] = merged[it.moduleSpecifier] ?? {
655
- moduleSpecifier: it.moduleSpecifier,
656
- defaultImport: it.defaultImport,
657
- namespaceImport: it.namespaceImport,
658
- namedImports: []
659
- };
660
- for (const named of it.namedImports) {
661
- if (!merged[it.moduleSpecifier].namedImports.some(
662
- (x) => x.name === named.name
663
- )) {
664
- merged[it.moduleSpecifier].namedImports.push(named);
665
- }
666
- }
667
- }
668
- return Object.values(merged);
669
- }
670
- function importsToString(...imports) {
671
- return imports.map((it) => {
672
- if (it.defaultImport) {
673
- return `import ${it.defaultImport} from '${it.moduleSpecifier}'`;
674
- }
675
- if (it.namespaceImport) {
676
- return `import * as ${it.namespaceImport} from '${it.moduleSpecifier}'`;
677
- }
678
- if (it.namedImports) {
679
- return `import {${removeDuplicates(it.namedImports, (it2) => it2.name).map((n) => `${n.isTypeOnly ? "type" : ""} ${n.name}`).join(", ")}} from '${it.moduleSpecifier}'`;
680
- }
681
- throw new Error(`Invalid import ${JSON.stringify(it)}`);
682
- });
683
- }
684
-
685
666
  // packages/typescript/src/lib/sdk.ts
686
667
  function toEndpoint(groupName, spec, specOperation, operation, utils) {
687
668
  const schemaName = camelcase(`${operation.name} schema`);
@@ -953,36 +934,6 @@ function generateCode(config) {
953
934
  groups[entry.groupName] ??= [];
954
935
  endpoints[entry.groupName] ??= [];
955
936
  const inputs = {};
956
- const additionalProperties = {};
957
- for (const param of operation.parameters) {
958
- if (!param.schema) {
959
- param.schema = {
960
- type: "string"
961
- };
962
- }
963
- inputs[param.name] = {
964
- in: param.in,
965
- schema: ""
966
- };
967
- additionalProperties[param.name] = param;
968
- }
969
- const securitySchemes = config.spec.components?.securitySchemes ?? {};
970
- const securityOptions = securityToOptions(
971
- config.spec,
972
- operation.security ?? [],
973
- securitySchemes
974
- );
975
- Object.assign(inputs, securityOptions);
976
- Object.entries(securityOptions).forEach(([name, value]) => {
977
- additionalProperties[name] = {
978
- name,
979
- required: false,
980
- schema: {
981
- type: "string"
982
- },
983
- in: value.in
984
- };
985
- });
986
937
  const schemas = {};
987
938
  const shortContenTypeMap = {
988
939
  "application/json": "json",
@@ -1001,11 +952,12 @@ function generateCode(config) {
1001
952
  config.spec,
1002
953
  operation.requestBody.content[type].schema
1003
954
  );
955
+ const xProperties = objectSchema["x-properties"] ?? {};
956
+ const xRequired = objectSchema["x-required"] ?? [];
1004
957
  if (type === "application/empty") {
1005
958
  objectSchema = {
1006
959
  type: "object",
1007
- // properties: objectSchema['x-properties'],
1008
- additionalProperties: isEmpty2(objectSchema["x-properties"])
960
+ additionalProperties: isEmpty2(xProperties)
1009
961
  };
1010
962
  } else {
1011
963
  if (objectSchema.type !== "object") {
@@ -1014,14 +966,29 @@ function generateCode(config) {
1014
966
  required: [operation.requestBody.required ? "$body" : ""],
1015
967
  properties: {
1016
968
  $body: objectSchema
1017
- // ...objectSchema['x-properties'],
1018
969
  }
1019
970
  };
1020
971
  }
1021
972
  }
973
+ const additionalProperties = {};
974
+ for (const [name, prop] of Object.entries(xProperties)) {
975
+ additionalProperties[name] = {
976
+ name,
977
+ required: xRequired?.includes(name),
978
+ schema: prop,
979
+ in: prop["x-in"]
980
+ };
981
+ inputs[name] = {
982
+ in: prop["x-in"],
983
+ schema: ""
984
+ };
985
+ }
1022
986
  const schema = merge({}, objectSchema, {
1023
987
  required: Object.values(additionalProperties).filter((p) => p.required).map((p) => p.name),
1024
- properties: Object.entries(additionalProperties).reduce((acc, [, p]) => ({ ...acc, [p.name]: p.schema }), {})
988
+ properties: Object.entries(additionalProperties).reduce(
989
+ (acc, [, p]) => ({ ...acc, [p.name]: p.schema }),
990
+ {}
991
+ )
1025
992
  });
1026
993
  Object.assign(inputs, bodyInputs(config.spec, objectSchema));
1027
994
  schemas[shortContenTypeMap[type]] = zodDeserialzer.handle(schema, true);
@@ -1123,8 +1090,8 @@ ${endpoint.flatMap((it) => it.schemas).join(",\n")}
1123
1090
  };
1124
1091
  }
1125
1092
  function toProps(spec, schemaOrRef, aggregator = []) {
1126
- if (isRef4(schemaOrRef)) {
1127
- const schema = followRef4(spec, schemaOrRef.$ref);
1093
+ if (isRef3(schemaOrRef)) {
1094
+ const schema = followRef3(spec, schemaOrRef.$ref);
1128
1095
  return toProps(spec, schema, aggregator);
1129
1096
  } else if (schemaOrRef.type === "object") {
1130
1097
  for (const [name] of Object.entries(schemaOrRef.properties ?? {})) {
@@ -1632,11 +1599,11 @@ import { camelcase as camelcase3, spinalcase as spinalcase2 } from "stringcase";
1632
1599
  import { isEmpty as isEmpty3, pascalcase as pascalcase4, resolveRef as resolveRef2 } from "@sdk-it/core";
1633
1600
  import {
1634
1601
  patchParameters,
1635
- securityToOptions as securityToOptions2
1602
+ securityToOptions
1636
1603
  } from "@sdk-it/spec";
1637
1604
 
1638
1605
  // packages/typescript/src/lib/emitters/snippet.ts
1639
- import { followRef as followRef5, isRef as isRef5 } from "@sdk-it/core";
1606
+ import { followRef as followRef4, isRef as isRef4 } from "@sdk-it/core";
1640
1607
  var SnippetEmitter = class {
1641
1608
  spec;
1642
1609
  generatedRefs = /* @__PURE__ */ new Set();
@@ -1645,12 +1612,12 @@ var SnippetEmitter = class {
1645
1612
  this.spec = spec;
1646
1613
  }
1647
1614
  object(schema) {
1648
- const schemaObj = isRef5(schema) ? followRef5(this.spec, schema.$ref) : schema;
1615
+ const schemaObj = isRef4(schema) ? followRef4(this.spec, schema.$ref) : schema;
1649
1616
  const result = {};
1650
1617
  const properties = schemaObj.properties || {};
1651
1618
  for (const [propName, propSchema] of Object.entries(properties)) {
1652
1619
  const isRequired = (schemaObj.required ?? []).includes(propName);
1653
- const resolvedProp = isRef5(propSchema) ? followRef5(this.spec, propSchema.$ref) : propSchema;
1620
+ const resolvedProp = isRef4(propSchema) ? followRef4(this.spec, propSchema.$ref) : propSchema;
1654
1621
  if (isRequired || resolvedProp.example !== void 0 || resolvedProp.default !== void 0 || Math.random() > 0.5) {
1655
1622
  result[propName] = this.handle(propSchema);
1656
1623
  }
@@ -1663,7 +1630,7 @@ var SnippetEmitter = class {
1663
1630
  return result;
1664
1631
  }
1665
1632
  array(schema) {
1666
- const schemaObj = isRef5(schema) ? followRef5(this.spec, schema.$ref) : schema;
1633
+ const schemaObj = isRef4(schema) ? followRef4(this.spec, schema.$ref) : schema;
1667
1634
  const itemsSchema = schemaObj.items;
1668
1635
  if (!itemsSchema) {
1669
1636
  return [];
@@ -1676,10 +1643,8 @@ var SnippetEmitter = class {
1676
1643
  return result;
1677
1644
  }
1678
1645
  string(schema) {
1679
- if (schema.example !== void 0)
1680
- return String(schema.example);
1681
- if (schema.default !== void 0)
1682
- return String(schema.default);
1646
+ if (schema.example !== void 0) return String(schema.example);
1647
+ if (schema.default !== void 0) return String(schema.default);
1683
1648
  switch (schema.format) {
1684
1649
  case "date-time":
1685
1650
  case "datetime":
@@ -1712,10 +1677,8 @@ var SnippetEmitter = class {
1712
1677
  }
1713
1678
  }
1714
1679
  number(schema) {
1715
- if (schema.example !== void 0)
1716
- return Number(schema.example);
1717
- if (schema.default !== void 0)
1718
- return Number(schema.default);
1680
+ if (schema.example !== void 0) return Number(schema.example);
1681
+ if (schema.default !== void 0) return Number(schema.default);
1719
1682
  let value;
1720
1683
  if (typeof schema.exclusiveMinimum === "number") {
1721
1684
  value = schema.exclusiveMinimum + 1;
@@ -1735,10 +1698,8 @@ var SnippetEmitter = class {
1735
1698
  return schema.type === "integer" ? Math.floor(value) : value;
1736
1699
  }
1737
1700
  boolean(schema) {
1738
- if (schema.example !== void 0)
1739
- return Boolean(schema.example);
1740
- if (schema.default !== void 0)
1741
- return Boolean(schema.default);
1701
+ if (schema.example !== void 0) return Boolean(schema.example);
1702
+ if (schema.default !== void 0) return Boolean(schema.default);
1742
1703
  return true;
1743
1704
  }
1744
1705
  null() {
@@ -1751,7 +1712,7 @@ var SnippetEmitter = class {
1751
1712
  return this.cache.get($ref);
1752
1713
  }
1753
1714
  this.cache.set($ref, { _ref: refKey });
1754
- const resolved = followRef5(this.spec, $ref);
1715
+ const resolved = followRef4(this.spec, $ref);
1755
1716
  const result = this.handle(resolved);
1756
1717
  this.cache.set($ref, result);
1757
1718
  return result;
@@ -1767,23 +1728,21 @@ var SnippetEmitter = class {
1767
1728
  }, initial);
1768
1729
  }
1769
1730
  anyOf(schemas) {
1770
- if (schemas.length === 0)
1771
- return {};
1731
+ if (schemas.length === 0) return {};
1772
1732
  return this.handle(schemas[0]);
1773
1733
  }
1774
1734
  oneOf(schemas) {
1775
- if (schemas.length === 0)
1776
- return {};
1735
+ if (schemas.length === 0) return {};
1777
1736
  return this.handle(schemas[0]);
1778
1737
  }
1779
1738
  enum(schema) {
1780
1739
  return Array.isArray(schema.enum) && schema.enum.length > 0 ? schema.enum[0] : void 0;
1781
1740
  }
1782
1741
  handle(schemaOrRef) {
1783
- if (isRef5(schemaOrRef)) {
1742
+ if (isRef4(schemaOrRef)) {
1784
1743
  return this.ref(schemaOrRef.$ref);
1785
1744
  }
1786
- const schema = isRef5(schemaOrRef) ? followRef5(this.spec, schemaOrRef.$ref) : schemaOrRef;
1745
+ const schema = isRef4(schemaOrRef) ? followRef4(this.spec, schemaOrRef.$ref) : schemaOrRef;
1787
1746
  if (schema.example !== void 0) {
1788
1747
  return schema.example;
1789
1748
  }
@@ -1981,7 +1940,7 @@ var TypeScriptGenerator = class {
1981
1940
  return content.join("\n");
1982
1941
  }
1983
1942
  #authentication() {
1984
- return securityToOptions2(
1943
+ return securityToOptions(
1985
1944
  this.#spec,
1986
1945
  this.#spec.security ?? [],
1987
1946
  this.#spec.components?.securitySchemes ?? {}
@@ -1994,7 +1953,9 @@ var TypeScriptGenerator = class {
1994
1953
  const authOptions = this.#authentication();
1995
1954
  if (!isEmpty3(authOptions)) {
1996
1955
  const [firstAuth] = authOptions;
1997
- inputs.push(`${firstAuth.name}: ${firstAuth.example}`);
1956
+ inputs.push(
1957
+ `'${firstAuth["x-optionName"] ?? firstAuth.name}': ${firstAuth.example}`
1958
+ );
1998
1959
  }
1999
1960
  return `import { ${this.#clientName} } from '${this.#packageName}';
2000
1961
 
@@ -2014,7 +1975,7 @@ function security(spec) {
2014
1975
  const components = spec.components || {};
2015
1976
  const securitySchemes = components.securitySchemes || {};
2016
1977
  const paths = Object.values(spec.paths ?? {});
2017
- const options = securityToOptions(spec, security2, securitySchemes);
1978
+ const options = securityToOptions2(spec, security2, securitySchemes);
2018
1979
  for (const it of paths) {
2019
1980
  for (const method of methods) {
2020
1981
  const operation = it[method];
@@ -2023,7 +1984,7 @@ function security(spec) {
2023
1984
  }
2024
1985
  Object.assign(
2025
1986
  options,
2026
- securityToOptions(
1987
+ securityToOptions2(
2027
1988
  spec,
2028
1989
  operation.security || [],
2029
1990
  securitySchemes,
@@ -2036,7 +1997,11 @@ function security(spec) {
2036
1997
  }
2037
1998
  async function generate(openapi, settings) {
2038
1999
  const spec = augmentSpec(
2039
- { spec: openapi, responses: { flattenErrorResponses: true } },
2000
+ {
2001
+ spec: openapi,
2002
+ responses: { flattenErrorResponses: true },
2003
+ pagination: settings.pagination
2004
+ },
2040
2005
  false
2041
2006
  );
2042
2007
  const generator = new TypeScriptGenerator(spec, settings);
@@ -2051,6 +2016,7 @@ async function generate(openapi, settings) {
2051
2016
  );
2052
2017
  const output = settings.mode === "full" ? join2(settings.output, "src") : settings.output;
2053
2018
  settings.useTsExtension ??= true;
2019
+ settings.readme ??= true;
2054
2020
  const { writer, files: writtenFiles } = createWriterProxy(
2055
2021
  settings.writer ?? writeFiles,
2056
2022
  output
@@ -2072,7 +2038,6 @@ async function generate(openapi, settings) {
2072
2038
  style,
2073
2039
  makeImport
2074
2040
  });
2075
- const options = security(spec);
2076
2041
  const clientName = pascalcase5((settings.name || "client").trim());
2077
2042
  const packageName = settings.name ? `@${spinalcase3(settings.name.trim().toLowerCase())}/sdk` : "sdk";
2078
2043
  const inputs = toInputs(groups, commonZod, makeImport);
@@ -2103,7 +2068,7 @@ ${template2(dispatcher_default, {})({ throwError: !style.errorAsValue, outputTyp
2103
2068
  {
2104
2069
  name: clientName,
2105
2070
  servers: (spec.servers ?? []).map((server) => server.url) || [],
2106
- options,
2071
+ options: security(spec),
2107
2072
  makeImport
2108
2073
  },
2109
2074
  style
@@ -2239,12 +2204,9 @@ ${template2(dispatcher_default, {})({ throwError: !style.errorAsValue, outputTyp
2239
2204
  }
2240
2205
  };
2241
2206
  if (settings.readme) {
2242
- configFiles["README.md"] = {
2243
- ignoreIfExists: false,
2244
- content: toReadme(spec, {
2245
- generateSnippet: (...args) => generator.snippet(...args)
2246
- })
2247
- };
2207
+ configFiles["README.md"] = toReadme(spec, {
2208
+ generateSnippet: (...args) => generator.snippet(...args)
2209
+ });
2248
2210
  }
2249
2211
  await settings.writer(settings.output, configFiles);
2250
2212
  }
@@ -2261,6 +2223,9 @@ function serializeModels(spec) {
2261
2223
  const isRequestBody = schema["x-requestbody"];
2262
2224
  const responseGroup = schema["x-response-group"];
2263
2225
  const stream = schema["x-stream"];
2226
+ if (isRequestBody) {
2227
+ continue;
2228
+ }
2264
2229
  const folder = isResponseBody ? "outputs" : "models";
2265
2230
  let typeContent = "ReadableStream";
2266
2231
  if (!stream) {