@orval/core 8.18.0 → 8.19.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 +203 -19
- package/dist/index.mjs +414 -164
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./chunk-8H4AJuhK.mjs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
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
|
-
import
|
|
5
|
+
import path from "node:path";
|
|
6
6
|
import { compare } from "compare-versions";
|
|
7
7
|
import debug from "debug";
|
|
8
8
|
import { pathToFileURL } from "node:url";
|
|
@@ -168,7 +168,7 @@ function isDynamicReference(obj) {
|
|
|
168
168
|
* @param pathValue - Path string to inspect.
|
|
169
169
|
*/
|
|
170
170
|
function isDirectory(pathValue) {
|
|
171
|
-
return !
|
|
171
|
+
return !path.extname(pathValue);
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
174
|
* Type guard for plain objects created with `{}` or `new Object()`.
|
|
@@ -560,8 +560,8 @@ async function dynamicImport(toImport, from = process.cwd(), takeDefault = true)
|
|
|
560
560
|
if (!toImport) return toImport;
|
|
561
561
|
try {
|
|
562
562
|
if (isString(toImport)) {
|
|
563
|
-
const filePath =
|
|
564
|
-
const extension =
|
|
563
|
+
const filePath = path.resolve(from, toImport);
|
|
564
|
+
const extension = path.extname(filePath);
|
|
565
565
|
if (TS_MODULE_EXTENSIONS.has(extension)) {
|
|
566
566
|
const data = await createJiti(from, { interopDefault: true }).import(filePath);
|
|
567
567
|
if (takeDefault && (isObject(data) || isModule(data)) && data.default) return data.default;
|
|
@@ -586,14 +586,14 @@ function getExtension(path) {
|
|
|
586
586
|
//#region src/utils/file.ts
|
|
587
587
|
function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
|
|
588
588
|
const isDir = isDirectory(target);
|
|
589
|
-
const filePath = isDir ?
|
|
589
|
+
const filePath = isDir ? path.join(target, backupFilename + extension) : target;
|
|
590
590
|
return {
|
|
591
591
|
path: filePath,
|
|
592
592
|
pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
|
|
593
593
|
extension,
|
|
594
594
|
isDirectory: isDir,
|
|
595
|
-
dirname:
|
|
596
|
-
filename:
|
|
595
|
+
dirname: path.dirname(filePath),
|
|
596
|
+
filename: path.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
|
|
597
597
|
};
|
|
598
598
|
}
|
|
599
599
|
async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
@@ -804,10 +804,10 @@ var path_exports = /* @__PURE__ */ __exportAll({
|
|
|
804
804
|
toUnix: () => toUnix
|
|
805
805
|
});
|
|
806
806
|
function isAbsolute(value) {
|
|
807
|
-
return
|
|
807
|
+
return path.isAbsolute(value);
|
|
808
808
|
}
|
|
809
809
|
function resolve(...args) {
|
|
810
|
-
return toUnix(
|
|
810
|
+
return toUnix(path.resolve(...args));
|
|
811
811
|
}
|
|
812
812
|
function toUnix(value) {
|
|
813
813
|
value = value.replaceAll("\\", "/");
|
|
@@ -815,13 +815,13 @@ function toUnix(value) {
|
|
|
815
815
|
return value;
|
|
816
816
|
}
|
|
817
817
|
function join(...args) {
|
|
818
|
-
return toUnix(
|
|
818
|
+
return toUnix(path.join(...args.map((a) => toUnix(a))));
|
|
819
819
|
}
|
|
820
820
|
/**
|
|
821
821
|
* Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
|
|
822
822
|
*/
|
|
823
823
|
function relativeSafe(from, to) {
|
|
824
|
-
return normalizeSafe(`./${toUnix(
|
|
824
|
+
return normalizeSafe(`./${toUnix(path.relative(toUnix(from), toUnix(to)))}`);
|
|
825
825
|
}
|
|
826
826
|
function getSchemaFileName(path) {
|
|
827
827
|
return path.replace(`.${getExtension(path)}`, "").slice(path.lastIndexOf("/") + 1);
|
|
@@ -829,13 +829,13 @@ function getSchemaFileName(path) {
|
|
|
829
829
|
function normalizeSafe(value) {
|
|
830
830
|
let result;
|
|
831
831
|
value = toUnix(value);
|
|
832
|
-
result = toUnix(
|
|
832
|
+
result = toUnix(path.normalize(value));
|
|
833
833
|
if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
834
834
|
else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
|
|
835
835
|
return result;
|
|
836
836
|
}
|
|
837
837
|
function joinSafe(...values) {
|
|
838
|
-
let result = toUnix(
|
|
838
|
+
let result = toUnix(path.join(...values.map((v) => toUnix(v))));
|
|
839
839
|
if (values.length > 0) {
|
|
840
840
|
const firstValue = toUnix(values[0]);
|
|
841
841
|
if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
@@ -866,14 +866,14 @@ function joinSafe(...values) {
|
|
|
866
866
|
* @returns The relative import path string.
|
|
867
867
|
*/
|
|
868
868
|
function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileExtension = false) {
|
|
869
|
-
if (!
|
|
870
|
-
if (!
|
|
871
|
-
const importerDir =
|
|
872
|
-
const relativePath =
|
|
873
|
-
let posixPath =
|
|
869
|
+
if (!path.isAbsolute(importerFilePath)) throw new Error(`'importerFilePath' is not an absolute path. "${importerFilePath}"`);
|
|
870
|
+
if (!path.isAbsolute(exporterFilePath)) throw new Error(`'exporterFilePath' is not an absolute path. "${exporterFilePath}"`);
|
|
871
|
+
const importerDir = path.dirname(importerFilePath);
|
|
872
|
+
const relativePath = path.relative(importerDir, exporterFilePath);
|
|
873
|
+
let posixPath = path.posix.join(...relativePath.split(path.sep));
|
|
874
874
|
if (!posixPath.startsWith("./") && !posixPath.startsWith("../")) posixPath = `./${posixPath}`;
|
|
875
875
|
if (!includeFileExtension) {
|
|
876
|
-
const ext =
|
|
876
|
+
const ext = path.extname(posixPath);
|
|
877
877
|
if (ext && posixPath.endsWith(ext)) posixPath = posixPath.slice(0, -ext.length);
|
|
878
878
|
}
|
|
879
879
|
return posixPath;
|
|
@@ -882,20 +882,20 @@ function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileEx
|
|
|
882
882
|
//#region src/utils/resolve-version.ts
|
|
883
883
|
function resolveInstalledVersion(packageName, fromDir) {
|
|
884
884
|
try {
|
|
885
|
-
const require = createRequire(
|
|
885
|
+
const require = createRequire(path.join(fromDir, "noop.js"));
|
|
886
886
|
try {
|
|
887
887
|
return require(`${packageName}/package.json`).version;
|
|
888
888
|
} catch (directError) {
|
|
889
889
|
if (directError instanceof Error && "code" in directError && directError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
|
|
890
890
|
const entryPath = require.resolve(packageName);
|
|
891
|
-
let dir =
|
|
892
|
-
while (dir !==
|
|
893
|
-
const pkgPath =
|
|
891
|
+
let dir = path.dirname(entryPath);
|
|
892
|
+
while (dir !== path.parse(dir).root) {
|
|
893
|
+
const pkgPath = path.join(dir, "package.json");
|
|
894
894
|
if (existsSync(pkgPath)) {
|
|
895
895
|
const pkgData = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
896
896
|
if (pkgData.name === packageName) return pkgData.version;
|
|
897
897
|
}
|
|
898
|
-
dir =
|
|
898
|
+
dir = path.dirname(dir);
|
|
899
899
|
}
|
|
900
900
|
return;
|
|
901
901
|
}
|
|
@@ -1159,6 +1159,55 @@ function dedupeUnionType(unionType) {
|
|
|
1159
1159
|
return [...new Set(parts)].join(" | ");
|
|
1160
1160
|
}
|
|
1161
1161
|
//#endregion
|
|
1162
|
+
//#region src/utils/tags.ts
|
|
1163
|
+
/**
|
|
1164
|
+
* Canonical bucket key for a single OpenAPI tag.
|
|
1165
|
+
*
|
|
1166
|
+
* In `tags` / `tags-split` mode operations are routed into files by their first
|
|
1167
|
+
* tag. This function is the **single source of truth** for turning a tag (or a
|
|
1168
|
+
* missing tag) into the key that identifies that file bucket. Every place that
|
|
1169
|
+
* groups operations by tag, derives a per-tag file/directory name, or checks
|
|
1170
|
+
* whether an operation belongs to a tag MUST go through here so that the
|
|
1171
|
+
* "build the key" side and the "look the key up" side can never disagree.
|
|
1172
|
+
*
|
|
1173
|
+
* The result is `kebab`-cased. `kebab` is idempotent
|
|
1174
|
+
* (`kebab(kebab(x)) === kebab(x)`), so it is always safe to call this on a value
|
|
1175
|
+
* that is already a canonical key. Other case functions (`camel`, `pascal`) are
|
|
1176
|
+
* NOT safe here: they do not round-trip through the bucket key for tags
|
|
1177
|
+
* containing acronyms or spaces (e.g. `"AB Widget"`), which is exactly the class
|
|
1178
|
+
* of bug this module exists to prevent.
|
|
1179
|
+
*
|
|
1180
|
+
* Missing or empty tags map to the implicit {@link DefaultTag} bucket.
|
|
1181
|
+
*/
|
|
1182
|
+
function getTagKey(tag) {
|
|
1183
|
+
const normalizedTag = tag?.trim();
|
|
1184
|
+
return kebab(normalizedTag ? normalizedTag : DefaultTag);
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Canonical bucket key for an operation, derived from its primary (first) tag.
|
|
1188
|
+
*
|
|
1189
|
+
* Untagged operations resolve to the {@link DefaultTag} bucket.
|
|
1190
|
+
*/
|
|
1191
|
+
function getOperationTagKey(operation) {
|
|
1192
|
+
return getTagKey(operation.tags[0]);
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Whether an operation belongs to the given tag bucket.
|
|
1196
|
+
*
|
|
1197
|
+
* Both sides are normalised through {@link getTagKey}, so the comparison is
|
|
1198
|
+
* correct regardless of how `tagKey` was spelled or cased by the caller. An
|
|
1199
|
+
* absent (`undefined`) `tagKey` matches every operation (the "no tag filter"
|
|
1200
|
+
* case); an empty/whitespace `tagKey` is normalised to the {@link DefaultTag}
|
|
1201
|
+
* bucket like any other tag.
|
|
1202
|
+
*
|
|
1203
|
+
* Prefer this over hand-rolling `operation.tags[0] === tagKey`: a raw tag
|
|
1204
|
+
* compared against a canonical key silently fails for multi-word/acronym tags.
|
|
1205
|
+
*/
|
|
1206
|
+
function isOperationInTagBucket(operation, tagKey) {
|
|
1207
|
+
if (tagKey == null) return true;
|
|
1208
|
+
return getOperationTagKey(operation) === getTagKey(tagKey);
|
|
1209
|
+
}
|
|
1210
|
+
//#endregion
|
|
1162
1211
|
//#region src/utils/tsconfig.ts
|
|
1163
1212
|
function isSyntheticDefaultImportsAllow(config) {
|
|
1164
1213
|
if (!config) return true;
|
|
@@ -2486,6 +2535,52 @@ function buildDynamicScope(schemaName, schema, context) {
|
|
|
2486
2535
|
return scope;
|
|
2487
2536
|
}
|
|
2488
2537
|
/**
|
|
2538
|
+
* Build dynamic scope entries for an **anonymous inline** subschema that declares
|
|
2539
|
+
* `$dynamicAnchor` without a `$ref` (e.g. inside `allOf`, `items`, nested props).
|
|
2540
|
+
*
|
|
2541
|
+
* Unlike {@link buildDynamicScope}, entries carry the concrete `inlineSchema` so
|
|
2542
|
+
* that a descendant `$dynamicRef` resolves to the inline override rather than the
|
|
2543
|
+
* outer/global component. Used when `dereference` enters a subschema without a
|
|
2544
|
+
* named component `$ref`.
|
|
2545
|
+
*
|
|
2546
|
+
* Scope of handling (deliberate, see #3492):
|
|
2547
|
+
* - Direct `$dynamicAnchor` on the subschema → inline entry.
|
|
2548
|
+
* - `$defs` `$dynamicAnchor` *without* a `$ref` → inline entry. Note this
|
|
2549
|
+
* differs from `buildDynamicScope`, which treats unbound `$defs` anchors as
|
|
2550
|
+
* generic parameters (`isParameter`); inline subschemas are concrete
|
|
2551
|
+
* instances, so the anchor resolves to the inline schema object itself.
|
|
2552
|
+
* - `$defs` `$dynamicAnchor` *with* a `$ref` → intentionally NOT collected
|
|
2553
|
+
* here. Such anchors rely on `resolveDynamicRef`'s global fallback (which
|
|
2554
|
+
* finds them when the `$ref` target declares the same anchor). Fully
|
|
2555
|
+
* resolving them would duplicate `buildDynamicScope`'s `$defs` logic.
|
|
2556
|
+
*/
|
|
2557
|
+
function buildInlineDynamicScope(schema) {
|
|
2558
|
+
const scope = {};
|
|
2559
|
+
const schemaRecord = schema;
|
|
2560
|
+
if (typeof schemaRecord.$dynamicAnchor === "string") {
|
|
2561
|
+
const anchor = schemaRecord.$dynamicAnchor;
|
|
2562
|
+
scope[anchor] = {
|
|
2563
|
+
name: anchor,
|
|
2564
|
+
schemaName: anchor,
|
|
2565
|
+
inlineSchema: schema
|
|
2566
|
+
};
|
|
2567
|
+
}
|
|
2568
|
+
const defs = schemaRecord.$defs;
|
|
2569
|
+
if (defs && typeof defs === "object") for (const defSchema of Object.values(defs)) {
|
|
2570
|
+
if (!defSchema || typeof defSchema !== "object") continue;
|
|
2571
|
+
const defRecord = defSchema;
|
|
2572
|
+
if (typeof defRecord.$dynamicAnchor === "string" && !defSchema.$ref) {
|
|
2573
|
+
const anchor = defRecord.$dynamicAnchor;
|
|
2574
|
+
scope[anchor] = {
|
|
2575
|
+
name: anchor,
|
|
2576
|
+
schemaName: anchor,
|
|
2577
|
+
inlineSchema: defSchema
|
|
2578
|
+
};
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
return scope;
|
|
2582
|
+
}
|
|
2583
|
+
/**
|
|
2489
2584
|
* Resolve a `$dynamicRef` anchor to its concrete type using the current dynamic scope.
|
|
2490
2585
|
* Returns `{ schema: {}, resolvedTypeName: 'unknown' }` when no scope override exists.
|
|
2491
2586
|
*/
|
|
@@ -2521,6 +2616,12 @@ function resolveDynamicRef(anchorName, context, imports = []) {
|
|
|
2521
2616
|
resolvedTypeName: scopeEntry.name,
|
|
2522
2617
|
schemaName: void 0
|
|
2523
2618
|
};
|
|
2619
|
+
if (scopeEntry.inlineSchema) return {
|
|
2620
|
+
schema: scopeEntry.inlineSchema,
|
|
2621
|
+
imports,
|
|
2622
|
+
resolvedTypeName: scopeEntry.name,
|
|
2623
|
+
schemaName: void 0
|
|
2624
|
+
};
|
|
2524
2625
|
const resolvedTypeName = scopeEntry.name;
|
|
2525
2626
|
const schemaRef = `#/components/schemas/${encodeJsonPointerSegment(scopeEntry.schemaName)}`;
|
|
2526
2627
|
try {
|
|
@@ -2713,7 +2814,7 @@ function resolveValue({ schema, name, context, formDataContext }) {
|
|
|
2713
2814
|
const refName = resolvedImport.name;
|
|
2714
2815
|
let effectiveContext = context;
|
|
2715
2816
|
const refAnchor = schemaObject.$dynamicAnchor;
|
|
2716
|
-
if (typeof refAnchor === "string" && context.dynamicScope?.[refAnchor] && context.dynamicScope[refAnchor].name !== refName && !context.dynamicScope[refAnchor].isParameter) {
|
|
2817
|
+
if (typeof refAnchor === "string" && context.dynamicScope?.[refAnchor] && context.dynamicScope[refAnchor].name !== refName && !context.dynamicScope[refAnchor].isParameter && !context.dynamicScope[refAnchor].inlineSchema) {
|
|
2717
2818
|
const scopeEntry = context.dynamicScope[refAnchor];
|
|
2718
2819
|
const allOf = ((context.spec.components?.schemas)?.[scopeEntry.schemaName])?.allOf;
|
|
2719
2820
|
if (!(Array.isArray(allOf) && allOf.some((el) => {
|
|
@@ -4621,7 +4722,7 @@ function parseFunction(ast, funcName) {
|
|
|
4621
4722
|
const BODY_TYPE_NAME = "BodyType";
|
|
4622
4723
|
const getImport = (output, mutator, tsconfig) => {
|
|
4623
4724
|
const outputFile = getFileInfo(output).path;
|
|
4624
|
-
const ext = mutator.extension ?? getImportExtension(
|
|
4725
|
+
const ext = mutator.extension ?? getImportExtension(path.extname(mutator.path), tsconfig);
|
|
4625
4726
|
return `${getRelativeImportPath(outputFile, mutator.path)}${ext}`;
|
|
4626
4727
|
};
|
|
4627
4728
|
async function generateMutator({ output, mutator, name, workspace, tsconfig }) {
|
|
@@ -4821,7 +4922,7 @@ function generateBodyOptions(body, isFormData, isFormUrlEncoded) {
|
|
|
4821
4922
|
if (isFormUrlEncoded && body.formUrlEncoded) return "formUrlEncoded";
|
|
4822
4923
|
if (body.implementation) return body.implementation;
|
|
4823
4924
|
}
|
|
4824
|
-
function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularObserve, angularParamsRef, requiredNullableQueryParamKeys, nonPrimitiveQueryParamKeys, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false,
|
|
4925
|
+
function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularObserve, angularParamsRef, requiredNullableQueryParamKeys, nonPrimitiveQueryParamKeys, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isAngular, paramsSerializer, paramsSerializerOptions, paramsFilter }) {
|
|
4825
4926
|
const isRequestOptions = requestOptions !== false;
|
|
4826
4927
|
const angularPassthroughQueryParamKeys = paramsSerializer ? nonPrimitiveQueryParamKeys : [];
|
|
4827
4928
|
const signalVar = hasSignalParam ? "querySignal" : "signal";
|
|
@@ -4858,8 +4959,7 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
4858
4959
|
if (isRequestOptions) {
|
|
4859
4960
|
value += isAngular ? "\n ...(options as Omit<NonNullable<typeof options>, 'observe'>)," : "\n ...options,";
|
|
4860
4961
|
if (isAngular && angularObserve) value += `\n observe: '${angularObserve}',`;
|
|
4861
|
-
if (queryParams) if (
|
|
4862
|
-
else if (isAngular && angularParamsRef) value += `\n params: ${angularParamsRef},`;
|
|
4962
|
+
if (queryParams) if (isAngular && angularParamsRef) value += `\n params: ${angularParamsRef},`;
|
|
4863
4963
|
else if (isAngular && paramsSerializer) {
|
|
4864
4964
|
const callExpr = buildAngularParamsFilterExpression({
|
|
4865
4965
|
paramsExpression: "{...params, ...options?.params}",
|
|
@@ -4888,7 +4988,7 @@ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularO
|
|
|
4888
4988
|
}
|
|
4889
4989
|
return value;
|
|
4890
4990
|
}
|
|
4891
|
-
function generateOptions({ route, body, angularObserve, angularParamsRef, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam,
|
|
4991
|
+
function generateOptions({ route, body, angularObserve, angularParamsRef, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, paramsSerializer, paramsSerializerOptions, paramsFilter }) {
|
|
4892
4992
|
const bodyIdentifier = getIsBodyVerb(verb) ? generateBodyOptions(body, isFormData, isFormUrlEncoded) : void 0;
|
|
4893
4993
|
const axiosOptions = generateAxiosOptions({
|
|
4894
4994
|
response,
|
|
@@ -4902,7 +5002,6 @@ function generateOptions({ route, body, angularObserve, angularParamsRef, header
|
|
|
4902
5002
|
isExactOptionalPropertyTypes,
|
|
4903
5003
|
hasSignal,
|
|
4904
5004
|
hasSignalParam,
|
|
4905
|
-
isVue: isVue ?? false,
|
|
4906
5005
|
isAngular: isAngular ?? false,
|
|
4907
5006
|
paramsSerializer,
|
|
4908
5007
|
paramsSerializerOptions,
|
|
@@ -4925,11 +5024,10 @@ function generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) {
|
|
|
4925
5024
|
if (body.implementation) return `,\n data: ${body.implementation}`;
|
|
4926
5025
|
return "";
|
|
4927
5026
|
}
|
|
4928
|
-
function generateQueryParamsAxiosConfig(response,
|
|
5027
|
+
function generateQueryParamsAxiosConfig(response, isAngular, requiredNullableQueryParamKeys, queryParams, paramsFilter) {
|
|
4929
5028
|
if (!queryParams && !response.isBlob) return "";
|
|
4930
5029
|
let value = "";
|
|
4931
|
-
if (queryParams) if (
|
|
4932
|
-
else if (isAngular) {
|
|
5030
|
+
if (queryParams) if (isAngular) {
|
|
4933
5031
|
const paramsExpr = buildAngularParamsFilterExpression({
|
|
4934
5032
|
paramsExpression: "params ?? {}",
|
|
4935
5033
|
requiredNullableParamKeys: requiredNullableQueryParamKeys,
|
|
@@ -4942,9 +5040,9 @@ function generateQueryParamsAxiosConfig(response, isVue, isAngular, requiredNull
|
|
|
4942
5040
|
if (response.isBlob) value += `,\n responseType: 'blob'`;
|
|
4943
5041
|
return value;
|
|
4944
5042
|
}
|
|
4945
|
-
function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes,
|
|
5043
|
+
function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isAngular, paramsFilter }) {
|
|
4946
5044
|
const bodyOptions = getIsBodyVerb(verb) ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) : "";
|
|
4947
|
-
const queryParamsOptions = generateQueryParamsAxiosConfig(response,
|
|
5045
|
+
const queryParamsOptions = generateQueryParamsAxiosConfig(response, isAngular ?? false, queryParams?.requiredNullableKeys, queryParams, paramsFilter);
|
|
4948
5046
|
const ignoreContentTypes = isAngular ? ["multipart/form-data"] : [];
|
|
4949
5047
|
const headerOptions = body.contentType && !ignoreContentTypes.includes(body.contentType) ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
|
|
4950
5048
|
const signalVar = hasSignalParam ? "querySignal" : "signal";
|
|
@@ -5479,6 +5577,50 @@ async function writeGeneratedFile(filePath, content) {
|
|
|
5479
5577
|
await fs$1.outputFile(filePath, content.replaceAll(TRAILING_WHITESPACE_RE, ""));
|
|
5480
5578
|
}
|
|
5481
5579
|
//#endregion
|
|
5580
|
+
//#region src/writers/schema-tag-mapper.ts
|
|
5581
|
+
const SHARED_DIR = ".";
|
|
5582
|
+
function buildSchemaTagMap(operations, schemas) {
|
|
5583
|
+
const schemaNames = new Set(schemas.map((s) => s.name));
|
|
5584
|
+
const schemaToTags = /* @__PURE__ */ new Map();
|
|
5585
|
+
for (const schema of schemas) if (!schemaToTags.has(schema.name)) schemaToTags.set(schema.name, /* @__PURE__ */ new Set());
|
|
5586
|
+
for (const operation of operations) {
|
|
5587
|
+
const tag = kebab(operation.tags[0] ?? "default");
|
|
5588
|
+
for (const imp of operation.imports) if (!imp.importPath && schemaNames.has(imp.name)) addTag(schemaToTags, imp.name, tag);
|
|
5589
|
+
}
|
|
5590
|
+
propagateTransitiveTags(schemaToTags, new Map(schemas.map((s) => [s.name, s])));
|
|
5591
|
+
const result = /* @__PURE__ */ new Map();
|
|
5592
|
+
for (const [name, tags] of schemaToTags) if (tags.size === 0 || tags.size > 1) result.set(name, ".");
|
|
5593
|
+
else result.set(name, [...tags][0]);
|
|
5594
|
+
return result;
|
|
5595
|
+
}
|
|
5596
|
+
function addTag(schemaToTags, schemaName, tag) {
|
|
5597
|
+
if (!schemaToTags.has(schemaName)) schemaToTags.set(schemaName, /* @__PURE__ */ new Set());
|
|
5598
|
+
schemaToTags.get(schemaName).add(tag);
|
|
5599
|
+
}
|
|
5600
|
+
function propagateTransitiveTags(schemaToTags, schemaByName) {
|
|
5601
|
+
let changed = true;
|
|
5602
|
+
while (changed) {
|
|
5603
|
+
changed = false;
|
|
5604
|
+
for (const [name, tags] of schemaToTags) {
|
|
5605
|
+
const schema = schemaByName.get(name);
|
|
5606
|
+
if (!schema) continue;
|
|
5607
|
+
for (const imp of schema.imports) {
|
|
5608
|
+
if (!isSchemaImport(imp)) continue;
|
|
5609
|
+
if (!schemaByName.has(imp.name)) continue;
|
|
5610
|
+
const targetTags = schemaToTags.get(imp.name);
|
|
5611
|
+
if (!targetTags) continue;
|
|
5612
|
+
for (const tag of tags) if (!targetTags.has(tag)) {
|
|
5613
|
+
targetTags.add(tag);
|
|
5614
|
+
changed = true;
|
|
5615
|
+
}
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5618
|
+
}
|
|
5619
|
+
}
|
|
5620
|
+
function isSchemaImport(imp) {
|
|
5621
|
+
return !imp.importPath;
|
|
5622
|
+
}
|
|
5623
|
+
//#endregion
|
|
5482
5624
|
//#region src/writers/schemas.ts
|
|
5483
5625
|
/**
|
|
5484
5626
|
* Patterns to detect operation-derived types (params, bodies, responses).
|
|
@@ -5631,8 +5773,8 @@ function getSchema({ schema: { imports, model }, header, namingConvention = Nami
|
|
|
5631
5773
|
file += model;
|
|
5632
5774
|
return file;
|
|
5633
5775
|
}
|
|
5634
|
-
function getPath(path, name, fileExtension) {
|
|
5635
|
-
return
|
|
5776
|
+
function getPath(path$1, name, fileExtension) {
|
|
5777
|
+
return path.join(path$1, `${name}${fileExtension}`);
|
|
5636
5778
|
}
|
|
5637
5779
|
function writeModelInline(acc, model) {
|
|
5638
5780
|
return acc + `${model}\n`;
|
|
@@ -5725,14 +5867,14 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
5725
5867
|
await writeGeneratedFile(getPath(factoryDir, factoryFileName, fileExtension), factoryFile);
|
|
5726
5868
|
}
|
|
5727
5869
|
if (indexFiles) {
|
|
5728
|
-
const schemaFilePath =
|
|
5870
|
+
const schemaFilePath = path.join(schemaPath, `index.ts`);
|
|
5729
5871
|
await fs$1.ensureFile(schemaFilePath);
|
|
5730
5872
|
const ext = getImportExtension(fileExtension, tsconfig);
|
|
5731
5873
|
const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
|
|
5732
5874
|
try {
|
|
5733
5875
|
const currentExports = [...conventionNamesSet].map((schemaName) => `export * from './${schemaName}${ext}';`);
|
|
5734
5876
|
if (factoryOutputDirectory && normalizeSafe(factoryOutputDirectory) !== normalizeSafe(schemaPath) && (isCombined.value || separateFactoryNames.length > 0)) {
|
|
5735
|
-
const factoryIndexFilePath =
|
|
5877
|
+
const factoryIndexFilePath = path.join(factoryOutputDirectory, `index.ts`);
|
|
5736
5878
|
await fs$1.ensureFile(factoryIndexFilePath);
|
|
5737
5879
|
const factoryExports = [];
|
|
5738
5880
|
if (isCombined.value) {
|
|
@@ -5755,6 +5897,61 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
5755
5897
|
}
|
|
5756
5898
|
}
|
|
5757
5899
|
//#endregion
|
|
5900
|
+
//#region src/writers/schemas-tags-split.ts
|
|
5901
|
+
async function writeSchemasTagsSplit({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles, tsconfig, factoryOutputDirectory, operations }) {
|
|
5902
|
+
const schemaTagMap = buildSchemaTagMap(operations, schemas);
|
|
5903
|
+
const importExtension = getImportExtension(fileExtension, tsconfig);
|
|
5904
|
+
const groups = /* @__PURE__ */ new Map();
|
|
5905
|
+
for (const schema of schemas) {
|
|
5906
|
+
const group = schemaTagMap.get(schema.name) ?? ".";
|
|
5907
|
+
if (!groups.has(group)) groups.set(group, []);
|
|
5908
|
+
groups.get(group).push(schema);
|
|
5909
|
+
}
|
|
5910
|
+
for (const [groupDir, groupSchemas] of groups) {
|
|
5911
|
+
const isRoot = groupDir === ".";
|
|
5912
|
+
const groupPath = isRoot ? schemaPath : path.join(schemaPath, groupDir);
|
|
5913
|
+
fixCrossTagImports(groupSchemas, schemaTagMap, schemaPath, groupDir, namingConvention, importExtension);
|
|
5914
|
+
const groupFactoryDir = factoryOutputDirectory ? isRoot ? factoryOutputDirectory : path.join(factoryOutputDirectory, groupDir) : void 0;
|
|
5915
|
+
await writeSchemas({
|
|
5916
|
+
schemaPath: groupPath,
|
|
5917
|
+
schemas: groupSchemas,
|
|
5918
|
+
target,
|
|
5919
|
+
namingConvention,
|
|
5920
|
+
fileExtension,
|
|
5921
|
+
header,
|
|
5922
|
+
indexFiles: !isRoot && indexFiles,
|
|
5923
|
+
tsconfig,
|
|
5924
|
+
factoryOutputDirectory: groupFactoryDir
|
|
5925
|
+
});
|
|
5926
|
+
}
|
|
5927
|
+
if (indexFiles && groups.size > 0) {
|
|
5928
|
+
const rootIndexPath = path.join(schemaPath, "index.ts");
|
|
5929
|
+
const rootExports = (groups.get(".") ?? []).map((s) => {
|
|
5930
|
+
return `export * from './${conventionName(s.name, namingConvention)}${importExtension}';`;
|
|
5931
|
+
});
|
|
5932
|
+
const tagExports = [...groups.keys()].filter((dir) => dir !== ".").toSorted((a, b) => a.localeCompare(b, "en", { numeric: true })).map((dir) => {
|
|
5933
|
+
return `export * from '${importExtension ? `./${dir}/index${importExtension}` : `./${dir}`}';`;
|
|
5934
|
+
});
|
|
5935
|
+
await writeGeneratedFile(rootIndexPath, `${header}\n${[...rootExports, ...tagExports].join("\n")}\n`);
|
|
5936
|
+
}
|
|
5937
|
+
}
|
|
5938
|
+
function fixCrossTagImports(schemas, schemaTagMap, schemaPath, currentGroupDir, namingConvention, importExtension) {
|
|
5939
|
+
const fromPath = currentGroupDir === "." ? schemaPath : path.join(schemaPath, currentGroupDir);
|
|
5940
|
+
for (const schema of schemas) {
|
|
5941
|
+
const fixImports = (imports) => imports.map((imp) => {
|
|
5942
|
+
const targetGroup = schemaTagMap.get(imp.name);
|
|
5943
|
+
if (targetGroup === void 0 || targetGroup === currentGroupDir) return imp;
|
|
5944
|
+
const importPath = joinSafe(relativeSafe(fromPath, targetGroup === "." ? schemaPath : path.join(schemaPath, targetGroup)), conventionName(imp.name, namingConvention)) + importExtension;
|
|
5945
|
+
return {
|
|
5946
|
+
...imp,
|
|
5947
|
+
importPath
|
|
5948
|
+
};
|
|
5949
|
+
});
|
|
5950
|
+
schema.imports = fixImports(schema.imports);
|
|
5951
|
+
if (schema.factoryImports) schema.factoryImports = fixImports(schema.factoryImports);
|
|
5952
|
+
}
|
|
5953
|
+
}
|
|
5954
|
+
//#endregion
|
|
5758
5955
|
//#region src/writers/finalize-mock-implementation.ts
|
|
5759
5956
|
function getFinalizeMockImplementationOptions(output, mockOutputs) {
|
|
5760
5957
|
const outputs = Array.isArray(mockOutputs) ? mockOutputs : [mockOutputs];
|
|
@@ -5778,7 +5975,7 @@ function filterLocalStrictMockTypeImports(imports, strictSchemaTypeNames) {
|
|
|
5778
5975
|
}
|
|
5779
5976
|
//#endregion
|
|
5780
5977
|
//#region src/writers/generate-imports-for-builder.ts
|
|
5781
|
-
function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
5978
|
+
function generateImportsForBuilder(output, imports, relativeSchemasPath, schemaTagMap) {
|
|
5782
5979
|
const isPackageImport = isObject(output.schemas) && !!output.schemas.importPath;
|
|
5783
5980
|
const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
|
|
5784
5981
|
const schemaFactoryImports = imports.filter((i) => i.schemaFactory);
|
|
@@ -5800,7 +5997,11 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
5800
5997
|
else {
|
|
5801
5998
|
const importsByDependency = /* @__PURE__ */ new Map();
|
|
5802
5999
|
for (const schemaImport of imports.filter((i) => !i.importPath)) {
|
|
5803
|
-
const
|
|
6000
|
+
const normalizedName = conventionName(isZodSchemaOutput ? schemaImport.name : schemaImport.schemaName ?? schemaImport.name, output.namingConvention);
|
|
6001
|
+
const suffix = isZodSchemaOutput ? ".zod" : "";
|
|
6002
|
+
const importExtension = isPackageImport ? "" : getImportExtension(output.fileExtension, output.tsconfig);
|
|
6003
|
+
const tagDir = schemaTagMap?.get(schemaImport.name);
|
|
6004
|
+
const dependency = joinSafe(relativeSchemasPath, `${tagDir && tagDir !== "." ? `${tagDir}/` : ""}${normalizedName}${suffix}${importExtension}`);
|
|
5804
6005
|
if (!importsByDependency.has(dependency)) importsByDependency.set(dependency, []);
|
|
5805
6006
|
importsByDependency.get(dependency)?.push(schemaImport);
|
|
5806
6007
|
}
|
|
@@ -5832,6 +6033,78 @@ function getFakerSchemasImportPath(mock) {
|
|
|
5832
6033
|
return mock.generators.find((g) => !isFunction(g) && g.type === OutputMockType.FAKER && g.schemas === true)?.schemasImportPath;
|
|
5833
6034
|
}
|
|
5834
6035
|
//#endregion
|
|
6036
|
+
//#region src/writers/mock-imports.ts
|
|
6037
|
+
/** Maps `components/schemas` names to consolidated index.faker import symbols. */
|
|
6038
|
+
function buildKnownSchemaFactoryImportSets(schemaNames) {
|
|
6039
|
+
const factoryNames = /* @__PURE__ */ new Set();
|
|
6040
|
+
const typeNames = /* @__PURE__ */ new Set();
|
|
6041
|
+
for (const name of schemaNames) {
|
|
6042
|
+
const typeName = pascal(name);
|
|
6043
|
+
factoryNames.add(`get${typeName}Mock`);
|
|
6044
|
+
typeNames.add(`${typeName}Mock`);
|
|
6045
|
+
}
|
|
6046
|
+
return {
|
|
6047
|
+
factoryNames,
|
|
6048
|
+
typeNames
|
|
6049
|
+
};
|
|
6050
|
+
}
|
|
6051
|
+
/**
|
|
6052
|
+
* Recover schema-factory imports referenced in generated mock bodies but
|
|
6053
|
+
* missing from the collected import list (e.g. after shared-array import
|
|
6054
|
+
* aggregation on large specs). Scans for `get<Schema>Mock()` calls and
|
|
6055
|
+
* `as <Schema>Mock` casts emitted by strict schema delegation (#3590).
|
|
6056
|
+
*
|
|
6057
|
+
* When `knownSets` is provided, only symbols that exist in the consolidated
|
|
6058
|
+
* schemas faker file are recovered — this avoids importing one-off split
|
|
6059
|
+
* response helper factories that live in the tag file itself.
|
|
6060
|
+
*/
|
|
6061
|
+
function collectSchemaFactoryImportsFromImplementation(implementation, knownSets) {
|
|
6062
|
+
const imports = [];
|
|
6063
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6064
|
+
for (const match of implementation.matchAll(/\b(get[A-Za-z0-9]+Mock)\(\)/g)) {
|
|
6065
|
+
const factoryName = match[1];
|
|
6066
|
+
if (knownSets && !knownSets.factoryNames.has(factoryName)) continue;
|
|
6067
|
+
const key = `value::${factoryName}`;
|
|
6068
|
+
if (seen.has(key)) continue;
|
|
6069
|
+
seen.add(key);
|
|
6070
|
+
imports.push({
|
|
6071
|
+
name: factoryName,
|
|
6072
|
+
values: true,
|
|
6073
|
+
schemaFactory: true
|
|
6074
|
+
});
|
|
6075
|
+
}
|
|
6076
|
+
for (const match of implementation.matchAll(/\bas ([A-Za-z0-9]+Mock)\b/g)) {
|
|
6077
|
+
const typeName = match[1];
|
|
6078
|
+
if (knownSets && !knownSets.typeNames.has(typeName)) continue;
|
|
6079
|
+
const key = `type::${typeName}`;
|
|
6080
|
+
if (seen.has(key)) continue;
|
|
6081
|
+
seen.add(key);
|
|
6082
|
+
imports.push({
|
|
6083
|
+
name: typeName,
|
|
6084
|
+
values: false,
|
|
6085
|
+
schemaFactory: true
|
|
6086
|
+
});
|
|
6087
|
+
}
|
|
6088
|
+
return imports;
|
|
6089
|
+
}
|
|
6090
|
+
function mergeGeneratorImports(...groups) {
|
|
6091
|
+
const merged = /* @__PURE__ */ new Map();
|
|
6092
|
+
for (const group of groups) for (const imp of group) {
|
|
6093
|
+
const key = `${imp.name}::${imp.alias ?? ""}`;
|
|
6094
|
+
const existing = merged.get(key);
|
|
6095
|
+
if (!existing) {
|
|
6096
|
+
merged.set(key, imp);
|
|
6097
|
+
continue;
|
|
6098
|
+
}
|
|
6099
|
+
if (!existing.values && imp.values) merged.set(key, imp);
|
|
6100
|
+
}
|
|
6101
|
+
return [...merged.values()];
|
|
6102
|
+
}
|
|
6103
|
+
/** Recover missing index.faker imports when `schemas: true` is enabled. */
|
|
6104
|
+
function collectRecoveredSchemaFactoryImports(implementation, componentSchemaNames) {
|
|
6105
|
+
return collectSchemaFactoryImportsFromImplementation(implementation, buildKnownSchemaFactoryImportSets(componentSchemaNames));
|
|
6106
|
+
}
|
|
6107
|
+
//#endregion
|
|
5835
6108
|
//#region src/writers/mock-outputs.ts
|
|
5836
6109
|
/**
|
|
5837
6110
|
* Collapses the per-generator mock outputs for "inline" writer modes
|
|
@@ -5856,8 +6129,8 @@ function hasAnyMockPath(mockConfig) {
|
|
|
5856
6129
|
return mockConfig.generators.some((g) => !isFunction(g) && !!g.path);
|
|
5857
6130
|
}
|
|
5858
6131
|
function resolveMockSchemasPath(mockFilePath, schemasTarget) {
|
|
5859
|
-
const ext =
|
|
5860
|
-
const targetExt =
|
|
6132
|
+
const ext = path.extname(mockFilePath);
|
|
6133
|
+
const targetExt = path.extname(schemasTarget);
|
|
5861
6134
|
return getRelativeImportPath(mockFilePath, targetExt === ".schemas" ? schemasTarget + ext : targetExt ? schemasTarget : schemasTarget + ext);
|
|
5862
6135
|
}
|
|
5863
6136
|
//#endregion
|
|
@@ -5901,7 +6174,8 @@ function generateTarget(builder, options) {
|
|
|
5901
6174
|
formUrlEncoded: [],
|
|
5902
6175
|
paramsSerializer: [],
|
|
5903
6176
|
paramsFilter: [],
|
|
5904
|
-
fetchReviver: []
|
|
6177
|
+
fetchReviver: [],
|
|
6178
|
+
sharedTypes: []
|
|
5905
6179
|
};
|
|
5906
6180
|
const operations = Object.values(builder.operations);
|
|
5907
6181
|
for (const [index, operation] of operations.entries()) {
|
|
@@ -5948,7 +6222,7 @@ function generateTarget(builder, options) {
|
|
|
5948
6222
|
verbOptions: builder.verbOptions,
|
|
5949
6223
|
clientImplementation: target.implementation
|
|
5950
6224
|
});
|
|
5951
|
-
target.implementation = header.implementation + target.implementation;
|
|
6225
|
+
target.implementation = (header.sharedTypes && header.sharedTypes.length > 0 ? header.sharedTypes.map((t) => `${t.exported ? "export " : ""}${t.code}`).join("\n") + "\n\n" : "") + header.implementation + target.implementation;
|
|
5952
6226
|
const footer = builder.footer({
|
|
5953
6227
|
outputClient: options.client,
|
|
5954
6228
|
operationNames,
|
|
@@ -6014,7 +6288,7 @@ interface TypedResponse<T> extends Response {
|
|
|
6014
6288
|
}
|
|
6015
6289
|
//#endregion
|
|
6016
6290
|
//#region src/writers/single-mode.ts
|
|
6017
|
-
async function writeSingleMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
|
|
6291
|
+
async function writeSingleMode({ builder, output, projectName, header, needSchema, generateSchemasInline, schemaTagMap }) {
|
|
6018
6292
|
try {
|
|
6019
6293
|
const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
|
|
6020
6294
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
@@ -6042,7 +6316,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
6042
6316
|
}
|
|
6043
6317
|
}
|
|
6044
6318
|
let data = header;
|
|
6045
|
-
const importsForBuilder = schemasPath ? generateImportsForBuilder(output, normalizedImports, relativeSchemasPath) : generateImportsForBuilder(output, normalizedImports.filter((imp) => !!imp.importPath), ".");
|
|
6319
|
+
const importsForBuilder = schemasPath ? generateImportsForBuilder(output, normalizedImports, relativeSchemasPath, schemaTagMap) : generateImportsForBuilder(output, normalizedImports.filter((imp) => !!imp.importPath), ".");
|
|
6046
6320
|
data += builder.imports({
|
|
6047
6321
|
client: output.client,
|
|
6048
6322
|
implementation,
|
|
@@ -6059,10 +6333,12 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
6059
6333
|
if (!shouldDeinlineMocks) for (const mockOutput of collapsedMockOutputs) {
|
|
6060
6334
|
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
6061
6335
|
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6062
|
-
const
|
|
6063
|
-
const
|
|
6336
|
+
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6337
|
+
const recoveredSchemaFactoryImports = !!entry && !isFunction(entry) && entry.type === OutputMockType.FAKER && entry.schemas === true && output.schemas ? collectRecoveredSchemaFactoryImports(finalizedMockImplementation, builder.schemas.filter((s) => s.schema).map((s) => s.name)) : [];
|
|
6338
|
+
const filteredMockImports = filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports).filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? ""))), finalizeMockOptions.strictSchemaTypeNames);
|
|
6339
|
+
const importsMockForBuilder = schemasPath ? generateImportsForBuilder(output, filteredMockImports, relativeSchemasPath, schemaTagMap) : generateImportsForBuilder(output, filteredMockImports.filter((imp) => !!imp.importPath), ".");
|
|
6064
6340
|
data += builder.importsMock({
|
|
6065
|
-
implementation:
|
|
6341
|
+
implementation: finalizedMockImplementation,
|
|
6066
6342
|
imports: importsMockForBuilder,
|
|
6067
6343
|
projectName,
|
|
6068
6344
|
hasSchemaDir: !!output.schemas,
|
|
@@ -6111,11 +6387,13 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
6111
6387
|
if (!rawEntry) continue;
|
|
6112
6388
|
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6113
6389
|
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6114
|
-
const mockFilePath =
|
|
6390
|
+
const mockFilePath = path.join(mockDir, filename + "." + mockExtension + extension);
|
|
6115
6391
|
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6116
|
-
const
|
|
6392
|
+
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6393
|
+
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6394
|
+
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)) : [];
|
|
6395
|
+
const importsMockForBuilder = schemasPath || mockDir !== dirname ? generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames), mockRelativeSchemasPath, schemaTagMap) : generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames).filter((imp) => !!imp.importPath), ".");
|
|
6117
6396
|
let mockData = header;
|
|
6118
|
-
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, getFinalizeMockImplementationOptions(output, mockOutput)) : mockOutput.implementation;
|
|
6119
6397
|
mockData += builder.importsMock({
|
|
6120
6398
|
implementation: finalizedMockImplementation,
|
|
6121
6399
|
imports: importsMockForBuilder,
|
|
@@ -6139,7 +6417,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
6139
6417
|
if (output.mock.indexMockFiles) {
|
|
6140
6418
|
const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
|
|
6141
6419
|
for (const { extension: mockExt, mockDir } of writtenMockEntries) {
|
|
6142
|
-
const indexMockPath =
|
|
6420
|
+
const indexMockPath = path.join(mockDir, `index.${mockExt}${extension}`);
|
|
6143
6421
|
await writeGeneratedFile(indexMockPath, `export * from './${filename}.${mockExt}${importExtension}'\n`);
|
|
6144
6422
|
extraPaths.push(indexMockPath);
|
|
6145
6423
|
}
|
|
@@ -6152,80 +6430,8 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
6152
6430
|
}
|
|
6153
6431
|
}
|
|
6154
6432
|
//#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
|
|
6227
6433
|
//#region src/writers/split-mode.ts
|
|
6228
|
-
async function writeSplitMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
|
|
6434
|
+
async function writeSplitMode({ builder, output, projectName, header, needSchema, generateSchemasInline, schemaTagMap }) {
|
|
6229
6435
|
try {
|
|
6230
6436
|
const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
|
|
6231
6437
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
@@ -6234,10 +6440,10 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
6234
6440
|
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, paramsFilter, fetchReviver } = generateTarget(builder, output);
|
|
6235
6441
|
let implementationData = header;
|
|
6236
6442
|
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6237
|
-
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath,
|
|
6238
|
-
const schemasTarget = output.schemas ?
|
|
6443
|
+
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(targetPath, isString(output.schemas) ? output.schemas : output.schemas.path, true) : "./" + filename + ".schemas" + getImportExtension(extension, output.tsconfig);
|
|
6444
|
+
const schemasTarget = output.schemas ? isString(output.schemas) ? output.schemas : output.schemas.path : path.join(dirname, filename + ".schemas" + getImportExtension(extension, output.tsconfig));
|
|
6239
6445
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
6240
|
-
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
6446
|
+
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath, schemaTagMap);
|
|
6241
6447
|
implementationData += builder.imports({
|
|
6242
6448
|
client: output.client,
|
|
6243
6449
|
implementation,
|
|
@@ -6251,7 +6457,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
6251
6457
|
packageJson: output.packageJson,
|
|
6252
6458
|
output
|
|
6253
6459
|
});
|
|
6254
|
-
const schemasPath = !output.schemas && needSchema ?
|
|
6460
|
+
const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
6255
6461
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
6256
6462
|
if (mutators) implementationData += generateMutatorImports({
|
|
6257
6463
|
mutators,
|
|
@@ -6273,7 +6479,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
6273
6479
|
}
|
|
6274
6480
|
implementationData += `\n${implementation}`;
|
|
6275
6481
|
const implementationFilename = filename + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
6276
|
-
const implementationPath =
|
|
6482
|
+
const implementationPath = path.join(dirname, implementationFilename);
|
|
6277
6483
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
6278
6484
|
const mockPaths = [];
|
|
6279
6485
|
const seenMockIndexKeys = /* @__PURE__ */ new Set();
|
|
@@ -6286,12 +6492,12 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
6286
6492
|
if (!rawEntry) continue;
|
|
6287
6493
|
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6288
6494
|
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6289
|
-
const mockFilePath =
|
|
6495
|
+
const mockFilePath = path.join(mockDir, filename + "." + mockExtension + extension);
|
|
6290
6496
|
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6291
6497
|
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6292
6498
|
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6293
6499
|
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);
|
|
6500
|
+
const importsMockForBuilder = generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames), mockRelativeSchemasPath, schemaTagMap);
|
|
6295
6501
|
let mockData = header;
|
|
6296
6502
|
mockData += builder.importsMock({
|
|
6297
6503
|
implementation: finalizedMockImplementation,
|
|
@@ -6317,7 +6523,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
6317
6523
|
if (output.mock.indexMockFiles) {
|
|
6318
6524
|
const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
|
|
6319
6525
|
for (const { extension: mockExt, mockDir } of writtenMockEntries) {
|
|
6320
|
-
const indexMockPath =
|
|
6526
|
+
const indexMockPath = path.join(mockDir, `index.${mockExt}${extension}`);
|
|
6321
6527
|
await writeGeneratedFile(indexMockPath, `export * from './${filename}.${mockExt}${importExtension}'\n`);
|
|
6322
6528
|
indexMockPaths.push(indexMockPath);
|
|
6323
6529
|
}
|
|
@@ -6409,7 +6615,7 @@ function initialMockOutputsForOperation(op) {
|
|
|
6409
6615
|
}));
|
|
6410
6616
|
}
|
|
6411
6617
|
function generateTargetTags(currentAcc, operation) {
|
|
6412
|
-
const tag =
|
|
6618
|
+
const tag = getOperationTagKey(operation);
|
|
6413
6619
|
if (!(tag in currentAcc)) {
|
|
6414
6620
|
currentAcc[tag] = {
|
|
6415
6621
|
imports: operation.imports,
|
|
@@ -6450,7 +6656,7 @@ function generateTargetForTags(builder, options) {
|
|
|
6450
6656
|
const transformed = {};
|
|
6451
6657
|
for (const [tag, target] of Object.entries(allTargetTags)) {
|
|
6452
6658
|
const isMutator = !!target.mutators?.some((mutator) => isAngularClient ? mutator.hasThirdArg : mutator.hasSecondArg);
|
|
6453
|
-
const operationNames =
|
|
6659
|
+
const operationNames = operations.filter((operation) => isOperationInTagBucket(operation, tag)).map(({ operationName }) => operationName);
|
|
6454
6660
|
const hasAwaitedType = compareVersions(options.packageJson?.dependencies?.typescript ?? options.packageJson?.devDependencies?.typescript ?? "4.4.0", "4.5.0");
|
|
6455
6661
|
const titles = builder.title({
|
|
6456
6662
|
outputClient: options.client,
|
|
@@ -6480,6 +6686,9 @@ function generateTargetForTags(builder, options) {
|
|
|
6480
6686
|
isDefaultTagBucket: tag === "default" && Object.values(builder.operations).some((operation) => operation.tags.length === 0),
|
|
6481
6687
|
clientImplementation: target.implementation
|
|
6482
6688
|
});
|
|
6689
|
+
const sharedTypes = header.sharedTypes;
|
|
6690
|
+
const deduplicationActive = options.tagsSplitDeduplication && !options.workspace;
|
|
6691
|
+
const inlinedSharedTypes = !deduplicationActive && sharedTypes && sharedTypes.length > 0 ? sharedTypes.map((t) => `${t.exported ? "export " : ""}${t.code}`).join("\n") + "\n\n" : "";
|
|
6483
6692
|
const wrappedMockOutputs = target.mockOutputs.map((m) => ({
|
|
6484
6693
|
type: m.type,
|
|
6485
6694
|
implementation: {
|
|
@@ -6492,7 +6701,7 @@ function generateTargetForTags(builder, options) {
|
|
|
6492
6701
|
strictMockSchemaKinds: m.strictMockSchemaKinds
|
|
6493
6702
|
}));
|
|
6494
6703
|
transformed[tag] = {
|
|
6495
|
-
implementation: header.implementation + target.implementation + footer.implementation,
|
|
6704
|
+
implementation: inlinedSharedTypes + header.implementation + target.implementation + footer.implementation,
|
|
6496
6705
|
mockOutputs: wrappedMockOutputs,
|
|
6497
6706
|
imports: target.imports,
|
|
6498
6707
|
mutators: target.mutators,
|
|
@@ -6501,7 +6710,8 @@ function generateTargetForTags(builder, options) {
|
|
|
6501
6710
|
formUrlEncoded: target.formUrlEncoded,
|
|
6502
6711
|
paramsSerializer: target.paramsSerializer,
|
|
6503
6712
|
paramsFilter: target.paramsFilter,
|
|
6504
|
-
fetchReviver: target.fetchReviver
|
|
6713
|
+
fetchReviver: target.fetchReviver,
|
|
6714
|
+
sharedTypes: deduplicationActive ? sharedTypes : void 0
|
|
6505
6715
|
};
|
|
6506
6716
|
}
|
|
6507
6717
|
allTargetTags = transformed;
|
|
@@ -6516,7 +6726,7 @@ function generateTargetForTags(builder, options) {
|
|
|
6516
6726
|
}
|
|
6517
6727
|
//#endregion
|
|
6518
6728
|
//#region src/writers/split-tags-mode.ts
|
|
6519
|
-
async function writeSplitTagsMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
|
|
6729
|
+
async function writeSplitTagsMode({ builder, output, projectName, header, needSchema, generateSchemasInline, schemaTagMap }) {
|
|
6520
6730
|
const { filename, dirname, extension } = getFileInfo(output.target, {
|
|
6521
6731
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
6522
6732
|
extension: output.fileExtension
|
|
@@ -6525,33 +6735,51 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6525
6735
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
6526
6736
|
const mockIndexEntries = [];
|
|
6527
6737
|
const seenMockIndexKeys = /* @__PURE__ */ new Set();
|
|
6528
|
-
const schemasTarget = output.schemas ?
|
|
6738
|
+
const schemasTarget = output.schemas ? isString(output.schemas) ? output.schemas : output.schemas.path : path.join(dirname, filename + ".schemas" + getImportExtension(extension, output.tsconfig));
|
|
6529
6739
|
const tagEntries = Object.entries(target).toSorted(([a], [b]) => a.localeCompare(b));
|
|
6740
|
+
const deduplicationEnabled = output.tagsSplitDeduplication && !output.workspace;
|
|
6741
|
+
const collectedSharedTypes = [];
|
|
6742
|
+
const seenSharedTypeNames = /* @__PURE__ */ new Set();
|
|
6743
|
+
for (const [, target] of tagEntries) {
|
|
6744
|
+
if (!target.sharedTypes) continue;
|
|
6745
|
+
for (const t of target.sharedTypes) if (!seenSharedTypeNames.has(t.name)) {
|
|
6746
|
+
seenSharedTypeNames.add(t.name);
|
|
6747
|
+
collectedSharedTypes.push(t);
|
|
6748
|
+
}
|
|
6749
|
+
}
|
|
6750
|
+
const commonTypesImportExtension = getImportExtension(extension, output.tsconfig);
|
|
6751
|
+
const commonTypesBasename = output.commonTypesFileName;
|
|
6752
|
+
const commonTypesPath = path.join(dirname, commonTypesBasename + extension);
|
|
6753
|
+
const commonTypesRelativeImport = "../" + commonTypesBasename + (deduplicationEnabled ? commonTypesImportExtension : "");
|
|
6530
6754
|
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
6531
6755
|
try {
|
|
6532
6756
|
const { imports, implementation, mockOutputs, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer, paramsFilter } = target;
|
|
6533
6757
|
let implementationData = header;
|
|
6534
|
-
|
|
6758
|
+
if (deduplicationEnabled && target.sharedTypes && target.sharedTypes.length > 0) {
|
|
6759
|
+
const typeNames = target.sharedTypes.map((t) => t.name).join(", ");
|
|
6760
|
+
implementationData += `import type { ${typeNames} } from '${commonTypesRelativeImport}';\n`;
|
|
6761
|
+
}
|
|
6762
|
+
const importerPath = path.join(dirname, tag, tag + extension);
|
|
6535
6763
|
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6536
|
-
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(importerPath,
|
|
6764
|
+
const relativeSchemasPath = output.schemas ? schemaCustomImportPath ?? getRelativeImportPath(importerPath, isString(output.schemas) ? output.schemas : output.schemas.path, true) : "../" + filename + ".schemas" + getImportExtension(extension, output.tsconfig);
|
|
6537
6765
|
const tagNames = new Set(tagEntries.map(([t]) => t));
|
|
6538
6766
|
const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
|
|
6539
6767
|
const importsForBuilder = generateImportsForBuilder(output, imports.map((imp) => {
|
|
6540
6768
|
if (!imp.importPath) return imp;
|
|
6541
6769
|
if (!imp.importPath.startsWith(".")) return imp;
|
|
6542
|
-
const resolvedPath =
|
|
6543
|
-
const targetBasename =
|
|
6770
|
+
const resolvedPath = path.resolve(dirname, imp.importPath);
|
|
6771
|
+
const targetBasename = path.basename(resolvedPath);
|
|
6544
6772
|
let targetFile;
|
|
6545
6773
|
if (tagNames.has(targetBasename)) {
|
|
6546
6774
|
const tagFilename = targetBasename + serviceSuffix + extension;
|
|
6547
|
-
targetFile =
|
|
6775
|
+
targetFile = path.join(resolvedPath, tagFilename);
|
|
6548
6776
|
} else targetFile = resolvedPath + extension;
|
|
6549
6777
|
const adjustedPath = getRelativeImportPath(importerPath, targetFile);
|
|
6550
6778
|
return {
|
|
6551
6779
|
...imp,
|
|
6552
6780
|
importPath: adjustedPath
|
|
6553
6781
|
};
|
|
6554
|
-
}), relativeSchemasPath);
|
|
6782
|
+
}), relativeSchemasPath, schemaTagMap);
|
|
6555
6783
|
implementationData += builder.imports({
|
|
6556
6784
|
client: output.client,
|
|
6557
6785
|
implementation,
|
|
@@ -6565,7 +6793,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6565
6793
|
packageJson: output.packageJson,
|
|
6566
6794
|
output
|
|
6567
6795
|
});
|
|
6568
|
-
const schemasPath = !output.schemas && needSchema ?
|
|
6796
|
+
const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
6569
6797
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
6570
6798
|
if (mutators) implementationData += generateMutatorImports({
|
|
6571
6799
|
mutators,
|
|
@@ -6606,7 +6834,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6606
6834
|
}
|
|
6607
6835
|
implementationData += `\n${implementation}`;
|
|
6608
6836
|
const implementationFilename = tag + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
6609
|
-
const implementationPath =
|
|
6837
|
+
const implementationPath = path.join(dirname, tag, implementationFilename);
|
|
6610
6838
|
await writeGeneratedFile(implementationPath, implementationData);
|
|
6611
6839
|
const mockPaths = [];
|
|
6612
6840
|
for (const mockOutput of mockOutputs) {
|
|
@@ -6617,12 +6845,12 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6617
6845
|
if (!rawEntry) continue;
|
|
6618
6846
|
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6619
6847
|
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6620
|
-
const mockFilePath =
|
|
6848
|
+
const mockFilePath = path.join(mockDir, tag, tag + "." + mockExtension + extension);
|
|
6621
6849
|
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6622
6850
|
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6623
6851
|
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6624
6852
|
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);
|
|
6853
|
+
const importsMockForBuilder = generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames), mockRelativeSchemasPath, schemaTagMap);
|
|
6626
6854
|
let mockData = header;
|
|
6627
6855
|
mockData += builder.importsMock({
|
|
6628
6856
|
implementation: finalizedMockImplementation,
|
|
@@ -6659,16 +6887,38 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
6659
6887
|
}));
|
|
6660
6888
|
if (output.mock.indexMockFiles) {
|
|
6661
6889
|
const mockImportExtension = getImportExtension(extension, output.tsconfig);
|
|
6662
|
-
for (const { ext, mockDir, tags } of mockIndexEntries) await writeGeneratedFile(
|
|
6890
|
+
for (const { ext, mockDir, tags } of mockIndexEntries) await writeGeneratedFile(path.join(mockDir, `index.${ext}${extension}`), tags.toSorted((a, b) => a.localeCompare(b)).map((tag) => {
|
|
6663
6891
|
const localMockPath = joinSafe("./", tag, tag + "." + ext + mockImportExtension);
|
|
6664
6892
|
return ext === OutputMockType.MSW ? `export { get${pascal(tag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
|
|
6665
6893
|
}).join(""));
|
|
6666
6894
|
}
|
|
6667
|
-
|
|
6895
|
+
let commonTypesFilePath;
|
|
6896
|
+
if (deduplicationEnabled && collectedSharedTypes.length > 0) {
|
|
6897
|
+
const commonTypesContent = collectedSharedTypes.map((t) => `export ${t.code}`).join("\n") + "\n";
|
|
6898
|
+
commonTypesFilePath = commonTypesPath;
|
|
6899
|
+
await writeGeneratedFile(commonTypesPath, commonTypesContent);
|
|
6900
|
+
}
|
|
6901
|
+
let indexFilePath;
|
|
6902
|
+
if (output.indexFiles && deduplicationEnabled && tagEntries.length > 0) {
|
|
6903
|
+
const importExtension = getImportExtension(output.fileExtension, output.tsconfig);
|
|
6904
|
+
const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
|
|
6905
|
+
const publicSharedTypeNames = collectedSharedTypes.filter((t) => t.exported).map((t) => t.name);
|
|
6906
|
+
const indexContent = (publicSharedTypeNames.length > 0 ? `export type { ${publicSharedTypeNames.join(", ")} } from './${commonTypesBasename}${importExtension}';\n` : "") + tagEntries.map(([tag]) => {
|
|
6907
|
+
return `export * from '${joinSafe("./", tag, tag + serviceSuffix + importExtension)}';\n`;
|
|
6908
|
+
}).join("");
|
|
6909
|
+
indexFilePath = path.join(dirname, `index${extension}`);
|
|
6910
|
+
await writeGeneratedFile(indexFilePath, indexContent);
|
|
6911
|
+
}
|
|
6912
|
+
return [...new Set([
|
|
6913
|
+
...output.mock.indexMockFiles ? mockIndexEntries.map(({ mockDir, ext }) => path.join(mockDir, `index.${ext}${extension}`)) : [],
|
|
6914
|
+
...commonTypesFilePath ? [commonTypesFilePath] : [],
|
|
6915
|
+
...indexFilePath ? [indexFilePath] : [],
|
|
6916
|
+
...generatedFilePathsArray.flat()
|
|
6917
|
+
])];
|
|
6668
6918
|
}
|
|
6669
6919
|
//#endregion
|
|
6670
6920
|
//#region src/writers/tags-mode.ts
|
|
6671
|
-
async function writeTagsMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
|
|
6921
|
+
async function writeTagsMode({ builder, output, projectName, header, needSchema, generateSchemasInline, schemaTagMap }) {
|
|
6672
6922
|
const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
|
|
6673
6923
|
backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
|
|
6674
6924
|
extension: output.fileExtension
|
|
@@ -6680,7 +6930,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6680
6930
|
const seenMockIndexKeys = /* @__PURE__ */ new Set();
|
|
6681
6931
|
const schemaCustomImportPath = getSchemasImportPath(output.schemas);
|
|
6682
6932
|
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 :
|
|
6933
|
+
const schemasTarget = output.schemas ? getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname : path.join(dirname, filename + ".schemas" + getImportExtension(extension, output.tsconfig));
|
|
6684
6934
|
const tagEntries = Object.entries(target).toSorted(([a], [b]) => a.localeCompare(b));
|
|
6685
6935
|
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
6686
6936
|
try {
|
|
@@ -6700,7 +6950,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6700
6950
|
if (!!mockImport.values || !!mockImport.isConstant || !!mockImport.default || !!mockImport.namespaceImport || !!mockImport.syntheticDefaultImport) matchingImport.values = true;
|
|
6701
6951
|
}
|
|
6702
6952
|
}
|
|
6703
|
-
const importsForBuilder = generateImportsForBuilder(output, normalizedImports, schemasPathRelative);
|
|
6953
|
+
const importsForBuilder = generateImportsForBuilder(output, normalizedImports, schemasPathRelative, schemaTagMap);
|
|
6704
6954
|
data += builder.imports({
|
|
6705
6955
|
client: output.client,
|
|
6706
6956
|
implementation,
|
|
@@ -6716,7 +6966,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6716
6966
|
});
|
|
6717
6967
|
if (!shouldDeinlineMocks) for (const mockOutput of collapsedMockOutputs) {
|
|
6718
6968
|
const entry = output.mock.generators.find((g) => !isFunction(g) && g.type === mockOutput.type);
|
|
6719
|
-
const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? ""))), schemasPathRelative);
|
|
6969
|
+
const importsMockForBuilder = generateImportsForBuilder(output, mockOutput.imports.filter((impMock) => !normalizedImports.some((imp) => imp.name === impMock.name && (imp.alias ?? "") === (impMock.alias ?? ""))), schemasPathRelative, schemaTagMap);
|
|
6720
6970
|
data += builder.importsMock({
|
|
6721
6971
|
implementation: mockOutput.implementation,
|
|
6722
6972
|
imports: importsMockForBuilder,
|
|
@@ -6726,7 +6976,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6726
6976
|
options: entry && !isFunction(entry) ? entry : void 0
|
|
6727
6977
|
});
|
|
6728
6978
|
}
|
|
6729
|
-
const schemasPath = !output.schemas && needSchema ?
|
|
6979
|
+
const schemasPath = !output.schemas && needSchema ? path.join(dirname, filename + ".schemas" + extension) : void 0;
|
|
6730
6980
|
if (schemasPath) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
|
|
6731
6981
|
if (mutators) data += generateMutatorImports({
|
|
6732
6982
|
mutators,
|
|
@@ -6757,7 +7007,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6757
7007
|
}
|
|
6758
7008
|
}
|
|
6759
7009
|
const kebabTag = kebab(tag);
|
|
6760
|
-
const implementationPath =
|
|
7010
|
+
const implementationPath = path.join(dirname, `${kebabTag}${extension}`);
|
|
6761
7011
|
await writeGeneratedFile(implementationPath, data);
|
|
6762
7012
|
const extraPaths = [];
|
|
6763
7013
|
if (shouldDeinlineMocks) for (const mockOutput of rawMockOutputs) {
|
|
@@ -6768,12 +7018,12 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6768
7018
|
if (!rawEntry) continue;
|
|
6769
7019
|
const mockExtension = isFunction(rawEntry) ? OutputMockType.MSW : getMockFileExtensionByTypeName(rawEntry);
|
|
6770
7020
|
const mockDir = getMockDir(rawEntry, output.mock) ?? dirname;
|
|
6771
|
-
const mockFilePath =
|
|
7021
|
+
const mockFilePath = path.join(mockDir, kebabTag, kebabTag + "." + mockExtension + extension);
|
|
6772
7022
|
const mockRelativeSchemasPath = schemaCustomImportPath ?? resolveMockSchemasPath(mockFilePath, schemasTarget);
|
|
6773
7023
|
const finalizeMockOptions = getFinalizeMockImplementationOptions(output, mockOutput);
|
|
6774
7024
|
const finalizedMockImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(mockOutput.implementation, finalizeMockOptions) : mockOutput.implementation;
|
|
6775
7025
|
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);
|
|
7026
|
+
const importsMockForBuilder = generateImportsForBuilder(output, filterLocalStrictMockTypeImports(mergeGeneratorImports(mockOutput.imports, recoveredSchemaFactoryImports), finalizeMockOptions.strictSchemaTypeNames), mockRelativeSchemasPath, schemaTagMap);
|
|
6777
7027
|
let mockData = header;
|
|
6778
7028
|
mockData += builder.importsMock({
|
|
6779
7029
|
implementation: finalizedMockImplementation,
|
|
@@ -6811,7 +7061,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6811
7061
|
if (shouldDeinlineMocks && output.mock.indexMockFiles) {
|
|
6812
7062
|
const mockImportExtension = getImportExtension(extension, output.tsconfig);
|
|
6813
7063
|
for (const { ext, mockDir, tags } of mockIndexEntries) {
|
|
6814
|
-
const indexPath =
|
|
7064
|
+
const indexPath = path.join(mockDir, `index.${ext}${extension}`);
|
|
6815
7065
|
await writeGeneratedFile(indexPath, tags.toSorted((a, b) => a.localeCompare(b)).map((kebabTag) => {
|
|
6816
7066
|
const localMockPath = joinSafe("./", kebabTag, kebabTag + "." + ext + mockImportExtension);
|
|
6817
7067
|
return ext === OutputMockType.MSW ? `export { get${pascal(kebabTag)}Mock } from '${localMockPath}'\n` : `export * from '${localMockPath}'\n`;
|
|
@@ -6822,6 +7072,6 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema,
|
|
|
6822
7072
|
return generatedFilePathsArray.flat();
|
|
6823
7073
|
}
|
|
6824
7074
|
//#endregion
|
|
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 };
|
|
7075
|
+
export { BODY_TYPE_NAME, DefaultTag, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NAMED_COMPONENT_SECTIONS, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SHARED_DIR, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, addDependency, asyncReduce, buildAngularParamsFilterExpression, buildDynamicScope, buildInlineDynamicScope, buildSchemaTagMap, 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, getOperationTagKey, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSchemasImportPath, getSuccessResponseType, getTagKey, getTypedResponse, getWarningCount, isBinaryContentType, isBinaryScalarSchema, isBoolean, isComponentRef, isDirectory, isDynamicReference, isFakerMock, isFunction, isModule, isMswMock, isNullish, isNumber, isNumeric, isObject, isOperationInTagBucket, 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, writeSchemasTagsSplit, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
|
|
6826
7076
|
|
|
6827
7077
|
//# sourceMappingURL=index.mjs.map
|