@orval/core 8.11.0 → 8.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +72 -27
- package/dist/index.mjs +305 -146
- 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 nodePath 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",
|
|
@@ -177,6 +180,20 @@ function isUrl(str) {
|
|
|
177
180
|
return false;
|
|
178
181
|
}
|
|
179
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
|
+
}
|
|
180
197
|
//#endregion
|
|
181
198
|
//#region src/utils/async-reduce.ts
|
|
182
199
|
async function asyncReduce(array, reducer, initValue) {
|
|
@@ -365,7 +382,7 @@ function createDebugger(ns, options = {}) {
|
|
|
365
382
|
//#region src/utils/doc.ts
|
|
366
383
|
const search = String.raw`\*/`;
|
|
367
384
|
const replacement = String.raw`*\/`;
|
|
368
|
-
const regex
|
|
385
|
+
const regex = new RegExp(search, "g");
|
|
369
386
|
const itemValidationKeys = [
|
|
370
387
|
"minLength",
|
|
371
388
|
"maxLength",
|
|
@@ -397,7 +414,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
397
414
|
const { description, deprecated, summary, minLength, maxLength, minimum, maximum, exclusiveMinimum, exclusiveMaximum, minItems, maxItems, pattern } = schema;
|
|
398
415
|
const isNullable = schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null");
|
|
399
416
|
const itemValidationDocEntries = getItemValidationDocEntries(schema.items);
|
|
400
|
-
const lines = (Array.isArray(description) ? description.filter((d) => !d.includes("eslint-disable")) : [description ?? ""]).map((line) => line.replaceAll(regex
|
|
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));
|
|
401
418
|
const count = [
|
|
402
419
|
description,
|
|
403
420
|
deprecated,
|
|
@@ -416,7 +433,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
416
433
|
].filter(Boolean).length;
|
|
417
434
|
if (!count) return "";
|
|
418
435
|
const oneLine = count === 1 && tryOneLine;
|
|
419
|
-
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;
|
|
420
437
|
let doc = `${eslintDisable ? `/* ${eslintDisable} */\n` : ""}/**`;
|
|
421
438
|
if (description) {
|
|
422
439
|
if (!oneLine) doc += `\n${tryOneLine ? " " : ""} *`;
|
|
@@ -428,7 +445,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
428
445
|
function tryAppendStringDocLine(key, value) {
|
|
429
446
|
if (value) {
|
|
430
447
|
appendPrefix();
|
|
431
|
-
doc += ` @${key} ${value.replaceAll(regex
|
|
448
|
+
doc += ` @${key} ${value.replaceAll(regex, replacement)}`;
|
|
432
449
|
}
|
|
433
450
|
}
|
|
434
451
|
function tryAppendBooleanDocLine(key, value) {
|
|
@@ -444,7 +461,7 @@ function jsDoc(schema, tryOneLine = false, context) {
|
|
|
444
461
|
}
|
|
445
462
|
}
|
|
446
463
|
tryAppendBooleanDocLine("deprecated", deprecated);
|
|
447
|
-
tryAppendStringDocLine("summary", summary?.replaceAll(regex
|
|
464
|
+
tryAppendStringDocLine("summary", summary?.replaceAll(regex, replacement));
|
|
448
465
|
tryAppendNumberDocLine("minLength", minLength);
|
|
449
466
|
tryAppendNumberDocLine("maxLength", maxLength);
|
|
450
467
|
tryAppendNumberDocLine("minimum", minimum);
|
|
@@ -527,12 +544,12 @@ function getFileInfo(target = "", { backupFilename = "filename", extension = ".t
|
|
|
527
544
|
};
|
|
528
545
|
}
|
|
529
546
|
async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
530
|
-
const files = await
|
|
547
|
+
const files = await glob(patterns, {
|
|
531
548
|
cwd: dir,
|
|
532
549
|
absolute: true
|
|
533
550
|
});
|
|
534
551
|
await Promise.all(files.map((file) => fs.promises.unlink(file)));
|
|
535
|
-
const sortedDirectories = (await
|
|
552
|
+
const sortedDirectories = (await glob(["**/*"], {
|
|
536
553
|
cwd: dir,
|
|
537
554
|
absolute: true,
|
|
538
555
|
onlyDirectories: true
|
|
@@ -546,11 +563,17 @@ async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
|
546
563
|
}
|
|
547
564
|
//#endregion
|
|
548
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
|
+
*/
|
|
549
574
|
function getMockFileExtensionByTypeName(mock) {
|
|
550
|
-
if (isFunction(mock)) return
|
|
551
|
-
|
|
552
|
-
default: return "msw";
|
|
553
|
-
}
|
|
575
|
+
if (isFunction(mock)) return OutputMockType.MSW;
|
|
576
|
+
return mock.type;
|
|
554
577
|
}
|
|
555
578
|
//#endregion
|
|
556
579
|
//#region src/utils/get-property-safe.ts
|
|
@@ -1296,7 +1319,8 @@ const COMPONENT_REF_PATTERN = new RegExp(String.raw`^#\/components\/(${NAMED_COM
|
|
|
1296
1319
|
function isComponentRef(ref) {
|
|
1297
1320
|
return COMPONENT_REF_PATTERN.test(ref);
|
|
1298
1321
|
}
|
|
1299
|
-
const
|
|
1322
|
+
const TILDE_1 = /~1/g;
|
|
1323
|
+
const TILDE_0 = /~0/g;
|
|
1300
1324
|
/**
|
|
1301
1325
|
* Return the output type from the $ref
|
|
1302
1326
|
*
|
|
@@ -1304,7 +1328,7 @@ const regex = /* @__PURE__ */ new RegExp("~1", "g");
|
|
|
1304
1328
|
*/
|
|
1305
1329
|
function getRefInfo($ref, context) {
|
|
1306
1330
|
const [pathname, ref] = $ref.split("#");
|
|
1307
|
-
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, "~"));
|
|
1308
1332
|
const getOverrideSuffix = (override, paths) => {
|
|
1309
1333
|
const firstLevel = override[paths[0]];
|
|
1310
1334
|
if (!firstLevel) return "";
|
|
@@ -1688,9 +1712,14 @@ const formDataContentTypes = new Set(["multipart/form-data"]);
|
|
|
1688
1712
|
const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
|
|
1689
1713
|
function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
|
|
1690
1714
|
if (!mediaType.schema) return;
|
|
1715
|
+
const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
|
|
1691
1716
|
const formDataContext = isFormData ? {
|
|
1692
1717
|
atPart: false,
|
|
1693
1718
|
encoding: mediaType.encoding ?? {}
|
|
1719
|
+
} : isFormUrlEncoded ? {
|
|
1720
|
+
atPart: false,
|
|
1721
|
+
encoding: mediaType.encoding ?? {},
|
|
1722
|
+
urlEncoded: true
|
|
1694
1723
|
} : void 0;
|
|
1695
1724
|
const resolvedObject = resolveObject({
|
|
1696
1725
|
schema: mediaType.schema,
|
|
@@ -1956,25 +1985,37 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
|
|
|
1956
1985
|
form += `Object.entries(${propName} ?? {}).forEach(([key, value]) => {\n`;
|
|
1957
1986
|
form += skipLine;
|
|
1958
1987
|
form += ` if (value !== undefined && value !== null) {\n`;
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
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
|
+
}
|
|
1978
2019
|
form += ` }\n`;
|
|
1979
2020
|
form += `});\n`;
|
|
1980
2021
|
} else {
|
|
@@ -2019,6 +2060,7 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
|
|
|
2019
2060
|
}
|
|
2020
2061
|
function resolveSchemaPropertiesToFormData({ schema, variableName, propName, context, isRequestBodyOptional, keyPrefix = "", depth = 0, encoding }) {
|
|
2021
2062
|
let formDataValues = "";
|
|
2063
|
+
const isUrlEncoded = variableName === "formUrlEncoded";
|
|
2022
2064
|
const schemaProps = getSchemaProperties(schema) ?? {};
|
|
2023
2065
|
for (const [key, value] of Object.entries(schemaProps)) {
|
|
2024
2066
|
const { schema: property } = resolveSchemaRef(value, context);
|
|
@@ -2031,9 +2073,10 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
2031
2073
|
const nonOptionalValueKey = `${propName}${formattedKey}`;
|
|
2032
2074
|
const fileType = getFormDataFieldFileType(property, partContentType);
|
|
2033
2075
|
const effectiveContentType = partContentType ?? property.contentMediaType;
|
|
2034
|
-
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`;
|
|
2035
2078
|
else if (fileType === "text") formDataValue = `${variableName}.append(\`${keyPrefix}${key}\`, ${nonOptionalValueKey} instanceof Blob ? ${nonOptionalValueKey} : new Blob([${nonOptionalValueKey}], { type: '${effectiveContentType}' }));\n`;
|
|
2036
|
-
else if (property.type === "object") formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
2079
|
+
else if (property.type === "object" || Array.isArray(property.type) && property.type.includes("object")) formDataValue = context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE ? resolveSchemaPropertiesToFormData({
|
|
2037
2080
|
schema: property,
|
|
2038
2081
|
variableName,
|
|
2039
2082
|
propName: nonOptionalValueKey,
|
|
@@ -2043,7 +2086,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
|
|
|
2043
2086
|
depth: depth + 1,
|
|
2044
2087
|
encoding
|
|
2045
2088
|
}) : `${variableName}.append(\`${keyPrefix}${key}\`, JSON.stringify(${nonOptionalValueKey}));\n`;
|
|
2046
|
-
else if (property.type === "array") {
|
|
2089
|
+
else if (property.type === "array" || Array.isArray(property.type) && property.type.includes("array")) {
|
|
2047
2090
|
let valueStr = "value";
|
|
2048
2091
|
let hasNonPrimitiveChild = false;
|
|
2049
2092
|
const propertyItems = getSchemaItems(property);
|
|
@@ -2348,7 +2391,8 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2348
2391
|
if (Object.keys(allSpecSchemas).some((schemaName) => pascal(schemaName) === propName)) propName = propName + "Property";
|
|
2349
2392
|
const propertyFormDataContext = formDataContext && !formDataContext.atPart ? {
|
|
2350
2393
|
atPart: true,
|
|
2351
|
-
partContentType: formDataContext.encoding[key]?.contentType
|
|
2394
|
+
partContentType: formDataContext.encoding[key]?.contentType,
|
|
2395
|
+
urlEncoded: formDataContext.urlEncoded
|
|
2352
2396
|
} : void 0;
|
|
2353
2397
|
const resolvedValue = resolveObject({
|
|
2354
2398
|
schema,
|
|
@@ -2625,11 +2669,13 @@ function getScalar({ item, name, context, formDataContext }) {
|
|
|
2625
2669
|
value = enumItems.map((enumItem) => isString(enumItem) ? `'${escape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2626
2670
|
isEnum = true;
|
|
2627
2671
|
}
|
|
2628
|
-
if (
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
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
|
+
}
|
|
2633
2679
|
if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
|
|
2634
2680
|
value += nullable;
|
|
2635
2681
|
if (schemaConst) value = `'${schemaConst}'`;
|
|
@@ -2970,10 +3016,13 @@ function getParameters({ parameters, context }) {
|
|
|
2970
3016
|
const { schema, imports } = resolveRef(p, context);
|
|
2971
3017
|
const parameter = schema;
|
|
2972
3018
|
const location = parameter.in;
|
|
2973
|
-
if (location === "path" || location === "query" || location === "header")
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
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
|
+
}
|
|
2977
3026
|
} else if (p.in === "query" || p.in === "path" || p.in === "header") result[p.in].push({
|
|
2978
3027
|
parameter: p,
|
|
2979
3028
|
imports: []
|
|
@@ -3262,7 +3311,7 @@ function getResponse({ responses, operationName, context, contentType }) {
|
|
|
3262
3311
|
success: success || (defaultType ?? "unknown"),
|
|
3263
3312
|
errors: errors || (defaultType ?? "unknown")
|
|
3264
3313
|
},
|
|
3265
|
-
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),
|
|
3266
3315
|
types: groupedByStatus,
|
|
3267
3316
|
contentTypes,
|
|
3268
3317
|
schemas,
|
|
@@ -3355,6 +3404,8 @@ function getBaseUrlRuntimeImports(baseUrl) {
|
|
|
3355
3404
|
values: imp.values ?? true
|
|
3356
3405
|
}));
|
|
3357
3406
|
}
|
|
3407
|
+
const wrapRouteParameters = (route, prepend, append) => route.replaceAll(TEMPLATE_TAG_REGEX, `\${${prepend}$1${append}}`);
|
|
3408
|
+
const makeRouteSafe = (route) => wrapRouteParameters(route, "encodeURIComponent(String(", "))");
|
|
3358
3409
|
function getRouteAsArray(route) {
|
|
3359
3410
|
return route.split("/").filter((i) => i !== "").flatMap((segment) => {
|
|
3360
3411
|
if (!segment.includes("${")) return [`'${segment}'`];
|
|
@@ -3605,7 +3656,7 @@ function generateModelsInline(obj) {
|
|
|
3605
3656
|
//#region src/generators/mutator-info.ts
|
|
3606
3657
|
async function getMutatorInfo(filePath, options) {
|
|
3607
3658
|
const { root = process.cwd(), namedExport = "default", alias, external, tsconfig } = options ?? {};
|
|
3608
|
-
return parseFile(await bundleFile(root, filePath, alias, external, tsconfig?.compilerOptions), namedExport
|
|
3659
|
+
return parseFile(await bundleFile(root, filePath, alias, external, tsconfig?.compilerOptions), namedExport);
|
|
3609
3660
|
}
|
|
3610
3661
|
async function bundleFile(root, fileName, alias, external, compilerOptions) {
|
|
3611
3662
|
const { text } = (await build({
|
|
@@ -3628,10 +3679,10 @@ async function bundleFile(root, fileName, alias, external, compilerOptions) {
|
|
|
3628
3679
|
})).outputFiles[0];
|
|
3629
3680
|
return text;
|
|
3630
3681
|
}
|
|
3631
|
-
function parseFile(file, name
|
|
3682
|
+
function parseFile(file, name) {
|
|
3632
3683
|
try {
|
|
3633
3684
|
const ast = Parser.parse(file, {
|
|
3634
|
-
ecmaVersion,
|
|
3685
|
+
ecmaVersion: "latest",
|
|
3635
3686
|
sourceType: "module"
|
|
3636
3687
|
});
|
|
3637
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");
|
|
@@ -3688,15 +3739,6 @@ function parseFunction(ast, funcName) {
|
|
|
3688
3739
|
}
|
|
3689
3740
|
}
|
|
3690
3741
|
}
|
|
3691
|
-
function getEcmaVersion(target) {
|
|
3692
|
-
if (!target) return;
|
|
3693
|
-
if (target.toLowerCase() === "esnext") return "latest";
|
|
3694
|
-
try {
|
|
3695
|
-
return Number(target.toLowerCase().replace("es", ""));
|
|
3696
|
-
} catch {
|
|
3697
|
-
return;
|
|
3698
|
-
}
|
|
3699
|
-
}
|
|
3700
3742
|
//#endregion
|
|
3701
3743
|
//#region src/generators/mutator.ts
|
|
3702
3744
|
const BODY_TYPE_NAME = "BodyType";
|
|
@@ -4691,7 +4733,39 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
4691
4733
|
return [...schemaImports, ...otherImports];
|
|
4692
4734
|
}
|
|
4693
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
|
|
4694
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
|
+
}
|
|
4695
4769
|
function generateTarget(builder, options) {
|
|
4696
4770
|
const operationNames = Object.values(builder.operations).map(({ operationName }) => operationName);
|
|
4697
4771
|
const isAngularClient = options.client === OutputClient.ANGULAR;
|
|
@@ -4704,12 +4778,7 @@ function generateTarget(builder, options) {
|
|
|
4704
4778
|
const target = {
|
|
4705
4779
|
imports: [],
|
|
4706
4780
|
implementation: "",
|
|
4707
|
-
|
|
4708
|
-
function: "",
|
|
4709
|
-
handler: "",
|
|
4710
|
-
handlerName: ""
|
|
4711
|
-
},
|
|
4712
|
-
importsMock: [],
|
|
4781
|
+
mockOutputs: [],
|
|
4713
4782
|
mutators: [],
|
|
4714
4783
|
clientMutators: [],
|
|
4715
4784
|
formData: [],
|
|
@@ -4721,12 +4790,21 @@ function generateTarget(builder, options) {
|
|
|
4721
4790
|
const operations = Object.values(builder.operations);
|
|
4722
4791
|
for (const [index, operation] of operations.entries()) {
|
|
4723
4792
|
target.imports.push(...operation.imports);
|
|
4724
|
-
target.importsMock.push(...operation.importsMock);
|
|
4725
4793
|
target.implementation += operation.implementation + "\n";
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
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
|
+
}
|
|
4730
4808
|
if (operation.mutator) target.mutators.push(operation.mutator);
|
|
4731
4809
|
if (operation.formData) target.formData.push(operation.formData);
|
|
4732
4810
|
if (operation.formUrlEncoded) target.formUrlEncoded.push(operation.formUrlEncoded);
|
|
@@ -4750,7 +4828,6 @@ function generateTarget(builder, options) {
|
|
|
4750
4828
|
clientImplementation: target.implementation
|
|
4751
4829
|
});
|
|
4752
4830
|
target.implementation = header.implementation + target.implementation;
|
|
4753
|
-
target.implementationMock.handler = target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName;
|
|
4754
4831
|
const footer = builder.footer({
|
|
4755
4832
|
outputClient: options.client,
|
|
4756
4833
|
operationNames,
|
|
@@ -4760,12 +4837,20 @@ function generateTarget(builder, options) {
|
|
|
4760
4837
|
output: options
|
|
4761
4838
|
});
|
|
4762
4839
|
target.implementation += footer.implementation;
|
|
4763
|
-
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;
|
|
4764
4841
|
}
|
|
4765
4842
|
}
|
|
4766
4843
|
return {
|
|
4767
|
-
|
|
4768
|
-
|
|
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
|
|
4769
4854
|
};
|
|
4770
4855
|
}
|
|
4771
4856
|
//#endregion
|
|
@@ -4814,7 +4899,10 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4814
4899
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
4815
4900
|
extension: output.fileExtension
|
|
4816
4901
|
});
|
|
4817
|
-
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);
|
|
4818
4906
|
let data = header;
|
|
4819
4907
|
const schemasPath = output.schemas ? getRelativeImportPath(path, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
|
|
4820
4908
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
@@ -4842,16 +4930,17 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4842
4930
|
packageJson: output.packageJson,
|
|
4843
4931
|
output
|
|
4844
4932
|
});
|
|
4845
|
-
|
|
4846
|
-
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 ?? "")));
|
|
4847
4936
|
const importsMockForBuilder = schemasPath ? generateImportsForBuilder(output, filteredMockImports, schemasPath) : generateImportsForBuilder(output, filteredMockImports.filter((imp) => !!imp.importPath), ".");
|
|
4848
4937
|
data += builder.importsMock({
|
|
4849
|
-
implementation:
|
|
4938
|
+
implementation: mockOutput.implementation,
|
|
4850
4939
|
imports: importsMockForBuilder,
|
|
4851
4940
|
projectName,
|
|
4852
4941
|
hasSchemaDir: !!output.schemas,
|
|
4853
4942
|
isAllowSyntheticDefaultImports,
|
|
4854
|
-
options: isFunction(
|
|
4943
|
+
options: entry && !isFunction(entry) ? entry : void 0
|
|
4855
4944
|
});
|
|
4856
4945
|
}
|
|
4857
4946
|
if (mutators) data += generateMutatorImports({
|
|
@@ -4874,7 +4963,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4874
4963
|
}
|
|
4875
4964
|
if (!output.schemas && needSchema) data += generateSchemasInline ? generateSchemasInline() : generateModelsInline(builder.schemas);
|
|
4876
4965
|
data += `${implementation.trim()}\n`;
|
|
4877
|
-
if (
|
|
4966
|
+
if (mockOutputs.length > 0) {
|
|
4878
4967
|
data += "\n\n";
|
|
4879
4968
|
data += implementationMock;
|
|
4880
4969
|
}
|
|
@@ -4893,9 +4982,8 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4893
4982
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
4894
4983
|
extension: output.fileExtension
|
|
4895
4984
|
});
|
|
4896
|
-
const { imports, implementation,
|
|
4985
|
+
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
4897
4986
|
let implementationData = header;
|
|
4898
|
-
let mockData = header;
|
|
4899
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$/, "");
|
|
4900
4988
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4901
4989
|
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
@@ -4912,15 +5000,6 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4912
5000
|
packageJson: output.packageJson,
|
|
4913
5001
|
output
|
|
4914
5002
|
});
|
|
4915
|
-
const importsMockForBuilder = generateImportsForBuilder(output, importsMock, relativeSchemasPath);
|
|
4916
|
-
mockData += builder.importsMock({
|
|
4917
|
-
implementation: implementationMock,
|
|
4918
|
-
imports: importsMockForBuilder,
|
|
4919
|
-
projectName,
|
|
4920
|
-
hasSchemaDir: !!output.schemas,
|
|
4921
|
-
isAllowSyntheticDefaultImports,
|
|
4922
|
-
options: isFunction(output.mock) ? void 0 : output.mock
|
|
4923
|
-
});
|
|
4924
5003
|
const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
4925
5004
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
4926
5005
|
if (mutators) implementationData += generateMutatorImports({
|
|
@@ -4942,16 +5021,32 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4942
5021
|
implementationData += "\n";
|
|
4943
5022
|
}
|
|
4944
5023
|
implementationData += `\n${implementation}`;
|
|
4945
|
-
mockData += `\n${implementationMock}`;
|
|
4946
5024
|
const implementationFilename = filename + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
4947
5025
|
const implementationPath = nodePath.join(dirname, implementationFilename);
|
|
4948
5026
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
4949
|
-
const
|
|
4950
|
-
|
|
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 = nodePath.join(dirname, filename + "." + getMockFileExtensionByTypeName(entry) + extension);
|
|
5043
|
+
await writeGeneratedFile(mockPath, mockData);
|
|
5044
|
+
mockPaths.push(mockPath);
|
|
5045
|
+
}
|
|
4951
5046
|
return [
|
|
4952
5047
|
implementationPath,
|
|
4953
5048
|
...schemasPath ? [schemasPath] : [],
|
|
4954
|
-
...
|
|
5049
|
+
...mockPaths
|
|
4955
5050
|
];
|
|
4956
5051
|
} catch (error) {
|
|
4957
5052
|
throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}`, { cause: error });
|
|
@@ -4971,12 +5066,63 @@ function addDefaultTagIfEmpty(operation) {
|
|
|
4971
5066
|
tags: operation.tags.length > 0 ? operation.tags : [DefaultTag]
|
|
4972
5067
|
};
|
|
4973
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
|
|
5085
|
+
};
|
|
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
|
+
}
|
|
4974
5120
|
function generateTargetTags(currentAcc, operation) {
|
|
4975
5121
|
const tag = kebab(operation.tags[0]);
|
|
4976
5122
|
if (!(tag in currentAcc)) {
|
|
4977
5123
|
currentAcc[tag] = {
|
|
4978
5124
|
imports: operation.imports,
|
|
4979
|
-
|
|
5125
|
+
mockOutputs: initialMockOutputsForOperation(operation),
|
|
4980
5126
|
mutators: operation.mutator ? [operation.mutator] : [],
|
|
4981
5127
|
clientMutators: operation.clientMutators ?? [],
|
|
4982
5128
|
formData: operation.formData ? [operation.formData] : [],
|
|
@@ -4984,12 +5130,7 @@ function generateTargetTags(currentAcc, operation) {
|
|
|
4984
5130
|
paramsSerializer: operation.paramsSerializer ? [operation.paramsSerializer] : [],
|
|
4985
5131
|
paramsFilter: operation.paramsFilter ? [operation.paramsFilter] : [],
|
|
4986
5132
|
fetchReviver: operation.fetchReviver ? [operation.fetchReviver] : [],
|
|
4987
|
-
implementation: operation.implementation
|
|
4988
|
-
implementationMock: {
|
|
4989
|
-
function: operation.implementationMock.function,
|
|
4990
|
-
handler: operation.implementationMock.handler,
|
|
4991
|
-
handlerName: " " + operation.implementationMock.handlerName + "()"
|
|
4992
|
-
}
|
|
5133
|
+
implementation: operation.implementation
|
|
4993
5134
|
};
|
|
4994
5135
|
return currentAcc;
|
|
4995
5136
|
}
|
|
@@ -4997,12 +5138,7 @@ function generateTargetTags(currentAcc, operation) {
|
|
|
4997
5138
|
currentAcc[tag] = {
|
|
4998
5139
|
implementation: currentOperation.implementation + operation.implementation,
|
|
4999
5140
|
imports: [...currentOperation.imports, ...operation.imports],
|
|
5000
|
-
|
|
5001
|
-
implementationMock: {
|
|
5002
|
-
function: currentOperation.implementationMock.function + operation.implementationMock.function,
|
|
5003
|
-
handler: currentOperation.implementationMock.handler + operation.implementationMock.handler,
|
|
5004
|
-
handlerName: currentOperation.implementationMock.handlerName + ",\n " + operation.implementationMock.handlerName + "()"
|
|
5005
|
-
},
|
|
5141
|
+
mockOutputs: mergeOperationMockOutputs(currentOperation.mockOutputs, operation.mockOutputs),
|
|
5006
5142
|
mutators: operation.mutator ? [...currentOperation.mutators ?? [], operation.mutator] : currentOperation.mutators,
|
|
5007
5143
|
clientMutators: operation.clientMutators ? [...currentOperation.clientMutators ?? [], ...operation.clientMutators] : currentOperation.clientMutators,
|
|
5008
5144
|
formData: operation.formData ? [...currentOperation.formData ?? [], operation.formData] : currentOperation.formData,
|
|
@@ -5053,15 +5189,19 @@ function generateTargetForTags(builder, options) {
|
|
|
5053
5189
|
isDefaultTagBucket: tag === "default" && Object.values(builder.operations).some((operation) => operation.tags.length === 0),
|
|
5054
5190
|
clientImplementation: target.implementation
|
|
5055
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
|
+
}));
|
|
5056
5201
|
transformed[tag] = {
|
|
5057
5202
|
implementation: header.implementation + target.implementation + footer.implementation,
|
|
5058
|
-
|
|
5059
|
-
function: target.implementationMock.function,
|
|
5060
|
-
handler: target.implementationMock.handler + header.implementationMock + target.implementationMock.handlerName + footer.implementationMock,
|
|
5061
|
-
handlerName: target.implementationMock.handlerName
|
|
5062
|
-
},
|
|
5203
|
+
mockOutputs: wrappedMockOutputs,
|
|
5063
5204
|
imports: target.imports,
|
|
5064
|
-
importsMock: target.importsMock,
|
|
5065
5205
|
mutators: target.mutators,
|
|
5066
5206
|
clientMutators: target.clientMutators,
|
|
5067
5207
|
formData: target.formData,
|
|
@@ -5077,7 +5217,7 @@ function generateTargetForTags(builder, options) {
|
|
|
5077
5217
|
const result = {};
|
|
5078
5218
|
for (const [tag, target] of Object.entries(allTargetTags)) result[tag] = {
|
|
5079
5219
|
...target,
|
|
5080
|
-
|
|
5220
|
+
mockOutputs: target.mockOutputs.map((m) => flattenMockOutput(m))
|
|
5081
5221
|
};
|
|
5082
5222
|
return result;
|
|
5083
5223
|
}
|
|
@@ -5090,15 +5230,20 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5090
5230
|
});
|
|
5091
5231
|
const target = generateTargetForTags(builder, output);
|
|
5092
5232
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
5093
|
-
|
|
5094
|
-
const
|
|
5095
|
-
|
|
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 = nodePath.join(dirname, `index.${ext}${extension}`);
|
|
5239
|
+
indexFilePathsByType.set(ext, indexPath);
|
|
5240
|
+
await fs$1.outputFile(indexPath, "");
|
|
5241
|
+
}
|
|
5096
5242
|
const tagEntries = Object.entries(target);
|
|
5097
5243
|
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
5098
5244
|
try {
|
|
5099
|
-
const { imports, implementation,
|
|
5245
|
+
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
|
|
5100
5246
|
let implementationData = header;
|
|
5101
|
-
let mockData = header;
|
|
5102
5247
|
const importerPath = nodePath.join(dirname, tag, tag + extension);
|
|
5103
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$/, "");
|
|
5104
5249
|
const tagNames = new Set(tagEntries.map(([t]) => t));
|
|
@@ -5132,15 +5277,6 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5132
5277
|
packageJson: output.packageJson,
|
|
5133
5278
|
output
|
|
5134
5279
|
});
|
|
5135
|
-
const importsMockForBuilder = generateImportsForBuilder(output, importsMock, relativeSchemasPath);
|
|
5136
|
-
mockData += builder.importsMock({
|
|
5137
|
-
implementation: implementationMock,
|
|
5138
|
-
imports: importsMockForBuilder,
|
|
5139
|
-
projectName,
|
|
5140
|
-
hasSchemaDir: !!output.schemas,
|
|
5141
|
-
isAllowSyntheticDefaultImports,
|
|
5142
|
-
options: isFunction(output.mock) ? void 0 : output.mock
|
|
5143
|
-
});
|
|
5144
5280
|
const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
5145
5281
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
5146
5282
|
if (mutators) implementationData += generateMutatorImports({
|
|
@@ -5181,29 +5317,48 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
5181
5317
|
implementationData += "\n";
|
|
5182
5318
|
}
|
|
5183
5319
|
implementationData += `\n${implementation}`;
|
|
5184
|
-
mockData += `\n${implementationMock}`;
|
|
5185
5320
|
const implementationFilename = tag + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
5186
5321
|
const implementationPath = nodePath.join(dirname, tag, implementationFilename);
|
|
5187
5322
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
5188
|
-
const
|
|
5189
|
-
|
|
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 = nodePath.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(entry) + extension);
|
|
5339
|
+
await writeGeneratedFile(mockPath, mockData);
|
|
5340
|
+
mockPaths.push(mockPath);
|
|
5341
|
+
}
|
|
5190
5342
|
return [
|
|
5191
5343
|
implementationPath,
|
|
5192
5344
|
...schemasPath ? [schemasPath] : [],
|
|
5193
|
-
...
|
|
5345
|
+
...mockPaths
|
|
5194
5346
|
];
|
|
5195
5347
|
} catch (error) {
|
|
5196
5348
|
throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}`, { cause: error });
|
|
5197
5349
|
}
|
|
5198
5350
|
}));
|
|
5199
|
-
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;
|
|
5200
5355
|
const indexContent = tagEntries.map(([tag]) => {
|
|
5201
|
-
const localMockPath = joinSafe("./", tag, tag + "." +
|
|
5202
|
-
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`;
|
|
5203
5358
|
}).join("");
|
|
5204
5359
|
await fs$1.appendFile(indexFilePath, indexContent);
|
|
5205
5360
|
}
|
|
5206
|
-
return [...new Set([...
|
|
5361
|
+
return [...new Set([...indexFilePathsByType.values(), ...generatedFilePathsArray.flat()])];
|
|
5207
5362
|
}
|
|
5208
5363
|
//#endregion
|
|
5209
5364
|
//#region src/writers/tags-mode.ts
|
|
@@ -5216,7 +5371,10 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5216
5371
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
5217
5372
|
return (await Promise.all(Object.entries(target).map(async ([tag, target]) => {
|
|
5218
5373
|
try {
|
|
5219
|
-
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");
|
|
5220
5378
|
let data = header;
|
|
5221
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$/, "");
|
|
5222
5380
|
const normalizedImports = imports.filter((imp) => {
|
|
@@ -5243,15 +5401,16 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5243
5401
|
packageJson: output.packageJson,
|
|
5244
5402
|
output
|
|
5245
5403
|
});
|
|
5246
|
-
|
|
5247
|
-
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);
|
|
5248
5407
|
data += builder.importsMock({
|
|
5249
|
-
implementation:
|
|
5408
|
+
implementation: mockOutput.implementation,
|
|
5250
5409
|
imports: importsMockForBuilder,
|
|
5251
5410
|
projectName,
|
|
5252
5411
|
hasSchemaDir: !!output.schemas,
|
|
5253
5412
|
isAllowSyntheticDefaultImports,
|
|
5254
|
-
options: isFunction(
|
|
5413
|
+
options: entry && !isFunction(entry) ? entry : void 0
|
|
5255
5414
|
});
|
|
5256
5415
|
}
|
|
5257
5416
|
const schemasPath = !output.schemas && needSchema ? nodePath.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
@@ -5276,7 +5435,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5276
5435
|
data += "\n";
|
|
5277
5436
|
}
|
|
5278
5437
|
data += implementation;
|
|
5279
|
-
if (
|
|
5438
|
+
if (mockOutputs.length > 0) {
|
|
5280
5439
|
data += "\n\n";
|
|
5281
5440
|
data += implementationMock;
|
|
5282
5441
|
}
|
|
@@ -5289,6 +5448,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
5289
5448
|
}))).flat();
|
|
5290
5449
|
}
|
|
5291
5450
|
//#endregion
|
|
5292
|
-
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, 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 };
|
|
5293
5452
|
|
|
5294
5453
|
//# sourceMappingURL=index.mjs.map
|