@orval/core 8.16.0 → 8.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +22 -5
- package/dist/index.mjs +397 -112
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -955,17 +955,18 @@ const sortByPriority = (arr) => arr.toSorted((a, b) => {
|
|
|
955
955
|
function stringify(data) {
|
|
956
956
|
if (data === void 0) return;
|
|
957
957
|
if (data === null) return "null";
|
|
958
|
-
if (isString(data)) return `'${data
|
|
958
|
+
if (isString(data)) return `'${jsStringLiteralEscape(data)}'`;
|
|
959
959
|
if (isNumber(data) || isBoolean(data) || isFunction(data)) return String(data);
|
|
960
960
|
if (Array.isArray(data)) return `[${data.map((item) => stringify(item)).join(", ")}]`;
|
|
961
961
|
const entries = Object.entries(data);
|
|
962
962
|
let result = "";
|
|
963
963
|
for (const [index, [key, value]] of entries.entries()) {
|
|
964
964
|
const strValue = stringify(value);
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
else if (
|
|
968
|
-
else result += `${
|
|
965
|
+
const safeKey = key === "__proto__" ? `['${jsStringLiteralEscape(key)}']` : keyword.isIdentifierNameES5(key) ? key : `'${jsStringLiteralEscape(key)}'`;
|
|
966
|
+
if (entries.length === 1) result = `{ ${safeKey}: ${strValue}, }`;
|
|
967
|
+
else if (!index) result = `{ ${safeKey}: ${strValue}, `;
|
|
968
|
+
else if (entries.length - 1 === index) result += `${safeKey}: ${strValue}, }`;
|
|
969
|
+
else result += `${safeKey}: ${strValue}, `;
|
|
969
970
|
}
|
|
970
971
|
return result;
|
|
971
972
|
}
|
|
@@ -1320,7 +1321,7 @@ const getUnion = (value, enumName) => {
|
|
|
1320
1321
|
};
|
|
1321
1322
|
function getEnumUnionFromSchema(schema) {
|
|
1322
1323
|
if (!schema?.enum) return "";
|
|
1323
|
-
return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${
|
|
1324
|
+
return schema.enum.filter((val) => val !== null).map((val) => isString(val) ? `'${jsStringLiteralEscape(val)}'` : String(val)).join(" | ");
|
|
1324
1325
|
}
|
|
1325
1326
|
const stripNullUnion = (value) => value.replaceAll(/\s*\|\s*null/g, "").trim();
|
|
1326
1327
|
const isSpreadableEnumRef = (schema, refName) => {
|
|
@@ -1707,13 +1708,13 @@ function getPropertyNamesEnumKeyType(item) {
|
|
|
1707
1708
|
if (Array.isArray(propertyNames.enum)) {
|
|
1708
1709
|
const enumValues = propertyNames.enum.filter((val) => isString(val));
|
|
1709
1710
|
if (enumValues.length > 0) return {
|
|
1710
|
-
value: enumValues.map((val) => `'${
|
|
1711
|
+
value: enumValues.map((val) => `'${jsStringLiteralEscape(val)}'`).join(" | "),
|
|
1711
1712
|
imports: [],
|
|
1712
1713
|
dependencies: []
|
|
1713
1714
|
};
|
|
1714
1715
|
}
|
|
1715
1716
|
if (isString(propertyNames.const)) return {
|
|
1716
|
-
value: `'${
|
|
1717
|
+
value: `'${jsStringLiteralEscape(propertyNames.const)}'`,
|
|
1717
1718
|
imports: [],
|
|
1718
1719
|
dependencies: []
|
|
1719
1720
|
};
|
|
@@ -1878,7 +1879,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
1878
1879
|
const hasConst = constValue !== void 0;
|
|
1879
1880
|
let constLiteral;
|
|
1880
1881
|
if (!hasConst) constLiteral = void 0;
|
|
1881
|
-
else if (isString(constValue)) constLiteral = `'${
|
|
1882
|
+
else if (isString(constValue)) constLiteral = `'${jsStringLiteralEscape(constValue)}'`;
|
|
1882
1883
|
else constLiteral = JSON.stringify(constValue);
|
|
1883
1884
|
const needsValueImport = hasConst && (resolvedValue.isEnum || resolvedValue.type === "enum");
|
|
1884
1885
|
const usedResolvedValue = !hasConst || needsValueImport;
|
|
@@ -2011,7 +2012,7 @@ function getObject({ item, name, context, nullable, formDataContext }) {
|
|
|
2011
2012
|
else if (typeof constValue === "boolean") type = "boolean";
|
|
2012
2013
|
else type = "object";
|
|
2013
2014
|
return {
|
|
2014
|
-
value: typeof constValue === "string" ? `'${
|
|
2015
|
+
value: typeof constValue === "string" ? `'${jsStringLiteralEscape(constValue)}'` : JSON.stringify(constValue),
|
|
2015
2016
|
imports: [],
|
|
2016
2017
|
schemas: [],
|
|
2017
2018
|
isEnum: false,
|
|
@@ -2152,7 +2153,7 @@ function getScalar({ item, name, context, formDataContext }) {
|
|
|
2152
2153
|
let value = "string";
|
|
2153
2154
|
let isEnum = false;
|
|
2154
2155
|
if (enumItems) {
|
|
2155
|
-
value = enumItems.map((enumItem) => isString(enumItem) ? `'${
|
|
2156
|
+
value = enumItems.map((enumItem) => isString(enumItem) ? `'${jsStringLiteralEscape(enumItem)}'` : `${enumItem}`).filter(Boolean).join(` | `);
|
|
2156
2157
|
isEnum = true;
|
|
2157
2158
|
}
|
|
2158
2159
|
if (!formDataContext?.urlEncoded) {
|
|
@@ -2164,7 +2165,7 @@ function getScalar({ item, name, context, formDataContext }) {
|
|
|
2164
2165
|
}
|
|
2165
2166
|
if (context.output.override.useDates && (schemaFormat === "date" || schemaFormat === "date-time")) value = "Date";
|
|
2166
2167
|
value += nullable;
|
|
2167
|
-
if (schemaConst) value = `'${schemaConst}'`;
|
|
2168
|
+
if (schemaConst) value = `'${jsStringLiteralEscape(schemaConst)}'`;
|
|
2168
2169
|
return {
|
|
2169
2170
|
value,
|
|
2170
2171
|
isEnum,
|
|
@@ -2214,7 +2215,7 @@ function getScalar({ item, name, context, formDataContext }) {
|
|
|
2214
2215
|
nullable
|
|
2215
2216
|
});
|
|
2216
2217
|
if (enumItems) return {
|
|
2217
|
-
value: enumItems.map((enumItem) => isString(enumItem) ? `'${
|
|
2218
|
+
value: enumItems.map((enumItem) => isString(enumItem) ? `'${jsStringLiteralEscape(enumItem)}'` : String(enumItem)).filter(Boolean).join(` | `) + nullable,
|
|
2218
2219
|
isEnum: true,
|
|
2219
2220
|
type: "string",
|
|
2220
2221
|
imports: [],
|
|
@@ -4457,8 +4458,9 @@ function findRefs(value) {
|
|
|
4457
4458
|
if (!value || typeof value !== "object") return [];
|
|
4458
4459
|
if (Array.isArray(value)) return value.flatMap((item) => findRefs(item));
|
|
4459
4460
|
const obj = value;
|
|
4460
|
-
|
|
4461
|
-
|
|
4461
|
+
const refs = [];
|
|
4462
|
+
if (typeof obj.$ref === "string") refs.push(obj.$ref);
|
|
4463
|
+
return refs.concat(Object.values(obj).flatMap((val) => findRefs(val)));
|
|
4462
4464
|
}
|
|
4463
4465
|
function parseComponentRef(ref) {
|
|
4464
4466
|
const parts = ref.split("/");
|
|
@@ -4617,9 +4619,10 @@ function parseFunction(ast, funcName) {
|
|
|
4617
4619
|
//#endregion
|
|
4618
4620
|
//#region src/generators/mutator.ts
|
|
4619
4621
|
const BODY_TYPE_NAME = "BodyType";
|
|
4620
|
-
const getImport = (output, mutator) => {
|
|
4622
|
+
const getImport = (output, mutator, tsconfig) => {
|
|
4621
4623
|
const outputFile = getFileInfo(output).path;
|
|
4622
|
-
|
|
4624
|
+
const ext = mutator.extension ?? getImportExtension(nodePath.extname(mutator.path), tsconfig);
|
|
4625
|
+
return `${getRelativeImportPath(outputFile, mutator.path)}${ext}`;
|
|
4623
4626
|
};
|
|
4624
4627
|
async function generateMutator({ output, mutator, name, workspace, tsconfig }) {
|
|
4625
4628
|
if (!mutator || !output) return;
|
|
@@ -4642,7 +4645,7 @@ async function generateMutator({ output, mutator, name, workspace, tsconfig }) {
|
|
|
4642
4645
|
tsconfig
|
|
4643
4646
|
});
|
|
4644
4647
|
if (!mutatorInfo) throw new Error(styleText("red", `Your mutator file doesn't have the ${mutatorInfoName} exported function`));
|
|
4645
|
-
const importStatementPath = getImport(output, mutator);
|
|
4648
|
+
const importStatementPath = getImport(output, mutator, tsconfig);
|
|
4646
4649
|
const isHook = mutator.name ? mutator.name.startsWith("use") && !mutatorInfo.numberOfParams : !mutatorInfo.numberOfParams;
|
|
4647
4650
|
return {
|
|
4648
4651
|
name: mutator.name || !isHook ? importName : `use${pascal(importName)}`,
|
|
@@ -4684,11 +4687,19 @@ const getAngularFilteredParamsExpression = (paramsExpression, requiredNullablePa
|
|
|
4684
4687
|
continue;
|
|
4685
4688
|
}
|
|
4686
4689
|
` : "";
|
|
4687
|
-
|
|
4690
|
+
let preserveNullableBranch;
|
|
4691
|
+
let requiredNullableParamKeysBranch;
|
|
4692
|
+
if (preserveRequiredNullables) {
|
|
4693
|
+
preserveNullableBranch = ` } else if (value === null && requiredNullableParamKeys.has(key)) {
|
|
4688
4694
|
filteredParams[key] = null;
|
|
4689
|
-
|
|
4695
|
+
`;
|
|
4696
|
+
requiredNullableParamKeysBranch = `const requiredNullableParamKeys = new Set<string>(${JSON.stringify(requiredNullableParamKeys)});`;
|
|
4697
|
+
} else {
|
|
4698
|
+
preserveNullableBranch = "";
|
|
4699
|
+
requiredNullableParamKeysBranch = "";
|
|
4700
|
+
}
|
|
4690
4701
|
return `(() => {
|
|
4691
|
-
${hasPassthrough ? ` const passthroughKeys = new Set<string>(${JSON.stringify(nonPrimitiveKeys)});\n` : ""}
|
|
4702
|
+
${hasPassthrough ? ` const passthroughKeys = new Set<string>(${JSON.stringify(nonPrimitiveKeys)});\n` : ""} ${requiredNullableParamKeysBranch}
|
|
4692
4703
|
const filteredParams: Record<string, ${filteredParamValueType}> = {};
|
|
4693
4704
|
for (const [key, value] of Object.entries(${paramsExpression})) {
|
|
4694
4705
|
${passthroughBranch} if (Array.isArray(value)) {
|
|
@@ -5746,12 +5757,25 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
5746
5757
|
//#endregion
|
|
5747
5758
|
//#region src/writers/finalize-mock-implementation.ts
|
|
5748
5759
|
function getFinalizeMockImplementationOptions(output, mockOutputs) {
|
|
5749
|
-
const
|
|
5760
|
+
const outputs = Array.isArray(mockOutputs) ? mockOutputs : [mockOutputs];
|
|
5761
|
+
const strictSchemaTypeNames = [...new Set(outputs.flatMap((mockOutput) => mockOutput.strictMockSchemaTypeNames ?? []))];
|
|
5762
|
+
const strictMockSchemaKinds = outputs.reduce((acc, mockOutput) => {
|
|
5763
|
+
if (!mockOutput.strictMockSchemaKinds) return acc;
|
|
5764
|
+
for (const [name, kind] of Object.entries(mockOutput.strictMockSchemaKinds)) acc[name] ??= kind;
|
|
5765
|
+
return acc;
|
|
5766
|
+
}, {});
|
|
5750
5767
|
return {
|
|
5751
5768
|
mockOptions: output.override.mock,
|
|
5752
|
-
strictSchemaTypeNames: strictSchemaTypeNames.length > 0 ? strictSchemaTypeNames : void 0
|
|
5769
|
+
strictSchemaTypeNames: strictSchemaTypeNames.length > 0 ? strictSchemaTypeNames : void 0,
|
|
5770
|
+
strictMockSchemaKinds: Object.keys(strictMockSchemaKinds).length > 0 ? strictMockSchemaKinds : void 0
|
|
5753
5771
|
};
|
|
5754
5772
|
}
|
|
5773
|
+
/** Drop schema-factory `{Schema}Mock` type imports that are declared locally. */
|
|
5774
|
+
function filterLocalStrictMockTypeImports(imports, strictSchemaTypeNames) {
|
|
5775
|
+
if (!strictSchemaTypeNames?.length) return [...imports];
|
|
5776
|
+
const localMockTypeNames = new Set(strictSchemaTypeNames.map((name) => `${name}Mock`));
|
|
5777
|
+
return imports.filter((imp) => !(imp.schemaFactory && !imp.values && localMockTypeNames.has(imp.name)));
|
|
5778
|
+
}
|
|
5755
5779
|
//#endregion
|
|
5756
5780
|
//#region src/writers/generate-imports-for-builder.ts
|
|
5757
5781
|
function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
@@ -5759,9 +5783,10 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
5759
5783
|
const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
|
|
5760
5784
|
const schemaFactoryImports = imports.filter((i) => i.schemaFactory);
|
|
5761
5785
|
const schemaFactoryImportExtension = isPackageImport ? "" : getImportExtension(output.fileExtension, output.tsconfig);
|
|
5786
|
+
const schemaFactoryDependency = getFakerSchemasImportPath(output.mock) ?? joinSafe(relativeSchemasPath, `index.faker${schemaFactoryImportExtension}`);
|
|
5762
5787
|
const schemaFactoryDeps = schemaFactoryImports.length > 0 ? [{
|
|
5763
5788
|
exports: uniqueBy(schemaFactoryImports, (entry) => `${entry.name}|${entry.alias ?? ""}`),
|
|
5764
|
-
dependency:
|
|
5789
|
+
dependency: schemaFactoryDependency
|
|
5765
5790
|
}] : [];
|
|
5766
5791
|
imports = imports.filter((i) => !i.schemaFactory);
|
|
5767
5792
|
let schemaImports;
|
|
@@ -5796,6 +5821,16 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
5796
5821
|
...otherImports
|
|
5797
5822
|
];
|
|
5798
5823
|
}
|
|
5824
|
+
/**
|
|
5825
|
+
* Extracts the faker generator's `schemasImportPath` from the normalized mock
|
|
5826
|
+
* config, if one is configured. Returns `undefined` when there is no faker
|
|
5827
|
+
* generator with schema factories enabled, or when `schemasImportPath` is not
|
|
5828
|
+
* set.
|
|
5829
|
+
*/
|
|
5830
|
+
function getFakerSchemasImportPath(mock) {
|
|
5831
|
+
if (!mock) return;
|
|
5832
|
+
return mock.generators.find((g) => !isFunction(g) && g.type === OutputMockType.FAKER && g.schemas === true)?.schemasImportPath;
|
|
5833
|
+
}
|
|
5799
5834
|
//#endregion
|
|
5800
5835
|
//#region src/writers/mock-outputs.ts
|
|
5801
5836
|
/**
|
|
@@ -5811,6 +5846,21 @@ function collapseInlineMockOutputs(mockOutputs) {
|
|
|
5811
5846
|
return mockOutputs.filter((m) => m.type !== OutputMockType.FAKER);
|
|
5812
5847
|
}
|
|
5813
5848
|
//#endregion
|
|
5849
|
+
//#region src/writers/mock-utils.ts
|
|
5850
|
+
function getMockDir(entry, mockConfig) {
|
|
5851
|
+
if (!isFunction(entry) && entry.path) return entry.path;
|
|
5852
|
+
return mockConfig.path;
|
|
5853
|
+
}
|
|
5854
|
+
function hasAnyMockPath(mockConfig) {
|
|
5855
|
+
if (mockConfig.path) return true;
|
|
5856
|
+
return mockConfig.generators.some((g) => !isFunction(g) && !!g.path);
|
|
5857
|
+
}
|
|
5858
|
+
function resolveMockSchemasPath(mockFilePath, schemasTarget) {
|
|
5859
|
+
const ext = nodePath.extname(mockFilePath);
|
|
5860
|
+
const targetExt = nodePath.extname(schemasTarget);
|
|
5861
|
+
return getRelativeImportPath(mockFilePath, targetExt === ".schemas" ? schemasTarget + ext : targetExt ? schemasTarget : schemasTarget + ext);
|
|
5862
|
+
}
|
|
5863
|
+
//#endregion
|
|
5814
5864
|
//#region src/writers/target.ts
|
|
5815
5865
|
function emptyMockOutputFull$1(type) {
|
|
5816
5866
|
return {
|
|
@@ -5828,7 +5878,8 @@ function flattenMockOutput$1(full) {
|
|
|
5828
5878
|
type: full.type,
|
|
5829
5879
|
implementation: full.implementation.function + full.implementation.handler,
|
|
5830
5880
|
imports: full.imports,
|
|
5831
|
-
strictMockSchemaTypeNames: full.strictMockSchemaTypeNames
|
|
5881
|
+
strictMockSchemaTypeNames: full.strictMockSchemaTypeNames,
|
|
5882
|
+
strictMockSchemaKinds: full.strictMockSchemaKinds
|
|
5832
5883
|
};
|
|
5833
5884
|
}
|
|
5834
5885
|
function generateTarget(builder, options) {
|
|
@@ -5864,6 +5915,10 @@ function generateTarget(builder, options) {
|
|
|
5864
5915
|
}
|
|
5865
5916
|
acc.imports.push(...opMock.imports);
|
|
5866
5917
|
if (opMock.strictMockSchemaTypeNames?.length) acc.strictMockSchemaTypeNames = [...new Set([...acc.strictMockSchemaTypeNames ?? [], ...opMock.strictMockSchemaTypeNames])];
|
|
5918
|
+
if (opMock.strictMockSchemaKinds) acc.strictMockSchemaKinds = {
|
|
5919
|
+
...acc.strictMockSchemaKinds,
|
|
5920
|
+
...opMock.strictMockSchemaKinds
|
|
5921
|
+
};
|
|
5867
5922
|
acc.implementation.function += opMock.implementation.function;
|
|
5868
5923
|
acc.implementation.handler += opMock.implementation.handler;
|
|
5869
5924
|
if (opMock.implementation.handlerName) {
|
|
@@ -5961,30 +6016,33 @@ interface TypedResponse<T> extends Response {
|
|
|
5961
6016
|
//#region src/writers/single-mode.ts
|
|
5962
6017
|
async function writeSingleMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
|
|
5963
6018
|
try {
|
|
5964
|
-
const { path } = getFileInfo(output.target, {
|
|
6019
|
+
const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
|
|
5965
6020
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
5966
6021
|
extension: output.fileExtension
|
|
5967
6022
|
});
|
|
5968
6023
|
const { imports, mockOutputs: rawMockOutputs, implementation, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
5969
|
-
const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
|
|
5970
|
-
const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
|
|
5971
|
-
const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, mockOutputs)) : implementationMock;
|
|
5972
|
-
const importsMock = mockOutputs.flatMap((m) => m.imports);
|
|
5973
|
-
let data = header;
|
|
5974
|
-
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
5975
|
-
const schemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(path, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
|
|
5976
6024
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
6025
|
+
const shouldDeinlineMocks = hasAnyMockPath(output.mock);
|
|
6026
|
+
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6027
|
+
const schemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
|
|
6028
|
+
const relativeSchemasPath = schemasPath ?? "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
6029
|
+
const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : targetPath;
|
|
5977
6030
|
const normalizedImports = imports.filter((imp) => {
|
|
5978
6031
|
const searchWords = [imp.alias, imp.name].filter((part) => Boolean(part?.length)).map((part) => escapeRegExp(part)).join("|");
|
|
5979
6032
|
if (!searchWords) return false;
|
|
5980
6033
|
return new RegExp(String.raw`\b(${searchWords})\b`, "g").test(implementation);
|
|
5981
6034
|
}).map((imp) => ({ ...imp }));
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
6035
|
+
const collapsedMockOutputs = shouldDeinlineMocks ? [] : collapseInlineMockOutputs(rawMockOutputs);
|
|
6036
|
+
if (!shouldDeinlineMocks) {
|
|
6037
|
+
const importsMock = collapsedMockOutputs.flatMap((m) => m.imports);
|
|
6038
|
+
for (const mockImport of importsMock) {
|
|
6039
|
+
const matchingImport = normalizedImports.find((imp) => imp.name === mockImport.name && (imp.alias ?? "") === (mockImport.alias ?? ""));
|
|
6040
|
+
if (!matchingImport) continue;
|
|
6041
|
+
if (!!mockImport.values || !!mockImport.isConstant || !!mockImport.default || !!mockImport.namespaceImport || !!mockImport.syntheticDefaultImport) matchingImport.values = true;
|
|
6042
|
+
}
|
|
5986
6043
|
}
|
|
5987
|
-
|
|
6044
|
+
let data = header;
|
|
6045
|
+
const importsForBuilder = schemasPath ? generateImportsForBuilder(output, normalizedImports, relativeSchemasPath) : generateImportsForBuilder(output, normalizedImports.filter((imp) => !!imp.importPath), ".");
|
|
5988
6046
|
data += builder.imports({
|
|
5989
6047
|
client: output.client,
|
|
5990
6048
|
implementation,
|
|
@@ -5998,10 +6056,11 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
5998
6056
|
packageJson: output.packageJson,
|
|
5999
6057
|
output
|
|
6000
6058
|
});
|
|
6001
|
-
for (const mockOutput of
|
|
6059
|
+
if (!shouldDeinlineMocks) for (const mockOutput of collapsedMockOutputs) {
|
|
6002
6060
|
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
6003
|
-
const
|
|
6004
|
-
const
|
|
6061
|
+
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6062
|
+
const filteredMockImports = filterLocalStrictMockTypeImports(mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? ""))), finalizeMockOptions.strictSchemaTypeNames);
|
|
6063
|
+
const importsMockForBuilder = schemasPath ? generateImportsForBuilder(output, filteredMockImports, relativeSchemasPath) : generateImportsForBuilder(output, filteredMockImports.filter((imp) => !!imp.importPath), ".");
|
|
6005
6064
|
data += builder.importsMock({
|
|
6006
6065
|
implementation: mockOutput.implementation,
|
|
6007
6066
|
imports: importsMockForBuilder,
|
|
@@ -6031,18 +6090,140 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
6031
6090
|
}
|
|
6032
6091
|
if (!output.schemas && needSchema) data += generateSchemasInline ? generateSchemasInline() : generateModelsInline(builder.schemas);
|
|
6033
6092
|
data += `${implementation.trim()}\n`;
|
|
6034
|
-
if (
|
|
6035
|
-
|
|
6036
|
-
|
|
6093
|
+
if (!shouldDeinlineMocks) {
|
|
6094
|
+
const implementationMock = collapsedMockOutputs.map((m) => m.implementation).join("\n\n");
|
|
6095
|
+
const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, collapsedMockOutputs)) : implementationMock;
|
|
6096
|
+
if (collapsedMockOutputs.length > 0) {
|
|
6097
|
+
data += "\n\n";
|
|
6098
|
+
data += finalizedImplementationMock;
|
|
6099
|
+
}
|
|
6037
6100
|
}
|
|
6038
|
-
await writeGeneratedFile(
|
|
6039
|
-
|
|
6101
|
+
await writeGeneratedFile(targetPath, data);
|
|
6102
|
+
const extraPaths = [];
|
|
6103
|
+
if (shouldDeinlineMocks) {
|
|
6104
|
+
const seenMockIndexKeys = /* @__PURE__ */ new Set();
|
|
6105
|
+
const writtenMockEntries = [];
|
|
6106
|
+
for (const mockOutput of rawMockOutputs) {
|
|
6107
|
+
const rawEntry = output.mock.generators.find((g) => {
|
|
6108
|
+
if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
|
|
6109
|
+
return g.type === mockOutput.type;
|
|
6110
|
+
});
|
|
6111
|
+
if (!rawEntry) continue;
|
|
6112
|
+
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6113
|
+
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6114
|
+
const mockFilePath = nodePath.join(mockDir, filename + "." + mockExtension + extension);
|
|
6115
|
+
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6116
|
+
const importsMockForBuilder = schemasPath || mockDir !== dirname ? generateImportsForBuilder(output, mockOutput.imports, mockRelativeSchemasPath) : generateImportsForBuilder(output, mockOutput.imports.filter((imp) => !!imp.importPath), ".");
|
|
6117
|
+
let mockData = header;
|
|
6118
|
+
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
|
|
6119
|
+
mockData += builder.importsMock({
|
|
6120
|
+
implementation: finalizedMockImplementation,
|
|
6121
|
+
imports: importsMockForBuilder,
|
|
6122
|
+
projectName,
|
|
6123
|
+
hasSchemaDir: !!output.schemas,
|
|
6124
|
+
isAllowSyntheticDefaultImports,
|
|
6125
|
+
options: isFunction(rawEntry) ? void 0 : rawEntry
|
|
6126
|
+
});
|
|
6127
|
+
mockData += `\n${finalizedMockImplementation}`;
|
|
6128
|
+
await writeGeneratedFile(mockFilePath, mockData);
|
|
6129
|
+
extraPaths.push(mockFilePath);
|
|
6130
|
+
const indexKey = `${mockExtension}::${mockDir}`;
|
|
6131
|
+
if (!seenMockIndexKeys.has(indexKey)) {
|
|
6132
|
+
seenMockIndexKeys.add(indexKey);
|
|
6133
|
+
writtenMockEntries.push({
|
|
6134
|
+
extension: mockExtension,
|
|
6135
|
+
mockDir
|
|
6136
|
+
});
|
|
6137
|
+
}
|
|
6138
|
+
}
|
|
6139
|
+
if (output.mock.indexMockFiles) {
|
|
6140
|
+
const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
|
|
6141
|
+
for (const { extension: mockExt, mockDir } of writtenMockEntries) {
|
|
6142
|
+
const indexMockPath = nodePath.join(mockDir, `index.${mockExt}${extension}`);
|
|
6143
|
+
await writeGeneratedFile(indexMockPath, `export * from './${filename}.${mockExt}${importExtension}'\n`);
|
|
6144
|
+
extraPaths.push(indexMockPath);
|
|
6145
|
+
}
|
|
6146
|
+
}
|
|
6147
|
+
}
|
|
6148
|
+
return [targetPath, ...extraPaths];
|
|
6040
6149
|
} catch (error) {
|
|
6041
6150
|
const errorMsg = error instanceof Error ? error.message : "unknown error";
|
|
6042
6151
|
throw new Error(`Oups... 🍻. An Error occurred while writing file => ${errorMsg}`, { cause: error });
|
|
6043
6152
|
}
|
|
6044
6153
|
}
|
|
6045
6154
|
//#endregion
|
|
6155
|
+
//#region src/writers/mock-imports.ts
|
|
6156
|
+
/** Maps `components/schemas` names to consolidated index.faker import symbols. */
|
|
6157
|
+
function buildKnownSchemaFactoryImportSets(schemaNames) {
|
|
6158
|
+
const factoryNames = /* @__PURE__ */ new Set();
|
|
6159
|
+
const typeNames = /* @__PURE__ */ new Set();
|
|
6160
|
+
for (const name of schemaNames) {
|
|
6161
|
+
const typeName = pascal(name);
|
|
6162
|
+
factoryNames.add(`get${typeName}Mock`);
|
|
6163
|
+
typeNames.add(`${typeName}Mock`);
|
|
6164
|
+
}
|
|
6165
|
+
return {
|
|
6166
|
+
factoryNames,
|
|
6167
|
+
typeNames
|
|
6168
|
+
};
|
|
6169
|
+
}
|
|
6170
|
+
/**
|
|
6171
|
+
* Recover schema-factory imports referenced in generated mock bodies but
|
|
6172
|
+
* missing from the collected import list (e.g. after shared-array import
|
|
6173
|
+
* aggregation on large specs). Scans for `get<Schema>Mock()` calls and
|
|
6174
|
+
* `as <Schema>Mock` casts emitted by strict schema delegation (#3590).
|
|
6175
|
+
*
|
|
6176
|
+
* When `knownSets` is provided, only symbols that exist in the consolidated
|
|
6177
|
+
* schemas faker file are recovered — this avoids importing one-off split
|
|
6178
|
+
* response helper factories that live in the tag file itself.
|
|
6179
|
+
*/
|
|
6180
|
+
function collectSchemaFactoryImportsFromImplementation(implementation, knownSets) {
|
|
6181
|
+
const imports = [];
|
|
6182
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6183
|
+
for (const match of implementation.matchAll(/\b(get[A-Za-z0-9]+Mock)\(\)/g)) {
|
|
6184
|
+
const factoryName = match[1];
|
|
6185
|
+
if (knownSets && !knownSets.factoryNames.has(factoryName)) continue;
|
|
6186
|
+
const key = `value::${factoryName}`;
|
|
6187
|
+
if (seen.has(key)) continue;
|
|
6188
|
+
seen.add(key);
|
|
6189
|
+
imports.push({
|
|
6190
|
+
name: factoryName,
|
|
6191
|
+
values: true,
|
|
6192
|
+
schemaFactory: true
|
|
6193
|
+
});
|
|
6194
|
+
}
|
|
6195
|
+
for (const match of implementation.matchAll(/\bas ([A-Za-z0-9]+Mock)\b/g)) {
|
|
6196
|
+
const typeName = match[1];
|
|
6197
|
+
if (knownSets && !knownSets.typeNames.has(typeName)) continue;
|
|
6198
|
+
const key = `type::${typeName}`;
|
|
6199
|
+
if (seen.has(key)) continue;
|
|
6200
|
+
seen.add(key);
|
|
6201
|
+
imports.push({
|
|
6202
|
+
name: typeName,
|
|
6203
|
+
values: false,
|
|
6204
|
+
schemaFactory: true
|
|
6205
|
+
});
|
|
6206
|
+
}
|
|
6207
|
+
return imports;
|
|
6208
|
+
}
|
|
6209
|
+
function mergeGeneratorImports(...groups) {
|
|
6210
|
+
const merged = /* @__PURE__ */ new Map();
|
|
6211
|
+
for (const group of groups) for (const imp of group) {
|
|
6212
|
+
const key = `${imp.name}::${imp.alias ?? ""}`;
|
|
6213
|
+
const existing = merged.get(key);
|
|
6214
|
+
if (!existing) {
|
|
6215
|
+
merged.set(key, imp);
|
|
6216
|
+
continue;
|
|
6217
|
+
}
|
|
6218
|
+
if (!existing.values && imp.values) merged.set(key, imp);
|
|
6219
|
+
}
|
|
6220
|
+
return [...merged.values()];
|
|
6221
|
+
}
|
|
6222
|
+
/** Recover missing index.faker imports when `schemas: true` is enabled. */
|
|
6223
|
+
function collectRecoveredSchemaFactoryImports(implementation, componentSchemaNames) {
|
|
6224
|
+
return collectSchemaFactoryImportsFromImplementation(implementation, buildKnownSchemaFactoryImportSets(componentSchemaNames));
|
|
6225
|
+
}
|
|
6226
|
+
//#endregion
|
|
6046
6227
|
//#region src/writers/split-mode.ts
|
|
6047
6228
|
async function writeSplitMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
|
|
6048
6229
|
try {
|
|
@@ -6053,7 +6234,8 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
6053
6234
|
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
6054
6235
|
let implementationData = header;
|
|
6055
6236
|
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6056
|
-
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.
|
|
6237
|
+
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + getImportExtension(extension, output.tsconfig);
|
|
6238
|
+
const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : nodePath.join(dirname, filename + ".schemas" + getImportExtension(extension, output.tsconfig));
|
|
6057
6239
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
6058
6240
|
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
6059
6241
|
implementationData += builder.imports({
|
|
@@ -6094,34 +6276,49 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
6094
6276
|
const implementationPath = nodePath.join(dirname, implementationFilename);
|
|
6095
6277
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
6096
6278
|
const mockPaths = [];
|
|
6097
|
-
const
|
|
6279
|
+
const seenMockIndexKeys = /* @__PURE__ */ new Set();
|
|
6280
|
+
const writtenMockEntries = [];
|
|
6098
6281
|
for (const mockOutput of mockOutputs) {
|
|
6099
|
-
const
|
|
6100
|
-
|
|
6101
|
-
|
|
6282
|
+
const rawEntry = output.mock.generators.find((g) => {
|
|
6283
|
+
if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
|
|
6284
|
+
return g.type === mockOutput.type;
|
|
6285
|
+
});
|
|
6286
|
+
if (!rawEntry) continue;
|
|
6287
|
+
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6288
|
+
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6289
|
+
const mockFilePath = nodePath.join(mockDir, filename + "." + mockExtension + extension);
|
|
6290
|
+
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6291
|
+
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6292
|
+
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6293
|
+
const recoveredSchemaFactoryImports = !isFunction(rawEntry) && rawEntry.type === OutputMockType.FAKER && rawEntry.schemas === true && output.schemas ? collectRecoveredSchemaFactoryImports(finalizedMockImplementation, builder.schemas.filter((s) => s.schema).map((s) => s.name)) : [];
|
|
6294
|
+
const importsMockForBuilder = generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames), mockRelativeSchemasPath);
|
|
6102
6295
|
let mockData = header;
|
|
6103
|
-
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
|
|
6104
6296
|
mockData += builder.importsMock({
|
|
6105
6297
|
implementation: finalizedMockImplementation,
|
|
6106
6298
|
imports: importsMockForBuilder,
|
|
6107
6299
|
projectName,
|
|
6108
6300
|
hasSchemaDir: !!output.schemas,
|
|
6109
6301
|
isAllowSyntheticDefaultImports,
|
|
6110
|
-
options:
|
|
6302
|
+
options: isFunction(rawEntry) ? void 0 : rawEntry
|
|
6111
6303
|
});
|
|
6112
6304
|
mockData += `\n${finalizedMockImplementation}`;
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6305
|
+
await writeGeneratedFile(mockFilePath, mockData);
|
|
6306
|
+
mockPaths.push(mockFilePath);
|
|
6307
|
+
const indexKey = `${mockExtension}::${mockDir}`;
|
|
6308
|
+
if (!seenMockIndexKeys.has(indexKey)) {
|
|
6309
|
+
seenMockIndexKeys.add(indexKey);
|
|
6310
|
+
writtenMockEntries.push({
|
|
6311
|
+
extension: mockExtension,
|
|
6312
|
+
mockDir
|
|
6313
|
+
});
|
|
6314
|
+
}
|
|
6118
6315
|
}
|
|
6119
6316
|
const indexMockPaths = [];
|
|
6120
6317
|
if (output.mock.indexMockFiles) {
|
|
6121
6318
|
const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
|
|
6122
|
-
for (const
|
|
6123
|
-
const indexMockPath = nodePath.join(
|
|
6124
|
-
await writeGeneratedFile(indexMockPath, `export * from './${filename}.${
|
|
6319
|
+
for (const { extension: mockExt, mockDir } of writtenMockEntries) {
|
|
6320
|
+
const indexMockPath = nodePath.join(mockDir, `index.${mockExt}${extension}`);
|
|
6321
|
+
await writeGeneratedFile(indexMockPath, `export * from './${filename}.${mockExt}${importExtension}'\n`);
|
|
6125
6322
|
indexMockPaths.push(indexMockPath);
|
|
6126
6323
|
}
|
|
6127
6324
|
}
|
|
@@ -6165,14 +6362,17 @@ function flattenMockOutput(full) {
|
|
|
6165
6362
|
type: full.type,
|
|
6166
6363
|
implementation: full.implementation.function + full.implementation.handler,
|
|
6167
6364
|
imports: full.imports,
|
|
6168
|
-
strictMockSchemaTypeNames: full.strictMockSchemaTypeNames
|
|
6365
|
+
strictMockSchemaTypeNames: full.strictMockSchemaTypeNames,
|
|
6366
|
+
strictMockSchemaKinds: full.strictMockSchemaKinds
|
|
6169
6367
|
};
|
|
6170
6368
|
}
|
|
6171
6369
|
function mergeOperationMockOutputs(accMockOutputs, opMockOutputs) {
|
|
6172
6370
|
const result = accMockOutputs.map((m) => ({
|
|
6173
6371
|
type: m.type,
|
|
6174
6372
|
implementation: { ...m.implementation },
|
|
6175
|
-
imports: [...m.imports]
|
|
6373
|
+
imports: [...m.imports],
|
|
6374
|
+
strictMockSchemaTypeNames: m.strictMockSchemaTypeNames ? [...m.strictMockSchemaTypeNames] : void 0,
|
|
6375
|
+
strictMockSchemaKinds: m.strictMockSchemaKinds ? { ...m.strictMockSchemaKinds } : void 0
|
|
6176
6376
|
}));
|
|
6177
6377
|
for (const op of opMockOutputs) {
|
|
6178
6378
|
let acc = result.find((m) => m.type === op.type);
|
|
@@ -6182,6 +6382,10 @@ function mergeOperationMockOutputs(accMockOutputs, opMockOutputs) {
|
|
|
6182
6382
|
}
|
|
6183
6383
|
acc.imports.push(...op.imports);
|
|
6184
6384
|
if (op.strictMockSchemaTypeNames?.length) acc.strictMockSchemaTypeNames = [...new Set([...acc.strictMockSchemaTypeNames ?? [], ...op.strictMockSchemaTypeNames])];
|
|
6385
|
+
if (op.strictMockSchemaKinds) acc.strictMockSchemaKinds = {
|
|
6386
|
+
...acc.strictMockSchemaKinds,
|
|
6387
|
+
...op.strictMockSchemaKinds
|
|
6388
|
+
};
|
|
6185
6389
|
acc.implementation.function += op.implementation.function;
|
|
6186
6390
|
acc.implementation.handler += op.implementation.handler;
|
|
6187
6391
|
if (op.implementation.handlerName) {
|
|
@@ -6199,7 +6403,9 @@ function initialMockOutputsForOperation(op) {
|
|
|
6199
6403
|
handler: m.implementation.handler,
|
|
6200
6404
|
handlerName: m.implementation.handlerName ? " " + m.implementation.handlerName + "()" : ""
|
|
6201
6405
|
},
|
|
6202
|
-
imports: [...m.imports]
|
|
6406
|
+
imports: [...m.imports],
|
|
6407
|
+
strictMockSchemaTypeNames: m.strictMockSchemaTypeNames ? [...m.strictMockSchemaTypeNames] : void 0,
|
|
6408
|
+
strictMockSchemaKinds: m.strictMockSchemaKinds ? { ...m.strictMockSchemaKinds } : void 0
|
|
6203
6409
|
}));
|
|
6204
6410
|
}
|
|
6205
6411
|
function generateTargetTags(currentAcc, operation) {
|
|
@@ -6281,7 +6487,9 @@ function generateTargetForTags(builder, options) {
|
|
|
6281
6487
|
handler: m.implementation.handlerName ? m.implementation.handler + header.implementationMock + m.implementation.handlerName + footer.implementationMock : m.implementation.handler,
|
|
6282
6488
|
handlerName: m.implementation.handlerName
|
|
6283
6489
|
},
|
|
6284
|
-
imports: m.imports
|
|
6490
|
+
imports: m.imports,
|
|
6491
|
+
strictMockSchemaTypeNames: m.strictMockSchemaTypeNames,
|
|
6492
|
+
strictMockSchemaKinds: m.strictMockSchemaKinds
|
|
6285
6493
|
}));
|
|
6286
6494
|
transformed[tag] = {
|
|
6287
6495
|
implementation: header.implementation + target.implementation + footer.implementation,
|
|
@@ -6315,23 +6523,17 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6315
6523
|
});
|
|
6316
6524
|
const target = generateTargetForTags(builder, output);
|
|
6317
6525
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
6318
|
-
|
|
6319
|
-
const
|
|
6320
|
-
const
|
|
6321
|
-
|
|
6322
|
-
const ext = getMockFileExtensionByTypeName(entry);
|
|
6323
|
-
const indexPath = nodePath.join(dirname, `index.${ext}${extension}`);
|
|
6324
|
-
indexFilePathsByType.set(ext, indexPath);
|
|
6325
|
-
await fs$1.outputFile(indexPath, "");
|
|
6326
|
-
}
|
|
6327
|
-
const tagEntries = Object.entries(target);
|
|
6526
|
+
const mockIndexEntries = [];
|
|
6527
|
+
const seenMockIndexKeys = /* @__PURE__ */ new Set();
|
|
6528
|
+
const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : nodePath.join(dirname, filename + ".schemas" + getImportExtension(extension, output.tsconfig));
|
|
6529
|
+
const tagEntries = Object.entries(target).toSorted(([a], [b]) => a.localeCompare(b));
|
|
6328
6530
|
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
6329
6531
|
try {
|
|
6330
6532
|
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
|
|
6331
6533
|
let implementationData = header;
|
|
6332
6534
|
const importerPath = nodePath.join(dirname, tag, tag + extension);
|
|
6333
6535
|
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6334
|
-
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + extension.
|
|
6536
|
+
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + getImportExtension(extension, output.tsconfig);
|
|
6335
6537
|
const tagNames = new Set(tagEntries.map(([t]) => t));
|
|
6336
6538
|
const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
|
|
6337
6539
|
const importsForBuilder = generateImportsForBuilder(output, imports.map((imp) => {
|
|
@@ -6408,10 +6610,19 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6408
6610
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
6409
6611
|
const mockPaths = [];
|
|
6410
6612
|
for (const mockOutput of mockOutputs) {
|
|
6411
|
-
const
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6613
|
+
const rawEntry = output.mock.generators.find((g) => {
|
|
6614
|
+
if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
|
|
6615
|
+
return g.type === mockOutput.type;
|
|
6616
|
+
});
|
|
6617
|
+
if (!rawEntry) continue;
|
|
6618
|
+
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6619
|
+
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6620
|
+
const mockFilePath = nodePath.join(mockDir, tag, tag + "." + mockExtension + extension);
|
|
6621
|
+
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6622
|
+
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6623
|
+
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6624
|
+
const recoveredSchemaFactoryImports = !isFunction(rawEntry) && rawEntry.type === OutputMockType.FAKER && rawEntry.schemas === true && output.schemas ? collectRecoveredSchemaFactoryImports(finalizedMockImplementation, builder.schemas.filter((s) => s.schema).map((s) => s.name)) : [];
|
|
6625
|
+
const importsMockForBuilder = generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames), mockRelativeSchemasPath);
|
|
6415
6626
|
let mockData = header;
|
|
6416
6627
|
mockData += builder.importsMock({
|
|
6417
6628
|
implementation: finalizedMockImplementation,
|
|
@@ -6419,12 +6630,23 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6419
6630
|
projectName,
|
|
6420
6631
|
hasSchemaDir: !!output.schemas,
|
|
6421
6632
|
isAllowSyntheticDefaultImports,
|
|
6422
|
-
options:
|
|
6633
|
+
options: isFunction(rawEntry) ? void 0 : rawEntry
|
|
6423
6634
|
});
|
|
6424
6635
|
mockData += `\n${finalizedMockImplementation}`;
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6636
|
+
await writeGeneratedFile(mockFilePath, mockData);
|
|
6637
|
+
mockPaths.push(mockFilePath);
|
|
6638
|
+
const indexKey = `${mockExtension}::${mockDir}`;
|
|
6639
|
+
let indexEntry = mockIndexEntries.find((e) => e.ext === mockExtension && e.mockDir === mockDir);
|
|
6640
|
+
if (!indexEntry) {
|
|
6641
|
+
indexEntry = {
|
|
6642
|
+
ext: mockExtension,
|
|
6643
|
+
mockDir,
|
|
6644
|
+
tags: []
|
|
6645
|
+
};
|
|
6646
|
+
mockIndexEntries.push(indexEntry);
|
|
6647
|
+
seenMockIndexKeys.add(indexKey);
|
|
6648
|
+
}
|
|
6649
|
+
if (!indexEntry.tags.includes(tag)) indexEntry.tags.push(tag);
|
|
6428
6650
|
}
|
|
6429
6651
|
return [
|
|
6430
6652
|
implementationPath,
|
|
@@ -6435,17 +6657,14 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6435
6657
|
throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}`, { cause: error });
|
|
6436
6658
|
}
|
|
6437
6659
|
}));
|
|
6438
|
-
if (output.mock.indexMockFiles)
|
|
6439
|
-
const
|
|
6440
|
-
const
|
|
6441
|
-
|
|
6442
|
-
const indexContent = tagEntries.map(([tag]) => {
|
|
6443
|
-
const localMockPath = joinSafe("./", tag, tag + "." + ext);
|
|
6660
|
+
if (output.mock.indexMockFiles) {
|
|
6661
|
+
const mockImportExtension = getImportExtension(extension, output.tsconfig);
|
|
6662
|
+
for (const { ext, mockDir, tags } of mockIndexEntries) await writeGeneratedFile(nodePath.join(mockDir, `index.${ext}${extension}`), tags.toSorted((a, b) => a.localeCompare(b)).map((tag) => {
|
|
6663
|
+
const localMockPath = joinSafe("./", tag, tag + "." + ext + mockImportExtension);
|
|
6444
6664
|
return ext === OutputMockType.MSW ? `export { get${pascal(tag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
|
|
6445
|
-
}).join("");
|
|
6446
|
-
await fs$1.appendFile(indexFilePath, indexContent);
|
|
6665
|
+
}).join(""));
|
|
6447
6666
|
}
|
|
6448
|
-
return [...new Set([...
|
|
6667
|
+
return [...new Set([...output.mock.indexMockFiles ? mockIndexEntries.map(({ mockDir, ext }) => nodePath.join(mockDir, `index.${ext}${extension}`)) : [], ...generatedFilePathsArray.flat()])];
|
|
6449
6668
|
}
|
|
6450
6669
|
//#endregion
|
|
6451
6670
|
//#region src/writers/tags-mode.ts
|
|
@@ -6456,25 +6675,30 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6456
6675
|
});
|
|
6457
6676
|
const target = generateTargetForTags(builder, output);
|
|
6458
6677
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
6459
|
-
|
|
6678
|
+
const shouldDeinlineMocks = hasAnyMockPath(output.mock);
|
|
6679
|
+
const mockIndexEntries = [];
|
|
6680
|
+
const seenMockIndexKeys = /* @__PURE__ */ new Set();
|
|
6681
|
+
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6682
|
+
const schemasPathRelative = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + getImportExtension(extension, output.tsconfig);
|
|
6683
|
+
const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : nodePath.join(dirname, filename + ".schemas" + getImportExtension(extension, output.tsconfig));
|
|
6684
|
+
const tagEntries = Object.entries(target).toSorted(([a], [b]) => a.localeCompare(b));
|
|
6685
|
+
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
6460
6686
|
try {
|
|
6461
6687
|
const { imports, implementation, mockOutputs: rawMockOutputs, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer, paramsFilter } = target;
|
|
6462
|
-
const mockOutputs = collapseInlineMockOutputs(rawMockOutputs);
|
|
6463
|
-
const importsMock = mockOutputs.flatMap((m) => m.imports);
|
|
6464
|
-
const implementationMock = mockOutputs.map((m) => m.implementation).join("\n\n");
|
|
6465
|
-
const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, mockOutputs)) : implementationMock;
|
|
6466
|
-
let data = header;
|
|
6467
|
-
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6468
|
-
const schemasPathRelative = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
|
|
6469
6688
|
const normalizedImports = imports.filter((imp) => {
|
|
6470
6689
|
const searchWords = [imp.alias, imp.name].filter((part) => Boolean(part?.length)).map((part) => escapeRegExp(part)).join("|");
|
|
6471
6690
|
if (!searchWords) return false;
|
|
6472
6691
|
return new RegExp(String.raw`\b(${searchWords})\b`, "g").test(implementation);
|
|
6473
6692
|
}).map((imp) => ({ ...imp }));
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6693
|
+
const collapsedMockOutputs = shouldDeinlineMocks ? [] : collapseInlineMockOutputs(rawMockOutputs);
|
|
6694
|
+
let data = header;
|
|
6695
|
+
if (!shouldDeinlineMocks) {
|
|
6696
|
+
const importsMock = collapsedMockOutputs.flatMap((m) => m.imports);
|
|
6697
|
+
for (const mockImport of importsMock) {
|
|
6698
|
+
const matchingImport = normalizedImports.find((imp) => imp.name === mockImport.name && (imp.alias ?? "") === (mockImport.alias ?? ""));
|
|
6699
|
+
if (!matchingImport) continue;
|
|
6700
|
+
if (!!mockImport.values || !!mockImport.isConstant || !!mockImport.default || !!mockImport.namespaceImport || !!mockImport.syntheticDefaultImport) matchingImport.values = true;
|
|
6701
|
+
}
|
|
6478
6702
|
}
|
|
6479
6703
|
const importsForBuilder = generateImportsForBuilder(output, normalizedImports, schemasPathRelative);
|
|
6480
6704
|
data += builder.imports({
|
|
@@ -6490,7 +6714,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6490
6714
|
packageJson: output.packageJson,
|
|
6491
6715
|
output
|
|
6492
6716
|
});
|
|
6493
|
-
for (const mockOutput of
|
|
6717
|
+
if (!shouldDeinlineMocks) for (const mockOutput of collapsedMockOutputs) {
|
|
6494
6718
|
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
6495
6719
|
const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? ""))), schemasPathRelative);
|
|
6496
6720
|
data += builder.importsMock({
|
|
@@ -6524,17 +6748,78 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6524
6748
|
data += "\n";
|
|
6525
6749
|
}
|
|
6526
6750
|
data += implementation;
|
|
6527
|
-
if (
|
|
6528
|
-
|
|
6529
|
-
|
|
6751
|
+
if (!shouldDeinlineMocks) {
|
|
6752
|
+
const implementationMock = collapsedMockOutputs.map((m) => m.implementation).join("\n\n");
|
|
6753
|
+
const finalizedImplementationMock = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementationMock, getFinalizeMockImplementationOptions(output, collapsedMockOutputs)) : implementationMock;
|
|
6754
|
+
if (collapsedMockOutputs.length > 0) {
|
|
6755
|
+
data += "\n\n";
|
|
6756
|
+
data += finalizedImplementationMock;
|
|
6757
|
+
}
|
|
6530
6758
|
}
|
|
6531
|
-
const
|
|
6759
|
+
const kebabTag = kebab(tag);
|
|
6760
|
+
const implementationPath = nodePath.join(dirname, `${kebabTag}${extension}`);
|
|
6532
6761
|
await writeGeneratedFile(implementationPath, data);
|
|
6533
|
-
|
|
6762
|
+
const extraPaths = [];
|
|
6763
|
+
if (shouldDeinlineMocks) for (const mockOutput of rawMockOutputs) {
|
|
6764
|
+
const rawEntry = output.mock.generators.find((g) => {
|
|
6765
|
+
if (isFunction(g)) return mockOutput.type === OutputMockType.MSW;
|
|
6766
|
+
return g.type === mockOutput.type;
|
|
6767
|
+
});
|
|
6768
|
+
if (!rawEntry) continue;
|
|
6769
|
+
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6770
|
+
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6771
|
+
const mockFilePath = nodePath.join(mockDir, kebabTag, kebabTag + "." + mockExtension + extension);
|
|
6772
|
+
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6773
|
+
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6774
|
+
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6775
|
+
const recoveredSchemaFactoryImports = !isFunction(rawEntry) && rawEntry.type === OutputMockType.FAKER && rawEntry.schemas === true && output.schemas ? collectRecoveredSchemaFactoryImports(finalizedMockImplementation, builder.schemas.filter((s) => s.schema).map((s) => s.name)) : [];
|
|
6776
|
+
const importsMockForBuilder = generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames), mockRelativeSchemasPath);
|
|
6777
|
+
let mockData = header;
|
|
6778
|
+
mockData += builder.importsMock({
|
|
6779
|
+
implementation: finalizedMockImplementation,
|
|
6780
|
+
imports: importsMockForBuilder,
|
|
6781
|
+
projectName,
|
|
6782
|
+
hasSchemaDir: !!output.schemas,
|
|
6783
|
+
isAllowSyntheticDefaultImports,
|
|
6784
|
+
options: isFunction(rawEntry) ? void 0 : rawEntry
|
|
6785
|
+
});
|
|
6786
|
+
mockData += `\n${finalizedMockImplementation}`;
|
|
6787
|
+
await writeGeneratedFile(mockFilePath, mockData);
|
|
6788
|
+
extraPaths.push(mockFilePath);
|
|
6789
|
+
const indexKey = `${mockExtension}::${mockDir}`;
|
|
6790
|
+
let indexEntry = mockIndexEntries.find((e) => e.ext === mockExtension && e.mockDir === mockDir);
|
|
6791
|
+
if (!indexEntry) {
|
|
6792
|
+
indexEntry = {
|
|
6793
|
+
ext: mockExtension,
|
|
6794
|
+
mockDir,
|
|
6795
|
+
tags: []
|
|
6796
|
+
};
|
|
6797
|
+
mockIndexEntries.push(indexEntry);
|
|
6798
|
+
seenMockIndexKeys.add(indexKey);
|
|
6799
|
+
}
|
|
6800
|
+
if (!indexEntry.tags.includes(kebabTag)) indexEntry.tags.push(kebabTag);
|
|
6801
|
+
}
|
|
6802
|
+
return [
|
|
6803
|
+
implementationPath,
|
|
6804
|
+
...schemasPath ? [schemasPath] : [],
|
|
6805
|
+
...extraPaths
|
|
6806
|
+
];
|
|
6534
6807
|
} catch (error) {
|
|
6535
6808
|
throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${String(error)}`, { cause: error });
|
|
6536
6809
|
}
|
|
6537
|
-
}))
|
|
6810
|
+
}));
|
|
6811
|
+
if (shouldDeinlineMocks && output.mock.indexMockFiles) {
|
|
6812
|
+
const mockImportExtension = getImportExtension(extension, output.tsconfig);
|
|
6813
|
+
for (const { ext, mockDir, tags } of mockIndexEntries) {
|
|
6814
|
+
const indexPath = nodePath.join(mockDir, `index.${ext}${extension}`);
|
|
6815
|
+
await writeGeneratedFile(indexPath, tags.toSorted((a, b) => a.localeCompare(b)).map((kebabTag) => {
|
|
6816
|
+
const localMockPath = joinSafe("./", kebabTag, kebabTag + "." + ext + mockImportExtension);
|
|
6817
|
+
return ext === OutputMockType.MSW ? `export { get${pascal(kebabTag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
|
|
6818
|
+
}).join(""));
|
|
6819
|
+
generatedFilePathsArray.push([indexPath]);
|
|
6820
|
+
}
|
|
6821
|
+
}
|
|
6822
|
+
return generatedFilePathsArray.flat();
|
|
6538
6823
|
}
|
|
6539
6824
|
//#endregion
|
|
6540
6825
|
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, buildDynamicScope, camel, collectReferencedComponents, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicAnchorToParamName, dynamicAnchorsToUniqueParamNames, dynamicImport, escape, escapeRegExp, extractBoundAliasInfo, filterByContentType, filteredVerbs, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFactory, 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, getDynamicAnchorName, 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, getSchemasImportPath, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBinaryScalarSchema, isBoolean, isComponentRef, isDirectory, isDynamicReference, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, jsStringLiteralEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, makeRouteSafe, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveDynamicRef, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, wrapRouteParameters, writeGeneratedFile, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|