zenko 0.1.4 → 0.1.6-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/dist/cli.cjs +114 -23
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +114 -23
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +104 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -48
- package/dist/index.d.ts +2 -48
- package/dist/index.mjs +101 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
- package/LICENSE +0 -21
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
|
-
// src/utils/topological-sort.ts
|
|
32
|
+
// ../zenko-core/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
|
-
// src/utils/property-name.ts
|
|
81
|
+
// ../zenko-core/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,7 @@ function formatPropertyName(name) {
|
|
|
158
158
|
return isValidJSIdentifier(name) ? name : `"${name}"`;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
// src/utils/http-status.ts
|
|
161
|
+
// ../zenko-core/src/utils/http-status.ts
|
|
162
162
|
var statusNameMap = {
|
|
163
163
|
"400": "badRequest",
|
|
164
164
|
"401": "unauthorized",
|
|
@@ -232,8 +232,8 @@ function isErrorStatus(status) {
|
|
|
232
232
|
return code >= 400;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
// src/zenko.ts
|
|
236
|
-
function
|
|
235
|
+
// ../zenko-core/src/zenko.ts
|
|
236
|
+
function generateWithMetadata(spec, options = {}) {
|
|
237
237
|
const output = [];
|
|
238
238
|
const generatedTypes = /* @__PURE__ */ new Set();
|
|
239
239
|
const { strictDates = false, strictNumeric = false } = options;
|
|
@@ -408,7 +408,16 @@ function generate(spec, options = {}) {
|
|
|
408
408
|
output.push("");
|
|
409
409
|
}
|
|
410
410
|
generateOperationTypes(output, operations, typesConfig);
|
|
411
|
-
|
|
411
|
+
const result = {
|
|
412
|
+
output: output.join("\n")
|
|
413
|
+
};
|
|
414
|
+
if (typesConfig.emit && typesConfig.helpers === "file" && typesConfig.helpersOutput) {
|
|
415
|
+
result.helperFile = {
|
|
416
|
+
path: typesConfig.helpersOutput,
|
|
417
|
+
content: generateHelperFile()
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
return result;
|
|
412
421
|
}
|
|
413
422
|
function appendOperationField(buffer, key, value) {
|
|
414
423
|
if (!value) return;
|
|
@@ -536,6 +545,9 @@ function appendHelperTypesImport(buffer, config) {
|
|
|
536
545
|
buffer.push(
|
|
537
546
|
"type HeaderFn<TArgs extends unknown[] = [], TResult = Record<string, unknown> | Record<string, never>> = (...args: TArgs) => TResult;"
|
|
538
547
|
);
|
|
548
|
+
buffer.push(
|
|
549
|
+
"type AnyHeaderFn = HeaderFn<any, unknown> | (() => unknown);"
|
|
550
|
+
);
|
|
539
551
|
buffer.push(
|
|
540
552
|
"type OperationErrors<TClient = unknown, TServer = unknown, TDefault = unknown, TOther = unknown> = {"
|
|
541
553
|
);
|
|
@@ -545,7 +557,7 @@ function appendHelperTypesImport(buffer, config) {
|
|
|
545
557
|
buffer.push(" otherErrors?: TOther;");
|
|
546
558
|
buffer.push("};");
|
|
547
559
|
buffer.push(
|
|
548
|
-
"type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends
|
|
560
|
+
"type OperationDefinition<TMethod extends RequestMethod, TPath extends (...args: any[]) => string, TRequest = undefined, TResponse = undefined, THeaders extends AnyHeaderFn | undefined = undefined, TErrors extends OperationErrors | undefined = undefined> = {"
|
|
549
561
|
);
|
|
550
562
|
buffer.push(" method: TMethod;");
|
|
551
563
|
buffer.push(" path: TPath;");
|
|
@@ -616,26 +628,35 @@ var TYPE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
616
628
|
"bigint",
|
|
617
629
|
"symbol"
|
|
618
630
|
]);
|
|
631
|
+
var IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
619
632
|
function wrapTypeReference(typeName) {
|
|
620
633
|
if (!typeName) return "undefined";
|
|
621
|
-
|
|
622
|
-
if (
|
|
623
|
-
if (
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
634
|
+
const normalized = typeName.trim();
|
|
635
|
+
if (normalized === "undefined") return "undefined";
|
|
636
|
+
if (TYPE_KEYWORDS.has(normalized)) return normalized;
|
|
637
|
+
if (normalized.startsWith("typeof ")) return normalized;
|
|
638
|
+
const arrayMatch = normalized.match(/^z\.array\((.+)\)$/);
|
|
639
|
+
if (arrayMatch) {
|
|
640
|
+
return `z.ZodArray<${wrapTypeReference(arrayMatch[1])}>`;
|
|
641
|
+
}
|
|
642
|
+
if (IDENTIFIER_PATTERN.test(normalized)) {
|
|
643
|
+
return `typeof ${normalized}`;
|
|
644
|
+
}
|
|
645
|
+
return normalized;
|
|
629
646
|
}
|
|
630
647
|
function wrapErrorValueType(typeName) {
|
|
631
648
|
if (!typeName) return "unknown";
|
|
632
|
-
|
|
633
|
-
if (
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
649
|
+
const normalized = typeName.trim();
|
|
650
|
+
if (TYPE_KEYWORDS.has(normalized)) return normalized;
|
|
651
|
+
if (normalized.startsWith("typeof ")) return normalized;
|
|
652
|
+
const arrayMatch = normalized.match(/^z\.array\((.+)\)$/);
|
|
653
|
+
if (arrayMatch) {
|
|
654
|
+
return `z.ZodArray<${wrapErrorValueType(arrayMatch[1])}>`;
|
|
637
655
|
}
|
|
638
|
-
|
|
656
|
+
if (IDENTIFIER_PATTERN.test(normalized)) {
|
|
657
|
+
return `typeof ${normalized}`;
|
|
658
|
+
}
|
|
659
|
+
return normalized;
|
|
639
660
|
}
|
|
640
661
|
function collectParameters(pathItem, operation, spec) {
|
|
641
662
|
const parametersMap = /* @__PURE__ */ new Map();
|
|
@@ -699,6 +720,11 @@ function getResponseTypes(operation, operationId) {
|
|
|
699
720
|
if (!content || Object.keys(content).length === 0) {
|
|
700
721
|
if (statusCode === "204" || /^3\d\d$/.test(statusCode)) {
|
|
701
722
|
successCodes.set(statusCode, "undefined");
|
|
723
|
+
} else if (isErrorStatus(statusCode)) {
|
|
724
|
+
errorEntries.push({
|
|
725
|
+
code: statusCode,
|
|
726
|
+
schema: "undefined"
|
|
727
|
+
});
|
|
702
728
|
}
|
|
703
729
|
continue;
|
|
704
730
|
}
|
|
@@ -793,6 +819,10 @@ function resolveResponseType(schema, fallbackName) {
|
|
|
793
819
|
if (schema.$ref) {
|
|
794
820
|
return extractRefName(schema.$ref);
|
|
795
821
|
}
|
|
822
|
+
if (schema.type === "array" && schema.items?.$ref) {
|
|
823
|
+
const itemRef = extractRefName(schema.items.$ref);
|
|
824
|
+
return `z.array(${itemRef})`;
|
|
825
|
+
}
|
|
796
826
|
return fallbackName;
|
|
797
827
|
}
|
|
798
828
|
function getRequestHeaders(parameters) {
|
|
@@ -1042,6 +1072,51 @@ function applyNumericBounds(schema, builder) {
|
|
|
1042
1072
|
}
|
|
1043
1073
|
return builder;
|
|
1044
1074
|
}
|
|
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
|
+
}
|
|
1045
1120
|
function toCamelCase(str) {
|
|
1046
1121
|
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
1047
1122
|
}
|
|
@@ -1206,15 +1281,31 @@ async function generateSingle(options) {
|
|
|
1206
1281
|
const resolvedInput = path.resolve(inputFile);
|
|
1207
1282
|
const resolvedOutput = path.resolve(outputFile);
|
|
1208
1283
|
const spec = readSpec(resolvedInput);
|
|
1209
|
-
const
|
|
1284
|
+
const result = generateWithMetadata(spec, {
|
|
1210
1285
|
strictDates,
|
|
1211
1286
|
strictNumeric,
|
|
1212
1287
|
types: typesConfig
|
|
1213
1288
|
});
|
|
1214
1289
|
fs.mkdirSync(path.dirname(resolvedOutput), { recursive: true });
|
|
1215
|
-
fs.writeFileSync(resolvedOutput, output);
|
|
1290
|
+
fs.writeFileSync(resolvedOutput, result.output);
|
|
1216
1291
|
console.log(`\u2705 Generated TypeScript types in ${resolvedOutput}`);
|
|
1217
1292
|
console.log(`\u{1F4C4} Processed ${Object.keys(spec.paths).length} paths`);
|
|
1293
|
+
if (result.helperFile) {
|
|
1294
|
+
const helperPath = path.isAbsolute(result.helperFile.path) ? result.helperFile.path : path.resolve(path.dirname(resolvedOutput), result.helperFile.path);
|
|
1295
|
+
const absoluteResolvedOutput = path.resolve(resolvedOutput);
|
|
1296
|
+
const absoluteHelperPath = path.resolve(helperPath);
|
|
1297
|
+
if (absoluteResolvedOutput === absoluteHelperPath) {
|
|
1298
|
+
console.warn(
|
|
1299
|
+
`\u26A0\uFE0F Skipping helper file generation: would overwrite main output at ${absoluteResolvedOutput}`
|
|
1300
|
+
);
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
fs.mkdirSync(path.dirname(helperPath), { recursive: true });
|
|
1304
|
+
fs.writeFileSync(helperPath, result.helperFile.content, {
|
|
1305
|
+
encoding: "utf8"
|
|
1306
|
+
});
|
|
1307
|
+
console.log(`\u{1F4E6} Generated helper types in ${helperPath}`);
|
|
1308
|
+
}
|
|
1218
1309
|
}
|
|
1219
1310
|
function readSpec(filePath) {
|
|
1220
1311
|
if (!fs.existsSync(filePath)) {
|