@orval/core 8.5.1 → 8.5.3
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 +49 -18
- package/dist/index.mjs +160 -91
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./chunk-C7Uep-_p.mjs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { entries, groupBy, isArray, isBoolean, isBoolean as isBoolean$1, isEmptyish, isFunction, isNullish, isNullish as isNullish$1, isNumber, isString, isString as isString$1, prop, unique, uniqueBy, uniqueWith } from "remeda";
|
|
4
4
|
import { keyword } from "esutils";
|
|
5
|
-
import
|
|
5
|
+
import nodePath from "node:path";
|
|
6
6
|
import { compare } from "compare-versions";
|
|
7
7
|
import debug from "debug";
|
|
8
8
|
import { pathToFileURL } from "node:url";
|
|
@@ -134,7 +134,7 @@ function isReference(obj) {
|
|
|
134
134
|
return !isNullish$1(obj) && Object.hasOwn(obj, "$ref");
|
|
135
135
|
}
|
|
136
136
|
function isDirectory(pathValue) {
|
|
137
|
-
return !
|
|
137
|
+
return !nodePath.extname(pathValue);
|
|
138
138
|
}
|
|
139
139
|
function isObject(x) {
|
|
140
140
|
return Object.prototype.toString.call(x) === "[object Object]";
|
|
@@ -461,14 +461,14 @@ async function dynamicImport(toImport, from = process.cwd(), takeDefault = true)
|
|
|
461
461
|
if (!toImport) return toImport;
|
|
462
462
|
try {
|
|
463
463
|
if (isString(toImport)) {
|
|
464
|
-
const fileUrl = pathToFileURL(
|
|
465
|
-
const data =
|
|
464
|
+
const fileUrl = pathToFileURL(nodePath.resolve(from, toImport));
|
|
465
|
+
const data = nodePath.extname(fileUrl.href) === ".json" ? await import(fileUrl.href, { with: { type: "json" } }) : await import(fileUrl.href);
|
|
466
466
|
if (takeDefault && (isObject(data) || isModule(data)) && data.default) return data.default;
|
|
467
467
|
return data;
|
|
468
468
|
}
|
|
469
469
|
return toImport;
|
|
470
470
|
} catch (error) {
|
|
471
|
-
throw new Error(`Oups... 🍻. Path: ${String(toImport)} => ${String(error)}
|
|
471
|
+
throw new Error(`Oups... 🍻. Path: ${String(toImport)} => ${String(error)}`, { cause: error });
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
474
|
|
|
@@ -482,14 +482,14 @@ function getExtension(path) {
|
|
|
482
482
|
//#region src/utils/file.ts
|
|
483
483
|
function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
|
|
484
484
|
const isDir = isDirectory(target);
|
|
485
|
-
const filePath = isDir ?
|
|
485
|
+
const filePath = isDir ? nodePath.join(target, backupFilename + extension) : target;
|
|
486
486
|
return {
|
|
487
487
|
path: filePath,
|
|
488
488
|
pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
|
|
489
489
|
extension,
|
|
490
490
|
isDirectory: isDir,
|
|
491
|
-
dirname:
|
|
492
|
-
filename:
|
|
491
|
+
dirname: nodePath.dirname(filePath),
|
|
492
|
+
filename: nodePath.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
|
|
493
493
|
};
|
|
494
494
|
}
|
|
495
495
|
async function removeFilesAndEmptyFolders(patterns, dir) {
|
|
@@ -565,7 +565,7 @@ function startMessage({ name, version, description }) {
|
|
|
565
565
|
return `🍻 ${styleText(["cyan", "bold"], name)} ${styleText("green", `v${version}`)}${description ? ` - ${description}` : ""}`;
|
|
566
566
|
}
|
|
567
567
|
function logError(err, tag) {
|
|
568
|
-
let message
|
|
568
|
+
let message;
|
|
569
569
|
if (err instanceof Error) {
|
|
570
570
|
message = (err.message || err.stack) ?? "Unknown error";
|
|
571
571
|
if (err.cause) {
|
|
@@ -678,51 +678,43 @@ function count(str = "", key) {
|
|
|
678
678
|
//#endregion
|
|
679
679
|
//#region src/utils/path.ts
|
|
680
680
|
var path_exports = /* @__PURE__ */ __exportAll({
|
|
681
|
-
|
|
682
|
-
dirname: () => dirname,
|
|
683
|
-
extname: () => extname,
|
|
681
|
+
getRelativeImportPath: () => getRelativeImportPath,
|
|
684
682
|
getSchemaFileName: () => getSchemaFileName,
|
|
685
|
-
isAbsolute: () => isAbsolute,
|
|
686
683
|
join: () => join,
|
|
687
684
|
joinSafe: () => joinSafe,
|
|
688
685
|
normalizeSafe: () => normalizeSafe,
|
|
689
686
|
relativeSafe: () => relativeSafe,
|
|
690
|
-
|
|
691
|
-
|
|
687
|
+
separator: () => separator,
|
|
688
|
+
toUnix: () => toUnix
|
|
692
689
|
});
|
|
693
|
-
function
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
690
|
+
function toUnix(value) {
|
|
691
|
+
value = value.replaceAll("\\", "/");
|
|
692
|
+
value = value.replaceAll(/(?<!^)\/+/g, "/");
|
|
693
|
+
return value;
|
|
694
|
+
}
|
|
695
|
+
function join(...args) {
|
|
696
|
+
return toUnix(nodePath.join(...args.map((a) => toUnix(a))));
|
|
698
697
|
}
|
|
699
|
-
const path$1 = Object.fromEntries(Object.entries(path).map(([key, value]) => [key, isFunction(value) ? wrapPathFn(value) : value]));
|
|
700
|
-
const { join, resolve, extname, dirname, basename, isAbsolute } = path$1;
|
|
701
698
|
/**
|
|
702
699
|
* Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
|
|
703
700
|
*/
|
|
704
701
|
function relativeSafe(from, to) {
|
|
705
|
-
return normalizeSafe(`.${separator}${
|
|
702
|
+
return normalizeSafe(`.${separator}${toUnix(nodePath.relative(toUnix(from), toUnix(to)))}`);
|
|
706
703
|
}
|
|
707
704
|
function getSchemaFileName(path) {
|
|
708
705
|
return path.replace(`.${getExtension(path)}`, "").slice(path.lastIndexOf("/") + 1);
|
|
709
706
|
}
|
|
710
707
|
const separator = "/";
|
|
711
|
-
const toUnix = function(value) {
|
|
712
|
-
value = value.replaceAll("\\", "/");
|
|
713
|
-
value = value.replaceAll(/(?<!^)\/+/g, "/");
|
|
714
|
-
return value;
|
|
715
|
-
};
|
|
716
708
|
function normalizeSafe(value) {
|
|
717
709
|
let result;
|
|
718
710
|
value = toUnix(value);
|
|
719
|
-
result =
|
|
711
|
+
result = toUnix(nodePath.normalize(value));
|
|
720
712
|
if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
721
713
|
else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
|
|
722
714
|
return result;
|
|
723
715
|
}
|
|
724
716
|
function joinSafe(...values) {
|
|
725
|
-
let result =
|
|
717
|
+
let result = toUnix(nodePath.join(...values.map((v) => toUnix(v))));
|
|
726
718
|
if (values.length > 0) {
|
|
727
719
|
const firstValue = toUnix(values[0]);
|
|
728
720
|
if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
|
|
@@ -730,25 +722,60 @@ function joinSafe(...values) {
|
|
|
730
722
|
}
|
|
731
723
|
return result;
|
|
732
724
|
}
|
|
725
|
+
/**
|
|
726
|
+
* Given two absolute file paths, generates a valid ESM relative import path
|
|
727
|
+
* from the 'importer' file to the 'exporter' file.
|
|
728
|
+
*
|
|
729
|
+
* @example
|
|
730
|
+
* ```ts
|
|
731
|
+
* getRelativeImportPath('/path/to/importer.ts', '/path/to/exporter.ts')
|
|
732
|
+
* // => './exporter'
|
|
733
|
+
* getRelativeImportPath('/path/to/importer.ts', '/path/to/sub/exporter.ts')
|
|
734
|
+
* // => './sub/exporter'
|
|
735
|
+
* getRelativeImportPath('/path/to/importer.ts', '/path/sibling/exporter.ts')
|
|
736
|
+
* // => '../sibling/exporter'
|
|
737
|
+
* ```
|
|
738
|
+
*
|
|
739
|
+
* This function handles path normalization, cross-platform separators, and
|
|
740
|
+
* ensures the path is a valid ESM relative specifier (e.g., starts with './').
|
|
741
|
+
*
|
|
742
|
+
* @param importerFilePath - The absolute path of the file that will contain the import statement.
|
|
743
|
+
* @param exporterFilePath - The absolute path of the file being imported.
|
|
744
|
+
* @param [includeFileExtension=false] - Whether the import path should include the file extension, defaults to false.
|
|
745
|
+
* @returns The relative import path string.
|
|
746
|
+
*/
|
|
747
|
+
function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileExtension = false) {
|
|
748
|
+
if (!nodePath.isAbsolute(importerFilePath)) throw new Error(`'importerFilePath' is not an absolute path. "${importerFilePath}"`);
|
|
749
|
+
if (!nodePath.isAbsolute(exporterFilePath)) throw new Error(`'exporterFilePath' is not an absolute path. "${exporterFilePath}"`);
|
|
750
|
+
const importerDir = nodePath.dirname(importerFilePath);
|
|
751
|
+
const relativePath = nodePath.relative(importerDir, exporterFilePath);
|
|
752
|
+
let posixPath = nodePath.posix.join(...relativePath.split(nodePath.sep));
|
|
753
|
+
if (!posixPath.startsWith("./") && !posixPath.startsWith("../")) posixPath = `./${posixPath}`;
|
|
754
|
+
if (!includeFileExtension) {
|
|
755
|
+
const ext = nodePath.extname(posixPath);
|
|
756
|
+
if (ext && posixPath.endsWith(ext)) posixPath = posixPath.slice(0, -ext.length);
|
|
757
|
+
}
|
|
758
|
+
return posixPath;
|
|
759
|
+
}
|
|
733
760
|
|
|
734
761
|
//#endregion
|
|
735
762
|
//#region src/utils/resolve-version.ts
|
|
736
763
|
function resolveInstalledVersion(packageName, fromDir) {
|
|
737
764
|
try {
|
|
738
|
-
const require = createRequire(
|
|
765
|
+
const require = createRequire(nodePath.join(fromDir, "noop.js"));
|
|
739
766
|
try {
|
|
740
767
|
return require(`${packageName}/package.json`).version;
|
|
741
768
|
} catch (directError) {
|
|
742
769
|
if (directError instanceof Error && "code" in directError && directError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
|
|
743
770
|
const entryPath = require.resolve(packageName);
|
|
744
|
-
let dir =
|
|
745
|
-
while (dir !==
|
|
746
|
-
const pkgPath =
|
|
771
|
+
let dir = nodePath.dirname(entryPath);
|
|
772
|
+
while (dir !== nodePath.parse(dir).root) {
|
|
773
|
+
const pkgPath = nodePath.join(dir, "package.json");
|
|
747
774
|
if (existsSync(pkgPath)) {
|
|
748
775
|
const pkgData = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
749
776
|
if (pkgData.name === packageName) return pkgData.version;
|
|
750
777
|
}
|
|
751
|
-
dir =
|
|
778
|
+
dir = nodePath.dirname(dir);
|
|
752
779
|
}
|
|
753
780
|
return;
|
|
754
781
|
}
|
|
@@ -891,17 +918,19 @@ function getNumberWord(num) {
|
|
|
891
918
|
return [...num.toString()].reduce((acc, n) => acc + NUMBERS[n], "");
|
|
892
919
|
}
|
|
893
920
|
/**
|
|
894
|
-
* Escapes a specific character in a string by prefixing
|
|
921
|
+
* Escapes a specific character in a string by prefixing all of its occurrences with a backslash.
|
|
895
922
|
*
|
|
896
923
|
* @param str - The string to escape, or null.
|
|
897
924
|
* @param char - The character to escape. Defaults to single quote (').
|
|
898
925
|
* @returns The escaped string, or null if the input is null.
|
|
899
926
|
* @example
|
|
900
927
|
* escape("don't") // returns "don\'t"
|
|
928
|
+
* escape("it's John's") // returns "it\'s John\'s"
|
|
901
929
|
* escape('say "hello"', '"') // returns 'say \\"hello\\"'
|
|
930
|
+
* escape("a'''b", "'") // returns "a\'\'\'b"
|
|
902
931
|
*/
|
|
903
932
|
function escape(str, char = "'") {
|
|
904
|
-
return str?.
|
|
933
|
+
return str?.replaceAll(char, `\\${char}`);
|
|
905
934
|
}
|
|
906
935
|
/**
|
|
907
936
|
* Escape all characters not included in SingleStringCharacters and
|
|
@@ -1174,48 +1203,80 @@ function getRefInfo($ref, context) {
|
|
|
1174
1203
|
|
|
1175
1204
|
//#endregion
|
|
1176
1205
|
//#region src/resolvers/ref.ts
|
|
1206
|
+
const REF_NOT_FOUND_PREFIX = "Oops... 🍻. Ref not found";
|
|
1207
|
+
/**
|
|
1208
|
+
* Recursively resolves a `$ref` in an OpenAPI document, following
|
|
1209
|
+
* nested schema refs and collecting imports along the way.
|
|
1210
|
+
*
|
|
1211
|
+
* Handles OpenAPI 3.0 `nullable` and 3.1 type-array hints on direct refs.
|
|
1212
|
+
*
|
|
1213
|
+
* @see https://spec.openapis.org/oas/v3.0.3#reference-object
|
|
1214
|
+
* @see https://spec.openapis.org/oas/v3.1.0#reference-object
|
|
1215
|
+
*/
|
|
1177
1216
|
function resolveRef(schema, context, imports = []) {
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1217
|
+
const refPath = "$ref" in schema ? schema.$ref : void 0;
|
|
1218
|
+
const nestedSchema = "schema" in schema ? schema.schema : void 0;
|
|
1219
|
+
if (isObject(nestedSchema) && isReference(nestedSchema) && typeof nestedSchema.$ref === "string") {
|
|
1220
|
+
const resolvedRef = resolveRef(nestedSchema, context, imports);
|
|
1221
|
+
if ("examples" in schema) {
|
|
1222
|
+
const schemaWithExamples = schema;
|
|
1223
|
+
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
1224
|
+
}
|
|
1225
|
+
if ("examples" in resolvedRef.schema) {
|
|
1226
|
+
const resolvedWithExamples = resolvedRef.schema;
|
|
1227
|
+
resolvedWithExamples.examples = resolveExampleRefs(resolvedWithExamples.examples, context);
|
|
1228
|
+
}
|
|
1182
1229
|
return {
|
|
1183
1230
|
schema: {
|
|
1184
1231
|
...schema,
|
|
1185
1232
|
schema: resolvedRef.schema
|
|
1186
1233
|
},
|
|
1187
|
-
imports
|
|
1234
|
+
imports: resolvedRef.imports
|
|
1188
1235
|
};
|
|
1189
1236
|
}
|
|
1190
1237
|
if (isDereferenced(schema)) {
|
|
1191
|
-
if ("examples" in schema)
|
|
1238
|
+
if ("examples" in schema) {
|
|
1239
|
+
const schemaWithExamples = schema;
|
|
1240
|
+
schemaWithExamples.examples = resolveExampleRefs(schemaWithExamples.examples, context);
|
|
1241
|
+
}
|
|
1192
1242
|
return {
|
|
1193
1243
|
schema,
|
|
1194
1244
|
imports
|
|
1195
1245
|
};
|
|
1196
1246
|
}
|
|
1247
|
+
if (!refPath) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
1197
1248
|
const { currentSchema, refInfo: { name, originalName } } = getSchema$1(schema, context);
|
|
1198
|
-
if (!currentSchema) throw new Error(
|
|
1249
|
+
if (!currentSchema) throw new Error(`${REF_NOT_FOUND_PREFIX}: ${refPath}`);
|
|
1199
1250
|
return resolveRef(currentSchema, { ...context }, [...imports, {
|
|
1200
1251
|
name,
|
|
1201
1252
|
schemaName: originalName
|
|
1202
1253
|
}]);
|
|
1203
1254
|
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Looks up a schema by its `$ref` path in the spec, applying suffix resolution.
|
|
1257
|
+
*
|
|
1258
|
+
* Preserves OpenAPI 3.0 `nullable` and 3.1 type-array (`["object", "null"]`)
|
|
1259
|
+
* hints from the referencing schema onto the resolved target.
|
|
1260
|
+
*
|
|
1261
|
+
* @see https://spec.openapis.org/oas/v3.0.3#fixed-fields-18 (nullable)
|
|
1262
|
+
* @see https://spec.openapis.org/oas/v3.1.0#schema-object (type as array)
|
|
1263
|
+
*/
|
|
1204
1264
|
function getSchema$1(schema, context) {
|
|
1265
|
+
if (!schema.$ref) throw new Error(`${REF_NOT_FOUND_PREFIX}: missing $ref`);
|
|
1205
1266
|
const refInfo = getRefInfo(schema.$ref, context);
|
|
1206
1267
|
const { refPaths } = refInfo;
|
|
1207
1268
|
let schemaByRefPaths = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
|
|
1208
1269
|
schemaByRefPaths ??= context.spec;
|
|
1209
1270
|
if (isReference(schemaByRefPaths)) return getSchema$1(schemaByRefPaths, context);
|
|
1210
1271
|
let currentSchema = schemaByRefPaths || context.spec;
|
|
1211
|
-
if ("nullable" in schema) {
|
|
1272
|
+
if (isObject(currentSchema) && "nullable" in schema) {
|
|
1212
1273
|
const nullable = schema.nullable;
|
|
1213
1274
|
currentSchema = {
|
|
1214
1275
|
...currentSchema,
|
|
1215
1276
|
nullable
|
|
1216
1277
|
};
|
|
1217
1278
|
}
|
|
1218
|
-
if ("type" in schema && Array.isArray(schema.type)) {
|
|
1279
|
+
if (isObject(currentSchema) && "type" in schema && Array.isArray(schema.type)) {
|
|
1219
1280
|
const type = schema.type;
|
|
1220
1281
|
currentSchema = {
|
|
1221
1282
|
...currentSchema,
|
|
@@ -1227,17 +1288,18 @@ function getSchema$1(schema, context) {
|
|
|
1227
1288
|
refInfo
|
|
1228
1289
|
};
|
|
1229
1290
|
}
|
|
1291
|
+
/** Recursively resolves `$ref` entries in an examples array or record. */
|
|
1230
1292
|
function resolveExampleRefs(examples, context) {
|
|
1231
1293
|
if (!examples) return;
|
|
1232
1294
|
return Array.isArray(examples) ? examples.map((example) => {
|
|
1233
|
-
if (isReference(example)) {
|
|
1295
|
+
if (isObject(example) && isReference(example)) {
|
|
1234
1296
|
const { schema } = resolveRef(example, context);
|
|
1235
1297
|
return schema.value;
|
|
1236
1298
|
}
|
|
1237
1299
|
return example;
|
|
1238
1300
|
}) : (() => {
|
|
1239
1301
|
const result = {};
|
|
1240
|
-
for (const [key, example] of Object.entries(examples)) result[key] = isReference(example) ? resolveRef(example, context).schema.value : example;
|
|
1302
|
+
for (const [key, example] of Object.entries(examples)) result[key] = isObject(example) && isReference(example) ? resolveRef(example, context).schema.value : example;
|
|
1241
1303
|
return result;
|
|
1242
1304
|
})();
|
|
1243
1305
|
}
|
|
@@ -3120,7 +3182,7 @@ function generateModelsInline(obj) {
|
|
|
3120
3182
|
//#region src/generators/mutator-info.ts
|
|
3121
3183
|
async function getMutatorInfo(filePath, options) {
|
|
3122
3184
|
const { root = process.cwd(), namedExport = "default", alias, external, tsconfig } = options ?? {};
|
|
3123
|
-
return parseFile(await bundleFile(root,
|
|
3185
|
+
return parseFile(await bundleFile(root, filePath, alias, external, tsconfig?.compilerOptions), namedExport, getEcmaVersion(tsconfig?.compilerOptions?.target));
|
|
3124
3186
|
}
|
|
3125
3187
|
async function bundleFile(root, fileName, alias, external, compilerOptions) {
|
|
3126
3188
|
const { text } = (await build({
|
|
@@ -3217,10 +3279,8 @@ function getEcmaVersion(target) {
|
|
|
3217
3279
|
//#region src/generators/mutator.ts
|
|
3218
3280
|
const BODY_TYPE_NAME = "BodyType";
|
|
3219
3281
|
const getImport = (output, mutator) => {
|
|
3220
|
-
const
|
|
3221
|
-
|
|
3222
|
-
const { pathWithoutExtension } = getFileInfo(relativeSafe(outputFileInfo.dirname, mutatorFileInfo.path));
|
|
3223
|
-
return `${pathWithoutExtension}${mutator.extension ?? ""}`;
|
|
3282
|
+
const outputFile = getFileInfo(output).path;
|
|
3283
|
+
return `${getRelativeImportPath(outputFile, mutator.path)}${mutator.extension ?? ""}`;
|
|
3224
3284
|
};
|
|
3225
3285
|
async function generateMutator({ output, mutator, name, workspace, tsconfig }) {
|
|
3226
3286
|
if (!mutator || !output) return;
|
|
@@ -3236,7 +3296,7 @@ async function generateMutator({ output, mutator, name, workspace, tsconfig }) {
|
|
|
3236
3296
|
const errorTypeName = mutator.default ? `${pascal(name)}ErrorType` : "ErrorType";
|
|
3237
3297
|
const bodyTypeName = mutator.default ? `${pascal(name)}${BODY_TYPE_NAME}` : BODY_TYPE_NAME;
|
|
3238
3298
|
const mutatorInfo = await getMutatorInfo(importPath, {
|
|
3239
|
-
root:
|
|
3299
|
+
root: workspace,
|
|
3240
3300
|
namedExport: mutatorInfoName,
|
|
3241
3301
|
alias: mutator.alias,
|
|
3242
3302
|
external: mutator.external,
|
|
@@ -3911,19 +3971,26 @@ function getSchemaGroups(schemaPath, schemas, namingConvention, fileExtension) {
|
|
|
3911
3971
|
}
|
|
3912
3972
|
function getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtension) {
|
|
3913
3973
|
const canonicalPathMap = /* @__PURE__ */ new Map();
|
|
3974
|
+
const canonicalNameMap = /* @__PURE__ */ new Map();
|
|
3914
3975
|
for (const [key, groupSchemas] of Object.entries(schemaGroups)) {
|
|
3915
|
-
const
|
|
3916
|
-
|
|
3917
|
-
importPath: canonicalPath,
|
|
3976
|
+
const canonicalInfo = {
|
|
3977
|
+
importPath: getPath(schemaPath, conventionName(groupSchemas[0].name, namingConvention), fileExtension),
|
|
3918
3978
|
name: groupSchemas[0].name
|
|
3919
|
-
}
|
|
3979
|
+
};
|
|
3980
|
+
canonicalPathMap.set(key, canonicalInfo);
|
|
3981
|
+
for (const schema of groupSchemas) canonicalNameMap.set(schema.name, canonicalInfo);
|
|
3920
3982
|
}
|
|
3921
|
-
return
|
|
3983
|
+
return {
|
|
3984
|
+
canonicalPathMap,
|
|
3985
|
+
canonicalNameMap
|
|
3986
|
+
};
|
|
3922
3987
|
}
|
|
3923
|
-
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, schemaPath, namingConvention, fileExtension) {
|
|
3988
|
+
function normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension) {
|
|
3924
3989
|
for (const schema of schemas) schema.imports = schema.imports.map((imp) => {
|
|
3990
|
+
const canonicalByName = canonicalNameMap.get(imp.name);
|
|
3925
3991
|
const resolvedImportKey = resolveImportKey(schemaPath, imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`, fileExtension);
|
|
3926
|
-
const
|
|
3992
|
+
const canonicalByPath = canonicalPathMap.get(resolvedImportKey);
|
|
3993
|
+
const canonical = canonicalByName ?? canonicalByPath;
|
|
3927
3994
|
if (!canonical?.importPath) return imp;
|
|
3928
3995
|
const importPath = removeFileExtension(relativeSafe(schemaPath, canonical.importPath.replaceAll("\\", "/")), fileExtension);
|
|
3929
3996
|
return {
|
|
@@ -3963,7 +4030,7 @@ function getSchema({ schema: { imports, model }, target, header, namingConventio
|
|
|
3963
4030
|
return file;
|
|
3964
4031
|
}
|
|
3965
4032
|
function getPath(path, name, fileExtension) {
|
|
3966
|
-
return join(path,
|
|
4033
|
+
return nodePath.join(path, `${name}${fileExtension}`);
|
|
3967
4034
|
}
|
|
3968
4035
|
function writeModelInline(acc, model) {
|
|
3969
4036
|
return acc + `${model}\n`;
|
|
@@ -3983,12 +4050,13 @@ async function writeSchema({ path, schema, target, namingConvention, fileExtensi
|
|
|
3983
4050
|
namingConvention
|
|
3984
4051
|
}));
|
|
3985
4052
|
} catch (error) {
|
|
3986
|
-
throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${String(error)}
|
|
4053
|
+
throw new Error(`Oups... 🍻. An Error occurred while writing schema ${name} => ${String(error)}`, { cause: error });
|
|
3987
4054
|
}
|
|
3988
4055
|
}
|
|
3989
4056
|
async function writeSchemas({ schemaPath, schemas, target, namingConvention, fileExtension, header, indexFiles }) {
|
|
3990
4057
|
const schemaGroups = getSchemaGroups(schemaPath, schemas, namingConvention, fileExtension);
|
|
3991
|
-
|
|
4058
|
+
const { canonicalPathMap, canonicalNameMap } = getCanonicalMap(schemaGroups, schemaPath, namingConvention, fileExtension);
|
|
4059
|
+
normalizeCanonicalImportPaths(schemas, canonicalPathMap, canonicalNameMap, schemaPath, namingConvention, fileExtension);
|
|
3992
4060
|
for (const groupSchemas of Object.values(schemaGroups)) {
|
|
3993
4061
|
if (groupSchemas.length === 1) {
|
|
3994
4062
|
await writeSchema({
|
|
@@ -4011,7 +4079,7 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4011
4079
|
});
|
|
4012
4080
|
}
|
|
4013
4081
|
if (indexFiles) {
|
|
4014
|
-
const schemaFilePath = join(schemaPath,
|
|
4082
|
+
const schemaFilePath = nodePath.join(schemaPath, `index${fileExtension}`);
|
|
4015
4083
|
await fs$1.ensureFile(schemaFilePath);
|
|
4016
4084
|
const ext = fileExtension.endsWith(".ts") ? fileExtension.slice(0, -3) : fileExtension;
|
|
4017
4085
|
const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
|
|
@@ -4025,7 +4093,7 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4025
4093
|
const fileContent = `${header}\n${[...new Set([...existingExports, ...currentExports])].toSorted((a, b) => a.localeCompare(b)).join("\n")}`;
|
|
4026
4094
|
await fs$1.writeFile(schemaFilePath, fileContent, { encoding: "utf8" });
|
|
4027
4095
|
} catch (error) {
|
|
4028
|
-
throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${String(error)}
|
|
4096
|
+
throw new Error(`Oups... 🍻. An Error occurred while writing schema index file ${schemaFilePath} => ${String(error)}`, { cause: error });
|
|
4029
4097
|
}
|
|
4030
4098
|
}
|
|
4031
4099
|
}
|
|
@@ -4034,7 +4102,7 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
|
|
|
4034
4102
|
//#region src/writers/generate-imports-for-builder.ts
|
|
4035
4103
|
function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
4036
4104
|
const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
|
|
4037
|
-
let schemaImports
|
|
4105
|
+
let schemaImports;
|
|
4038
4106
|
if (output.indexFiles) schemaImports = isZodSchemaOutput ? [{
|
|
4039
4107
|
exports: imports.filter((i) => !i.importPath),
|
|
4040
4108
|
dependency: joinSafe(relativeSchemasPath, "index.zod")
|
|
@@ -4043,7 +4111,7 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
4043
4111
|
dependency: relativeSchemasPath
|
|
4044
4112
|
}];
|
|
4045
4113
|
else schemaImports = uniqueBy(imports.filter((i) => !i.importPath), (x) => x.name).map((i) => {
|
|
4046
|
-
const name = conventionName(i.schemaName ?? i.name, output.namingConvention);
|
|
4114
|
+
const name = conventionName(isZodSchemaOutput ? i.name : i.schemaName ?? i.name, output.namingConvention);
|
|
4047
4115
|
const suffix = isZodSchemaOutput ? ".zod" : "";
|
|
4048
4116
|
const importExtension = output.fileExtension.replace(/\.ts$/, "") || "";
|
|
4049
4117
|
return {
|
|
@@ -4051,7 +4119,7 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
|
|
|
4051
4119
|
dependency: joinSafe(relativeSchemasPath, `${name}${suffix}${importExtension}`)
|
|
4052
4120
|
};
|
|
4053
4121
|
});
|
|
4054
|
-
const otherImports = uniqueBy(imports.filter((i) => !!i.importPath), (x) => x.name +
|
|
4122
|
+
const otherImports = uniqueBy(imports.filter((i) => !!i.importPath), (x) => x.name + x.importPath).map((i) => {
|
|
4055
4123
|
return {
|
|
4056
4124
|
exports: [i],
|
|
4057
4125
|
dependency: i.importPath
|
|
@@ -4180,13 +4248,13 @@ interface TypedResponse<T> extends Response {
|
|
|
4180
4248
|
//#region src/writers/single-mode.ts
|
|
4181
4249
|
async function writeSingleMode({ builder, output, projectName, header, needSchema }) {
|
|
4182
4250
|
try {
|
|
4183
|
-
const { path
|
|
4251
|
+
const { path } = getFileInfo(output.target, {
|
|
4184
4252
|
backupFilename: conventionName(builder.info.title, output.namingConvention),
|
|
4185
4253
|
extension: output.fileExtension
|
|
4186
4254
|
});
|
|
4187
4255
|
const { imports, importsMock, implementation, implementationMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
|
|
4188
4256
|
let data = header;
|
|
4189
|
-
const schemasPath = output.schemas ?
|
|
4257
|
+
const schemasPath = output.schemas ? getRelativeImportPath(path, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : void 0;
|
|
4190
4258
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4191
4259
|
const importsForBuilder = schemasPath ? generateImportsForBuilder(output, imports.filter((imp) => !importsMock.some((impMock) => imp.name === impMock.name)), schemasPath) : [];
|
|
4192
4260
|
data += builder.imports({
|
|
@@ -4240,7 +4308,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4240
4308
|
return [path];
|
|
4241
4309
|
} catch (error) {
|
|
4242
4310
|
const errorMsg = error instanceof Error ? error.message : "unknown error";
|
|
4243
|
-
throw new Error(`Oups... 🍻. An Error occurred while writing file => ${errorMsg}
|
|
4311
|
+
throw new Error(`Oups... 🍻. An Error occurred while writing file => ${errorMsg}`, { cause: error });
|
|
4244
4312
|
}
|
|
4245
4313
|
}
|
|
4246
4314
|
|
|
@@ -4248,14 +4316,14 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
|
|
|
4248
4316
|
//#region src/writers/split-mode.ts
|
|
4249
4317
|
async function writeSplitMode({ builder, output, projectName, header, needSchema }) {
|
|
4250
4318
|
try {
|
|
4251
|
-
const { filename, dirname, extension } = getFileInfo(output.target, {
|
|
4319
|
+
const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
|
|
4252
4320
|
backupFilename: conventionName(builder.info.title, output.namingConvention),
|
|
4253
4321
|
extension: output.fileExtension
|
|
4254
4322
|
});
|
|
4255
4323
|
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
|
|
4256
4324
|
let implementationData = header;
|
|
4257
4325
|
let mockData = header;
|
|
4258
|
-
const relativeSchemasPath = output.schemas ?
|
|
4326
|
+
const relativeSchemasPath = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
|
|
4259
4327
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4260
4328
|
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
4261
4329
|
implementationData += builder.imports({
|
|
@@ -4280,10 +4348,10 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4280
4348
|
isAllowSyntheticDefaultImports,
|
|
4281
4349
|
options: isFunction(output.mock) ? void 0 : output.mock
|
|
4282
4350
|
});
|
|
4283
|
-
const schemasPath = output.schemas ? void 0 : join(dirname, filename + ".schemas" + extension);
|
|
4351
|
+
const schemasPath = output.schemas ? void 0 : nodePath.join(dirname, filename + ".schemas" + extension);
|
|
4284
4352
|
if (schemasPath && needSchema) {
|
|
4285
4353
|
const schemasData = header + generateModelsInline(builder.schemas);
|
|
4286
|
-
await fs$1.outputFile(
|
|
4354
|
+
await fs$1.outputFile(schemasPath, schemasData);
|
|
4287
4355
|
}
|
|
4288
4356
|
if (mutators) implementationData += generateMutatorImports({
|
|
4289
4357
|
mutators,
|
|
@@ -4305,9 +4373,9 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4305
4373
|
implementationData += `\n${implementation}`;
|
|
4306
4374
|
mockData += `\n${implementationMock}`;
|
|
4307
4375
|
const implementationFilename = filename + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
4308
|
-
const implementationPath = join(dirname, implementationFilename);
|
|
4309
|
-
await fs$1.outputFile(
|
|
4310
|
-
const mockPath = output.mock ? join(dirname, filename + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
|
|
4376
|
+
const implementationPath = nodePath.join(dirname, implementationFilename);
|
|
4377
|
+
await fs$1.outputFile(implementationPath, implementationData);
|
|
4378
|
+
const mockPath = output.mock ? nodePath.join(dirname, filename + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
|
|
4311
4379
|
if (mockPath) await fs$1.outputFile(mockPath, mockData);
|
|
4312
4380
|
return [
|
|
4313
4381
|
implementationPath,
|
|
@@ -4315,7 +4383,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
|
|
|
4315
4383
|
...mockPath ? [mockPath] : []
|
|
4316
4384
|
];
|
|
4317
4385
|
} catch (error) {
|
|
4318
|
-
throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}
|
|
4386
|
+
throw new Error(`Oups... 🍻. An Error occurred while splitting => ${String(error)}`, { cause: error });
|
|
4319
4387
|
}
|
|
4320
4388
|
}
|
|
4321
4389
|
|
|
@@ -4444,7 +4512,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4444
4512
|
const target = generateTargetForTags(builder, output);
|
|
4445
4513
|
const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
|
|
4446
4514
|
const mockOption = output.mock && !isFunction(output.mock) ? output.mock : void 0;
|
|
4447
|
-
const indexFilePath = mockOption?.indexMockFiles ? join(dirname, "index." + getMockFileExtensionByTypeName(mockOption) + extension) : void 0;
|
|
4515
|
+
const indexFilePath = mockOption?.indexMockFiles ? nodePath.join(dirname, "index." + getMockFileExtensionByTypeName(mockOption) + extension) : void 0;
|
|
4448
4516
|
if (indexFilePath) await fs$1.outputFile(indexFilePath, "");
|
|
4449
4517
|
const tagEntries = Object.entries(target);
|
|
4450
4518
|
const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
|
|
@@ -4452,7 +4520,8 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4452
4520
|
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer } = target;
|
|
4453
4521
|
let implementationData = header;
|
|
4454
4522
|
let mockData = header;
|
|
4455
|
-
const
|
|
4523
|
+
const importerPath = nodePath.join(dirname, tag, tag + extension);
|
|
4524
|
+
const relativeSchemasPath = output.schemas ? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas";
|
|
4456
4525
|
const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
|
|
4457
4526
|
implementationData += builder.imports({
|
|
4458
4527
|
client: output.client,
|
|
@@ -4476,7 +4545,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4476
4545
|
isAllowSyntheticDefaultImports,
|
|
4477
4546
|
options: isFunction(output.mock) ? void 0 : output.mock
|
|
4478
4547
|
});
|
|
4479
|
-
const schemasPath = output.schemas ? void 0 : join(dirname, filename + ".schemas" + extension);
|
|
4548
|
+
const schemasPath = output.schemas ? void 0 : nodePath.join(dirname, filename + ".schemas" + extension);
|
|
4480
4549
|
if (schemasPath && needSchema) {
|
|
4481
4550
|
const schemasData = header + generateModelsInline(builder.schemas);
|
|
4482
4551
|
await fs$1.outputFile(schemasPath, schemasData);
|
|
@@ -4517,9 +4586,9 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4517
4586
|
implementationData += `\n${implementation}`;
|
|
4518
4587
|
mockData += `\n${implementationMock}`;
|
|
4519
4588
|
const implementationFilename = tag + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
|
|
4520
|
-
const implementationPath = join(dirname, tag, implementationFilename);
|
|
4589
|
+
const implementationPath = nodePath.join(dirname, tag, implementationFilename);
|
|
4521
4590
|
await fs$1.outputFile(implementationPath, implementationData);
|
|
4522
|
-
const mockPath = output.mock ? join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
|
|
4591
|
+
const mockPath = output.mock ? nodePath.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
|
|
4523
4592
|
if (mockPath) await fs$1.outputFile(mockPath, mockData);
|
|
4524
4593
|
return [
|
|
4525
4594
|
implementationPath,
|
|
@@ -4527,7 +4596,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4527
4596
|
...mockPath ? [mockPath] : []
|
|
4528
4597
|
];
|
|
4529
4598
|
} catch (error) {
|
|
4530
|
-
throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}
|
|
4599
|
+
throw new Error(`Oups... 🍻. An Error occurred while splitting tag ${tag} => ${String(error)}`, { cause: error });
|
|
4531
4600
|
}
|
|
4532
4601
|
}));
|
|
4533
4602
|
if (indexFilePath && mockOption) {
|
|
@@ -4543,7 +4612,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
|
|
|
4543
4612
|
//#endregion
|
|
4544
4613
|
//#region src/writers/tags-mode.ts
|
|
4545
4614
|
async function writeTagsMode({ builder, output, projectName, header, needSchema }) {
|
|
4546
|
-
const { filename, dirname, extension } = getFileInfo(output.target, {
|
|
4615
|
+
const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
|
|
4547
4616
|
backupFilename: conventionName(builder.info.title, output.namingConvention),
|
|
4548
4617
|
extension: output.fileExtension
|
|
4549
4618
|
});
|
|
@@ -4553,7 +4622,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
|
|
|
4553
4622
|
try {
|
|
4554
4623
|
const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer } = target;
|
|
4555
4624
|
let data = header;
|
|
4556
|
-
const schemasPathRelative = output.schemas ?
|
|
4625
|
+
const schemasPathRelative = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
|
|
4557
4626
|
const importsForBuilder = generateImportsForBuilder(output, imports.filter((imp) => !importsMock.some((impMock) => imp.name === impMock.name)), schemasPathRelative);
|
|
4558
4627
|
data += builder.imports({
|
|
4559
4628
|
client: output.client,
|
|
@@ -4579,7 +4648,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
|
|
|
4579
4648
|
options: isFunction(output.mock) ? void 0 : output.mock
|
|
4580
4649
|
});
|
|
4581
4650
|
}
|
|
4582
|
-
const schemasPath = output.schemas ? void 0 : join(dirname, filename + ".schemas" + extension);
|
|
4651
|
+
const schemasPath = output.schemas ? void 0 : nodePath.join(dirname, filename + ".schemas" + extension);
|
|
4583
4652
|
if (schemasPath && needSchema) {
|
|
4584
4653
|
const schemasData = header + generateModelsInline(builder.schemas);
|
|
4585
4654
|
await fs$1.outputFile(schemasPath, schemasData);
|
|
@@ -4607,11 +4676,11 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
|
|
|
4607
4676
|
data += "\n\n";
|
|
4608
4677
|
data += implementationMock;
|
|
4609
4678
|
}
|
|
4610
|
-
const implementationPath = join(dirname, `${kebab(tag)}${extension}`);
|
|
4679
|
+
const implementationPath = nodePath.join(dirname, `${kebab(tag)}${extension}`);
|
|
4611
4680
|
await fs$1.outputFile(implementationPath, data);
|
|
4612
4681
|
return [implementationPath, ...schemasPath ? [schemasPath] : []];
|
|
4613
4682
|
} catch (error) {
|
|
4614
|
-
throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${String(error)}
|
|
4683
|
+
throw new Error(`Oups... 🍻. An Error occurred while writing tag ${tag} => ${String(error)}`, { cause: error });
|
|
4615
4684
|
}
|
|
4616
4685
|
}))).flat();
|
|
4617
4686
|
}
|