zenko 0.1.9 → 0.1.10-beta.2
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/README.md +11 -21
- package/dist/cli.cjs +337 -95
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.mjs +337 -95
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +231 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -47
- package/dist/index.d.ts +1 -47
- package/dist/index.mjs +228 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -4
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/utils/topological-sort.ts
|
|
1
|
+
// ../zenko-core/src/utils/topological-sort.ts
|
|
2
2
|
function topologicalSort(schemas) {
|
|
3
3
|
const visited = /* @__PURE__ */ new Set();
|
|
4
4
|
const visiting = /* @__PURE__ */ new Set();
|
|
@@ -47,7 +47,7 @@ function extractRefName(ref) {
|
|
|
47
47
|
return ref.split("/").pop() || "Unknown";
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
// src/utils/property-name.ts
|
|
50
|
+
// ../zenko-core/src/utils/property-name.ts
|
|
51
51
|
function isValidJSIdentifier(name) {
|
|
52
52
|
if (!name) return false;
|
|
53
53
|
const firstChar = name.at(0);
|
|
@@ -127,7 +127,7 @@ function formatPropertyName(name) {
|
|
|
127
127
|
return isValidJSIdentifier(name) ? name : `"${name}"`;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
// src/utils/string-utils.ts
|
|
130
|
+
// ../zenko-core/src/utils/string-utils.ts
|
|
131
131
|
function toCamelCase(str) {
|
|
132
132
|
return str.replace(/-([a-zA-Z])/g, (_, letter) => letter.toUpperCase()).replace(/-+$/, "");
|
|
133
133
|
}
|
|
@@ -135,7 +135,7 @@ function capitalize(str) {
|
|
|
135
135
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
// src/utils/http-status.ts
|
|
138
|
+
// ../zenko-core/src/utils/http-status.ts
|
|
139
139
|
var statusNameMap = {
|
|
140
140
|
"400": "badRequest",
|
|
141
141
|
"401": "unauthorized",
|
|
@@ -201,7 +201,7 @@ function isErrorStatus(status) {
|
|
|
201
201
|
return code >= 400;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
// src/utils/tree-shaking.ts
|
|
204
|
+
// ../zenko-core/src/utils/tree-shaking.ts
|
|
205
205
|
function analyzeZenkoUsage(operations) {
|
|
206
206
|
const usage = {
|
|
207
207
|
usesHeaderFn: false,
|
|
@@ -241,7 +241,7 @@ function hasAnyErrors(errors) {
|
|
|
241
241
|
return Boolean(errors && Object.keys(errors).length > 0);
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
// src/utils/collect-inline-types.ts
|
|
244
|
+
// ../zenko-core/src/utils/collect-inline-types.ts
|
|
245
245
|
function collectInlineRequestTypes(operations, spec) {
|
|
246
246
|
const requestTypesToGenerate = /* @__PURE__ */ new Map();
|
|
247
247
|
const operationLookup = /* @__PURE__ */ new Map();
|
|
@@ -318,8 +318,186 @@ function collectInlineResponseTypes(operations, spec) {
|
|
|
318
318
|
}
|
|
319
319
|
return responseTypesToGenerate;
|
|
320
320
|
}
|
|
321
|
+
function collectInlineErrorTypes(operations, spec) {
|
|
322
|
+
const errorTypesToGenerate = /* @__PURE__ */ new Map();
|
|
323
|
+
const operationLookup = /* @__PURE__ */ new Map();
|
|
324
|
+
for (const [, pathItem] of Object.entries(spec.paths || {})) {
|
|
325
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
326
|
+
const op = operation;
|
|
327
|
+
if (op.operationId) {
|
|
328
|
+
operationLookup.set(op.operationId, op);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
|
|
333
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
334
|
+
const op = operation;
|
|
335
|
+
if (op.operationId) {
|
|
336
|
+
operationLookup.set(op.operationId, op);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
for (const op of operations) {
|
|
341
|
+
const operation = operationLookup.get(op.operationId);
|
|
342
|
+
if (!operation) continue;
|
|
343
|
+
const responses = operation.responses || {};
|
|
344
|
+
for (const [statusCode, response] of Object.entries(responses)) {
|
|
345
|
+
if (isErrorStatus(statusCode) && response.content) {
|
|
346
|
+
const content = response.content;
|
|
347
|
+
const jsonContent = content["application/json"];
|
|
348
|
+
if (jsonContent && jsonContent.schema) {
|
|
349
|
+
const schema = jsonContent.schema;
|
|
350
|
+
const identifier = mapStatusToIdentifier(statusCode);
|
|
351
|
+
const typeName = `${capitalize(toCamelCase(op.operationId))}${capitalize(identifier)}`;
|
|
352
|
+
if (!schema.$ref || schema.allOf || schema.oneOf || schema.anyOf) {
|
|
353
|
+
errorTypesToGenerate.set(typeName, schema);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return errorTypesToGenerate;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ../zenko-core/src/utils/collect-referenced-schemas.ts
|
|
363
|
+
function findContentType(content) {
|
|
364
|
+
const contentTypes = Object.keys(content);
|
|
365
|
+
if (contentTypes.includes("application/json")) {
|
|
366
|
+
return "application/json";
|
|
367
|
+
}
|
|
368
|
+
const CONTENT_TYPE_MAP2 = {
|
|
369
|
+
"application/json": "unknown",
|
|
370
|
+
"text/csv": "string",
|
|
371
|
+
"text/plain": "string",
|
|
372
|
+
"application/octet-stream": "unknown",
|
|
373
|
+
"application/pdf": "unknown"
|
|
374
|
+
};
|
|
375
|
+
for (const contentType of contentTypes) {
|
|
376
|
+
if (contentType in CONTENT_TYPE_MAP2) {
|
|
377
|
+
return contentType;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return contentTypes[0] || "";
|
|
381
|
+
}
|
|
382
|
+
function resolveParameter(parameter, spec) {
|
|
383
|
+
if (!parameter) return void 0;
|
|
384
|
+
if (parameter.$ref) {
|
|
385
|
+
const refName = extractRefName(parameter.$ref);
|
|
386
|
+
const resolved = spec.components?.parameters?.[refName];
|
|
387
|
+
if (!resolved) return void 0;
|
|
388
|
+
const { $ref, ...overrides } = parameter;
|
|
389
|
+
return {
|
|
390
|
+
...resolved,
|
|
391
|
+
...overrides
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
return parameter;
|
|
395
|
+
}
|
|
396
|
+
function collectReferencedSchemas(operations, spec) {
|
|
397
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
398
|
+
const operationLookup = /* @__PURE__ */ new Map();
|
|
399
|
+
for (const [, pathItem] of Object.entries(spec.paths || {})) {
|
|
400
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
401
|
+
const op = operation;
|
|
402
|
+
if (op.operationId) {
|
|
403
|
+
operationLookup.set(op.operationId, op);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
for (const [, pathItem] of Object.entries(spec.webhooks || {})) {
|
|
408
|
+
for (const [, operation] of Object.entries(pathItem)) {
|
|
409
|
+
const op = operation;
|
|
410
|
+
if (op.operationId) {
|
|
411
|
+
operationLookup.set(op.operationId, op);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
for (const op of operations) {
|
|
416
|
+
const rawOperation = operationLookup.get(op.operationId);
|
|
417
|
+
if (!rawOperation) continue;
|
|
418
|
+
const requestBody = rawOperation.requestBody?.content?.["application/json"]?.schema;
|
|
419
|
+
if (requestBody?.$ref) {
|
|
420
|
+
const refName = extractRefName(requestBody.$ref);
|
|
421
|
+
referenced.add(refName);
|
|
422
|
+
} else if (requestBody) {
|
|
423
|
+
const deps = extractDependencies(requestBody);
|
|
424
|
+
for (const dep of deps) {
|
|
425
|
+
if (spec.components?.schemas?.[dep]) {
|
|
426
|
+
referenced.add(dep);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
const responses = rawOperation.responses || {};
|
|
431
|
+
for (const [, response] of Object.entries(responses)) {
|
|
432
|
+
const content = response?.content;
|
|
433
|
+
if (!content) continue;
|
|
434
|
+
const contentType = findContentType(content);
|
|
435
|
+
const responseSchema = content[contentType]?.schema;
|
|
436
|
+
if (responseSchema?.$ref) {
|
|
437
|
+
const refName = extractRefName(responseSchema.$ref);
|
|
438
|
+
referenced.add(refName);
|
|
439
|
+
} else if (responseSchema) {
|
|
440
|
+
const deps = extractDependencies(responseSchema);
|
|
441
|
+
for (const dep of deps) {
|
|
442
|
+
if (spec.components?.schemas?.[dep]) {
|
|
443
|
+
referenced.add(dep);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
for (const param of op.queryParams) {
|
|
449
|
+
if (param.schema?.$ref) {
|
|
450
|
+
const refName = extractRefName(param.schema.$ref);
|
|
451
|
+
referenced.add(refName);
|
|
452
|
+
}
|
|
453
|
+
if (param.schema?.items?.$ref) {
|
|
454
|
+
const refName = extractRefName(param.schema.items.$ref);
|
|
455
|
+
referenced.add(refName);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
for (const header of op.requestHeaders || []) {
|
|
459
|
+
if (header.schema?.$ref) {
|
|
460
|
+
const refName = extractRefName(header.schema.$ref);
|
|
461
|
+
referenced.add(refName);
|
|
462
|
+
}
|
|
463
|
+
if (header.schema?.items?.$ref) {
|
|
464
|
+
const refName = extractRefName(header.schema.items.$ref);
|
|
465
|
+
referenced.add(refName);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
const parameters = rawOperation.parameters || [];
|
|
469
|
+
for (const param of parameters) {
|
|
470
|
+
const resolvedParam = resolveParameter(param, spec);
|
|
471
|
+
if (resolvedParam?.schema?.$ref) {
|
|
472
|
+
const refName = extractRefName(resolvedParam.schema.$ref);
|
|
473
|
+
referenced.add(refName);
|
|
474
|
+
}
|
|
475
|
+
if (resolvedParam?.schema?.items?.$ref) {
|
|
476
|
+
const refName = extractRefName(resolvedParam.schema.items.$ref);
|
|
477
|
+
referenced.add(refName);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const visited = /* @__PURE__ */ new Set();
|
|
482
|
+
const toVisit = Array.from(referenced);
|
|
483
|
+
while (toVisit.length > 0) {
|
|
484
|
+
const schemaName = toVisit.pop();
|
|
485
|
+
if (visited.has(schemaName)) continue;
|
|
486
|
+
visited.add(schemaName);
|
|
487
|
+
const schema = spec.components?.schemas?.[schemaName];
|
|
488
|
+
if (!schema) continue;
|
|
489
|
+
const dependencies = extractDependencies(schema);
|
|
490
|
+
for (const dep of dependencies) {
|
|
491
|
+
if (spec.components?.schemas?.[dep] && !visited.has(dep)) {
|
|
492
|
+
referenced.add(dep);
|
|
493
|
+
toVisit.push(dep);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return referenced;
|
|
498
|
+
}
|
|
321
499
|
|
|
322
|
-
// src/utils/generate-helper-file.ts
|
|
500
|
+
// ../zenko-core/src/utils/generate-helper-file.ts
|
|
323
501
|
function generateHelperFile() {
|
|
324
502
|
const output = [];
|
|
325
503
|
output.push("// Generated helper types for Zenko");
|
|
@@ -361,11 +539,11 @@ function generateHelperFile() {
|
|
|
361
539
|
return output.join("\n");
|
|
362
540
|
}
|
|
363
541
|
|
|
364
|
-
// src/zenko.ts
|
|
542
|
+
// ../zenko-core/src/zenko.ts
|
|
365
543
|
function generateWithMetadata(spec, options = {}) {
|
|
366
544
|
const output = [];
|
|
367
545
|
const generatedTypes = /* @__PURE__ */ new Set();
|
|
368
|
-
const { strictDates = false, strictNumeric = false } = options;
|
|
546
|
+
const { strictDates = false, strictNumeric = false, operationIds } = options;
|
|
369
547
|
const typesConfig = normalizeTypesConfig(options.types);
|
|
370
548
|
const schemaOptions = {
|
|
371
549
|
strictDates,
|
|
@@ -379,13 +557,26 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
379
557
|
nameMap.set(name, toCamelCase(name));
|
|
380
558
|
}
|
|
381
559
|
}
|
|
382
|
-
|
|
560
|
+
let operations = parseOperations(spec, nameMap);
|
|
561
|
+
if (operationIds && operationIds.length > 0) {
|
|
562
|
+
const selectedIds = new Set(operationIds);
|
|
563
|
+
operations = operations.filter((op) => selectedIds.has(op.operationId));
|
|
564
|
+
}
|
|
383
565
|
appendHelperTypesImport(output, typesConfig, operations);
|
|
384
566
|
output.push("");
|
|
385
567
|
if (spec.components?.schemas) {
|
|
386
568
|
output.push("// Generated Zod Schemas");
|
|
387
569
|
output.push("");
|
|
388
|
-
|
|
570
|
+
let schemasToGenerate;
|
|
571
|
+
if (operationIds && operationIds.length > 0) {
|
|
572
|
+
const referencedSchemas = collectReferencedSchemas(operations, spec);
|
|
573
|
+
schemasToGenerate = Array.from(referencedSchemas);
|
|
574
|
+
} else {
|
|
575
|
+
schemasToGenerate = Object.keys(spec.components.schemas);
|
|
576
|
+
}
|
|
577
|
+
const sortedSchemas = topologicalSort(spec.components.schemas).filter(
|
|
578
|
+
(name) => schemasToGenerate.includes(name)
|
|
579
|
+
);
|
|
389
580
|
for (const name of sortedSchemas) {
|
|
390
581
|
const schema = spec.components.schemas[name];
|
|
391
582
|
const sanitizedName = nameMap.get(name);
|
|
@@ -574,6 +765,9 @@ function generateWithMetadata(spec, options = {}) {
|
|
|
574
765
|
}
|
|
575
766
|
return result;
|
|
576
767
|
}
|
|
768
|
+
function generateFromDocument(spec, options = {}) {
|
|
769
|
+
return generateWithMetadata(spec, options);
|
|
770
|
+
}
|
|
577
771
|
function generateRequestTypes(output, operations, spec, nameMap, schemaOptions) {
|
|
578
772
|
const requestTypesToGenerate = collectInlineRequestTypes(operations, spec);
|
|
579
773
|
if (requestTypesToGenerate.size > 0) {
|
|
@@ -596,7 +790,8 @@ function generateRequestTypes(output, operations, spec, nameMap, schemaOptions)
|
|
|
596
790
|
}
|
|
597
791
|
function generateResponseTypes(output, operations, spec, nameMap, schemaOptions) {
|
|
598
792
|
const responseTypesToGenerate = collectInlineResponseTypes(operations, spec);
|
|
599
|
-
|
|
793
|
+
const errorTypesToGenerate = collectInlineErrorTypes(operations, spec);
|
|
794
|
+
if (responseTypesToGenerate.size > 0 || errorTypesToGenerate.size > 0) {
|
|
600
795
|
output.push("// Generated Response Types");
|
|
601
796
|
output.push("");
|
|
602
797
|
for (const [typeName, schema] of responseTypesToGenerate) {
|
|
@@ -612,10 +807,23 @@ function generateResponseTypes(output, operations, spec, nameMap, schemaOptions)
|
|
|
612
807
|
output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
|
|
613
808
|
output.push("");
|
|
614
809
|
}
|
|
810
|
+
for (const [typeName, schema] of errorTypesToGenerate) {
|
|
811
|
+
const generatedSchema = generateZodSchema(
|
|
812
|
+
typeName,
|
|
813
|
+
schema,
|
|
814
|
+
/* @__PURE__ */ new Set(),
|
|
815
|
+
schemaOptions,
|
|
816
|
+
nameMap
|
|
817
|
+
);
|
|
818
|
+
output.push(generatedSchema);
|
|
819
|
+
output.push("");
|
|
820
|
+
output.push(`export type ${typeName} = z.infer<typeof ${typeName}>;`);
|
|
821
|
+
output.push("");
|
|
822
|
+
}
|
|
615
823
|
}
|
|
616
824
|
}
|
|
617
825
|
function generate(spec, options = {}) {
|
|
618
|
-
return
|
|
826
|
+
return generateFromDocument(spec, options).output;
|
|
619
827
|
}
|
|
620
828
|
function appendOperationField(buffer, key, value) {
|
|
621
829
|
if (!value) return;
|
|
@@ -656,7 +864,7 @@ var CONTENT_TYPE_MAP = {
|
|
|
656
864
|
"application/octet-stream": "unknown",
|
|
657
865
|
"application/pdf": "unknown"
|
|
658
866
|
};
|
|
659
|
-
function
|
|
867
|
+
function findContentType2(content) {
|
|
660
868
|
const contentTypes = Object.keys(content);
|
|
661
869
|
if (contentTypes.includes("application/json")) {
|
|
662
870
|
return "application/json";
|
|
@@ -907,7 +1115,7 @@ function collectParameters(pathItem, operation, spec) {
|
|
|
907
1115
|
const addParameters = (params) => {
|
|
908
1116
|
if (!Array.isArray(params)) return;
|
|
909
1117
|
for (const param of params) {
|
|
910
|
-
const resolved =
|
|
1118
|
+
const resolved = resolveParameter2(param, spec);
|
|
911
1119
|
if (!resolved) continue;
|
|
912
1120
|
const key = `${resolved.in}:${resolved.name}`;
|
|
913
1121
|
parametersMap.set(key, resolved);
|
|
@@ -917,7 +1125,7 @@ function collectParameters(pathItem, operation, spec) {
|
|
|
917
1125
|
addParameters(operation.parameters);
|
|
918
1126
|
return Array.from(parametersMap.values());
|
|
919
1127
|
}
|
|
920
|
-
function
|
|
1128
|
+
function resolveParameter2(parameter, spec) {
|
|
921
1129
|
if (!parameter) return void 0;
|
|
922
1130
|
if (parameter.$ref) {
|
|
923
1131
|
const refName = extractRefName(parameter.$ref);
|
|
@@ -972,7 +1180,7 @@ function getResponseTypes(operation, operationId, nameMap) {
|
|
|
972
1180
|
}
|
|
973
1181
|
continue;
|
|
974
1182
|
}
|
|
975
|
-
const contentType =
|
|
1183
|
+
const contentType = findContentType2(content);
|
|
976
1184
|
const resolvedSchema = content[contentType]?.schema;
|
|
977
1185
|
if (!resolvedSchema) {
|
|
978
1186
|
const inferredType = inferResponseType(contentType, statusCode);
|
|
@@ -1344,6 +1552,8 @@ function applyNumericBounds(schema, builder) {
|
|
|
1344
1552
|
return builder;
|
|
1345
1553
|
}
|
|
1346
1554
|
export {
|
|
1347
|
-
generate
|
|
1555
|
+
generate,
|
|
1556
|
+
generateFromDocument,
|
|
1557
|
+
generateWithMetadata
|
|
1348
1558
|
};
|
|
1349
1559
|
//# sourceMappingURL=index.mjs.map
|