@orval/core 8.10.0 → 8.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +185 -46
- package/dist/index.mjs +612 -202
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
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
|
+
import { entries, groupBy, isArray, isBoolean, isBoolean as isBoolean$1, isEmptyish, isFunction, isFunction as isFunction$1, isNullish, isNullish as isNullish$1, isNumber, isString, isString as isString$1, prop, unique, uniqueBy, uniqueWith } from "remeda";
|
|
4
4
|
import { keyword } from "esutils";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { compare } from "compare-versions";
|
|
@@ -8,7 +8,7 @@ import debug from "debug";
|
|
|
8
8
|
import { pathToFileURL } from "node:url";
|
|
9
9
|
import { createJiti } from "jiti";
|
|
10
10
|
import fs, { existsSync, readFileSync } from "node:fs";
|
|
11
|
-
import {
|
|
11
|
+
import { glob } from "tinyglobby";
|
|
12
12
|
import readline from "node:readline";
|
|
13
13
|
import { styleText } from "node:util";
|
|
14
14
|
import { isDereferenced } from "@scalar/openapi-types/helpers";
|
|
@@ -63,7 +63,10 @@ const OutputMode = {
|
|
|
63
63
|
TAGS: "tags",
|
|
64
64
|
TAGS_SPLIT: "tags-split"
|
|
65
65
|
};
|
|
66
|
-
const OutputMockType = {
|
|
66
|
+
const OutputMockType = {
|
|
67
|
+
MSW: "msw",
|
|
68
|
+
FAKER: "faker"
|
|
69
|
+
};
|
|
67
70
|
const FormDataArrayHandling = {
|
|
68
71
|
SERIALIZE: "serialize",
|
|
69
72
|
EXPLODE: "explode",
|
|
@@ -77,6 +80,10 @@ const Verbs = {
|
|
|
77
80
|
DELETE: "delete",
|
|
78
81
|
HEAD: "head"
|
|
79
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* Canonical tag name used for the generated bucket that collects untagged operations.
|
|
85
|
+
*/
|
|
86
|
+
const DefaultTag = "default";
|
|
80
87
|
const GetterPropType = {
|
|
81
88
|
PARAM: "param",
|
|
82
89
|
NAMED_PATH_PARAMS: "namedPathParams",
|
|
@@ -173,6 +180,20 @@ function isUrl(str) {
|
|
|
173
180
|
return false;
|
|
174
181
|
}
|
|
175
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Type guard for the MSW mock generator. Use to narrow a
|
|
185
|
+
* `GlobalMockOptions | ClientMockBuilder` value to `MswMockOptions`.
|
|
186
|
+
*/
|
|
187
|
+
function isMswMock(mock) {
|
|
188
|
+
return !isFunction$1(mock) && mock.type === OutputMockType.MSW;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Type guard for the Faker mock generator. Use to narrow a
|
|
192
|
+
* `GlobalMockOptions | ClientMockBuilder` value to `FakerMockOptions`.
|
|
193
|
+
*/
|
|
194
|
+
function isFakerMock(mock) {
|
|
195
|
+
return !isFunction$1(mock) && mock.type === OutputMockType.FAKER;
|
|
196
|
+
}
|
|
176
197
|
//#endregion
|
|
177
198
|
//#region src/utils/async-reduce.ts
|
|
178
199
|
async function asyncReduce(array, reducer, initValue) {
|
|
@@ -361,7 +382,30 @@ function createDebugger(ns, options = {}) {
|
|
|
361
382
|
//#region src/utils/doc.ts
|
|
362
383
|
const search = String.raw`\*/`;
|
|
363
384
|
const replacement = String.raw`*\/`;
|
|
364
|
-
const regex
|
|
385
|
+
const regex = new RegExp(search, "g");
|
|
386
|
+
const itemValidationKeys = [
|
|
387
|
+
"minLength",
|
|
388
|
+
"maxLength",
|
|
389
|
+
"minimum",
|
|
390
|
+
"maximum",
|
|
391
|
+
"exclusiveMinimum",
|
|
392
|
+
"exclusiveMaximum",
|
|
393
|
+
"minItems",
|
|
394
|
+
"maxItems",
|
|
395
|
+
"pattern"
|
|
396
|
+
];
|
|
397
|
+
function getItemValidationDocEntries(schema, prefix = "items", visited = /* @__PURE__ */ new WeakSet()) {
|
|
398
|
+
if (!schema) return [];
|
|
399
|
+
if (visited.has(schema)) return [];
|
|
400
|
+
visited.add(schema);
|
|
401
|
+
return [...itemValidationKeys.flatMap((key) => {
|
|
402
|
+
const value = schema[key];
|
|
403
|
+
return value === void 0 ? [] : [{
|
|
404
|
+
key: `${prefix}.${key}`,
|
|
405
|
+
value
|
|
406
|
+
}];
|
|
407
|
+
}), ...getItemValidationDocEntries(schema.items, `${prefix}.items`, visited)];
|
|
408
|
+
}
|
|
365
409
|
function jsDoc(schema, tryOneLine = false, context) {
|
|
366
410
|
if (context?.output.override.jsDoc) {
|
|
367
411
|
const { filter } = context.output.override.jsDoc;
|
|
@@ -369,7 +413,8 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
369
413
|
}
|
|
370
414
|
const { description, deprecated, summary, minLength, maxLength, minimum, maximum, exclusiveMinimum, exclusiveMaximum, minItems, maxItems, pattern } = schema;
|
|
371
415
|
const isNullable = schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null");
|
|
372
|
-
const
|
|
416
|
+
const itemValidationDocEntries = getItemValidationDocEntries(schema.items);
|
|
417
|
+
const lines = (Array.isArray(description) ? description.filter((d) => !d.includes("eslint-disable")) : [description ?? ""]).flatMap((line) => line.split(/\r?\n/)).map((line) => line.replaceAll(regex, replacement));
|
|
373
418
|
const count = [
|
|
374
419
|
description,
|
|
375
420
|
deprecated,
|
|
@@ -383,11 +428,12 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
383
428
|
minItems?.toString(),
|
|
384
429
|
maxItems?.toString(),
|
|
385
430
|
isNullable ? "null" : "",
|
|
386
|
-
pattern
|
|
431
|
+
pattern,
|
|
432
|
+
...itemValidationDocEntries.map(({ value }) => value.toString())
|
|
387
433
|
].filter(Boolean).length;
|
|
388
434
|
if (!count) return "";
|
|
389
435
|
const oneLine = count === 1 && tryOneLine;
|
|
390
|
-
const eslintDisable = Array.isArray(description) ? description.find((d) => d.includes("eslint-disable"))?.replaceAll(regex
|
|
436
|
+
const eslintDisable = Array.isArray(description) ? description.find((d) => d.includes("eslint-disable"))?.replaceAll(regex, replacement) : void 0;
|
|
391
437
|
let doc = `${eslintDisable ? `/* ${eslintDisable} */\n` : ""}/**`;
|
|
392
438
|
if (description) {
|
|
393
439
|
if (!oneLine) doc += `\n${tryOneLine ? " " : ""} *`;
|
|
@@ -399,7 +445,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
399
445
|
function tryAppendStringDocLine(key, value) {
|
|
400
446
|
if (value) {
|
|
401
447
|
appendPrefix();
|
|
402
|
-
doc += ` @${key} ${value.replaceAll(regex
|
|
448
|
+
doc += ` @${key} ${value.replaceAll(regex, replacement)}`;
|
|
403
449
|
}
|
|
404
450
|
}
|
|
405
451
|
function tryAppendBooleanDocLine(key, value) {
|
|
@@ -415,7 +461,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
415
461
|
}
|
|
416
462
|
}
|
|
417
463
|
tryAppendBooleanDocLine("deprecated", deprecated);
|
|
418
|
-
tryAppendStringDocLine("summary", summary?.replaceAll(regex
|
|
464
|
+
tryAppendStringDocLine("summary", summary?.replaceAll(regex, replacement));
|
|
419
465
|
tryAppendNumberDocLine("minLength", minLength);
|
|
420
466
|
tryAppendNumberDocLine("maxLength", maxLength);
|
|
421
467
|
tryAppendNumberDocLine("minimum", minimum);
|
|
@@ -426,6 +472,17 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
426
472
|
tryAppendNumberDocLine("maxItems", maxItems);
|
|
427
473
|
tryAppendBooleanDocLine("nullable", isNullable);
|
|
428
474
|
tryAppendStringDocLine("pattern", pattern);
|
|
475
|
+
for (const { key, value } of itemValidationDocEntries) {
|
|
476
|
+
if (typeof value === "string") {
|
|
477
|
+
tryAppendStringDocLine(key, value);
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
if (typeof value === "number") {
|
|
481
|
+
tryAppendNumberDocLine(key, value);
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
tryAppendBooleanDocLine(key, value);
|
|
485
|
+
}
|
|
429
486
|
doc += oneLine ? " " : `\n ${tryOneLine ? " " : ""}`;
|
|
430
487
|
doc += "*/\n";
|
|
431
488
|
return doc;
|
|
@@ -487,12 +544,12 @@ function getFileInfo(target = "", { backupFilename = "filename", extension = ".t
|
|
|
487
544
|
};
|
|
488
545
|
}
|
|
489
546
|
async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
490
|
-
const files = await
|
|
547
|
+
const files = await glob(patterns, {
|
|
491
548
|
cwd: dir,
|
|
492
549
|
absolute: true
|
|
493
550
|
});
|
|
494
551
|
await Promise.all(files.map((file) => fs.promises.unlink(file)));
|
|
495
|
-
const sortedDirectories = (await
|
|
552
|
+
const sortedDirectories = (await glob(["**/*"], {
|
|
496
553
|
cwd: dir,
|
|
497
554
|
absolute: true,
|
|
498
555
|
onlyDirectories: true
|
|
@@ -506,11 +563,17 @@ async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
|
506
563
|
}
|
|
507
564
|
//#endregion
|
|
508
565
|
//#region src/utils/file-extensions.ts
|
|
566
|
+
/**
|
|
567
|
+
* Returns the filename suffix for a given mock entry's output file. For
|
|
568
|
+
* example a `{ type: OutputMockType.MSW }` entry produces `<file>.msw.ts` and
|
|
569
|
+
* a `{ type: OutputMockType.FAKER }` entry produces `<file>.faker.ts`.
|
|
570
|
+
*
|
|
571
|
+
* Custom `ClientMockBuilder` functions default to the `msw` suffix to preserve
|
|
572
|
+
* the historical behavior.
|
|
573
|
+
*/
|
|
509
574
|
function getMockFileExtensionByTypeName(mock) {
|
|
510
|
-
if (isFunction(mock)) return
|
|
511
|
-
|
|
512
|
-
default: return "msw";
|
|
513
|
-
}
|
|
575
|
+
if (isFunction(mock)) return OutputMockType.MSW;
|
|
576
|
+
return mock.type;
|
|
514
577
|
}
|
|
515
578
|
//#endregion
|
|
516
579
|
//#region src/utils/get-property-safe.ts
|
|
@@ -1001,6 +1064,24 @@ function isSyntheticDefaultImportsAllow(config) {
|
|
|
1001
1064
|
if (!config) return true;
|
|
1002
1065
|
return !!(config.compilerOptions?.allowSyntheticDefaultImports ?? config.compilerOptions?.esModuleInterop);
|
|
1003
1066
|
}
|
|
1067
|
+
const NODE_NEXT_MODULES = new Set(["nodenext", "node16"]);
|
|
1068
|
+
const NODE_NEXT_EXTENSION_MAP = [
|
|
1069
|
+
[".tsx", ".jsx"],
|
|
1070
|
+
[".mts", ".mjs"],
|
|
1071
|
+
[".cts", ".cjs"],
|
|
1072
|
+
[".ts", ".js"]
|
|
1073
|
+
];
|
|
1074
|
+
function getImportExtension(fileExtension, tsconfig) {
|
|
1075
|
+
const compilerOptions = tsconfig?.compilerOptions;
|
|
1076
|
+
if (compilerOptions?.allowImportingTsExtensions) return fileExtension;
|
|
1077
|
+
const module = compilerOptions?.module?.toLowerCase();
|
|
1078
|
+
const moduleResolution = compilerOptions?.moduleResolution?.toLowerCase();
|
|
1079
|
+
if (module && NODE_NEXT_MODULES.has(module) || moduleResolution && NODE_NEXT_MODULES.has(moduleResolution)) {
|
|
1080
|
+
for (const [from, to] of NODE_NEXT_EXTENSION_MAP) if (fileExtension.endsWith(from)) return `${fileExtension.slice(0, -from.length)}${to}`;
|
|
1081
|
+
return fileExtension;
|
|
1082
|
+
}
|
|
1083
|
+
return fileExtension.replace(/\.ts$/, "") || "";
|
|
1084
|
+
}
|
|
1004
1085
|
//#endregion
|
|
1005
1086
|
//#region src/getters/enum.ts
|
|
1006
1087
|
/**
|
|
@@ -1210,13 +1291,36 @@ function getCombinedEnumValue(inputs) {
|
|
|
1210
1291
|
}
|
|
1211
1292
|
//#endregion
|
|
1212
1293
|
//#region src/getters/ref.ts
|
|
1294
|
+
/**
|
|
1295
|
+
* `$ref`s targeting these sections under `#/components/...` are emitted as
|
|
1296
|
+
* named TypeScript imports (e.g. `import type { Pet } from './model'`).
|
|
1297
|
+
* Refs to any other location — for example `#/paths/.../schema` produced by
|
|
1298
|
+
* JSON-Schema-Ref-Parser `bundle()` — have no corresponding `export type`
|
|
1299
|
+
* and must be inlined by the resolver. See issue #398.
|
|
1300
|
+
*/
|
|
1301
|
+
const NAMED_COMPONENT_SECTIONS = [
|
|
1302
|
+
"schemas",
|
|
1303
|
+
"responses",
|
|
1304
|
+
"parameters",
|
|
1305
|
+
"requestBodies"
|
|
1306
|
+
];
|
|
1213
1307
|
const RefComponentSuffix = {
|
|
1214
1308
|
schemas: "",
|
|
1215
1309
|
responses: "Response",
|
|
1216
1310
|
parameters: "Parameter",
|
|
1217
1311
|
requestBodies: "Body"
|
|
1218
1312
|
};
|
|
1219
|
-
const
|
|
1313
|
+
const COMPONENT_REF_PATTERN = new RegExp(String.raw`^#\/components\/(${NAMED_COMPONENT_SECTIONS.join("|")})\/[^/]+$`);
|
|
1314
|
+
/**
|
|
1315
|
+
* True iff `ref` targets a named slot eligible for emission as a TypeScript
|
|
1316
|
+
* import. Used by `resolveValue` to decide between named import vs inlining
|
|
1317
|
+
* the resolved schema.
|
|
1318
|
+
*/
|
|
1319
|
+
function isComponentRef(ref) {
|
|
1320
|
+
return COMPONENT_REF_PATTERN.test(ref);
|
|
1321
|
+
}
|
|
1322
|
+
const TILDE_1 = /~1/g;
|
|
1323
|
+
const TILDE_0 = /~0/g;
|
|
1220
1324
|
/**
|
|
1221
1325
|
* Return the output type from the $ref
|
|
1222
1326
|
*
|
|
@@ -1224,7 +1328,7 @@ const regex = /* @__PURE__ */ new RegExp("~1", "g");
|
|
|
1224
1328
|
*/
|
|
1225
1329
|
function getRefInfo($ref, context) {
|
|
1226
1330
|
const [pathname, ref] = $ref.split("#");
|
|
1227
|
-
const refPaths = ref.slice(1).split("/").map((part) => decodeURIComponent(part.replaceAll(
|
|
1331
|
+
const refPaths = ref.slice(1).split("/").map((part) => decodeURIComponent(part).replaceAll(TILDE_1, "/").replaceAll(TILDE_0, "~"));
|
|
1228
1332
|
const getOverrideSuffix = (override, paths) => {
|
|
1229
1333
|
const firstLevel = override[paths[0]];
|
|
1230
1334
|
if (!firstLevel) return "";
|
|
@@ -1358,7 +1462,34 @@ function resolveExampleRefs(examples, context) {
|
|
|
1358
1462
|
//#region src/resolvers/value.ts
|
|
1359
1463
|
function resolveValue({ schema, name, context, formDataContext }) {
|
|
1360
1464
|
if (isReference(schema)) {
|
|
1465
|
+
const refValue = schema.$ref;
|
|
1361
1466
|
const { schema: schemaObject, imports } = resolveRef(schema, context);
|
|
1467
|
+
if (refValue && !isComponentRef(refValue)) {
|
|
1468
|
+
if (context.parents?.includes(refValue)) return {
|
|
1469
|
+
value: "unknown",
|
|
1470
|
+
imports: [],
|
|
1471
|
+
schemas: [],
|
|
1472
|
+
type: "unknown",
|
|
1473
|
+
isEnum: false,
|
|
1474
|
+
originalSchema: schemaObject,
|
|
1475
|
+
hasReadonlyProps: false,
|
|
1476
|
+
isRef: false,
|
|
1477
|
+
dependencies: []
|
|
1478
|
+
};
|
|
1479
|
+
return {
|
|
1480
|
+
...getScalar({
|
|
1481
|
+
item: schemaObject,
|
|
1482
|
+
name,
|
|
1483
|
+
context: {
|
|
1484
|
+
...context,
|
|
1485
|
+
parents: [...context.parents ?? [], refValue]
|
|
1486
|
+
},
|
|
1487
|
+
formDataContext
|
|
1488
|
+
}),
|
|
1489
|
+
originalSchema: schemaObject,
|
|
1490
|
+
isRef: false
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1362
1493
|
const resolvedImport = imports[0];
|
|
1363
1494
|
let hasReadonlyProps = false;
|
|
1364
1495
|
const refName = resolvedImport.name;
|
|
@@ -1568,7 +1699,7 @@ function getArray({ schema, name, context, formDataContext }) {
|
|
|
1568
1699
|
}
|
|
1569
1700
|
//#endregion
|
|
1570
1701
|
//#region src/getters/res-req-types.ts
|
|
1571
|
-
const getSchemaType = (s) => s.type;
|
|
1702
|
+
const getSchemaType$1 = (s) => s.type;
|
|
1572
1703
|
const getSchemaCombined = (s) => s.oneOf ?? s.anyOf ?? s.allOf;
|
|
1573
1704
|
const getSchemaOneOf = (s) => s.oneOf;
|
|
1574
1705
|
const getSchemaAnyOf = (s) => s.anyOf;
|
|
@@ -1581,9 +1712,14 @@ const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
|
1581
1712
|
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
1582
1713
|
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
1583
1714
|
if (!mediaType.schema) return;
|
|
1715
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1584
1716
|
const formDataContext = isFormData ? {
|
|
1585
1717
|
atPart: false,
|
|
1586
1718
|
encoding: mediaType.encoding ?? {}
|
|
1719
|
+
} : isFormUrlEncoded ? {
|
|
1720
|
+
atPart: false,
|
|
1721
|
+
encoding: mediaType.encoding ?? {},
|
|
1722
|
+
urlEncoded: true
|
|
1587
1723
|
} : void 0;
|
|
1588
1724
|
const resolvedObject = resolveObject({
|
|
1589
1725
|
schema: mediaType.schema,
|
|
@@ -1849,25 +1985,37 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
|
|
|
1849
1985
|
form += `Object.entries(${propName} ?? {}).forEach(([key, value]) => {\n`;
|
|
1850
1986
|
form += skipLine;
|
|
1851
1987
|
form += ` if (value !== undefined && value !== null) {\n`;
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1988
|
+
if (isUrlEncoded) {
|
|
1989
|
+
form += ` if (Array.isArray(value)) {\n`;
|
|
1990
|
+
form += ` value.forEach(v => {\n`;
|
|
1991
|
+
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
1992
|
+
form += ` });\n`;
|
|
1993
|
+
form += ` } else if (typeof value === 'object') {\n`;
|
|
1994
|
+
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
1995
|
+
form += ` } else {\n`;
|
|
1996
|
+
form += ` ${variableName}.append(key, String(value));\n`;
|
|
1997
|
+
form += ` }\n`;
|
|
1998
|
+
} else {
|
|
1999
|
+
form += ` if ((typeof File !== 'undefined' && value instanceof File) || value instanceof Blob) {\n`;
|
|
2000
|
+
form += ` ${variableName}.append(key, value);\n`;
|
|
2001
|
+
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n`;
|
|
2002
|
+
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(value)]));\n`;
|
|
2003
|
+
form += ` } else if (Array.isArray(value)) {\n`;
|
|
2004
|
+
form += ` value.forEach(v => {\n`;
|
|
2005
|
+
form += ` if ((typeof File !== 'undefined' && v instanceof File) || v instanceof Blob) {\n`;
|
|
2006
|
+
form += ` ${variableName}.append(key, v);\n`;
|
|
2007
|
+
form += ` } else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(v)) {\n`;
|
|
2008
|
+
form += ` ${variableName}.append(key, new Blob([Uint8Array.from(v)]));\n`;
|
|
2009
|
+
form += ` } else {\n`;
|
|
2010
|
+
form += ` ${variableName}.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v));\n`;
|
|
2011
|
+
form += ` }\n`;
|
|
2012
|
+
form += ` });\n`;
|
|
2013
|
+
form += ` } else if (typeof value === 'object') {\n`;
|
|
2014
|
+
form += ` ${variableName}.append(key, JSON.stringify(value));\n`;
|
|
2015
|
+
form += ` } else {\n`;
|
|
2016
|
+
form += ` ${variableName}.append(key, String(value));\n`;
|
|
2017
|
+
form += ` }\n`;
|
|
2018
|
+
}
|
|
1871
2019
|
form += ` }\n`;
|
|
1872
2020
|
form += `});\n`;
|
|
1873
2021
|
} else {
|
|
@@ -1912,6 +2060,7 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
|
|
|
1912
2060
|
}
|
|
1913
2061
|
function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
|
|
1914
2062
|
let formDataValues = "";
|
|
2063
|
+
const isUrlEncoded = variableName === "formUrlEncoded";
|
|
1915
2064
|
const schemaProps = getSchemaProperties(schema) ?? {};
|
|
1916
2065
|
for (const [key, value] of Object.entries(schemaProps)) {
|
|
1917
2066
|
const { schema: property } = resolveSchemaRef(value, context);
|
|
@@ -1924,7 +2073,8 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
1924
2073
|
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
1925
2074
|
const fileType = getFormDataFieldFileType(property, partContentType);
|
|
1926
2075
|
const effectiveContentType = partContentType ?? property.contentMediaType;
|
|
1927
|
-
if (
|
|
2076
|
+
if (isUrlEncoded && (fileType || property.format === "binary")) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
2077
|
+
else if (fileType === "binary" || property.format === "binary") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
1928
2078
|
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
1929
2079
|
else if (property.type === "object") formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
1930
2080
|
schema: property,
|
|
@@ -1957,7 +2107,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
1957
2107
|
${resolvedValue}});\n`;
|
|
1958
2108
|
} else valueStr = "JSON.stringify(value)";
|
|
1959
2109
|
else {
|
|
1960
|
-
const itemType = getSchemaType(itemSchema);
|
|
2110
|
+
const itemType = getSchemaType$1(itemSchema);
|
|
1961
2111
|
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()";
|
|
1962
2112
|
}
|
|
1963
2113
|
}
|
|
@@ -1965,7 +2115,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
1965
2115
|
if (!hasNonPrimitiveChild) formDataValue = `${valueKey}.forEach((value, index${depth > 0 ? depth : ""}) => ${variableName}.append(\`${keyPrefix}${key}[\${index${depth > 0 ? depth : ""}}]\`, ${valueStr}));\n`;
|
|
1966
2116
|
} else formDataValue = `${valueKey}.forEach(value => ${variableName}.append(\`${keyPrefix}${key}${context.output.override.formData.arrayHandling === FormDataArrayHandling.SERIALIZE_WITH_BRACKETS ? "[]" : ""}\`, ${valueStr}));\n`;
|
|
1967
2117
|
} else if ((() => {
|
|
1968
|
-
const propType = getSchemaType(property);
|
|
2118
|
+
const propType = getSchemaType$1(property);
|
|
1969
2119
|
return propType === "number" || Array.isArray(propType) && propType.includes("number") || propType === "integer" || Array.isArray(propType) && propType.includes("integer") || propType === "boolean" || Array.isArray(propType) && propType.includes("boolean");
|
|
1970
2120
|
})()) formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey}.toString())\n`;
|
|
1971
2121
|
else formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey});\n`;
|
|
@@ -1989,7 +2139,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
1989
2139
|
})) existSubSchemaNullable = true;
|
|
1990
2140
|
}
|
|
1991
2141
|
const isRequired = getSchemaRequired(schema)?.includes(key) && !isRequestBodyOptional;
|
|
1992
|
-
const propType = getSchemaType(property);
|
|
2142
|
+
const propType = getSchemaType$1(property);
|
|
1993
2143
|
if (property.nullable || Array.isArray(propType) && propType.includes("null") || existSubSchemaNullable) {
|
|
1994
2144
|
if (isRequired) {
|
|
1995
2145
|
formDataValues += `if(${valueKey} !== null) {\n ${formDataValue} }\n`;
|
|
@@ -2241,7 +2391,8 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2241
2391
|
if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
|
|
2242
2392
|
const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
|
|
2243
2393
|
atPart: true,
|
|
2244
|
-
partContentType: formDataContext.encoding[key]?.contentType
|
|
2394
|
+
partContentType: formDataContext.encoding[key]?.contentType,
|
|
2395
|
+
urlEncoded: formDataContext.urlEncoded
|
|
2245
2396
|
} : void 0;
|
|
2246
2397
|
const resolvedValue = resolveObject({
|
|
2247
2398
|
schema,
|
|
@@ -2253,7 +2404,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2253
2404
|
if (!index) acc.value += "{";
|
|
2254
2405
|
const doc = jsDoc(schema, true, context);
|
|
2255
2406
|
const propertyDoc = doc ? `${doc.trimEnd().split("\n").map((line) => ` ${line}`).join("\n")}\n` : "";
|
|
2256
|
-
if (isReadOnly) acc.hasReadonlyProps = true;
|
|
2407
|
+
if (isReadOnly || resolvedValue.hasReadonlyProps) acc.hasReadonlyProps = true;
|
|
2257
2408
|
const constValue = "const" in schema ? schema.const : void 0;
|
|
2258
2409
|
const hasConst = constValue !== void 0;
|
|
2259
2410
|
let constLiteral;
|
|
@@ -2518,11 +2669,13 @@ function getScalar({ item, name, context, formDataContext }) {
|
|
|
2518
2669
|
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2519
2670
|
isEnum = true;
|
|
2520
2671
|
}
|
|
2521
|
-
if (
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2672
|
+
if (!formDataContext?.urlEncoded) {
|
|
2673
|
+
if (schemaFormat === "binary") value = "Blob";
|
|
2674
|
+
else if (formDataContext?.atPart) {
|
|
2675
|
+
const fileType = getFormDataFieldFileType(item, formDataContext.partContentType);
|
|
2676
|
+
if (fileType) value = fileType === "binary" ? "Blob" : "Blob | string";
|
|
2677
|
+
} else if (schemaContentMediaType === "application/octet-stream" && !schemaContentEncoding) value = "Blob";
|
|
2678
|
+
}
|
|
2526
2679
|
if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
|
|
2527
2680
|
value += nullable;
|
|
2528
2681
|
if (schemaConst) value = `'${schemaConst}'`;
|
|
@@ -2863,10 +3016,13 @@ function getParameters({ parameters, context }) {
|
|
|
2863
3016
|
const { schema, imports } = resolveRef(p, context);
|
|
2864
3017
|
const parameter = schema;
|
|
2865
3018
|
const location = parameter.in;
|
|
2866
|
-
if (location === "path" || location === "query" || location === "header")
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
3019
|
+
if (location === "path" || location === "query" || location === "header") {
|
|
3020
|
+
const safeImports = p.$ref && isComponentRef(p.$ref) ? imports : [];
|
|
3021
|
+
result[location].push({
|
|
3022
|
+
parameter,
|
|
3023
|
+
imports: safeImports
|
|
3024
|
+
});
|
|
3025
|
+
}
|
|
2870
3026
|
} else if (p.in === "query" || p.in === "path" || p.in === "header") result[p.in].push({
|
|
2871
3027
|
parameter: p,
|
|
2872
3028
|
imports: []
|
|
@@ -2999,6 +3155,50 @@ const isOpenApiSchemaObject = (value) => {
|
|
|
2999
3155
|
if (!value || typeof value !== "object") return false;
|
|
3000
3156
|
return !("$ref" in value);
|
|
3001
3157
|
};
|
|
3158
|
+
/**
|
|
3159
|
+
* A `$ref` schema object (e.g. array `items` or a oneOf/anyOf/allOf variant
|
|
3160
|
+
* pointing at a component). We don't resolve the reference here, but a query
|
|
3161
|
+
* parameter behind a `$ref` is virtually always a complex (object-like) type,
|
|
3162
|
+
* so it must be treated as non-primitive. Over-flagging is harmless: the only
|
|
3163
|
+
* consumer (the Angular `nonPrimitiveKeys` passthrough) is gated on a
|
|
3164
|
+
* configured `paramsSerializer`, which is precisely what handles raw values.
|
|
3165
|
+
*/
|
|
3166
|
+
const isRefObject = (value) => !!value && typeof value === "object" && "$ref" in value;
|
|
3167
|
+
const getSchemaType = (schema) => {
|
|
3168
|
+
const type = schema.type;
|
|
3169
|
+
if (typeof type === "string") return type;
|
|
3170
|
+
if (Array.isArray(type) && type.every((variant) => typeof variant === "string")) return type;
|
|
3171
|
+
};
|
|
3172
|
+
/**
|
|
3173
|
+
* Detects whether a query parameter's resolved schema is non-primitive — i.e.
|
|
3174
|
+
* an object, an array of objects, or a composition (oneOf/anyOf/allOf) that
|
|
3175
|
+
* resolves to a non-primitive shape.
|
|
3176
|
+
*
|
|
3177
|
+
* Used by Angular generators so the default `filterParams` helper preserves
|
|
3178
|
+
* such values instead of silently dropping them. Angular's `HttpParams` only
|
|
3179
|
+
* accepts primitives, but a user-provided `paramsSerializer`, `mutator`, or
|
|
3180
|
+
* `paramsFilter` may need the raw object to flatten or stringify it.
|
|
3181
|
+
*/
|
|
3182
|
+
const isSchemaNonPrimitive = (schema) => {
|
|
3183
|
+
const schemaType = getSchemaType(schema);
|
|
3184
|
+
const type = Array.isArray(schemaType) ? schemaType.filter((variant) => variant !== "null") : schemaType;
|
|
3185
|
+
const additionalProperties = schema.additionalProperties;
|
|
3186
|
+
if (type === "object") return true;
|
|
3187
|
+
if (Array.isArray(type) && type.includes("object")) return true;
|
|
3188
|
+
if (type === "array" || Array.isArray(type) && type.includes("array")) {
|
|
3189
|
+
const items = schema.items;
|
|
3190
|
+
if (isOpenApiSchemaObject(items)) return isSchemaNonPrimitive(items);
|
|
3191
|
+
return true;
|
|
3192
|
+
}
|
|
3193
|
+
const compositions = [
|
|
3194
|
+
...Array.isArray(schema.oneOf) ? schema.oneOf : [],
|
|
3195
|
+
...Array.isArray(schema.anyOf) ? schema.anyOf : [],
|
|
3196
|
+
...Array.isArray(schema.allOf) ? schema.allOf : []
|
|
3197
|
+
];
|
|
3198
|
+
if (compositions.length > 0) return compositions.some((variant) => isOpenApiSchemaObject(variant) ? isSchemaNonPrimitive(variant) : isRefObject(variant));
|
|
3199
|
+
if (!type && (schema.properties !== void 0 || additionalProperties !== void 0 && additionalProperties !== false)) return true;
|
|
3200
|
+
return false;
|
|
3201
|
+
};
|
|
3002
3202
|
const isSchemaNullable = (schema) => {
|
|
3003
3203
|
if (schema.nullable === true) return true;
|
|
3004
3204
|
if (schema.type === "null") return true;
|
|
@@ -3076,6 +3276,7 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
|
|
|
3076
3276
|
const type = types.map(({ definition }) => definition).join("\n");
|
|
3077
3277
|
const allOptional = queryParams.every(({ parameter }) => !parameter.required);
|
|
3078
3278
|
const requiredNullableKeys = types.filter(({ required, originalSchema }) => required && isSchemaNullable(originalSchema)).map(({ name }) => name);
|
|
3279
|
+
const nonPrimitiveKeys = types.filter(({ originalSchema }) => isSchemaNonPrimitive(originalSchema)).map(({ name }) => name);
|
|
3079
3280
|
return {
|
|
3080
3281
|
schema: {
|
|
3081
3282
|
name,
|
|
@@ -3084,7 +3285,8 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
|
|
|
3084
3285
|
},
|
|
3085
3286
|
deps: schemas,
|
|
3086
3287
|
isOptional: allOptional,
|
|
3087
|
-
requiredNullableKeys
|
|
3288
|
+
requiredNullableKeys,
|
|
3289
|
+
...nonPrimitiveKeys.length > 0 ? { nonPrimitiveKeys } : {}
|
|
3088
3290
|
};
|
|
3089
3291
|
}
|
|
3090
3292
|
//#endregion
|
|
@@ -3109,7 +3311,7 @@ function getResponse({ responses, operationName, context, contentType }) {
|
|
|
3109
3311
|
success: success || (defaultType ?? "unknown"),
|
|
3110
3312
|
errors: errors || (defaultType ?? "unknown")
|
|
3111
3313
|
},
|
|
3112
|
-
isBlob: groupedByStatus.success.some((t) => !!t.contentType && isBinaryContentType(t.contentType) || t.
|
|
3314
|
+
isBlob: groupedByStatus.success.some((t) => !!t.contentType && isBinaryContentType(t.contentType) || t.originalSchema?.format === "binary" || t.originalSchema?.contentMediaType === "application/octet-stream" && !t.originalSchema.contentEncoding),
|
|
3113
3315
|
types: groupedByStatus,
|
|
3114
3316
|
contentTypes,
|
|
3115
3317
|
schemas,
|
|
@@ -3202,6 +3404,8 @@ function getBaseUrlRuntimeImports(baseUrl) {
|
|
|
3202
3404
|
values: imp.values ?? true
|
|
3203
3405
|
}));
|
|
3204
3406
|
}
|
|
3407
|
+
const wrapRouteParameters = (route, prepend, append) => route.replaceAll(TEMPLATE_TAG_REGEX, `\${${prepend}$1${append}}`);
|
|
3408
|
+
const makeRouteSafe = (route) => wrapRouteParameters(route, "encodeURIComponent(String(", "))");
|
|
3205
3409
|
function getRouteAsArray(route) {
|
|
3206
3410
|
return route.split("/").filter((i) => i !== "").flatMap((segment) => {
|
|
3207
3411
|
if (!segment.includes("${")) return [`'${segment}'`];
|
|
@@ -3240,11 +3444,11 @@ function generateComponentDefinition(responses = {}, context, suffix) {
|
|
|
3240
3444
|
}
|
|
3241
3445
|
//#endregion
|
|
3242
3446
|
//#region src/generators/imports.ts
|
|
3243
|
-
function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CASE }) {
|
|
3447
|
+
function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CASE, importExtension = "" }) {
|
|
3244
3448
|
if (imports.length === 0) return "";
|
|
3245
3449
|
const grouped = groupBy(uniqueWith(imports, (a, b) => a.name === b.name && a.default === b.default && a.alias === b.alias && a.values === b.values && a.isConstant === b.isConstant && a.namespaceImport === b.namespaceImport && a.syntheticDefaultImport === b.syntheticDefaultImport && a.importPath === b.importPath).map((imp) => ({
|
|
3246
3450
|
...imp,
|
|
3247
|
-
importPath: imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`
|
|
3451
|
+
importPath: imp.importPath ?? `./${conventionName(imp.name, namingConvention)}${importExtension}`
|
|
3248
3452
|
})), (imp) => !imp.default && !imp.namespaceImport && !imp.syntheticDefaultImport && !imp.values && !imp.isConstant ? `aggregate|${imp.importPath}` : `single|${imp.importPath}|${imp.name}|${imp.alias ?? ""}|${String(imp.default)}|${String(imp.namespaceImport)}|${String(imp.syntheticDefaultImport)}|${String(imp.values)}|${String(imp.isConstant)}`);
|
|
3249
3453
|
return Object.entries(grouped).toSorted(([a], [b]) => a.localeCompare(b, "en", { numeric: true })).map(([, group]) => {
|
|
3250
3454
|
const sample = group[0];
|
|
@@ -3256,7 +3460,8 @@ function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CA
|
|
|
3256
3460
|
function generateMutatorImports({ mutators, implementation, oneMore }) {
|
|
3257
3461
|
let imports = "";
|
|
3258
3462
|
for (const mutator of uniqueWith(mutators, (a, b) => a.name === b.name && a.default === b.default)) {
|
|
3259
|
-
const
|
|
3463
|
+
const isRelativeImport = mutator.path.startsWith(".");
|
|
3464
|
+
const path = `${oneMore && isRelativeImport ? "../" : ""}${mutator.path}`;
|
|
3260
3465
|
const importDefault = mutator.default ? mutator.name : `{ ${mutator.name} }`;
|
|
3261
3466
|
imports += `import ${importDefault} from '${path}';`;
|
|
3262
3467
|
imports += "\n";
|
|
@@ -3451,7 +3656,7 @@ function generateModelsInline(obj) {
|
|
|
3451
3656
|
//#region src/generators/mutator-info.ts
|
|
3452
3657
|
async function getMutatorInfo(filePath, options) {
|
|
3453
3658
|
const { root = process.cwd(), namedExport = "default", alias, external, tsconfig } = options ?? {};
|
|
3454
|
-
return parseFile(await bundleFile(root, filePath, alias, external, tsconfig?.compilerOptions), namedExport
|
|
3659
|
+
return parseFile(await bundleFile(root, filePath, alias, external, tsconfig?.compilerOptions), namedExport);
|
|
3455
3660
|
}
|
|
3456
3661
|
async function bundleFile(root, fileName, alias, external, compilerOptions) {
|
|
3457
3662
|
const { text } = (await build({
|
|
@@ -3474,10 +3679,10 @@ async function bundleFile(root, fileName, alias, external, compilerOptions) {
|
|
|
3474
3679
|
})).outputFiles[0];
|
|
3475
3680
|
return text;
|
|
3476
3681
|
}
|
|
3477
|
-
function parseFile(file, name
|
|
3682
|
+
function parseFile(file, name) {
|
|
3478
3683
|
try {
|
|
3479
3684
|
const ast = Parser.parse(file, {
|
|
3480
|
-
ecmaVersion,
|
|
3685
|
+
ecmaVersion: "latest",
|
|
3481
3686
|
sourceType: "module"
|
|
3482
3687
|
});
|
|
3483
3688
|
const foundSpecifier = ast.body.filter((x) => x.type === "ExportNamedDeclaration").flatMap((x) => x.specifiers).find((x) => x.exported.type === "Identifier" && x.exported.name === name && x.local.type === "Identifier");
|
|
@@ -3534,15 +3739,6 @@ function parseFunction(ast, funcName) {
|
|
|
3534
3739
|
}
|
|
3535
3740
|
}
|
|
3536
3741
|
}
|
|
3537
|
-
function getEcmaVersion(target) {
|
|
3538
|
-
if (!target) return;
|
|
3539
|
-
if (target.toLowerCase() === "esnext") return "latest";
|
|
3540
|
-
try {
|
|
3541
|
-
return Number(target.toLowerCase().replace("es", ""));
|
|
3542
|
-
} catch {
|
|
3543
|
-
return;
|
|
3544
|
-
}
|
|
3545
|
-
}
|
|
3546
3742
|
//#endregion
|
|
3547
3743
|
//#region src/generators/mutator.ts
|
|
3548
3744
|
const BODY_TYPE_NAME = "BodyType";
|
|
@@ -3603,16 +3799,24 @@ function removeComments(file) {
|
|
|
3603
3799
|
* (e.g. observe-mode branches), prefer getAngularFilteredParamsCallExpression +
|
|
3604
3800
|
* getAngularFilteredParamsHelperBody instead.
|
|
3605
3801
|
*/
|
|
3606
|
-
const getAngularFilteredParamsExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false) => {
|
|
3607
|
-
const
|
|
3802
|
+
const getAngularFilteredParamsExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false, nonPrimitiveKeys = []) => {
|
|
3803
|
+
const hasPassthrough = nonPrimitiveKeys.length > 0;
|
|
3804
|
+
const filteredParamValueType = hasPassthrough ? "unknown" : `string | number | boolean${preserveRequiredNullables ? " | null" : ""} | Array<string | number | boolean>`;
|
|
3805
|
+
const passthroughBranch = hasPassthrough ? ` if (passthroughKeys.has(key)) {
|
|
3806
|
+
if (value !== undefined) {
|
|
3807
|
+
filteredParams[key] = value;
|
|
3808
|
+
}
|
|
3809
|
+
continue;
|
|
3810
|
+
}
|
|
3811
|
+
` : "";
|
|
3608
3812
|
const preserveNullableBranch = preserveRequiredNullables ? ` } else if (value === null && requiredNullableParamKeys.has(key)) {
|
|
3609
3813
|
filteredParams[key] = null;
|
|
3610
3814
|
` : "";
|
|
3611
3815
|
return `(() => {
|
|
3612
|
-
const requiredNullableParamKeys = new Set<string>(${JSON.stringify(requiredNullableParamKeys)});
|
|
3816
|
+
${hasPassthrough ? ` const passthroughKeys = new Set<string>(${JSON.stringify(nonPrimitiveKeys)});\n` : ""} const requiredNullableParamKeys = new Set<string>(${JSON.stringify(requiredNullableParamKeys)});
|
|
3613
3817
|
const filteredParams: Record<string, ${filteredParamValueType}> = {};
|
|
3614
3818
|
for (const [key, value] of Object.entries(${paramsExpression})) {
|
|
3615
|
-
if (Array.isArray(value)) {
|
|
3819
|
+
${passthroughBranch} if (Array.isArray(value)) {
|
|
3616
3820
|
const filtered = value.filter(
|
|
3617
3821
|
(item) =>
|
|
3618
3822
|
item != null &&
|
|
@@ -3647,19 +3851,34 @@ function filterParams(
|
|
|
3647
3851
|
params: Record<string, unknown>,
|
|
3648
3852
|
requiredNullableKeys?: ReadonlySet<string>,
|
|
3649
3853
|
preserveRequiredNullables?: false,
|
|
3854
|
+
passthroughKeys?: undefined,
|
|
3650
3855
|
): Record<string, AngularHttpParamValue>;
|
|
3651
3856
|
function filterParams(
|
|
3652
3857
|
params: Record<string, unknown>,
|
|
3653
3858
|
requiredNullableKeys: ReadonlySet<string> | undefined,
|
|
3654
3859
|
preserveRequiredNullables: true,
|
|
3860
|
+
passthroughKeys?: undefined,
|
|
3655
3861
|
): Record<string, AngularHttpParamValueWithNullable>;
|
|
3862
|
+
function filterParams(
|
|
3863
|
+
params: Record<string, unknown>,
|
|
3864
|
+
requiredNullableKeys: ReadonlySet<string> | undefined,
|
|
3865
|
+
preserveRequiredNullables: boolean | undefined,
|
|
3866
|
+
passthroughKeys: ReadonlySet<string>,
|
|
3867
|
+
): Record<string, unknown>;
|
|
3656
3868
|
function filterParams(
|
|
3657
3869
|
params: Record<string, unknown>,
|
|
3658
3870
|
requiredNullableKeys: ReadonlySet<string> = new Set(),
|
|
3659
3871
|
preserveRequiredNullables = false,
|
|
3660
|
-
|
|
3661
|
-
|
|
3872
|
+
passthroughKeys: ReadonlySet<string> = new Set(),
|
|
3873
|
+
): Record<string, unknown> {
|
|
3874
|
+
const filteredParams: Record<string, unknown> = {};
|
|
3662
3875
|
for (const [key, value] of Object.entries(params)) {
|
|
3876
|
+
if (passthroughKeys.has(key)) {
|
|
3877
|
+
if (value !== undefined) {
|
|
3878
|
+
filteredParams[key] = value;
|
|
3879
|
+
}
|
|
3880
|
+
continue;
|
|
3881
|
+
}
|
|
3663
3882
|
if (Array.isArray(value)) {
|
|
3664
3883
|
const filtered = value.filter(
|
|
3665
3884
|
(item) =>
|
|
@@ -3691,14 +3910,34 @@ function filterParams(
|
|
|
3691
3910
|
/**
|
|
3692
3911
|
* Returns a call expression to the `filterParams` helper function.
|
|
3693
3912
|
*/
|
|
3694
|
-
const getAngularFilteredParamsCallExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false
|
|
3913
|
+
const getAngularFilteredParamsCallExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false, nonPrimitiveKeys = []) => {
|
|
3914
|
+
const baseArgs = `${paramsExpression}, new Set<string>(${JSON.stringify(requiredNullableParamKeys)})`;
|
|
3915
|
+
if (nonPrimitiveKeys.length > 0) return `filterParams(${baseArgs}, ${preserveRequiredNullables}, new Set<string>(${JSON.stringify(nonPrimitiveKeys)}))`;
|
|
3916
|
+
return `filterParams(${baseArgs}${preserveRequiredNullables ? ", true" : ""})`;
|
|
3917
|
+
};
|
|
3918
|
+
/**
|
|
3919
|
+
* Returns the filter call/IIFE used to massage query params before passing
|
|
3920
|
+
* them to Angular's HttpParams. When the user supplied a `paramsFilter`
|
|
3921
|
+
* mutator, the built-in `filterParams` is bypassed entirely and the user's
|
|
3922
|
+
* function is called with the raw params — they own nullish-stripping and
|
|
3923
|
+
* any object/array handling. Otherwise the built-in filter is used (either
|
|
3924
|
+
* the shared helper or an inline IIFE), and callers should only pass
|
|
3925
|
+
* `nonPrimitiveKeys` when a downstream serializer or custom consumer can
|
|
3926
|
+
* legally handle raw object/array values.
|
|
3927
|
+
*/
|
|
3928
|
+
const buildAngularParamsFilterExpression = ({ paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false, nonPrimitiveKeys = [], paramsFilter, useSharedHelper }) => {
|
|
3929
|
+
if (paramsFilter) return `${paramsFilter.name}(${paramsExpression})`;
|
|
3930
|
+
if (useSharedHelper) return getAngularFilteredParamsCallExpression(paramsExpression, requiredNullableParamKeys, preserveRequiredNullables, nonPrimitiveKeys);
|
|
3931
|
+
return getAngularFilteredParamsExpression(paramsExpression, requiredNullableParamKeys, preserveRequiredNullables, nonPrimitiveKeys);
|
|
3932
|
+
};
|
|
3695
3933
|
function generateBodyOptions(body, isFormData, isFormUrlEncoded) {
|
|
3696
3934
|
if (isFormData && body.formData) return "formData";
|
|
3697
3935
|
if (isFormUrlEncoded && body.formUrlEncoded) return "formUrlEncoded";
|
|
3698
3936
|
if (body.implementation) return body.implementation;
|
|
3699
3937
|
}
|
|
3700
|
-
function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularObserve, angularParamsRef, requiredNullableQueryParamKeys, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isVue, isAngular, paramsSerializer, paramsSerializerOptions }) {
|
|
3938
|
+
function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularObserve, angularParamsRef, requiredNullableQueryParamKeys, nonPrimitiveQueryParamKeys, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isVue, isAngular, paramsSerializer, paramsSerializerOptions, paramsFilter }) {
|
|
3701
3939
|
const isRequestOptions = requestOptions !== false;
|
|
3940
|
+
const angularPassthroughQueryParamKeys = paramsSerializer ? nonPrimitiveQueryParamKeys : [];
|
|
3702
3941
|
const signalVar = hasSignalParam ? "querySignal" : "signal";
|
|
3703
3942
|
const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
|
|
3704
3943
|
if (!queryParams && !headers && !response.isBlob && response.definition.success !== "string") {
|
|
@@ -3712,7 +3951,14 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
3712
3951
|
let value = "";
|
|
3713
3952
|
if (!isRequestOptions) {
|
|
3714
3953
|
if (queryParams) if (isAngular) {
|
|
3715
|
-
const iifeExpr =
|
|
3954
|
+
const iifeExpr = buildAngularParamsFilterExpression({
|
|
3955
|
+
paramsExpression: "params ?? {}",
|
|
3956
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
3957
|
+
preserveRequiredNullables: !!paramsSerializer,
|
|
3958
|
+
nonPrimitiveKeys: angularPassthroughQueryParamKeys,
|
|
3959
|
+
paramsFilter,
|
|
3960
|
+
useSharedHelper: false
|
|
3961
|
+
});
|
|
3716
3962
|
value += paramsSerializer ? `\n params: ${paramsSerializer.name}(${iifeExpr}),` : `\n params: ${iifeExpr},`;
|
|
3717
3963
|
} else value += "\n params,";
|
|
3718
3964
|
if (headers) value += "\n headers,";
|
|
@@ -3729,10 +3975,25 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
3729
3975
|
if (queryParams) if (isVue) value += "\n params: {...unref(params), ...options?.params},";
|
|
3730
3976
|
else if (isAngular && angularParamsRef) value += `\n params: ${angularParamsRef},`;
|
|
3731
3977
|
else if (isAngular && paramsSerializer) {
|
|
3732
|
-
const callExpr =
|
|
3978
|
+
const callExpr = buildAngularParamsFilterExpression({
|
|
3979
|
+
paramsExpression: "{...params, ...options?.params}",
|
|
3980
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
3981
|
+
preserveRequiredNullables: true,
|
|
3982
|
+
nonPrimitiveKeys: angularPassthroughQueryParamKeys,
|
|
3983
|
+
paramsFilter,
|
|
3984
|
+
useSharedHelper: true
|
|
3985
|
+
});
|
|
3733
3986
|
value += `\n params: ${paramsSerializer.name}(${callExpr}),`;
|
|
3734
|
-
} else if (isAngular)
|
|
3735
|
-
|
|
3987
|
+
} else if (isAngular) {
|
|
3988
|
+
const callExpr = buildAngularParamsFilterExpression({
|
|
3989
|
+
paramsExpression: "{...params, ...options?.params}",
|
|
3990
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
3991
|
+
nonPrimitiveKeys: angularPassthroughQueryParamKeys,
|
|
3992
|
+
paramsFilter,
|
|
3993
|
+
useSharedHelper: true
|
|
3994
|
+
});
|
|
3995
|
+
value += `\n params: ${callExpr},`;
|
|
3996
|
+
} else value += "\n params: {...params, ...options?.params},";
|
|
3736
3997
|
if (headers) value += "\n headers: {...headers, ...options?.headers},";
|
|
3737
3998
|
}
|
|
3738
3999
|
if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) {
|
|
@@ -3741,13 +4002,14 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
3741
4002
|
}
|
|
3742
4003
|
return value;
|
|
3743
4004
|
}
|
|
3744
|
-
function generateOptions({ route, body, angularObserve, angularParamsRef, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions }) {
|
|
4005
|
+
function generateOptions({ route, body, angularObserve, angularParamsRef, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions, paramsFilter }) {
|
|
3745
4006
|
const bodyIdentifier = getIsBodyVerb(verb) ? generateBodyOptions(body, isFormData, isFormUrlEncoded) : void 0;
|
|
3746
4007
|
const axiosOptions = generateAxiosOptions({
|
|
3747
4008
|
response,
|
|
3748
4009
|
angularObserve,
|
|
3749
4010
|
angularParamsRef,
|
|
3750
4011
|
requiredNullableQueryParamKeys: queryParams?.requiredNullableKeys,
|
|
4012
|
+
nonPrimitiveQueryParamKeys: queryParams?.nonPrimitiveKeys,
|
|
3751
4013
|
queryParams: queryParams?.schema,
|
|
3752
4014
|
headers: headers?.schema,
|
|
3753
4015
|
requestOptions,
|
|
@@ -3757,7 +4019,8 @@ function generateOptions({ route, body, angularObserve, angularParamsRef, header
|
|
|
3757
4019
|
isVue: isVue ?? false,
|
|
3758
4020
|
isAngular: isAngular ?? false,
|
|
3759
4021
|
paramsSerializer,
|
|
3760
|
-
paramsSerializerOptions
|
|
4022
|
+
paramsSerializerOptions,
|
|
4023
|
+
paramsFilter
|
|
3761
4024
|
});
|
|
3762
4025
|
const trimmedAxiosOptions = axiosOptions.trim();
|
|
3763
4026
|
const isRawOptionsArgument = trimmedAxiosOptions === "options" || trimmedAxiosOptions.startsWith("(") && trimmedAxiosOptions.endsWith(")") || trimmedAxiosOptions.startsWith("{") && trimmedAxiosOptions.endsWith("}");
|
|
@@ -3776,18 +4039,26 @@ function generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) {
|
|
|
3776
4039
|
if (body.implementation) return `,\n data: ${body.implementation}`;
|
|
3777
4040
|
return "";
|
|
3778
4041
|
}
|
|
3779
|
-
function generateQueryParamsAxiosConfig(response, isVue, isAngular, requiredNullableQueryParamKeys, queryParams) {
|
|
4042
|
+
function generateQueryParamsAxiosConfig(response, isVue, isAngular, requiredNullableQueryParamKeys, queryParams, paramsFilter) {
|
|
3780
4043
|
if (!queryParams && !response.isBlob) return "";
|
|
3781
4044
|
let value = "";
|
|
3782
4045
|
if (queryParams) if (isVue) value += ",\n params: unref(params)";
|
|
3783
|
-
else if (isAngular)
|
|
3784
|
-
|
|
4046
|
+
else if (isAngular) {
|
|
4047
|
+
const paramsExpr = buildAngularParamsFilterExpression({
|
|
4048
|
+
paramsExpression: "params ?? {}",
|
|
4049
|
+
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
4050
|
+
nonPrimitiveKeys: queryParams.nonPrimitiveKeys,
|
|
4051
|
+
paramsFilter,
|
|
4052
|
+
useSharedHelper: false
|
|
4053
|
+
});
|
|
4054
|
+
value += `,\n params: ${paramsExpr}`;
|
|
4055
|
+
} else value += ",\n params";
|
|
3785
4056
|
if (response.isBlob) value += `,\n responseType: 'blob'`;
|
|
3786
4057
|
return value;
|
|
3787
4058
|
}
|
|
3788
|
-
function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue, isAngular }) {
|
|
4059
|
+
function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue, isAngular, paramsFilter }) {
|
|
3789
4060
|
const bodyOptions = getIsBodyVerb(verb) ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) : "";
|
|
3790
|
-
const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, isAngular ?? false, queryParams?.requiredNullableKeys, queryParams);
|
|
4061
|
+
const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, isAngular ?? false, queryParams?.requiredNullableKeys, queryParams, paramsFilter);
|
|
3791
4062
|
const ignoreContentTypes = isAngular ? ["multipart/form-data"] : [];
|
|
3792
4063
|
const headerOptions = body.contentType && !ignoreContentTypes.includes(body.contentType) ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
|
|
3793
4064
|
const signalVar = hasSignalParam ? "querySignal" : "signal";
|
|
@@ -4100,6 +4371,13 @@ async function buildVerbOption({ verb, output, operation, route, pathRoute, verb
|
|
|
4100
4371
|
workspace: context.workspace,
|
|
4101
4372
|
tsconfig: context.output.tsconfig
|
|
4102
4373
|
}) : void 0,
|
|
4374
|
+
paramsFilter: isString(override.paramsFilter) || isObject(override.paramsFilter) ? await generateMutator({
|
|
4375
|
+
output: output.target,
|
|
4376
|
+
name: "paramsFilter",
|
|
4377
|
+
mutator: override.paramsFilter,
|
|
4378
|
+
workspace: context.workspace,
|
|
4379
|
+
tsconfig: context.output.tsconfig
|
|
4380
|
+
}) : void 0,
|
|
4103
4381
|
fetchReviver: isString(override.fetch.jsonReviver) || isObject(override.fetch.jsonReviver) ? await generateMutator({
|
|
4104
4382
|
output: output.target,
|
|
4105
4383
|
name: "fetchReviver",
|
|
@@ -4264,19 +4542,12 @@ function splitSchemasByType(schemas) {
|
|
|
4264
4542
|
};
|
|
4265
4543
|
}
|
|
4266
4544
|
/**
|
|
4267
|
-
* Get the import extension from a file extension.
|
|
4268
|
-
* Removes `.ts` suffix since TypeScript doesn't need it in imports.
|
|
4269
|
-
*/
|
|
4270
|
-
function getImportExtension(fileExtension) {
|
|
4271
|
-
return fileExtension.replace(/\.ts$/, "") || "";
|
|
4272
|
-
}
|
|
4273
|
-
/**
|
|
4274
4545
|
* Fix cross-directory imports when schemas reference other schemas in a different directory.
|
|
4275
4546
|
* Updates import paths to use correct relative paths between directories.
|
|
4276
4547
|
*/
|
|
4277
|
-
function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention, fileExtension) {
|
|
4548
|
+
function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingConvention, fileExtension, tsconfig) {
|
|
4278
4549
|
const relativePath = relativeSafe(fromPath, toPath);
|
|
4279
|
-
const importExtension = getImportExtension(fileExtension);
|
|
4550
|
+
const importExtension = getImportExtension(fileExtension, tsconfig);
|
|
4280
4551
|
for (const schema of schemas) schema.imports = schema.imports.map((imp) => {
|
|
4281
4552
|
if (targetSchemaNames.has(imp.name)) {
|
|
4282
4553
|
const fileName = conventionName(imp.name, namingConvention);
|
|
@@ -4291,14 +4562,14 @@ function fixSchemaImports(schemas, targetSchemaNames, fromPath, toPath, namingCo
|
|
|
4291
4562
|
/**
|
|
4292
4563
|
* Fix imports in operation schemas that reference regular schemas.
|
|
4293
4564
|
*/
|
|
4294
|
-
function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
|
|
4295
|
-
fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention, fileExtension);
|
|
4565
|
+
function fixCrossDirectoryImports(operationSchemas, regularSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension, tsconfig) {
|
|
4566
|
+
fixSchemaImports(operationSchemas, regularSchemaNames, operationSchemaPath, schemaPath, namingConvention, fileExtension, tsconfig);
|
|
4296
4567
|
}
|
|
4297
4568
|
/**
|
|
4298
4569
|
* Fix imports in regular schemas that reference operation schemas.
|
|
4299
4570
|
*/
|
|
4300
|
-
function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension) {
|
|
4301
|
-
fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension);
|
|
4571
|
+
function fixRegularSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension, tsconfig) {
|
|
4572
|
+
fixSchemaImports(regularSchemas, operationSchemaNames, schemaPath, operationSchemaPath, namingConvention, fileExtension, tsconfig);
|
|
4302
4573
|
}
|
|
4303
4574
|
function getSchemaKey(schemaPath, schemaName, namingConvention, fileExtension) {
|
|
4304
4575
|
return getPath(schemaPath, conventionName(schemaName, namingConvention), fileExtension).toLowerCase().replaceAll("\\", "/");
|
|
@@ -4322,14 +4593,16 @@ function getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtensi
|
|
|
4322
4593
|
canonicalNameMap
|
|
4323
4594
|
};
|
|
4324
4595
|
}
|
|
4325
|
-
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension) {
|
|
4596
|
+
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig) {
|
|
4597
|
+
const importExtension = getImportExtension(fileExtension, tsconfig);
|
|
4326
4598
|
for (const schema of schemas) schema.imports = schema.imports.map((imp) => {
|
|
4327
4599
|
const canonicalByName = canonicalNameMap.get(imp.name);
|
|
4328
4600
|
const resolvedImportKey = resolveImportKey(schemaPath, imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`, fileExtension);
|
|
4329
4601
|
const canonicalByPath = canonicalPathMap.get(resolvedImportKey);
|
|
4330
4602
|
const canonical = canonicalByName ?? canonicalByPath;
|
|
4331
4603
|
if (!canonical?.importPath) return imp;
|
|
4332
|
-
const
|
|
4604
|
+
const relative = relativeSafe(schemaPath, canonical.importPath.replaceAll("\\", "/"));
|
|
4605
|
+
const importPath = `${relative.endsWith(fileExtension) ? relative.slice(0, -fileExtension.length) : relative.replace(/\.ts$/, "")}${importExtension}`;
|
|
4333
4606
|
return {
|
|
4334
4607
|
...imp,
|
|
4335
4608
|
importPath
|
|
@@ -4352,14 +4625,12 @@ function mergeSchemaGroup(schemas) {
|
|
|
4352
4625
|
function resolveImportKey(schemaPath, importPath, fileExtension) {
|
|
4353
4626
|
return join(schemaPath, `${importPath}${fileExtension}`).toLowerCase().replaceAll("\\", "/");
|
|
4354
4627
|
}
|
|
4355
|
-
function
|
|
4356
|
-
return path.endsWith(".ts") ? path.slice(0, -3) : path;
|
|
4357
|
-
}
|
|
4358
|
-
function getSchema({ schema: { imports, model }, header, namingConvention = NamingConvention.CAMEL_CASE }) {
|
|
4628
|
+
function getSchema({ schema: { imports, model }, header, namingConvention = NamingConvention.CAMEL_CASE, importExtension }) {
|
|
4359
4629
|
let file = header;
|
|
4360
4630
|
file += generateImports({
|
|
4361
4631
|
imports: imports.filter((imp) => !model.includes(`type ${imp.alias ?? imp.name} =`) && !model.includes(`interface ${imp.alias ?? imp.name} {`)),
|
|
4362
|
-
namingConvention
|
|
4632
|
+
namingConvention,
|
|
4633
|
+
importExtension
|
|
4363
4634
|
});
|
|
4364
4635
|
file += imports.length > 0 ? "\n\n" : "\n";
|
|
4365
4636
|
file += model;
|
|
@@ -4376,23 +4647,24 @@ function writeModelsInline(array) {
|
|
|
4376
4647
|
for (const { model } of array) acc = writeModelInline(acc, model);
|
|
4377
4648
|
return acc;
|
|
4378
4649
|
}
|
|
4379
|
-
async function writeSchema({ path, schema, target, namingConvention, fileExtension, header }) {
|
|
4650
|
+
async function writeSchema({ path, schema, target, namingConvention, fileExtension, header, tsconfig }) {
|
|
4380
4651
|
const name = conventionName(schema.name, namingConvention);
|
|
4381
4652
|
try {
|
|
4382
4653
|
await writeGeneratedFile(getPath(path, name, fileExtension), getSchema({
|
|
4383
4654
|
schema,
|
|
4384
4655
|
target,
|
|
4385
4656
|
header,
|
|
4386
|
-
namingConvention
|
|
4657
|
+
namingConvention,
|
|
4658
|
+
importExtension: getImportExtension(fileExtension, tsconfig)
|
|
4387
4659
|
}));
|
|
4388
4660
|
} catch (error) {
|
|
4389
4661
|
throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${String(error)}`, { cause: error });
|
|
4390
4662
|
}
|
|
4391
4663
|
}
|
|
4392
|
-
async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles }) {
|
|
4664
|
+
async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles, tsconfig }) {
|
|
4393
4665
|
const schemaGroups = getSchemaGroups(schemaPath, schemas, namingConvention, fileExtension);
|
|
4394
4666
|
const { canonicalPathMap, canonicalNameMap } = getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtension);
|
|
4395
|
-
normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension);
|
|
4667
|
+
normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension, tsconfig);
|
|
4396
4668
|
for (const groupSchemas of Object.values(schemaGroups)) {
|
|
4397
4669
|
if (groupSchemas.length === 1) {
|
|
4398
4670
|
await writeSchema({
|
|
@@ -4401,7 +4673,8 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4401
4673
|
target,
|
|
4402
4674
|
namingConvention,
|
|
4403
4675
|
fileExtension,
|
|
4404
|
-
header
|
|
4676
|
+
header,
|
|
4677
|
+
tsconfig
|
|
4405
4678
|
});
|
|
4406
4679
|
continue;
|
|
4407
4680
|
}
|
|
@@ -4411,13 +4684,14 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4411
4684
|
target,
|
|
4412
4685
|
namingConvention,
|
|
4413
4686
|
fileExtension,
|
|
4414
|
-
header
|
|
4687
|
+
header,
|
|
4688
|
+
tsconfig
|
|
4415
4689
|
});
|
|
4416
4690
|
}
|
|
4417
4691
|
if (indexFiles) {
|
|
4418
4692
|
const schemaFilePath = path.join(schemaPath, `index.ts`);
|
|
4419
4693
|
await fs$1.ensureFile(schemaFilePath);
|
|
4420
|
-
const ext =
|
|
4694
|
+
const ext = getImportExtension(fileExtension, tsconfig);
|
|
4421
4695
|
const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
|
|
4422
4696
|
try {
|
|
4423
4697
|
await writeGeneratedFile(schemaFilePath, `${header}\n${[...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`).toSorted((a, b) => a.localeCompare(b, "en", { numeric: true })).join("\n")}\n`);
|
|
@@ -4441,7 +4715,7 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
4441
4715
|
else {
|
|
4442
4716
|
const importsByDependency = /* @__PURE__ */ new Map();
|
|
4443
4717
|
for (const schemaImport of imports.filter((i) => !i.importPath)) {
|
|
4444
|
-
const dependency = joinSafe(relativeSchemasPath, `${conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention)}${isZodSchemaOutput ? ".zod" : ""}${output.fileExtension.
|
|
4718
|
+
const dependency = joinSafe(relativeSchemasPath, `${conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention)}${isZodSchemaOutput ? ".zod" : ""}${getImportExtension(output.fileExtension, output.tsconfig)}`);
|
|
4445
4719
|
if (!importsByDependency.has(dependency)) importsByDependency.set(dependency, []);
|
|
4446
4720
|
importsByDependency.get(dependency)?.push(schemaImport);
|
|
4447
4721
|
}
|
|
@@ -4459,7 +4733,39 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
4459
4733
|
return [...schemaImports, ...otherImports];
|
|
4460
4734
|
}
|
|
4461
4735
|
//#endregion
|
|
4736
|
+
//#region src/writers/mock-outputs.ts
|
|
4737
|
+
/**
|
|
4738
|
+
* Collapses the per-generator mock outputs for "inline" writer modes
|
|
4739
|
+
* (`single`, `tags`) where every mock generator's content is concatenated
|
|
4740
|
+
* into the implementation file. The MSW generator already emits the
|
|
4741
|
+
* response-factory functions (`get<Op>ResponseMock`) that Faker would emit,
|
|
4742
|
+
* so when both generators are configured we keep MSW and drop Faker to
|
|
4743
|
+
* avoid duplicate function declarations and re-imported faker bindings.
|
|
4744
|
+
*/
|
|
4745
|
+
function collapseInlineMockOutputs(mockOutputs) {
|
|
4746
|
+
if (!mockOutputs.some((m) => m.type === OutputMockType.MSW)) return mockOutputs;
|
|
4747
|
+
return mockOutputs.filter((m) => m.type !== OutputMockType.FAKER);
|
|
4748
|
+
}
|
|
4749
|
+
//#endregion
|
|
4462
4750
|
//#region src/writers/target.ts
|
|
4751
|
+
function emptyMockOutputFull$1(type) {
|
|
4752
|
+
return {
|
|
4753
|
+
type,
|
|
4754
|
+
implementation: {
|
|
4755
|
+
function: "",
|
|
4756
|
+
handler: "",
|
|
4757
|
+
handlerName: ""
|
|
4758
|
+
},
|
|
4759
|
+
imports: []
|
|
4760
|
+
};
|
|
4761
|
+
}
|
|
4762
|
+
function flattenMockOutput$1(full) {
|
|
4763
|
+
return {
|
|
4764
|
+
type: full.type,
|
|
4765
|
+
implementation: full.implementation.function + full.implementation.handler,
|
|
4766
|
+
imports: full.imports
|
|
4767
|
+
};
|
|
4768
|
+
}
|
|
4463
4769
|
function generateTarget(builder, options) {
|
|
4464
4770
|
const operationNames = Object.values(builder.operations).map(({ operationName }) => operationName);
|
|
4465
4771
|
const isAngularClient = options.client === OutputClient.ANGULAR;
|
|
@@ -4472,32 +4778,38 @@ function generateTarget(builder, options) {
|
|
|
4472
4778
|
const target = {
|
|
4473
4779
|
imports: [],
|
|
4474
4780
|
implementation: "",
|
|
4475
|
-
|
|
4476
|
-
function: "",
|
|
4477
|
-
handler: "",
|
|
4478
|
-
handlerName: ""
|
|
4479
|
-
},
|
|
4480
|
-
importsMock: [],
|
|
4781
|
+
mockOutputs: [],
|
|
4481
4782
|
mutators: [],
|
|
4482
4783
|
clientMutators: [],
|
|
4483
4784
|
formData: [],
|
|
4484
4785
|
formUrlEncoded: [],
|
|
4485
4786
|
paramsSerializer: [],
|
|
4787
|
+
paramsFilter: [],
|
|
4486
4788
|
fetchReviver: []
|
|
4487
4789
|
};
|
|
4488
4790
|
const operations = Object.values(builder.operations);
|
|
4489
4791
|
for (const [index, operation] of operations.entries()) {
|
|
4490
4792
|
target.imports.push(...operation.imports);
|
|
4491
|
-
target.importsMock.push(...operation.importsMock);
|
|
4492
4793
|
target.implementation += operation.implementation + "\n";
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4794
|
+
for (const opMock of operation.mockOutputs) {
|
|
4795
|
+
let acc = target.mockOutputs.find((m) => m.type === opMock.type);
|
|
4796
|
+
if (!acc) {
|
|
4797
|
+
acc = emptyMockOutputFull$1(opMock.type);
|
|
4798
|
+
target.mockOutputs.push(acc);
|
|
4799
|
+
}
|
|
4800
|
+
acc.imports.push(...opMock.imports);
|
|
4801
|
+
acc.implementation.function += opMock.implementation.function;
|
|
4802
|
+
acc.implementation.handler += opMock.implementation.handler;
|
|
4803
|
+
if (opMock.implementation.handlerName) {
|
|
4804
|
+
const separator = acc.implementation.handlerName.length > 0 ? ",\n " : " ";
|
|
4805
|
+
acc.implementation.handlerName += separator + opMock.implementation.handlerName + "()";
|
|
4806
|
+
}
|
|
4807
|
+
}
|
|
4497
4808
|
if (operation.mutator) target.mutators.push(operation.mutator);
|
|
4498
4809
|
if (operation.formData) target.formData.push(operation.formData);
|
|
4499
4810
|
if (operation.formUrlEncoded) target.formUrlEncoded.push(operation.formUrlEncoded);
|
|
4500
4811
|
if (operation.paramsSerializer) target.paramsSerializer.push(operation.paramsSerializer);
|
|
4812
|
+
if (operation.paramsFilter) target.paramsFilter.push(operation.paramsFilter);
|
|
4501
4813
|
if (operation.clientMutators) target.clientMutators.push(...operation.clientMutators);
|
|
4502
4814
|
if (operation.fetchReviver) target.fetchReviver.push(operation.fetchReviver);
|
|
4503
4815
|
if (index === operations.length - 1) {
|
|
@@ -4516,7 +4828,6 @@ function generateTarget(builder, options) {
|
|
|
4516
4828
|
clientImplementation: target.implementation
|
|
4517
4829
|
});
|
|
4518
4830
|
target.implementation = header.implementation + target.implementation;
|
|
4519
|
-
target.implementationMock.handler = target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName;
|
|
4520
4831
|
const footer = builder.footer({
|
|
4521
4832
|
outputClient: options.client,
|
|
4522
4833
|
operationNames,
|
|
@@ -4526,12 +4837,20 @@ function generateTarget(builder, options) {
|
|
|
4526
4837
|
output: options
|
|
4527
4838
|
});
|
|
4528
4839
|
target.implementation += footer.implementation;
|
|
4529
|
-
target.
|
|
4840
|
+
for (const acc of target.mockOutputs) if (acc.implementation.handlerName) acc.implementation.handler = acc.implementation.handler + header.implementationMock + acc.implementation.handlerName + footer.implementationMock;
|
|
4530
4841
|
}
|
|
4531
4842
|
}
|
|
4532
4843
|
return {
|
|
4533
|
-
|
|
4534
|
-
|
|
4844
|
+
imports: target.imports,
|
|
4845
|
+
implementation: target.implementation,
|
|
4846
|
+
mockOutputs: target.mockOutputs.map((m) => flattenMockOutput$1(m)),
|
|
4847
|
+
mutators: target.mutators,
|
|
4848
|
+
clientMutators: target.clientMutators,
|
|
4849
|
+
formData: target.formData,
|
|
4850
|
+
formUrlEncoded: target.formUrlEncoded,
|
|
4851
|
+
paramsSerializer: target.paramsSerializer,
|
|
4852
|
+
paramsFilter: target.paramsFilter,
|
|
4853
|
+
fetchReviver: target.fetchReviver
|
|
4535
4854
|
};
|
|
4536
4855
|
}
|
|
4537
4856
|
//#endregion
|
|
@@ -4580,7 +4899,10 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4580
4899
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
4581
4900
|
extension: output.fileExtension
|
|
4582
4901
|
});
|
|
4583
|
-
const { imports,
|
|
4902
|
+
const { imports, mockOutputs: rawMockOutputs, implementation, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
4903
|
+
const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
|
|
4904
|
+
const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
|
|
4905
|
+
const importsMock = mockOutputs.flatMap((m) => m.imports);
|
|
4584
4906
|
let data = header;
|
|
4585
4907
|
const schemasPath = output.schemas ? getRelativeImportPath(path, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
|
|
4586
4908
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
@@ -4608,16 +4930,17 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4608
4930
|
packageJson: output.packageJson,
|
|
4609
4931
|
output
|
|
4610
4932
|
});
|
|
4611
|
-
|
|
4612
|
-
const
|
|
4933
|
+
for (const mockOutput of mockOutputs) {
|
|
4934
|
+
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
4935
|
+
const filteredMockImports = mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? "")));
|
|
4613
4936
|
const importsMockForBuilder = schemasPath ? generateImportsForBuilder(output, filteredMockImports, schemasPath) : generateImportsForBuilder(output, filteredMockImports.filter((imp) => !!imp.importPath), ".");
|
|
4614
4937
|
data += builder.importsMock({
|
|
4615
|
-
implementation:
|
|
4938
|
+
implementation: mockOutput.implementation,
|
|
4616
4939
|
imports: importsMockForBuilder,
|
|
4617
4940
|
projectName,
|
|
4618
4941
|
hasSchemaDir: !!output.schemas,
|
|
4619
4942
|
isAllowSyntheticDefaultImports,
|
|
4620
|
-
options: isFunction(
|
|
4943
|
+
options: entry && !isFunction(entry) ? entry : void 0
|
|
4621
4944
|
});
|
|
4622
4945
|
}
|
|
4623
4946
|
if (mutators) data += generateMutatorImports({
|
|
@@ -4628,6 +4951,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4628
4951
|
if (formData) data += generateMutatorImports({ mutators: formData });
|
|
4629
4952
|
if (formUrlEncoded) data += generateMutatorImports({ mutators: formUrlEncoded });
|
|
4630
4953
|
if (paramsSerializer) data += generateMutatorImports({ mutators: paramsSerializer });
|
|
4954
|
+
if (paramsFilter) data += generateMutatorImports({ mutators: paramsFilter });
|
|
4631
4955
|
if (fetchReviver) data += generateMutatorImports({ mutators: fetchReviver });
|
|
4632
4956
|
if (implementation.includes("NonReadonly<")) {
|
|
4633
4957
|
data += getOrvalGeneratedTypes();
|
|
@@ -4639,7 +4963,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4639
4963
|
}
|
|
4640
4964
|
if (!output.schemas && needSchema) data += generateSchemasInline ? generateSchemasInline() : generateModelsInline(builder.schemas);
|
|
4641
4965
|
data += `${implementation.trim()}\n`;
|
|
4642
|
-
if (
|
|
4966
|
+
if (mockOutputs.length > 0) {
|
|
4643
4967
|
data += "\n\n";
|
|
4644
4968
|
data += implementationMock;
|
|
4645
4969
|
}
|
|
@@ -4658,9 +4982,8 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4658
4982
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
4659
4983
|
extension: output.fileExtension
|
|
4660
4984
|
});
|
|
4661
|
-
const { imports, implementation,
|
|
4985
|
+
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
4662
4986
|
let implementationData = header;
|
|
4663
|
-
let mockData = header;
|
|
4664
4987
|
const relativeSchemasPath = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
4665
4988
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4666
4989
|
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
@@ -4677,15 +5000,6 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4677
5000
|
packageJson: output.packageJson,
|
|
4678
5001
|
output
|
|
4679
5002
|
});
|
|
4680
|
-
const importsMockForBuilder = generateImportsForBuilder(output, importsMock, relativeSchemasPath);
|
|
4681
|
-
mockData += builder.importsMock({
|
|
4682
|
-
implementation: implementationMock,
|
|
4683
|
-
imports: importsMockForBuilder,
|
|
4684
|
-
projectName,
|
|
4685
|
-
hasSchemaDir: !!output.schemas,
|
|
4686
|
-
isAllowSyntheticDefaultImports,
|
|
4687
|
-
options: isFunction(output.mock) ? void 0 : output.mock
|
|
4688
|
-
});
|
|
4689
5003
|
const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
4690
5004
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
4691
5005
|
if (mutators) implementationData += generateMutatorImports({
|
|
@@ -4696,6 +5010,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4696
5010
|
if (formData) implementationData += generateMutatorImports({ mutators: formData });
|
|
4697
5011
|
if (formUrlEncoded) implementationData += generateMutatorImports({ mutators: formUrlEncoded });
|
|
4698
5012
|
if (paramsSerializer) implementationData += generateMutatorImports({ mutators: paramsSerializer });
|
|
5013
|
+
if (paramsFilter) implementationData += generateMutatorImports({ mutators: paramsFilter });
|
|
4699
5014
|
if (fetchReviver) implementationData += generateMutatorImports({ mutators: fetchReviver });
|
|
4700
5015
|
if (implementation.includes("NonReadonly<")) {
|
|
4701
5016
|
implementationData += getOrvalGeneratedTypes();
|
|
@@ -4706,16 +5021,32 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4706
5021
|
implementationData += "\n";
|
|
4707
5022
|
}
|
|
4708
5023
|
implementationData += `\n${implementation}`;
|
|
4709
|
-
mockData += `\n${implementationMock}`;
|
|
4710
5024
|
const implementationFilename = filename + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
4711
5025
|
const implementationPath = path.join(dirname, implementationFilename);
|
|
4712
5026
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
4713
|
-
const
|
|
4714
|
-
|
|
5027
|
+
const mockPaths = [];
|
|
5028
|
+
for (const mockOutput of mockOutputs) {
|
|
5029
|
+
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
5030
|
+
if (!entry) continue;
|
|
5031
|
+
const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, relativeSchemasPath);
|
|
5032
|
+
let mockData = header;
|
|
5033
|
+
mockData += builder.importsMock({
|
|
5034
|
+
implementation: mockOutput.implementation,
|
|
5035
|
+
imports: importsMockForBuilder,
|
|
5036
|
+
projectName,
|
|
5037
|
+
hasSchemaDir: !!output.schemas,
|
|
5038
|
+
isAllowSyntheticDefaultImports,
|
|
5039
|
+
options: entry
|
|
5040
|
+
});
|
|
5041
|
+
mockData += `\n${mockOutput.implementation}`;
|
|
5042
|
+
const mockPath = path.join(dirname, filename + "." + getMockFileExtensionByTypeName(entry) + extension);
|
|
5043
|
+
await writeGeneratedFile(mockPath, mockData);
|
|
5044
|
+
mockPaths.push(mockPath);
|
|
5045
|
+
}
|
|
4715
5046
|
return [
|
|
4716
5047
|
implementationPath,
|
|
4717
5048
|
...schemasPath ? [schemasPath] : [],
|
|
4718
|
-
...
|
|
5049
|
+
...mockPaths
|
|
4719
5050
|
];
|
|
4720
5051
|
} catch (error) {
|
|
4721
5052
|
throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}`, { cause: error });
|
|
@@ -4723,30 +5054,83 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4723
5054
|
}
|
|
4724
5055
|
//#endregion
|
|
4725
5056
|
//#region src/writers/target-tags.ts
|
|
5057
|
+
/**
|
|
5058
|
+
* Ensures every operation has at least one tag by falling back to the
|
|
5059
|
+
* {@link DefaultTag} constant for untagged operations, so the tag-routing
|
|
5060
|
+
* logic in {@link generateTargetTags} always has a bucket to assign the
|
|
5061
|
+
* operation to.
|
|
5062
|
+
*/
|
|
4726
5063
|
function addDefaultTagIfEmpty(operation) {
|
|
4727
5064
|
return {
|
|
4728
5065
|
...operation,
|
|
4729
|
-
tags: operation.tags.length > 0 ? operation.tags : [
|
|
5066
|
+
tags: operation.tags.length > 0 ? operation.tags : [DefaultTag]
|
|
5067
|
+
};
|
|
5068
|
+
}
|
|
5069
|
+
function emptyMockOutputFull(type) {
|
|
5070
|
+
return {
|
|
5071
|
+
type,
|
|
5072
|
+
implementation: {
|
|
5073
|
+
function: "",
|
|
5074
|
+
handler: "",
|
|
5075
|
+
handlerName: ""
|
|
5076
|
+
},
|
|
5077
|
+
imports: []
|
|
5078
|
+
};
|
|
5079
|
+
}
|
|
5080
|
+
function flattenMockOutput(full) {
|
|
5081
|
+
return {
|
|
5082
|
+
type: full.type,
|
|
5083
|
+
implementation: full.implementation.function + full.implementation.handler,
|
|
5084
|
+
imports: full.imports
|
|
4730
5085
|
};
|
|
4731
5086
|
}
|
|
5087
|
+
function mergeOperationMockOutputs(accMockOutputs, opMockOutputs) {
|
|
5088
|
+
const result = accMockOutputs.map((m) => ({
|
|
5089
|
+
type: m.type,
|
|
5090
|
+
implementation: { ...m.implementation },
|
|
5091
|
+
imports: [...m.imports]
|
|
5092
|
+
}));
|
|
5093
|
+
for (const op of opMockOutputs) {
|
|
5094
|
+
let acc = result.find((m) => m.type === op.type);
|
|
5095
|
+
if (!acc) {
|
|
5096
|
+
acc = emptyMockOutputFull(op.type);
|
|
5097
|
+
result.push(acc);
|
|
5098
|
+
}
|
|
5099
|
+
acc.imports.push(...op.imports);
|
|
5100
|
+
acc.implementation.function += op.implementation.function;
|
|
5101
|
+
acc.implementation.handler += op.implementation.handler;
|
|
5102
|
+
if (op.implementation.handlerName) {
|
|
5103
|
+
const separator = acc.implementation.handlerName.length > 0 ? ",\n " : " ";
|
|
5104
|
+
acc.implementation.handlerName += separator + op.implementation.handlerName + "()";
|
|
5105
|
+
}
|
|
5106
|
+
}
|
|
5107
|
+
return result;
|
|
5108
|
+
}
|
|
5109
|
+
function initialMockOutputsForOperation(op) {
|
|
5110
|
+
return op.mockOutputs.map((m) => ({
|
|
5111
|
+
type: m.type,
|
|
5112
|
+
implementation: {
|
|
5113
|
+
function: m.implementation.function,
|
|
5114
|
+
handler: m.implementation.handler,
|
|
5115
|
+
handlerName: m.implementation.handlerName ? " " + m.implementation.handlerName + "()" : ""
|
|
5116
|
+
},
|
|
5117
|
+
imports: [...m.imports]
|
|
5118
|
+
}));
|
|
5119
|
+
}
|
|
4732
5120
|
function generateTargetTags(currentAcc, operation) {
|
|
4733
5121
|
const tag = kebab(operation.tags[0]);
|
|
4734
5122
|
if (!(tag in currentAcc)) {
|
|
4735
5123
|
currentAcc[tag] = {
|
|
4736
5124
|
imports: operation.imports,
|
|
4737
|
-
|
|
5125
|
+
mockOutputs: initialMockOutputsForOperation(operation),
|
|
4738
5126
|
mutators: operation.mutator ? [operation.mutator] : [],
|
|
4739
5127
|
clientMutators: operation.clientMutators ?? [],
|
|
4740
5128
|
formData: operation.formData ? [operation.formData] : [],
|
|
4741
5129
|
formUrlEncoded: operation.formUrlEncoded ? [operation.formUrlEncoded] : [],
|
|
4742
5130
|
paramsSerializer: operation.paramsSerializer ? [operation.paramsSerializer] : [],
|
|
5131
|
+
paramsFilter: operation.paramsFilter ? [operation.paramsFilter] : [],
|
|
4743
5132
|
fetchReviver: operation.fetchReviver ? [operation.fetchReviver] : [],
|
|
4744
|
-
implementation: operation.implementation
|
|
4745
|
-
implementationMock: {
|
|
4746
|
-
function: operation.implementationMock.function,
|
|
4747
|
-
handler: operation.implementationMock.handler,
|
|
4748
|
-
handlerName: " " + operation.implementationMock.handlerName + "()"
|
|
4749
|
-
}
|
|
5133
|
+
implementation: operation.implementation
|
|
4750
5134
|
};
|
|
4751
5135
|
return currentAcc;
|
|
4752
5136
|
}
|
|
@@ -4754,17 +5138,13 @@ function generateTargetTags(currentAcc, operation) {
|
|
|
4754
5138
|
currentAcc[tag] = {
|
|
4755
5139
|
implementation: currentOperation.implementation + operation.implementation,
|
|
4756
5140
|
imports: [...currentOperation.imports, ...operation.imports],
|
|
4757
|
-
|
|
4758
|
-
implementationMock: {
|
|
4759
|
-
function: currentOperation.implementationMock.function + operation.implementationMock.function,
|
|
4760
|
-
handler: currentOperation.implementationMock.handler + operation.implementationMock.handler,
|
|
4761
|
-
handlerName: currentOperation.implementationMock.handlerName + ",\n " + operation.implementationMock.handlerName + "()"
|
|
4762
|
-
},
|
|
5141
|
+
mockOutputs: mergeOperationMockOutputs(currentOperation.mockOutputs, operation.mockOutputs),
|
|
4763
5142
|
mutators: operation.mutator ? [...currentOperation.mutators ?? [], operation.mutator] : currentOperation.mutators,
|
|
4764
5143
|
clientMutators: operation.clientMutators ? [...currentOperation.clientMutators ?? [], ...operation.clientMutators] : currentOperation.clientMutators,
|
|
4765
5144
|
formData: operation.formData ? [...currentOperation.formData ?? [], operation.formData] : currentOperation.formData,
|
|
4766
5145
|
formUrlEncoded: operation.formUrlEncoded ? [...currentOperation.formUrlEncoded ?? [], operation.formUrlEncoded] : currentOperation.formUrlEncoded,
|
|
4767
5146
|
paramsSerializer: operation.paramsSerializer ? [...currentOperation.paramsSerializer ?? [], operation.paramsSerializer] : currentOperation.paramsSerializer,
|
|
5147
|
+
paramsFilter: operation.paramsFilter ? [...currentOperation.paramsFilter ?? [], operation.paramsFilter] : currentOperation.paramsFilter,
|
|
4768
5148
|
fetchReviver: operation.fetchReviver ? [...currentOperation.fetchReviver ?? [], operation.fetchReviver] : currentOperation.fetchReviver
|
|
4769
5149
|
};
|
|
4770
5150
|
return currentAcc;
|
|
@@ -4806,22 +5186,28 @@ function generateTargetForTags(builder, options) {
|
|
|
4806
5186
|
output: options,
|
|
4807
5187
|
verbOptions: builder.verbOptions,
|
|
4808
5188
|
tag,
|
|
5189
|
+
isDefaultTagBucket: tag === "default" && Object.values(builder.operations).some((operation) => operation.tags.length === 0),
|
|
4809
5190
|
clientImplementation: target.implementation
|
|
4810
5191
|
});
|
|
5192
|
+
const wrappedMockOutputs = target.mockOutputs.map((m) => ({
|
|
5193
|
+
type: m.type,
|
|
5194
|
+
implementation: {
|
|
5195
|
+
function: m.implementation.function,
|
|
5196
|
+
handler: m.implementation.handlerName ? m.implementation.handler + header.implementationMock + m.implementation.handlerName + footer.implementationMock : m.implementation.handler,
|
|
5197
|
+
handlerName: m.implementation.handlerName
|
|
5198
|
+
},
|
|
5199
|
+
imports: m.imports
|
|
5200
|
+
}));
|
|
4811
5201
|
transformed[tag] = {
|
|
4812
5202
|
implementation: header.implementation + target.implementation + footer.implementation,
|
|
4813
|
-
|
|
4814
|
-
function: target.implementationMock.function,
|
|
4815
|
-
handler: target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName + footer.implementationMock,
|
|
4816
|
-
handlerName: target.implementationMock.handlerName
|
|
4817
|
-
},
|
|
5203
|
+
mockOutputs: wrappedMockOutputs,
|
|
4818
5204
|
imports: target.imports,
|
|
4819
|
-
importsMock: target.importsMock,
|
|
4820
5205
|
mutators: target.mutators,
|
|
4821
5206
|
clientMutators: target.clientMutators,
|
|
4822
5207
|
formData: target.formData,
|
|
4823
5208
|
formUrlEncoded: target.formUrlEncoded,
|
|
4824
5209
|
paramsSerializer: target.paramsSerializer,
|
|
5210
|
+
paramsFilter: target.paramsFilter,
|
|
4825
5211
|
fetchReviver: target.fetchReviver
|
|
4826
5212
|
};
|
|
4827
5213
|
}
|
|
@@ -4831,7 +5217,7 @@ function generateTargetForTags(builder, options) {
|
|
|
4831
5217
|
const result = {};
|
|
4832
5218
|
for (const [tag, target] of Object.entries(allTargetTags)) result[tag] = {
|
|
4833
5219
|
...target,
|
|
4834
|
-
|
|
5220
|
+
mockOutputs: target.mockOutputs.map((m) => flattenMockOutput(m))
|
|
4835
5221
|
};
|
|
4836
5222
|
return result;
|
|
4837
5223
|
}
|
|
@@ -4844,15 +5230,20 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4844
5230
|
});
|
|
4845
5231
|
const target = generateTargetForTags(builder, output);
|
|
4846
5232
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4847
|
-
|
|
4848
|
-
const
|
|
4849
|
-
|
|
5233
|
+
if (output.mock.generators.some((g) => isFunction(g))) throw new Error("Function mock generators (ClientMockBuilder) are not supported in tags-split mode. Use typed generators ({ type: \"msw\" } or { type: \"faker\" }).");
|
|
5234
|
+
const generatorEntries = output.mock.generators.filter((g) => !isFunction(g));
|
|
5235
|
+
const indexFilePathsByType = /* @__PURE__ */ new Map();
|
|
5236
|
+
if (output.mock.indexMockFiles) for (const entry of generatorEntries) {
|
|
5237
|
+
const ext = getMockFileExtensionByTypeName(entry);
|
|
5238
|
+
const indexPath = path.join(dirname, `index.${ext}${extension}`);
|
|
5239
|
+
indexFilePathsByType.set(ext, indexPath);
|
|
5240
|
+
await fs$1.outputFile(indexPath, "");
|
|
5241
|
+
}
|
|
4850
5242
|
const tagEntries = Object.entries(target);
|
|
4851
5243
|
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
4852
5244
|
try {
|
|
4853
|
-
const { imports, implementation,
|
|
5245
|
+
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
|
|
4854
5246
|
let implementationData = header;
|
|
4855
|
-
let mockData = header;
|
|
4856
5247
|
const importerPath = path.join(dirname, tag, tag + extension);
|
|
4857
5248
|
const relativeSchemasPath = output.schemas ? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
4858
5249
|
const tagNames = new Set(tagEntries.map(([t]) => t));
|
|
@@ -4886,15 +5277,6 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4886
5277
|
packageJson: output.packageJson,
|
|
4887
5278
|
output
|
|
4888
5279
|
});
|
|
4889
|
-
const importsMockForBuilder = generateImportsForBuilder(output, importsMock, relativeSchemasPath);
|
|
4890
|
-
mockData += builder.importsMock({
|
|
4891
|
-
implementation: implementationMock,
|
|
4892
|
-
imports: importsMockForBuilder,
|
|
4893
|
-
projectName,
|
|
4894
|
-
hasSchemaDir: !!output.schemas,
|
|
4895
|
-
isAllowSyntheticDefaultImports,
|
|
4896
|
-
options: isFunction(output.mock) ? void 0 : output.mock
|
|
4897
|
-
});
|
|
4898
5280
|
const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
4899
5281
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
4900
5282
|
if (mutators) implementationData += generateMutatorImports({
|
|
@@ -4918,6 +5300,10 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4918
5300
|
mutators: paramsSerializer,
|
|
4919
5301
|
oneMore: true
|
|
4920
5302
|
});
|
|
5303
|
+
if (paramsFilter) implementationData += generateMutatorImports({
|
|
5304
|
+
mutators: paramsFilter,
|
|
5305
|
+
oneMore: true
|
|
5306
|
+
});
|
|
4921
5307
|
if (fetchReviver) implementationData += generateMutatorImports({
|
|
4922
5308
|
mutators: fetchReviver,
|
|
4923
5309
|
oneMore: true
|
|
@@ -4931,29 +5317,48 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4931
5317
|
implementationData += "\n";
|
|
4932
5318
|
}
|
|
4933
5319
|
implementationData += `\n${implementation}`;
|
|
4934
|
-
mockData += `\n${implementationMock}`;
|
|
4935
5320
|
const implementationFilename = tag + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
4936
5321
|
const implementationPath = path.join(dirname, tag, implementationFilename);
|
|
4937
5322
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
4938
|
-
const
|
|
4939
|
-
|
|
5323
|
+
const mockPaths = [];
|
|
5324
|
+
for (const mockOutput of mockOutputs) {
|
|
5325
|
+
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
5326
|
+
if (!entry) continue;
|
|
5327
|
+
const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports, relativeSchemasPath);
|
|
5328
|
+
let mockData = header;
|
|
5329
|
+
mockData += builder.importsMock({
|
|
5330
|
+
implementation: mockOutput.implementation,
|
|
5331
|
+
imports: importsMockForBuilder,
|
|
5332
|
+
projectName,
|
|
5333
|
+
hasSchemaDir: !!output.schemas,
|
|
5334
|
+
isAllowSyntheticDefaultImports,
|
|
5335
|
+
options: entry
|
|
5336
|
+
});
|
|
5337
|
+
mockData += `\n${mockOutput.implementation}`;
|
|
5338
|
+
const mockPath = path.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(entry) + extension);
|
|
5339
|
+
await writeGeneratedFile(mockPath, mockData);
|
|
5340
|
+
mockPaths.push(mockPath);
|
|
5341
|
+
}
|
|
4940
5342
|
return [
|
|
4941
5343
|
implementationPath,
|
|
4942
5344
|
...schemasPath ? [schemasPath] : [],
|
|
4943
|
-
...
|
|
5345
|
+
...mockPaths
|
|
4944
5346
|
];
|
|
4945
5347
|
} catch (error) {
|
|
4946
5348
|
throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}`, { cause: error });
|
|
4947
5349
|
}
|
|
4948
5350
|
}));
|
|
4949
|
-
if (
|
|
5351
|
+
if (output.mock.indexMockFiles) for (const entry of generatorEntries) {
|
|
5352
|
+
const ext = getMockFileExtensionByTypeName(entry);
|
|
5353
|
+
const indexFilePath = indexFilePathsByType.get(ext);
|
|
5354
|
+
if (!indexFilePath) continue;
|
|
4950
5355
|
const indexContent = tagEntries.map(([tag]) => {
|
|
4951
|
-
const localMockPath = joinSafe("./", tag, tag + "." +
|
|
4952
|
-
return `export { get${pascal(tag)}Mock } from '${localMockPath}'\n`;
|
|
5356
|
+
const localMockPath = joinSafe("./", tag, tag + "." + ext);
|
|
5357
|
+
return ext === OutputMockType.MSW ? `export { get${pascal(tag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
|
|
4953
5358
|
}).join("");
|
|
4954
5359
|
await fs$1.appendFile(indexFilePath, indexContent);
|
|
4955
5360
|
}
|
|
4956
|
-
return [...new Set([...
|
|
5361
|
+
return [...new Set([...indexFilePathsByType.values(), ...generatedFilePathsArray.flat()])];
|
|
4957
5362
|
}
|
|
4958
5363
|
//#endregion
|
|
4959
5364
|
//#region src/writers/tags-mode.ts
|
|
@@ -4966,7 +5371,10 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
4966
5371
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4967
5372
|
return (await Promise.all(Object.entries(target).map(async ([tag, target]) => {
|
|
4968
5373
|
try {
|
|
4969
|
-
const { imports, implementation,
|
|
5374
|
+
const { imports, implementation, mockOutputs: rawMockOutputs, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer, paramsFilter } = target;
|
|
5375
|
+
const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
|
|
5376
|
+
const importsMock = mockOutputs.flatMap((m) => m.imports);
|
|
5377
|
+
const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
|
|
4970
5378
|
let data = header;
|
|
4971
5379
|
const schemasPathRelative = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
4972
5380
|
const normalizedImports = imports.filter((imp) => {
|
|
@@ -4993,15 +5401,16 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
4993
5401
|
packageJson: output.packageJson,
|
|
4994
5402
|
output
|
|
4995
5403
|
});
|
|
4996
|
-
|
|
4997
|
-
const
|
|
5404
|
+
for (const mockOutput of mockOutputs) {
|
|
5405
|
+
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
5406
|
+
const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? ""))), schemasPathRelative);
|
|
4998
5407
|
data += builder.importsMock({
|
|
4999
|
-
implementation:
|
|
5408
|
+
implementation: mockOutput.implementation,
|
|
5000
5409
|
imports: importsMockForBuilder,
|
|
5001
5410
|
projectName,
|
|
5002
5411
|
hasSchemaDir: !!output.schemas,
|
|
5003
5412
|
isAllowSyntheticDefaultImports,
|
|
5004
|
-
options: isFunction(
|
|
5413
|
+
options: entry && !isFunction(entry) ? entry : void 0
|
|
5005
5414
|
});
|
|
5006
5415
|
}
|
|
5007
5416
|
const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
@@ -5014,6 +5423,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5014
5423
|
if (formData) data += generateMutatorImports({ mutators: formData });
|
|
5015
5424
|
if (formUrlEncoded) data += generateMutatorImports({ mutators: formUrlEncoded });
|
|
5016
5425
|
if (paramsSerializer) data += generateMutatorImports({ mutators: paramsSerializer });
|
|
5426
|
+
if (paramsFilter) data += generateMutatorImports({ mutators: paramsFilter });
|
|
5017
5427
|
if (fetchReviver) data += generateMutatorImports({ mutators: fetchReviver });
|
|
5018
5428
|
data += "\n\n";
|
|
5019
5429
|
if (implementation.includes("NonReadonly<")) {
|
|
@@ -5025,7 +5435,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5025
5435
|
data += "\n";
|
|
5026
5436
|
}
|
|
5027
5437
|
data += implementation;
|
|
5028
|
-
if (
|
|
5438
|
+
if (mockOutputs.length > 0) {
|
|
5029
5439
|
data += "\n\n";
|
|
5030
5440
|
data += implementationMock;
|
|
5031
5441
|
}
|
|
@@ -5038,6 +5448,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5038
5448
|
}))).flat();
|
|
5039
5449
|
}
|
|
5040
5450
|
//#endregion
|
|
5041
|
-
export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, 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, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, 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, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
5451
|
+
export { BODY_TYPE_NAME, DefaultTag, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NAMED_COMPONENT_SECTIONS, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, buildAngularParamsFilterExpression, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, filteredVerbs, 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, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getImportExtension, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBoolean, isComponentRef, isDirectory, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, makeRouteSafe, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
5042
5452
|
|
|
5043
5453
|
//# sourceMappingURL=index.mjs.map
|