zenko 0.1.6-beta.1 → 0.1.7-beta.1
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/LICENSE +21 -0
- package/dist/cli.cjs +437 -195
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +437 -195
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +435 -200
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -2
- package/dist/index.d.ts +46 -2
- package/dist/index.mjs +434 -197
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -6
package/dist/cli.cjs
CHANGED
|
@@ -29,7 +29,7 @@ var path = __toESM(require("path"), 1);
|
|
|
29
29
|
var import_url = require("url");
|
|
30
30
|
var import_js_yaml = require("js-yaml");
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// src/utils/topological-sort.ts
|
|
33
33
|
function topologicalSort(schemas) {
|
|
34
34
|
const visited = /* @__PURE__ */ new Set();
|
|
35
35
|
const visiting = /* @__PURE__ */ new Set();
|
|
@@ -78,7 +78,7 @@ function extractRefName(ref) {
|
|
|
78
78
|
return ref.split("/").pop() || "Unknown";
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
//
|
|
81
|
+
// src/utils/property-name.ts
|
|
82
82
|
function isValidJSIdentifier(name) {
|
|
83
83
|
if (!name) return false;
|
|
84
84
|
const firstChar = name.at(0);
|
|
@@ -158,7 +158,15 @@ function formatPropertyName(name) {
|
|
|
158
158
|
return isValidJSIdentifier(name) ? name : `"${name}"`;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
//
|
|
161
|
+
// src/utils/string-utils.ts
|
|
162
|
+
function toCamelCase(str) {
|
|
163
|
+
return str.replace(/-([a-zA-Z])/g, (_, letter) => letter.toUpperCase()).replace(/-+$/, "");
|
|
164
|
+
}
|
|
165
|
+
function capitalize(str) {
|
|
166
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/utils/http-status.ts
|
|
162
170
|
var statusNameMap = {
|
|
163
171
|
"400": "badRequest",
|
|
164
172
|
"401": "unauthorized",
|
|
@@ -217,14 +225,6 @@ function mapStatusToIdentifier(status) {
|
|
|
217
225
|
if (!candidate) return "unknownError";
|
|
218
226
|
return /^[a-zA-Z_$]/.test(candidate) ? candidate : `status${candidate.charAt(0).toUpperCase()}${candidate.slice(1)}`;
|
|
219
227
|
}
|
|
220
|
-
function getStatusCategory(status) {
|
|
221
|
-
if (status === "default") return "default";
|
|
222
|
-
const code = Number(status);
|
|
223
|
-
if (!Number.isInteger(code)) return "unknown";
|
|
224
|
-
if (code >= 400 && code <= 499) return "client";
|
|
225
|
-
if (code >= 500 && code <= 599) return "server";
|
|
226
|
-
return "unknown";
|
|
227
|
-
}
|
|
228
228
|
function isErrorStatus(status) {
|
|
229
229
|
if (status === "default") return true;
|
|
230
230
|
const code = Number(status);
|
|
@@ -232,7 +232,170 @@ function isErrorStatus(status) {
|
|
|
232
232
|
return code >= 400;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
//
|
|
235
|
+
// src/utils/tree-shaking.ts
|
|
236
|
+
function analyzeZenkoUsage(operations) {
|
|
237
|
+
const usage = {
|
|
238
|
+
usesHeaderFn: false,
|
|
239
|
+
usesOperationDefinition: false,
|
|
240
|
+
usesOperationErrors: false
|
|
241
|
+
};
|
|
242
|
+
if (operations.length > 0) {
|
|
243
|
+
usage.usesOperationDefinition = true;
|
|
244
|
+
}
|
|
245
|
+
for (const op of operations) {
|
|
246
|
+
if (op.requestHeaders && op.requestHeaders.length > 0) {
|
|
247
|
+
usage.usesHeaderFn = true;
|
|
248
|
+
}
|
|
249
|
+
if (op.errors && hasAnyErrors(op.errors)) {
|
|
250
|
+
usage.usesOperationErrors = true;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (operations.length > 0 && !usage.usesOperationErrors) {
|
|
254
|
+
const hasDefaultErrors = operations.some(
|
|
255
|
+
(op) => !op.errors || !hasAnyErrors(op.errors)
|
|
256
|
+
);
|
|
257
|
+
if (hasDefaultErrors) {
|
|
258
|
+
usage.usesOperationErrors = true;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return usage;
|
|
262
|
+
}
|
|
263
|
+
function generateZenkoImport(usage, mode, helpersOutput) {
|
|
264
|
+
const types = [];
|
|
265
|
+
if (usage.usesHeaderFn) types.push("HeaderFn");
|
|
266
|
+
if (usage.usesOperationDefinition) types.push("OperationDefinition");
|
|
267
|
+
if (usage.usesOperationErrors) types.push("OperationErrors");
|
|
268
|
+
if (types.length === 0) {
|
|
269
|
+
return "";
|
|
270
|
+
}
|
|
271
|
+
const importSource = mode === "package" ? '"zenko"' : `"${helpersOutput}"`;
|
|
272
|
+
return `import type { ${types.join(", ")} } from ${importSource};`;
|
|
273
|
+
}
|
|
274
|
+
function hasAnyErrors(errors) {
|
|
275
|
+
return Boolean(errors && Object.keys(errors).length > 0);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/utils/collect-inline-types.ts
|
|
279
|
+
function collectInlineRequestTypes(operations, spec) {
|
|
280
|
+
const requestTypesToGenerate = /* @__PURE__ */ new Map();
|
|
281
|
+
const operationLookup = /* @__PURE__ */ new Map();
|
|
282
|
+
for (const [, pathItem] of Object.entries(spec.paths || {})) {
|
|
283
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
284
|
+
const op = operation;
|
|
285
|
+
if (op.operationId) {
|
|
286
|
+
operationLookup.set(op.operationId, op);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
|
|
291
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
292
|
+
const op = operation;
|
|
293
|
+
if (op.operationId) {
|
|
294
|
+
operationLookup.set(op.operationId, op);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
for (const op of operations) {
|
|
299
|
+
const operation = operationLookup.get(op.operationId);
|
|
300
|
+
if (!operation) continue;
|
|
301
|
+
const requestBody = operation.requestBody;
|
|
302
|
+
if (requestBody && requestBody.content) {
|
|
303
|
+
const content = requestBody.content;
|
|
304
|
+
const jsonContent = content["application/json"];
|
|
305
|
+
if (jsonContent && jsonContent.schema) {
|
|
306
|
+
const schema = jsonContent.schema;
|
|
307
|
+
const typeName = `${capitalize(toCamelCase(op.operationId))}Request`;
|
|
308
|
+
if (!schema.$ref || schema.allOf || schema.oneOf || schema.anyOf) {
|
|
309
|
+
requestTypesToGenerate.set(typeName, schema);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return requestTypesToGenerate;
|
|
315
|
+
}
|
|
316
|
+
function collectInlineResponseTypes(operations, spec) {
|
|
317
|
+
const responseTypesToGenerate = /* @__PURE__ */ new Map();
|
|
318
|
+
const operationLookup = /* @__PURE__ */ new Map();
|
|
319
|
+
for (const [, pathItem] of Object.entries(spec.paths || {})) {
|
|
320
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
321
|
+
const op = operation;
|
|
322
|
+
if (op.operationId) {
|
|
323
|
+
operationLookup.set(op.operationId, op);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
|
|
328
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
329
|
+
const op = operation;
|
|
330
|
+
if (op.operationId) {
|
|
331
|
+
operationLookup.set(op.operationId, op);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
for (const op of operations) {
|
|
336
|
+
const operation = operationLookup.get(op.operationId);
|
|
337
|
+
if (!operation) continue;
|
|
338
|
+
const responses = operation.responses || {};
|
|
339
|
+
for (const [statusCode, response] of Object.entries(responses)) {
|
|
340
|
+
if (/^2\d\d$/.test(statusCode) && response.content) {
|
|
341
|
+
const content = response.content;
|
|
342
|
+
const jsonContent = content["application/json"];
|
|
343
|
+
if (jsonContent && jsonContent.schema) {
|
|
344
|
+
const schema = jsonContent.schema;
|
|
345
|
+
const typeName = `${capitalize(toCamelCase(op.operationId))}Response`;
|
|
346
|
+
if (!schema.$ref || schema.allOf || schema.oneOf || schema.anyOf) {
|
|
347
|
+
responseTypesToGenerate.set(typeName, schema);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return responseTypesToGenerate;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// src/utils/generate-helper-file.ts
|
|
357
|
+
function generateHelperFile() {
|
|
358
|
+
const output = [];
|
|
359
|
+
output.push("// Generated helper types for Zenko");
|
|
360
|
+
output.push(
|
|
361
|
+
"// This file provides type definitions for operation objects and path functions"
|
|
362
|
+
);
|
|
363
|
+
output.push("");
|
|
364
|
+
output.push(
|
|
365
|
+
"export type PathFn<TArgs extends unknown[] = []> = (...args: TArgs) => string"
|
|
366
|
+
);
|
|
367
|
+
output.push("");
|
|
368
|
+
output.push(
|
|
369
|
+
'export type RequestMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"'
|
|
370
|
+
);
|
|
371
|
+
output.push("");
|
|
372
|
+
output.push(
|
|
373
|
+
"export type HeaderFn<TArgs extends unknown[] = [], TResult = Record<string, unknown> | Record<string, never>> = (...args: TArgs) => TResult"
|
|
374
|
+
);
|
|
375
|
+
output.push("");
|
|
376
|
+
output.push(
|
|
377
|
+
"export type AnyHeaderFn = HeaderFn<any, unknown> | (() => unknown)"
|
|
378
|
+
);
|
|
379
|
+
output.push("");
|
|
380
|
+
output.push(
|
|
381
|
+
"export type OperationErrors<TError = unknown> = TError extends Record<string, unknown> ? TError : Record<string, TError>;"
|
|
382
|
+
);
|
|
383
|
+
output.push("");
|
|
384
|
+
output.push(
|
|
385
|
+
"export type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends AnyHeaderFn | undefined = undefined, TErrors extends OperationErrors | undefined = undefined> = {"
|
|
386
|
+
);
|
|
387
|
+
output.push(" method: TMethod");
|
|
388
|
+
output.push(" path: TPath");
|
|
389
|
+
output.push(" request?: TRequest");
|
|
390
|
+
output.push(" response?: TResponse");
|
|
391
|
+
output.push(" headers?: THeaders");
|
|
392
|
+
output.push(" errors?: TErrors");
|
|
393
|
+
output.push("}");
|
|
394
|
+
output.push("");
|
|
395
|
+
return output.join("\n");
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/zenko.ts
|
|
236
399
|
function generateWithMetadata(spec, options = {}) {
|
|
237
400
|
const output = [];
|
|
238
401
|
const generatedTypes = /* @__PURE__ */ new Set();
|
|
@@ -243,7 +406,14 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
243
406
|
strictNumeric
|
|
244
407
|
};
|
|
245
408
|
output.push('import { z } from "zod";');
|
|
246
|
-
|
|
409
|
+
const nameMap = /* @__PURE__ */ new Map();
|
|
410
|
+
if (spec.components?.schemas) {
|
|
411
|
+
for (const name of Object.keys(spec.components.schemas)) {
|
|
412
|
+
nameMap.set(name, toCamelCase(name));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
const operations = parseOperations(spec, nameMap);
|
|
416
|
+
appendHelperTypesImport(output, typesConfig, operations);
|
|
247
417
|
output.push("");
|
|
248
418
|
if (spec.components?.schemas) {
|
|
249
419
|
output.push("// Generated Zod Schemas");
|
|
@@ -251,15 +421,23 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
251
421
|
const sortedSchemas = topologicalSort(spec.components.schemas);
|
|
252
422
|
for (const name of sortedSchemas) {
|
|
253
423
|
const schema = spec.components.schemas[name];
|
|
424
|
+
const sanitizedName = nameMap.get(name);
|
|
254
425
|
output.push(
|
|
255
|
-
generateZodSchema(
|
|
426
|
+
generateZodSchema(
|
|
427
|
+
sanitizedName,
|
|
428
|
+
schema,
|
|
429
|
+
generatedTypes,
|
|
430
|
+
schemaOptions,
|
|
431
|
+
nameMap
|
|
432
|
+
)
|
|
256
433
|
);
|
|
257
434
|
output.push("");
|
|
258
|
-
output.push(
|
|
435
|
+
output.push(
|
|
436
|
+
`export type ${sanitizedName} = z.infer<typeof ${sanitizedName}>;`
|
|
437
|
+
);
|
|
259
438
|
output.push("");
|
|
260
439
|
}
|
|
261
440
|
}
|
|
262
|
-
const operations = parseOperations(spec);
|
|
263
441
|
output.push("// Path Functions");
|
|
264
442
|
output.push("export const paths = {");
|
|
265
443
|
for (const op of operations) {
|
|
@@ -273,24 +451,37 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
273
451
|
);
|
|
274
452
|
continue;
|
|
275
453
|
}
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
454
|
+
const alias = (n) => {
|
|
455
|
+
if (isValidJSIdentifier(n)) return n;
|
|
456
|
+
let aliased = toCamelCase(n);
|
|
457
|
+
if (!isValidJSIdentifier(aliased)) {
|
|
458
|
+
aliased = `_${aliased}`;
|
|
459
|
+
}
|
|
460
|
+
return aliased;
|
|
461
|
+
};
|
|
462
|
+
const destructPieces = [];
|
|
463
|
+
const typePieces = [];
|
|
281
464
|
for (const param of op.pathParams) {
|
|
282
|
-
|
|
465
|
+
destructPieces.push(
|
|
466
|
+
isValidJSIdentifier(param.name) ? param.name : `${formatPropertyName(param.name)}: ${alias(param.name)}`
|
|
467
|
+
);
|
|
468
|
+
typePieces.push(`${formatPropertyName(param.name)}: string`);
|
|
283
469
|
}
|
|
284
470
|
for (const param of op.queryParams) {
|
|
285
|
-
|
|
286
|
-
|
|
471
|
+
destructPieces.push(
|
|
472
|
+
isValidJSIdentifier(param.name) ? param.name : `${formatPropertyName(param.name)}: ${alias(param.name)}`
|
|
473
|
+
);
|
|
474
|
+
typePieces.push(
|
|
475
|
+
`${formatPropertyName(param.name)}${param.required ? "" : "?"}: ${mapQueryType(param)}`
|
|
287
476
|
);
|
|
288
477
|
}
|
|
289
|
-
const signatureParams = signaturePieces.join(", ");
|
|
290
478
|
const needsDefaultObject = !hasPathParams && hasQueryParams && op.queryParams.every((param) => !param.required);
|
|
291
|
-
const signatureArgs =
|
|
292
|
-
const signature = `${signatureArgs}: { ${
|
|
293
|
-
const pathWithParams = op.path.replace(
|
|
479
|
+
const signatureArgs = destructPieces.length ? `{ ${destructPieces.join(", ")} }` : "{}";
|
|
480
|
+
const signature = `${signatureArgs}: { ${typePieces.join(", ")} }${needsDefaultObject ? " = {}" : ""}`;
|
|
481
|
+
const pathWithParams = op.path.replace(
|
|
482
|
+
/{([^}]+)}/g,
|
|
483
|
+
(_m, n) => `\${${alias(n)}}`
|
|
484
|
+
);
|
|
294
485
|
if (!hasQueryParams) {
|
|
295
486
|
output.push(
|
|
296
487
|
` ${formatPropertyName(camelCaseOperationId)}: (${signature}) => \`${pathWithParams}\`,`
|
|
@@ -302,8 +493,7 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
302
493
|
);
|
|
303
494
|
output.push(" const params = new URLSearchParams()");
|
|
304
495
|
for (const param of op.queryParams) {
|
|
305
|
-
const
|
|
306
|
-
const accessor = isValidJSIdentifier(param.name) ? param.name : propertyKey;
|
|
496
|
+
const accessor = isValidJSIdentifier(param.name) ? param.name : alias(toCamelCase(param.name));
|
|
307
497
|
const schema = param.schema ?? {};
|
|
308
498
|
if (schema?.type === "array") {
|
|
309
499
|
const itemValueExpression = convertQueryParamValue(
|
|
@@ -385,10 +575,14 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
385
575
|
}
|
|
386
576
|
output.push("} as const;");
|
|
387
577
|
output.push("");
|
|
578
|
+
generateRequestTypes(output, operations, spec, nameMap, schemaOptions);
|
|
579
|
+
generateResponseTypes(output, operations, spec, nameMap, schemaOptions);
|
|
580
|
+
generateOperationTypes(output, operations, typesConfig);
|
|
388
581
|
output.push("// Operation Objects");
|
|
389
582
|
for (const op of operations) {
|
|
390
583
|
const camelCaseOperationId = toCamelCase(op.operationId);
|
|
391
|
-
|
|
584
|
+
const typeAnnotation = typesConfig.emit ? `: ${capitalize(camelCaseOperationId)}Operation` : "";
|
|
585
|
+
output.push(`export const ${camelCaseOperationId}${typeAnnotation} = {`);
|
|
392
586
|
output.push(` method: "${op.method}",`);
|
|
393
587
|
output.push(` path: paths.${camelCaseOperationId},`);
|
|
394
588
|
appendOperationField(output, "request", op.requestType);
|
|
@@ -396,18 +590,12 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
396
590
|
if (op.requestHeaders && op.requestHeaders.length > 0) {
|
|
397
591
|
output.push(` headers: headers.${camelCaseOperationId},`);
|
|
398
592
|
}
|
|
399
|
-
if (op.errors &&
|
|
400
|
-
output
|
|
401
|
-
appendErrorGroup(output, "clientErrors", op.errors.clientErrors);
|
|
402
|
-
appendErrorGroup(output, "serverErrors", op.errors.serverErrors);
|
|
403
|
-
appendErrorGroup(output, "defaultErrors", op.errors.defaultErrors);
|
|
404
|
-
appendErrorGroup(output, "otherErrors", op.errors.otherErrors);
|
|
405
|
-
output.push(" },");
|
|
593
|
+
if (op.errors && hasAnyErrors2(op.errors)) {
|
|
594
|
+
appendErrorGroup(output, "errors", op.errors);
|
|
406
595
|
}
|
|
407
596
|
output.push("} as const;");
|
|
408
597
|
output.push("");
|
|
409
598
|
}
|
|
410
|
-
generateOperationTypes(output, operations, typesConfig);
|
|
411
599
|
const result = {
|
|
412
600
|
output: output.join("\n")
|
|
413
601
|
};
|
|
@@ -419,6 +607,46 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
419
607
|
}
|
|
420
608
|
return result;
|
|
421
609
|
}
|
|
610
|
+
function generateRequestTypes(output, operations, spec, nameMap, schemaOptions) {
|
|
611
|
+
const requestTypesToGenerate = collectInlineRequestTypes(operations, spec);
|
|
612
|
+
if (requestTypesToGenerate.size > 0) {
|
|
613
|
+
output.push("// Generated Request Types");
|
|
614
|
+
output.push("");
|
|
615
|
+
for (const [typeName, schema] of requestTypesToGenerate) {
|
|
616
|
+
const generatedSchema = generateZodSchema(
|
|
617
|
+
typeName,
|
|
618
|
+
schema,
|
|
619
|
+
/* @__PURE__ */ new Set(),
|
|
620
|
+
schemaOptions,
|
|
621
|
+
nameMap
|
|
622
|
+
);
|
|
623
|
+
output.push(generatedSchema);
|
|
624
|
+
output.push("");
|
|
625
|
+
output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
|
|
626
|
+
output.push("");
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
function generateResponseTypes(output, operations, spec, nameMap, schemaOptions) {
|
|
631
|
+
const responseTypesToGenerate = collectInlineResponseTypes(operations, spec);
|
|
632
|
+
if (responseTypesToGenerate.size > 0) {
|
|
633
|
+
output.push("// Generated Response Types");
|
|
634
|
+
output.push("");
|
|
635
|
+
for (const [typeName, schema] of responseTypesToGenerate) {
|
|
636
|
+
const generatedSchema = generateZodSchema(
|
|
637
|
+
typeName,
|
|
638
|
+
schema,
|
|
639
|
+
/* @__PURE__ */ new Set(),
|
|
640
|
+
schemaOptions,
|
|
641
|
+
nameMap
|
|
642
|
+
);
|
|
643
|
+
output.push(generatedSchema);
|
|
644
|
+
output.push("");
|
|
645
|
+
output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
|
|
646
|
+
output.push("");
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
422
650
|
function appendOperationField(buffer, key, value) {
|
|
423
651
|
if (!value) return;
|
|
424
652
|
buffer.push(` ${key}: ${value},`);
|
|
@@ -431,13 +659,8 @@ function appendErrorGroup(buffer, label, errors) {
|
|
|
431
659
|
}
|
|
432
660
|
buffer.push(" },");
|
|
433
661
|
}
|
|
434
|
-
function
|
|
435
|
-
return
|
|
436
|
-
group.clientErrors,
|
|
437
|
-
group.serverErrors,
|
|
438
|
-
group.defaultErrors,
|
|
439
|
-
group.otherErrors
|
|
440
|
-
].some((bucket) => bucket && Object.keys(bucket).length > 0);
|
|
662
|
+
function hasAnyErrors2(group) {
|
|
663
|
+
return Boolean(group && Object.keys(group).length > 0);
|
|
441
664
|
}
|
|
442
665
|
function isRequestMethod(method) {
|
|
443
666
|
switch (method) {
|
|
@@ -484,33 +707,70 @@ function inferResponseType(contentType, statusCode) {
|
|
|
484
707
|
}
|
|
485
708
|
return "unknown";
|
|
486
709
|
}
|
|
487
|
-
function parseOperations(spec) {
|
|
710
|
+
function parseOperations(spec, nameMap) {
|
|
488
711
|
const operations = [];
|
|
489
|
-
|
|
490
|
-
for (const [
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
712
|
+
if (spec.paths) {
|
|
713
|
+
for (const [path2, pathItem] of Object.entries(spec.paths)) {
|
|
714
|
+
for (const [method, operation] of Object.entries(pathItem)) {
|
|
715
|
+
const normalizedMethod = method.toLowerCase();
|
|
716
|
+
if (!isRequestMethod(normalizedMethod)) continue;
|
|
717
|
+
if (!operation.operationId) continue;
|
|
718
|
+
const pathParams = extractPathParams(path2);
|
|
719
|
+
const requestType = getRequestType(operation);
|
|
720
|
+
const { successResponse, errors } = getResponseTypes(
|
|
721
|
+
operation,
|
|
722
|
+
operation.operationId,
|
|
723
|
+
nameMap
|
|
724
|
+
);
|
|
725
|
+
const resolvedParameters = collectParameters(pathItem, operation, spec);
|
|
726
|
+
const requestHeaders = getRequestHeaders(resolvedParameters);
|
|
727
|
+
const queryParams = getQueryParams(resolvedParameters);
|
|
728
|
+
operations.push({
|
|
729
|
+
operationId: operation.operationId,
|
|
730
|
+
path: path2,
|
|
731
|
+
method: normalizedMethod,
|
|
732
|
+
pathParams,
|
|
733
|
+
queryParams,
|
|
734
|
+
requestType,
|
|
735
|
+
responseType: successResponse,
|
|
736
|
+
requestHeaders,
|
|
737
|
+
errors
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (spec.webhooks) {
|
|
743
|
+
for (const [webhookName, webhookItem] of Object.entries(spec.webhooks)) {
|
|
744
|
+
for (const [method, operation] of Object.entries(webhookItem)) {
|
|
745
|
+
const normalizedMethod = method.toLowerCase();
|
|
746
|
+
if (!isRequestMethod(normalizedMethod)) continue;
|
|
747
|
+
if (!operation.operationId) continue;
|
|
748
|
+
const path2 = webhookName;
|
|
749
|
+
const pathParams = extractPathParams(path2);
|
|
750
|
+
const requestType = getRequestType(operation);
|
|
751
|
+
const { successResponse, errors } = getResponseTypes(
|
|
752
|
+
operation,
|
|
753
|
+
operation.operationId
|
|
754
|
+
);
|
|
755
|
+
const resolvedParameters = collectParameters(
|
|
756
|
+
webhookItem,
|
|
757
|
+
operation,
|
|
758
|
+
spec
|
|
759
|
+
);
|
|
760
|
+
const requestHeaders = getRequestHeaders(resolvedParameters);
|
|
761
|
+
const queryParams = getQueryParams(resolvedParameters);
|
|
762
|
+
operations.push({
|
|
763
|
+
operationId: operation.operationId,
|
|
764
|
+
path: path2,
|
|
765
|
+
method: normalizedMethod,
|
|
766
|
+
pathParams,
|
|
767
|
+
queryParams,
|
|
768
|
+
requestType,
|
|
769
|
+
responseType: successResponse,
|
|
770
|
+
requestHeaders,
|
|
771
|
+
errors
|
|
772
|
+
});
|
|
773
|
+
}
|
|
514
774
|
}
|
|
515
775
|
}
|
|
516
776
|
return operations;
|
|
@@ -519,21 +779,42 @@ function normalizeTypesConfig(config) {
|
|
|
519
779
|
return {
|
|
520
780
|
emit: config?.emit ?? true,
|
|
521
781
|
helpers: config?.helpers ?? "package",
|
|
522
|
-
helpersOutput: config?.helpersOutput ?? "./zenko-types"
|
|
782
|
+
helpersOutput: config?.helpersOutput ?? "./zenko-types",
|
|
783
|
+
treeShake: config?.treeShake ?? true
|
|
523
784
|
};
|
|
524
785
|
}
|
|
525
|
-
function appendHelperTypesImport(buffer, config) {
|
|
786
|
+
function appendHelperTypesImport(buffer, config, operations) {
|
|
526
787
|
if (!config.emit) return;
|
|
527
788
|
switch (config.helpers) {
|
|
528
789
|
case "package":
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
790
|
+
if (config.treeShake) {
|
|
791
|
+
const usage = analyzeZenkoUsage(operations);
|
|
792
|
+
const importStatement = generateZenkoImport(usage, "package");
|
|
793
|
+
if (importStatement) {
|
|
794
|
+
buffer.push(importStatement);
|
|
795
|
+
}
|
|
796
|
+
} else {
|
|
797
|
+
buffer.push(
|
|
798
|
+
'import type { PathFn, HeaderFn, OperationDefinition, OperationErrors } from "zenko";'
|
|
799
|
+
);
|
|
800
|
+
}
|
|
532
801
|
return;
|
|
533
802
|
case "file":
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
803
|
+
if (config.treeShake) {
|
|
804
|
+
const usage = analyzeZenkoUsage(operations);
|
|
805
|
+
const importStatement = generateZenkoImport(
|
|
806
|
+
usage,
|
|
807
|
+
"file",
|
|
808
|
+
config.helpersOutput
|
|
809
|
+
);
|
|
810
|
+
if (importStatement) {
|
|
811
|
+
buffer.push(importStatement);
|
|
812
|
+
}
|
|
813
|
+
} else {
|
|
814
|
+
buffer.push(
|
|
815
|
+
`import type { PathFn, HeaderFn, OperationDefinition, OperationErrors } from "${config.helpersOutput}";`
|
|
816
|
+
);
|
|
817
|
+
}
|
|
537
818
|
return;
|
|
538
819
|
case "inline":
|
|
539
820
|
buffer.push(
|
|
@@ -549,24 +830,19 @@ function appendHelperTypesImport(buffer, config) {
|
|
|
549
830
|
"type AnyHeaderFn = HeaderFn<any, unknown> | (() => unknown);"
|
|
550
831
|
);
|
|
551
832
|
buffer.push(
|
|
552
|
-
"type OperationErrors<
|
|
833
|
+
"type OperationErrors<TError = unknown> = TError extends Record<string, unknown> ? TError : Record<string, TError>;"
|
|
553
834
|
);
|
|
554
|
-
buffer.push(" clientErrors?: TClient;");
|
|
555
|
-
buffer.push(" serverErrors?: TServer;");
|
|
556
|
-
buffer.push(" defaultErrors?: TDefault;");
|
|
557
|
-
buffer.push(" otherErrors?: TOther;");
|
|
558
|
-
buffer.push("};");
|
|
559
835
|
buffer.push(
|
|
560
836
|
"type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends AnyHeaderFn | undefined = undefined, TErrors extends OperationErrors | undefined = undefined> = {"
|
|
561
837
|
);
|
|
562
|
-
buffer.push(" method: TMethod
|
|
563
|
-
buffer.push(" path: TPath
|
|
564
|
-
buffer.push(" request?: TRequest
|
|
565
|
-
buffer.push(" response?: TResponse
|
|
566
|
-
buffer.push(" headers?: THeaders
|
|
567
|
-
buffer.push(" errors?: TErrors
|
|
568
|
-
buffer.push("}
|
|
569
|
-
|
|
838
|
+
buffer.push(" method: TMethod");
|
|
839
|
+
buffer.push(" path: TPath");
|
|
840
|
+
buffer.push(" request?: TRequest");
|
|
841
|
+
buffer.push(" response?: TResponse");
|
|
842
|
+
buffer.push(" headers?: THeaders");
|
|
843
|
+
buffer.push(" errors?: TErrors");
|
|
844
|
+
buffer.push("}");
|
|
845
|
+
buffer.push("");
|
|
570
846
|
}
|
|
571
847
|
}
|
|
572
848
|
function generateOperationTypes(buffer, operations, config) {
|
|
@@ -594,14 +870,11 @@ function generateOperationTypes(buffer, operations, config) {
|
|
|
594
870
|
}
|
|
595
871
|
}
|
|
596
872
|
function buildOperationErrorsType(errors) {
|
|
597
|
-
if (!errors || !
|
|
873
|
+
if (!errors || !hasAnyErrors2(errors)) {
|
|
598
874
|
return "OperationErrors";
|
|
599
875
|
}
|
|
600
|
-
const
|
|
601
|
-
|
|
602
|
-
const fallback = buildErrorBucket(errors.defaultErrors);
|
|
603
|
-
const other = buildErrorBucket(errors.otherErrors);
|
|
604
|
-
return `OperationErrors<${client}, ${server}, ${fallback}, ${other}>`;
|
|
876
|
+
const errorBucket = buildErrorBucket(errors);
|
|
877
|
+
return `OperationErrors<${errorBucket}>`;
|
|
605
878
|
}
|
|
606
879
|
function buildErrorBucket(bucket) {
|
|
607
880
|
if (!bucket || Object.keys(bucket).length === 0) {
|
|
@@ -708,10 +981,10 @@ function getRequestType(operation) {
|
|
|
708
981
|
if (requestBody.$ref) {
|
|
709
982
|
return extractRefName(requestBody.$ref);
|
|
710
983
|
}
|
|
711
|
-
const typeName = `${capitalize(operation.operationId)}Request`;
|
|
984
|
+
const typeName = `${capitalize(toCamelCase(operation.operationId))}Request`;
|
|
712
985
|
return typeName;
|
|
713
986
|
}
|
|
714
|
-
function getResponseTypes(operation, operationId) {
|
|
987
|
+
function getResponseTypes(operation, operationId, nameMap) {
|
|
715
988
|
const responses = operation.responses ?? {};
|
|
716
989
|
const successCodes = /* @__PURE__ */ new Map();
|
|
717
990
|
const errorEntries = [];
|
|
@@ -752,11 +1025,15 @@ function getResponseTypes(operation, operationId) {
|
|
|
752
1025
|
successCodes.set(statusCode, resolvedSchema);
|
|
753
1026
|
}
|
|
754
1027
|
}
|
|
755
|
-
const successResponse = selectSuccessResponse(
|
|
756
|
-
|
|
1028
|
+
const successResponse = selectSuccessResponse(
|
|
1029
|
+
successCodes,
|
|
1030
|
+
operationId,
|
|
1031
|
+
nameMap
|
|
1032
|
+
);
|
|
1033
|
+
const errors = buildErrorGroups(errorEntries, operationId, nameMap);
|
|
757
1034
|
return { successResponse, errors };
|
|
758
1035
|
}
|
|
759
|
-
function selectSuccessResponse(responses, operationId) {
|
|
1036
|
+
function selectSuccessResponse(responses, operationId, nameMap) {
|
|
760
1037
|
if (responses.size === 0) return void 0;
|
|
761
1038
|
const preferredOrder = ["200", "201", "204"];
|
|
762
1039
|
for (const code of preferredOrder) {
|
|
@@ -767,61 +1044,51 @@ function selectSuccessResponse(responses, operationId) {
|
|
|
767
1044
|
}
|
|
768
1045
|
return resolveResponseType(
|
|
769
1046
|
schema,
|
|
770
|
-
`${capitalize(operationId)}Response
|
|
1047
|
+
`${capitalize(toCamelCase(operationId))}Response`,
|
|
1048
|
+
nameMap
|
|
771
1049
|
);
|
|
772
1050
|
}
|
|
773
1051
|
}
|
|
774
|
-
const [
|
|
1052
|
+
const [, firstSchema] = responses.entries().next().value ?? [];
|
|
775
1053
|
if (!firstSchema) return void 0;
|
|
776
1054
|
if (typeof firstSchema === "string") {
|
|
777
1055
|
return firstSchema;
|
|
778
1056
|
}
|
|
779
1057
|
return resolveResponseType(
|
|
780
1058
|
firstSchema,
|
|
781
|
-
`${capitalize(operationId)}Response
|
|
1059
|
+
`${capitalize(toCamelCase(operationId))}Response`,
|
|
1060
|
+
nameMap
|
|
782
1061
|
);
|
|
783
1062
|
}
|
|
784
|
-
function buildErrorGroups(errors = [], operationId) {
|
|
1063
|
+
function buildErrorGroups(errors = [], operationId, nameMap) {
|
|
785
1064
|
if (!errors.length) return void 0;
|
|
786
1065
|
const group = {};
|
|
787
1066
|
for (const { code, schema } of errors) {
|
|
788
|
-
const category = getStatusCategory(code);
|
|
789
1067
|
const identifier = mapStatusToIdentifier(code);
|
|
790
1068
|
const typeName = resolveResponseType(
|
|
791
1069
|
schema,
|
|
792
|
-
`${capitalize(operationId)}${capitalize(identifier)}
|
|
1070
|
+
`${capitalize(toCamelCase(operationId))}${capitalize(identifier)}`,
|
|
1071
|
+
nameMap
|
|
793
1072
|
);
|
|
794
|
-
|
|
795
|
-
case "client":
|
|
796
|
-
group.clientErrors ??= {};
|
|
797
|
-
group.clientErrors[identifier] = typeName;
|
|
798
|
-
break;
|
|
799
|
-
case "server":
|
|
800
|
-
group.serverErrors ??= {};
|
|
801
|
-
group.serverErrors[identifier] = typeName;
|
|
802
|
-
break;
|
|
803
|
-
case "default":
|
|
804
|
-
group.defaultErrors ??= {};
|
|
805
|
-
group.defaultErrors[identifier] = typeName;
|
|
806
|
-
break;
|
|
807
|
-
default:
|
|
808
|
-
group.otherErrors ??= {};
|
|
809
|
-
group.otherErrors[identifier] = typeName;
|
|
810
|
-
break;
|
|
811
|
-
}
|
|
1073
|
+
group[identifier] = typeName;
|
|
812
1074
|
}
|
|
813
1075
|
return group;
|
|
814
1076
|
}
|
|
815
|
-
function resolveResponseType(schema, fallbackName) {
|
|
1077
|
+
function resolveResponseType(schema, fallbackName, nameMap) {
|
|
816
1078
|
if (typeof schema === "string") {
|
|
817
1079
|
return schema;
|
|
818
1080
|
}
|
|
819
1081
|
if (schema.$ref) {
|
|
820
|
-
|
|
1082
|
+
const refName = extractRefName(schema.$ref);
|
|
1083
|
+
return nameMap?.get(refName) || refName;
|
|
821
1084
|
}
|
|
822
1085
|
if (schema.type === "array" && schema.items?.$ref) {
|
|
823
1086
|
const itemRef = extractRefName(schema.items.$ref);
|
|
824
|
-
|
|
1087
|
+
const sanitizedItemRef = nameMap?.get(itemRef) || itemRef;
|
|
1088
|
+
return `z.array(${sanitizedItemRef})`;
|
|
1089
|
+
}
|
|
1090
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
1091
|
+
return fallbackName;
|
|
825
1092
|
}
|
|
826
1093
|
return fallbackName;
|
|
827
1094
|
}
|
|
@@ -904,19 +1171,30 @@ function convertQueryParamValue(schema, accessor) {
|
|
|
904
1171
|
return `String(${accessor})`;
|
|
905
1172
|
}
|
|
906
1173
|
}
|
|
907
|
-
function generateZodSchema(name, schema, generatedTypes, options) {
|
|
1174
|
+
function generateZodSchema(name, schema, generatedTypes, options, nameMap) {
|
|
908
1175
|
if (generatedTypes.has(name)) return "";
|
|
909
1176
|
generatedTypes.add(name);
|
|
910
1177
|
if (schema.enum) {
|
|
911
1178
|
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
912
1179
|
return `export const ${name} = z.enum([${enumValues}]);`;
|
|
913
1180
|
}
|
|
1181
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
1182
|
+
const allOfParts = schema.allOf.map(
|
|
1183
|
+
(part) => getZodTypeFromSchema(part, options, nameMap)
|
|
1184
|
+
);
|
|
1185
|
+
if (allOfParts.length === 0) return `export const ${name} = z.object({});`;
|
|
1186
|
+
if (allOfParts.length === 1)
|
|
1187
|
+
return `export const ${name} = ${allOfParts[0]};`;
|
|
1188
|
+
const first = allOfParts[0];
|
|
1189
|
+
const rest = allOfParts.slice(1).map((part) => `.and(${part})`).join("");
|
|
1190
|
+
return `export const ${name} = ${first}${rest};`;
|
|
1191
|
+
}
|
|
914
1192
|
if (schema.type === "object" || schema.properties) {
|
|
915
|
-
return `export const ${name} = ${buildZodObject(schema, options)};`;
|
|
1193
|
+
return `export const ${name} = ${buildZodObject(schema, options, nameMap)};`;
|
|
916
1194
|
}
|
|
917
1195
|
if (schema.type === "array") {
|
|
918
1196
|
const itemSchema = schema.items ?? { type: "unknown" };
|
|
919
|
-
const itemType = getZodTypeFromSchema(itemSchema, options);
|
|
1197
|
+
const itemType = getZodTypeFromSchema(itemSchema, options, nameMap);
|
|
920
1198
|
const builder = applyStrictArrayBounds(
|
|
921
1199
|
schema,
|
|
922
1200
|
`z.array(${itemType})`,
|
|
@@ -925,18 +1203,29 @@ function generateZodSchema(name, schema, generatedTypes, options) {
|
|
|
925
1203
|
);
|
|
926
1204
|
return `export const ${name} = ${builder};`;
|
|
927
1205
|
}
|
|
928
|
-
return `export const ${name} = ${getZodTypeFromSchema(schema, options)};`;
|
|
1206
|
+
return `export const ${name} = ${getZodTypeFromSchema(schema, options, nameMap)};`;
|
|
929
1207
|
}
|
|
930
|
-
function getZodTypeFromSchema(schema, options) {
|
|
1208
|
+
function getZodTypeFromSchema(schema, options, nameMap) {
|
|
931
1209
|
if (schema.$ref) {
|
|
932
|
-
|
|
1210
|
+
const refName = extractRefName(schema.$ref);
|
|
1211
|
+
return nameMap?.get(refName) || refName;
|
|
933
1212
|
}
|
|
934
1213
|
if (schema.enum) {
|
|
935
1214
|
const enumValues = schema.enum.map((v) => `"${v}"`).join(", ");
|
|
936
1215
|
return `z.enum([${enumValues}])`;
|
|
937
1216
|
}
|
|
938
|
-
if (schema.
|
|
939
|
-
|
|
1217
|
+
if (schema.allOf && Array.isArray(schema.allOf)) {
|
|
1218
|
+
const allOfParts = schema.allOf.map(
|
|
1219
|
+
(part) => getZodTypeFromSchema(part, options, nameMap)
|
|
1220
|
+
);
|
|
1221
|
+
if (allOfParts.length === 0) return "z.object({})";
|
|
1222
|
+
if (allOfParts.length === 1) return allOfParts[0];
|
|
1223
|
+
const first = allOfParts[0];
|
|
1224
|
+
const rest = allOfParts.slice(1).map((part) => `.and(${part})`).join("");
|
|
1225
|
+
return `${first}${rest}`;
|
|
1226
|
+
}
|
|
1227
|
+
if (schema.type === "object" || schema.properties || schema.allOf || schema.oneOf || schema.anyOf) {
|
|
1228
|
+
return buildZodObject(schema, options, nameMap);
|
|
940
1229
|
}
|
|
941
1230
|
switch (schema.type) {
|
|
942
1231
|
case "string":
|
|
@@ -946,7 +1235,8 @@ function getZodTypeFromSchema(schema, options) {
|
|
|
946
1235
|
case "array":
|
|
947
1236
|
return `z.array(${getZodTypeFromSchema(
|
|
948
1237
|
schema.items ?? { type: "unknown" },
|
|
949
|
-
options
|
|
1238
|
+
options,
|
|
1239
|
+
nameMap
|
|
950
1240
|
)})`;
|
|
951
1241
|
case "null":
|
|
952
1242
|
return "z.null()";
|
|
@@ -958,13 +1248,13 @@ function getZodTypeFromSchema(schema, options) {
|
|
|
958
1248
|
return "z.unknown()";
|
|
959
1249
|
}
|
|
960
1250
|
}
|
|
961
|
-
function buildZodObject(schema, options) {
|
|
1251
|
+
function buildZodObject(schema, options, nameMap) {
|
|
962
1252
|
const properties = [];
|
|
963
1253
|
for (const [propName, propSchema] of Object.entries(
|
|
964
1254
|
schema.properties || {}
|
|
965
1255
|
)) {
|
|
966
1256
|
const isRequired = schema.required?.includes(propName) ?? false;
|
|
967
|
-
const zodType = getZodTypeFromSchema(propSchema, options);
|
|
1257
|
+
const zodType = getZodTypeFromSchema(propSchema, options, nameMap);
|
|
968
1258
|
const finalType = isRequired ? zodType : `${zodType}.optional()`;
|
|
969
1259
|
properties.push(` ${formatPropertyName(propName)}: ${finalType},`);
|
|
970
1260
|
}
|
|
@@ -1072,57 +1362,6 @@ function applyNumericBounds(schema, builder) {
|
|
|
1072
1362
|
}
|
|
1073
1363
|
return builder;
|
|
1074
1364
|
}
|
|
1075
|
-
function generateHelperFile() {
|
|
1076
|
-
const output = [];
|
|
1077
|
-
output.push("// Generated helper types for Zenko");
|
|
1078
|
-
output.push(
|
|
1079
|
-
"// This file provides type definitions for operation objects and path functions"
|
|
1080
|
-
);
|
|
1081
|
-
output.push("");
|
|
1082
|
-
output.push(
|
|
1083
|
-
"export type PathFn<TArgs extends unknown[] = []> = (...args: TArgs) => string"
|
|
1084
|
-
);
|
|
1085
|
-
output.push("");
|
|
1086
|
-
output.push(
|
|
1087
|
-
'export type RequestMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"'
|
|
1088
|
-
);
|
|
1089
|
-
output.push("");
|
|
1090
|
-
output.push(
|
|
1091
|
-
"export type HeaderFn<TArgs extends unknown[] = [], TResult = Record<string, unknown> | Record<string, never>> = (...args: TArgs) => TResult"
|
|
1092
|
-
);
|
|
1093
|
-
output.push("");
|
|
1094
|
-
output.push(
|
|
1095
|
-
"export type AnyHeaderFn = HeaderFn<any, unknown> | (() => unknown)"
|
|
1096
|
-
);
|
|
1097
|
-
output.push("");
|
|
1098
|
-
output.push(
|
|
1099
|
-
"export type OperationErrors<TClient = unknown, TServer = unknown, TDefault = unknown, TOther = unknown> = {"
|
|
1100
|
-
);
|
|
1101
|
-
output.push(" clientErrors?: TClient");
|
|
1102
|
-
output.push(" serverErrors?: TServer");
|
|
1103
|
-
output.push(" defaultErrors?: TDefault");
|
|
1104
|
-
output.push(" otherErrors?: TOther");
|
|
1105
|
-
output.push("}");
|
|
1106
|
-
output.push("");
|
|
1107
|
-
output.push(
|
|
1108
|
-
"export type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends AnyHeaderFn | undefined = undefined, TErrors extends OperationErrors | undefined = undefined> = {"
|
|
1109
|
-
);
|
|
1110
|
-
output.push(" method: TMethod");
|
|
1111
|
-
output.push(" path: TPath");
|
|
1112
|
-
output.push(" request?: TRequest");
|
|
1113
|
-
output.push(" response?: TResponse");
|
|
1114
|
-
output.push(" headers?: THeaders");
|
|
1115
|
-
output.push(" errors?: TErrors");
|
|
1116
|
-
output.push("}");
|
|
1117
|
-
output.push("");
|
|
1118
|
-
return output.join("\n");
|
|
1119
|
-
}
|
|
1120
|
-
function toCamelCase(str) {
|
|
1121
|
-
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
1122
|
-
}
|
|
1123
|
-
function capitalize(str) {
|
|
1124
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
1125
|
-
}
|
|
1126
1365
|
|
|
1127
1366
|
// src/cli.ts
|
|
1128
1367
|
async function main() {
|
|
@@ -1289,7 +1528,10 @@ async function generateSingle(options) {
|
|
|
1289
1528
|
fs.mkdirSync(path.dirname(resolvedOutput), { recursive: true });
|
|
1290
1529
|
fs.writeFileSync(resolvedOutput, result.output);
|
|
1291
1530
|
console.log(`\u2705 Generated TypeScript types in ${resolvedOutput}`);
|
|
1292
|
-
console.log(`\u{1F4C4} Processed ${Object.keys(spec.paths).length} paths`);
|
|
1531
|
+
console.log(`\u{1F4C4} Processed ${Object.keys(spec.paths || {}).length} paths`);
|
|
1532
|
+
if (spec.webhooks) {
|
|
1533
|
+
console.log(`\u{1FA9D} Processed ${Object.keys(spec.webhooks).length} webhooks`);
|
|
1534
|
+
}
|
|
1293
1535
|
if (result.helperFile) {
|
|
1294
1536
|
const helperPath = path.isAbsolute(result.helperFile.path) ? result.helperFile.path : path.resolve(path.dirname(resolvedOutput), result.helperFile.path);
|
|
1295
1537
|
const absoluteResolvedOutput = path.resolve(resolvedOutput);
|