@orval/core 8.1.0 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +150 -74
- package/dist/index.mjs +1524 -1332
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -6
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { t as __export } from "./chunk-C6wwvPpM.mjs";
|
|
2
|
-
import { entries, groupBy, isArray, isEmptyish, prop, unique, uniqueBy, uniqueWith } from "remeda";
|
|
2
|
+
import { entries, groupBy, isArray, isBoolean, isBoolean as isBoolean$1, isEmptyish, isFunction, isNullish, isNullish as isNullish$1, isNumber, isString, isString as isString$1, prop, unique, uniqueBy, uniqueWith } from "remeda";
|
|
3
3
|
import { keyword } from "esutils";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import fs from "node:fs";
|
|
6
|
-
import { globby } from "globby";
|
|
7
5
|
import { compare } from "compare-versions";
|
|
8
6
|
import debug from "debug";
|
|
9
7
|
import { pathToFileURL } from "node:url";
|
|
8
|
+
import fs from "node:fs";
|
|
9
|
+
import { globby } from "globby";
|
|
10
10
|
import readline from "node:readline";
|
|
11
11
|
import chalk from "chalk";
|
|
12
12
|
import { isDereferenced } from "@scalar/openapi-types/helpers";
|
|
@@ -108,124 +108,20 @@ const generalJSTypes = [
|
|
|
108
108
|
"object",
|
|
109
109
|
"blob"
|
|
110
110
|
];
|
|
111
|
-
const generalJSTypesWithArray = generalJSTypes.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
111
|
+
const generalJSTypesWithArray = generalJSTypes.flatMap((type) => [
|
|
112
|
+
type,
|
|
113
|
+
`Array<${type}>`,
|
|
114
|
+
`${type}[]`
|
|
115
|
+
]);
|
|
115
116
|
const VERBS_WITH_BODY = [
|
|
116
117
|
Verbs.POST,
|
|
117
118
|
Verbs.PUT,
|
|
118
119
|
Verbs.PATCH,
|
|
119
120
|
Verbs.DELETE
|
|
120
121
|
];
|
|
121
|
-
const URL_REGEX = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w
|
|
122
|
+
const URL_REGEX = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/;
|
|
122
123
|
const TEMPLATE_TAG_REGEX = /\${(.+?)}/g;
|
|
123
124
|
|
|
124
|
-
//#endregion
|
|
125
|
-
//#region src/utils/extension.ts
|
|
126
|
-
function getExtension(path$2) {
|
|
127
|
-
return path$2.toLowerCase().includes(".yaml") || path$2.toLowerCase().includes(".yml") ? "yaml" : "json";
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
//#endregion
|
|
131
|
-
//#region src/utils/file.ts
|
|
132
|
-
function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
|
|
133
|
-
const isDir = isDirectory(target);
|
|
134
|
-
const filePath = isDir ? path.join(target, backupFilename + extension) : target;
|
|
135
|
-
return {
|
|
136
|
-
path: filePath,
|
|
137
|
-
pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
|
|
138
|
-
extension,
|
|
139
|
-
isDirectory: isDir,
|
|
140
|
-
dirname: path.dirname(filePath),
|
|
141
|
-
filename: path.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
145
|
-
const files = await globby(patterns, {
|
|
146
|
-
cwd: dir,
|
|
147
|
-
absolute: true
|
|
148
|
-
});
|
|
149
|
-
await Promise.all(files.map((file) => fs.promises.unlink(file)));
|
|
150
|
-
const sortedDirectories = (await globby(["**/*"], {
|
|
151
|
-
cwd: dir,
|
|
152
|
-
absolute: true,
|
|
153
|
-
onlyDirectories: true
|
|
154
|
-
})).toSorted((a, b) => {
|
|
155
|
-
const depthA = a.split("/").length;
|
|
156
|
-
return b.split("/").length - depthA;
|
|
157
|
-
});
|
|
158
|
-
for (const directory of sortedDirectories) try {
|
|
159
|
-
if ((await fs.promises.readdir(directory)).length === 0) await fs.promises.rmdir(directory);
|
|
160
|
-
} catch {}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
//#endregion
|
|
164
|
-
//#region src/utils/path.ts
|
|
165
|
-
var path_exports = /* @__PURE__ */ __export({
|
|
166
|
-
basename: () => basename,
|
|
167
|
-
dirname: () => dirname,
|
|
168
|
-
extname: () => extname,
|
|
169
|
-
getSchemaFileName: () => getSchemaFileName,
|
|
170
|
-
isAbsolute: () => isAbsolute,
|
|
171
|
-
join: () => join,
|
|
172
|
-
joinSafe: () => joinSafe,
|
|
173
|
-
normalizeSafe: () => normalizeSafe,
|
|
174
|
-
relativeSafe: () => relativeSafe,
|
|
175
|
-
resolve: () => resolve,
|
|
176
|
-
separator: () => separator
|
|
177
|
-
});
|
|
178
|
-
const path$1 = {};
|
|
179
|
-
const isFunction$1 = (val) => typeof val == "function";
|
|
180
|
-
const isString$1 = (val) => {
|
|
181
|
-
if (typeof val === "string") return true;
|
|
182
|
-
if (typeof val === "object" && val !== null) return Object.toString.call(val) == "[object String]";
|
|
183
|
-
return false;
|
|
184
|
-
};
|
|
185
|
-
for (const [propName, propValue] of Object.entries(path)) if (isFunction$1(propValue)) path$1[propName] = ((propName$1) => {
|
|
186
|
-
return (...args) => {
|
|
187
|
-
args = args.map((p) => {
|
|
188
|
-
return isString$1(p) ? toUnix(p) : p;
|
|
189
|
-
});
|
|
190
|
-
const result = path[propName$1](...args);
|
|
191
|
-
return isString$1(result) ? toUnix(result) : result;
|
|
192
|
-
};
|
|
193
|
-
})(propName);
|
|
194
|
-
else path$1[propName] = propValue;
|
|
195
|
-
const { join, resolve, extname, dirname, basename, isAbsolute } = path$1;
|
|
196
|
-
/**
|
|
197
|
-
* Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
|
|
198
|
-
*/
|
|
199
|
-
function relativeSafe(from, to) {
|
|
200
|
-
return normalizeSafe(`.${separator}${path$1.relative(from, to)}`);
|
|
201
|
-
}
|
|
202
|
-
function getSchemaFileName(path$2) {
|
|
203
|
-
return path$2.replace(`.${getExtension(path$2)}`, "").slice(path$2.lastIndexOf("/") + 1);
|
|
204
|
-
}
|
|
205
|
-
const separator = "/";
|
|
206
|
-
const toUnix = function(value) {
|
|
207
|
-
value = value.replaceAll("\\", "/");
|
|
208
|
-
value = value.replaceAll(/(?<!^)\/+/g, "/");
|
|
209
|
-
return value;
|
|
210
|
-
};
|
|
211
|
-
function normalizeSafe(value) {
|
|
212
|
-
let result;
|
|
213
|
-
value = toUnix(value);
|
|
214
|
-
result = path$1.normalize(value);
|
|
215
|
-
if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
216
|
-
else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
|
|
217
|
-
return result;
|
|
218
|
-
}
|
|
219
|
-
function joinSafe(...values) {
|
|
220
|
-
let result = path$1.join(...values);
|
|
221
|
-
if (values.length > 0) {
|
|
222
|
-
const firstValue = toUnix(values[0]);
|
|
223
|
-
if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
224
|
-
else if (firstValue.startsWith("//") && !result.startsWith("//")) result = firstValue.startsWith("//./") ? "//." + result : "/" + result;
|
|
225
|
-
}
|
|
226
|
-
return result;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
125
|
//#endregion
|
|
230
126
|
//#region src/utils/assertion.ts
|
|
231
127
|
/**
|
|
@@ -234,42 +130,29 @@ function joinSafe(...values) {
|
|
|
234
130
|
* @param property
|
|
235
131
|
*/
|
|
236
132
|
function isReference(obj) {
|
|
237
|
-
return !
|
|
133
|
+
return !isNullish$1(obj) && Object.hasOwn(obj, "$ref");
|
|
238
134
|
}
|
|
239
|
-
function isDirectory(
|
|
240
|
-
return !extname(
|
|
135
|
+
function isDirectory(pathValue) {
|
|
136
|
+
return !path.extname(pathValue);
|
|
241
137
|
}
|
|
242
138
|
function isObject(x) {
|
|
243
139
|
return Object.prototype.toString.call(x) === "[object Object]";
|
|
244
140
|
}
|
|
141
|
+
function isStringLike(val) {
|
|
142
|
+
if (isString$1(val)) return true;
|
|
143
|
+
return Object.prototype.toString.call(val) === "[object String]";
|
|
144
|
+
}
|
|
245
145
|
function isModule(x) {
|
|
246
146
|
return Object.prototype.toString.call(x) === "[object Module]";
|
|
247
147
|
}
|
|
248
|
-
function isString(x) {
|
|
249
|
-
return typeof x === "string";
|
|
250
|
-
}
|
|
251
|
-
function isNumber(x) {
|
|
252
|
-
return typeof x === "number";
|
|
253
|
-
}
|
|
254
148
|
function isNumeric(x) {
|
|
255
|
-
return
|
|
256
|
-
|
|
257
|
-
function isBoolean(x) {
|
|
258
|
-
return typeof x === "boolean";
|
|
259
|
-
}
|
|
260
|
-
function isFunction(x) {
|
|
261
|
-
return typeof x === "function";
|
|
262
|
-
}
|
|
263
|
-
function isUndefined(x) {
|
|
264
|
-
return x === void 0;
|
|
265
|
-
}
|
|
266
|
-
function isNull(x) {
|
|
267
|
-
return x === null;
|
|
149
|
+
if (typeof x === "number") return Number.isInteger(x);
|
|
150
|
+
return isString$1(x) && /^-?\d+$/.test(x);
|
|
268
151
|
}
|
|
269
152
|
function isSchema(x) {
|
|
270
153
|
if (!isObject(x)) return false;
|
|
271
|
-
if (isString(x.type) && Object.values(SchemaType).includes(x.type)) return true;
|
|
272
|
-
const combine = x.allOf
|
|
154
|
+
if (isString$1(x.type) && Object.values(SchemaType).includes(x.type)) return true;
|
|
155
|
+
const combine = x.allOf ?? x.anyOf ?? x.oneOf;
|
|
273
156
|
if (Array.isArray(combine)) return true;
|
|
274
157
|
if (isObject(x.properties)) return true;
|
|
275
158
|
return false;
|
|
@@ -278,27 +161,26 @@ function isVerb(verb) {
|
|
|
278
161
|
return Object.values(Verbs).includes(verb);
|
|
279
162
|
}
|
|
280
163
|
function isUrl(str) {
|
|
281
|
-
|
|
164
|
+
if (!str.trim()) return false;
|
|
282
165
|
try {
|
|
283
|
-
|
|
166
|
+
const url = new URL(str);
|
|
167
|
+
return ["http:", "https:"].includes(url.protocol);
|
|
284
168
|
} catch {
|
|
285
169
|
return false;
|
|
286
170
|
}
|
|
287
|
-
return givenURL.protocol === "http:" || givenURL.protocol === "https:";
|
|
288
171
|
}
|
|
289
172
|
|
|
290
173
|
//#endregion
|
|
291
174
|
//#region src/utils/async-reduce.ts
|
|
292
175
|
async function asyncReduce(array, reducer, initValue) {
|
|
293
|
-
let accumulate =
|
|
176
|
+
let accumulate = initValue === null || initValue === Object(initValue) && !isFunction(initValue) ? Object.create(initValue) : initValue;
|
|
294
177
|
for (const item of array) accumulate = await reducer(accumulate, item);
|
|
295
178
|
return accumulate;
|
|
296
179
|
}
|
|
297
180
|
|
|
298
181
|
//#endregion
|
|
299
182
|
//#region src/utils/case.ts
|
|
300
|
-
const unicodes = function(s, prefix) {
|
|
301
|
-
prefix = prefix || "";
|
|
183
|
+
const unicodes = function(s, prefix = "") {
|
|
302
184
|
return s.replaceAll(/(^|-)/g, String.raw`$1\u` + prefix).replaceAll(",", String.raw`\u` + prefix);
|
|
303
185
|
};
|
|
304
186
|
const symbols = unicodes("20-26,28-2F,3A-40,5B-60,7B-7E,A0-BF,D7,F7", "00");
|
|
@@ -320,8 +202,8 @@ const regexps = {
|
|
|
320
202
|
const deapostrophe = (s) => {
|
|
321
203
|
return s.replace(regexps.apostrophe, "");
|
|
322
204
|
};
|
|
323
|
-
const up =
|
|
324
|
-
const low =
|
|
205
|
+
const up = (s) => s.toUpperCase();
|
|
206
|
+
const low = (s) => s.toLowerCase();
|
|
325
207
|
const fill = (s, fillWith, isDeapostrophe = false) => {
|
|
326
208
|
s = s.replace(regexps.fill, function(m, next) {
|
|
327
209
|
return next ? fillWith + next : "";
|
|
@@ -330,14 +212,13 @@ const fill = (s, fillWith, isDeapostrophe = false) => {
|
|
|
330
212
|
return s;
|
|
331
213
|
};
|
|
332
214
|
const decap = (s, char = 0) => {
|
|
333
|
-
return low
|
|
215
|
+
return low(s.charAt(char)) + s.slice(char + 1);
|
|
334
216
|
};
|
|
335
217
|
const relax = (m, before, acronym, caps) => {
|
|
336
218
|
return before + " " + (acronym ? acronym + " " : "") + caps;
|
|
337
219
|
};
|
|
338
220
|
const prep = (s, isFill = false, isPascal = false, isUpper = false) => {
|
|
339
|
-
|
|
340
|
-
if (!isUpper && regexps.upper.test(s)) s = low.call(s);
|
|
221
|
+
if (!isUpper && regexps.upper.test(s)) s = low(s);
|
|
341
222
|
if (!isFill && !regexps.hole.test(s)) {
|
|
342
223
|
var holey = fill(s, " ");
|
|
343
224
|
if (regexps.hole.test(holey)) s = holey;
|
|
@@ -346,20 +227,20 @@ const prep = (s, isFill = false, isPascal = false, isUpper = false) => {
|
|
|
346
227
|
return s;
|
|
347
228
|
};
|
|
348
229
|
const lower = (s, fillWith, isDeapostrophe) => {
|
|
349
|
-
return fill(low
|
|
230
|
+
return fill(low(prep(s, !!fillWith)), fillWith, isDeapostrophe);
|
|
350
231
|
};
|
|
351
232
|
const pascalMemory = {};
|
|
352
|
-
function pascal(s) {
|
|
233
|
+
function pascal(s = "") {
|
|
353
234
|
if (pascalMemory[s]) return pascalMemory[s];
|
|
354
|
-
const isStartWithUnderscore = s
|
|
355
|
-
if (regexps.upper.test(s)) s = low
|
|
356
|
-
const pascalString = (s
|
|
235
|
+
const isStartWithUnderscore = s.startsWith("_");
|
|
236
|
+
if (regexps.upper.test(s)) s = low(s);
|
|
237
|
+
const pascalString = (s.match(/[a-zA-Z0-9\u00C0-\u017F]+/g) ?? []).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
|
|
357
238
|
const pascalWithUnderscore = isStartWithUnderscore ? `_${pascalString}` : pascalString;
|
|
358
239
|
pascalMemory[s] = pascalWithUnderscore;
|
|
359
240
|
return pascalWithUnderscore;
|
|
360
241
|
}
|
|
361
|
-
function camel(s) {
|
|
362
|
-
const isStartWithUnderscore = s
|
|
242
|
+
function camel(s = "") {
|
|
243
|
+
const isStartWithUnderscore = s.startsWith("_");
|
|
363
244
|
const camelString = decap(pascal(s), isStartWithUnderscore ? 1 : 0);
|
|
364
245
|
return isStartWithUnderscore ? `_${camelString}` : camelString;
|
|
365
246
|
}
|
|
@@ -370,7 +251,7 @@ function kebab(s) {
|
|
|
370
251
|
return lower(s, "-", true);
|
|
371
252
|
}
|
|
372
253
|
function upper(s, fillWith, isDeapostrophe) {
|
|
373
|
-
return fill(up
|
|
254
|
+
return fill(up(prep(s, !!fillWith, false, true)), fillWith, isDeapostrophe);
|
|
374
255
|
}
|
|
375
256
|
function conventionName(name, convention) {
|
|
376
257
|
let nameConventionTransform = camel;
|
|
@@ -396,6 +277,87 @@ function compareVersions(firstVersion, secondVersions, operator = ">=") {
|
|
|
396
277
|
return compare(firstVersion.replace(/(\s(.*))/, ""), secondVersions, operator);
|
|
397
278
|
}
|
|
398
279
|
|
|
280
|
+
//#endregion
|
|
281
|
+
//#region src/utils/content-type.ts
|
|
282
|
+
/**
|
|
283
|
+
* Determine if a content type is binary (vs text-based).
|
|
284
|
+
*/
|
|
285
|
+
function isBinaryContentType(contentType) {
|
|
286
|
+
if (contentType === "application/octet-stream") return true;
|
|
287
|
+
if (contentType.startsWith("image/")) return true;
|
|
288
|
+
if (contentType.startsWith("audio/")) return true;
|
|
289
|
+
if (contentType.startsWith("video/")) return true;
|
|
290
|
+
if (contentType.startsWith("font/")) return true;
|
|
291
|
+
if (contentType.startsWith("text/")) return false;
|
|
292
|
+
if ([
|
|
293
|
+
"+json",
|
|
294
|
+
"-json",
|
|
295
|
+
"+xml",
|
|
296
|
+
"-xml",
|
|
297
|
+
"+yaml",
|
|
298
|
+
"-yaml",
|
|
299
|
+
"+rss",
|
|
300
|
+
"-rss",
|
|
301
|
+
"+csv",
|
|
302
|
+
"-csv"
|
|
303
|
+
].some((suffix) => contentType.includes(suffix))) return false;
|
|
304
|
+
return !new Set([
|
|
305
|
+
"application/json",
|
|
306
|
+
"application/xml",
|
|
307
|
+
"application/yaml",
|
|
308
|
+
"application/x-www-form-urlencoded",
|
|
309
|
+
"application/javascript",
|
|
310
|
+
"application/ecmascript",
|
|
311
|
+
"application/graphql"
|
|
312
|
+
]).has(contentType);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Determine if a form-data field should be treated as a file (binary or text).
|
|
316
|
+
*
|
|
317
|
+
* Precedence (per OAS 3.1): encoding.contentType > schema.contentMediaType
|
|
318
|
+
*
|
|
319
|
+
* Returns:
|
|
320
|
+
* - 'binary': binary file (Blob)
|
|
321
|
+
* - 'text': text file (Blob | string)
|
|
322
|
+
* - undefined: not a file, use standard string resolution
|
|
323
|
+
*/
|
|
324
|
+
function getFormDataFieldFileType(resolvedSchema, partContentType) {
|
|
325
|
+
if (resolvedSchema.type !== "string") return;
|
|
326
|
+
if (resolvedSchema.contentEncoding) return;
|
|
327
|
+
const contentMediaType = resolvedSchema.contentMediaType;
|
|
328
|
+
const effectiveContentType = partContentType ?? contentMediaType;
|
|
329
|
+
if (effectiveContentType) return isBinaryContentType(effectiveContentType) ? "binary" : "text";
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Filters items by content type based on include/exclude rules
|
|
333
|
+
*
|
|
334
|
+
* @param items - Array of items with contentType property
|
|
335
|
+
* @param filter - Optional filter configuration
|
|
336
|
+
* @returns Filtered array
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* ```ts
|
|
340
|
+
* const types = [
|
|
341
|
+
* { contentType: 'application/json', value: '...' },
|
|
342
|
+
* { contentType: 'text/xml', value: '...' }
|
|
343
|
+
* ];
|
|
344
|
+
*
|
|
345
|
+
* // Include only JSON
|
|
346
|
+
* filterByContentType(types, { include: ['application/json'] });
|
|
347
|
+
*
|
|
348
|
+
* // Exclude XML
|
|
349
|
+
* filterByContentType(types, { exclude: ['text/xml'] });
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
function filterByContentType(items, filter$1) {
|
|
353
|
+
if (!filter$1) return items;
|
|
354
|
+
return items.filter((item) => {
|
|
355
|
+
const shouldInclude = !filter$1.include || filter$1.include.includes(item.contentType);
|
|
356
|
+
const shouldExclude = filter$1.exclude?.includes(item.contentType) ?? false;
|
|
357
|
+
return shouldInclude && !shouldExclude;
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
|
|
399
361
|
//#endregion
|
|
400
362
|
//#region src/utils/debug.ts
|
|
401
363
|
const filter = process.env.ORVAL_DEBUG_FILTER;
|
|
@@ -403,7 +365,7 @@ const DEBUG = process.env.DEBUG;
|
|
|
403
365
|
function createDebugger(ns, options = {}) {
|
|
404
366
|
const log$1 = debug(ns);
|
|
405
367
|
const { onlyWhenFocused } = options;
|
|
406
|
-
const focus =
|
|
368
|
+
const focus = isString(onlyWhenFocused) ? onlyWhenFocused : ns;
|
|
407
369
|
return (msg, ...args) => {
|
|
408
370
|
if (filter && !msg.includes(filter)) return;
|
|
409
371
|
if (onlyWhenFocused && !DEBUG?.includes(focus)) return;
|
|
@@ -417,13 +379,13 @@ const search = String.raw`\*/`;
|
|
|
417
379
|
const replacement = String.raw`*\/`;
|
|
418
380
|
const regex$1 = new RegExp(search, "g");
|
|
419
381
|
function jsDoc(schema, tryOneLine = false, context) {
|
|
420
|
-
if (context?.output
|
|
382
|
+
if (context?.output.override.jsDoc) {
|
|
421
383
|
const { filter: filter$1 } = context.output.override.jsDoc;
|
|
422
384
|
if (filter$1) return keyValuePairsToJsDoc(filter$1(schema));
|
|
423
385
|
}
|
|
424
386
|
const { description, deprecated, summary, minLength, maxLength, minimum, maximum, exclusiveMinimum, exclusiveMaximum, minItems, maxItems, pattern } = schema;
|
|
425
387
|
const isNullable = schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null");
|
|
426
|
-
const lines = (Array.isArray(description) ? description.filter((d) => !d.includes("eslint-disable")) : [description
|
|
388
|
+
const lines = (Array.isArray(description) ? description.filter((d) => !d.includes("eslint-disable")) : [description ?? ""]).map((line) => line.replaceAll(regex$1, replacement));
|
|
427
389
|
const count$1 = [
|
|
428
390
|
description,
|
|
429
391
|
deprecated,
|
|
@@ -438,7 +400,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
438
400
|
maxItems?.toString(),
|
|
439
401
|
isNullable ? "null" : "",
|
|
440
402
|
pattern
|
|
441
|
-
].
|
|
403
|
+
].filter(Boolean).length;
|
|
442
404
|
if (!count$1) return "";
|
|
443
405
|
const oneLine = count$1 === 1 && tryOneLine;
|
|
444
406
|
const eslintDisable = Array.isArray(description) ? description.find((d) => d.includes("eslint-disable"))?.replaceAll(regex$1, replacement) : void 0;
|
|
@@ -505,10 +467,49 @@ async function dynamicImport(toImport, from = process.cwd(), takeDefault = true)
|
|
|
505
467
|
}
|
|
506
468
|
return toImport;
|
|
507
469
|
} catch (error) {
|
|
508
|
-
throw new Error(`Oups... 🍻. Path: ${toImport} => ${error}`);
|
|
470
|
+
throw new Error(`Oups... 🍻. Path: ${String(toImport)} => ${String(error)}`);
|
|
509
471
|
}
|
|
510
472
|
}
|
|
511
473
|
|
|
474
|
+
//#endregion
|
|
475
|
+
//#region src/utils/extension.ts
|
|
476
|
+
function getExtension(path$2) {
|
|
477
|
+
return path$2.toLowerCase().includes(".yaml") || path$2.toLowerCase().includes(".yml") ? "yaml" : "json";
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
//#endregion
|
|
481
|
+
//#region src/utils/file.ts
|
|
482
|
+
function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
|
|
483
|
+
const isDir = isDirectory(target);
|
|
484
|
+
const filePath = isDir ? path.join(target, backupFilename + extension) : target;
|
|
485
|
+
return {
|
|
486
|
+
path: filePath,
|
|
487
|
+
pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
|
|
488
|
+
extension,
|
|
489
|
+
isDirectory: isDir,
|
|
490
|
+
dirname: path.dirname(filePath),
|
|
491
|
+
filename: path.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
495
|
+
const files = await globby(patterns, {
|
|
496
|
+
cwd: dir,
|
|
497
|
+
absolute: true
|
|
498
|
+
});
|
|
499
|
+
await Promise.all(files.map((file) => fs.promises.unlink(file)));
|
|
500
|
+
const sortedDirectories = (await globby(["**/*"], {
|
|
501
|
+
cwd: dir,
|
|
502
|
+
absolute: true,
|
|
503
|
+
onlyDirectories: true
|
|
504
|
+
})).toSorted((a, b) => {
|
|
505
|
+
const depthA = a.split("/").length;
|
|
506
|
+
return b.split("/").length - depthA;
|
|
507
|
+
});
|
|
508
|
+
for (const directory of sortedDirectories) try {
|
|
509
|
+
if ((await fs.promises.readdir(directory)).length === 0) await fs.promises.rmdir(directory);
|
|
510
|
+
} catch {}
|
|
511
|
+
}
|
|
512
|
+
|
|
512
513
|
//#endregion
|
|
513
514
|
//#region src/utils/file-extensions.ts
|
|
514
515
|
function getMockFileExtensionByTypeName(mock) {
|
|
@@ -557,7 +558,7 @@ function logError(err, tag) {
|
|
|
557
558
|
if (err instanceof Error) {
|
|
558
559
|
message = (err.message || err.stack) ?? "Unknown error";
|
|
559
560
|
if (err.cause) {
|
|
560
|
-
const causeMsg = err.cause instanceof Error ? err.cause.message :
|
|
561
|
+
const causeMsg = err.cause instanceof Error ? err.cause.message : isString(err.cause) ? err.cause : JSON.stringify(err.cause, void 0, 2);
|
|
561
562
|
message += `\n Cause: ${causeMsg}`;
|
|
562
563
|
}
|
|
563
564
|
} else message = String(err);
|
|
@@ -644,16 +645,16 @@ function createLogger(level = "info", options = {}) {
|
|
|
644
645
|
|
|
645
646
|
//#endregion
|
|
646
647
|
//#region src/utils/merge-deep.ts
|
|
647
|
-
const isObject$1 = (obj) => obj && typeof obj === "object";
|
|
648
648
|
function mergeDeep(source, target) {
|
|
649
|
-
if (!isObject
|
|
650
|
-
|
|
649
|
+
if (!isObject(target) || !isObject(source)) return source;
|
|
650
|
+
const acc = Object.assign({}, source);
|
|
651
|
+
for (const [key, value] of Object.entries(target)) {
|
|
651
652
|
const sourceValue = acc[key];
|
|
652
653
|
if (Array.isArray(sourceValue) && Array.isArray(value)) acc[key] = [...sourceValue, ...value];
|
|
653
|
-
else if (isObject
|
|
654
|
+
else if (isObject(sourceValue) && isObject(value)) acc[key] = mergeDeep(sourceValue, value);
|
|
654
655
|
else acc[key] = value;
|
|
655
|
-
|
|
656
|
-
|
|
656
|
+
}
|
|
657
|
+
return acc;
|
|
657
658
|
}
|
|
658
659
|
|
|
659
660
|
//#endregion
|
|
@@ -663,9 +664,65 @@ function count(str = "", key) {
|
|
|
663
664
|
return (str.match(new RegExp(key, "g")) ?? []).length;
|
|
664
665
|
}
|
|
665
666
|
|
|
667
|
+
//#endregion
|
|
668
|
+
//#region src/utils/path.ts
|
|
669
|
+
var path_exports = /* @__PURE__ */ __export({
|
|
670
|
+
basename: () => basename,
|
|
671
|
+
dirname: () => dirname,
|
|
672
|
+
extname: () => extname,
|
|
673
|
+
getSchemaFileName: () => getSchemaFileName,
|
|
674
|
+
isAbsolute: () => isAbsolute,
|
|
675
|
+
join: () => join,
|
|
676
|
+
joinSafe: () => joinSafe,
|
|
677
|
+
normalizeSafe: () => normalizeSafe,
|
|
678
|
+
relativeSafe: () => relativeSafe,
|
|
679
|
+
resolve: () => resolve,
|
|
680
|
+
separator: () => separator
|
|
681
|
+
});
|
|
682
|
+
function wrapPathFn(fn) {
|
|
683
|
+
return (...args) => {
|
|
684
|
+
const result = fn(...args.map((p) => isStringLike(p) ? toUnix(p) : p));
|
|
685
|
+
return isStringLike(result) ? toUnix(result) : result;
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
const path$1 = Object.fromEntries(Object.entries(path).map(([key, value]) => [key, isFunction(value) ? wrapPathFn(value) : value]));
|
|
689
|
+
const { join, resolve, extname, dirname, basename, isAbsolute } = path$1;
|
|
690
|
+
/**
|
|
691
|
+
* Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
|
|
692
|
+
*/
|
|
693
|
+
function relativeSafe(from, to) {
|
|
694
|
+
return normalizeSafe(`.${separator}${path$1.relative(from, to)}`);
|
|
695
|
+
}
|
|
696
|
+
function getSchemaFileName(path$2) {
|
|
697
|
+
return path$2.replace(`.${getExtension(path$2)}`, "").slice(path$2.lastIndexOf("/") + 1);
|
|
698
|
+
}
|
|
699
|
+
const separator = "/";
|
|
700
|
+
const toUnix = function(value) {
|
|
701
|
+
value = value.replaceAll("\\", "/");
|
|
702
|
+
value = value.replaceAll(/(?<!^)\/+/g, "/");
|
|
703
|
+
return value;
|
|
704
|
+
};
|
|
705
|
+
function normalizeSafe(value) {
|
|
706
|
+
let result;
|
|
707
|
+
value = toUnix(value);
|
|
708
|
+
result = path$1.normalize(value);
|
|
709
|
+
if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
710
|
+
else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
|
|
711
|
+
return result;
|
|
712
|
+
}
|
|
713
|
+
function joinSafe(...values) {
|
|
714
|
+
let result = path$1.join(...values);
|
|
715
|
+
if (values.length > 0) {
|
|
716
|
+
const firstValue = toUnix(values[0]);
|
|
717
|
+
if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
718
|
+
else if (firstValue.startsWith("//") && !result.startsWith("//")) result = firstValue.startsWith("//./") ? "//." + result : "/" + result;
|
|
719
|
+
}
|
|
720
|
+
return result;
|
|
721
|
+
}
|
|
722
|
+
|
|
666
723
|
//#endregion
|
|
667
724
|
//#region src/utils/sort.ts
|
|
668
|
-
const sortByPriority = (arr) => arr.
|
|
725
|
+
const sortByPriority = (arr) => arr.toSorted((a, b) => {
|
|
669
726
|
if (a.default) return 1;
|
|
670
727
|
if (b.default) return -1;
|
|
671
728
|
if (a.required && b.required) return 0;
|
|
@@ -689,17 +746,20 @@ const sortByPriority = (arr) => arr.sort((a, b) => {
|
|
|
689
746
|
* stringify({ a: 1, b: 'test' }) // returns "{ a: 1, b: 'test', }"
|
|
690
747
|
*/
|
|
691
748
|
function stringify(data) {
|
|
692
|
-
if (
|
|
749
|
+
if (isNullish$1(data)) return;
|
|
693
750
|
if (isString(data)) return `'${data.replaceAll("'", String.raw`\'`)}'`;
|
|
694
|
-
if (isNumber(data) || isBoolean(data) || isFunction(data)) return
|
|
695
|
-
if (Array.isArray(data)) return `[${data.map(stringify).join(", ")}]`;
|
|
696
|
-
|
|
751
|
+
if (isNumber(data) || isBoolean(data) || isFunction(data)) return String(data);
|
|
752
|
+
if (Array.isArray(data)) return `[${data.map((item) => stringify(item)).join(", ")}]`;
|
|
753
|
+
const entries$1 = Object.entries(data);
|
|
754
|
+
let result = "";
|
|
755
|
+
for (const [index, [key, value]] of entries$1.entries()) {
|
|
697
756
|
const strValue = stringify(value);
|
|
698
|
-
if (
|
|
699
|
-
if (!index)
|
|
700
|
-
if (
|
|
701
|
-
|
|
702
|
-
}
|
|
757
|
+
if (entries$1.length === 1) result = `{ ${key}: ${strValue}, }`;
|
|
758
|
+
else if (!index) result = `{ ${key}: ${strValue}, `;
|
|
759
|
+
else if (entries$1.length - 1 === index) result += `${key}: ${strValue}, }`;
|
|
760
|
+
else result += `${key}: ${strValue}, `;
|
|
761
|
+
}
|
|
762
|
+
return result;
|
|
703
763
|
}
|
|
704
764
|
/**
|
|
705
765
|
* Sanitizes a string value by removing or replacing special characters and ensuring
|
|
@@ -723,7 +783,7 @@ function stringify(data) {
|
|
|
723
783
|
function sanitize(value, options) {
|
|
724
784
|
const { whitespace = "", underscore = "", dot = "", dash = "", es5keyword = false, es5IdentifierName = false, special = false } = options ?? {};
|
|
725
785
|
let newValue = value;
|
|
726
|
-
if (!special) newValue = newValue.replaceAll(/[!"`'#%&,:;<>=@{}
|
|
786
|
+
if (!special) newValue = newValue.replaceAll(/[!"`'#%&,:;<>=@{}~$()*+/\\?[\]^|]/g, "");
|
|
727
787
|
if (whitespace !== true) newValue = newValue.replaceAll(/[\s]/g, whitespace);
|
|
728
788
|
if (underscore !== true) newValue = newValue.replaceAll(/['_']/g, underscore);
|
|
729
789
|
if (dot !== true) newValue = newValue.replaceAll(/[.]/g, dot);
|
|
@@ -748,7 +808,11 @@ function sanitize(value, options) {
|
|
|
748
808
|
*/
|
|
749
809
|
function toObjectString(props, path$2) {
|
|
750
810
|
if (props.length === 0) return "";
|
|
751
|
-
return (
|
|
811
|
+
return (isString(path$2) ? props.map((prop$1) => {
|
|
812
|
+
let obj = prop$1;
|
|
813
|
+
for (const key of path$2.split(".")) obj = obj && (isObject(obj) || Array.isArray(obj)) ? obj[key] : void 0;
|
|
814
|
+
return obj;
|
|
815
|
+
}) : props).join(",\n ") + ",";
|
|
752
816
|
}
|
|
753
817
|
const NUMBERS = {
|
|
754
818
|
"0": "zero",
|
|
@@ -772,7 +836,7 @@ const NUMBERS = {
|
|
|
772
836
|
* getNumberWord(42) // returns "fourtwo"
|
|
773
837
|
*/
|
|
774
838
|
function getNumberWord(num) {
|
|
775
|
-
return num.toString().
|
|
839
|
+
return [...num.toString()].reduce((acc, n) => acc + NUMBERS[n], "");
|
|
776
840
|
}
|
|
777
841
|
/**
|
|
778
842
|
* Escapes a specific character in a string by prefixing it with a backslash.
|
|
@@ -797,11 +861,13 @@ function escape(str, char = "'") {
|
|
|
797
861
|
* @param input String to escape
|
|
798
862
|
*/
|
|
799
863
|
function jsStringEscape(input) {
|
|
800
|
-
return input.replaceAll(/["'\\\n\r\u2028\u2029]/g, (character) => {
|
|
864
|
+
return input.replaceAll(/["'\\\n\r\u2028\u2029/*]/g, (character) => {
|
|
801
865
|
switch (character) {
|
|
802
866
|
case "\"":
|
|
803
867
|
case "'":
|
|
804
|
-
case "\\":
|
|
868
|
+
case "\\":
|
|
869
|
+
case "/":
|
|
870
|
+
case "*": return "\\" + character;
|
|
805
871
|
case "\n": return String.raw`\n`;
|
|
806
872
|
case "\r": return String.raw`\r`;
|
|
807
873
|
case "\u2028": return String.raw`\u2028`;
|
|
@@ -813,12 +879,35 @@ function jsStringEscape(input) {
|
|
|
813
879
|
/**
|
|
814
880
|
* Deduplicates a TypeScript union type string.
|
|
815
881
|
* Handles types like "A | B | B" → "A | B" and "null | null" → "null".
|
|
882
|
+
* Only splits on top-level | (not inside {} () [] <> or string literals).
|
|
816
883
|
*/
|
|
817
884
|
function dedupeUnionType(unionType) {
|
|
818
|
-
const parts =
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
885
|
+
const parts = [];
|
|
886
|
+
let current = "";
|
|
887
|
+
let depth = 0;
|
|
888
|
+
let quote = "";
|
|
889
|
+
let escaped = false;
|
|
890
|
+
for (const c of unionType) {
|
|
891
|
+
if (!escaped && (c === "'" || c === "\"")) {
|
|
892
|
+
if (!quote) quote = c;
|
|
893
|
+
else if (quote === c) quote = "";
|
|
894
|
+
}
|
|
895
|
+
if (!quote) {
|
|
896
|
+
if ("{([<".includes(c)) depth++;
|
|
897
|
+
if ("})]>".includes(c)) depth--;
|
|
898
|
+
if (c === "|" && depth === 0) {
|
|
899
|
+
parts.push(current.trim());
|
|
900
|
+
current = "";
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
current += c;
|
|
905
|
+
escaped = !!quote && !escaped && c === "\\";
|
|
906
|
+
}
|
|
907
|
+
if (current.trim()) parts.push(current.trim());
|
|
908
|
+
return [...new Set(parts)].join(" | ");
|
|
909
|
+
}
|
|
910
|
+
|
|
822
911
|
//#endregion
|
|
823
912
|
//#region src/utils/tsconfig.ts
|
|
824
913
|
function isSyntheticDefaultImportsAllow(config) {
|
|
@@ -841,8 +930,7 @@ function getEnumDescriptions(schemaObject) {
|
|
|
841
930
|
function getEnum(value, enumName, names, enumGenerationType, descriptions, enumNamingConvention) {
|
|
842
931
|
if (enumGenerationType === EnumGeneration.CONST) return getTypeConstEnum(value, enumName, names, descriptions, enumNamingConvention);
|
|
843
932
|
if (enumGenerationType === EnumGeneration.ENUM) return getNativeEnum(value, enumName, names, enumNamingConvention);
|
|
844
|
-
|
|
845
|
-
throw new Error(`Invalid enumGenerationType: ${enumGenerationType}`);
|
|
933
|
+
return getUnion(value, enumName);
|
|
846
934
|
}
|
|
847
935
|
const getTypeConstEnum = (value, enumName, names, descriptions, enumNamingConvention) => {
|
|
848
936
|
let enumValue = `export type ${enumName} = typeof ${enumName}[keyof typeof ${enumName}]`;
|
|
@@ -858,11 +946,16 @@ const getTypeConstEnum = (value, enumName, names, descriptions, enumNamingConven
|
|
|
858
946
|
};
|
|
859
947
|
function getEnumImplementation(value, names, descriptions, enumNamingConvention) {
|
|
860
948
|
if (value === "") return "";
|
|
861
|
-
|
|
949
|
+
const uniqueValues = [...new Set(value.split(" | "))];
|
|
950
|
+
let result = "";
|
|
951
|
+
for (const [index, val] of uniqueValues.entries()) {
|
|
862
952
|
const name = names?.[index];
|
|
863
953
|
const description = descriptions?.[index];
|
|
864
954
|
const comment = description ? ` /** ${description} */\n` : "";
|
|
865
|
-
if (name)
|
|
955
|
+
if (name) {
|
|
956
|
+
result += comment + ` ${keyword.isIdentifierNameES5(name) ? name : `'${name}'`}: ${val},\n`;
|
|
957
|
+
continue;
|
|
958
|
+
}
|
|
866
959
|
let key = val.startsWith("'") ? val.slice(1, -1) : val;
|
|
867
960
|
if (isNumeric(key)) key = toNumberKey(key);
|
|
868
961
|
if (key.length > 1) key = sanitize(key, {
|
|
@@ -872,17 +965,23 @@ function getEnumImplementation(value, names, descriptions, enumNamingConvention)
|
|
|
872
965
|
special: true
|
|
873
966
|
});
|
|
874
967
|
if (enumNamingConvention) key = conventionName(key, enumNamingConvention);
|
|
875
|
-
|
|
876
|
-
}
|
|
968
|
+
result += comment + ` ${keyword.isIdentifierNameES5(key) ? key : `'${key}'`}: ${val},\n`;
|
|
969
|
+
}
|
|
970
|
+
return result;
|
|
877
971
|
}
|
|
878
972
|
const getNativeEnum = (value, enumName, names, enumNamingConvention) => {
|
|
879
973
|
return `export enum ${enumName} {\n${getNativeEnumItems(value, names, enumNamingConvention)}\n}`;
|
|
880
974
|
};
|
|
881
975
|
const getNativeEnumItems = (value, names, enumNamingConvention) => {
|
|
882
976
|
if (value === "") return "";
|
|
883
|
-
|
|
977
|
+
const uniqueValues = [...new Set(value.split(" | "))];
|
|
978
|
+
let result = "";
|
|
979
|
+
for (const [index, val] of uniqueValues.entries()) {
|
|
884
980
|
const name = names?.[index];
|
|
885
|
-
if (name)
|
|
981
|
+
if (name) {
|
|
982
|
+
result += ` ${keyword.isIdentifierNameES5(name) ? name : `'${name}'`}= ${val},\n`;
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
886
985
|
let key = val.startsWith("'") ? val.slice(1, -1) : val;
|
|
887
986
|
if (isNumeric(key)) key = toNumberKey(key);
|
|
888
987
|
if (key.length > 1) key = sanitize(key, {
|
|
@@ -892,8 +991,9 @@ const getNativeEnumItems = (value, names, enumNamingConvention) => {
|
|
|
892
991
|
special: true
|
|
893
992
|
});
|
|
894
993
|
if (enumNamingConvention) key = conventionName(key, enumNamingConvention);
|
|
895
|
-
|
|
896
|
-
}
|
|
994
|
+
result += ` ${keyword.isIdentifierNameES5(key) ? key : `'${key}'`}= ${val},\n`;
|
|
995
|
+
}
|
|
996
|
+
return result;
|
|
897
997
|
};
|
|
898
998
|
const toNumberKey = (value) => {
|
|
899
999
|
if (value.startsWith("-")) return `NUMBER_MINUS_${value.slice(1)}`;
|
|
@@ -905,9 +1005,9 @@ const getUnion = (value, enumName) => {
|
|
|
905
1005
|
};
|
|
906
1006
|
function getEnumUnionFromSchema(schema) {
|
|
907
1007
|
if (!schema?.enum) return "";
|
|
908
|
-
return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${escape(val)}'` :
|
|
1008
|
+
return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${escape(val)}'` : String(val)).join(" | ");
|
|
909
1009
|
}
|
|
910
|
-
const stripNullUnion = (value) => value.
|
|
1010
|
+
const stripNullUnion = (value) => value.replaceAll(/\s*\|\s*null/g, "").trim();
|
|
911
1011
|
const isSpreadableEnumRef = (schema, refName) => {
|
|
912
1012
|
if (!schema?.enum || !refName) return false;
|
|
913
1013
|
if (!getEnumUnionFromSchema(schema)) return false;
|
|
@@ -1053,13 +1153,23 @@ function getSchema$1(schema, context) {
|
|
|
1053
1153
|
const refInfo = getRefInfo(schema.$ref, context);
|
|
1054
1154
|
const { refPaths } = refInfo;
|
|
1055
1155
|
let schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
|
|
1056
|
-
|
|
1156
|
+
schemaByRefPaths ??= context.spec;
|
|
1057
1157
|
if (isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
|
|
1058
|
-
let currentSchema = schemaByRefPaths
|
|
1059
|
-
if ("nullable" in schema)
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1158
|
+
let currentSchema = schemaByRefPaths || context.spec;
|
|
1159
|
+
if ("nullable" in schema) {
|
|
1160
|
+
const nullable = schema.nullable;
|
|
1161
|
+
currentSchema = {
|
|
1162
|
+
...currentSchema,
|
|
1163
|
+
nullable
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
if ("type" in schema && Array.isArray(schema.type)) {
|
|
1167
|
+
const type = schema.type;
|
|
1168
|
+
currentSchema = {
|
|
1169
|
+
...currentSchema,
|
|
1170
|
+
type
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1063
1173
|
return {
|
|
1064
1174
|
currentSchema,
|
|
1065
1175
|
refInfo
|
|
@@ -1073,19 +1183,16 @@ function resolveExampleRefs(examples, context) {
|
|
|
1073
1183
|
return schema.value;
|
|
1074
1184
|
}
|
|
1075
1185
|
return example;
|
|
1076
|
-
}) :
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
return
|
|
1080
|
-
|
|
1081
|
-
[key]: schema
|
|
1082
|
-
};
|
|
1083
|
-
}, {});
|
|
1186
|
+
}) : (() => {
|
|
1187
|
+
const result = {};
|
|
1188
|
+
for (const [key, example] of Object.entries(examples)) result[key] = isReference(example) ? resolveRef(example, context).schema.value : example;
|
|
1189
|
+
return result;
|
|
1190
|
+
})();
|
|
1084
1191
|
}
|
|
1085
1192
|
|
|
1086
1193
|
//#endregion
|
|
1087
1194
|
//#region src/resolvers/value.ts
|
|
1088
|
-
function resolveValue({ schema, name, context }) {
|
|
1195
|
+
function resolveValue({ schema, name, context, formDataContext }) {
|
|
1089
1196
|
if (isReference(schema)) {
|
|
1090
1197
|
const { schema: schemaObject, imports } = resolveRef(schema, context);
|
|
1091
1198
|
const resolvedImport = imports[0];
|
|
@@ -1099,7 +1206,8 @@ function resolveValue({ schema, name, context }) {
|
|
|
1099
1206
|
parents: [...context.parents ?? [], refName]
|
|
1100
1207
|
}
|
|
1101
1208
|
}).hasReadonlyProps;
|
|
1102
|
-
const
|
|
1209
|
+
const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
|
|
1210
|
+
const nullable = Array.isArray(schemaObject.type) && schemaObject.type.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
|
|
1103
1211
|
return {
|
|
1104
1212
|
value: resolvedImport.name + nullable,
|
|
1105
1213
|
imports: [{
|
|
@@ -1119,7 +1227,8 @@ function resolveValue({ schema, name, context }) {
|
|
|
1119
1227
|
...getScalar({
|
|
1120
1228
|
item: schema,
|
|
1121
1229
|
name,
|
|
1122
|
-
context
|
|
1230
|
+
context,
|
|
1231
|
+
formDataContext
|
|
1123
1232
|
}),
|
|
1124
1233
|
originalSchema: schema,
|
|
1125
1234
|
isRef: false
|
|
@@ -1135,7 +1244,7 @@ function resolveValue({ schema, name, context }) {
|
|
|
1135
1244
|
function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
|
|
1136
1245
|
if (!propName) return;
|
|
1137
1246
|
if (resolvedValue.isEnum || resolvedValue.type !== "object") return;
|
|
1138
|
-
const aliasPattern = context.output.override.aliasCombinedTypes ?
|
|
1247
|
+
const aliasPattern = context.output.override.aliasCombinedTypes ? String.raw`{|&|\|` : "{";
|
|
1139
1248
|
if (!new RegExp(aliasPattern).test(resolvedValue.value)) return;
|
|
1140
1249
|
const { originalSchema } = resolvedValue;
|
|
1141
1250
|
const doc = jsDoc(originalSchema);
|
|
@@ -1161,11 +1270,12 @@ function createTypeAliasIfNeeded({ resolvedValue, propName, context }) {
|
|
|
1161
1270
|
dependencies: resolvedValue.dependencies
|
|
1162
1271
|
};
|
|
1163
1272
|
}
|
|
1164
|
-
function resolveObjectOriginal({ schema, propName, combined = false, context }) {
|
|
1273
|
+
function resolveObjectOriginal({ schema, propName, combined = false, context, formDataContext }) {
|
|
1165
1274
|
const resolvedValue = resolveValue({
|
|
1166
1275
|
schema,
|
|
1167
1276
|
name: propName,
|
|
1168
|
-
context
|
|
1277
|
+
context,
|
|
1278
|
+
formDataContext
|
|
1169
1279
|
});
|
|
1170
1280
|
const aliased = createTypeAliasIfNeeded({
|
|
1171
1281
|
resolvedValue,
|
|
@@ -1177,8 +1287,8 @@ function resolveObjectOriginal({ schema, propName, combined = false, context })
|
|
|
1177
1287
|
originalSchema: resolvedValue.originalSchema
|
|
1178
1288
|
};
|
|
1179
1289
|
if (propName && resolvedValue.isEnum && !combined && !resolvedValue.isRef) {
|
|
1180
|
-
const doc = jsDoc(resolvedValue.originalSchema
|
|
1181
|
-
const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention
|
|
1290
|
+
const doc = jsDoc(resolvedValue.originalSchema);
|
|
1291
|
+
const enumValue = getEnum(resolvedValue.value, propName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
|
|
1182
1292
|
return {
|
|
1183
1293
|
value: propName,
|
|
1184
1294
|
imports: [{ name: propName }],
|
|
@@ -1199,19 +1309,21 @@ function resolveObjectOriginal({ schema, propName, combined = false, context })
|
|
|
1199
1309
|
return resolvedValue;
|
|
1200
1310
|
}
|
|
1201
1311
|
const resolveObjectCacheMap = /* @__PURE__ */ new Map();
|
|
1202
|
-
function resolveObject({ schema, propName, combined = false, context }) {
|
|
1312
|
+
function resolveObject({ schema, propName, combined = false, context, formDataContext }) {
|
|
1203
1313
|
const hashKey = JSON.stringify({
|
|
1204
1314
|
schema,
|
|
1205
1315
|
propName,
|
|
1206
1316
|
combined,
|
|
1207
|
-
projectName: context.projectName ?? context.output.target
|
|
1317
|
+
projectName: context.projectName ?? context.output.target,
|
|
1318
|
+
formDataContext
|
|
1208
1319
|
});
|
|
1209
1320
|
if (resolveObjectCacheMap.has(hashKey)) return resolveObjectCacheMap.get(hashKey);
|
|
1210
1321
|
const result = resolveObjectOriginal({
|
|
1211
1322
|
schema,
|
|
1212
1323
|
propName,
|
|
1213
1324
|
combined,
|
|
1214
|
-
context
|
|
1325
|
+
context,
|
|
1326
|
+
formDataContext
|
|
1215
1327
|
});
|
|
1216
1328
|
resolveObjectCacheMap.set(hashKey, result);
|
|
1217
1329
|
return result;
|
|
@@ -1224,18 +1336,22 @@ function resolveObject({ schema, propName, combined = false, context }) {
|
|
|
1224
1336
|
*
|
|
1225
1337
|
* @param item item with type === "array"
|
|
1226
1338
|
*/
|
|
1227
|
-
function getArray({ schema, name, context }) {
|
|
1228
|
-
const
|
|
1229
|
-
|
|
1230
|
-
|
|
1339
|
+
function getArray({ schema, name, context, formDataContext }) {
|
|
1340
|
+
const schemaPrefixItems = schema.prefixItems;
|
|
1341
|
+
const schemaItems = schema.items;
|
|
1342
|
+
const schemaExample = schema.example;
|
|
1343
|
+
const schemaExamples = schema.examples;
|
|
1344
|
+
const itemSuffix = context.output.override.components.schemas.itemSuffix;
|
|
1345
|
+
if (schemaPrefixItems) {
|
|
1346
|
+
const resolvedObjects = schemaPrefixItems.map((item, index) => resolveObject({
|
|
1231
1347
|
schema: item,
|
|
1232
|
-
propName: name +
|
|
1348
|
+
propName: name ? name + itemSuffix + String(index) : void 0,
|
|
1233
1349
|
context
|
|
1234
1350
|
}));
|
|
1235
|
-
if (
|
|
1351
|
+
if (schemaItems) {
|
|
1236
1352
|
const additional = resolveObject({
|
|
1237
|
-
schema:
|
|
1238
|
-
propName: name +
|
|
1353
|
+
schema: schemaItems,
|
|
1354
|
+
propName: name ? name + itemSuffix + "Additional" : void 0,
|
|
1239
1355
|
context
|
|
1240
1356
|
});
|
|
1241
1357
|
resolvedObjects.push({
|
|
@@ -1252,15 +1368,16 @@ function getArray({ schema, name, context }) {
|
|
|
1252
1368
|
schemas: resolvedObjects.flatMap((o) => o.schemas),
|
|
1253
1369
|
dependencies: resolvedObjects.flatMap((o) => o.dependencies),
|
|
1254
1370
|
hasReadonlyProps: resolvedObjects.some((o) => o.hasReadonlyProps),
|
|
1255
|
-
example:
|
|
1256
|
-
examples: resolveExampleRefs(
|
|
1371
|
+
example: schemaExample,
|
|
1372
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
1257
1373
|
};
|
|
1258
1374
|
}
|
|
1259
|
-
if (
|
|
1375
|
+
if (schemaItems) {
|
|
1260
1376
|
const resolvedObject = resolveObject({
|
|
1261
|
-
schema:
|
|
1262
|
-
propName: name +
|
|
1263
|
-
context
|
|
1377
|
+
schema: schemaItems,
|
|
1378
|
+
propName: name ? name + itemSuffix : void 0,
|
|
1379
|
+
context,
|
|
1380
|
+
formDataContext
|
|
1264
1381
|
});
|
|
1265
1382
|
return {
|
|
1266
1383
|
value: `${schema.readOnly === true && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${resolvedObject.value.includes("|") ? `(${resolvedObject.value})[]` : `${resolvedObject.value}[]`}`,
|
|
@@ -1271,8 +1388,8 @@ function getArray({ schema, name, context }) {
|
|
|
1271
1388
|
type: "array",
|
|
1272
1389
|
isRef: false,
|
|
1273
1390
|
hasReadonlyProps: resolvedObject.hasReadonlyProps,
|
|
1274
|
-
example:
|
|
1275
|
-
examples: resolveExampleRefs(
|
|
1391
|
+
example: schemaExample,
|
|
1392
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
1276
1393
|
};
|
|
1277
1394
|
} else if (compareVersions(context.spec.openapi, "3.1", ">=")) return {
|
|
1278
1395
|
value: "unknown[]",
|
|
@@ -1288,321 +1405,452 @@ function getArray({ schema, name, context }) {
|
|
|
1288
1405
|
}
|
|
1289
1406
|
|
|
1290
1407
|
//#endregion
|
|
1291
|
-
//#region src/getters/
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1408
|
+
//#region src/getters/res-req-types.ts
|
|
1409
|
+
const getSchemaType = (s) => s.type;
|
|
1410
|
+
const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
|
|
1411
|
+
const getSchemaOneOf = (s) => s.oneOf;
|
|
1412
|
+
const getSchemaAnyOf = (s) => s.anyOf;
|
|
1413
|
+
const getSchemaItems = (s) => s.items;
|
|
1414
|
+
const getSchemaRequired = (s) => s.required;
|
|
1415
|
+
const getSchemaProperties = (s) => s.properties;
|
|
1416
|
+
const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
1417
|
+
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
1418
|
+
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
1419
|
+
if (!mediaType.schema) return;
|
|
1420
|
+
const formDataContext = isFormData ? {
|
|
1421
|
+
atPart: false,
|
|
1422
|
+
encoding: mediaType.encoding ?? {}
|
|
1423
|
+
} : void 0;
|
|
1424
|
+
const resolvedObject = resolveObject({
|
|
1425
|
+
schema: mediaType.schema,
|
|
1426
|
+
propName,
|
|
1427
|
+
context,
|
|
1428
|
+
formDataContext
|
|
1429
|
+
});
|
|
1430
|
+
if (!isFormData && isBinaryContentType(contentType)) return {
|
|
1431
|
+
...resolvedObject,
|
|
1432
|
+
value: "Blob"
|
|
1433
|
+
};
|
|
1434
|
+
return resolvedObject;
|
|
1310
1435
|
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
if (!itemType && item.items) {
|
|
1325
|
-
item.type = "array";
|
|
1326
|
-
itemType = "array";
|
|
1327
|
-
}
|
|
1328
|
-
if (isArray(item.type) && item.type.includes("null")) {
|
|
1329
|
-
const typesWithoutNull = item.type.filter((x) => x !== "null");
|
|
1330
|
-
itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
|
|
1331
|
-
}
|
|
1332
|
-
switch (itemType) {
|
|
1333
|
-
case "number":
|
|
1334
|
-
case "integer": {
|
|
1335
|
-
let value = context.output.override.useBigInt && (item.format === "int64" || item.format === "uint64") ? "bigint" : "number";
|
|
1336
|
-
let isEnum = false;
|
|
1337
|
-
if (enumItems) {
|
|
1338
|
-
value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
1339
|
-
isEnum = true;
|
|
1340
|
-
}
|
|
1341
|
-
value += nullable;
|
|
1342
|
-
const itemWithConst = item;
|
|
1343
|
-
if (itemWithConst.const !== void 0) value = itemWithConst.const;
|
|
1344
|
-
return {
|
|
1345
|
-
value,
|
|
1346
|
-
isEnum,
|
|
1347
|
-
type: "number",
|
|
1436
|
+
function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
|
|
1437
|
+
return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
|
|
1438
|
+
if (isReference(res)) {
|
|
1439
|
+
const { schema: bodySchema, imports: [{ name: name$1, schemaName }] } = resolveRef(res, context);
|
|
1440
|
+
const [contentType, mediaType] = Object.entries(bodySchema.content ?? {})[0] ?? [];
|
|
1441
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
1442
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1443
|
+
if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
|
|
1444
|
+
value: name$1,
|
|
1445
|
+
imports: [{
|
|
1446
|
+
name: name$1,
|
|
1447
|
+
schemaName
|
|
1448
|
+
}],
|
|
1348
1449
|
schemas: [],
|
|
1349
|
-
|
|
1350
|
-
isRef: false,
|
|
1351
|
-
hasReadonlyProps: item.readOnly || false,
|
|
1352
|
-
dependencies: [],
|
|
1353
|
-
example: item.example,
|
|
1354
|
-
examples: resolveExampleRefs(item.examples, context)
|
|
1355
|
-
};
|
|
1356
|
-
}
|
|
1357
|
-
case "boolean": {
|
|
1358
|
-
let value = "boolean" + nullable;
|
|
1359
|
-
const itemWithConst = item;
|
|
1360
|
-
if (itemWithConst.const !== void 0) value = itemWithConst.const;
|
|
1361
|
-
return {
|
|
1362
|
-
value,
|
|
1363
|
-
type: "boolean",
|
|
1450
|
+
type: "unknown",
|
|
1364
1451
|
isEnum: false,
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
};
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1452
|
+
isRef: true,
|
|
1453
|
+
hasReadonlyProps: false,
|
|
1454
|
+
originalSchema: mediaType.schema,
|
|
1455
|
+
example: mediaType.example,
|
|
1456
|
+
examples: resolveExampleRefs(mediaType.examples, context),
|
|
1457
|
+
key,
|
|
1458
|
+
contentType
|
|
1459
|
+
}];
|
|
1460
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1461
|
+
name: name$1,
|
|
1462
|
+
schemaObject: mediaType.schema,
|
|
1463
|
+
context,
|
|
1464
|
+
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1465
|
+
isRef: true,
|
|
1466
|
+
encoding: mediaType.encoding
|
|
1467
|
+
}) : void 0;
|
|
1468
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1469
|
+
name: name$1,
|
|
1470
|
+
schemaObject: mediaType.schema,
|
|
1471
|
+
context,
|
|
1472
|
+
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1473
|
+
isUrlEncoded: true,
|
|
1474
|
+
isRef: true,
|
|
1475
|
+
encoding: mediaType.encoding
|
|
1476
|
+
}) : void 0;
|
|
1477
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
1478
|
+
schemaObject: mediaType.schema,
|
|
1378
1479
|
context
|
|
1379
1480
|
});
|
|
1380
|
-
return {
|
|
1381
|
-
value:
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
case "string": {
|
|
1387
|
-
let value = "string";
|
|
1388
|
-
let isEnum = false;
|
|
1389
|
-
if (enumItems) {
|
|
1390
|
-
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
1391
|
-
isEnum = true;
|
|
1392
|
-
}
|
|
1393
|
-
if (item.format === "binary") value = "Blob";
|
|
1394
|
-
if (context.output.override.useDates && (item.format === "date" || item.format === "date-time")) value = "Date";
|
|
1395
|
-
value += nullable;
|
|
1396
|
-
const itemWithConst = item;
|
|
1397
|
-
if (itemWithConst.const) value = `'${itemWithConst.const}'`;
|
|
1398
|
-
return {
|
|
1399
|
-
value,
|
|
1400
|
-
isEnum,
|
|
1401
|
-
type: "string",
|
|
1402
|
-
imports: [],
|
|
1481
|
+
return [{
|
|
1482
|
+
value: name$1,
|
|
1483
|
+
imports: [{
|
|
1484
|
+
name: name$1,
|
|
1485
|
+
schemaName
|
|
1486
|
+
}, ...additionalImports],
|
|
1403
1487
|
schemas: [],
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1488
|
+
type: "unknown",
|
|
1489
|
+
isEnum: false,
|
|
1490
|
+
hasReadonlyProps: false,
|
|
1491
|
+
formData,
|
|
1492
|
+
formUrlEncoded,
|
|
1493
|
+
isRef: true,
|
|
1494
|
+
originalSchema: mediaType.schema,
|
|
1495
|
+
example: mediaType.example,
|
|
1496
|
+
examples: resolveExampleRefs(mediaType.examples, context),
|
|
1497
|
+
key,
|
|
1498
|
+
contentType
|
|
1499
|
+
}];
|
|
1410
1500
|
}
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
if (isArray(itemType)) return combineSchemas({
|
|
1424
|
-
schema: { anyOf: itemType.map((type) => ({
|
|
1425
|
-
...item,
|
|
1426
|
-
type
|
|
1427
|
-
})) },
|
|
1428
|
-
name,
|
|
1429
|
-
separator: "anyOf",
|
|
1501
|
+
if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
|
|
1502
|
+
let propName = key ? pascal(name) + pascal(key) : void 0;
|
|
1503
|
+
if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
|
|
1504
|
+
let effectivePropName = propName;
|
|
1505
|
+
if (mediaType.schema && isReference(mediaType.schema)) {
|
|
1506
|
+
const { imports } = resolveRef(mediaType.schema, context);
|
|
1507
|
+
if (imports[0]?.name) effectivePropName = imports[0].name;
|
|
1508
|
+
}
|
|
1509
|
+
const isFormData = formDataContentTypes.has(contentType);
|
|
1510
|
+
const resolvedValue = getResReqContentTypes({
|
|
1511
|
+
mediaType,
|
|
1512
|
+
propName: effectivePropName,
|
|
1430
1513
|
context,
|
|
1431
|
-
|
|
1514
|
+
isFormData,
|
|
1515
|
+
contentType
|
|
1432
1516
|
});
|
|
1433
|
-
if (
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1517
|
+
if (!resolvedValue) {
|
|
1518
|
+
if (isBinaryContentType(contentType)) return {
|
|
1519
|
+
value: "Blob",
|
|
1520
|
+
imports: [],
|
|
1521
|
+
schemas: [],
|
|
1522
|
+
type: "Blob",
|
|
1523
|
+
isEnum: false,
|
|
1524
|
+
key,
|
|
1525
|
+
isRef: false,
|
|
1526
|
+
hasReadonlyProps: false,
|
|
1527
|
+
contentType
|
|
1528
|
+
};
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1532
|
+
if (!isFormData && !isFormUrlEncoded || !effectivePropName || !mediaType.schema) return {
|
|
1533
|
+
...resolvedValue,
|
|
1534
|
+
imports: resolvedValue.imports,
|
|
1535
|
+
contentType,
|
|
1536
|
+
example: mediaType.example,
|
|
1537
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
1444
1538
|
};
|
|
1445
|
-
const
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
context,
|
|
1449
|
-
|
|
1539
|
+
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1540
|
+
name: effectivePropName,
|
|
1541
|
+
schemaObject: mediaType.schema,
|
|
1542
|
+
context,
|
|
1543
|
+
isRequestBodyOptional: "required" in res && res.required === false,
|
|
1544
|
+
isRef: true,
|
|
1545
|
+
encoding: mediaType.encoding
|
|
1546
|
+
}) : void 0;
|
|
1547
|
+
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1548
|
+
name: effectivePropName,
|
|
1549
|
+
schemaObject: mediaType.schema,
|
|
1550
|
+
context,
|
|
1551
|
+
isUrlEncoded: true,
|
|
1552
|
+
isRequestBodyOptional: "required" in res && res.required === false,
|
|
1553
|
+
isRef: true,
|
|
1554
|
+
encoding: mediaType.encoding
|
|
1555
|
+
}) : void 0;
|
|
1556
|
+
const additionalImports = getFormDataAdditionalImports({
|
|
1557
|
+
schemaObject: mediaType.schema,
|
|
1558
|
+
context
|
|
1450
1559
|
});
|
|
1451
1560
|
return {
|
|
1452
|
-
|
|
1453
|
-
...
|
|
1561
|
+
...resolvedValue,
|
|
1562
|
+
imports: [...resolvedValue.imports, ...additionalImports],
|
|
1563
|
+
formData,
|
|
1564
|
+
formUrlEncoded,
|
|
1565
|
+
contentType,
|
|
1566
|
+
example: mediaType.example,
|
|
1567
|
+
examples: resolveExampleRefs(mediaType.examples, context)
|
|
1454
1568
|
};
|
|
1569
|
+
}).filter(Boolean).map((x) => ({
|
|
1570
|
+
...x,
|
|
1571
|
+
key
|
|
1572
|
+
}));
|
|
1573
|
+
const swaggerSchema = "schema" in res ? res.schema : void 0;
|
|
1574
|
+
if (swaggerSchema) return [{
|
|
1575
|
+
...resolveObject({
|
|
1576
|
+
schema: swaggerSchema,
|
|
1577
|
+
propName: key ? pascal(name) + pascal(key) : void 0,
|
|
1578
|
+
context
|
|
1579
|
+
}),
|
|
1580
|
+
contentType: "application/json",
|
|
1581
|
+
key
|
|
1582
|
+
}];
|
|
1583
|
+
return [{
|
|
1584
|
+
value: defaultType,
|
|
1585
|
+
imports: [],
|
|
1586
|
+
schemas: [],
|
|
1587
|
+
type: defaultType,
|
|
1588
|
+
isEnum: false,
|
|
1589
|
+
key,
|
|
1590
|
+
isRef: false,
|
|
1591
|
+
hasReadonlyProps: false,
|
|
1592
|
+
contentType: "application/json"
|
|
1593
|
+
}];
|
|
1594
|
+
}).flat(), uniqueKey);
|
|
1595
|
+
}
|
|
1596
|
+
/**
|
|
1597
|
+
* Determine the response type category for a given content type.
|
|
1598
|
+
* Used to set the correct responseType option in HTTP clients.
|
|
1599
|
+
*
|
|
1600
|
+
* @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
|
|
1601
|
+
* @returns The response type category to use for parsing
|
|
1602
|
+
*/
|
|
1603
|
+
function getResponseTypeCategory(contentType) {
|
|
1604
|
+
if (isBinaryContentType(contentType)) return "blob";
|
|
1605
|
+
if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
|
|
1606
|
+
return "text";
|
|
1607
|
+
}
|
|
1608
|
+
/**
|
|
1609
|
+
* Get the default content type from a list of content types.
|
|
1610
|
+
* Priority: application/json > any JSON-like type > first in list
|
|
1611
|
+
*
|
|
1612
|
+
* @param contentTypes - Array of content types from OpenAPI spec
|
|
1613
|
+
* @returns The default content type to use
|
|
1614
|
+
*/
|
|
1615
|
+
function getDefaultContentType(contentTypes) {
|
|
1616
|
+
if (contentTypes.length === 0) return "application/json";
|
|
1617
|
+
if (contentTypes.includes("application/json")) return "application/json";
|
|
1618
|
+
const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
|
|
1619
|
+
if (jsonType) return jsonType;
|
|
1620
|
+
return contentTypes[0];
|
|
1621
|
+
}
|
|
1622
|
+
function getFormDataAdditionalImports({ schemaObject, context }) {
|
|
1623
|
+
const { schema } = resolveRef(schemaObject, context);
|
|
1624
|
+
if (schema.type !== "object") return [];
|
|
1625
|
+
const combinedSchemas = getSchemaOneOf(schema) ?? getSchemaAnyOf(schema);
|
|
1626
|
+
if (!combinedSchemas) return [];
|
|
1627
|
+
return combinedSchemas.map((subSchema) => resolveRef(subSchema, context).imports[0]).filter(Boolean);
|
|
1628
|
+
}
|
|
1629
|
+
function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
|
|
1630
|
+
const { schema, imports } = resolveRef(schemaObject, context);
|
|
1631
|
+
const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
|
|
1632
|
+
const additionalImports = [];
|
|
1633
|
+
const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
|
|
1634
|
+
let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
|
|
1635
|
+
const combinedSchemas = getSchemaCombined(schema);
|
|
1636
|
+
if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
|
|
1637
|
+
if (combinedSchemas) {
|
|
1638
|
+
const shouldCast = !!getSchemaOneOf(schema) || !!getSchemaAnyOf(schema);
|
|
1639
|
+
const combinedSchemasFormData = combinedSchemas.map((subSchema) => {
|
|
1640
|
+
const { schema: combinedSchema, imports: imports$1 } = resolveRef(subSchema, context);
|
|
1641
|
+
let newPropName = propName;
|
|
1642
|
+
let newPropDefinition = "";
|
|
1643
|
+
if (shouldCast && imports$1[0]) {
|
|
1644
|
+
additionalImports.push(imports$1[0]);
|
|
1645
|
+
newPropName = `${propName}${pascal(imports$1[0].name)}`;
|
|
1646
|
+
newPropDefinition = `const ${newPropName} = (${propName} as ${imports$1[0].name}${isRequestBodyOptional ? " | undefined" : ""});\n`;
|
|
1647
|
+
}
|
|
1648
|
+
return newPropDefinition + resolveSchemaPropertiesToFormData({
|
|
1649
|
+
schema: combinedSchema,
|
|
1650
|
+
variableName,
|
|
1651
|
+
propName: newPropName,
|
|
1652
|
+
context,
|
|
1653
|
+
isRequestBodyOptional,
|
|
1654
|
+
encoding
|
|
1655
|
+
});
|
|
1656
|
+
}).filter(Boolean).join("\n");
|
|
1657
|
+
form += combinedSchemasFormData;
|
|
1658
|
+
}
|
|
1659
|
+
if (schema.properties) {
|
|
1660
|
+
const formDataValues = resolveSchemaPropertiesToFormData({
|
|
1661
|
+
schema,
|
|
1662
|
+
variableName,
|
|
1663
|
+
propName,
|
|
1664
|
+
context,
|
|
1665
|
+
isRequestBodyOptional,
|
|
1666
|
+
encoding
|
|
1667
|
+
});
|
|
1668
|
+
form += formDataValues;
|
|
1455
1669
|
}
|
|
1670
|
+
return form;
|
|
1456
1671
|
}
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
|
|
1465
|
-
if (resolvedData.originalSchema.length > 0 && resolvedValue) {
|
|
1466
|
-
const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => s?.discriminator && resolvedValue.value.includes(` ${s.discriminator.propertyName}:`));
|
|
1467
|
-
if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
|
|
1672
|
+
if (schema.type === "array") {
|
|
1673
|
+
let valueStr = "value";
|
|
1674
|
+
const schemaItems = getSchemaItems(schema);
|
|
1675
|
+
if (schemaItems) {
|
|
1676
|
+
const { schema: itemSchema } = resolveRef(schemaItems, context);
|
|
1677
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
|
|
1678
|
+
else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
|
|
1468
1679
|
}
|
|
1469
|
-
|
|
1470
|
-
const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
|
|
1471
|
-
const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop$1) => !resolvedData.originalSchema.some((schema) => schema?.properties?.[prop$1] && schema.required?.includes(prop$1)));
|
|
1472
|
-
if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
|
|
1473
|
-
return joined;
|
|
1680
|
+
return `${form}${propName}.forEach(value => ${variableName}.append('data', ${valueStr}))\n`;
|
|
1474
1681
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1682
|
+
if (schema.type === "number" || schema.type === "integer" || schema.type === "boolean") return `${form}${variableName}.append('data', ${propName}.toString())\n`;
|
|
1683
|
+
return `${form}${variableName}.append('data', ${propName})\n`;
|
|
1684
|
+
}
|
|
1685
|
+
function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
|
|
1686
|
+
let formDataValues = "";
|
|
1687
|
+
const schemaProps = getSchemaProperties(schema) ?? {};
|
|
1688
|
+
for (const [key, value] of Object.entries(schemaProps)) {
|
|
1689
|
+
const { schema: property } = resolveRef(value, context);
|
|
1690
|
+
if (property.readOnly) continue;
|
|
1691
|
+
let formDataValue = "";
|
|
1692
|
+
const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
|
|
1693
|
+
const formattedKeyPrefix = isRequestBodyOptional ? keyword.isIdentifierNameES5(key) ? "?" : "?." : "";
|
|
1694
|
+
const formattedKey = keyword.isIdentifierNameES5(key) ? `.${key}` : `['${key}']`;
|
|
1695
|
+
const valueKey = `${propName}${formattedKeyPrefix}${formattedKey}`;
|
|
1696
|
+
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
1697
|
+
const fileType = getFormDataFieldFileType(property, partContentType);
|
|
1698
|
+
const effectiveContentType = partContentType ?? property.contentMediaType;
|
|
1699
|
+
if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
1700
|
+
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
1701
|
+
else if (property.type === "object") formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
1702
|
+
schema: property,
|
|
1703
|
+
variableName,
|
|
1704
|
+
propName: nonOptionalValueKey,
|
|
1705
|
+
context,
|
|
1706
|
+
isRequestBodyOptional,
|
|
1707
|
+
keyPrefix: `${keyPrefix}${key}.`,
|
|
1708
|
+
depth: depth + 1,
|
|
1709
|
+
encoding
|
|
1710
|
+
}) : partContentType ? `${variableName}.append(\`${keyPrefix}${key}\`, new Blob([JSON.stringify(${nonOptionalValueKey})], { type: '${partContentType}' }));\n` : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
|
|
1711
|
+
else if (property.type === "array") {
|
|
1712
|
+
let valueStr = "value";
|
|
1713
|
+
let hasNonPrimitiveChild = false;
|
|
1714
|
+
const propertyItems = getSchemaItems(property);
|
|
1715
|
+
if (propertyItems) {
|
|
1716
|
+
const { schema: itemSchema } = resolveRef(propertyItems, context);
|
|
1717
|
+
if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
1718
|
+
hasNonPrimitiveChild = true;
|
|
1719
|
+
const resolvedValue = resolveSchemaPropertiesToFormData({
|
|
1720
|
+
schema: itemSchema,
|
|
1721
|
+
variableName,
|
|
1722
|
+
propName: "value",
|
|
1723
|
+
context,
|
|
1724
|
+
isRequestBodyOptional,
|
|
1725
|
+
keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
|
|
1726
|
+
depth: depth + 1
|
|
1727
|
+
});
|
|
1728
|
+
formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
|
|
1729
|
+
${resolvedValue}});\n`;
|
|
1730
|
+
} else valueStr = "JSON.stringify(value)";
|
|
1731
|
+
else {
|
|
1732
|
+
const itemType = getSchemaType(itemSchema);
|
|
1733
|
+
if (itemType === "number" || Array.isArray(itemType) && itemType.includes("number") || itemType === "integer" || Array.isArray(itemType) && itemType.includes("integer") || itemType === "boolean" || Array.isArray(itemType) && itemType.includes("boolean")) valueStr = "value.toString()";
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
|
|
1737
|
+
if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
|
|
1738
|
+
} else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
|
|
1739
|
+
} else if ((() => {
|
|
1740
|
+
const propType$1 = getSchemaType(property);
|
|
1741
|
+
return propType$1 === "number" || Array.isArray(propType$1) && propType$1.includes("number") || propType$1 === "integer" || Array.isArray(propType$1) && propType$1.includes("integer") || propType$1 === "boolean" || Array.isArray(propType$1) && propType$1.includes("boolean");
|
|
1742
|
+
})()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
1743
|
+
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
1744
|
+
let existSubSchemaNullable = false;
|
|
1745
|
+
const combine = getSchemaCombined(property);
|
|
1746
|
+
if (combine) {
|
|
1747
|
+
const subSchemas = combine.map((c) => resolveObject({
|
|
1748
|
+
schema: c,
|
|
1749
|
+
combined: true,
|
|
1750
|
+
context
|
|
1751
|
+
}));
|
|
1752
|
+
if (subSchemas.some((subSchema) => {
|
|
1753
|
+
return [
|
|
1754
|
+
"number",
|
|
1755
|
+
"integer",
|
|
1756
|
+
"boolean"
|
|
1757
|
+
].includes(subSchema.type);
|
|
1758
|
+
})) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
1759
|
+
if (subSchemas.some((subSchema) => {
|
|
1760
|
+
return subSchema.type === "null";
|
|
1761
|
+
})) existSubSchemaNullable = true;
|
|
1762
|
+
}
|
|
1763
|
+
const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
|
|
1764
|
+
const propType = getSchemaType(property);
|
|
1765
|
+
if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
|
|
1766
|
+
if (isRequired) {
|
|
1767
|
+
formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
1482
1768
|
continue;
|
|
1483
1769
|
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1770
|
+
formDataValues += `if(${valueKey} !== undefined && ${nonOptionalValueKey} !== null) {\n ${formDataValue} }\n`;
|
|
1771
|
+
continue;
|
|
1486
1772
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
}
|
|
1491
|
-
function combineSchemas({ name, schema, separator: separator$1, context, nullable }) {
|
|
1492
|
-
const items = schema[separator$1] ?? [];
|
|
1493
|
-
const resolvedData = items.reduce((acc, subSchema) => {
|
|
1494
|
-
let propName;
|
|
1495
|
-
if (context.output.override.aliasCombinedTypes) {
|
|
1496
|
-
propName = name ? name + pascal(separator$1) : void 0;
|
|
1497
|
-
if (propName && acc.schemas.length > 0) propName = propName + pascal(getNumberWord(acc.schemas.length + 1));
|
|
1773
|
+
if (isRequired) {
|
|
1774
|
+
formDataValues += formDataValue;
|
|
1775
|
+
continue;
|
|
1498
1776
|
}
|
|
1499
|
-
if
|
|
1500
|
-
const resolvedValue$1 = resolveObject({
|
|
1501
|
-
schema: subSchema,
|
|
1502
|
-
propName,
|
|
1503
|
-
combined: true,
|
|
1504
|
-
context
|
|
1505
|
-
});
|
|
1506
|
-
const aliasedImports = getAliasedImports({
|
|
1507
|
-
context,
|
|
1508
|
-
name,
|
|
1509
|
-
resolvedValue: resolvedValue$1
|
|
1510
|
-
});
|
|
1511
|
-
const value = getImportAliasForRefOrValue({
|
|
1512
|
-
context,
|
|
1513
|
-
resolvedValue: resolvedValue$1,
|
|
1514
|
-
imports: aliasedImports
|
|
1515
|
-
});
|
|
1516
|
-
acc.values.push(value);
|
|
1517
|
-
acc.imports.push(...aliasedImports);
|
|
1518
|
-
acc.schemas.push(...resolvedValue$1.schemas);
|
|
1519
|
-
acc.dependencies.push(...resolvedValue$1.dependencies);
|
|
1520
|
-
acc.isEnum.push(resolvedValue$1.isEnum);
|
|
1521
|
-
acc.types.push(resolvedValue$1.type);
|
|
1522
|
-
acc.isRef.push(resolvedValue$1.isRef);
|
|
1523
|
-
acc.originalSchema.push(resolvedValue$1.originalSchema);
|
|
1524
|
-
acc.hasReadonlyProps ||= resolvedValue$1.hasReadonlyProps;
|
|
1525
|
-
if (resolvedValue$1.type === "object" && resolvedValue$1.originalSchema.properties) acc.allProperties.push(...Object.keys(resolvedValue$1.originalSchema.properties));
|
|
1526
|
-
return acc;
|
|
1527
|
-
}, {
|
|
1528
|
-
values: [],
|
|
1529
|
-
imports: [],
|
|
1530
|
-
schemas: [],
|
|
1531
|
-
isEnum: [],
|
|
1532
|
-
isRef: [],
|
|
1533
|
-
types: [],
|
|
1534
|
-
dependencies: [],
|
|
1535
|
-
originalSchema: [],
|
|
1536
|
-
allProperties: [],
|
|
1537
|
-
hasReadonlyProps: false,
|
|
1538
|
-
example: schema.example,
|
|
1539
|
-
examples: resolveExampleRefs(schema.examples, context),
|
|
1540
|
-
requiredProperties: separator$1 === "allOf" ? schema.required ?? [] : []
|
|
1541
|
-
});
|
|
1542
|
-
if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
|
|
1543
|
-
const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
|
|
1544
|
-
value,
|
|
1545
|
-
isRef: resolvedData.isRef[index],
|
|
1546
|
-
schema: resolvedData.originalSchema[index]
|
|
1547
|
-
})));
|
|
1548
|
-
const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
|
|
1549
|
-
const valueImportSet = new Set(valueImports);
|
|
1550
|
-
const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
|
|
1551
|
-
return {
|
|
1552
|
-
value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
|
|
1553
|
-
imports: [{ name: pascal(name) }],
|
|
1554
|
-
schemas: [...resolvedData.schemas, {
|
|
1555
|
-
imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
|
|
1556
|
-
...toImport,
|
|
1557
|
-
values: true
|
|
1558
|
-
})),
|
|
1559
|
-
model: newEnum,
|
|
1560
|
-
name
|
|
1561
|
-
}],
|
|
1562
|
-
isEnum: false,
|
|
1563
|
-
type: "object",
|
|
1564
|
-
isRef: false,
|
|
1565
|
-
hasReadonlyProps: resolvedData.hasReadonlyProps,
|
|
1566
|
-
dependencies: resolvedData.dependencies,
|
|
1567
|
-
example: schema.example,
|
|
1568
|
-
examples: resolveExampleRefs(schema.examples, context)
|
|
1569
|
-
};
|
|
1777
|
+
formDataValues += `if(${valueKey} !== undefined) {\n ${formDataValue} }\n`;
|
|
1570
1778
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1779
|
+
return formDataValues;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
//#endregion
|
|
1783
|
+
//#region src/getters/body.ts
|
|
1784
|
+
/**
|
|
1785
|
+
* Extract all content types from a requestBody (#2812)
|
|
1786
|
+
*/
|
|
1787
|
+
function getRequestBodyContentTypes(requestBody, context) {
|
|
1788
|
+
if (!requestBody) return [];
|
|
1789
|
+
const content = (isReference(requestBody) ? resolveRef(requestBody, context).schema : requestBody).content;
|
|
1790
|
+
return content ? Object.keys(content) : [];
|
|
1791
|
+
}
|
|
1792
|
+
function getBody({ requestBody, operationName, context, contentType }) {
|
|
1793
|
+
const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType);
|
|
1794
|
+
const imports = filteredBodyTypes.flatMap(({ imports: imports$1 }) => imports$1);
|
|
1795
|
+
const schemas = filteredBodyTypes.flatMap(({ schemas: schemas$1 }) => schemas$1);
|
|
1796
|
+
const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
|
|
1797
|
+
const nonReadonlyDefinition = filteredBodyTypes.some((x) => x.hasReadonlyProps) && definition ? `NonReadonly<${definition}>` : definition;
|
|
1798
|
+
let implementation = generalJSTypesWithArray.includes(definition.toLowerCase()) || filteredBodyTypes.length > 1 ? camel(operationName) + context.output.override.components.requestBodies.suffix : camel(definition);
|
|
1799
|
+
let isOptional = false;
|
|
1800
|
+
if (implementation) {
|
|
1801
|
+
implementation = sanitize(implementation, {
|
|
1802
|
+
underscore: "_",
|
|
1803
|
+
whitespace: "_",
|
|
1804
|
+
dash: true,
|
|
1805
|
+
es5keyword: true,
|
|
1806
|
+
es5IdentifierName: true
|
|
1585
1807
|
});
|
|
1808
|
+
if (isReference(requestBody)) {
|
|
1809
|
+
const { schema: bodySchema } = resolveRef(requestBody, context);
|
|
1810
|
+
if (bodySchema.required !== void 0) isOptional = !bodySchema.required;
|
|
1811
|
+
} else if (requestBody.required !== void 0) isOptional = !requestBody.required;
|
|
1586
1812
|
}
|
|
1587
1813
|
return {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1814
|
+
originalSchema: requestBody,
|
|
1815
|
+
definition: nonReadonlyDefinition,
|
|
1816
|
+
implementation,
|
|
1817
|
+
imports,
|
|
1818
|
+
schemas,
|
|
1819
|
+
isOptional,
|
|
1820
|
+
...filteredBodyTypes.length === 1 ? {
|
|
1821
|
+
formData: filteredBodyTypes[0].formData,
|
|
1822
|
+
formUrlEncoded: filteredBodyTypes[0].formUrlEncoded,
|
|
1823
|
+
contentType: filteredBodyTypes[0].contentType
|
|
1824
|
+
} : {
|
|
1825
|
+
formData: "",
|
|
1826
|
+
formUrlEncoded: "",
|
|
1827
|
+
contentType: ""
|
|
1828
|
+
}
|
|
1603
1829
|
};
|
|
1604
1830
|
}
|
|
1605
1831
|
|
|
1832
|
+
//#endregion
|
|
1833
|
+
//#region src/getters/imports.ts
|
|
1834
|
+
function getAliasedImports({ name, resolvedValue, context }) {
|
|
1835
|
+
return context.output.schemas && resolvedValue.isRef ? resolvedValue.imports.map((imp) => {
|
|
1836
|
+
if (!needCreateImportAlias({
|
|
1837
|
+
name,
|
|
1838
|
+
imp
|
|
1839
|
+
})) return imp;
|
|
1840
|
+
return {
|
|
1841
|
+
...imp,
|
|
1842
|
+
alias: `__${imp.name}`
|
|
1843
|
+
};
|
|
1844
|
+
}) : resolvedValue.imports;
|
|
1845
|
+
}
|
|
1846
|
+
function needCreateImportAlias({ imp, name }) {
|
|
1847
|
+
return !imp.alias && imp.name === name;
|
|
1848
|
+
}
|
|
1849
|
+
function getImportAliasForRefOrValue({ context, imports, resolvedValue }) {
|
|
1850
|
+
if (!context.output.schemas || !resolvedValue.isRef) return resolvedValue.value;
|
|
1851
|
+
return imports.find((imp) => imp.name === resolvedValue.value)?.alias ?? resolvedValue.value;
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1606
1854
|
//#endregion
|
|
1607
1855
|
//#region src/getters/keys.ts
|
|
1608
1856
|
function getKey(key) {
|
|
@@ -1616,7 +1864,10 @@ function getKey(key) {
|
|
|
1616
1864
|
* Returns undefined if propertyNames doesn't have an enum
|
|
1617
1865
|
*/
|
|
1618
1866
|
function getPropertyNamesEnum(item) {
|
|
1619
|
-
if ("propertyNames" in item && item.propertyNames && "enum" in item.propertyNames
|
|
1867
|
+
if ("propertyNames" in item && item.propertyNames && "enum" in item.propertyNames) {
|
|
1868
|
+
const propertyNames = item.propertyNames;
|
|
1869
|
+
if (Array.isArray(propertyNames.enum)) return propertyNames.enum.filter((val) => isString(val));
|
|
1870
|
+
}
|
|
1620
1871
|
}
|
|
1621
1872
|
/**
|
|
1622
1873
|
* Generate index signature key type based on propertyNames enum
|
|
@@ -1637,7 +1888,7 @@ function getPropertyNamesRecordType(item, valueType) {
|
|
|
1637
1888
|
*
|
|
1638
1889
|
* @param item item with type === "object"
|
|
1639
1890
|
*/
|
|
1640
|
-
function getObject({ item, name, context, nullable,
|
|
1891
|
+
function getObject({ item, name, context, nullable, formDataContext }) {
|
|
1641
1892
|
if (isReference(item)) {
|
|
1642
1893
|
const { name: name$1 } = getRefInfo(item.$ref, context);
|
|
1643
1894
|
return {
|
|
@@ -1658,25 +1909,46 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1658
1909
|
name,
|
|
1659
1910
|
separator: item.allOf ? "allOf" : item.oneOf ? "oneOf" : "anyOf",
|
|
1660
1911
|
context,
|
|
1661
|
-
nullable
|
|
1662
|
-
|
|
1663
|
-
if (Array.isArray(item.type)) return combineSchemas({
|
|
1664
|
-
schema: { anyOf: item.type.map((type) => ({
|
|
1665
|
-
...item,
|
|
1666
|
-
type
|
|
1667
|
-
})) },
|
|
1668
|
-
name,
|
|
1669
|
-
separator: "anyOf",
|
|
1670
|
-
context,
|
|
1671
|
-
nullable
|
|
1912
|
+
nullable,
|
|
1913
|
+
formDataContext
|
|
1672
1914
|
});
|
|
1673
|
-
if (
|
|
1674
|
-
const
|
|
1915
|
+
if (Array.isArray(item.type)) {
|
|
1916
|
+
const typeArray = item.type;
|
|
1917
|
+
const baseItem = item;
|
|
1918
|
+
return combineSchemas({
|
|
1919
|
+
schema: { anyOf: typeArray.map((type) => ({
|
|
1920
|
+
...baseItem,
|
|
1921
|
+
type
|
|
1922
|
+
})) },
|
|
1923
|
+
name,
|
|
1924
|
+
separator: "anyOf",
|
|
1925
|
+
context,
|
|
1926
|
+
nullable
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
const itemProperties = item.properties;
|
|
1930
|
+
if (itemProperties && Object.entries(itemProperties).length > 0) {
|
|
1931
|
+
const entries$1 = Object.entries(itemProperties);
|
|
1675
1932
|
if (context.output.propertySortOrder === PropertySortOrder.ALPHABETICAL) entries$1.sort((a, b) => {
|
|
1676
1933
|
return a[0].localeCompare(b[0]);
|
|
1677
1934
|
});
|
|
1678
|
-
|
|
1679
|
-
|
|
1935
|
+
const acc = {
|
|
1936
|
+
imports: [],
|
|
1937
|
+
schemas: [],
|
|
1938
|
+
value: "",
|
|
1939
|
+
isEnum: false,
|
|
1940
|
+
type: "object",
|
|
1941
|
+
isRef: false,
|
|
1942
|
+
schema: {},
|
|
1943
|
+
hasReadonlyProps: false,
|
|
1944
|
+
useTypeAlias: false,
|
|
1945
|
+
dependencies: [],
|
|
1946
|
+
example: item.example,
|
|
1947
|
+
examples: resolveExampleRefs(item.examples, context)
|
|
1948
|
+
};
|
|
1949
|
+
const itemRequired = item.required;
|
|
1950
|
+
for (const [index, [key, schema]] of entries$1.entries()) {
|
|
1951
|
+
const isRequired = (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
|
|
1680
1952
|
let propName = "";
|
|
1681
1953
|
if (name) {
|
|
1682
1954
|
const isKeyStartWithUnderscore = key.startsWith("_");
|
|
@@ -1684,21 +1956,26 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1684
1956
|
}
|
|
1685
1957
|
const allSpecSchemas = context.spec.components?.schemas ?? {};
|
|
1686
1958
|
if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
|
|
1687
|
-
const
|
|
1959
|
+
const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
|
|
1960
|
+
atPart: true,
|
|
1961
|
+
partContentType: formDataContext.encoding[key]?.contentType
|
|
1962
|
+
} : void 0;
|
|
1963
|
+
const resolvedValue = resolveObject({
|
|
1688
1964
|
schema,
|
|
1689
1965
|
propName,
|
|
1690
|
-
context
|
|
1966
|
+
context,
|
|
1967
|
+
formDataContext: propertyFormDataContext
|
|
1691
1968
|
});
|
|
1692
|
-
const isReadOnly = item.readOnly
|
|
1969
|
+
const isReadOnly = item.readOnly ?? schema.readOnly;
|
|
1693
1970
|
if (!index) acc.value += "{";
|
|
1694
1971
|
const doc = jsDoc(schema, true, context);
|
|
1695
|
-
acc.hasReadonlyProps
|
|
1696
|
-
const constValue = "const" in schema ? schema.const : void 0;
|
|
1697
|
-
const hasConst = constValue !== void 0;
|
|
1972
|
+
if (isReadOnly ?? false) acc.hasReadonlyProps = true;
|
|
1973
|
+
const constValue$1 = "const" in schema ? schema.const : void 0;
|
|
1974
|
+
const hasConst = constValue$1 !== void 0;
|
|
1698
1975
|
let constLiteral;
|
|
1699
1976
|
if (!hasConst) constLiteral = void 0;
|
|
1700
|
-
else if (
|
|
1701
|
-
else constLiteral = JSON.stringify(constValue);
|
|
1977
|
+
else if (isString(constValue$1)) constLiteral = `'${escape(constValue$1)}'`;
|
|
1978
|
+
else constLiteral = JSON.stringify(constValue$1);
|
|
1702
1979
|
const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
|
|
1703
1980
|
const aliasedImports = needsValueImport ? resolvedValue.imports.map((imp) => ({
|
|
1704
1981
|
...imp,
|
|
@@ -1719,8 +1996,9 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1719
1996
|
acc.value += `\n ${doc ? `${doc} ` : ""}${isReadOnly && !context.output.override.suppressReadonlyModifier ? "readonly " : ""}${getKey(key)}${isRequired ? "" : "?"}: ${finalPropValue};`;
|
|
1720
1997
|
acc.schemas.push(...resolvedValue.schemas);
|
|
1721
1998
|
acc.dependencies.push(...resolvedValue.dependencies);
|
|
1722
|
-
if (
|
|
1723
|
-
|
|
1999
|
+
if (entries$1.length - 1 === index) {
|
|
2000
|
+
const additionalProps = item.additionalProperties;
|
|
2001
|
+
if (additionalProps) if (isBoolean(additionalProps)) {
|
|
1724
2002
|
const recordType$1 = getPropertyNamesRecordType(item, "unknown");
|
|
1725
2003
|
if (recordType$1) {
|
|
1726
2004
|
acc.value += "\n}";
|
|
@@ -1732,42 +2010,31 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1732
2010
|
}
|
|
1733
2011
|
} else {
|
|
1734
2012
|
const resolvedValue$1 = resolveValue({
|
|
1735
|
-
schema:
|
|
2013
|
+
schema: additionalProps,
|
|
1736
2014
|
name,
|
|
1737
2015
|
context
|
|
1738
2016
|
});
|
|
1739
2017
|
const recordType$1 = getPropertyNamesRecordType(item, resolvedValue$1.value);
|
|
1740
2018
|
if (recordType$1) {
|
|
1741
|
-
acc.value += "\n}";
|
|
1742
|
-
acc.value += ` & ${recordType$1}`;
|
|
1743
|
-
acc.useTypeAlias = true;
|
|
1744
|
-
} else {
|
|
1745
|
-
const keyType$1 = getIndexSignatureKey(item);
|
|
1746
|
-
acc.value += `\n [key: ${keyType$1}]: ${resolvedValue$1.value};\n}`;
|
|
1747
|
-
}
|
|
1748
|
-
acc.dependencies.push(...resolvedValue$1.dependencies);
|
|
1749
|
-
}
|
|
1750
|
-
else acc.value += "\n}";
|
|
1751
|
-
acc.value += nullable;
|
|
1752
|
-
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
imports: [],
|
|
1756
|
-
schemas: [],
|
|
1757
|
-
value: "",
|
|
1758
|
-
isEnum: false,
|
|
1759
|
-
type: "object",
|
|
1760
|
-
isRef: false,
|
|
1761
|
-
schema: {},
|
|
1762
|
-
hasReadonlyProps: false,
|
|
1763
|
-
useTypeAlias: false,
|
|
1764
|
-
dependencies: [],
|
|
1765
|
-
example: item.example,
|
|
1766
|
-
examples: resolveExampleRefs(item.examples, context)
|
|
1767
|
-
});
|
|
2019
|
+
acc.value += "\n}";
|
|
2020
|
+
acc.value += ` & ${recordType$1}`;
|
|
2021
|
+
acc.useTypeAlias = true;
|
|
2022
|
+
} else {
|
|
2023
|
+
const keyType$1 = getIndexSignatureKey(item);
|
|
2024
|
+
acc.value += `\n [key: ${keyType$1}]: ${resolvedValue$1.value};\n}`;
|
|
2025
|
+
}
|
|
2026
|
+
acc.dependencies.push(...resolvedValue$1.dependencies);
|
|
2027
|
+
}
|
|
2028
|
+
else acc.value += "\n}";
|
|
2029
|
+
acc.value += nullable;
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
return acc;
|
|
1768
2033
|
}
|
|
1769
|
-
|
|
1770
|
-
|
|
2034
|
+
const outerAdditionalProps = item.additionalProperties;
|
|
2035
|
+
const readOnlyFlag = item.readOnly;
|
|
2036
|
+
if (outerAdditionalProps) {
|
|
2037
|
+
if (isBoolean(outerAdditionalProps)) {
|
|
1771
2038
|
const recordType$2 = getPropertyNamesRecordType(item, "unknown");
|
|
1772
2039
|
if (recordType$2) return {
|
|
1773
2040
|
value: recordType$2 + nullable,
|
|
@@ -1776,7 +2043,7 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1776
2043
|
isEnum: false,
|
|
1777
2044
|
type: "object",
|
|
1778
2045
|
isRef: false,
|
|
1779
|
-
hasReadonlyProps:
|
|
2046
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1780
2047
|
useTypeAlias: true,
|
|
1781
2048
|
dependencies: []
|
|
1782
2049
|
};
|
|
@@ -1787,21 +2054,21 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1787
2054
|
isEnum: false,
|
|
1788
2055
|
type: "object",
|
|
1789
2056
|
isRef: false,
|
|
1790
|
-
hasReadonlyProps:
|
|
2057
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1791
2058
|
useTypeAlias: false,
|
|
1792
2059
|
dependencies: []
|
|
1793
2060
|
};
|
|
1794
2061
|
}
|
|
1795
2062
|
const resolvedValue = resolveValue({
|
|
1796
|
-
schema:
|
|
2063
|
+
schema: outerAdditionalProps,
|
|
1797
2064
|
name,
|
|
1798
2065
|
context
|
|
1799
2066
|
});
|
|
1800
2067
|
const recordType$1 = getPropertyNamesRecordType(item, resolvedValue.value);
|
|
1801
2068
|
if (recordType$1) return {
|
|
1802
2069
|
value: recordType$1 + nullable,
|
|
1803
|
-
imports: resolvedValue.imports
|
|
1804
|
-
schemas: resolvedValue.schemas
|
|
2070
|
+
imports: resolvedValue.imports,
|
|
2071
|
+
schemas: resolvedValue.schemas,
|
|
1805
2072
|
isEnum: false,
|
|
1806
2073
|
type: "object",
|
|
1807
2074
|
isRef: false,
|
|
@@ -1811,8 +2078,8 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1811
2078
|
};
|
|
1812
2079
|
return {
|
|
1813
2080
|
value: `{[key: ${getIndexSignatureKey(item)}]: ${resolvedValue.value}}` + nullable,
|
|
1814
|
-
imports: resolvedValue.imports
|
|
1815
|
-
schemas: resolvedValue.schemas
|
|
2081
|
+
imports: resolvedValue.imports,
|
|
2082
|
+
schemas: resolvedValue.schemas,
|
|
1816
2083
|
isEnum: false,
|
|
1817
2084
|
type: "object",
|
|
1818
2085
|
isRef: false,
|
|
@@ -1821,15 +2088,15 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1821
2088
|
dependencies: resolvedValue.dependencies
|
|
1822
2089
|
};
|
|
1823
2090
|
}
|
|
1824
|
-
const
|
|
1825
|
-
if (
|
|
1826
|
-
value: `'${
|
|
2091
|
+
const constValue = item.const;
|
|
2092
|
+
if (constValue) return {
|
|
2093
|
+
value: `'${constValue}'`,
|
|
1827
2094
|
imports: [],
|
|
1828
2095
|
schemas: [],
|
|
1829
2096
|
isEnum: false,
|
|
1830
2097
|
type: "string",
|
|
1831
2098
|
isRef: false,
|
|
1832
|
-
hasReadonlyProps:
|
|
2099
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1833
2100
|
dependencies: []
|
|
1834
2101
|
};
|
|
1835
2102
|
const keyType = item.type === "object" ? getIndexSignatureKey(item) : "string";
|
|
@@ -1841,7 +2108,7 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1841
2108
|
isEnum: false,
|
|
1842
2109
|
type: "object",
|
|
1843
2110
|
isRef: false,
|
|
1844
|
-
hasReadonlyProps:
|
|
2111
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1845
2112
|
useTypeAlias: true,
|
|
1846
2113
|
dependencies: []
|
|
1847
2114
|
};
|
|
@@ -1852,492 +2119,367 @@ function getObject({ item, name, context, nullable, propertyOverrides }) {
|
|
|
1852
2119
|
isEnum: false,
|
|
1853
2120
|
type: "object",
|
|
1854
2121
|
isRef: false,
|
|
1855
|
-
hasReadonlyProps:
|
|
2122
|
+
hasReadonlyProps: readOnlyFlag ?? false,
|
|
1856
2123
|
useTypeAlias: false,
|
|
1857
2124
|
dependencies: []
|
|
1858
2125
|
};
|
|
1859
2126
|
}
|
|
1860
2127
|
|
|
1861
2128
|
//#endregion
|
|
1862
|
-
//#region src/getters/
|
|
1863
|
-
const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
1864
|
-
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
1865
|
-
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
1866
|
-
if (!mediaType.schema) return;
|
|
1867
|
-
if (isFormData) {
|
|
1868
|
-
const formDataResult = resolveFormDataRootObject({
|
|
1869
|
-
schemaOrRef: mediaType.schema,
|
|
1870
|
-
propName,
|
|
1871
|
-
context,
|
|
1872
|
-
encoding: mediaType.encoding
|
|
1873
|
-
});
|
|
1874
|
-
if (formDataResult) return formDataResult;
|
|
1875
|
-
}
|
|
1876
|
-
const resolvedObject = resolveObject({
|
|
1877
|
-
schema: mediaType.schema,
|
|
1878
|
-
propName,
|
|
1879
|
-
context
|
|
1880
|
-
});
|
|
1881
|
-
if (!isFormData && isBinaryContentType(contentType)) return {
|
|
1882
|
-
...resolvedObject,
|
|
1883
|
-
value: "Blob"
|
|
1884
|
-
};
|
|
1885
|
-
return resolvedObject;
|
|
1886
|
-
}
|
|
1887
|
-
function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
|
|
1888
|
-
return uniqueBy(responsesOrRequests.filter(([_, res]) => Boolean(res)).map(([key, res]) => {
|
|
1889
|
-
if (isReference(res)) {
|
|
1890
|
-
const { schema: bodySchema, imports: [{ name: name$1, schemaName }] } = resolveRef(res, context);
|
|
1891
|
-
const [contentType, mediaType] = Object.entries(bodySchema.content ?? {})[0] ?? [];
|
|
1892
|
-
const isFormData = formDataContentTypes.has(contentType);
|
|
1893
|
-
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1894
|
-
if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
|
|
1895
|
-
value: name$1,
|
|
1896
|
-
imports: [{
|
|
1897
|
-
name: name$1,
|
|
1898
|
-
schemaName
|
|
1899
|
-
}],
|
|
1900
|
-
schemas: [],
|
|
1901
|
-
type: "unknown",
|
|
1902
|
-
isEnum: false,
|
|
1903
|
-
isRef: true,
|
|
1904
|
-
hasReadonlyProps: false,
|
|
1905
|
-
originalSchema: mediaType?.schema,
|
|
1906
|
-
example: mediaType?.example,
|
|
1907
|
-
examples: resolveExampleRefs(mediaType?.examples, context),
|
|
1908
|
-
key,
|
|
1909
|
-
contentType
|
|
1910
|
-
}];
|
|
1911
|
-
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1912
|
-
name: name$1,
|
|
1913
|
-
schemaObject: mediaType.schema,
|
|
1914
|
-
context,
|
|
1915
|
-
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1916
|
-
isRef: true,
|
|
1917
|
-
encoding: mediaType.encoding
|
|
1918
|
-
}) : void 0;
|
|
1919
|
-
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1920
|
-
name: name$1,
|
|
1921
|
-
schemaObject: mediaType.schema,
|
|
1922
|
-
context,
|
|
1923
|
-
isRequestBodyOptional: "required" in bodySchema && bodySchema.required === false,
|
|
1924
|
-
isUrlEncoded: true,
|
|
1925
|
-
isRef: true,
|
|
1926
|
-
encoding: mediaType.encoding
|
|
1927
|
-
}) : void 0;
|
|
1928
|
-
const additionalImports = getFormDataAdditionalImports({
|
|
1929
|
-
schemaObject: mediaType.schema,
|
|
1930
|
-
context
|
|
1931
|
-
});
|
|
1932
|
-
return [{
|
|
1933
|
-
value: name$1,
|
|
1934
|
-
imports: [{
|
|
1935
|
-
name: name$1,
|
|
1936
|
-
schemaName
|
|
1937
|
-
}, ...additionalImports],
|
|
1938
|
-
schemas: [],
|
|
1939
|
-
type: "unknown",
|
|
1940
|
-
isEnum: false,
|
|
1941
|
-
hasReadonlyProps: false,
|
|
1942
|
-
formData,
|
|
1943
|
-
formUrlEncoded,
|
|
1944
|
-
isRef: true,
|
|
1945
|
-
originalSchema: mediaType.schema,
|
|
1946
|
-
example: mediaType.example,
|
|
1947
|
-
examples: resolveExampleRefs(mediaType.examples, context),
|
|
1948
|
-
key,
|
|
1949
|
-
contentType
|
|
1950
|
-
}];
|
|
1951
|
-
}
|
|
1952
|
-
if (res.content) return Object.entries(res.content).map(([contentType, mediaType], index, arr) => {
|
|
1953
|
-
let propName = key ? pascal(name) + pascal(key) : void 0;
|
|
1954
|
-
if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
|
|
1955
|
-
let effectivePropName = propName;
|
|
1956
|
-
if (mediaType.schema && isReference(mediaType.schema)) {
|
|
1957
|
-
const { imports } = resolveRef(mediaType.schema, context);
|
|
1958
|
-
if (imports[0]?.name) effectivePropName = imports[0].name;
|
|
1959
|
-
}
|
|
1960
|
-
const isFormData = formDataContentTypes.has(contentType);
|
|
1961
|
-
const resolvedValue = getResReqContentTypes({
|
|
1962
|
-
mediaType,
|
|
1963
|
-
propName: effectivePropName,
|
|
1964
|
-
context,
|
|
1965
|
-
isFormData,
|
|
1966
|
-
contentType
|
|
1967
|
-
});
|
|
1968
|
-
if (!resolvedValue) {
|
|
1969
|
-
if (isBinaryContentType(contentType)) return {
|
|
1970
|
-
value: "Blob",
|
|
1971
|
-
imports: [],
|
|
1972
|
-
schemas: [],
|
|
1973
|
-
type: "Blob",
|
|
1974
|
-
isEnum: false,
|
|
1975
|
-
key,
|
|
1976
|
-
isRef: false,
|
|
1977
|
-
hasReadonlyProps: false,
|
|
1978
|
-
contentType
|
|
1979
|
-
};
|
|
1980
|
-
return;
|
|
1981
|
-
}
|
|
1982
|
-
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1983
|
-
if (!isFormData && !isFormUrlEncoded || !effectivePropName) return {
|
|
1984
|
-
...resolvedValue,
|
|
1985
|
-
imports: resolvedValue.imports,
|
|
1986
|
-
contentType,
|
|
1987
|
-
example: mediaType.example,
|
|
1988
|
-
examples: resolveExampleRefs(mediaType.examples, context)
|
|
1989
|
-
};
|
|
1990
|
-
const formData = isFormData ? getSchemaFormDataAndUrlEncoded({
|
|
1991
|
-
name: effectivePropName,
|
|
1992
|
-
schemaObject: mediaType.schema,
|
|
1993
|
-
context,
|
|
1994
|
-
isRequestBodyOptional: "required" in res && res.required === false,
|
|
1995
|
-
isRef: true,
|
|
1996
|
-
encoding: mediaType.encoding
|
|
1997
|
-
}) : void 0;
|
|
1998
|
-
const formUrlEncoded = isFormUrlEncoded ? getSchemaFormDataAndUrlEncoded({
|
|
1999
|
-
name: effectivePropName,
|
|
2000
|
-
schemaObject: mediaType.schema,
|
|
2001
|
-
context,
|
|
2002
|
-
isUrlEncoded: true,
|
|
2003
|
-
isRequestBodyOptional: "required" in res && res.required === false,
|
|
2004
|
-
isRef: true,
|
|
2005
|
-
encoding: mediaType.encoding
|
|
2006
|
-
}) : void 0;
|
|
2007
|
-
const additionalImports = getFormDataAdditionalImports({
|
|
2008
|
-
schemaObject: mediaType.schema,
|
|
2009
|
-
context
|
|
2010
|
-
});
|
|
2011
|
-
return {
|
|
2012
|
-
...resolvedValue,
|
|
2013
|
-
imports: [...resolvedValue.imports, ...additionalImports],
|
|
2014
|
-
formData,
|
|
2015
|
-
formUrlEncoded,
|
|
2016
|
-
contentType,
|
|
2017
|
-
example: mediaType.example,
|
|
2018
|
-
examples: resolveExampleRefs(mediaType.examples, context)
|
|
2019
|
-
};
|
|
2020
|
-
}).filter(Boolean).map((x) => ({
|
|
2021
|
-
...x,
|
|
2022
|
-
key
|
|
2023
|
-
}));
|
|
2024
|
-
const swaggerSchema = "schema" in res ? res.schema : void 0;
|
|
2025
|
-
if (swaggerSchema) return [{
|
|
2026
|
-
...resolveObject({
|
|
2027
|
-
schema: swaggerSchema,
|
|
2028
|
-
propName: key ? pascal(name) + pascal(key) : void 0,
|
|
2029
|
-
context
|
|
2030
|
-
}),
|
|
2031
|
-
contentType: "application/json",
|
|
2032
|
-
key
|
|
2033
|
-
}];
|
|
2034
|
-
return [{
|
|
2035
|
-
value: defaultType,
|
|
2036
|
-
imports: [],
|
|
2037
|
-
schemas: [],
|
|
2038
|
-
type: defaultType,
|
|
2039
|
-
isEnum: false,
|
|
2040
|
-
key,
|
|
2041
|
-
isRef: false,
|
|
2042
|
-
hasReadonlyProps: false,
|
|
2043
|
-
contentType: "application/json"
|
|
2044
|
-
}];
|
|
2045
|
-
}).flat(), uniqueKey);
|
|
2046
|
-
}
|
|
2047
|
-
function isBinaryContentType(contentType) {
|
|
2048
|
-
if (contentType === "application/octet-stream") return true;
|
|
2049
|
-
if (contentType.startsWith("image/")) return true;
|
|
2050
|
-
if (contentType.startsWith("audio/")) return true;
|
|
2051
|
-
if (contentType.startsWith("video/")) return true;
|
|
2052
|
-
if (contentType.startsWith("font/")) return true;
|
|
2053
|
-
if (contentType.startsWith("text/")) return false;
|
|
2054
|
-
if ([
|
|
2055
|
-
"+json",
|
|
2056
|
-
"-json",
|
|
2057
|
-
"+xml",
|
|
2058
|
-
"-xml",
|
|
2059
|
-
"+yaml",
|
|
2060
|
-
"-yaml",
|
|
2061
|
-
"+rss",
|
|
2062
|
-
"-rss",
|
|
2063
|
-
"+csv",
|
|
2064
|
-
"-csv"
|
|
2065
|
-
].some((suffix) => contentType.includes(suffix))) return false;
|
|
2066
|
-
return !new Set([
|
|
2067
|
-
"application/json",
|
|
2068
|
-
"application/xml",
|
|
2069
|
-
"application/yaml",
|
|
2070
|
-
"application/x-www-form-urlencoded",
|
|
2071
|
-
"application/javascript",
|
|
2072
|
-
"application/ecmascript",
|
|
2073
|
-
"application/graphql"
|
|
2074
|
-
]).has(contentType);
|
|
2075
|
-
}
|
|
2076
|
-
/**
|
|
2077
|
-
* Determine the response type category for a given content type.
|
|
2078
|
-
* Used to set the correct responseType option in HTTP clients.
|
|
2079
|
-
*
|
|
2080
|
-
* @param contentType - The MIME content type (e.g., 'application/json', 'text/plain')
|
|
2081
|
-
* @returns The response type category to use for parsing
|
|
2082
|
-
*/
|
|
2083
|
-
function getResponseTypeCategory(contentType) {
|
|
2084
|
-
if (isBinaryContentType(contentType)) return "blob";
|
|
2085
|
-
if (contentType === "application/json" || contentType.includes("+json") || contentType.includes("-json")) return "json";
|
|
2086
|
-
return "text";
|
|
2087
|
-
}
|
|
2088
|
-
/**
|
|
2089
|
-
* Get the default content type from a list of content types.
|
|
2090
|
-
* Priority: application/json > any JSON-like type > first in list
|
|
2091
|
-
*
|
|
2092
|
-
* @param contentTypes - Array of content types from OpenAPI spec
|
|
2093
|
-
* @returns The default content type to use
|
|
2094
|
-
*/
|
|
2095
|
-
function getDefaultContentType(contentTypes) {
|
|
2096
|
-
if (contentTypes.length === 0) return "application/json";
|
|
2097
|
-
if (contentTypes.includes("application/json")) return "application/json";
|
|
2098
|
-
const jsonType = contentTypes.find((ct) => ct.includes("+json") || ct.includes("-json"));
|
|
2099
|
-
if (jsonType) return jsonType;
|
|
2100
|
-
return contentTypes[0];
|
|
2101
|
-
}
|
|
2102
|
-
/**
|
|
2103
|
-
* Determine if a form-data root field should be treated as binary or text file
|
|
2104
|
-
* based on encoding.contentType or contentMediaType.
|
|
2105
|
-
*
|
|
2106
|
-
* Returns:
|
|
2107
|
-
* - 'binary': field is a binary file (Blob in types, File in zod)
|
|
2108
|
-
* - 'text': field is a text file that can accept string (Blob | string in types, File | string in zod)
|
|
2109
|
-
* - undefined: no override, use standard resolution
|
|
2110
|
-
*/
|
|
2111
|
-
function getFormDataFieldFileType(resolvedSchema, encodingContentType) {
|
|
2112
|
-
if (resolvedSchema.type !== "string") return;
|
|
2113
|
-
if (resolvedSchema.contentEncoding) return;
|
|
2114
|
-
const effectiveContentType = encodingContentType ?? resolvedSchema.contentMediaType;
|
|
2115
|
-
if (effectiveContentType) return isBinaryContentType(effectiveContentType) ? "binary" : "text";
|
|
2116
|
-
}
|
|
2129
|
+
//#region src/getters/scalar.ts
|
|
2117
2130
|
/**
|
|
2118
|
-
*
|
|
2119
|
-
*
|
|
2131
|
+
* Return the typescript equivalent of open-api data type
|
|
2132
|
+
*
|
|
2133
|
+
* @param item
|
|
2134
|
+
* @ref https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#data-types
|
|
2120
2135
|
*/
|
|
2121
|
-
function
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
const
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
};
|
|
2136
|
+
function getScalar({ item, name, context, formDataContext }) {
|
|
2137
|
+
const schemaEnum = item.enum;
|
|
2138
|
+
const schemaType = item.type;
|
|
2139
|
+
const schemaReadOnly = item.readOnly;
|
|
2140
|
+
const schemaExample = item.example;
|
|
2141
|
+
const schemaExamples = item.examples;
|
|
2142
|
+
const schemaConst = item.const;
|
|
2143
|
+
const schemaFormat = item.format;
|
|
2144
|
+
const schemaNullable = item.nullable;
|
|
2145
|
+
const nullable = isArray(schemaType) && schemaType.includes("null") || schemaNullable === true ? " | null" : "";
|
|
2146
|
+
const enumItems = schemaEnum?.filter((enumItem) => enumItem !== null);
|
|
2147
|
+
let itemType = schemaType;
|
|
2148
|
+
if (!itemType && item.items) {
|
|
2149
|
+
item.type = "array";
|
|
2150
|
+
itemType = "array";
|
|
2137
2151
|
}
|
|
2138
|
-
if (
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
const additionalImports = [];
|
|
2166
|
-
const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
|
|
2167
|
-
let form = isUrlEncoded ? `const ${variableName} = new URLSearchParams();\n` : `const ${variableName} = new FormData();\n`;
|
|
2168
|
-
const combinedSchemas = schema.oneOf || schema.anyOf || schema.allOf;
|
|
2169
|
-
if (schema.type === "object" || schema.type === void 0 && combinedSchemas) {
|
|
2170
|
-
if (combinedSchemas) {
|
|
2171
|
-
const shouldCast = !!schema.oneOf || !!schema.anyOf;
|
|
2172
|
-
const combinedSchemasFormData = combinedSchemas.map((schema$1) => {
|
|
2173
|
-
const { schema: combinedSchema, imports: imports$1 } = resolveRef(schema$1, context);
|
|
2174
|
-
let newPropName = propName;
|
|
2175
|
-
let newPropDefinition = "";
|
|
2176
|
-
if (shouldCast && imports$1[0]) {
|
|
2177
|
-
additionalImports.push(imports$1[0]);
|
|
2178
|
-
newPropName = `${propName}${pascal(imports$1[0].name)}`;
|
|
2179
|
-
newPropDefinition = `const ${newPropName} = (${propName} as ${imports$1[0].name}${isRequestBodyOptional ? " | undefined" : ""});\n`;
|
|
2180
|
-
}
|
|
2181
|
-
return newPropDefinition + resolveSchemaPropertiesToFormData({
|
|
2182
|
-
schema: combinedSchema,
|
|
2183
|
-
variableName,
|
|
2184
|
-
propName: newPropName,
|
|
2185
|
-
context,
|
|
2186
|
-
isRequestBodyOptional,
|
|
2187
|
-
encoding
|
|
2188
|
-
});
|
|
2189
|
-
}).filter(Boolean).join("\n");
|
|
2190
|
-
form += combinedSchemasFormData;
|
|
2152
|
+
if (isArray(schemaType) && schemaType.includes("null")) {
|
|
2153
|
+
const typesWithoutNull = schemaType.filter((x) => x !== "null");
|
|
2154
|
+
itemType = typesWithoutNull.length === 1 ? typesWithoutNull[0] : typesWithoutNull;
|
|
2155
|
+
}
|
|
2156
|
+
switch (itemType) {
|
|
2157
|
+
case "number":
|
|
2158
|
+
case "integer": {
|
|
2159
|
+
let value = context.output.override.useBigInt && (schemaFormat === "int64" || schemaFormat === "uint64") ? "bigint" : "number";
|
|
2160
|
+
let isEnum = false;
|
|
2161
|
+
if (enumItems) {
|
|
2162
|
+
value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
|
|
2163
|
+
isEnum = true;
|
|
2164
|
+
}
|
|
2165
|
+
value += nullable;
|
|
2166
|
+
if (schemaConst !== void 0) value = schemaConst;
|
|
2167
|
+
return {
|
|
2168
|
+
value,
|
|
2169
|
+
isEnum,
|
|
2170
|
+
type: "number",
|
|
2171
|
+
schemas: [],
|
|
2172
|
+
imports: [],
|
|
2173
|
+
isRef: false,
|
|
2174
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2175
|
+
dependencies: [],
|
|
2176
|
+
example: schemaExample,
|
|
2177
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2178
|
+
};
|
|
2191
2179
|
}
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2180
|
+
case "boolean": {
|
|
2181
|
+
let value = "boolean" + nullable;
|
|
2182
|
+
if (schemaConst !== void 0) value = schemaConst;
|
|
2183
|
+
return {
|
|
2184
|
+
value,
|
|
2185
|
+
type: "boolean",
|
|
2186
|
+
isEnum: false,
|
|
2187
|
+
schemas: [],
|
|
2188
|
+
imports: [],
|
|
2189
|
+
isRef: false,
|
|
2190
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2191
|
+
dependencies: [],
|
|
2192
|
+
example: schemaExample,
|
|
2193
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2194
|
+
};
|
|
2195
|
+
}
|
|
2196
|
+
case "array": {
|
|
2197
|
+
const { value, ...rest } = getArray({
|
|
2198
|
+
schema: item,
|
|
2199
|
+
name,
|
|
2197
2200
|
context,
|
|
2198
|
-
|
|
2199
|
-
encoding
|
|
2201
|
+
formDataContext
|
|
2200
2202
|
});
|
|
2201
|
-
|
|
2203
|
+
return {
|
|
2204
|
+
value: value + nullable,
|
|
2205
|
+
...rest,
|
|
2206
|
+
dependencies: rest.dependencies
|
|
2207
|
+
};
|
|
2208
|
+
}
|
|
2209
|
+
case "string": {
|
|
2210
|
+
let value = "string";
|
|
2211
|
+
let isEnum = false;
|
|
2212
|
+
if (enumItems) {
|
|
2213
|
+
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2214
|
+
isEnum = true;
|
|
2215
|
+
}
|
|
2216
|
+
if (schemaFormat === "binary") value = "Blob";
|
|
2217
|
+
else if (formDataContext?.atPart) {
|
|
2218
|
+
const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
|
|
2219
|
+
if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
|
|
2220
|
+
}
|
|
2221
|
+
if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
|
|
2222
|
+
value += nullable;
|
|
2223
|
+
if (schemaConst) value = `'${schemaConst}'`;
|
|
2224
|
+
return {
|
|
2225
|
+
value,
|
|
2226
|
+
isEnum,
|
|
2227
|
+
type: "string",
|
|
2228
|
+
imports: [],
|
|
2229
|
+
schemas: [],
|
|
2230
|
+
isRef: false,
|
|
2231
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2232
|
+
dependencies: [],
|
|
2233
|
+
example: schemaExample,
|
|
2234
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2237
|
+
case "null": return {
|
|
2238
|
+
value: "null",
|
|
2239
|
+
isEnum: false,
|
|
2240
|
+
type: "null",
|
|
2241
|
+
imports: [],
|
|
2242
|
+
schemas: [],
|
|
2243
|
+
isRef: false,
|
|
2244
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2245
|
+
dependencies: []
|
|
2246
|
+
};
|
|
2247
|
+
default: {
|
|
2248
|
+
if (isArray(itemType)) return combineSchemas({
|
|
2249
|
+
schema: { anyOf: itemType.map((type) => Object.assign({}, item, { type })) },
|
|
2250
|
+
name,
|
|
2251
|
+
separator: "anyOf",
|
|
2252
|
+
context,
|
|
2253
|
+
nullable
|
|
2254
|
+
});
|
|
2255
|
+
if (enumItems) return {
|
|
2256
|
+
value: enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
|
|
2257
|
+
isEnum: true,
|
|
2258
|
+
type: "string",
|
|
2259
|
+
imports: [],
|
|
2260
|
+
schemas: [],
|
|
2261
|
+
isRef: false,
|
|
2262
|
+
hasReadonlyProps: schemaReadOnly ?? false,
|
|
2263
|
+
dependencies: [],
|
|
2264
|
+
example: schemaExample,
|
|
2265
|
+
examples: resolveExampleRefs(schemaExamples, context)
|
|
2266
|
+
};
|
|
2267
|
+
const hasCombiners = item.allOf ?? item.anyOf ?? item.oneOf;
|
|
2268
|
+
const { value, ...rest } = getObject({
|
|
2269
|
+
item,
|
|
2270
|
+
name,
|
|
2271
|
+
context,
|
|
2272
|
+
nullable,
|
|
2273
|
+
formDataContext: formDataContext?.atPart === false || formDataContext?.atPart && hasCombiners ? formDataContext : void 0
|
|
2274
|
+
});
|
|
2275
|
+
return {
|
|
2276
|
+
value,
|
|
2277
|
+
...rest
|
|
2278
|
+
};
|
|
2202
2279
|
}
|
|
2203
|
-
return form;
|
|
2204
2280
|
}
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2281
|
+
}
|
|
2282
|
+
|
|
2283
|
+
//#endregion
|
|
2284
|
+
//#region src/getters/combine.ts
|
|
2285
|
+
const mergeableAllOfKeys = new Set([
|
|
2286
|
+
"type",
|
|
2287
|
+
"properties",
|
|
2288
|
+
"required"
|
|
2289
|
+
]);
|
|
2290
|
+
function isMergeableAllOfObject(schema) {
|
|
2291
|
+
if (isNullish$1(schema.properties)) return false;
|
|
2292
|
+
if (schema.allOf || schema.anyOf || schema.oneOf) return false;
|
|
2293
|
+
if (!isNullish$1(schema.type) && schema.type !== "object") return false;
|
|
2294
|
+
return Object.keys(schema).every((key) => mergeableAllOfKeys.has(key));
|
|
2295
|
+
}
|
|
2296
|
+
function normalizeAllOfSchema(schema) {
|
|
2297
|
+
const schemaAllOf = schema.allOf;
|
|
2298
|
+
if (!schemaAllOf) return schema;
|
|
2299
|
+
let didMerge = false;
|
|
2300
|
+
const schemaProperties = schema.properties;
|
|
2301
|
+
const schemaRequired = schema.required;
|
|
2302
|
+
const mergedProperties = { ...schemaProperties };
|
|
2303
|
+
const mergedRequired = new Set(schemaRequired);
|
|
2304
|
+
const remainingAllOf = [];
|
|
2305
|
+
for (const subSchema of schemaAllOf) {
|
|
2306
|
+
if (isSchema(subSchema) && isMergeableAllOfObject(subSchema)) {
|
|
2307
|
+
didMerge = true;
|
|
2308
|
+
if (subSchema.properties) Object.assign(mergedProperties, subSchema.properties);
|
|
2309
|
+
const subRequired = subSchema.required;
|
|
2310
|
+
if (subRequired) for (const prop$1 of subRequired) mergedRequired.add(prop$1);
|
|
2311
|
+
continue;
|
|
2211
2312
|
}
|
|
2212
|
-
|
|
2313
|
+
remainingAllOf.push(subSchema);
|
|
2213
2314
|
}
|
|
2214
|
-
if (
|
|
2215
|
-
return
|
|
2315
|
+
if (!didMerge || remainingAllOf.length === 0) return schema;
|
|
2316
|
+
return {
|
|
2317
|
+
...schema,
|
|
2318
|
+
...Object.keys(mergedProperties).length > 0 && { properties: mergedProperties },
|
|
2319
|
+
...mergedRequired.size > 0 && { required: [...mergedRequired] },
|
|
2320
|
+
...remainingAllOf.length > 0 && { allOf: remainingAllOf }
|
|
2321
|
+
};
|
|
2216
2322
|
}
|
|
2217
|
-
function
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
const
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
schema
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
variableName,
|
|
2251
|
-
propName: "value",
|
|
2252
|
-
context,
|
|
2253
|
-
isRequestBodyOptional,
|
|
2254
|
-
keyPrefix: `${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}].`,
|
|
2255
|
-
depth: depth + 1
|
|
2256
|
-
});
|
|
2257
|
-
formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => {
|
|
2258
|
-
${resolvedValue}});\n`;
|
|
2259
|
-
} else valueStr = "JSON.stringify(value)";
|
|
2260
|
-
else if (itemSchema.type === "number" || itemSchema.type?.includes("number") || itemSchema.type === "integer" || itemSchema.type?.includes("integer") || itemSchema.type === "boolean" || itemSchema.type?.includes("boolean")) valueStr = "value.toString()";
|
|
2323
|
+
function combineValues({ resolvedData, resolvedValue, separator: separator$1, context, parentSchema }) {
|
|
2324
|
+
if (resolvedData.isEnum.every(Boolean)) return `${resolvedData.values.join(` | `)}${resolvedValue ? ` | ${resolvedValue.value}` : ""}`;
|
|
2325
|
+
if (separator$1 === "allOf") {
|
|
2326
|
+
let resolvedDataValue = resolvedData.values.map((v) => v.includes(" | ") ? `(${v})` : v).join(` & `);
|
|
2327
|
+
if (resolvedData.originalSchema.length > 0 && resolvedValue) {
|
|
2328
|
+
const discriminatedPropertySchemas = resolvedData.originalSchema.filter((s) => {
|
|
2329
|
+
const disc = s?.discriminator;
|
|
2330
|
+
return disc && resolvedValue.value.includes(` ${disc.propertyName}:`);
|
|
2331
|
+
});
|
|
2332
|
+
if (discriminatedPropertySchemas.length > 0) resolvedDataValue = `Omit<${resolvedDataValue}, '${discriminatedPropertySchemas.map((s) => s.discriminator?.propertyName).join("' | '")}'>`;
|
|
2333
|
+
}
|
|
2334
|
+
const resolvedValueStr = resolvedValue?.value.includes(" | ") ? `(${resolvedValue.value})` : resolvedValue?.value;
|
|
2335
|
+
const joined = `${resolvedDataValue}${resolvedValue ? ` & ${resolvedValueStr}` : ""}`;
|
|
2336
|
+
const overrideRequiredProperties = resolvedData.requiredProperties.filter((prop$1) => !resolvedData.originalSchema.some((schema) => {
|
|
2337
|
+
const props = schema?.properties;
|
|
2338
|
+
const req = schema?.required;
|
|
2339
|
+
return props?.[prop$1] && req?.includes(prop$1);
|
|
2340
|
+
}) && !(() => {
|
|
2341
|
+
const parentProps = parentSchema?.properties;
|
|
2342
|
+
const parentReq = parentSchema?.required;
|
|
2343
|
+
return !!(parentProps?.[prop$1] && parentReq?.includes(prop$1));
|
|
2344
|
+
})());
|
|
2345
|
+
if (overrideRequiredProperties.length > 0) return `${joined} & Required<Pick<${joined}, '${overrideRequiredProperties.join("' | '")}'>>`;
|
|
2346
|
+
return joined;
|
|
2347
|
+
}
|
|
2348
|
+
let values = resolvedData.values;
|
|
2349
|
+
if (resolvedData.allProperties.length && context.output.unionAddMissingProperties) {
|
|
2350
|
+
values = [];
|
|
2351
|
+
for (let i = 0; i < resolvedData.values.length; i += 1) {
|
|
2352
|
+
const subSchema = resolvedData.originalSchema[i];
|
|
2353
|
+
if (subSchema?.type !== "object" || !subSchema.properties) {
|
|
2354
|
+
values.push(resolvedData.values[i]);
|
|
2355
|
+
continue;
|
|
2261
2356
|
}
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
}
|
|
2265
|
-
} else if (property.type === "number" || property.type?.includes("number") || property.type === "integer" || property.type?.includes("integer") || property.type === "boolean" || property.type?.includes("boolean")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2266
|
-
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2267
|
-
let existSubSchemaNullable = false;
|
|
2268
|
-
if (property.allOf || property.anyOf || property.oneOf) {
|
|
2269
|
-
const subSchemas = (property.allOf || property.anyOf || property.oneOf)?.map((c) => resolveObject({
|
|
2270
|
-
schema: c,
|
|
2271
|
-
combined: true,
|
|
2272
|
-
context
|
|
2273
|
-
}));
|
|
2274
|
-
if (subSchemas?.some((subSchema) => {
|
|
2275
|
-
return [
|
|
2276
|
-
"number",
|
|
2277
|
-
"integer",
|
|
2278
|
-
"boolean"
|
|
2279
|
-
].includes(subSchema.type);
|
|
2280
|
-
})) formDataValue = `${variableName}.append(\`${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
2281
|
-
if (subSchemas?.some((subSchema) => {
|
|
2282
|
-
return subSchema.type === "null";
|
|
2283
|
-
})) existSubSchemaNullable = true;
|
|
2357
|
+
const subSchemaProps = subSchema.properties;
|
|
2358
|
+
const missingProperties = unique(resolvedData.allProperties.filter((p) => !Object.keys(subSchemaProps).includes(p)));
|
|
2359
|
+
values.push(`${resolvedData.values[i]}${missingProperties.length > 0 ? ` & {${missingProperties.map((p) => `${p}?: never`).join("; ")}}` : ""}`);
|
|
2284
2360
|
}
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2361
|
+
}
|
|
2362
|
+
if (resolvedValue) return `(${values.join(` & ${resolvedValue.value}) | (`)} & ${resolvedValue.value})`;
|
|
2363
|
+
return values.join(" | ");
|
|
2364
|
+
}
|
|
2365
|
+
function combineSchemas({ name, schema, separator: separator$1, context, nullable, formDataContext }) {
|
|
2366
|
+
const normalizedSchema = separator$1 === "allOf" && !context.output.override.aliasCombinedTypes && !schema.oneOf && !schema.anyOf ? normalizeAllOfSchema(schema) : schema;
|
|
2367
|
+
const items = normalizedSchema[separator$1] ?? [];
|
|
2368
|
+
const resolvedData = {
|
|
2369
|
+
values: [],
|
|
2370
|
+
imports: [],
|
|
2371
|
+
schemas: [],
|
|
2372
|
+
isEnum: [],
|
|
2373
|
+
isRef: [],
|
|
2374
|
+
types: [],
|
|
2375
|
+
dependencies: [],
|
|
2376
|
+
originalSchema: [],
|
|
2377
|
+
allProperties: [],
|
|
2378
|
+
hasReadonlyProps: false,
|
|
2379
|
+
example: schema.example,
|
|
2380
|
+
examples: resolveExampleRefs(schema.examples, context),
|
|
2381
|
+
requiredProperties: separator$1 === "allOf" ? schema.required ?? [] : []
|
|
2382
|
+
};
|
|
2383
|
+
for (const subSchema of items) {
|
|
2384
|
+
let propName;
|
|
2385
|
+
if (context.output.override.aliasCombinedTypes) {
|
|
2386
|
+
propName = name ? name + pascal(separator$1) : void 0;
|
|
2387
|
+
if (propName && resolvedData.schemas.length > 0) propName = propName + pascal(getNumberWord(resolvedData.schemas.length + 1));
|
|
2289
2388
|
}
|
|
2290
|
-
if (
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2389
|
+
if (separator$1 === "allOf" && isSchema(subSchema) && subSchema.required) resolvedData.requiredProperties.push(...subSchema.required);
|
|
2390
|
+
const resolvedValue$1 = resolveObject({
|
|
2391
|
+
schema: subSchema,
|
|
2392
|
+
propName,
|
|
2393
|
+
combined: true,
|
|
2394
|
+
context,
|
|
2395
|
+
formDataContext
|
|
2396
|
+
});
|
|
2397
|
+
const aliasedImports = getAliasedImports({
|
|
2398
|
+
context,
|
|
2399
|
+
name,
|
|
2400
|
+
resolvedValue: resolvedValue$1
|
|
2401
|
+
});
|
|
2402
|
+
const value = getImportAliasForRefOrValue({
|
|
2403
|
+
context,
|
|
2404
|
+
resolvedValue: resolvedValue$1,
|
|
2405
|
+
imports: aliasedImports
|
|
2406
|
+
});
|
|
2407
|
+
resolvedData.values.push(value);
|
|
2408
|
+
resolvedData.imports.push(...aliasedImports);
|
|
2409
|
+
resolvedData.schemas.push(...resolvedValue$1.schemas);
|
|
2410
|
+
resolvedData.dependencies.push(...resolvedValue$1.dependencies);
|
|
2411
|
+
resolvedData.isEnum.push(resolvedValue$1.isEnum);
|
|
2412
|
+
resolvedData.types.push(resolvedValue$1.type);
|
|
2413
|
+
resolvedData.isRef.push(resolvedValue$1.isRef);
|
|
2414
|
+
resolvedData.originalSchema.push(resolvedValue$1.originalSchema);
|
|
2415
|
+
if (resolvedValue$1.hasReadonlyProps) resolvedData.hasReadonlyProps = true;
|
|
2416
|
+
const originalProps = resolvedValue$1.originalSchema.properties;
|
|
2417
|
+
if (resolvedValue$1.type === "object" && originalProps) resolvedData.allProperties.push(...Object.keys(originalProps));
|
|
2418
|
+
}
|
|
2419
|
+
if (resolvedData.isEnum.every(Boolean) && name && items.length > 1 && context.output.override.enumGenerationType !== EnumGeneration.UNION) {
|
|
2420
|
+
const { value: combinedEnumValue, valueImports, hasNull } = getCombinedEnumValue(resolvedData.values.map((value, index) => ({
|
|
2421
|
+
value,
|
|
2422
|
+
isRef: resolvedData.isRef[index],
|
|
2423
|
+
schema: resolvedData.originalSchema[index]
|
|
2424
|
+
})));
|
|
2425
|
+
const newEnum = `export const ${pascal(name)} = ${combinedEnumValue}`;
|
|
2426
|
+
const valueImportSet = new Set(valueImports);
|
|
2427
|
+
const typeSuffix = `${nullable}${hasNull && !nullable.includes("null") ? " | null" : ""}`;
|
|
2428
|
+
return {
|
|
2429
|
+
value: `typeof ${pascal(name)}[keyof typeof ${pascal(name)}]${typeSuffix}`,
|
|
2430
|
+
imports: [{ name: pascal(name) }],
|
|
2431
|
+
schemas: [...resolvedData.schemas, {
|
|
2432
|
+
imports: resolvedData.imports.filter((toImport) => valueImportSet.has(toImport.alias ?? toImport.name)).map((toImport) => ({
|
|
2433
|
+
...toImport,
|
|
2434
|
+
values: true
|
|
2435
|
+
})),
|
|
2436
|
+
model: newEnum,
|
|
2437
|
+
name
|
|
2438
|
+
}],
|
|
2439
|
+
isEnum: false,
|
|
2440
|
+
type: "object",
|
|
2441
|
+
isRef: false,
|
|
2442
|
+
hasReadonlyProps: resolvedData.hasReadonlyProps,
|
|
2443
|
+
dependencies: resolvedData.dependencies,
|
|
2444
|
+
example: schema.example,
|
|
2445
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
2446
|
+
};
|
|
2447
|
+
}
|
|
2448
|
+
let resolvedValue;
|
|
2449
|
+
if (normalizedSchema.properties) resolvedValue = getScalar({
|
|
2450
|
+
item: Object.fromEntries(Object.entries(normalizedSchema).filter(([key]) => key !== separator$1)),
|
|
2451
|
+
name,
|
|
2452
|
+
context,
|
|
2453
|
+
formDataContext
|
|
2454
|
+
});
|
|
2455
|
+
else if (separator$1 === "allOf" && (schema.oneOf || schema.anyOf)) {
|
|
2456
|
+
const siblingCombiner = schema.oneOf ? "oneOf" : "anyOf";
|
|
2457
|
+
const siblingSchemas = schema[siblingCombiner];
|
|
2458
|
+
resolvedValue = combineSchemas({
|
|
2459
|
+
schema: { [siblingCombiner]: siblingSchemas },
|
|
2460
|
+
name,
|
|
2461
|
+
separator: siblingCombiner,
|
|
2462
|
+
context,
|
|
2463
|
+
nullable: ""
|
|
2319
2464
|
});
|
|
2320
|
-
if (isReference(requestBody)) {
|
|
2321
|
-
const { schema: bodySchema } = resolveRef(requestBody, context);
|
|
2322
|
-
if (bodySchema.required !== void 0) isOptional = !bodySchema.required;
|
|
2323
|
-
} else if (requestBody.required !== void 0) isOptional = !requestBody.required;
|
|
2324
2465
|
}
|
|
2325
2466
|
return {
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2467
|
+
value: dedupeUnionType(combineValues({
|
|
2468
|
+
resolvedData,
|
|
2469
|
+
separator: separator$1,
|
|
2470
|
+
resolvedValue,
|
|
2471
|
+
context,
|
|
2472
|
+
parentSchema: normalizedSchema
|
|
2473
|
+
}) + nullable),
|
|
2474
|
+
imports: resolvedValue ? [...resolvedData.imports, ...resolvedValue.imports] : resolvedData.imports,
|
|
2475
|
+
schemas: resolvedValue ? [...resolvedData.schemas, ...resolvedValue.schemas] : resolvedData.schemas,
|
|
2476
|
+
dependencies: resolvedValue ? [...resolvedData.dependencies, ...resolvedValue.dependencies] : resolvedData.dependencies,
|
|
2477
|
+
isEnum: false,
|
|
2478
|
+
type: "object",
|
|
2479
|
+
isRef: false,
|
|
2480
|
+
hasReadonlyProps: resolvedData.hasReadonlyProps || (resolvedValue?.hasReadonlyProps ?? false),
|
|
2481
|
+
example: schema.example,
|
|
2482
|
+
examples: resolveExampleRefs(schema.examples, context)
|
|
2341
2483
|
};
|
|
2342
2484
|
}
|
|
2343
2485
|
|
|
@@ -2346,7 +2488,9 @@ function getBody({ requestBody, operationName, context, contentType }) {
|
|
|
2346
2488
|
function resolveDiscriminators(schemas, context) {
|
|
2347
2489
|
const transformedSchemas = schemas;
|
|
2348
2490
|
for (const schema of Object.values(transformedSchemas)) {
|
|
2349
|
-
if (
|
|
2491
|
+
if (isBoolean$1(schema)) continue;
|
|
2492
|
+
const discriminator = schema.discriminator;
|
|
2493
|
+
if (!schema.oneOf && isArray(discriminator?.oneOf)) schema.oneOf = discriminator.oneOf;
|
|
2350
2494
|
if (schema.discriminator?.mapping) {
|
|
2351
2495
|
const { mapping, propertyName } = schema.discriminator;
|
|
2352
2496
|
for (const [mappingKey, mappingValue] of Object.entries(mapping)) {
|
|
@@ -2357,17 +2501,25 @@ function resolveDiscriminators(schemas, context) {
|
|
|
2357
2501
|
} catch {
|
|
2358
2502
|
subTypeSchema = transformedSchemas[mappingValue];
|
|
2359
2503
|
}
|
|
2360
|
-
if (
|
|
2504
|
+
if (isBoolean$1(subTypeSchema) || propertyName === void 0) continue;
|
|
2361
2505
|
const property = subTypeSchema.properties?.[propertyName];
|
|
2362
|
-
if (
|
|
2506
|
+
if (isBoolean$1(property)) continue;
|
|
2507
|
+
const schemaProperty = property && !isReference(property) ? property : void 0;
|
|
2508
|
+
const enumProperty = schemaProperty ? getPropertySafe(schemaProperty, "enum") : {
|
|
2509
|
+
hasProperty: false,
|
|
2510
|
+
value: void 0
|
|
2511
|
+
};
|
|
2512
|
+
const mergedEnumValues = [...((enumProperty.hasProperty && Array.isArray(enumProperty.value) ? enumProperty.value : void 0) ?? []).filter((value) => value !== mappingKey), mappingKey];
|
|
2513
|
+
const mergedProperty = {
|
|
2514
|
+
...schemaProperty,
|
|
2515
|
+
type: "string",
|
|
2516
|
+
enum: mergedEnumValues
|
|
2517
|
+
};
|
|
2363
2518
|
subTypeSchema.properties = {
|
|
2364
2519
|
...subTypeSchema.properties,
|
|
2365
|
-
[propertyName]:
|
|
2366
|
-
type: "string",
|
|
2367
|
-
enum: [...property?.enum?.filter((value) => value !== mappingKey) ?? [], mappingKey]
|
|
2368
|
-
}
|
|
2520
|
+
[propertyName]: mergedProperty
|
|
2369
2521
|
};
|
|
2370
|
-
subTypeSchema.required = [...subTypeSchema.required ?? [], propertyName];
|
|
2522
|
+
subTypeSchema.required = [...new Set([...subTypeSchema.required ?? [], propertyName])];
|
|
2371
2523
|
}
|
|
2372
2524
|
}
|
|
2373
2525
|
}
|
|
@@ -2389,23 +2541,22 @@ function getOperationId(operation, route, verb) {
|
|
|
2389
2541
|
//#endregion
|
|
2390
2542
|
//#region src/getters/parameters.ts
|
|
2391
2543
|
function getParameters({ parameters, context }) {
|
|
2392
|
-
|
|
2393
|
-
if (isReference(p)) {
|
|
2394
|
-
const { schema: parameter, imports } = resolveRef(p, context);
|
|
2395
|
-
if (parameter.in === "path" || parameter.in === "query" || parameter.in === "header") acc[parameter.in].push({
|
|
2396
|
-
parameter,
|
|
2397
|
-
imports
|
|
2398
|
-
});
|
|
2399
|
-
} else if (p.in === "query" || p.in === "path" || p.in === "header") acc[p.in].push({
|
|
2400
|
-
parameter: p,
|
|
2401
|
-
imports: []
|
|
2402
|
-
});
|
|
2403
|
-
return acc;
|
|
2404
|
-
}, {
|
|
2544
|
+
const result = {
|
|
2405
2545
|
path: [],
|
|
2406
2546
|
query: [],
|
|
2407
2547
|
header: []
|
|
2548
|
+
};
|
|
2549
|
+
for (const p of parameters) if (isReference(p)) {
|
|
2550
|
+
const { schema: parameter, imports } = resolveRef(p, context);
|
|
2551
|
+
if (parameter.in === "path" || parameter.in === "query" || parameter.in === "header") result[parameter.in].push({
|
|
2552
|
+
parameter,
|
|
2553
|
+
imports
|
|
2554
|
+
});
|
|
2555
|
+
} else if (p.in === "query" || p.in === "path" || p.in === "header") result[p.in].push({
|
|
2556
|
+
parameter: p,
|
|
2557
|
+
imports: []
|
|
2408
2558
|
});
|
|
2559
|
+
return result;
|
|
2409
2560
|
}
|
|
2410
2561
|
|
|
2411
2562
|
//#endregion
|
|
@@ -2449,16 +2600,18 @@ function getParams({ route, pathParams = [], operationId, context, output }) {
|
|
|
2449
2600
|
schema,
|
|
2450
2601
|
context
|
|
2451
2602
|
});
|
|
2603
|
+
const originalSchema = resolvedValue.originalSchema;
|
|
2604
|
+
const schemaDefault = originalSchema.default;
|
|
2452
2605
|
let paramType = resolvedValue.value;
|
|
2453
2606
|
if (output.allParamsOptional) paramType = `${paramType} | undefined | null`;
|
|
2454
2607
|
return {
|
|
2455
2608
|
name,
|
|
2456
|
-
definition: `${name}${!required ||
|
|
2457
|
-
implementation: `${name}${!required && !
|
|
2458
|
-
default:
|
|
2609
|
+
definition: `${name}${!required || schemaDefault ? "?" : ""}: ${paramType}`,
|
|
2610
|
+
implementation: `${name}${!required && !schemaDefault ? "?" : ""}${schemaDefault ? `: ${paramType} = ${stringify(schemaDefault)}` : `: ${paramType}`}`,
|
|
2611
|
+
default: schemaDefault,
|
|
2459
2612
|
required,
|
|
2460
2613
|
imports: resolvedValue.imports,
|
|
2461
|
-
originalSchema
|
|
2614
|
+
originalSchema
|
|
2462
2615
|
};
|
|
2463
2616
|
});
|
|
2464
2617
|
}
|
|
@@ -2479,7 +2632,7 @@ function getProps({ body, queryParams, params, operationName, headers, context }
|
|
|
2479
2632
|
definition: getQueryParamDefinition(queryParams, context),
|
|
2480
2633
|
implementation: getQueryParamDefinition(queryParams, context),
|
|
2481
2634
|
default: false,
|
|
2482
|
-
required:
|
|
2635
|
+
required: isNullish(queryParams?.isOptional) ? !context.output.allParamsOptional || context.output.optionsParamRequired : !queryParams.isOptional && !context.output.allParamsOptional || context.output.optionsParamRequired,
|
|
2483
2636
|
type: GetterPropType.QUERY_PARAM
|
|
2484
2637
|
};
|
|
2485
2638
|
const headersProp = {
|
|
@@ -2487,7 +2640,7 @@ function getProps({ body, queryParams, params, operationName, headers, context }
|
|
|
2487
2640
|
definition: `headers${headers?.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${headers?.schema.name}`,
|
|
2488
2641
|
implementation: `headers${headers?.isOptional && !context.output.optionsParamRequired ? "?" : ""}: ${headers?.schema.name}`,
|
|
2489
2642
|
default: false,
|
|
2490
|
-
required:
|
|
2643
|
+
required: isNullish(headers?.isOptional) ? false : !headers.isOptional || context.output.optionsParamRequired,
|
|
2491
2644
|
type: GetterPropType.HEADER
|
|
2492
2645
|
};
|
|
2493
2646
|
let paramGetterProps;
|
|
@@ -2541,16 +2694,18 @@ function getQueryParamsTypes(queryParams, operationName, context) {
|
|
|
2541
2694
|
es5keyword: true,
|
|
2542
2695
|
es5IdentifierName: true
|
|
2543
2696
|
});
|
|
2544
|
-
const schema = schemaParam
|
|
2697
|
+
const schema = schemaParam ?? content?.["application/json"]?.schema;
|
|
2698
|
+
if (!schema) throw new Error(`Query parameter "${name}" has no schema or content definition`);
|
|
2545
2699
|
const resolvedValue = resolveValue({
|
|
2546
2700
|
schema,
|
|
2547
2701
|
context,
|
|
2548
2702
|
name: queryName
|
|
2549
2703
|
});
|
|
2550
2704
|
const key = getKey(name);
|
|
2705
|
+
const schemaForDoc = schema;
|
|
2551
2706
|
const doc = jsDoc({
|
|
2552
2707
|
description: parameter.description,
|
|
2553
|
-
...
|
|
2708
|
+
...schemaForDoc
|
|
2554
2709
|
}, void 0, context);
|
|
2555
2710
|
if (parameterImports.length > 0) return {
|
|
2556
2711
|
definition: `${doc}${key}${!required || schema.default ? "?" : ""}: ${parameterImports[0].name};`,
|
|
@@ -2560,7 +2715,7 @@ function getQueryParamsTypes(queryParams, operationName, context) {
|
|
|
2560
2715
|
};
|
|
2561
2716
|
if (resolvedValue.isEnum && !resolvedValue.isRef) {
|
|
2562
2717
|
const enumName = queryName;
|
|
2563
|
-
const enumValue = getEnum(resolvedValue.value, enumName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention
|
|
2718
|
+
const enumValue = getEnum(resolvedValue.value, enumName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
|
|
2564
2719
|
return {
|
|
2565
2720
|
definition: `${doc}${key}${!required || schema.default ? "?" : ""}: ${enumName};`,
|
|
2566
2721
|
imports: [{ name: enumName }],
|
|
@@ -2602,39 +2757,16 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
|
|
|
2602
2757
|
//#endregion
|
|
2603
2758
|
//#region src/getters/response.ts
|
|
2604
2759
|
function getResponse({ responses, operationName, context, contentType }) {
|
|
2605
|
-
|
|
2606
|
-
imports: [],
|
|
2607
|
-
definition: {
|
|
2608
|
-
success: "",
|
|
2609
|
-
errors: ""
|
|
2610
|
-
},
|
|
2611
|
-
isBlob: false,
|
|
2612
|
-
types: {
|
|
2613
|
-
success: [],
|
|
2614
|
-
errors: []
|
|
2615
|
-
},
|
|
2616
|
-
schemas: [],
|
|
2617
|
-
contentTypes: []
|
|
2618
|
-
};
|
|
2619
|
-
const types = getResReqTypes(Object.entries(responses), operationName, context, "void", (type) => `${type.key}-${type.value}`);
|
|
2620
|
-
const filteredTypes = contentType ? types.filter((type) => {
|
|
2621
|
-
let include = true;
|
|
2622
|
-
let exclude = false;
|
|
2623
|
-
if (contentType.include) include = contentType.include.includes(type.contentType);
|
|
2624
|
-
if (contentType.exclude) exclude = contentType.exclude.includes(type.contentType);
|
|
2625
|
-
return include && !exclude;
|
|
2626
|
-
}) : types;
|
|
2760
|
+
const filteredTypes = filterByContentType(getResReqTypes(Object.entries(responses), operationName, context, "void", (type) => `${type.key}-${type.value}`), contentType);
|
|
2627
2761
|
const imports = filteredTypes.flatMap(({ imports: imports$1 }) => imports$1);
|
|
2628
2762
|
const schemas = filteredTypes.flatMap(({ schemas: schemas$1 }) => schemas$1);
|
|
2629
2763
|
const contentTypes = [...new Set(filteredTypes.map(({ contentType: contentType$1 }) => contentType$1))];
|
|
2630
|
-
const groupedByStatus =
|
|
2631
|
-
if (type.key.startsWith("2")) acc.success.push(type);
|
|
2632
|
-
else acc.errors.push(type);
|
|
2633
|
-
return acc;
|
|
2634
|
-
}, {
|
|
2764
|
+
const groupedByStatus = {
|
|
2635
2765
|
success: [],
|
|
2636
2766
|
errors: []
|
|
2637
|
-
}
|
|
2767
|
+
};
|
|
2768
|
+
for (const type of filteredTypes) if (type.key.startsWith("2")) groupedByStatus.success.push(type);
|
|
2769
|
+
else groupedByStatus.errors.push(type);
|
|
2638
2770
|
const success = dedupeUnionType(groupedByStatus.success.map(({ value, formData }) => formData ? "Blob" : value).join(" | "));
|
|
2639
2771
|
const errors = dedupeUnionType(groupedByStatus.errors.map(({ value }) => value).join(" | "));
|
|
2640
2772
|
const defaultType = filteredTypes.find(({ key }) => key === "default")?.value;
|
|
@@ -2670,16 +2802,18 @@ const getRoutePath = (path$2) => {
|
|
|
2670
2802
|
return hasParam(path$2) ? `${prev}\${${param}}${next}` : `${prev}${param}${next}`;
|
|
2671
2803
|
};
|
|
2672
2804
|
function getRoute(route) {
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2805
|
+
const splittedRoute = route.split("/");
|
|
2806
|
+
let result = "";
|
|
2807
|
+
for (const [i, path$2] of splittedRoute.entries()) {
|
|
2808
|
+
if (!path$2 && !i) continue;
|
|
2809
|
+
result += path$2.includes("{") ? `/${getRoutePath(path$2)}` : `/${path$2}`;
|
|
2810
|
+
}
|
|
2811
|
+
return result;
|
|
2678
2812
|
}
|
|
2679
2813
|
function getFullRoute(route, servers, baseUrl) {
|
|
2680
2814
|
const getBaseUrl = () => {
|
|
2681
2815
|
if (!baseUrl) return "";
|
|
2682
|
-
if (
|
|
2816
|
+
if (isString(baseUrl)) return baseUrl;
|
|
2683
2817
|
if (baseUrl.getBaseUrlFromSpecification) {
|
|
2684
2818
|
if (!servers) throw new Error("Orval is configured to use baseUrl from the specifications 'servers' field, but there exist no servers in the specification.");
|
|
2685
2819
|
const server = servers.at(Math.min(baseUrl.index ?? 0, servers.length - 1));
|
|
@@ -2754,25 +2888,26 @@ function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CA
|
|
|
2754
2888
|
}).join("\n");
|
|
2755
2889
|
}
|
|
2756
2890
|
function generateMutatorImports({ mutators, implementation, oneMore }) {
|
|
2757
|
-
|
|
2891
|
+
let imports = "";
|
|
2892
|
+
for (const mutator of uniqueWith(mutators, (a, b) => a.name === b.name && a.default === b.default)) {
|
|
2758
2893
|
const path$2 = `${oneMore ? "../" : ""}${mutator.path}`;
|
|
2759
2894
|
const importDefault = mutator.default ? mutator.name : `{ ${mutator.name} }`;
|
|
2760
|
-
|
|
2761
|
-
|
|
2895
|
+
imports += `import ${importDefault} from '${path$2}';`;
|
|
2896
|
+
imports += "\n";
|
|
2762
2897
|
if (implementation && (mutator.hasErrorType || mutator.bodyTypeName)) {
|
|
2763
2898
|
let errorImportName = "";
|
|
2764
2899
|
const targetErrorImportName = mutator.default ? `ErrorType as ${mutator.errorTypeName}` : mutator.errorTypeName;
|
|
2765
|
-
if (mutator.hasErrorType && implementation.includes(mutator.errorTypeName) && !
|
|
2900
|
+
if (mutator.hasErrorType && implementation.includes(mutator.errorTypeName) && !imports.includes(`{ ${targetErrorImportName} `)) errorImportName = targetErrorImportName;
|
|
2766
2901
|
let bodyImportName = "";
|
|
2767
2902
|
const targetBodyImportName = mutator.default ? `BodyType as ${mutator.bodyTypeName}` : mutator.bodyTypeName;
|
|
2768
|
-
if (mutator.bodyTypeName && implementation.includes(mutator.bodyTypeName) && !
|
|
2903
|
+
if (mutator.bodyTypeName && implementation.includes(mutator.bodyTypeName) && !imports.includes(` ${targetBodyImportName} }`)) bodyImportName = targetBodyImportName ?? "";
|
|
2769
2904
|
if (bodyImportName || errorImportName) {
|
|
2770
|
-
|
|
2771
|
-
|
|
2905
|
+
imports += `import type { ${errorImportName}${errorImportName && bodyImportName ? " , " : ""}${bodyImportName} } from '${path$2}';`;
|
|
2906
|
+
imports += "\n";
|
|
2772
2907
|
}
|
|
2773
2908
|
}
|
|
2774
|
-
|
|
2775
|
-
|
|
2909
|
+
}
|
|
2910
|
+
return imports;
|
|
2776
2911
|
}
|
|
2777
2912
|
function generateDependency({ deps, isAllowSyntheticDefaultImports, dependency, projectName, key, onlyTypes }) {
|
|
2778
2913
|
const defaultDep = deps.find((e) => e.default && (isAllowSyntheticDefaultImports || !e.syntheticDefaultImport));
|
|
@@ -2787,31 +2922,25 @@ function generateDependency({ deps, isAllowSyntheticDefaultImports, dependency,
|
|
|
2787
2922
|
importString += `import ${onlyTypes ? "type " : ""}${defaultDep ? `${defaultDep.name}${depsString ? "," : ""}` : ""}${depsString ? `{\n ${depsString}\n}` : ""} from '${dependency}${key !== "default" && projectName ? `/${projectName}` : ""}';`;
|
|
2788
2923
|
return importString;
|
|
2789
2924
|
}
|
|
2790
|
-
function addDependency({ implementation, exports, dependency, projectName,
|
|
2925
|
+
function addDependency({ implementation, exports, dependency, projectName, isAllowSyntheticDefaultImports }) {
|
|
2791
2926
|
const toAdds = exports.filter((e) => {
|
|
2792
2927
|
const searchWords = [e.alias, e.name].filter((p) => p?.length).join("|");
|
|
2793
2928
|
const pattern = new RegExp(String.raw`\b(${searchWords})\b`, "g");
|
|
2794
2929
|
return implementation.match(pattern);
|
|
2795
2930
|
});
|
|
2796
2931
|
if (toAdds.length === 0) return;
|
|
2797
|
-
const groupedBySpecKey =
|
|
2932
|
+
const groupedBySpecKey = { default: {
|
|
2933
|
+
types: [],
|
|
2934
|
+
values: []
|
|
2935
|
+
} };
|
|
2936
|
+
for (const dep of toAdds) {
|
|
2798
2937
|
const key = "default";
|
|
2799
|
-
if (dep.values && (isAllowSyntheticDefaultImports || !dep.syntheticDefaultImport))
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
values: [...acc[key]?.values ?? [], dep]
|
|
2803
|
-
};
|
|
2804
|
-
return acc;
|
|
2805
|
-
}
|
|
2806
|
-
acc[key] = {
|
|
2807
|
-
...acc[key],
|
|
2808
|
-
types: [...acc[key]?.types ?? [], dep]
|
|
2809
|
-
};
|
|
2810
|
-
return acc;
|
|
2811
|
-
}, {});
|
|
2938
|
+
if (dep.values && (isAllowSyntheticDefaultImports || !dep.syntheticDefaultImport)) groupedBySpecKey[key].values.push(dep);
|
|
2939
|
+
else groupedBySpecKey[key].types.push(dep);
|
|
2940
|
+
}
|
|
2812
2941
|
return Object.entries(groupedBySpecKey).map(([key, { values, types }]) => {
|
|
2813
2942
|
let dep = "";
|
|
2814
|
-
if (values) dep += generateDependency({
|
|
2943
|
+
if (values.length > 0) dep += generateDependency({
|
|
2815
2944
|
deps: values,
|
|
2816
2945
|
isAllowSyntheticDefaultImports,
|
|
2817
2946
|
dependency,
|
|
@@ -2819,9 +2948,9 @@ function addDependency({ implementation, exports, dependency, projectName, hasSc
|
|
|
2819
2948
|
key,
|
|
2820
2949
|
onlyTypes: false
|
|
2821
2950
|
});
|
|
2822
|
-
if (types) {
|
|
2951
|
+
if (types.length > 0) {
|
|
2823
2952
|
let uniqueTypes = types;
|
|
2824
|
-
if (values) {
|
|
2953
|
+
if (values.length > 0) {
|
|
2825
2954
|
uniqueTypes = types.filter((t) => !values.some((v) => v.name === t.name));
|
|
2826
2955
|
dep += "\n";
|
|
2827
2956
|
}
|
|
@@ -2848,7 +2977,7 @@ function generateDependencyImports(implementation, imports, projectName, hasSche
|
|
|
2848
2977
|
projectName,
|
|
2849
2978
|
hasSchemaDir,
|
|
2850
2979
|
isAllowSyntheticDefaultImports
|
|
2851
|
-
})).filter(Boolean).
|
|
2980
|
+
})).filter((x) => Boolean(x)).toSorted((a, b) => {
|
|
2852
2981
|
const aLib = getLibName(a);
|
|
2853
2982
|
const bLib = getLibName(b);
|
|
2854
2983
|
if (aLib === bLib) return 0;
|
|
@@ -2874,7 +3003,10 @@ function generateModelInline(acc, model) {
|
|
|
2874
3003
|
return acc + `${model}\n`;
|
|
2875
3004
|
}
|
|
2876
3005
|
function generateModelsInline(obj) {
|
|
2877
|
-
|
|
3006
|
+
const schemas = Object.values(obj).flat();
|
|
3007
|
+
let result = "";
|
|
3008
|
+
for (const { model } of schemas) result = generateModelInline(result, model);
|
|
3009
|
+
return result;
|
|
2878
3010
|
}
|
|
2879
3011
|
|
|
2880
3012
|
//#endregion
|
|
@@ -2900,7 +3032,7 @@ async function bundleFile(root, fileName, alias, external, compilerOptions) {
|
|
|
2900
3032
|
treeShaking: false,
|
|
2901
3033
|
keepNames: false,
|
|
2902
3034
|
alias,
|
|
2903
|
-
external: external
|
|
3035
|
+
external: external ?? ["*"]
|
|
2904
3036
|
})).outputFiles[0];
|
|
2905
3037
|
return text;
|
|
2906
3038
|
}
|
|
@@ -3045,7 +3177,7 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryPar
|
|
|
3045
3177
|
if (headers) value += "\n headers,";
|
|
3046
3178
|
if (hasSignal) value += isExactOptionalPropertyTypes ? `\n ...(${signalVar} ? { ${signalProp} } : {}),` : `\n ${signalProp},`;
|
|
3047
3179
|
}
|
|
3048
|
-
if (!isObject(requestOptions) || !
|
|
3180
|
+
if (!isObject(requestOptions) || !Object.hasOwn(requestOptions, "responseType")) {
|
|
3049
3181
|
if (response.isBlob) value += `\n responseType: 'blob',`;
|
|
3050
3182
|
else if (response.contentTypes.at(0) === "text/plain") value += `\n responseType: 'text',`;
|
|
3051
3183
|
}
|
|
@@ -3057,7 +3189,7 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryPar
|
|
|
3057
3189
|
else value += "\n params: {...params, ...options?.params},";
|
|
3058
3190
|
if (headers) value += "\n headers: {...headers, ...options?.headers},";
|
|
3059
3191
|
}
|
|
3060
|
-
if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) value += paramsSerializer ? `\n paramsSerializer: ${paramsSerializer.name},` : `\n paramsSerializer: (params) => qs.stringify(params, ${JSON.stringify(paramsSerializerOptions
|
|
3192
|
+
if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) value += paramsSerializer ? `\n paramsSerializer: ${paramsSerializer.name},` : `\n paramsSerializer: (params) => qs.stringify(params, ${JSON.stringify(paramsSerializerOptions?.qs)}),`;
|
|
3061
3193
|
return value;
|
|
3062
3194
|
}
|
|
3063
3195
|
function generateOptions({ route, body, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions }) {
|
|
@@ -3098,7 +3230,7 @@ function generateQueryParamsAxiosConfig(response, isVue, queryParams) {
|
|
|
3098
3230
|
function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue }) {
|
|
3099
3231
|
const bodyOptions = getIsBodyVerb(verb) ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) : "";
|
|
3100
3232
|
const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, queryParams);
|
|
3101
|
-
const headerOptions = body.contentType ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
|
|
3233
|
+
const headerOptions = body.contentType && !["multipart/form-data"].includes(body.contentType) ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
|
|
3102
3234
|
const signalVar = hasSignalParam ? "querySignal" : "signal";
|
|
3103
3235
|
const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
|
|
3104
3236
|
return `{url: \`${route}\`, method: '${verb.toUpperCase()}'${headerOptions}${bodyOptions}${queryParamsOptions}${hasSignal ? `, ${isExactOptionalPropertyTypes ? `...(${signalVar} ? { ${signalProp} }: {})` : signalProp}` : ""}\n }`;
|
|
@@ -3180,18 +3312,20 @@ function generateInterface({ name, schema, context }) {
|
|
|
3180
3312
|
context
|
|
3181
3313
|
});
|
|
3182
3314
|
const isEmptyObject = scalar.value === "{}";
|
|
3183
|
-
const shouldUseTypeAlias = context
|
|
3315
|
+
const shouldUseTypeAlias = context.output.override.useTypeOverInterfaces ?? scalar.useTypeAlias;
|
|
3184
3316
|
let model = "";
|
|
3185
3317
|
model += jsDoc(schema);
|
|
3186
3318
|
if (isEmptyObject) model += "// eslint-disable-next-line @typescript-eslint/no-empty-interface\n";
|
|
3187
|
-
if (scalar.type === "object" && !shouldUseTypeAlias)
|
|
3188
|
-
const
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3319
|
+
if (scalar.type === "object" && !shouldUseTypeAlias) {
|
|
3320
|
+
const properties = schema.properties;
|
|
3321
|
+
if (properties && Object.values(properties).length > 0 && Object.values(properties).every((item) => "const" in item)) {
|
|
3322
|
+
const mappedScalarValue = scalar.value.replaceAll(";", ",").replaceAll("?:", ":");
|
|
3323
|
+
model += `export const ${name}Value = ${mappedScalarValue} as const;\nexport type ${name} = typeof ${name}Value;\n`;
|
|
3324
|
+
} else {
|
|
3325
|
+
const blankInterfaceValue = scalar.value === "unknown" ? "{}" : scalar.value;
|
|
3326
|
+
model += `export interface ${name} ${blankInterfaceValue}\n`;
|
|
3327
|
+
}
|
|
3328
|
+
} else model += `export type ${name} = ${scalar.value};\n`;
|
|
3195
3329
|
const externalModulesImportsOnly = scalar.imports.filter((importName) => importName.alias ? importName.alias !== name : importName.name !== name);
|
|
3196
3330
|
return [...scalar.schemas, {
|
|
3197
3331
|
name,
|
|
@@ -3241,7 +3375,7 @@ function sortSchemasByDependencies(schemas) {
|
|
|
3241
3375
|
for (const dependencyName of schema.dependencies) if (dependencyName && schemaNames.has(dependencyName)) dependencies.add(dependencyName);
|
|
3242
3376
|
}
|
|
3243
3377
|
for (const imp of schema.imports) {
|
|
3244
|
-
const dependencyName = imp.alias
|
|
3378
|
+
const dependencyName = imp.alias ?? imp.name;
|
|
3245
3379
|
if (dependencyName && schemaNames.has(dependencyName)) dependencies.add(dependencyName);
|
|
3246
3380
|
}
|
|
3247
3381
|
dependencyMap.set(schema.name, dependencies);
|
|
@@ -3278,7 +3412,7 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
|
|
|
3278
3412
|
es5keyword: true,
|
|
3279
3413
|
es5IdentifierName: true
|
|
3280
3414
|
});
|
|
3281
|
-
if (
|
|
3415
|
+
if (isBoolean(schema)) return [{
|
|
3282
3416
|
name: sanitizedSchemaName,
|
|
3283
3417
|
model: `export type ${sanitizedSchemaName} = ${schema ? "any" : "never"};\n`,
|
|
3284
3418
|
imports: [],
|
|
@@ -3297,7 +3431,7 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
|
|
|
3297
3431
|
let output = "";
|
|
3298
3432
|
let imports = resolvedValue.imports;
|
|
3299
3433
|
output += jsDoc(schema);
|
|
3300
|
-
if (resolvedValue.isEnum && !resolvedValue.isRef) output += getEnum(resolvedValue.value, sanitizedSchemaName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention
|
|
3434
|
+
if (resolvedValue.isEnum && !resolvedValue.isRef) output += getEnum(resolvedValue.value, sanitizedSchemaName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
|
|
3301
3435
|
else if (sanitizedSchemaName === resolvedValue.value && resolvedValue.isRef) {
|
|
3302
3436
|
const { schema: referredSchema } = resolveRef(schema, context);
|
|
3303
3437
|
if (!shouldCreateInterface(referredSchema)) {
|
|
@@ -3316,7 +3450,7 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
|
|
|
3316
3450
|
resolvedValue.schemas = resolvedValue.schemas.filter((schema$1) => {
|
|
3317
3451
|
if (schema$1.name !== sanitizedSchemaName) return true;
|
|
3318
3452
|
output += `${schema$1.model}\n`;
|
|
3319
|
-
imports = imports
|
|
3453
|
+
imports = [...imports, ...schema$1.imports];
|
|
3320
3454
|
resolvedValue.dependencies.push(...schema$1.dependencies ?? []);
|
|
3321
3455
|
return false;
|
|
3322
3456
|
});
|
|
@@ -3333,26 +3467,56 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
|
|
|
3333
3467
|
|
|
3334
3468
|
//#endregion
|
|
3335
3469
|
//#region src/generators/verbs-options.ts
|
|
3336
|
-
|
|
3337
|
-
|
|
3470
|
+
/**
|
|
3471
|
+
* Get a content-type specific suffix for operation names (#2812)
|
|
3472
|
+
*/
|
|
3473
|
+
function getContentTypeSuffix(contentType) {
|
|
3474
|
+
return {
|
|
3475
|
+
"application/json": "Json",
|
|
3476
|
+
"multipart/form-data": "FormData",
|
|
3477
|
+
"application/x-www-form-urlencoded": "UrlEncoded",
|
|
3478
|
+
"application/xml": "Xml",
|
|
3479
|
+
"text/plain": "Text"
|
|
3480
|
+
}[contentType] || pascal(contentType.replaceAll(/[^a-zA-Z0-9]/g, "_"));
|
|
3481
|
+
}
|
|
3482
|
+
async function generateVerbOptions({ verb, output, operation, route, pathRoute, verbParameters = [], context, contentType }) {
|
|
3483
|
+
const { responses, requestBody, parameters: operationParameters, tags: rawTags, deprecated: rawDeprecated, description: rawDescription, summary: rawSummary } = operation;
|
|
3484
|
+
const tags = rawTags ?? [];
|
|
3485
|
+
const deprecated = rawDeprecated;
|
|
3486
|
+
const description = rawDescription;
|
|
3487
|
+
const summary = rawSummary;
|
|
3338
3488
|
const operationId = getOperationId(operation, route, verb);
|
|
3339
3489
|
const overrideOperation = output.override.operations[operationId];
|
|
3340
|
-
|
|
3341
|
-
const
|
|
3490
|
+
let overrideTag = {};
|
|
3491
|
+
for (const [tag, options] of Object.entries(output.override.tags)) if (tags.includes(tag) && options) overrideTag = mergeDeep(overrideTag, options);
|
|
3492
|
+
const override = mergeDeep(mergeDeep(output.override, overrideTag), overrideOperation ?? {});
|
|
3493
|
+
const originalContentTypeFilter = override.contentType;
|
|
3494
|
+
const requestBodyContentTypeFilter = contentType ? { include: [contentType] } : override.contentType;
|
|
3342
3495
|
const overrideOperationName = overrideOperation?.operationName ?? output.override.operationName;
|
|
3343
|
-
|
|
3496
|
+
let operationName = overrideOperationName ? overrideOperationName(operation, route, verb) : sanitize(camel(operationId), { es5keyword: true });
|
|
3497
|
+
if (contentType) operationName = operationName + "With" + getContentTypeSuffix(contentType);
|
|
3344
3498
|
const response = getResponse({
|
|
3345
|
-
responses,
|
|
3499
|
+
responses: responses ?? {},
|
|
3346
3500
|
operationName,
|
|
3347
3501
|
context,
|
|
3348
|
-
contentType:
|
|
3502
|
+
contentType: originalContentTypeFilter
|
|
3349
3503
|
});
|
|
3350
|
-
const body = getBody({
|
|
3504
|
+
const body = requestBody ? getBody({
|
|
3351
3505
|
requestBody,
|
|
3352
3506
|
operationName,
|
|
3353
3507
|
context,
|
|
3354
|
-
contentType:
|
|
3355
|
-
})
|
|
3508
|
+
contentType: requestBodyContentTypeFilter
|
|
3509
|
+
}) : {
|
|
3510
|
+
originalSchema: {},
|
|
3511
|
+
definition: "",
|
|
3512
|
+
implementation: "",
|
|
3513
|
+
imports: [],
|
|
3514
|
+
schemas: [],
|
|
3515
|
+
formData: "",
|
|
3516
|
+
formUrlEncoded: "",
|
|
3517
|
+
contentType: "",
|
|
3518
|
+
isOptional: false
|
|
3519
|
+
};
|
|
3356
3520
|
const parameters = getParameters({
|
|
3357
3521
|
parameters: [...verbParameters, ...operationParameters ?? []],
|
|
3358
3522
|
context
|
|
@@ -3428,7 +3592,7 @@ async function generateVerbOptions({ verb, output, operation, route, pathRoute,
|
|
|
3428
3592
|
tags,
|
|
3429
3593
|
route,
|
|
3430
3594
|
pathRoute,
|
|
3431
|
-
summary
|
|
3595
|
+
summary,
|
|
3432
3596
|
operationId,
|
|
3433
3597
|
operationName,
|
|
3434
3598
|
response,
|
|
@@ -3453,23 +3617,39 @@ async function generateVerbOptions({ verb, output, operation, route, pathRoute,
|
|
|
3453
3617
|
function generateVerbsOptions({ verbs, input, output, route, pathRoute, context }) {
|
|
3454
3618
|
return asyncReduce(_filteredVerbs(verbs, input.filters), async (acc, [verb, operation]) => {
|
|
3455
3619
|
if (isVerb(verb)) {
|
|
3456
|
-
const
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3620
|
+
const contentTypes = getRequestBodyContentTypes(operation.requestBody, context);
|
|
3621
|
+
if (contentTypes.length > 1) for (const contentType of contentTypes) {
|
|
3622
|
+
const verbOptions = await generateVerbOptions({
|
|
3623
|
+
verb,
|
|
3624
|
+
output,
|
|
3625
|
+
verbParameters: verbs.parameters,
|
|
3626
|
+
route,
|
|
3627
|
+
pathRoute,
|
|
3628
|
+
operation,
|
|
3629
|
+
context,
|
|
3630
|
+
contentType
|
|
3631
|
+
});
|
|
3632
|
+
acc.push(verbOptions);
|
|
3633
|
+
}
|
|
3634
|
+
else {
|
|
3635
|
+
const verbOptions = await generateVerbOptions({
|
|
3636
|
+
verb,
|
|
3637
|
+
output,
|
|
3638
|
+
verbParameters: verbs.parameters,
|
|
3639
|
+
route,
|
|
3640
|
+
pathRoute,
|
|
3641
|
+
operation,
|
|
3642
|
+
context
|
|
3643
|
+
});
|
|
3644
|
+
acc.push(verbOptions);
|
|
3645
|
+
}
|
|
3466
3646
|
}
|
|
3467
3647
|
return acc;
|
|
3468
3648
|
}, []);
|
|
3469
3649
|
}
|
|
3470
3650
|
function _filteredVerbs(verbs, filters) {
|
|
3471
3651
|
if (filters?.tags === void 0) return Object.entries(verbs);
|
|
3472
|
-
const filterTags = filters.tags
|
|
3652
|
+
const filterTags = filters.tags;
|
|
3473
3653
|
const filterMode = filters.mode ?? "include";
|
|
3474
3654
|
return Object.entries(verbs).filter(([, operation]) => {
|
|
3475
3655
|
const isMatch = (operation.tags ?? []).some((tag) => filterTags.some((filterTag) => filterTag instanceof RegExp ? filterTag.test(tag) : filterTag === tag));
|
|
@@ -3515,17 +3695,25 @@ function splitSchemasByType(schemas) {
|
|
|
3515
3695
|
};
|
|
3516
3696
|
}
|
|
3517
3697
|
/**
|
|
3698
|
+
* Get the import extension from a file extension.
|
|
3699
|
+
* Removes `.ts` suffix since TypeScript doesn't need it in imports.
|
|
3700
|
+
*/
|
|
3701
|
+
function getImportExtension(fileExtension) {
|
|
3702
|
+
return fileExtension.replace(/\.ts$/, "") || "";
|
|
3703
|
+
}
|
|
3704
|
+
/**
|
|
3518
3705
|
* Fix cross-directory imports when schemas reference other schemas in a different directory.
|
|
3519
3706
|
* Updates import paths to use correct relative paths between directories.
|
|
3520
3707
|
*/
|
|
3521
|
-
function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention) {
|
|
3708
|
+
function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention, fileExtension) {
|
|
3522
3709
|
const relativePath = relativeSafe(fromPath, toPath);
|
|
3710
|
+
const importExtension = getImportExtension(fileExtension);
|
|
3523
3711
|
for (const schema of schemas) schema.imports = schema.imports.map((imp) => {
|
|
3524
3712
|
if (targetSchemaNames.has(imp.name)) {
|
|
3525
3713
|
const fileName = conventionName(imp.name, namingConvention);
|
|
3526
3714
|
return {
|
|
3527
3715
|
...imp,
|
|
3528
|
-
importPath: joinSafe(relativePath, fileName)
|
|
3716
|
+
importPath: joinSafe(relativePath, fileName) + importExtension
|
|
3529
3717
|
};
|
|
3530
3718
|
}
|
|
3531
3719
|
return imp;
|
|
@@ -3534,14 +3722,14 @@ function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingCo
|
|
|
3534
3722
|
/**
|
|
3535
3723
|
* Fix imports in operation schemas that reference regular schemas.
|
|
3536
3724
|
*/
|
|
3537
|
-
function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention) {
|
|
3538
|
-
fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention);
|
|
3725
|
+
function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
|
|
3726
|
+
fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention, fileExtension);
|
|
3539
3727
|
}
|
|
3540
3728
|
/**
|
|
3541
3729
|
* Fix imports in regular schemas that reference operation schemas.
|
|
3542
3730
|
*/
|
|
3543
|
-
function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention) {
|
|
3544
|
-
fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention);
|
|
3731
|
+
function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
|
|
3732
|
+
fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension);
|
|
3545
3733
|
}
|
|
3546
3734
|
function getSchemaKey(schemaPath, schemaName, namingConvention, fileExtension) {
|
|
3547
3735
|
return getPath(schemaPath, conventionName(schemaName, namingConvention), fileExtension).toLowerCase().replaceAll("\\", "/");
|
|
@@ -3594,7 +3782,7 @@ function removeFileExtension(path$2, fileExtension) {
|
|
|
3594
3782
|
function getSchema({ schema: { imports, model }, target, header, namingConvention = NamingConvention.CAMEL_CASE }) {
|
|
3595
3783
|
let file = header;
|
|
3596
3784
|
file += generateImports({
|
|
3597
|
-
imports: imports.filter((imp) => !model.includes(`type ${imp.alias
|
|
3785
|
+
imports: imports.filter((imp) => !model.includes(`type ${imp.alias ?? imp.name} =`) && !model.includes(`interface ${imp.alias ?? imp.name} {`)),
|
|
3598
3786
|
target,
|
|
3599
3787
|
namingConvention
|
|
3600
3788
|
});
|
|
@@ -3623,7 +3811,7 @@ async function writeSchema({ path: path$2, schema, target, namingConvention, fil
|
|
|
3623
3811
|
namingConvention
|
|
3624
3812
|
}));
|
|
3625
3813
|
} catch (error) {
|
|
3626
|
-
throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${error}`);
|
|
3814
|
+
throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${String(error)}`);
|
|
3627
3815
|
}
|
|
3628
3816
|
}
|
|
3629
3817
|
async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles }) {
|
|
@@ -3658,14 +3846,14 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
3658
3846
|
try {
|
|
3659
3847
|
const currentExports = [...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`).toSorted((a, b) => a.localeCompare(b));
|
|
3660
3848
|
const existingExports = (await fs$1.readFile(schemaFilePath, "utf8")).match(/export\s+\*\s+from\s+['"][^'"]+['"]/g)?.map((statement) => {
|
|
3661
|
-
const match =
|
|
3662
|
-
if (!match) return
|
|
3849
|
+
const match = /export\s+\*\s+from\s+['"]([^'"]+)['"]/.exec(statement);
|
|
3850
|
+
if (!match) return;
|
|
3663
3851
|
return `export * from '${match[1]}';`;
|
|
3664
|
-
}).filter(
|
|
3852
|
+
}).filter(Boolean) ?? [];
|
|
3665
3853
|
const fileContent = `${header}\n${[...new Set([...existingExports, ...currentExports])].toSorted((a, b) => a.localeCompare(b)).join("\n")}`;
|
|
3666
3854
|
await fs$1.writeFile(schemaFilePath, fileContent, { encoding: "utf8" });
|
|
3667
3855
|
} catch (error) {
|
|
3668
|
-
throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${error}`);
|
|
3856
|
+
throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${String(error)}`);
|
|
3669
3857
|
}
|
|
3670
3858
|
}
|
|
3671
3859
|
}
|
|
@@ -3674,10 +3862,20 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
3674
3862
|
//#region src/writers/generate-imports-for-builder.ts
|
|
3675
3863
|
function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
3676
3864
|
const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
|
|
3677
|
-
if (
|
|
3678
|
-
|
|
3865
|
+
if (output.indexFiles) return isZodSchemaOutput ? [{
|
|
3866
|
+
exports: imports.map((i) => ({
|
|
3867
|
+
...i,
|
|
3868
|
+
values: true
|
|
3869
|
+
})),
|
|
3870
|
+
dependency: joinSafe(relativeSchemasPath, "index.zod")
|
|
3871
|
+
}] : [{
|
|
3872
|
+
exports: imports,
|
|
3873
|
+
dependency: relativeSchemasPath
|
|
3874
|
+
}];
|
|
3875
|
+
else return uniqueBy(imports, (x) => x.name).map((i) => {
|
|
3876
|
+
const name = conventionName(i.schemaName ?? i.name, output.namingConvention);
|
|
3679
3877
|
const suffix = isZodSchemaOutput ? ".zod" : "";
|
|
3680
|
-
const importExtension = output.fileExtension
|
|
3878
|
+
const importExtension = output.fileExtension.replace(/\.ts$/, "") || "";
|
|
3681
3879
|
return {
|
|
3682
3880
|
exports: isZodSchemaOutput ? [{
|
|
3683
3881
|
...i,
|
|
@@ -3686,46 +3884,52 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
3686
3884
|
dependency: joinSafe(relativeSchemasPath, `${name}${suffix}${importExtension}`)
|
|
3687
3885
|
};
|
|
3688
3886
|
});
|
|
3689
|
-
else if (isZodSchemaOutput) return [{
|
|
3690
|
-
exports: imports.map((i) => ({
|
|
3691
|
-
...i,
|
|
3692
|
-
values: true
|
|
3693
|
-
})),
|
|
3694
|
-
dependency: joinSafe(relativeSchemasPath, "index.zod")
|
|
3695
|
-
}];
|
|
3696
|
-
else return [{
|
|
3697
|
-
exports: imports,
|
|
3698
|
-
dependency: relativeSchemasPath
|
|
3699
|
-
}];
|
|
3700
3887
|
}
|
|
3701
3888
|
|
|
3702
3889
|
//#endregion
|
|
3703
3890
|
//#region src/writers/target.ts
|
|
3704
3891
|
function generateTarget(builder, options) {
|
|
3705
3892
|
const operationNames = Object.values(builder.operations).map(({ operationName }) => operationName);
|
|
3706
|
-
const isAngularClient = options
|
|
3893
|
+
const isAngularClient = options.client === OutputClient.ANGULAR;
|
|
3707
3894
|
const titles = builder.title({
|
|
3708
3895
|
outputClient: options.client,
|
|
3709
3896
|
title: pascal(builder.info.title),
|
|
3710
3897
|
customTitleFunc: options.override.title,
|
|
3711
3898
|
output: options
|
|
3712
3899
|
});
|
|
3713
|
-
const target =
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3900
|
+
const target = {
|
|
3901
|
+
imports: [],
|
|
3902
|
+
implementation: "",
|
|
3903
|
+
implementationMock: {
|
|
3904
|
+
function: "",
|
|
3905
|
+
handler: "",
|
|
3906
|
+
handlerName: ""
|
|
3907
|
+
},
|
|
3908
|
+
importsMock: [],
|
|
3909
|
+
mutators: [],
|
|
3910
|
+
clientMutators: [],
|
|
3911
|
+
formData: [],
|
|
3912
|
+
formUrlEncoded: [],
|
|
3913
|
+
paramsSerializer: [],
|
|
3914
|
+
fetchReviver: []
|
|
3915
|
+
};
|
|
3916
|
+
const operations = Object.values(builder.operations);
|
|
3917
|
+
for (const [index, operation] of operations.entries()) {
|
|
3918
|
+
target.imports.push(...operation.imports);
|
|
3919
|
+
target.importsMock.push(...operation.importsMock);
|
|
3920
|
+
target.implementation += operation.implementation + "\n";
|
|
3921
|
+
target.implementationMock.function += operation.implementationMock.function;
|
|
3922
|
+
target.implementationMock.handler += operation.implementationMock.handler;
|
|
3923
|
+
const handlerNameSeparator = target.implementationMock.handlerName.length > 0 ? ",\n " : " ";
|
|
3924
|
+
target.implementationMock.handlerName += handlerNameSeparator + operation.implementationMock.handlerName + "()";
|
|
3925
|
+
if (operation.mutator) target.mutators.push(operation.mutator);
|
|
3926
|
+
if (operation.formData) target.formData.push(operation.formData);
|
|
3927
|
+
if (operation.formUrlEncoded) target.formUrlEncoded.push(operation.formUrlEncoded);
|
|
3928
|
+
if (operation.paramsSerializer) target.paramsSerializer.push(operation.paramsSerializer);
|
|
3929
|
+
if (operation.clientMutators) target.clientMutators.push(...operation.clientMutators);
|
|
3930
|
+
if (operation.fetchReviver) target.fetchReviver.push(operation.fetchReviver);
|
|
3931
|
+
if (index === operations.length - 1) {
|
|
3932
|
+
const isMutator = target.mutators.some((mutator) => isAngularClient ? mutator.hasThirdArg : mutator.hasSecondArg);
|
|
3729
3933
|
const hasAwaitedType = compareVersions(options.packageJson?.dependencies?.typescript ?? options.packageJson?.devDependencies?.typescript ?? "4.4.0", "4.5.0");
|
|
3730
3934
|
const header = builder.header({
|
|
3731
3935
|
outputClient: options.client,
|
|
@@ -3737,38 +3941,22 @@ function generateTarget(builder, options) {
|
|
|
3737
3941
|
titles,
|
|
3738
3942
|
output: options,
|
|
3739
3943
|
verbOptions: builder.verbOptions,
|
|
3740
|
-
clientImplementation:
|
|
3944
|
+
clientImplementation: target.implementation
|
|
3741
3945
|
});
|
|
3742
|
-
|
|
3743
|
-
|
|
3946
|
+
target.implementation = header.implementation + target.implementation;
|
|
3947
|
+
target.implementationMock.handler = target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName;
|
|
3744
3948
|
const footer = builder.footer({
|
|
3745
|
-
outputClient: options
|
|
3949
|
+
outputClient: options.client,
|
|
3746
3950
|
operationNames,
|
|
3747
|
-
hasMutator:
|
|
3951
|
+
hasMutator: target.mutators.length > 0,
|
|
3748
3952
|
hasAwaitedType,
|
|
3749
3953
|
titles,
|
|
3750
3954
|
output: options
|
|
3751
3955
|
});
|
|
3752
|
-
|
|
3753
|
-
|
|
3956
|
+
target.implementation += footer.implementation;
|
|
3957
|
+
target.implementationMock.handler += footer.implementationMock;
|
|
3754
3958
|
}
|
|
3755
|
-
|
|
3756
|
-
}, {
|
|
3757
|
-
imports: [],
|
|
3758
|
-
implementation: "",
|
|
3759
|
-
implementationMock: {
|
|
3760
|
-
function: "",
|
|
3761
|
-
handler: "",
|
|
3762
|
-
handlerName: ""
|
|
3763
|
-
},
|
|
3764
|
-
importsMock: [],
|
|
3765
|
-
mutators: [],
|
|
3766
|
-
clientMutators: [],
|
|
3767
|
-
formData: [],
|
|
3768
|
-
formUrlEncoded: [],
|
|
3769
|
-
paramsSerializer: [],
|
|
3770
|
-
fetchReviver: []
|
|
3771
|
-
});
|
|
3959
|
+
}
|
|
3772
3960
|
return {
|
|
3773
3961
|
...target,
|
|
3774
3962
|
implementationMock: target.implementationMock.function + target.implementationMock.handler
|
|
@@ -3824,7 +4012,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
3824
4012
|
});
|
|
3825
4013
|
const { imports, importsMock, implementation, implementationMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
|
|
3826
4014
|
let data = header;
|
|
3827
|
-
const schemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(
|
|
4015
|
+
const schemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
|
|
3828
4016
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
3829
4017
|
const importsForBuilder = schemasPath ? generateImportsForBuilder(output, imports.filter((imp) => !importsMock.some((impMock) => imp.name === impMock.name)), schemasPath) : [];
|
|
3830
4018
|
data += builder.imports({
|
|
@@ -3893,7 +4081,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
3893
4081
|
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
|
|
3894
4082
|
let implementationData = header;
|
|
3895
4083
|
let mockData = header;
|
|
3896
|
-
const relativeSchemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(
|
|
4084
|
+
const relativeSchemasPath = output.schemas ? relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
|
|
3897
4085
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
3898
4086
|
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
3899
4087
|
implementationData += builder.imports({
|
|
@@ -3953,7 +4141,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
3953
4141
|
...mockPath ? [mockPath] : []
|
|
3954
4142
|
];
|
|
3955
4143
|
} catch (error) {
|
|
3956
|
-
throw new Error(`Oups... 🍻. An Error occurred while splitting => ${error}`);
|
|
4144
|
+
throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}`);
|
|
3957
4145
|
}
|
|
3958
4146
|
}
|
|
3959
4147
|
|
|
@@ -3967,8 +4155,7 @@ function addDefaultTagIfEmpty(operation) {
|
|
|
3967
4155
|
}
|
|
3968
4156
|
function generateTargetTags(currentAcc, operation) {
|
|
3969
4157
|
const tag = kebab(operation.tags[0]);
|
|
3970
|
-
|
|
3971
|
-
if (!currentOperation) {
|
|
4158
|
+
if (!(tag in currentAcc)) {
|
|
3972
4159
|
currentAcc[tag] = {
|
|
3973
4160
|
imports: operation.imports,
|
|
3974
4161
|
importsMock: operation.importsMock,
|
|
@@ -3987,6 +4174,7 @@ function generateTargetTags(currentAcc, operation) {
|
|
|
3987
4174
|
};
|
|
3988
4175
|
return currentAcc;
|
|
3989
4176
|
}
|
|
4177
|
+
const currentOperation = currentAcc[tag];
|
|
3990
4178
|
currentAcc[tag] = {
|
|
3991
4179
|
implementation: currentOperation.implementation + operation.implementation,
|
|
3992
4180
|
imports: [...currentOperation.imports, ...operation.imports],
|
|
@@ -4007,66 +4195,69 @@ function generateTargetTags(currentAcc, operation) {
|
|
|
4007
4195
|
}
|
|
4008
4196
|
function generateTargetForTags(builder, options) {
|
|
4009
4197
|
const isAngularClient = options.client === OutputClient.ANGULAR;
|
|
4010
|
-
const
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
const
|
|
4016
|
-
const
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4198
|
+
const operations = Object.values(builder.operations).map((operation) => addDefaultTagIfEmpty(operation));
|
|
4199
|
+
let allTargetTags = {};
|
|
4200
|
+
for (const [index, operation] of operations.entries()) {
|
|
4201
|
+
allTargetTags = generateTargetTags(allTargetTags, operation);
|
|
4202
|
+
if (index === operations.length - 1) {
|
|
4203
|
+
const transformed = {};
|
|
4204
|
+
for (const [tag, target] of Object.entries(allTargetTags)) {
|
|
4205
|
+
const isMutator = !!target.mutators?.some((mutator) => isAngularClient ? mutator.hasThirdArg : mutator.hasSecondArg);
|
|
4206
|
+
const operationNames = Object.values(builder.operations).filter(({ tags }) => tags.map((tag$1) => kebab(tag$1)).indexOf(kebab(tag)) === 0).map(({ operationName }) => operationName);
|
|
4207
|
+
const hasAwaitedType = compareVersions(options.packageJson?.dependencies?.typescript ?? options.packageJson?.devDependencies?.typescript ?? "4.4.0", "4.5.0");
|
|
4208
|
+
const titles = builder.title({
|
|
4209
|
+
outputClient: options.client,
|
|
4210
|
+
title: pascal(tag),
|
|
4211
|
+
customTitleFunc: options.override.title,
|
|
4212
|
+
output: options
|
|
4213
|
+
});
|
|
4214
|
+
const footer = builder.footer({
|
|
4215
|
+
outputClient: options.client,
|
|
4216
|
+
operationNames,
|
|
4217
|
+
hasMutator: !!target.mutators?.length,
|
|
4218
|
+
hasAwaitedType,
|
|
4219
|
+
titles,
|
|
4220
|
+
output: options
|
|
4221
|
+
});
|
|
4222
|
+
const header = builder.header({
|
|
4223
|
+
outputClient: options.client,
|
|
4224
|
+
isRequestOptions: options.override.requestOptions !== false,
|
|
4225
|
+
isMutator,
|
|
4226
|
+
isGlobalMutator: !!options.override.mutator,
|
|
4227
|
+
provideIn: options.override.angular.provideIn,
|
|
4228
|
+
hasAwaitedType,
|
|
4229
|
+
titles,
|
|
4230
|
+
output: options,
|
|
4231
|
+
verbOptions: builder.verbOptions,
|
|
4232
|
+
tag,
|
|
4233
|
+
clientImplementation: target.implementation
|
|
4234
|
+
});
|
|
4235
|
+
transformed[tag] = {
|
|
4236
|
+
implementation: header.implementation + target.implementation + footer.implementation,
|
|
4237
|
+
implementationMock: {
|
|
4238
|
+
function: target.implementationMock.function,
|
|
4239
|
+
handler: target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName + footer.implementationMock,
|
|
4240
|
+
handlerName: target.implementationMock.handlerName
|
|
4241
|
+
},
|
|
4242
|
+
imports: target.imports,
|
|
4243
|
+
importsMock: target.importsMock,
|
|
4244
|
+
mutators: target.mutators,
|
|
4245
|
+
clientMutators: target.clientMutators,
|
|
4246
|
+
formData: target.formData,
|
|
4247
|
+
formUrlEncoded: target.formUrlEncoded,
|
|
4248
|
+
paramsSerializer: target.paramsSerializer,
|
|
4249
|
+
fetchReviver: target.fetchReviver
|
|
4250
|
+
};
|
|
4251
|
+
}
|
|
4252
|
+
allTargetTags = transformed;
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
const result = {};
|
|
4256
|
+
for (const [tag, target] of Object.entries(allTargetTags)) result[tag] = {
|
|
4257
|
+
...target,
|
|
4258
|
+
implementationMock: target.implementationMock.function + target.implementationMock.handler
|
|
4259
|
+
};
|
|
4260
|
+
return result;
|
|
4070
4261
|
}
|
|
4071
4262
|
|
|
4072
4263
|
//#endregion
|
|
@@ -4078,14 +4269,15 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4078
4269
|
});
|
|
4079
4270
|
const target = generateTargetForTags(builder, output);
|
|
4080
4271
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4081
|
-
const
|
|
4272
|
+
const mockOption = output.mock && !isFunction(output.mock) ? output.mock : void 0;
|
|
4273
|
+
const indexFilePath = mockOption?.indexMockFiles ? join(dirname$1, "index." + getMockFileExtensionByTypeName(mockOption) + extension) : void 0;
|
|
4082
4274
|
if (indexFilePath) await fs$1.outputFile(indexFilePath, "");
|
|
4083
4275
|
return (await Promise.all(Object.entries(target).map(async ([tag, target$1]) => {
|
|
4084
4276
|
try {
|
|
4085
4277
|
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer } = target$1;
|
|
4086
4278
|
let implementationData = header;
|
|
4087
4279
|
let mockData = header;
|
|
4088
|
-
const relativeSchemasPath = output.schemas ? "../" + relativeSafe(dirname$1, getFileInfo(
|
|
4280
|
+
const relativeSchemasPath = output.schemas ? "../" + relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas";
|
|
4089
4281
|
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
4090
4282
|
implementationData += builder.imports({
|
|
4091
4283
|
client: output.client,
|
|
@@ -4155,9 +4347,9 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4155
4347
|
const mockPath = output.mock ? join(dirname$1, tag, tag + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
|
|
4156
4348
|
if (mockPath) {
|
|
4157
4349
|
await fs$1.outputFile(mockPath, mockData);
|
|
4158
|
-
if (indexFilePath) {
|
|
4159
|
-
const localMockPath = joinSafe("./", tag, tag + "." + getMockFileExtensionByTypeName(
|
|
4160
|
-
fs$1.appendFile(indexFilePath, `export { get${pascal(tag)}Mock } from '${localMockPath}'\n`);
|
|
4350
|
+
if (indexFilePath && mockOption) {
|
|
4351
|
+
const localMockPath = joinSafe("./", tag, tag + "." + getMockFileExtensionByTypeName(mockOption));
|
|
4352
|
+
await fs$1.appendFile(indexFilePath, `export { get${pascal(tag)}Mock } from '${localMockPath}'\n`);
|
|
4161
4353
|
}
|
|
4162
4354
|
}
|
|
4163
4355
|
return [
|
|
@@ -4166,7 +4358,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4166
4358
|
...mockPath ? [mockPath] : []
|
|
4167
4359
|
];
|
|
4168
4360
|
} catch (error) {
|
|
4169
|
-
throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${error}`);
|
|
4361
|
+
throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}`);
|
|
4170
4362
|
}
|
|
4171
4363
|
}))).flat();
|
|
4172
4364
|
}
|
|
@@ -4184,7 +4376,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
|
|
|
4184
4376
|
try {
|
|
4185
4377
|
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer } = target$1;
|
|
4186
4378
|
let data = header;
|
|
4187
|
-
const schemasPathRelative = output.schemas ? relativeSafe(dirname$1, getFileInfo(
|
|
4379
|
+
const schemasPathRelative = output.schemas ? relativeSafe(dirname$1, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
|
|
4188
4380
|
const importsForBuilder = generateImportsForBuilder(output, imports.filter((imp) => !importsMock.some((impMock) => imp.name === impMock.name)), schemasPathRelative);
|
|
4189
4381
|
data += builder.imports({
|
|
4190
4382
|
client: output.client,
|
|
@@ -4242,11 +4434,11 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
|
|
|
4242
4434
|
await fs$1.outputFile(implementationPath, data);
|
|
4243
4435
|
return [implementationPath, ...schemasPath ? [schemasPath] : []];
|
|
4244
4436
|
} catch (error) {
|
|
4245
|
-
throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${error}`);
|
|
4437
|
+
throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${String(error)}`);
|
|
4246
4438
|
}
|
|
4247
4439
|
}))).flat();
|
|
4248
4440
|
}
|
|
4249
4441
|
|
|
4250
4442
|
//#endregion
|
|
4251
|
-
export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule,
|
|
4443
|
+
export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, filterByContentType, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getRequestBodyContentTypes, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveObject, resolveRef, resolveValue, sanitize, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
4252
4444
|
//# sourceMappingURL=index.mjs.map
|