@povio/openapi-codegen-cli 3.1.1 → 3.2.0-rc.11
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 +63 -15
- package/dist/AuthGuard-GbtTDXs0.d.mts +32 -0
- package/dist/AuthGuard-qpAtHaBz.mjs +24 -0
- package/dist/acl.d.mts +6 -20
- package/dist/acl.mjs +8 -13
- package/dist/{auth.context-Bu5KW2sI.mjs → auth.context-COWO6ssl.mjs} +1 -21
- package/dist/auth.d.mts +2 -0
- package/dist/auth.mjs +3 -0
- package/dist/axios.d.mts +2 -0
- package/dist/axios.mjs +2 -0
- package/dist/{config-BU7wVf7U.d.mts → config-DgrOddSC.d.mts} +1 -2
- package/dist/config.d.mts +4 -0
- package/dist/config.mjs +5 -0
- package/dist/{error-handling-DSI86D3u.mjs → error-handling-BeydPL7s.mjs} +21 -51
- package/dist/{error-handling-D-mHJ60d.d.mts → error-handling-LPEPQV1V.d.mts} +3 -42
- package/dist/errors.d.mts +3 -0
- package/dist/errors.mjs +2 -0
- package/dist/generate.runner-CD7mlcJ4.mjs +184 -0
- package/dist/generate.utils-CT-LA-gX.cjs +2267 -0
- package/dist/generateCodeFromOpenAPIDoc-D9W5BtAt.mjs +2097 -0
- package/dist/{generateCodeFromOpenAPIDoc-DseBECa-.mjs → generateCodeFromOpenAPIDoc-DhI7CHeh.cjs} +1349 -2344
- package/dist/generator.d.mts +3 -10
- package/dist/generator.mjs +9 -9
- package/dist/getDataFromOpenAPIDoc-D8w0QElH.mjs +2011 -0
- package/dist/i18n-B_brQh4X.d.mts +38 -0
- package/dist/i18n-D-FesqFb.mjs +36 -0
- package/dist/index.d.mts +12 -200
- package/dist/index.mjs +12 -264
- package/dist/metro.cjs +114 -4959
- package/dist/metro.d.mts +3 -4
- package/dist/metro.mjs +4 -9
- package/dist/native-bindings-BTQGSGhU.mjs +1480 -0
- package/dist/native-rest-interceptor-CAWR8H5Y.mjs +208 -0
- package/dist/native-rest-interceptor-Cz6saoq5.d.mts +46 -0
- package/dist/native.d.mts +3 -0
- package/dist/native.mjs +3 -0
- package/dist/openapi-codegen-native-darwin-arm64.node +0 -0
- package/dist/openapi-codegen-native-linux-x64.node +0 -0
- package/dist/openapi-codegen-native-win32-x64.node +0 -0
- package/dist/{openapi-codegen.runner-Co_bG00_.mjs → openapi-codegen.runner-C4TIXQNx.mjs} +4 -5
- package/dist/{openapi-source.runner-wLs5vqw6.mjs → openapi-source.runner-BZ6ZLgRO.mjs} +19 -10
- package/dist/{openapi-source.runner-BSIrB6ny.d.mts → openapi-source.runner-ykstqlPC.d.mts} +2 -8
- package/dist/{options-CE4Koxof.d.mts → options-KPf-Fti5.d.mts} +6 -1
- package/dist/query.d.mts +3 -0
- package/dist/query.mjs +3 -0
- package/dist/queryConfig.context-CRJOgf19.d.mts +22 -0
- package/dist/queryConfig.context-CldQ5YL9.mjs +34 -0
- package/dist/rest-client-CQyFvqYC.d.mts +55 -0
- package/dist/rest-interceptor-D5NCNTm1.mjs +115 -0
- package/dist/rest-transport.types-DM5-qyOJ.d.mts +66 -0
- package/dist/rest-transport.types-DxitRtsB.mjs +11 -0
- package/dist/rest.d.mts +2 -0
- package/dist/rest.mjs +2 -0
- package/dist/rest.utils-rezWAIYL.d.mts +10 -0
- package/dist/router.context-EPlMBk3G.mjs +21 -0
- package/dist/sh.d.mts +1 -1
- package/dist/sh.mjs +41 -71
- package/dist/tiny.d.mts +1 -3
- package/dist/tiny.mjs +2 -3
- package/dist/useMutationEffects-DIdL8tlx.d.mts +29 -0
- package/dist/useMutationEffects-PB1fvKWM.mjs +68 -0
- package/dist/vite.d.mts +3 -4
- package/dist/vite.mjs +6 -10
- package/dist/workspace.context-XWvQ_7Hg.mjs +26 -0
- package/dist/workspace.context-isVY9ves.d.mts +23 -0
- package/dist/zod.d.mts +2 -7
- package/dist/zod.mjs +2 -4
- package/package.json +73 -26
- package/dist/generate.runner-C1HrS_9G.mjs +0 -90
|
@@ -0,0 +1,2011 @@
|
|
|
1
|
+
import { $t as isPrimitiveType, Bn as getMostCommonAdjacentCombinationSplit, Ct as getParamZodSchemaName, Et as getZodSchemaOperationName, Fn as isTagIncluded, Gt as getParameterEnumNames, Hn as removeWord, Ht as getNamespaceName, Jt as isErrorStatus, Kt as getSchemaNameByRef, Mn as formatTag, Nn as getEndpointTag, On as BODY_PARAMETER_NAME, Ot as isNamedZodSchema, Pn as getOperationTag, Qt as isPathExcluded, Rn as capitalize, Sn as VOID_SCHEMA, St as getEnumZodSchemaName, Tt as getZodSchemaName, Un as snakeToCamel, Ut as autocorrectRef, Wn as Profiler, Wt as escapeControlCharacters, Xt as isMediaTypeAllowed, Yt as isMainResponseStatus, Zt as isParamMediaTypeAllowed, _n as INT_SCHEMA, an as wrapWithQuotesIfNeeded, bn as URL_SCHEMA, bt as invalidVariableNameCharactersToCamel, cn as isReferenceObject, d as isQuery, dn as ALLOWED_PATH_IN, en as isSortingParameterObject, fn as ANY_SCHEMA, gn as ENUM_SCHEMA, hn as EMAIL_SCHEMA, in as unwrapQuotesIfNeeded, kn as JSON_APPLICATION_FORMAT, ln as isSchemaObject, lt as iterateSchema, mn as DATETIME_SCHEMA, nn as pathToVariableName, on as inferRequiredSchema, pn as BLOB_SCHEMA, qt as getSchemaRef, rn as replaceHyphenatedPath, s as pick, sn as isArraySchemaObject, tn as pathParamToVariableName, un as ALLOWED_METHODS, ut as getUniqueArray, vn as NUMBER_SCHEMA, wt as getResponseZodSchemaName, xn as UUID_SCHEMA, xt as getBodyZodSchemaName, yn as STRING_SCHEMA, zn as decapitalize } from "./native-bindings-BTQGSGhU.mjs";
|
|
2
|
+
//#region src/generators/const/validation.const.ts
|
|
3
|
+
const HTTP_STATUS_CODES = {
|
|
4
|
+
"100": "Continue",
|
|
5
|
+
"101": "Switching Protocols",
|
|
6
|
+
"102": "Processing",
|
|
7
|
+
"103": "Early Hints",
|
|
8
|
+
"200": "OK",
|
|
9
|
+
"201": "Created",
|
|
10
|
+
"202": "Accepted",
|
|
11
|
+
"203": "Non-Authoritative Information",
|
|
12
|
+
"204": "No Content",
|
|
13
|
+
"205": "Reset Content",
|
|
14
|
+
"206": "Partial Content",
|
|
15
|
+
"300": "Ambiguous",
|
|
16
|
+
"301": "Moved Permanently",
|
|
17
|
+
"302": "Found",
|
|
18
|
+
"303": "See Other",
|
|
19
|
+
"304": "Not Modified",
|
|
20
|
+
"307": "Temporary Redirect",
|
|
21
|
+
"308": "Permanent Redirect",
|
|
22
|
+
"400": "Bad Request",
|
|
23
|
+
"401": "Unauthorized",
|
|
24
|
+
"402": "Payment Required",
|
|
25
|
+
"403": "Forbidden",
|
|
26
|
+
"404": "Not Found",
|
|
27
|
+
"405": "Method Not Allowed",
|
|
28
|
+
"406": "Not Acceptable",
|
|
29
|
+
"407": "Proxy Authentication Required",
|
|
30
|
+
"408": "Request Timeout",
|
|
31
|
+
"409": "Conflict",
|
|
32
|
+
"410": "Gone",
|
|
33
|
+
"411": "Length Required",
|
|
34
|
+
"412": "Precondition Failed",
|
|
35
|
+
"413": "Payload Too Large",
|
|
36
|
+
"414": "URI Too Long",
|
|
37
|
+
"415": "Unsupported Media Type",
|
|
38
|
+
"416": "Requested Range Not Satisfiable",
|
|
39
|
+
"417": "Expectation Failed",
|
|
40
|
+
"418": "I Am a Teapot",
|
|
41
|
+
"421": "Misdirected Request",
|
|
42
|
+
"422": "Unprocessable Entity",
|
|
43
|
+
"424": "Failed Dependency",
|
|
44
|
+
"428": "Precondition Required",
|
|
45
|
+
"429": "Too Many Requests",
|
|
46
|
+
"500": "Internal Server Error",
|
|
47
|
+
"501": "Not Implemented",
|
|
48
|
+
"502": "Bad Gateway",
|
|
49
|
+
"503": "Service Unavailable",
|
|
50
|
+
"504": "Gateway Timeout",
|
|
51
|
+
"505": "HTTP Version Not Supported"
|
|
52
|
+
};
|
|
53
|
+
const VALIDATION_ERROR_TYPE_TITLE = {
|
|
54
|
+
"invalid-schema": "Invalid OpenAPI Schemas",
|
|
55
|
+
"invalid-operation-id": "Invalid Operation IDs",
|
|
56
|
+
"missing-path-parameter": "Missing Path Parameters",
|
|
57
|
+
"not-allowed-inline-enum": "Not Allowed Inline Enums",
|
|
58
|
+
"not-allowed-circular-schema": "Not Allowed Circular Schemas",
|
|
59
|
+
"missing-acl-condition-property": "Missing x-acl Condition Properties",
|
|
60
|
+
"missing-status-code": "Missing HTTP Status Codes",
|
|
61
|
+
"invalid-status-code": "Invalid HTTP Status Codes",
|
|
62
|
+
"multiple-success-status-codes": "Multiple Success HTTP Status Codes"
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/generators/core/zod/getZodChain.ts
|
|
66
|
+
const zodChainCache = /* @__PURE__ */ new WeakMap();
|
|
67
|
+
function getZodChain({ schema, meta, options }) {
|
|
68
|
+
let optionsCache = zodChainCache.get(options);
|
|
69
|
+
if (!optionsCache) {
|
|
70
|
+
optionsCache = /* @__PURE__ */ new WeakMap();
|
|
71
|
+
zodChainCache.set(options, optionsCache);
|
|
72
|
+
}
|
|
73
|
+
let schemaCache = optionsCache.get(schema);
|
|
74
|
+
if (!schemaCache) {
|
|
75
|
+
schemaCache = /* @__PURE__ */ new Map();
|
|
76
|
+
optionsCache.set(schema, schemaCache);
|
|
77
|
+
}
|
|
78
|
+
const cacheKey = `${Boolean(meta?.isRequired)}|${Boolean(meta?.isParentPartial)}`;
|
|
79
|
+
const cached = schemaCache.get(cacheKey);
|
|
80
|
+
if (cached !== void 0) return cached;
|
|
81
|
+
const chains = [];
|
|
82
|
+
if (schema.type === "string") chains.push(getZodChainableStringValidations(schema));
|
|
83
|
+
else if (schema.type === "number" || schema.type === "integer") chains.push(getZodChainableNumberValidations(schema));
|
|
84
|
+
else if (schema.type === "array") chains.push(getZodChainableArrayValidations(schema));
|
|
85
|
+
if (typeof schema.description === "string" && schema.description !== "" && options.withDescription) chains.push(`describe(${JSON.stringify(schema.description)})`);
|
|
86
|
+
const output = chains.concat(getZodChainablePresence({
|
|
87
|
+
schema,
|
|
88
|
+
meta,
|
|
89
|
+
options
|
|
90
|
+
}), options.withDefaultValues !== false ? getZodChainableDefault(schema) : []).filter(Boolean).join(".");
|
|
91
|
+
const chain = output ? `.${output}` : "";
|
|
92
|
+
schemaCache.set(cacheKey, chain);
|
|
93
|
+
return chain;
|
|
94
|
+
}
|
|
95
|
+
function getZodChainablePresence({ schema, meta, options }) {
|
|
96
|
+
if (schema.nullable && !meta?.isRequired) return "nullish()";
|
|
97
|
+
if (schema.nullable || options.replaceOptionalWithNullish && meta?.isParentPartial) return "nullable()";
|
|
98
|
+
if (!meta?.isRequired) return options.replaceOptionalWithNullish ? "nullish()" : "optional()";
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
function getZodChainableDefault(schema) {
|
|
102
|
+
if (schema.default !== void 0) return `default(${schema.type === "number" || schema.type === "integer" ? unwrapQuotesIfNeeded(schema.default) : JSON.stringify(schema.default)})`;
|
|
103
|
+
return "";
|
|
104
|
+
}
|
|
105
|
+
function getZodChainableStringValidations(schema) {
|
|
106
|
+
const validations = [];
|
|
107
|
+
if (!schema.enum) {
|
|
108
|
+
if (schema.minLength !== void 0) validations.push(`min(${schema.minLength})`);
|
|
109
|
+
if (schema.maxLength !== void 0) validations.push(`max(${schema.maxLength})`);
|
|
110
|
+
}
|
|
111
|
+
if (schema.pattern) validations.push(`regex(${formatPatternIfNeeded(schema.pattern)})`);
|
|
112
|
+
return validations.join(".");
|
|
113
|
+
}
|
|
114
|
+
function formatPatternIfNeeded(pattern) {
|
|
115
|
+
if (pattern.startsWith("/") && pattern.endsWith("/")) pattern = pattern.slice(1, -1);
|
|
116
|
+
pattern = escapeControlCharacters(pattern);
|
|
117
|
+
return `/${pattern}/`;
|
|
118
|
+
}
|
|
119
|
+
function getZodChainableNumberValidations(schema) {
|
|
120
|
+
const validations = [];
|
|
121
|
+
if (schema.enum) return "";
|
|
122
|
+
if (schema.minimum !== void 0) if (schema.exclusiveMinimum === true) validations.push(`gt(${schema.minimum})`);
|
|
123
|
+
else validations.push(`gte(${schema.minimum})`);
|
|
124
|
+
else if (typeof schema.exclusiveMinimum === "number") validations.push(`gt(${schema.exclusiveMinimum})`);
|
|
125
|
+
if (schema.maximum !== void 0) if (schema.exclusiveMaximum === true) validations.push(`lt(${schema.maximum})`);
|
|
126
|
+
else validations.push(`lte(${schema.maximum})`);
|
|
127
|
+
else if (typeof schema.exclusiveMaximum === "number") validations.push(`lt(${schema.exclusiveMaximum})`);
|
|
128
|
+
if (schema.multipleOf) validations.push(`multipleOf(${schema.multipleOf})`);
|
|
129
|
+
return validations.join(".");
|
|
130
|
+
}
|
|
131
|
+
function getZodChainableArrayValidations(schema) {
|
|
132
|
+
const validations = [];
|
|
133
|
+
if (schema.minItems) validations.push(`min(${schema.minItems})`);
|
|
134
|
+
if (schema.maxItems) validations.push(`max(${schema.maxItems})`);
|
|
135
|
+
return validations.join(".");
|
|
136
|
+
}
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/generators/core/zod/getZodSchemaRefs.ts
|
|
139
|
+
function getZodSchemaRefs(resolver, zodSchemaName) {
|
|
140
|
+
const schemaRef = resolver.getRefByZodSchemaName(zodSchemaName);
|
|
141
|
+
if (schemaRef) {
|
|
142
|
+
const refs = Array.from(resolver.dependencyGraph.refsDependencyGraph[schemaRef] ?? []).map((ref) => resolver.getZodSchemaNameByRef(ref));
|
|
143
|
+
const enumRefs = resolver.getExtractedEnumZodSchemaNamesReferencedBySchemaRef(schemaRef);
|
|
144
|
+
return [...refs, ...enumRefs];
|
|
145
|
+
}
|
|
146
|
+
const zodSchema = resolver.getCompositeZodSchemaByZodSchemaName(zodSchemaName);
|
|
147
|
+
if (zodSchema) return Array.from(getSchemaRefs(zodSchema)).map((schemaRef) => resolver.getZodSchemaNameByRef(schemaRef));
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
function getSchemaRefs(zodSchema, { skipObjectSchema = false } = {}) {
|
|
151
|
+
return zodSchema.children.reduce((acc, child) => {
|
|
152
|
+
const ref = child.ref ?? child.enumRef;
|
|
153
|
+
if (ref) acc.add(ref);
|
|
154
|
+
if (child.children.length > 0 && (!skipObjectSchema || !isSchemaObject(child.schema) || child.schema.type !== "object")) getSchemaRefs(child).forEach((ref) => acc.add(ref));
|
|
155
|
+
return acc;
|
|
156
|
+
}, /* @__PURE__ */ new Set());
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/generators/utils/math.utils.ts
|
|
160
|
+
const sum = (arr) => arr.reduce((acc, item) => acc + item, 0);
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/generators/core/openapi/getOpenAPISchemaComplexity.ts
|
|
163
|
+
function getOpenAPISchemaComplexity(current, schema) {
|
|
164
|
+
if (!schema) return current;
|
|
165
|
+
if (isReferenceObject(schema)) return current + 2;
|
|
166
|
+
if (Array.isArray(schema.type)) {
|
|
167
|
+
if (schema.type.length === 1) return complexityByComposite("oneOf") + getOpenAPISchemaComplexity(current, {
|
|
168
|
+
...schema,
|
|
169
|
+
type: schema.type[0]
|
|
170
|
+
});
|
|
171
|
+
return current + complexityByComposite("oneOf") + sum(schema.type.map((prop) => getOpenAPISchemaComplexity(0, {
|
|
172
|
+
...schema,
|
|
173
|
+
type: prop
|
|
174
|
+
})));
|
|
175
|
+
}
|
|
176
|
+
if (schema.oneOf) {
|
|
177
|
+
if (schema.oneOf.length === 1) return complexityByComposite("oneOf") + getOpenAPISchemaComplexity(current, schema.oneOf[0]);
|
|
178
|
+
return current + complexityByComposite("oneOf") + sum(schema.oneOf.map((prop) => getOpenAPISchemaComplexity(0, prop)));
|
|
179
|
+
}
|
|
180
|
+
if (schema.anyOf) {
|
|
181
|
+
if (schema.anyOf.length === 1) return complexityByComposite("anyOf") + getOpenAPISchemaComplexity(current, schema.anyOf[0]);
|
|
182
|
+
return current + complexityByComposite("anyOf") + sum(schema.anyOf.map((prop) => getOpenAPISchemaComplexity(0, prop)));
|
|
183
|
+
}
|
|
184
|
+
if (schema.allOf) {
|
|
185
|
+
if (schema.allOf.length === 1) return complexityByComposite("allOf") + getOpenAPISchemaComplexity(current, schema.allOf[0]);
|
|
186
|
+
return current + complexityByComposite("allOf") + sum(schema.allOf.map((prop) => getOpenAPISchemaComplexity(0, prop)));
|
|
187
|
+
}
|
|
188
|
+
if (!schema.type) return current;
|
|
189
|
+
if (isPrimitiveType(schema.type)) {
|
|
190
|
+
if (schema.enum) return current + complexityByType(schema) + complexityByComposite("enum") + sum(schema.enum.map((prop) => getOpenAPISchemaComplexity(0, prop)));
|
|
191
|
+
return current + complexityByType(schema);
|
|
192
|
+
}
|
|
193
|
+
if (schema.type === "array") {
|
|
194
|
+
if (schema.items) return complexityByComposite("array") + getOpenAPISchemaComplexity(current, schema.items);
|
|
195
|
+
return complexityByComposite("array") + getOpenAPISchemaComplexity(current);
|
|
196
|
+
}
|
|
197
|
+
if (schema.type === "object" || schema.properties || schema.additionalProperties) {
|
|
198
|
+
if (schema.properties) {
|
|
199
|
+
const props = Object.values(schema.properties);
|
|
200
|
+
current += complexityByComposite("object") + sum(props.map((prop) => getOpenAPISchemaComplexity(0, prop)));
|
|
201
|
+
} else current += complexityByComposite("empty-object");
|
|
202
|
+
if (schema.additionalProperties) if (typeof schema.additionalProperties === "object") current += getOpenAPISchemaComplexity(0, schema.additionalProperties);
|
|
203
|
+
else current += getOpenAPISchemaComplexity(1);
|
|
204
|
+
}
|
|
205
|
+
return current;
|
|
206
|
+
}
|
|
207
|
+
function complexityByType(schema) {
|
|
208
|
+
return schema.type === "string" || schema.type === "number" || schema.type === "integer" || schema.type === "boolean" ? 1 : 0;
|
|
209
|
+
}
|
|
210
|
+
function complexityByComposite(type) {
|
|
211
|
+
switch (type) {
|
|
212
|
+
case "anyOf": return 3;
|
|
213
|
+
case "oneOf":
|
|
214
|
+
case "allOf":
|
|
215
|
+
case "object": return 2;
|
|
216
|
+
case "enum":
|
|
217
|
+
case "array":
|
|
218
|
+
case "empty-object": return 1;
|
|
219
|
+
default: return 0;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region src/generators/core/zod/ZodSchema.class.ts
|
|
224
|
+
var ZodSchema = class {
|
|
225
|
+
schema;
|
|
226
|
+
resolver;
|
|
227
|
+
code;
|
|
228
|
+
ref;
|
|
229
|
+
enumRef;
|
|
230
|
+
children = [];
|
|
231
|
+
meta;
|
|
232
|
+
constructor(schema, resolver, meta = { referencedBy: [] }, enumRef) {
|
|
233
|
+
this.schema = schema;
|
|
234
|
+
this.resolver = resolver;
|
|
235
|
+
if (isReferenceObject(schema)) this.ref = schema.$ref;
|
|
236
|
+
if (enumRef) this.enumRef = enumRef;
|
|
237
|
+
this.meta = {
|
|
238
|
+
...meta,
|
|
239
|
+
referencedBy: [...meta?.referencedBy ?? []]
|
|
240
|
+
};
|
|
241
|
+
if (this.ref) this.meta.referencedBy.push(this);
|
|
242
|
+
}
|
|
243
|
+
getCodeString(tag, options) {
|
|
244
|
+
if (!this.ref && this.code) return this.code;
|
|
245
|
+
if (!this.ref) throw new Error("Zod schema is missing both ref and code");
|
|
246
|
+
const zodSchemaName = this.resolver?.getZodSchemaNameByRef(this.ref);
|
|
247
|
+
if (!zodSchemaName) return this.ref;
|
|
248
|
+
const zodSchemaTag = this.resolver?.getTagByZodSchemaName(zodSchemaName);
|
|
249
|
+
if (options?.tsNamespaces && zodSchemaTag && zodSchemaTag !== tag) return `${getNamespaceName({
|
|
250
|
+
type: "models",
|
|
251
|
+
tag: zodSchemaTag,
|
|
252
|
+
options
|
|
253
|
+
})}.${zodSchemaName}`;
|
|
254
|
+
return zodSchemaName;
|
|
255
|
+
}
|
|
256
|
+
get complexity() {
|
|
257
|
+
return getOpenAPISchemaComplexity(0, this.schema);
|
|
258
|
+
}
|
|
259
|
+
assign(code) {
|
|
260
|
+
this.code = code;
|
|
261
|
+
return this;
|
|
262
|
+
}
|
|
263
|
+
inherit(parent) {
|
|
264
|
+
if (parent) parent.children.push(this);
|
|
265
|
+
return this;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
function getParentRef(meta) {
|
|
269
|
+
if (!meta) return;
|
|
270
|
+
if (meta.parent?.ref) return meta.parent.ref;
|
|
271
|
+
return getParentRef(meta.parent?.meta);
|
|
272
|
+
}
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region src/generators/core/zod/getZodSchema.ts
|
|
275
|
+
/**
|
|
276
|
+
* @see https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schemaObject
|
|
277
|
+
* @see https://github.com/colinhacks/zod
|
|
278
|
+
*/
|
|
279
|
+
function getZodSchema({ schema, resolver, meta: inheritedMeta, tag }) {
|
|
280
|
+
const zodSchema = new ZodSchema(schema, resolver, inheritedMeta);
|
|
281
|
+
const meta = {
|
|
282
|
+
parent: zodSchema.inherit(inheritedMeta?.parent),
|
|
283
|
+
referencedBy: [...zodSchema.meta.referencedBy]
|
|
284
|
+
};
|
|
285
|
+
const params = {
|
|
286
|
+
resolver,
|
|
287
|
+
meta,
|
|
288
|
+
tag
|
|
289
|
+
};
|
|
290
|
+
if (isReferenceObject(schema)) return getReferenceZodSchema({
|
|
291
|
+
schema,
|
|
292
|
+
zodSchema,
|
|
293
|
+
resolver,
|
|
294
|
+
meta,
|
|
295
|
+
tag
|
|
296
|
+
});
|
|
297
|
+
const arrayZodSchema = getArrayZodSchema({
|
|
298
|
+
schema,
|
|
299
|
+
zodSchema,
|
|
300
|
+
resolver,
|
|
301
|
+
meta,
|
|
302
|
+
tag
|
|
303
|
+
});
|
|
304
|
+
if (arrayZodSchema) return arrayZodSchema;
|
|
305
|
+
const oneOfZodSchema = getOneOfZodSchema({
|
|
306
|
+
schema,
|
|
307
|
+
zodSchema,
|
|
308
|
+
resolver,
|
|
309
|
+
meta,
|
|
310
|
+
tag
|
|
311
|
+
});
|
|
312
|
+
if (oneOfZodSchema) return oneOfZodSchema;
|
|
313
|
+
const anyOfZodSchema = getAnyOfZodSchema({
|
|
314
|
+
schema,
|
|
315
|
+
zodSchema,
|
|
316
|
+
resolver,
|
|
317
|
+
meta,
|
|
318
|
+
tag
|
|
319
|
+
});
|
|
320
|
+
if (anyOfZodSchema) return anyOfZodSchema;
|
|
321
|
+
const allOfZodSchema = getAllOfZodSchema({
|
|
322
|
+
schema,
|
|
323
|
+
zodSchema,
|
|
324
|
+
resolver,
|
|
325
|
+
meta,
|
|
326
|
+
tag
|
|
327
|
+
});
|
|
328
|
+
if (allOfZodSchema) return allOfZodSchema;
|
|
329
|
+
const primitiveZodSchema = getPrimitiveZodSchema({
|
|
330
|
+
schema,
|
|
331
|
+
zodSchema,
|
|
332
|
+
resolver,
|
|
333
|
+
meta,
|
|
334
|
+
tag
|
|
335
|
+
});
|
|
336
|
+
if (primitiveZodSchema) return primitiveZodSchema;
|
|
337
|
+
const readonly = resolver.options.allReadonly ? ".readonly()" : "";
|
|
338
|
+
if (isArraySchemaObject(schema)) {
|
|
339
|
+
if (schema.items) return zodSchema.assign(`z.array(${getZodSchema({
|
|
340
|
+
...params,
|
|
341
|
+
schema: schema.items
|
|
342
|
+
}).getCodeString(tag, resolver.options)}${getZodChain({
|
|
343
|
+
schema: schema.items,
|
|
344
|
+
meta: {
|
|
345
|
+
...meta,
|
|
346
|
+
isRequired: true
|
|
347
|
+
},
|
|
348
|
+
options: resolver.options
|
|
349
|
+
})})${readonly}`);
|
|
350
|
+
return zodSchema.assign(`z.array(${ANY_SCHEMA})${readonly}`);
|
|
351
|
+
}
|
|
352
|
+
const schemaType = schema.type ? schema.type.toLowerCase() : void 0;
|
|
353
|
+
if (schemaType === "object" || schema.properties || schema.additionalProperties) {
|
|
354
|
+
const hasRequiredArray = schema.required && schema.required.length > 0;
|
|
355
|
+
const isPartial = resolver.options.withImplicitRequiredProps ? false : schema.properties && !schema.required?.length;
|
|
356
|
+
let properties = "{}";
|
|
357
|
+
if (schema.properties) properties = `{ ${Object.entries(schema.properties).map(([prop, propSchema]) => {
|
|
358
|
+
const propMetadata = {
|
|
359
|
+
...meta,
|
|
360
|
+
isRequired: isPartial ? true : hasRequiredArray ? schema.required?.includes(prop) : resolver.options.withImplicitRequiredProps,
|
|
361
|
+
name: prop,
|
|
362
|
+
isParentPartial: isPartial
|
|
363
|
+
};
|
|
364
|
+
let propActualSchema = propSchema;
|
|
365
|
+
if (isReferenceObject(propSchema) && resolver) {
|
|
366
|
+
propActualSchema = resolver.getSchemaByRef(propSchema.$ref);
|
|
367
|
+
if (!propActualSchema) throw new Error(`Schema ${propSchema.$ref} not found`);
|
|
368
|
+
}
|
|
369
|
+
const zodSchema = getZodSchema({
|
|
370
|
+
...params,
|
|
371
|
+
schema: propSchema,
|
|
372
|
+
meta: propMetadata
|
|
373
|
+
});
|
|
374
|
+
const propZodSchema = zodSchema.getCodeString(tag, resolver.options) + getZodChain({
|
|
375
|
+
schema: propActualSchema,
|
|
376
|
+
meta: propMetadata,
|
|
377
|
+
options: resolver.options
|
|
378
|
+
});
|
|
379
|
+
let isCircular = false;
|
|
380
|
+
const parentRef = getParentRef(inheritedMeta);
|
|
381
|
+
if (parentRef) isCircular = [...isReferenceObject(propSchema) ? [propSchema.$ref] : [], ...getSchemaRefs(zodSchema, { skipObjectSchema: true })].some((ref) => resolver.dependencyGraph.deepDependencyGraph[ref]?.has(parentRef));
|
|
382
|
+
return [
|
|
383
|
+
prop,
|
|
384
|
+
propZodSchema,
|
|
385
|
+
isCircular
|
|
386
|
+
];
|
|
387
|
+
}).map(([prop, propSchema, isCircular]) => isCircular ? `get ${wrapWithQuotesIfNeeded(prop)}() { return ${propSchema} }` : `${wrapWithQuotesIfNeeded(prop)}: ${propSchema}`).join(", ")} }`;
|
|
388
|
+
let additionalPropsSchema = "";
|
|
389
|
+
if (schema.additionalProperties) additionalPropsSchema = `.catchall(${typeof schema.additionalProperties === "object" && Object.keys(schema.additionalProperties).length > 0 ? getZodSchema({
|
|
390
|
+
...params,
|
|
391
|
+
schema: schema.additionalProperties
|
|
392
|
+
}).getCodeString(tag, resolver.options) + getZodChain({
|
|
393
|
+
schema: schema.additionalProperties,
|
|
394
|
+
meta: {
|
|
395
|
+
...meta,
|
|
396
|
+
isRequired: true
|
|
397
|
+
},
|
|
398
|
+
options: resolver.options
|
|
399
|
+
}) : ANY_SCHEMA})`;
|
|
400
|
+
const zodObject = `z.object(${properties})${isPartial ? ".partial()" : ""}${additionalPropsSchema}${readonly}`;
|
|
401
|
+
return zodSchema.assign(zodObject);
|
|
402
|
+
}
|
|
403
|
+
if (schemaType === "any") return zodSchema.assign(ANY_SCHEMA);
|
|
404
|
+
if (schemaType === "null") return zodSchema.assign("z.null()");
|
|
405
|
+
if (!schemaType) return zodSchema.assign("z.unknown()");
|
|
406
|
+
throw new Error(`Unsupported schema type: ${schemaType}`);
|
|
407
|
+
}
|
|
408
|
+
function getReferenceZodSchema({ schema, zodSchema, resolver, meta, tag }) {
|
|
409
|
+
if (!isReferenceObject(schema)) return;
|
|
410
|
+
const zodSchemaName = resolver.getZodSchemaNameByRef(schema.$ref);
|
|
411
|
+
if (zodSchema.meta.referencedBy.length > 2) {
|
|
412
|
+
const refsPath = zodSchema.meta.referencedBy.slice(0, -1).map((prev) => prev.ref ? resolver.getZodSchemaNameByRef(prev.ref) ?? prev.ref : void 0).filter(Boolean);
|
|
413
|
+
if (refsPath.length > 1 && refsPath.includes(zodSchemaName)) return zodSchema.assign(resolver.getCodeByZodSchemaName(zodSchema.ref));
|
|
414
|
+
}
|
|
415
|
+
let result = resolver.getCodeByZodSchemaName(schema.$ref);
|
|
416
|
+
if (!result) {
|
|
417
|
+
const actualSchema = resolver.getSchemaByRef(schema.$ref);
|
|
418
|
+
if (!actualSchema) throw new Error(`Schema ${schema.$ref} not found`);
|
|
419
|
+
result = getZodSchema({
|
|
420
|
+
schema: actualSchema,
|
|
421
|
+
resolver,
|
|
422
|
+
meta,
|
|
423
|
+
tag
|
|
424
|
+
}).getCodeString(tag, resolver.options);
|
|
425
|
+
}
|
|
426
|
+
if (resolver.getCodeByZodSchemaName(zodSchemaName)) return zodSchema;
|
|
427
|
+
resolver.setZodSchema(zodSchemaName, result, tag);
|
|
428
|
+
return zodSchema;
|
|
429
|
+
}
|
|
430
|
+
function getOneOfZodSchema({ schema, zodSchema, resolver, meta, tag }) {
|
|
431
|
+
if (!isSchemaObject(schema) || !schema.oneOf) return;
|
|
432
|
+
if (schema.oneOf.length === 1) {
|
|
433
|
+
const type = getZodSchema({
|
|
434
|
+
schema: schema.oneOf[0],
|
|
435
|
+
resolver,
|
|
436
|
+
meta,
|
|
437
|
+
tag
|
|
438
|
+
});
|
|
439
|
+
return zodSchema.assign(type.getCodeString(tag, resolver.options));
|
|
440
|
+
}
|
|
441
|
+
const hasMultipleAllOf = schema.oneOf?.some((obj) => isSchemaObject(obj) && (obj?.allOf || []).length > 1);
|
|
442
|
+
if (schema.discriminator && !hasMultipleAllOf) {
|
|
443
|
+
const propertyName = schema.discriminator.propertyName;
|
|
444
|
+
return zodSchema.assign(`
|
|
445
|
+
z.discriminatedUnion("${propertyName}", [${schema.oneOf.map((schema) => getZodSchema({
|
|
446
|
+
schema,
|
|
447
|
+
resolver,
|
|
448
|
+
meta,
|
|
449
|
+
tag
|
|
450
|
+
}).getCodeString(tag, resolver.options)).join(", ")}])
|
|
451
|
+
`);
|
|
452
|
+
}
|
|
453
|
+
return zodSchema.assign(`z.union([${schema.oneOf.map((schema) => getZodSchema({
|
|
454
|
+
schema,
|
|
455
|
+
resolver,
|
|
456
|
+
meta,
|
|
457
|
+
tag
|
|
458
|
+
}).getCodeString(tag, resolver.options)).join(", ")}])`);
|
|
459
|
+
}
|
|
460
|
+
function getArrayZodSchema({ schema, zodSchema, resolver, meta, tag }) {
|
|
461
|
+
if (!isSchemaObject(schema) || !Array.isArray(schema.type)) return;
|
|
462
|
+
if (schema.type.length === 1) return getZodSchema({
|
|
463
|
+
schema: {
|
|
464
|
+
...schema,
|
|
465
|
+
type: schema.type[0]
|
|
466
|
+
},
|
|
467
|
+
resolver,
|
|
468
|
+
meta,
|
|
469
|
+
tag
|
|
470
|
+
});
|
|
471
|
+
return zodSchema.assign(`z.union([${schema.type.map((prop) => getZodSchema({
|
|
472
|
+
schema: {
|
|
473
|
+
...schema,
|
|
474
|
+
type: prop
|
|
475
|
+
},
|
|
476
|
+
resolver,
|
|
477
|
+
meta,
|
|
478
|
+
tag
|
|
479
|
+
}).getCodeString(tag, resolver.options)).join(", ")}])`);
|
|
480
|
+
}
|
|
481
|
+
function getAnyOfZodSchema({ schema, zodSchema, resolver, meta, tag }) {
|
|
482
|
+
if (!isSchemaObject(schema) || !schema.anyOf) return;
|
|
483
|
+
if (schema.anyOf.length === 1) {
|
|
484
|
+
const type = getZodSchema({
|
|
485
|
+
schema: schema.anyOf[0],
|
|
486
|
+
resolver,
|
|
487
|
+
meta,
|
|
488
|
+
tag
|
|
489
|
+
});
|
|
490
|
+
return zodSchema.assign(type.getCodeString(tag, resolver.options));
|
|
491
|
+
}
|
|
492
|
+
const types = schema.anyOf.map((schema) => getZodSchema({
|
|
493
|
+
schema,
|
|
494
|
+
resolver,
|
|
495
|
+
meta,
|
|
496
|
+
tag
|
|
497
|
+
})).map((type) => type.getCodeString(tag, resolver.options)).join(", ");
|
|
498
|
+
return zodSchema.assign(`z.union([${types}])`);
|
|
499
|
+
}
|
|
500
|
+
function getAllOfZodSchema({ schema, zodSchema, resolver, meta, tag }) {
|
|
501
|
+
if (!isSchemaObject(schema) || !schema.allOf) return;
|
|
502
|
+
if (schema.allOf.length === 1) {
|
|
503
|
+
const type = getZodSchema({
|
|
504
|
+
schema: schema.allOf[0],
|
|
505
|
+
resolver,
|
|
506
|
+
meta,
|
|
507
|
+
tag
|
|
508
|
+
});
|
|
509
|
+
return zodSchema.assign(type.getCodeString(tag, resolver.options));
|
|
510
|
+
}
|
|
511
|
+
const { patchRequiredSchemaInLoop, noRequiredOnlyAllof, composedRequiredSchema } = inferRequiredSchema(schema);
|
|
512
|
+
const types = noRequiredOnlyAllof.map((schema) => {
|
|
513
|
+
const type = getZodSchema({
|
|
514
|
+
schema,
|
|
515
|
+
resolver,
|
|
516
|
+
meta,
|
|
517
|
+
tag
|
|
518
|
+
});
|
|
519
|
+
if (resolver) patchRequiredSchemaInLoop(schema, resolver.getSchemaByRef.bind(resolver));
|
|
520
|
+
return type;
|
|
521
|
+
});
|
|
522
|
+
if (composedRequiredSchema.required.length) types.push(getZodSchema({
|
|
523
|
+
schema: composedRequiredSchema,
|
|
524
|
+
resolver,
|
|
525
|
+
meta,
|
|
526
|
+
tag
|
|
527
|
+
}));
|
|
528
|
+
const first = types.at(0);
|
|
529
|
+
const rest = types.slice(1).map((type) => `...${type.getCodeString(tag, resolver.options)}.shape`).join(", ");
|
|
530
|
+
return zodSchema.assign(`z.object({ ...${first.getCodeString(tag, resolver.options)}.shape, ${rest} })`);
|
|
531
|
+
}
|
|
532
|
+
function getPrimitiveZodSchema({ schema, zodSchema, resolver, meta, tag }) {
|
|
533
|
+
if (!isSchemaObject(schema)) return;
|
|
534
|
+
const schemaType = schema.type ? schema.type.toLowerCase() : void 0;
|
|
535
|
+
if (schemaType && isPrimitiveType(schemaType)) {
|
|
536
|
+
if (schema.enum) {
|
|
537
|
+
if (schemaType === "string") return getEnumZodSchema({
|
|
538
|
+
schema,
|
|
539
|
+
zodSchema,
|
|
540
|
+
resolver,
|
|
541
|
+
meta,
|
|
542
|
+
tag
|
|
543
|
+
});
|
|
544
|
+
if (schema.enum.some((e) => typeof e === "string")) return zodSchema.assign("z.never()");
|
|
545
|
+
if (schema.enum.length === 1) {
|
|
546
|
+
const value = schema.enum[0];
|
|
547
|
+
return zodSchema.assign(`z.literal(${value === null ? "null" : value})`);
|
|
548
|
+
}
|
|
549
|
+
return zodSchema.assign(`z.union([${schema.enum.map((value) => `z.literal(${value === null ? "null" : value})`).join(", ")}])`);
|
|
550
|
+
}
|
|
551
|
+
if (schemaType === "integer") return zodSchema.assign(schema.type === "integer" ? INT_SCHEMA : NUMBER_SCHEMA);
|
|
552
|
+
if (schemaType === "string") {
|
|
553
|
+
let stringSchema = STRING_SCHEMA;
|
|
554
|
+
switch (schema.format) {
|
|
555
|
+
case "binary":
|
|
556
|
+
stringSchema = BLOB_SCHEMA;
|
|
557
|
+
break;
|
|
558
|
+
case "email":
|
|
559
|
+
stringSchema = EMAIL_SCHEMA;
|
|
560
|
+
break;
|
|
561
|
+
case "hostname":
|
|
562
|
+
case "uri":
|
|
563
|
+
stringSchema = URL_SCHEMA;
|
|
564
|
+
break;
|
|
565
|
+
case "uuid":
|
|
566
|
+
stringSchema = UUID_SCHEMA;
|
|
567
|
+
break;
|
|
568
|
+
case "date-time": stringSchema = DATETIME_SCHEMA;
|
|
569
|
+
}
|
|
570
|
+
return zodSchema.assign(stringSchema);
|
|
571
|
+
}
|
|
572
|
+
return zodSchema.assign(`z.${schemaType}()`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function getEnumZodSchema({ resolver, schema, zodSchema, meta, tag }) {
|
|
576
|
+
if (!isSchemaObject(schema)) return;
|
|
577
|
+
const code = getEnumZodSchemaCode(schema);
|
|
578
|
+
if (!resolver.options.extractEnums) return zodSchema.assign(code);
|
|
579
|
+
const enumZodSchema = resolver.getEnumZodSchemaDataByCode(code);
|
|
580
|
+
if (enumZodSchema) {
|
|
581
|
+
if (zodSchema.meta.parent?.ref === resolver.getRefByZodSchemaName(enumZodSchema.zodSchemaName)) return zodSchema.assign(enumZodSchema.code);
|
|
582
|
+
return new ZodSchema({ $ref: resolver.getRefByZodSchemaName(enumZodSchema.zodSchemaName) }, resolver, meta).inherit(zodSchema).assign(code);
|
|
583
|
+
}
|
|
584
|
+
const extractedEnumZodSchema = resolver.getExtractedEnumZodSchemaDataByCode(code);
|
|
585
|
+
if (!extractedEnumZodSchema) return zodSchema.assign(code);
|
|
586
|
+
if (!extractedEnumZodSchema.zodSchemaName || !extractedEnumZodSchema.tag) throw new Error(`Enum zod schema name or tag not resolved for code: ${code}`);
|
|
587
|
+
const namespacePrefix = resolver.options.tsNamespaces && extractedEnumZodSchema.tag !== tag ? `${getNamespaceName({
|
|
588
|
+
type: "models",
|
|
589
|
+
tag: extractedEnumZodSchema.tag,
|
|
590
|
+
options: resolver.options
|
|
591
|
+
})}.` : "";
|
|
592
|
+
return zodSchema.assign(`${namespacePrefix}${extractedEnumZodSchema.zodSchemaName}`);
|
|
593
|
+
}
|
|
594
|
+
function getEnumZodSchemaCode(schema) {
|
|
595
|
+
return `${ENUM_SCHEMA}([${schema.enum?.map((value) => value === null ? "null" : `"${value}"`).join(", ")}])`;
|
|
596
|
+
}
|
|
597
|
+
function getEnumZodSchemaCodeFromEnumNames(enumNames) {
|
|
598
|
+
return `${ENUM_SCHEMA}([${enumNames.map((value) => `"${value}"`).join(", ")}])`;
|
|
599
|
+
}
|
|
600
|
+
//#endregion
|
|
601
|
+
//#region src/generators/core/zod/resolveZodSchemaName.ts
|
|
602
|
+
const resolverResolveZodSchemaNameCache = /* @__PURE__ */ new WeakMap();
|
|
603
|
+
function resolveZodSchemaName({ schema, zodSchema, fallbackName, resolver, tag }) {
|
|
604
|
+
const result = zodSchema.getCodeString();
|
|
605
|
+
const cacheKey = `${zodSchema.ref ?? ""}|${fallbackName ?? ""}|${tag}|${zodSchema.complexity}|${result}`;
|
|
606
|
+
let cacheForResolver = resolverResolveZodSchemaNameCache.get(resolver);
|
|
607
|
+
if (!cacheForResolver) {
|
|
608
|
+
cacheForResolver = /* @__PURE__ */ new Map();
|
|
609
|
+
resolverResolveZodSchemaNameCache.set(resolver, cacheForResolver);
|
|
610
|
+
}
|
|
611
|
+
const cachedName = cacheForResolver.get(cacheKey);
|
|
612
|
+
if (cachedName) return cachedName;
|
|
613
|
+
if ((!isNamedZodSchema(result) || zodSchema.ref === void 0) && fallbackName) {
|
|
614
|
+
if (zodSchema.complexity < 2) return result;
|
|
615
|
+
const zodSchemaName = getZodSchemaName(fallbackName, resolver.options.schemaSuffix);
|
|
616
|
+
while (resolver.getCodeByZodSchemaName(zodSchemaName)) if (resolver.getZodSchemaNamesByCompositeCode(result)?.includes(zodSchemaName)) return zodSchemaName;
|
|
617
|
+
else if (resolver.getCodeByZodSchemaName(zodSchemaName) === zodSchemaName) return zodSchemaName;
|
|
618
|
+
else throw new Error(`Can't uniquely resolve zod schema name: ${zodSchemaName}`);
|
|
619
|
+
resolver.setZodSchema(zodSchemaName, result, tag);
|
|
620
|
+
resolver.addZodSchemaForCompositeCode(result, zodSchema, zodSchemaName, schema);
|
|
621
|
+
cacheForResolver.set(cacheKey, zodSchemaName);
|
|
622
|
+
return zodSchemaName;
|
|
623
|
+
}
|
|
624
|
+
let resolvedSchema = resolver.getCodeByZodSchemaName(result);
|
|
625
|
+
if (!resolvedSchema && zodSchema.ref) resolvedSchema = resolver.getCodeByZodSchemaName(resolver.getZodSchemaNameByRef(zodSchema.ref));
|
|
626
|
+
if (zodSchema.ref && resolvedSchema) {
|
|
627
|
+
if (getOpenAPISchemaComplexity(0, resolver.getSchemaByRef(zodSchema.ref)) < 2) {
|
|
628
|
+
const resolvedName = resolver.getCodeByZodSchemaName(result);
|
|
629
|
+
cacheForResolver.set(cacheKey, resolvedName);
|
|
630
|
+
return resolvedName;
|
|
631
|
+
}
|
|
632
|
+
cacheForResolver.set(cacheKey, result);
|
|
633
|
+
return result;
|
|
634
|
+
}
|
|
635
|
+
if (zodSchema.ref) {
|
|
636
|
+
const resolvedRefName = resolver.getZodSchemaNameByRef(zodSchema.ref);
|
|
637
|
+
cacheForResolver.set(cacheKey, resolvedRefName);
|
|
638
|
+
return resolvedRefName;
|
|
639
|
+
}
|
|
640
|
+
throw new Error(`Invalid ref: ${zodSchema.ref}`);
|
|
641
|
+
}
|
|
642
|
+
//#endregion
|
|
643
|
+
//#region src/generators/utils/validation.utils.ts
|
|
644
|
+
function getInvalidSchemaError(message) {
|
|
645
|
+
return {
|
|
646
|
+
type: "invalid-schema",
|
|
647
|
+
message
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function getInvalidOperationIdError(operationId) {
|
|
651
|
+
return {
|
|
652
|
+
type: "invalid-operation-id",
|
|
653
|
+
message: `Operation ${operationId}`
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
function getMissingPathParameterError(params, path) {
|
|
657
|
+
return {
|
|
658
|
+
type: "missing-path-parameter",
|
|
659
|
+
message: `Path ${path} is missing [${params.map(({ name }) => name).join(", ")}]`
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
function getNotAllowedInlineEnumError(enumProperty) {
|
|
663
|
+
return {
|
|
664
|
+
type: "not-allowed-inline-enum",
|
|
665
|
+
message: `${enumProperty} is missing @IsEnum() and @ApiProperty(enum:, enumName:)`
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
function getMissingAclConditionPropertyError(propertyName, operation, endpoint) {
|
|
669
|
+
return {
|
|
670
|
+
type: "missing-acl-condition-property",
|
|
671
|
+
message: `Condition property ${propertyName} is not found in parameters or body in operation ${getOperationDescriptor(operation, endpoint)}`
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
function getMissingStatusCodeError(statusCode, operation, endpoint) {
|
|
675
|
+
return {
|
|
676
|
+
type: "missing-status-code",
|
|
677
|
+
message: `Missing HTTP status code ${getStatusCodeDescription(statusCode)} in operation ${getOperationDescriptor(operation, endpoint)}`
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
function getInvalidStatusCodeError(statusCode, operation, endpoint) {
|
|
681
|
+
return {
|
|
682
|
+
type: "invalid-status-code",
|
|
683
|
+
message: `Operation ${getOperationDescriptor(operation, endpoint)} expected HTTP status code ${getStatusCodeDescription(statusCode.expected)} but received ${getStatusCodeDescription(statusCode.received)}`
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function getMultipleSuccessStatusCodesError(statusCodes, operation, endpoint) {
|
|
687
|
+
return {
|
|
688
|
+
type: "multiple-success-status-codes",
|
|
689
|
+
message: `Operation ${getOperationDescriptor(operation, endpoint)} has multiple success HTTP status codes: ${statusCodes.map(getStatusCodeDescription).join(", ")}`
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
function getOperationDescriptor(operation, endpoint) {
|
|
693
|
+
return operation.operationId ?? `${endpoint.method} ${endpoint.path}`;
|
|
694
|
+
}
|
|
695
|
+
function getStatusCodeDescription(statusCode) {
|
|
696
|
+
return `${statusCode} (${HTTP_STATUS_CODES[statusCode]})`;
|
|
697
|
+
}
|
|
698
|
+
function groupByType(validationErrors) {
|
|
699
|
+
return validationErrors.reduce((acc, err) => ({
|
|
700
|
+
...acc,
|
|
701
|
+
[err.type]: [...acc[err.type] ?? [], err.message]
|
|
702
|
+
}), {});
|
|
703
|
+
}
|
|
704
|
+
//#endregion
|
|
705
|
+
//#region src/generators/core/endpoints/getEndpointAcl.ts
|
|
706
|
+
function getEndpointAcl({ resolver, endpoint, operation }) {
|
|
707
|
+
const acl = operation["x-acl"];
|
|
708
|
+
return acl?.map((item) => {
|
|
709
|
+
const conditionsTypes = Object.keys(item.conditions ?? {}).reduce((acc, name) => {
|
|
710
|
+
const propertyType = getEndpointAclConditionPropertyType({
|
|
711
|
+
resolver,
|
|
712
|
+
endpoint,
|
|
713
|
+
acl,
|
|
714
|
+
name
|
|
715
|
+
});
|
|
716
|
+
if (!propertyType) {
|
|
717
|
+
resolver.validationErrors.push(getMissingAclConditionPropertyError(name, operation, endpoint));
|
|
718
|
+
return acc;
|
|
719
|
+
}
|
|
720
|
+
return [...acc, propertyType];
|
|
721
|
+
}, []);
|
|
722
|
+
return {
|
|
723
|
+
...item,
|
|
724
|
+
conditionsTypes
|
|
725
|
+
};
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
function getEndpointAclConditionPropertyType({ resolver, endpoint, acl, name }) {
|
|
729
|
+
const conditionPropertyPath = acl[0]?.conditions?.[name];
|
|
730
|
+
if (!conditionPropertyPath) return;
|
|
731
|
+
const pathSplits = conditionPropertyPath.replace(/^\$[^.]*\./, "").split(".");
|
|
732
|
+
let schema = void 0;
|
|
733
|
+
let required = void 0;
|
|
734
|
+
let info = void 0;
|
|
735
|
+
let index = 0;
|
|
736
|
+
const parameter = endpoint.parameters.find(({ name }) => name === pathSplits[index]);
|
|
737
|
+
if (parameter) {
|
|
738
|
+
required = parameter.parameterObject?.required;
|
|
739
|
+
schema = parameter.parameterObject?.schema;
|
|
740
|
+
info = `${parameter.name} ${decapitalize(parameter.type)} parameter`;
|
|
741
|
+
index++;
|
|
742
|
+
} else {
|
|
743
|
+
const bodyParameter = endpoint.parameters.find(({ bodyObject }) => !!bodyObject);
|
|
744
|
+
const matchingMediaType = Object.keys(bodyParameter?.bodyObject?.content ?? {}).find(isParamMediaTypeAllowed);
|
|
745
|
+
if (matchingMediaType) {
|
|
746
|
+
schema = bodyParameter?.bodyObject?.content?.[matchingMediaType]?.schema;
|
|
747
|
+
required = bodyParameter?.bodyObject?.required;
|
|
748
|
+
info = `${isQuery(endpoint) ? "query" : "mutation"} data`;
|
|
749
|
+
if (pathSplits[index]?.startsWith("$")) index++;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
while (schema && index < pathSplits.length) {
|
|
753
|
+
const resolvedSchema = resolver.resolveObject(schema);
|
|
754
|
+
schema = Object.entries(resolvedSchema.properties ?? {}).find(([key]) => key === pathSplits[index])?.[1];
|
|
755
|
+
required = resolvedSchema.required?.includes(pathSplits[index]) ?? false;
|
|
756
|
+
index++;
|
|
757
|
+
}
|
|
758
|
+
if (!schema) return;
|
|
759
|
+
return {
|
|
760
|
+
name,
|
|
761
|
+
type: isReferenceObject(schema) ? void 0 : schema.type,
|
|
762
|
+
zodSchemaName: isReferenceObject(schema) ? resolver.getZodSchemaNameByRef(schema.$ref) : void 0,
|
|
763
|
+
required,
|
|
764
|
+
info
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
//#endregion
|
|
768
|
+
//#region src/generators/core/endpoints/resolveEndpointZodSchema.ts
|
|
769
|
+
const resolverEndpointZodSchemaCache = /* @__PURE__ */ new WeakMap();
|
|
770
|
+
function getResolverSchemaCache(resolver) {
|
|
771
|
+
let schemaCache = resolverEndpointZodSchemaCache.get(resolver);
|
|
772
|
+
if (!schemaCache) {
|
|
773
|
+
schemaCache = {
|
|
774
|
+
byObject: /* @__PURE__ */ new WeakMap(),
|
|
775
|
+
byRef: /* @__PURE__ */ new Map()
|
|
776
|
+
};
|
|
777
|
+
resolverEndpointZodSchemaCache.set(resolver, schemaCache);
|
|
778
|
+
}
|
|
779
|
+
return schemaCache;
|
|
780
|
+
}
|
|
781
|
+
function getOrCreateSchemaEntries(schemaCache, schema) {
|
|
782
|
+
if (isReferenceObject(schema)) {
|
|
783
|
+
let entries = schemaCache.byRef.get(schema.$ref);
|
|
784
|
+
if (!entries) {
|
|
785
|
+
entries = /* @__PURE__ */ new Map();
|
|
786
|
+
schemaCache.byRef.set(schema.$ref, entries);
|
|
787
|
+
}
|
|
788
|
+
return entries;
|
|
789
|
+
}
|
|
790
|
+
let entries = schemaCache.byObject.get(schema);
|
|
791
|
+
if (!entries) {
|
|
792
|
+
entries = /* @__PURE__ */ new Map();
|
|
793
|
+
schemaCache.byObject.set(schema, entries);
|
|
794
|
+
}
|
|
795
|
+
return entries;
|
|
796
|
+
}
|
|
797
|
+
function resolveEndpointZodSchema({ resolver, schema, meta, tag, fallbackName, composeBeforeResolve }) {
|
|
798
|
+
const entries = getOrCreateSchemaEntries(getResolverSchemaCache(resolver), schema);
|
|
799
|
+
const isRefSchema = isReferenceObject(schema);
|
|
800
|
+
const normalizedFallbackName = isRefSchema ? "" : fallbackName ?? "";
|
|
801
|
+
const normalizedTag = isRefSchema ? "" : tag;
|
|
802
|
+
const metaKey = `required:${Boolean(meta.isRequired)}|name:${meta.name ?? ""}|parentPartial:${Boolean(meta.isParentPartial)}|fallback:${normalizedFallbackName}|tag:${normalizedTag}|compose:${composeBeforeResolve ? 1 : 0}`;
|
|
803
|
+
const cached = entries.get(metaKey);
|
|
804
|
+
if (cached) return cached;
|
|
805
|
+
const zodSchema = getZodSchema({
|
|
806
|
+
schema,
|
|
807
|
+
resolver,
|
|
808
|
+
meta,
|
|
809
|
+
tag
|
|
810
|
+
});
|
|
811
|
+
const schemaObject = resolver.resolveObject(schema);
|
|
812
|
+
const zodChain = getZodChain({
|
|
813
|
+
schema: schemaObject,
|
|
814
|
+
meta: zodSchema.meta,
|
|
815
|
+
options: resolver.options
|
|
816
|
+
});
|
|
817
|
+
const resolved = composeBeforeResolve ? resolveZodSchemaName({
|
|
818
|
+
schema: schemaObject,
|
|
819
|
+
zodSchema: zodSchema.assign(zodSchema.getCodeString(tag) + zodChain),
|
|
820
|
+
fallbackName,
|
|
821
|
+
resolver,
|
|
822
|
+
tag
|
|
823
|
+
}) : (() => {
|
|
824
|
+
const name = resolveZodSchemaName({
|
|
825
|
+
schema: schemaObject,
|
|
826
|
+
zodSchema,
|
|
827
|
+
fallbackName,
|
|
828
|
+
resolver,
|
|
829
|
+
tag
|
|
830
|
+
});
|
|
831
|
+
return isNamedZodSchema(name) ? name : name + zodChain;
|
|
832
|
+
})();
|
|
833
|
+
entries.set(metaKey, resolved);
|
|
834
|
+
return resolved;
|
|
835
|
+
}
|
|
836
|
+
//#endregion
|
|
837
|
+
//#region src/generators/core/endpoints/getEndpointBody.ts
|
|
838
|
+
function getEndpointBody({ resolver, operation, operationName, isUniqueOperationName, tag }) {
|
|
839
|
+
const requestBodyObj = resolver.resolveObject(operation.requestBody);
|
|
840
|
+
if (!requestBodyObj) return;
|
|
841
|
+
const matchingMediaType = Object.keys(requestBodyObj.content ?? {}).find(isParamMediaTypeAllowed);
|
|
842
|
+
if (!matchingMediaType) return;
|
|
843
|
+
const schema = requestBodyObj.content?.[matchingMediaType]?.schema;
|
|
844
|
+
if (!schema) return;
|
|
845
|
+
const zodSchema = resolveEndpointZodSchema({
|
|
846
|
+
resolver,
|
|
847
|
+
schema,
|
|
848
|
+
meta: { isRequired: requestBodyObj.required ?? true },
|
|
849
|
+
tag,
|
|
850
|
+
fallbackName: getBodyZodSchemaName(getZodSchemaOperationName(operationName, isUniqueOperationName, tag)),
|
|
851
|
+
composeBeforeResolve: false
|
|
852
|
+
});
|
|
853
|
+
return {
|
|
854
|
+
endpointParameter: {
|
|
855
|
+
name: BODY_PARAMETER_NAME,
|
|
856
|
+
type: "Body",
|
|
857
|
+
description: requestBodyObj.description,
|
|
858
|
+
zodSchema,
|
|
859
|
+
bodyObject: requestBodyObj
|
|
860
|
+
},
|
|
861
|
+
requestFormat: matchingMediaType
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
//#endregion
|
|
865
|
+
//#region src/generators/core/endpoints/getEndpointParameter.ts
|
|
866
|
+
function getEndpointParameter({ resolver, param, operationName, isUniqueOperationName, tag }) {
|
|
867
|
+
const paramObj = resolver.resolveObject(param);
|
|
868
|
+
if (!ALLOWED_PATH_IN.includes(paramObj.in)) return;
|
|
869
|
+
let schema = {};
|
|
870
|
+
if (paramObj.content) {
|
|
871
|
+
const mediaTypes = Object.keys(paramObj.content ?? {});
|
|
872
|
+
const matchingMediaType = mediaTypes.find(isParamMediaTypeAllowed);
|
|
873
|
+
if (!matchingMediaType) throw new Error(`Unsupported media type for param ${paramObj.name}: ${mediaTypes.join(", ")}`);
|
|
874
|
+
const mediaTypeObject = paramObj.content?.[matchingMediaType];
|
|
875
|
+
if (!mediaTypeObject) throw new Error(`No content with media type for param ${paramObj.name}: ${matchingMediaType}`);
|
|
876
|
+
schema = mediaTypeObject?.schema ?? mediaTypeObject;
|
|
877
|
+
} else if (paramObj.schema) schema = paramObj.schema;
|
|
878
|
+
if (resolver.options.withDescription && schema) schema.description = (paramObj.description ?? "").trim();
|
|
879
|
+
const fallbackName = getParamZodSchemaName(getZodSchemaOperationName(operationName, isUniqueOperationName, tag), paramObj.name);
|
|
880
|
+
let parameterSortingEnumSchemaName = void 0;
|
|
881
|
+
if (isSortingParameterObject(paramObj, schema, resolver)) {
|
|
882
|
+
const enumZodSchemaName = getEnumZodSchemaName(fallbackName, resolver.options.enumSuffix, resolver.options.schemaSuffix);
|
|
883
|
+
const code = getEnumZodSchemaCodeFromEnumNames(getParameterEnumNames(paramObj, schema) ?? []);
|
|
884
|
+
resolver.setZodSchema(enumZodSchemaName, code, tag);
|
|
885
|
+
parameterSortingEnumSchemaName = enumZodSchemaName;
|
|
886
|
+
}
|
|
887
|
+
const zodSchema = getZodSchema({
|
|
888
|
+
schema,
|
|
889
|
+
resolver,
|
|
890
|
+
meta: { isRequired: paramObj.in === "path" ? true : paramObj.required ?? false },
|
|
891
|
+
tag
|
|
892
|
+
});
|
|
893
|
+
const schemaObject = resolver.resolveObject(schema);
|
|
894
|
+
const zodChain = getZodChain({
|
|
895
|
+
schema: schemaObject,
|
|
896
|
+
meta: (paramObj.in === "query" || paramObj.in === "header") && !paramObj.required && isSchemaObject(schemaObject) && (schemaObject.type === "object" || !!schemaObject.properties && Object.keys(schemaObject.properties).length > 0) ? {
|
|
897
|
+
...zodSchema.meta,
|
|
898
|
+
isRequired: true
|
|
899
|
+
} : zodSchema.meta,
|
|
900
|
+
options: resolver.options
|
|
901
|
+
});
|
|
902
|
+
const zodSchemaName = resolveZodSchemaName({
|
|
903
|
+
schema: schemaObject,
|
|
904
|
+
zodSchema: zodSchema.assign(zodSchema.getCodeString(tag) + zodChain),
|
|
905
|
+
fallbackName,
|
|
906
|
+
resolver,
|
|
907
|
+
tag
|
|
908
|
+
});
|
|
909
|
+
return {
|
|
910
|
+
name: paramObj.in === "path" ? pathParamToVariableName(paramObj.name) : paramObj.name,
|
|
911
|
+
type: paramObj.in === "header" ? "Header" : paramObj.in === "query" ? "Query" : "Path",
|
|
912
|
+
zodSchema: zodSchemaName,
|
|
913
|
+
parameterObject: paramObj,
|
|
914
|
+
...parameterSortingEnumSchemaName !== void 0 ? { parameterSortingEnumSchemaName } : {}
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
//#endregion
|
|
918
|
+
//#region src/generators/core/endpoints/getEndpointsFromOpenAPIDoc.ts
|
|
919
|
+
function getEndpointsFromOpenAPIDoc(resolver, profiler = new Profiler(false)) {
|
|
920
|
+
const endpoints = [];
|
|
921
|
+
const responseSchemaByRefAndTag = /* @__PURE__ */ new Map();
|
|
922
|
+
for (const context of resolver.getOperationContexts()) {
|
|
923
|
+
const { path, method, operation, operationName, isUniqueOperationName, tag, parameters, responses } = context;
|
|
924
|
+
const invalidOperationId = operation.operationId && operation.operationId !== invalidVariableNameCharactersToCamel(operation.operationId);
|
|
925
|
+
if (operation.operationId && invalidOperationId) resolver.validationErrors.push(getInvalidOperationIdError(operation.operationId));
|
|
926
|
+
const endpoint = {
|
|
927
|
+
method,
|
|
928
|
+
path: replaceHyphenatedPath(path),
|
|
929
|
+
operationName,
|
|
930
|
+
description: operation.description,
|
|
931
|
+
summary: operation.summary,
|
|
932
|
+
tags: operation.tags?.map(formatTag),
|
|
933
|
+
requestFormat: JSON_APPLICATION_FORMAT,
|
|
934
|
+
parameters: [],
|
|
935
|
+
response: "",
|
|
936
|
+
errors: [],
|
|
937
|
+
responseStatusCodes: [],
|
|
938
|
+
mediaUpload: !!operation["x-media-upload"],
|
|
939
|
+
mediaDownload: !!operation["x-media-download"]
|
|
940
|
+
};
|
|
941
|
+
if (operation.requestBody) {
|
|
942
|
+
const body = profiler.runSync("endpoints.body", () => getEndpointBody({
|
|
943
|
+
resolver,
|
|
944
|
+
operation,
|
|
945
|
+
operationName,
|
|
946
|
+
isUniqueOperationName,
|
|
947
|
+
tag
|
|
948
|
+
}));
|
|
949
|
+
if (body) {
|
|
950
|
+
endpoint.parameters.push(body.endpointParameter);
|
|
951
|
+
endpoint.requestFormat = body.requestFormat;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
for (const param of parameters) {
|
|
955
|
+
const endpointParameter = profiler.runSync("endpoints.parameter", () => getEndpointParameter({
|
|
956
|
+
resolver,
|
|
957
|
+
param,
|
|
958
|
+
operationName,
|
|
959
|
+
isUniqueOperationName,
|
|
960
|
+
tag
|
|
961
|
+
}));
|
|
962
|
+
if (endpointParameter) endpoint.parameters.push(endpointParameter);
|
|
963
|
+
}
|
|
964
|
+
const missingPathParameters = getMissingPathParameters(endpoint.path, endpoint.parameters);
|
|
965
|
+
endpoint.parameters.push(...missingPathParameters);
|
|
966
|
+
if (missingPathParameters.length > 0) resolver.validationErrors.push(getMissingPathParameterError(missingPathParameters, path));
|
|
967
|
+
for (const { statusCode, responseObj, matchingMediaType, schema } of responses) {
|
|
968
|
+
endpoint.responseStatusCodes.push(statusCode);
|
|
969
|
+
if (matchingMediaType) {
|
|
970
|
+
const statusNum = Number(statusCode);
|
|
971
|
+
if (isMainResponseStatus(statusNum) || statusCode === "default" && !endpoint.responseFormat) endpoint.responseFormat = matchingMediaType;
|
|
972
|
+
} else if (statusCode === "200") resolver.validationErrors.push(getInvalidStatusCodeError({
|
|
973
|
+
received: "200",
|
|
974
|
+
expected: "204"
|
|
975
|
+
}, operation, endpoint));
|
|
976
|
+
if (schema) {
|
|
977
|
+
const responseCacheKey = isReferenceObject(schema) ? `${schema.$ref}|${tag}` : void 0;
|
|
978
|
+
let resolvedResponse = responseCacheKey ? responseSchemaByRefAndTag.get(responseCacheKey) : void 0;
|
|
979
|
+
if (!resolvedResponse) {
|
|
980
|
+
const zodSchema = profiler.runSync("endpoints.response.zod", () => getZodSchema({
|
|
981
|
+
schema,
|
|
982
|
+
resolver,
|
|
983
|
+
meta: { isRequired: true },
|
|
984
|
+
tag
|
|
985
|
+
}));
|
|
986
|
+
const schemaObject = resolver.resolveObject(schema);
|
|
987
|
+
resolvedResponse = {
|
|
988
|
+
schemaObject,
|
|
989
|
+
responseZodSchema: resolveZodSchemaName({
|
|
990
|
+
schema: schemaObject,
|
|
991
|
+
zodSchema,
|
|
992
|
+
fallbackName: zodSchema.ref ? void 0 : getResponseZodSchemaName({
|
|
993
|
+
statusCode,
|
|
994
|
+
operationName,
|
|
995
|
+
isUniqueOperationName,
|
|
996
|
+
tag
|
|
997
|
+
}),
|
|
998
|
+
resolver,
|
|
999
|
+
tag
|
|
1000
|
+
}) + getZodChain({
|
|
1001
|
+
schema: schemaObject,
|
|
1002
|
+
meta: zodSchema.meta,
|
|
1003
|
+
options: resolver.options
|
|
1004
|
+
})
|
|
1005
|
+
};
|
|
1006
|
+
if (responseCacheKey) responseSchemaByRefAndTag.set(responseCacheKey, resolvedResponse);
|
|
1007
|
+
}
|
|
1008
|
+
const { schemaObject, responseZodSchema } = resolvedResponse;
|
|
1009
|
+
const status = Number(statusCode);
|
|
1010
|
+
if (isMainResponseStatus(status) && !endpoint.response) {
|
|
1011
|
+
endpoint.response = responseZodSchema;
|
|
1012
|
+
endpoint.responseObject = responseObj;
|
|
1013
|
+
endpoint.responseDescription = responseObj?.description;
|
|
1014
|
+
} else if (statusCode === "default" && !endpoint.response) {
|
|
1015
|
+
endpoint.response = responseZodSchema;
|
|
1016
|
+
endpoint.responseObject = responseObj;
|
|
1017
|
+
endpoint.responseDescription = responseObj?.description;
|
|
1018
|
+
} else if (statusCode !== "default" && !Number.isNaN(status) && isErrorStatus(status)) {
|
|
1019
|
+
const rawSchema = schemaObject;
|
|
1020
|
+
const domainStr = rawSchema["x-domain-error-domain"];
|
|
1021
|
+
const domainName = rawSchema["x-domain-error-name"];
|
|
1022
|
+
const codeEnumArr = ((rawSchema?.properties)?.code)?.enum;
|
|
1023
|
+
const domainCode = Array.isArray(codeEnumArr) && codeEnumArr.length === 1 && (typeof codeEnumArr[0] === "number" || typeof codeEnumArr[0] === "string") ? codeEnumArr[0] : void 0;
|
|
1024
|
+
endpoint.errors.push({
|
|
1025
|
+
zodSchema: responseZodSchema,
|
|
1026
|
+
status,
|
|
1027
|
+
description: responseObj?.description,
|
|
1028
|
+
...typeof domainStr === "string" && domainCode !== void 0 ? { domainError: {
|
|
1029
|
+
domain: domainStr,
|
|
1030
|
+
code: domainCode,
|
|
1031
|
+
...typeof domainName === "string" ? { name: domainName } : {}
|
|
1032
|
+
} } : {}
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
} else {
|
|
1036
|
+
const status = Number(statusCode);
|
|
1037
|
+
const responseZodSchema = VOID_SCHEMA;
|
|
1038
|
+
if (statusCode !== "default" && !Number.isNaN(status) && isErrorStatus(status)) endpoint.errors.push({
|
|
1039
|
+
zodSchema: responseZodSchema,
|
|
1040
|
+
status,
|
|
1041
|
+
description: responseObj?.description
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
if (!endpoint.response) endpoint.response = VOID_SCHEMA;
|
|
1046
|
+
const mainStatusCodes = [];
|
|
1047
|
+
for (const { statusCode } of responses) {
|
|
1048
|
+
const status = Number(statusCode);
|
|
1049
|
+
if (isMainResponseStatus(status)) mainStatusCodes.push(status);
|
|
1050
|
+
}
|
|
1051
|
+
if (mainStatusCodes.length > 1) resolver.validationErrors.push(getMultipleSuccessStatusCodesError(mainStatusCodes.map(String), operation, endpoint));
|
|
1052
|
+
const resolvedAcl = getEndpointAcl({
|
|
1053
|
+
resolver,
|
|
1054
|
+
endpoint,
|
|
1055
|
+
operation
|
|
1056
|
+
});
|
|
1057
|
+
if (resolvedAcl?.length) endpoint.acl = resolvedAcl;
|
|
1058
|
+
if (operation.security?.[0].Authorization && !endpoint.responseStatusCodes.includes("401")) resolver.validationErrors.push(getMissingStatusCodeError("401", operation, endpoint));
|
|
1059
|
+
if (endpoint.acl?.[0] && !endpoint.responseStatusCodes.includes("403")) resolver.validationErrors.push(getMissingStatusCodeError("403", operation, endpoint));
|
|
1060
|
+
endpoints.push(endpoint);
|
|
1061
|
+
}
|
|
1062
|
+
return endpoints;
|
|
1063
|
+
}
|
|
1064
|
+
function getMissingPathParameters(path, parameters) {
|
|
1065
|
+
if (!path.includes(":")) return [];
|
|
1066
|
+
const parameterNames = new Set(parameters.map(({ name }) => name));
|
|
1067
|
+
const missingParameters = [];
|
|
1068
|
+
for (const match of path.matchAll(/:([a-zA-Z0-9_]+)/g)) {
|
|
1069
|
+
const name = match[1];
|
|
1070
|
+
if (name && !parameterNames.has(name)) missingParameters.push(getPathParameterFromName(name));
|
|
1071
|
+
}
|
|
1072
|
+
return missingParameters;
|
|
1073
|
+
}
|
|
1074
|
+
function getPathParameterFromName(name) {
|
|
1075
|
+
return {
|
|
1076
|
+
name,
|
|
1077
|
+
type: "Path",
|
|
1078
|
+
zodSchema: STRING_SCHEMA,
|
|
1079
|
+
parameterObject: {
|
|
1080
|
+
name,
|
|
1081
|
+
required: true,
|
|
1082
|
+
in: "path",
|
|
1083
|
+
schema: { type: "string" }
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
//#endregion
|
|
1088
|
+
//#region src/generators/const/js.const.ts
|
|
1089
|
+
const RESERVED_WORDS = [
|
|
1090
|
+
"break",
|
|
1091
|
+
"case",
|
|
1092
|
+
"catch",
|
|
1093
|
+
"class",
|
|
1094
|
+
"const",
|
|
1095
|
+
"continue",
|
|
1096
|
+
"debugger",
|
|
1097
|
+
"default",
|
|
1098
|
+
"delete",
|
|
1099
|
+
"do",
|
|
1100
|
+
"else",
|
|
1101
|
+
"export",
|
|
1102
|
+
"extends",
|
|
1103
|
+
"false",
|
|
1104
|
+
"finally",
|
|
1105
|
+
"for",
|
|
1106
|
+
"function",
|
|
1107
|
+
"if",
|
|
1108
|
+
"import",
|
|
1109
|
+
"in",
|
|
1110
|
+
"instanceof",
|
|
1111
|
+
"new",
|
|
1112
|
+
"null",
|
|
1113
|
+
"return",
|
|
1114
|
+
"super",
|
|
1115
|
+
"switch",
|
|
1116
|
+
"this",
|
|
1117
|
+
"throw",
|
|
1118
|
+
"true",
|
|
1119
|
+
"try",
|
|
1120
|
+
"typeof",
|
|
1121
|
+
"var",
|
|
1122
|
+
"void",
|
|
1123
|
+
"while",
|
|
1124
|
+
"with"
|
|
1125
|
+
];
|
|
1126
|
+
//#endregion
|
|
1127
|
+
//#region src/generators/utils/operation.utils.ts
|
|
1128
|
+
function isOperationExcluded(operation, options) {
|
|
1129
|
+
const isDeprecated = operation.deprecated && !options.withDeprecatedEndpoints;
|
|
1130
|
+
const tag = getOperationTag(operation, options);
|
|
1131
|
+
const isIncluded = isTagIncluded(tag, options);
|
|
1132
|
+
return isDeprecated || !isIncluded;
|
|
1133
|
+
}
|
|
1134
|
+
function getOperationName({ path, method, operation, options, tag, keepOperationTag, keepOperationPrefix }) {
|
|
1135
|
+
return resolveOperationName({
|
|
1136
|
+
path,
|
|
1137
|
+
method,
|
|
1138
|
+
operation,
|
|
1139
|
+
options,
|
|
1140
|
+
tag,
|
|
1141
|
+
keepOperationTag,
|
|
1142
|
+
keepOperationPrefix
|
|
1143
|
+
}).name;
|
|
1144
|
+
}
|
|
1145
|
+
function resolveOperationName({ path, method, operation, options, tag, keepOperationTag, keepOperationPrefix }) {
|
|
1146
|
+
const usesPathAsSource = !operation.operationId;
|
|
1147
|
+
let pathOperationName;
|
|
1148
|
+
let operationName;
|
|
1149
|
+
if (operation.operationId) operationName = invalidVariableNameCharactersToCamel(operation.operationId);
|
|
1150
|
+
else {
|
|
1151
|
+
pathOperationName = `${method}${pathToVariableName(path)}`;
|
|
1152
|
+
operationName = pathOperationName;
|
|
1153
|
+
}
|
|
1154
|
+
if (options.removeOperationPrefixEndingWith && keepOperationPrefix) operationName = operationName.split(options.removeOperationPrefixEndingWith).map((split, index) => index === 0 ? split : capitalize(split)).join("");
|
|
1155
|
+
else if (options.removeOperationPrefixEndingWith && !keepOperationPrefix) {
|
|
1156
|
+
const regex = new RegExp(`^.*${options.removeOperationPrefixEndingWith}`);
|
|
1157
|
+
operationName = operationName.replace(regex, "");
|
|
1158
|
+
}
|
|
1159
|
+
if ((options.tsNamespaces || options.treeShakeableNamespaces) && !keepOperationTag) {
|
|
1160
|
+
const operationNameWithoutTag = removeWord(operationName, tag);
|
|
1161
|
+
if (operationNameWithoutTag === "") operationName = method.toLowerCase();
|
|
1162
|
+
else if (!RESERVED_WORDS.includes(operationNameWithoutTag)) operationName = operationNameWithoutTag;
|
|
1163
|
+
}
|
|
1164
|
+
const usesReservedWordFallback = RESERVED_WORDS.includes(operationName);
|
|
1165
|
+
if (usesReservedWordFallback && pathOperationName === void 0) pathOperationName = `${method}${pathToVariableName(path)}`;
|
|
1166
|
+
return {
|
|
1167
|
+
name: usesReservedWordFallback ? pathOperationName : operationName,
|
|
1168
|
+
usesPathAsSource,
|
|
1169
|
+
usesReservedWordFallback
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
function createOperationNameIndex({ operations, options, tag, keepOperationTag }) {
|
|
1173
|
+
const index = {
|
|
1174
|
+
stableCounts: /* @__PURE__ */ new Map(),
|
|
1175
|
+
pathSourceCount: 0,
|
|
1176
|
+
reservedFallbackCount: 0
|
|
1177
|
+
};
|
|
1178
|
+
for (const operation of operations) {
|
|
1179
|
+
if (!operation.operationId) {
|
|
1180
|
+
index.pathSourceCount++;
|
|
1181
|
+
continue;
|
|
1182
|
+
}
|
|
1183
|
+
const result = resolveOperationName({
|
|
1184
|
+
path: "",
|
|
1185
|
+
method: "",
|
|
1186
|
+
operation,
|
|
1187
|
+
options,
|
|
1188
|
+
tag,
|
|
1189
|
+
keepOperationTag
|
|
1190
|
+
});
|
|
1191
|
+
if (result.usesReservedWordFallback) index.reservedFallbackCount++;
|
|
1192
|
+
else index.stableCounts.set(result.name, (index.stableCounts.get(result.name) ?? 0) + 1);
|
|
1193
|
+
}
|
|
1194
|
+
return index;
|
|
1195
|
+
}
|
|
1196
|
+
function getUniqueOperationName({ operationsByTag, nameIndexes, ...params }) {
|
|
1197
|
+
const { operation, options } = params;
|
|
1198
|
+
const tag = options.splitByTags ? getOperationTag(operation, options) : options.defaultTag;
|
|
1199
|
+
const operationName = (keepOperationTag, nameIndex) => {
|
|
1200
|
+
const name = getOperationName({
|
|
1201
|
+
...params,
|
|
1202
|
+
tag,
|
|
1203
|
+
keepOperationTag
|
|
1204
|
+
});
|
|
1205
|
+
if (nameIndex) {
|
|
1206
|
+
const pathSourceMatches = nameIndex.pathSourceCount > 0 && getOperationName({
|
|
1207
|
+
...params,
|
|
1208
|
+
operation: {},
|
|
1209
|
+
tag,
|
|
1210
|
+
keepOperationTag
|
|
1211
|
+
}) === name;
|
|
1212
|
+
const pathFallbackMatches = nameIndex.reservedFallbackCount > 0 && `${params.method}${pathToVariableName(params.path)}` === name;
|
|
1213
|
+
return (nameIndex.stableCounts.get(name) ?? 0) + (pathSourceMatches ? nameIndex.pathSourceCount : 0) + (pathFallbackMatches ? nameIndex.reservedFallbackCount : 0) === 1 ? name : void 0;
|
|
1214
|
+
}
|
|
1215
|
+
let matchingOperations = 0;
|
|
1216
|
+
for (const candidate of operationsByTag[tag]) if (getOperationName({
|
|
1217
|
+
...params,
|
|
1218
|
+
operation: candidate,
|
|
1219
|
+
tag,
|
|
1220
|
+
keepOperationTag
|
|
1221
|
+
}) === name) {
|
|
1222
|
+
matchingOperations++;
|
|
1223
|
+
if (matchingOperations > 1) return;
|
|
1224
|
+
}
|
|
1225
|
+
if (matchingOperations === 1) return name;
|
|
1226
|
+
};
|
|
1227
|
+
return operationName(void 0, nameIndexes?.[0]) ?? operationName(true, nameIndexes?.[1]) ?? getOperationName({
|
|
1228
|
+
...params,
|
|
1229
|
+
tag,
|
|
1230
|
+
keepOperationTag: true,
|
|
1231
|
+
keepOperationPrefix: true
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
function getUniqueOperationNamesFromIndex(indexedOperations, operationsByTag, options, operationNameByOperation) {
|
|
1235
|
+
const operationNames = [];
|
|
1236
|
+
const nameIndexesByTag = /* @__PURE__ */ new Map();
|
|
1237
|
+
for (const { path, method, operation, tag } of indexedOperations) {
|
|
1238
|
+
let nameIndexes = nameIndexesByTag.get(tag);
|
|
1239
|
+
if (!nameIndexes) {
|
|
1240
|
+
const operations = operationsByTag[tag];
|
|
1241
|
+
nameIndexes = [createOperationNameIndex({
|
|
1242
|
+
operations,
|
|
1243
|
+
options,
|
|
1244
|
+
tag
|
|
1245
|
+
}), createOperationNameIndex({
|
|
1246
|
+
operations,
|
|
1247
|
+
options,
|
|
1248
|
+
tag,
|
|
1249
|
+
keepOperationTag: true
|
|
1250
|
+
})];
|
|
1251
|
+
nameIndexesByTag.set(tag, nameIndexes);
|
|
1252
|
+
}
|
|
1253
|
+
const operationName = getUniqueOperationName({
|
|
1254
|
+
path,
|
|
1255
|
+
method,
|
|
1256
|
+
operation,
|
|
1257
|
+
operationsByTag,
|
|
1258
|
+
options,
|
|
1259
|
+
nameIndexes
|
|
1260
|
+
});
|
|
1261
|
+
operationNameByOperation?.set(operation, operationName);
|
|
1262
|
+
operationNames.push(operationName);
|
|
1263
|
+
}
|
|
1264
|
+
return operationNames;
|
|
1265
|
+
}
|
|
1266
|
+
function getOperationIndex(openApiDoc, options) {
|
|
1267
|
+
const operationsByTag = {};
|
|
1268
|
+
const indexedOperations = [];
|
|
1269
|
+
for (const path in openApiDoc.paths) {
|
|
1270
|
+
if (isPathExcluded(path, options)) continue;
|
|
1271
|
+
const pathItemObj = openApiDoc.paths[path];
|
|
1272
|
+
const pathItem = pick(pathItemObj, ALLOWED_METHODS);
|
|
1273
|
+
for (const method in pathItem) {
|
|
1274
|
+
const operation = pathItem[method];
|
|
1275
|
+
if (!operation || isOperationExcluded(operation, options)) continue;
|
|
1276
|
+
const tag = options.splitByTags ? getOperationTag(operation, options) : options.defaultTag;
|
|
1277
|
+
(operationsByTag[tag] ??= []).push(operation);
|
|
1278
|
+
indexedOperations.push({
|
|
1279
|
+
path,
|
|
1280
|
+
method,
|
|
1281
|
+
operation,
|
|
1282
|
+
tag,
|
|
1283
|
+
pathParameters: pathItemObj.parameters
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
const operationNameByOperation = /* @__PURE__ */ new WeakMap();
|
|
1288
|
+
return {
|
|
1289
|
+
operationsByTag,
|
|
1290
|
+
operationNames: getUniqueOperationNamesFromIndex(indexedOperations, operationsByTag, options, operationNameByOperation),
|
|
1291
|
+
operationNameByOperation,
|
|
1292
|
+
indexedOperations
|
|
1293
|
+
};
|
|
1294
|
+
}
|
|
1295
|
+
//#endregion
|
|
1296
|
+
//#region src/generators/core/openapi/getOpenAPISchemaDependencyGraph.ts
|
|
1297
|
+
function getOpenAPISchemaDependencyGraph(schemaRef, getSchemaByRef) {
|
|
1298
|
+
const refsDependencyGraph = getRefsDependencyGraph(schemaRef, getSchemaByRef);
|
|
1299
|
+
return {
|
|
1300
|
+
refsDependencyGraph,
|
|
1301
|
+
deepDependencyGraph: getDeepRefsDependencyGraph(schemaRef, refsDependencyGraph)
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
function getRefsDependencyGraph(schemaRef, getSchemaByRef) {
|
|
1305
|
+
const visitedRefs = {};
|
|
1306
|
+
const refsDependencyGraph = {};
|
|
1307
|
+
schemaRef.forEach((ref) => getSchemaRefsDependencyGraph({
|
|
1308
|
+
schema: getSchemaByRef(ref),
|
|
1309
|
+
fromRef: ref,
|
|
1310
|
+
getSchemaByRef,
|
|
1311
|
+
visitedRefs,
|
|
1312
|
+
refsDependencyGraph
|
|
1313
|
+
}));
|
|
1314
|
+
return refsDependencyGraph;
|
|
1315
|
+
}
|
|
1316
|
+
function getDeepRefsDependencyGraph(schemaRef, refsDependencyGraph) {
|
|
1317
|
+
const visitedDeepRefs = {};
|
|
1318
|
+
const deepDependencyGraph = {};
|
|
1319
|
+
const visit = (dep, ref) => {
|
|
1320
|
+
deepDependencyGraph[ref].add(dep);
|
|
1321
|
+
if (refsDependencyGraph[dep] && ref !== dep) refsDependencyGraph[dep].forEach((transitive) => {
|
|
1322
|
+
const refName = `${ref}__${transitive}`;
|
|
1323
|
+
if (visitedDeepRefs[refName]) return;
|
|
1324
|
+
visitedDeepRefs[refName] = true;
|
|
1325
|
+
visit(transitive, ref);
|
|
1326
|
+
});
|
|
1327
|
+
};
|
|
1328
|
+
schemaRef.forEach((ref) => {
|
|
1329
|
+
const deps = refsDependencyGraph[ref];
|
|
1330
|
+
if (!deps) return;
|
|
1331
|
+
if (!deepDependencyGraph[ref]) deepDependencyGraph[ref] = /* @__PURE__ */ new Set();
|
|
1332
|
+
deps.forEach((dep) => visit(dep, ref));
|
|
1333
|
+
});
|
|
1334
|
+
return deepDependencyGraph;
|
|
1335
|
+
}
|
|
1336
|
+
function getSchemaRefsDependencyGraph({ schema, fromRef, getSchemaByRef, visitedRefs = {}, refsDependencyGraph = {} }) {
|
|
1337
|
+
const onSchema = (callbackData) => {
|
|
1338
|
+
if (callbackData.type !== "reference" || !callbackData.data) return;
|
|
1339
|
+
const { schema, data } = callbackData;
|
|
1340
|
+
if (!refsDependencyGraph[data.fromRef]) refsDependencyGraph[data.fromRef] = /* @__PURE__ */ new Set();
|
|
1341
|
+
refsDependencyGraph[data.fromRef].add(schema.$ref);
|
|
1342
|
+
if (visitedRefs[schema.$ref]) return true;
|
|
1343
|
+
visitedRefs[data.fromRef] = true;
|
|
1344
|
+
iterateSchema(getSchemaByRef(schema.$ref), {
|
|
1345
|
+
data: { fromRef: schema.$ref },
|
|
1346
|
+
onSchema
|
|
1347
|
+
});
|
|
1348
|
+
};
|
|
1349
|
+
iterateSchema(schema, {
|
|
1350
|
+
data: { fromRef },
|
|
1351
|
+
onSchema
|
|
1352
|
+
});
|
|
1353
|
+
return {
|
|
1354
|
+
visitedRefs,
|
|
1355
|
+
refsDependencyGraph
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
//#endregion
|
|
1359
|
+
//#region src/generators/core/openapi/getSchemaRefObjs.ts
|
|
1360
|
+
function getSchemaRefObjs(resolver, schema, schemaInfo) {
|
|
1361
|
+
const schemaRefObjs = [];
|
|
1362
|
+
const onSchema = (data) => {
|
|
1363
|
+
if (data.type === "reference") schemaRefObjs.push(data.schema);
|
|
1364
|
+
else if (isReferenceObject(data.parentSchema)) {
|
|
1365
|
+
if (data.type === "property") resolver.validationErrors.push(getInvalidSchemaError(`${schemaInfo} has both reference and properties`));
|
|
1366
|
+
else if (data.type === "additionalProperties") resolver.validationErrors.push(getInvalidSchemaError(`${schemaInfo} has both reference and additionalProperties`));
|
|
1367
|
+
else if (data.type === "array") resolver.validationErrors.push(getInvalidSchemaError(`${schemaInfo} is both reference and array schema`));
|
|
1368
|
+
else if (data.type === "composite") resolver.validationErrors.push(getInvalidSchemaError(`${schemaInfo} has both reference and composite keyword`));
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
iterateSchema(schema, { onSchema });
|
|
1372
|
+
return schemaRefObjs;
|
|
1373
|
+
}
|
|
1374
|
+
function getDeepSchemaRefObjs(resolver, schemaRefs) {
|
|
1375
|
+
return schemaRefs.map((schemaRef) => autocorrectRef(schemaRef.$ref)).reduce((acc, schemaRef) => {
|
|
1376
|
+
const refs = resolver.dependencyGraph.deepDependencyGraph[schemaRef];
|
|
1377
|
+
return [
|
|
1378
|
+
...acc,
|
|
1379
|
+
schemaRef,
|
|
1380
|
+
...Array.from(refs ?? [])
|
|
1381
|
+
];
|
|
1382
|
+
}, []);
|
|
1383
|
+
}
|
|
1384
|
+
//#endregion
|
|
1385
|
+
//#region src/generators/core/zod/enumExtraction/resolveExtractedEnumZodSchemaNames.ts
|
|
1386
|
+
function resolveExtractedEnumZodSchemaNames(resolver) {
|
|
1387
|
+
resolver.extractedEnumZodSchemaData.forEach((enumData) => {
|
|
1388
|
+
const lastSegements = enumData.meta.zodSchemaNameSegments.map((arr) => arr[arr.length - 1]).filter(Boolean);
|
|
1389
|
+
const mostCommonLastSegment = getMostCommonAdjacentCombinationSplit(lastSegements);
|
|
1390
|
+
if (!mostCommonLastSegment) throw new Error(`No common last segment found for enum: ${enumData.code}`);
|
|
1391
|
+
enumData.zodSchemaName = getEnumZodSchemaName(mostCommonLastSegment, resolver.options.enumSuffix, resolver.options.schemaSuffix);
|
|
1392
|
+
});
|
|
1393
|
+
let nameResolutionIterationsCounter = 0;
|
|
1394
|
+
while (nameResolutionIterationsCounter < 5) {
|
|
1395
|
+
if (allExtractedEnumZodSchemaNamesAreUnique(resolver)) break;
|
|
1396
|
+
additionalResolveExtractedEnumZodSchemaName(resolver, nameResolutionIterationsCounter + 2);
|
|
1397
|
+
nameResolutionIterationsCounter++;
|
|
1398
|
+
}
|
|
1399
|
+
if (!allExtractedEnumZodSchemaNamesAreUnique(resolver)) resolver.extractedEnumZodSchemaData.filter((enumData) => !isUnique(resolver, enumData)).forEach((enumData) => {
|
|
1400
|
+
enumData.zodSchemaName = getEnumZodSchemaName(enumData.meta.zodSchemaNameSegments[0].map((name) => sanitizeName(capitalize(name))).join(""), resolver.options.enumSuffix, resolver.options.schemaSuffix);
|
|
1401
|
+
});
|
|
1402
|
+
if (!allExtractedEnumZodSchemaNamesAreUnique(resolver)) throw new Error("Failed to resolve unique names for enum zod schemas");
|
|
1403
|
+
}
|
|
1404
|
+
function allExtractedEnumZodSchemaNamesAreUnique(resolver) {
|
|
1405
|
+
return resolver.extractedEnumZodSchemaData.every((enumData) => isUnique(resolver, enumData));
|
|
1406
|
+
}
|
|
1407
|
+
function additionalResolveExtractedEnumZodSchemaName(resolver, index) {
|
|
1408
|
+
resolver.extractedEnumZodSchemaData.forEach((enumData) => {
|
|
1409
|
+
const enumsDataWithSameName = resolver.extractedEnumZodSchemaData.filter(({ zodSchemaName }) => enumData.zodSchemaName === zodSchemaName);
|
|
1410
|
+
if (enumsDataWithSameName.length === 1) return;
|
|
1411
|
+
suffixWithPreviousSegmentName(enumsDataWithSameName, index);
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
function suffixWithPreviousSegmentName(enumsData, index = 2) {
|
|
1415
|
+
enumsData.forEach((data) => {
|
|
1416
|
+
const precedingLastFragments = data.meta.zodSchemaNameSegments.map((arr) => arr[arr.length - index]).filter(Boolean);
|
|
1417
|
+
if (precedingLastFragments.length === 1) data.zodSchemaName = [sanitizeName(capitalize(precedingLastFragments[0])), data.zodSchemaName].filter(Boolean).join("");
|
|
1418
|
+
else {
|
|
1419
|
+
const secondLastFragmentSplit = getMostCommonAdjacentCombinationSplit(precedingLastFragments);
|
|
1420
|
+
data.zodSchemaName = [secondLastFragmentSplit ? sanitizeName(capitalize(secondLastFragmentSplit)) : "", data.zodSchemaName].filter(Boolean).join("");
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
function isUnique(resolver, enumData) {
|
|
1425
|
+
return resolver.extractedEnumZodSchemaData.filter(({ zodSchemaName }) => enumData.zodSchemaName === zodSchemaName).length === 1;
|
|
1426
|
+
}
|
|
1427
|
+
function sanitizeName(name) {
|
|
1428
|
+
return name.replace(/(Dto|DTO|Response|Request)/g, "");
|
|
1429
|
+
}
|
|
1430
|
+
//#endregion
|
|
1431
|
+
//#region src/generators/core/zod/enumExtraction/resolveExtractedEnumZodSchemaTags.ts
|
|
1432
|
+
function resolveExtractedEnumZodSchemaTags(resolver) {
|
|
1433
|
+
resolver.extractedEnumZodSchemaData.forEach((enumData) => {
|
|
1434
|
+
const tags = getUniqueArray(enumData.meta.tags);
|
|
1435
|
+
enumData.tag = tags.length === 1 ? tags[0] : resolver.options.defaultTag;
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
//#endregion
|
|
1439
|
+
//#region src/generators/core/zod/enumExtraction/updateExtractedEnumZodSchemaData.ts
|
|
1440
|
+
function updateExtractedEnumZodSchemaData({ schema, nameSegments = [], includeSelf, ...params }) {
|
|
1441
|
+
if (!isReferenceObject(schema) && schema?.["x-domain-error-domain"]) return;
|
|
1442
|
+
if (includeSelf) handleExtractedEnumZodSchemaDataUpdate({
|
|
1443
|
+
schema,
|
|
1444
|
+
nameSegments,
|
|
1445
|
+
...params
|
|
1446
|
+
});
|
|
1447
|
+
const onSchema = (data) => {
|
|
1448
|
+
if (data.type === "reference") return true;
|
|
1449
|
+
const segments = [...data.data?.nameSegments ?? []];
|
|
1450
|
+
if (data.type === "property") segments.push(data.propertyName);
|
|
1451
|
+
handleExtractedEnumZodSchemaDataUpdate({
|
|
1452
|
+
schema: data.schema,
|
|
1453
|
+
nameSegments: [...segments],
|
|
1454
|
+
...params
|
|
1455
|
+
});
|
|
1456
|
+
};
|
|
1457
|
+
iterateSchema(schema, {
|
|
1458
|
+
data: { nameSegments },
|
|
1459
|
+
onSchema
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
function handleExtractedEnumZodSchemaDataUpdate({ resolver, schema, schemaRef, schemaInfo, tags, nameSegments = [] }) {
|
|
1463
|
+
if (!schema || isReferenceObject(schema) || !schema.enum) return;
|
|
1464
|
+
const code = getEnumZodSchemaCode(schema);
|
|
1465
|
+
const enumZodSchema = resolver.extractedEnumZodSchemaData.find((data) => data.code === code);
|
|
1466
|
+
if (enumZodSchema) {
|
|
1467
|
+
enumZodSchema.meta.zodSchemaNameSegments.push(nameSegments);
|
|
1468
|
+
enumZodSchema.meta.tags.push(...tags);
|
|
1469
|
+
enumZodSchema.meta.schemaRefs.push(...schemaRef ? [schemaRef] : []);
|
|
1470
|
+
enumZodSchema.meta.schemas.push(...schema ? [schema] : []);
|
|
1471
|
+
} else resolver.extractedEnumZodSchemaData.push({
|
|
1472
|
+
code,
|
|
1473
|
+
meta: {
|
|
1474
|
+
zodSchemaNameSegments: [nameSegments],
|
|
1475
|
+
tags: [...tags],
|
|
1476
|
+
schemaRefs: schemaRef ? [schemaRef] : [],
|
|
1477
|
+
schemas: schema ? [schema] : []
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
resolver.validationErrors.push(getNotAllowedInlineEnumError(schemaRef ? `${getSchemaNameByRef(schemaRef)}.${nameSegments[nameSegments.length - 1]}` : schemaInfo ?? nameSegments.join(".")));
|
|
1481
|
+
}
|
|
1482
|
+
//#endregion
|
|
1483
|
+
//#region src/generators/core/zod/getZodSchemasFromOpenAPIDoc.ts
|
|
1484
|
+
function getZodSchemasFromOpenAPIDoc(resolver, profiler) {
|
|
1485
|
+
const p = profiler ?? new Profiler(false);
|
|
1486
|
+
const zodSchemas = {};
|
|
1487
|
+
const enumZodSchemas = {};
|
|
1488
|
+
Object.entries(resolver.openApiDoc.components?.schemas ?? {}).forEach(([name, schema]) => p.runSync("zod.extract.schemaEntry", () => {
|
|
1489
|
+
const schemaData = resolver.getSchemaDataByName(name);
|
|
1490
|
+
if (resolver.options.excludeRedundantZodSchemas && (!schemaData || schemaData.deepRefOperations.length === 0 && schemaData.tags.length === 0)) return;
|
|
1491
|
+
const zodSchemaName = getZodSchemaName(name, resolver.options.schemaSuffix);
|
|
1492
|
+
if (zodSchemas[zodSchemaName]) return;
|
|
1493
|
+
const tag = resolver.getTagByZodSchemaName(zodSchemaName);
|
|
1494
|
+
const schemaObject = resolver.resolveObject(schema);
|
|
1495
|
+
if (schemaObject.enum) enumZodSchemas[zodSchemaName] = getEnumZodSchemaCode(schemaObject);
|
|
1496
|
+
else {
|
|
1497
|
+
const existingCode = resolver.getCodeByZodSchemaName(zodSchemaName);
|
|
1498
|
+
if (existingCode !== void 0) {
|
|
1499
|
+
zodSchemas[zodSchemaName] = existingCode;
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
zodSchemas[zodSchemaName] = p.runSync("zod.extract.schemaToCode", () => getZodSchema({
|
|
1503
|
+
schema,
|
|
1504
|
+
resolver,
|
|
1505
|
+
tag
|
|
1506
|
+
}).getCodeString(tag));
|
|
1507
|
+
}
|
|
1508
|
+
}));
|
|
1509
|
+
return {
|
|
1510
|
+
zodSchemas,
|
|
1511
|
+
enumZodSchemas
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
function getEnumZodSchemasFromOpenAPIDoc(resolver) {
|
|
1515
|
+
const enumZodSchemas = [];
|
|
1516
|
+
Object.entries(resolver.openApiDoc.components?.schemas ?? {}).forEach(([name, schema]) => {
|
|
1517
|
+
const zodSchemaName = getZodSchemaName(name, resolver.options.schemaSuffix);
|
|
1518
|
+
const schemaObject = resolver.resolveObject(schema);
|
|
1519
|
+
if (schemaObject.enum) enumZodSchemas.push({
|
|
1520
|
+
zodSchemaName,
|
|
1521
|
+
code: getEnumZodSchemaCode(schemaObject)
|
|
1522
|
+
});
|
|
1523
|
+
});
|
|
1524
|
+
return enumZodSchemas;
|
|
1525
|
+
}
|
|
1526
|
+
//#endregion
|
|
1527
|
+
//#region src/generators/core/SchemaResolver.class.ts
|
|
1528
|
+
var SchemaResolver = class {
|
|
1529
|
+
openApiDoc;
|
|
1530
|
+
options;
|
|
1531
|
+
profiler;
|
|
1532
|
+
schemaData = [];
|
|
1533
|
+
zodSchemaData = [];
|
|
1534
|
+
compositeZodSchemaData = [];
|
|
1535
|
+
schemaRefs;
|
|
1536
|
+
schemaByRef = /* @__PURE__ */ new Map();
|
|
1537
|
+
schemaDataByRef = /* @__PURE__ */ new Map();
|
|
1538
|
+
schemaDataByName = /* @__PURE__ */ new Map();
|
|
1539
|
+
refByZodSchemaName = /* @__PURE__ */ new Map();
|
|
1540
|
+
zodSchemaDataByName = /* @__PURE__ */ new Map();
|
|
1541
|
+
compositeByCode = /* @__PURE__ */ new Map();
|
|
1542
|
+
compositeSchemaByZodSchemaName = /* @__PURE__ */ new Map();
|
|
1543
|
+
dependencyGraph;
|
|
1544
|
+
enumZodSchemas = [];
|
|
1545
|
+
extractedEnumZodSchemaData = [];
|
|
1546
|
+
operationsByTag = {};
|
|
1547
|
+
operationNames = [];
|
|
1548
|
+
operationNameCounts = /* @__PURE__ */ new Map();
|
|
1549
|
+
operationNameByOperation;
|
|
1550
|
+
indexedOperations;
|
|
1551
|
+
operationContexts = [];
|
|
1552
|
+
zodSchemaTagCache;
|
|
1553
|
+
validationErrors = [];
|
|
1554
|
+
get docSchemas() {
|
|
1555
|
+
return this.openApiDoc.components?.schemas ?? {};
|
|
1556
|
+
}
|
|
1557
|
+
constructor(openApiDoc, options, profiler) {
|
|
1558
|
+
this.openApiDoc = openApiDoc;
|
|
1559
|
+
this.options = options;
|
|
1560
|
+
this.profiler = profiler;
|
|
1561
|
+
const p = profiler ?? new Profiler(false);
|
|
1562
|
+
this.schemaRefs = p.runSync("resolver.construct.schemaRefs", () => Object.keys(this.docSchemas).map(getSchemaRef));
|
|
1563
|
+
this.dependencyGraph = p.runSync("resolver.construct.dependencyGraph", () => getOpenAPISchemaDependencyGraph(this.schemaRefs, this.getSchemaByRef.bind(this)));
|
|
1564
|
+
this.enumZodSchemas = p.runSync("resolver.construct.enums", () => getEnumZodSchemasFromOpenAPIDoc(this));
|
|
1565
|
+
const operationIndex = p.runSync("resolver.construct.operationIndex", () => getOperationIndex(openApiDoc, options));
|
|
1566
|
+
this.operationsByTag = operationIndex.operationsByTag;
|
|
1567
|
+
this.operationNames = operationIndex.operationNames;
|
|
1568
|
+
this.operationNameByOperation = operationIndex.operationNameByOperation;
|
|
1569
|
+
this.indexedOperations = operationIndex.indexedOperations;
|
|
1570
|
+
p.runSync("resolver.construct.operationNameCounts", () => {
|
|
1571
|
+
for (const name of this.operationNames) this.operationNameCounts.set(name, (this.operationNameCounts.get(name) ?? 0) + 1);
|
|
1572
|
+
});
|
|
1573
|
+
this.initialize();
|
|
1574
|
+
}
|
|
1575
|
+
getSchemaByRef(ref) {
|
|
1576
|
+
const correctRef = autocorrectRef(ref);
|
|
1577
|
+
const cachedSchema = this.schemaByRef.get(correctRef);
|
|
1578
|
+
if (cachedSchema) return cachedSchema;
|
|
1579
|
+
const schema = this.docSchemas[getSchemaNameByRef(correctRef)];
|
|
1580
|
+
this.schemaByRef.set(correctRef, schema);
|
|
1581
|
+
return schema;
|
|
1582
|
+
}
|
|
1583
|
+
getSchemaDataByName(name) {
|
|
1584
|
+
return this.schemaDataByName.get(name);
|
|
1585
|
+
}
|
|
1586
|
+
getZodSchemaNameByRef(ref) {
|
|
1587
|
+
const zodSchemaName = this.getSchemaDataByRef(autocorrectRef(ref))?.zodSchemaName ?? this.extractedEnumZodSchemaData.find((data) => data.zodSchemaName === ref)?.zodSchemaName;
|
|
1588
|
+
if (!zodSchemaName) throw new Error(`Zod schema not found for ref: ${ref}`);
|
|
1589
|
+
return zodSchemaName;
|
|
1590
|
+
}
|
|
1591
|
+
getRefByZodSchemaName(zodSchemaName) {
|
|
1592
|
+
return this.refByZodSchemaName.get(zodSchemaName);
|
|
1593
|
+
}
|
|
1594
|
+
getTagByZodSchemaName(zodSchemaName) {
|
|
1595
|
+
const cachedTag = this.zodSchemaTagCache?.get(zodSchemaName);
|
|
1596
|
+
if (cachedTag) return cachedTag;
|
|
1597
|
+
const tag = this.resolveTagByZodSchemaName(zodSchemaName);
|
|
1598
|
+
this.zodSchemaTagCache?.set(zodSchemaName, tag);
|
|
1599
|
+
return tag;
|
|
1600
|
+
}
|
|
1601
|
+
getTagsByZodSchemaName(zodSchemaName) {
|
|
1602
|
+
if (!this.options.splitByTags) return [formatTag(this.options.defaultTag)];
|
|
1603
|
+
const extractedEnum = this.extractedEnumZodSchemaData.find((data) => data.zodSchemaName === zodSchemaName);
|
|
1604
|
+
if (extractedEnum) {
|
|
1605
|
+
const tags = getUniqueArray(extractedEnum.meta.tags);
|
|
1606
|
+
return (tags.length > 0 ? tags : [extractedEnum.tag ?? this.options.defaultTag]).map(formatTag);
|
|
1607
|
+
}
|
|
1608
|
+
const schemaRef = this.getRefByZodSchemaName(zodSchemaName);
|
|
1609
|
+
const tags = getUniqueArray(schemaRef ? this.getSchemaDataByRef(schemaRef)?.tags ?? [] : [], this.zodSchemaDataByName.get(zodSchemaName)?.tags ?? []);
|
|
1610
|
+
return (tags.length > 0 ? tags : [this.options.defaultTag]).map(formatTag);
|
|
1611
|
+
}
|
|
1612
|
+
enableZodSchemaTagCache() {
|
|
1613
|
+
this.zodSchemaTagCache = /* @__PURE__ */ new Map();
|
|
1614
|
+
}
|
|
1615
|
+
resolveTagByZodSchemaName(zodSchemaName) {
|
|
1616
|
+
if (!this.options.splitByTags) return this.options.defaultTag;
|
|
1617
|
+
if (this.options.modelsInCommon) return formatTag(this.options.defaultTag);
|
|
1618
|
+
const extractedEnumZodSchema = this.extractedEnumZodSchemaData.find((data) => data.zodSchemaName === zodSchemaName);
|
|
1619
|
+
if (extractedEnumZodSchema) return formatTag(extractedEnumZodSchema.tag ?? this.options.defaultTag);
|
|
1620
|
+
const schemaRef = this.getRefByZodSchemaName(zodSchemaName);
|
|
1621
|
+
const schemaTags = schemaRef ? this.getSchemaDataByRef(schemaRef)?.tags ?? [] : [];
|
|
1622
|
+
const zodSchemaTags = this.zodSchemaDataByName.get(zodSchemaName)?.tags ?? [];
|
|
1623
|
+
const tags = getUniqueArray(schemaTags, zodSchemaTags);
|
|
1624
|
+
const tag = tags.length === 1 ? tags[0] : this.options.defaultTag;
|
|
1625
|
+
return formatTag(tag ?? this.options.defaultTag);
|
|
1626
|
+
}
|
|
1627
|
+
getCodeByZodSchemaName(name) {
|
|
1628
|
+
return this.zodSchemaDataByName.get(name)?.code;
|
|
1629
|
+
}
|
|
1630
|
+
getZodSchemaNamesByCompositeCode(code) {
|
|
1631
|
+
return this.compositeByCode.get(code)?.zodSchemas.map((schema) => schema.zodSchemaName);
|
|
1632
|
+
}
|
|
1633
|
+
setZodSchema(name, code, tag) {
|
|
1634
|
+
const zodSchema = this.zodSchemaDataByName.get(name);
|
|
1635
|
+
if (zodSchema) {
|
|
1636
|
+
zodSchema.code = code;
|
|
1637
|
+
zodSchema.tags = (zodSchema.tags ?? []).concat(tag);
|
|
1638
|
+
} else {
|
|
1639
|
+
const newZodSchemaData = {
|
|
1640
|
+
zodSchemaName: name,
|
|
1641
|
+
code,
|
|
1642
|
+
tags: [tag]
|
|
1643
|
+
};
|
|
1644
|
+
this.zodSchemaData.push(newZodSchemaData);
|
|
1645
|
+
this.zodSchemaDataByName.set(name, newZodSchemaData);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
addZodSchemaForCompositeCode(code, zodSchema, zodSchemaName, schema) {
|
|
1649
|
+
const compositeZodSchema = {
|
|
1650
|
+
zodSchemaName,
|
|
1651
|
+
zodSchema,
|
|
1652
|
+
schema
|
|
1653
|
+
};
|
|
1654
|
+
const compositeData = this.compositeByCode.get(code);
|
|
1655
|
+
if (compositeData) compositeData.zodSchemas.push(compositeZodSchema);
|
|
1656
|
+
else {
|
|
1657
|
+
const newCompositeData = {
|
|
1658
|
+
code,
|
|
1659
|
+
zodSchemas: [compositeZodSchema]
|
|
1660
|
+
};
|
|
1661
|
+
this.compositeZodSchemaData.push(newCompositeData);
|
|
1662
|
+
this.compositeByCode.set(code, newCompositeData);
|
|
1663
|
+
}
|
|
1664
|
+
this.compositeSchemaByZodSchemaName.set(zodSchemaName, {
|
|
1665
|
+
zodSchema,
|
|
1666
|
+
schema
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1669
|
+
getCompositeZodSchemaByZodSchemaName(zodSchemaName) {
|
|
1670
|
+
return this.compositeSchemaByZodSchemaName.get(zodSchemaName)?.zodSchema;
|
|
1671
|
+
}
|
|
1672
|
+
getSchemaByCompositeZodSchemaName(compositeZodSchemaName) {
|
|
1673
|
+
return this.compositeSchemaByZodSchemaName.get(compositeZodSchemaName)?.schema;
|
|
1674
|
+
}
|
|
1675
|
+
getEnumZodSchemaDataByCode(code) {
|
|
1676
|
+
return this.enumZodSchemas.find((data) => data.code === code);
|
|
1677
|
+
}
|
|
1678
|
+
getExtractedEnumZodSchemaDataByCode(code) {
|
|
1679
|
+
return this.extractedEnumZodSchemaData.find((data) => data.code === code);
|
|
1680
|
+
}
|
|
1681
|
+
getExtractedEnumZodSchemaNamesReferencedBySchemaRef(schemaRef) {
|
|
1682
|
+
return this.extractedEnumZodSchemaData.reduce((acc, { zodSchemaName, meta }) => {
|
|
1683
|
+
if (zodSchemaName && meta.schemaRefs.includes(schemaRef)) return [...acc, zodSchemaName];
|
|
1684
|
+
return acc;
|
|
1685
|
+
}, []);
|
|
1686
|
+
}
|
|
1687
|
+
getZodSchemas() {
|
|
1688
|
+
const zodSchemas = {};
|
|
1689
|
+
for (const { zodSchemaName, code } of this.zodSchemaData) zodSchemas[zodSchemaName] = code;
|
|
1690
|
+
return zodSchemas;
|
|
1691
|
+
}
|
|
1692
|
+
getExtractedEnumZodSchemas() {
|
|
1693
|
+
const zodSchemas = {};
|
|
1694
|
+
for (const { zodSchemaName, code } of this.extractedEnumZodSchemaData) if (zodSchemaName) zodSchemas[zodSchemaName] = code;
|
|
1695
|
+
return zodSchemas;
|
|
1696
|
+
}
|
|
1697
|
+
resolveObject(obj) {
|
|
1698
|
+
return isReferenceObject(obj) ? this.getSchemaByRef(obj.$ref) : obj;
|
|
1699
|
+
}
|
|
1700
|
+
isSchemaCircular(ref) {
|
|
1701
|
+
return this.dependencyGraph.deepDependencyGraph[ref]?.has(ref);
|
|
1702
|
+
}
|
|
1703
|
+
getCircularSchemaChain(ref, currentRef = ref, chain = [], visited = []) {
|
|
1704
|
+
if (visited.includes(currentRef)) return [];
|
|
1705
|
+
visited.push(currentRef);
|
|
1706
|
+
if (this.dependencyGraph.refsDependencyGraph[currentRef]?.has(ref)) return [
|
|
1707
|
+
...chain,
|
|
1708
|
+
currentRef,
|
|
1709
|
+
ref
|
|
1710
|
+
];
|
|
1711
|
+
return Array.from(this.dependencyGraph.refsDependencyGraph[currentRef]?.values() ?? []).flatMap((childRef) => {
|
|
1712
|
+
const childChain = this.getCircularSchemaChain(ref, childRef, chain, visited);
|
|
1713
|
+
return childChain.length > 0 ? [currentRef, ...childChain] : childChain;
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
getBaseUrl() {
|
|
1717
|
+
const serverUrl = this.openApiDoc.servers?.[0]?.url;
|
|
1718
|
+
if (this.options.baseUrl === "" && serverUrl) return serverUrl;
|
|
1719
|
+
return this.options.baseUrl;
|
|
1720
|
+
}
|
|
1721
|
+
isOperationNameUnique(operationName) {
|
|
1722
|
+
return (this.operationNameCounts.get(operationName) ?? 0) <= 1;
|
|
1723
|
+
}
|
|
1724
|
+
getOperationContexts() {
|
|
1725
|
+
return this.operationContexts;
|
|
1726
|
+
}
|
|
1727
|
+
getZodSchemaObj(zodSchemaName) {
|
|
1728
|
+
const ref = this.getRefByZodSchemaName(zodSchemaName);
|
|
1729
|
+
if (ref) return this.getSchemaByRef(ref);
|
|
1730
|
+
const schema = this.getSchemaByCompositeZodSchemaName(zodSchemaName);
|
|
1731
|
+
if (schema) return schema;
|
|
1732
|
+
const enumZodSchemaData = this.getExtractedEnumZodSchemaDataByName(zodSchemaName);
|
|
1733
|
+
if (enumZodSchemaData) {
|
|
1734
|
+
const schemaObject = {};
|
|
1735
|
+
for (const schema of enumZodSchemaData.meta.schemas) Object.assign(schemaObject, this.resolveObject(schema));
|
|
1736
|
+
return schemaObject;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
getSchemaDataByRef(ref) {
|
|
1740
|
+
return this.schemaDataByRef.get(ref);
|
|
1741
|
+
}
|
|
1742
|
+
getExtractedEnumZodSchemaDataByName(enumZodSchemaName) {
|
|
1743
|
+
return this.extractedEnumZodSchemaData.find(({ zodSchemaName }) => zodSchemaName === enumZodSchemaName);
|
|
1744
|
+
}
|
|
1745
|
+
initialize() {
|
|
1746
|
+
const p = this.profiler ?? new Profiler(false);
|
|
1747
|
+
p.runSync("resolver.init.seedSchemas", () => {
|
|
1748
|
+
this.schemaRefs.forEach((ref) => {
|
|
1749
|
+
const correctRef = autocorrectRef(ref);
|
|
1750
|
+
const name = getSchemaNameByRef(correctRef);
|
|
1751
|
+
const zodSchemaName = getZodSchemaName(name, this.options.schemaSuffix);
|
|
1752
|
+
const data = {
|
|
1753
|
+
ref: correctRef,
|
|
1754
|
+
name,
|
|
1755
|
+
zodSchemaName,
|
|
1756
|
+
tags: [],
|
|
1757
|
+
deepRefOperations: []
|
|
1758
|
+
};
|
|
1759
|
+
this.schemaData.push(data);
|
|
1760
|
+
this.schemaDataByRef.set(correctRef, data);
|
|
1761
|
+
this.schemaDataByName.set(name, data);
|
|
1762
|
+
this.refByZodSchemaName.set(zodSchemaName, correctRef);
|
|
1763
|
+
});
|
|
1764
|
+
});
|
|
1765
|
+
p.runSync("resolver.init.operationsLoop", () => {
|
|
1766
|
+
let currentPath = "";
|
|
1767
|
+
let pathParameters = {};
|
|
1768
|
+
for (const { path, method, operation, pathParameters: rawPathParameters } of this.indexedOperations) {
|
|
1769
|
+
if (path !== currentPath) {
|
|
1770
|
+
currentPath = path;
|
|
1771
|
+
pathParameters = this.getParameters(rawPathParameters ?? []);
|
|
1772
|
+
}
|
|
1773
|
+
const tag = getOperationTag(operation, this.options);
|
|
1774
|
+
const operationName = this.operationNameByOperation.get(operation);
|
|
1775
|
+
const isUniqueOperationName = this.isOperationNameUnique(operationName);
|
|
1776
|
+
const parameters = p.runSync("resolver.init.parameters.mergeResolve", () => Object.entries({
|
|
1777
|
+
...pathParameters,
|
|
1778
|
+
...this.getParameters(operation.parameters ?? [])
|
|
1779
|
+
}).map(([, param]) => this.resolveObject(param)));
|
|
1780
|
+
const responses = p.runSync("resolver.init.responses.prepare", () => Object.entries(operation.responses).map(([statusCode, response]) => {
|
|
1781
|
+
const responseObj = this.resolveObject(response);
|
|
1782
|
+
const mediaTypes = Object.keys(responseObj?.content ?? {});
|
|
1783
|
+
const matchingMediaType = mediaTypes.find((mediaType) => responseObj.content?.[mediaType]?.schema) ?? mediaTypes.find(isMediaTypeAllowed);
|
|
1784
|
+
return {
|
|
1785
|
+
statusCode,
|
|
1786
|
+
responseObj,
|
|
1787
|
+
matchingMediaType,
|
|
1788
|
+
schema: matchingMediaType ? responseObj.content?.[matchingMediaType]?.schema : void 0
|
|
1789
|
+
};
|
|
1790
|
+
}));
|
|
1791
|
+
const zodSchemaOperationName = snakeToCamel(getZodSchemaOperationName(operationName, isUniqueOperationName, tag));
|
|
1792
|
+
const schemaRefObjs = [];
|
|
1793
|
+
p.runSync("resolver.init.parameters.refs", () => {
|
|
1794
|
+
parameters.forEach((parameter) => {
|
|
1795
|
+
const parameterObject = this.resolveObject(parameter);
|
|
1796
|
+
const parameterSchema = parameterObject.schema;
|
|
1797
|
+
const schemaInfo = `Operation ${operation.operationId ?? path} parameter ${parameterObject.name}`;
|
|
1798
|
+
schemaRefObjs.push(...getSchemaRefObjs(this, parameterSchema, schemaInfo));
|
|
1799
|
+
if (this.options.extractEnums) updateExtractedEnumZodSchemaData({
|
|
1800
|
+
resolver: this,
|
|
1801
|
+
schema: parameterSchema,
|
|
1802
|
+
schemaInfo,
|
|
1803
|
+
tags: [tag],
|
|
1804
|
+
nameSegments: [zodSchemaOperationName, parameterObject.name],
|
|
1805
|
+
includeSelf: true
|
|
1806
|
+
});
|
|
1807
|
+
});
|
|
1808
|
+
});
|
|
1809
|
+
p.runSync("resolver.init.requestBody.refs", () => {
|
|
1810
|
+
if (operation.requestBody) {
|
|
1811
|
+
const requestBodyObj = this.resolveObject(operation.requestBody);
|
|
1812
|
+
const matchingMediaType = Object.keys(requestBodyObj.content ?? {}).find(isParamMediaTypeAllowed);
|
|
1813
|
+
if (matchingMediaType) {
|
|
1814
|
+
const matchingMediaSchema = requestBodyObj.content?.[matchingMediaType]?.schema;
|
|
1815
|
+
const schemaInfo = `Operation ${operation.operationId} request body`;
|
|
1816
|
+
schemaRefObjs.push(...getSchemaRefObjs(this, matchingMediaSchema, schemaInfo));
|
|
1817
|
+
if (this.options.extractEnums) updateExtractedEnumZodSchemaData({
|
|
1818
|
+
resolver: this,
|
|
1819
|
+
schema: matchingMediaSchema,
|
|
1820
|
+
schemaInfo,
|
|
1821
|
+
tags: [tag],
|
|
1822
|
+
nameSegments: [getBodyZodSchemaName(zodSchemaOperationName)]
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
p.runSync("resolver.init.responses.refs", () => {
|
|
1828
|
+
for (const responseData of responses) {
|
|
1829
|
+
if (!responseData.matchingMediaType) continue;
|
|
1830
|
+
const schemaInfo = `Operation ${operation.operationId} response body`;
|
|
1831
|
+
schemaRefObjs.push(...getSchemaRefObjs(this, responseData.schema, schemaInfo));
|
|
1832
|
+
if (this.options.extractEnums) updateExtractedEnumZodSchemaData({
|
|
1833
|
+
resolver: this,
|
|
1834
|
+
schema: responseData.schema,
|
|
1835
|
+
schemaInfo,
|
|
1836
|
+
tags: [tag],
|
|
1837
|
+
nameSegments: [getResponseZodSchemaName({
|
|
1838
|
+
statusCode: responseData.statusCode,
|
|
1839
|
+
operationName,
|
|
1840
|
+
isUniqueOperationName,
|
|
1841
|
+
tag
|
|
1842
|
+
})]
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
});
|
|
1846
|
+
const deepRefs = p.runSync("resolver.init.deepRefs", () => getDeepSchemaRefObjs(this, schemaRefObjs));
|
|
1847
|
+
const operationContext = {
|
|
1848
|
+
path,
|
|
1849
|
+
method,
|
|
1850
|
+
operation,
|
|
1851
|
+
tag,
|
|
1852
|
+
operationName,
|
|
1853
|
+
isUniqueOperationName,
|
|
1854
|
+
parameters,
|
|
1855
|
+
deepRefs,
|
|
1856
|
+
responses
|
|
1857
|
+
};
|
|
1858
|
+
this.operationContexts.push(operationContext);
|
|
1859
|
+
deepRefs.forEach((schemaRef) => {
|
|
1860
|
+
const schemaData = this.getSchemaDataByRef(schemaRef);
|
|
1861
|
+
if (schemaData) {
|
|
1862
|
+
schemaData.tags.push(tag);
|
|
1863
|
+
schemaData.deepRefOperations.push(operation);
|
|
1864
|
+
}
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
});
|
|
1868
|
+
if (this.options.extractEnums) p.runSync("resolver.init.enums.finalize", () => {
|
|
1869
|
+
this.schemaRefs.forEach((ref) => {
|
|
1870
|
+
const schemaRef = autocorrectRef(ref);
|
|
1871
|
+
updateExtractedEnumZodSchemaData({
|
|
1872
|
+
resolver: this,
|
|
1873
|
+
schema: this.getSchemaByRef(schemaRef),
|
|
1874
|
+
schemaRef,
|
|
1875
|
+
tags: this.getSchemaDataByRef(schemaRef)?.tags ?? [],
|
|
1876
|
+
nameSegments: [getSchemaNameByRef(schemaRef)]
|
|
1877
|
+
});
|
|
1878
|
+
});
|
|
1879
|
+
resolveExtractedEnumZodSchemaTags(this);
|
|
1880
|
+
this.handleDuplicateEnumZodSchemas();
|
|
1881
|
+
resolveExtractedEnumZodSchemaNames(this);
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
handleDuplicateEnumZodSchemas() {
|
|
1885
|
+
const codes = new Set(this.enumZodSchemas.map(({ code }) => code));
|
|
1886
|
+
const duplicates = this.enumZodSchemas.filter(({ code }) => codes.has(code));
|
|
1887
|
+
this.schemaData.forEach((schemaData) => {
|
|
1888
|
+
const duplicateCode = duplicates.find(({ zodSchemaName }) => zodSchemaName === schemaData.zodSchemaName)?.code;
|
|
1889
|
+
if (!duplicateCode) return;
|
|
1890
|
+
const duplicate = this.extractedEnumZodSchemaData.find(({ code }) => code === duplicateCode);
|
|
1891
|
+
if (!duplicate || this.getEnumZodSchemaDataByCode(duplicate.code)?.zodSchemaName !== schemaData.zodSchemaName) return;
|
|
1892
|
+
schemaData.tags.push(...duplicate.meta.tags ?? []);
|
|
1893
|
+
duplicate.meta.schemaRefs.forEach((ref) => {
|
|
1894
|
+
if (!this.dependencyGraph.refsDependencyGraph[ref]) this.dependencyGraph.refsDependencyGraph[ref] = /* @__PURE__ */ new Set();
|
|
1895
|
+
this.dependencyGraph.refsDependencyGraph[ref].add(schemaData.ref);
|
|
1896
|
+
if (!this.dependencyGraph.deepDependencyGraph[ref]) this.dependencyGraph.deepDependencyGraph[ref] = /* @__PURE__ */ new Set();
|
|
1897
|
+
this.dependencyGraph.deepDependencyGraph[ref].add(schemaData.ref);
|
|
1898
|
+
});
|
|
1899
|
+
});
|
|
1900
|
+
this.extractedEnumZodSchemaData.splice(0, this.extractedEnumZodSchemaData.length, ...this.extractedEnumZodSchemaData.filter(({ code }) => !codes.has(code)));
|
|
1901
|
+
}
|
|
1902
|
+
getParameters(parameters) {
|
|
1903
|
+
return Object.fromEntries((parameters ?? []).map((param) => [isReferenceObject(param) ? param.$ref : param.name, param]));
|
|
1904
|
+
}
|
|
1905
|
+
};
|
|
1906
|
+
//#endregion
|
|
1907
|
+
//#region src/generators/utils/sort.utils.ts
|
|
1908
|
+
/** @see https://gist.github.com/RubyTuesdayDONO/5006455 */
|
|
1909
|
+
function topologicalSort(graph) {
|
|
1910
|
+
const sorted = [];
|
|
1911
|
+
const sortedNames = /* @__PURE__ */ new Set();
|
|
1912
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1913
|
+
function visit(name, ancestors) {
|
|
1914
|
+
ancestors.add(name);
|
|
1915
|
+
visited.add(name);
|
|
1916
|
+
if (graph[name]) graph[name].forEach((dep) => {
|
|
1917
|
+
if (ancestors.has(dep)) return;
|
|
1918
|
+
if (visited.has(dep)) return;
|
|
1919
|
+
visit(dep, ancestors);
|
|
1920
|
+
});
|
|
1921
|
+
ancestors.delete(name);
|
|
1922
|
+
if (!sortedNames.has(name)) {
|
|
1923
|
+
sortedNames.add(name);
|
|
1924
|
+
sorted.push(name);
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
Object.keys(graph).forEach((name) => visit(name, /* @__PURE__ */ new Set()));
|
|
1928
|
+
return sorted;
|
|
1929
|
+
}
|
|
1930
|
+
/** Sort object keys using a reference order array, sort keys not in reference order in lasts positions */
|
|
1931
|
+
function sortObjKeysFromArray(obj, orderedKeys) {
|
|
1932
|
+
const entries = Object.entries(obj);
|
|
1933
|
+
const keyRanks = new Map(orderedKeys.map((key, index) => [key, index]));
|
|
1934
|
+
const orderedEntries = [];
|
|
1935
|
+
const remainingEntries = [];
|
|
1936
|
+
for (const entry of entries) (keyRanks.has(entry[0]) ? orderedEntries : remainingEntries).push(entry);
|
|
1937
|
+
orderedEntries.sort(([a], [b]) => keyRanks.get(a) - keyRanks.get(b));
|
|
1938
|
+
return Object.fromEntries(orderedEntries.concat(remainingEntries));
|
|
1939
|
+
}
|
|
1940
|
+
//#endregion
|
|
1941
|
+
//#region src/generators/core/zod/sortZodSchemasByTopology.ts
|
|
1942
|
+
function sortZodSchemasByTopology(resolver, zodSchemas) {
|
|
1943
|
+
return sortObjKeysFromArray(zodSchemas, topologicalSort(resolver.dependencyGraph.deepDependencyGraph).map((ref) => resolver.getZodSchemaNameByRef(ref)));
|
|
1944
|
+
}
|
|
1945
|
+
//#endregion
|
|
1946
|
+
//#region src/generators/core/getDataFromOpenAPIDoc.ts
|
|
1947
|
+
function getDataFromOpenAPIDoc(openApiDoc, options, profiler) {
|
|
1948
|
+
const p = profiler ?? new Profiler(false);
|
|
1949
|
+
const resolver = p.runSync("data.resolver.init", () => new SchemaResolver(openApiDoc, options, p));
|
|
1950
|
+
const endpoints = p.runSync("data.endpoints.extract", () => getEndpointsFromOpenAPIDoc(resolver, p));
|
|
1951
|
+
const zodSchemasFromDocSchemas = p.runSync("data.zod.extract", () => getZodSchemasFromOpenAPIDoc(resolver, p));
|
|
1952
|
+
resolver.enableZodSchemaTagCache();
|
|
1953
|
+
let zodSchemas = {
|
|
1954
|
+
...zodSchemasFromDocSchemas.zodSchemas,
|
|
1955
|
+
...resolver.getZodSchemas(),
|
|
1956
|
+
...zodSchemasFromDocSchemas.enumZodSchemas
|
|
1957
|
+
};
|
|
1958
|
+
zodSchemas = p.runSync("data.zod.sortTopology", () => sortZodSchemasByTopology(resolver, zodSchemas));
|
|
1959
|
+
zodSchemas = {
|
|
1960
|
+
...resolver.getExtractedEnumZodSchemas(),
|
|
1961
|
+
...zodSchemas
|
|
1962
|
+
};
|
|
1963
|
+
return {
|
|
1964
|
+
resolver,
|
|
1965
|
+
data: p.runSync("data.splitByTags", () => splitDataByTags({
|
|
1966
|
+
resolver,
|
|
1967
|
+
endpoints,
|
|
1968
|
+
zodSchemas,
|
|
1969
|
+
options
|
|
1970
|
+
}))
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
function splitDataByTags({ resolver, endpoints, zodSchemas, options }) {
|
|
1974
|
+
const data = /* @__PURE__ */ new Map();
|
|
1975
|
+
if (!options.splitByTags) {
|
|
1976
|
+
data.set(options.defaultTag, {
|
|
1977
|
+
endpoints,
|
|
1978
|
+
zodSchemas
|
|
1979
|
+
});
|
|
1980
|
+
return data;
|
|
1981
|
+
}
|
|
1982
|
+
endpoints.forEach((endpoint) => {
|
|
1983
|
+
getTagElement(getEndpointTag(endpoint, options), data).endpoints.push(endpoint);
|
|
1984
|
+
});
|
|
1985
|
+
Object.entries(zodSchemas).forEach(([zodSchemaName, zodSchemaCode]) => {
|
|
1986
|
+
if (options.modelsInModules) {
|
|
1987
|
+
for (const tag of resolver.getTagsByZodSchemaName(zodSchemaName)) getTagElement(tag, data).zodSchemas[zodSchemaName] = zodSchemaCode;
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
const tag = options.modelsInCommon ? options.defaultTag : resolver.getTagByZodSchemaName(zodSchemaName);
|
|
1991
|
+
if (tag) getTagElement(tag, data).zodSchemas[zodSchemaName] = zodSchemaCode;
|
|
1992
|
+
});
|
|
1993
|
+
if (options.modelsInModules) for (const tagData of data.values()) {
|
|
1994
|
+
const pending = Object.keys(tagData.zodSchemas);
|
|
1995
|
+
for (let index = 0; index < pending.length; index++) for (const dependencyName of getZodSchemaRefs(resolver, pending[index])) {
|
|
1996
|
+
if (tagData.zodSchemas[dependencyName] || !zodSchemas[dependencyName]) continue;
|
|
1997
|
+
tagData.zodSchemas[dependencyName] = zodSchemas[dependencyName];
|
|
1998
|
+
pending.push(dependencyName);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
return data;
|
|
2002
|
+
}
|
|
2003
|
+
function getTagElement(tag, data) {
|
|
2004
|
+
if (!data.has(tag)) data.set(tag, {
|
|
2005
|
+
endpoints: [],
|
|
2006
|
+
zodSchemas: {}
|
|
2007
|
+
});
|
|
2008
|
+
return data.get(tag);
|
|
2009
|
+
}
|
|
2010
|
+
//#endregion
|
|
2011
|
+
export { VALIDATION_ERROR_TYPE_TITLE as i, groupByType as n, getZodSchemaRefs as r, getDataFromOpenAPIDoc as t };
|