@orval/core 8.6.2 → 8.7.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.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 path from "node:path";
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";
@@ -17,6 +17,11 @@ import { Parser } from "acorn";
17
17
  import { build } from "esbuild";
18
18
 
19
19
  //#region src/types.ts
20
+ const SupportedFormatter = {
21
+ PRETTIER: "prettier",
22
+ BIOME: "biome",
23
+ OXFMT: "oxfmt"
24
+ };
20
25
  const PropertySortOrder = {
21
26
  ALPHABETICAL: "Alphabetical",
22
27
  SPECIFICATION: "Specification"
@@ -135,7 +140,7 @@ function isReference(obj) {
135
140
  return !isNullish$1(obj) && Object.hasOwn(obj, "$ref");
136
141
  }
137
142
  function isDirectory(pathValue) {
138
- return !path.extname(pathValue);
143
+ return !nodePath.extname(pathValue);
139
144
  }
140
145
  function isObject(x) {
141
146
  return Object.prototype.toString.call(x) === "[object Object]";
@@ -281,37 +286,19 @@ function compareVersions(firstVersion, secondVersions, operator = ">=") {
281
286
 
282
287
  //#endregion
283
288
  //#region src/utils/content-type.ts
289
+ const binaryApplicationTypes = new Set(["application/octet-stream", "application/pdf"]);
284
290
  /**
285
- * Determine if a content type is binary (vs text-based).
291
+ * Determine if a content type is binary.
292
+ * Only known binary types return true. Unknown types default to false (non-binary)
293
+ * so that schema type information is preserved rather than being overridden with Blob.
286
294
  */
287
295
  function isBinaryContentType(contentType) {
288
- if (contentType === "application/octet-stream") return true;
289
- if (contentType.startsWith("image/")) return true;
290
- if (contentType.startsWith("audio/")) return true;
291
- if (contentType.startsWith("video/")) return true;
292
- if (contentType.startsWith("font/")) return true;
293
- if (contentType.startsWith("text/")) return false;
294
- if ([
295
- "+json",
296
- "-json",
297
- "+xml",
298
- "-xml",
299
- "+yaml",
300
- "-yaml",
301
- "+rss",
302
- "-rss",
303
- "+csv",
304
- "-csv"
305
- ].some((suffix) => contentType.includes(suffix))) return false;
306
- return !new Set([
307
- "application/json",
308
- "application/xml",
309
- "application/yaml",
310
- "application/x-www-form-urlencoded",
311
- "application/javascript",
312
- "application/ecmascript",
313
- "application/graphql"
314
- ]).has(contentType);
296
+ const baseType = contentType.split(";")[0].trim();
297
+ if (baseType.startsWith("image/")) return true;
298
+ if (baseType.startsWith("audio/")) return true;
299
+ if (baseType.startsWith("video/")) return true;
300
+ if (baseType.startsWith("font/")) return true;
301
+ return binaryApplicationTypes.has(baseType);
315
302
  }
316
303
  /**
317
304
  * Determine if a form-data field should be treated as a file (binary or text).
@@ -469,8 +456,8 @@ async function dynamicImport(toImport, from = process.cwd(), takeDefault = true)
469
456
  if (!toImport) return toImport;
470
457
  try {
471
458
  if (isString(toImport)) {
472
- const filePath = path.resolve(from, toImport);
473
- const extension = path.extname(filePath);
459
+ const filePath = nodePath.resolve(from, toImport);
460
+ const extension = nodePath.extname(filePath);
474
461
  if (TS_MODULE_EXTENSIONS.has(extension)) {
475
462
  const data = await createJiti(from, { interopDefault: true }).import(filePath);
476
463
  if (takeDefault && (isObject(data) || isModule(data)) && data.default) return data.default;
@@ -497,14 +484,14 @@ function getExtension(path) {
497
484
  //#region src/utils/file.ts
498
485
  function getFileInfo(target = "", { backupFilename = "filename", extension = ".ts" } = {}) {
499
486
  const isDir = isDirectory(target);
500
- const filePath = isDir ? path.join(target, backupFilename + extension) : target;
487
+ const filePath = isDir ? nodePath.join(target, backupFilename + extension) : target;
501
488
  return {
502
489
  path: filePath,
503
490
  pathWithoutExtension: filePath.replace(/\.[^/.]+$/, ""),
504
491
  extension,
505
492
  isDirectory: isDir,
506
- dirname: path.dirname(filePath),
507
- filename: path.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
493
+ dirname: nodePath.dirname(filePath),
494
+ filename: nodePath.basename(filePath, extension.startsWith(".") ? extension : `.${extension}`)
508
495
  };
509
496
  }
510
497
  async function removeFilesAndEmptyFolders(patterns, dir) {
@@ -566,6 +553,17 @@ function getIsBodyVerb(verb) {
566
553
  //#endregion
567
554
  //#region src/utils/logger.ts
568
555
  const log = console.log;
556
+ let _warningCount = 0;
557
+ function logWarning(message) {
558
+ _warningCount++;
559
+ log(styleText("yellow", message));
560
+ }
561
+ function getWarningCount() {
562
+ return _warningCount;
563
+ }
564
+ function resetWarnings() {
565
+ _warningCount = 0;
566
+ }
569
567
  let _verbose = false;
570
568
  function setVerbose(v) {
571
569
  _verbose = v;
@@ -595,7 +593,7 @@ function logError(err, tag) {
595
593
  ].filter(Boolean).join(" ")));
596
594
  }
597
595
  function mismatchArgsMessage(mismatchArgs) {
598
- log(styleText("yellow", `${mismatchArgs.join(", ")} ${mismatchArgs.length === 1 ? "is" : "are"} not defined in your configuration!`));
596
+ logWarning(`${mismatchArgs.join(", ")} ${mismatchArgs.length === 1 ? "is" : "are"} not defined in your configuration!`);
599
597
  }
600
598
  function createSuccessMessage(backend) {
601
599
  log(`🎉 ${backend ? `${styleText("green", backend)} - ` : ""}Your OpenAPI spec has been converted into ready to use orval!`);
@@ -708,13 +706,13 @@ function toUnix(value) {
708
706
  return value;
709
707
  }
710
708
  function join(...args) {
711
- return toUnix(path.join(...args.map((a) => toUnix(a))));
709
+ return toUnix(nodePath.join(...args.map((a) => toUnix(a))));
712
710
  }
713
711
  /**
714
712
  * Behaves exactly like `path.relative(from, to)`, but keeps the first meaningful "./"
715
713
  */
716
714
  function relativeSafe(from, to) {
717
- return normalizeSafe(`.${separator}${toUnix(path.relative(toUnix(from), toUnix(to)))}`);
715
+ return normalizeSafe(`.${separator}${toUnix(nodePath.relative(toUnix(from), toUnix(to)))}`);
718
716
  }
719
717
  function getSchemaFileName(path) {
720
718
  return path.replace(`.${getExtension(path)}`, "").slice(path.lastIndexOf("/") + 1);
@@ -723,13 +721,13 @@ const separator = "/";
723
721
  function normalizeSafe(value) {
724
722
  let result;
725
723
  value = toUnix(value);
726
- result = toUnix(path.normalize(value));
724
+ result = toUnix(nodePath.normalize(value));
727
725
  if (value.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
728
726
  else if (value.startsWith("//") && !result.startsWith("//")) result = value.startsWith("//./") ? "//." + result : "/" + result;
729
727
  return result;
730
728
  }
731
729
  function joinSafe(...values) {
732
- let result = toUnix(path.join(...values.map((v) => toUnix(v))));
730
+ let result = toUnix(nodePath.join(...values.map((v) => toUnix(v))));
733
731
  if (values.length > 0) {
734
732
  const firstValue = toUnix(values[0]);
735
733
  if (firstValue.startsWith("./") && !result.startsWith("./") && !result.startsWith("..")) result = "./" + result;
@@ -760,14 +758,14 @@ function joinSafe(...values) {
760
758
  * @returns The relative import path string.
761
759
  */
762
760
  function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileExtension = false) {
763
- if (!path.isAbsolute(importerFilePath)) throw new Error(`'importerFilePath' is not an absolute path. "${importerFilePath}"`);
764
- if (!path.isAbsolute(exporterFilePath)) throw new Error(`'exporterFilePath' is not an absolute path. "${exporterFilePath}"`);
765
- const importerDir = path.dirname(importerFilePath);
766
- const relativePath = path.relative(importerDir, exporterFilePath);
767
- let posixPath = path.posix.join(...relativePath.split(path.sep));
761
+ if (!nodePath.isAbsolute(importerFilePath)) throw new Error(`'importerFilePath' is not an absolute path. "${importerFilePath}"`);
762
+ if (!nodePath.isAbsolute(exporterFilePath)) throw new Error(`'exporterFilePath' is not an absolute path. "${exporterFilePath}"`);
763
+ const importerDir = nodePath.dirname(importerFilePath);
764
+ const relativePath = nodePath.relative(importerDir, exporterFilePath);
765
+ let posixPath = nodePath.posix.join(...relativePath.split(nodePath.sep));
768
766
  if (!posixPath.startsWith("./") && !posixPath.startsWith("../")) posixPath = `./${posixPath}`;
769
767
  if (!includeFileExtension) {
770
- const ext = path.extname(posixPath);
768
+ const ext = nodePath.extname(posixPath);
771
769
  if (ext && posixPath.endsWith(ext)) posixPath = posixPath.slice(0, -ext.length);
772
770
  }
773
771
  return posixPath;
@@ -777,20 +775,20 @@ function getRelativeImportPath(importerFilePath, exporterFilePath, includeFileEx
777
775
  //#region src/utils/resolve-version.ts
778
776
  function resolveInstalledVersion(packageName, fromDir) {
779
777
  try {
780
- const require = createRequire(path.join(fromDir, "noop.js"));
778
+ const require = createRequire(nodePath.join(fromDir, "noop.js"));
781
779
  try {
782
780
  return require(`${packageName}/package.json`).version;
783
781
  } catch (directError) {
784
782
  if (directError instanceof Error && "code" in directError && directError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
785
783
  const entryPath = require.resolve(packageName);
786
- let dir = path.dirname(entryPath);
787
- while (dir !== path.parse(dir).root) {
788
- const pkgPath = path.join(dir, "package.json");
784
+ let dir = nodePath.dirname(entryPath);
785
+ while (dir !== nodePath.parse(dir).root) {
786
+ const pkgPath = nodePath.join(dir, "package.json");
789
787
  if (existsSync(pkgPath)) {
790
788
  const pkgData = JSON.parse(readFileSync(pkgPath, "utf8"));
791
789
  if (pkgData.name === packageName) return pkgData.version;
792
790
  }
793
- dir = path.dirname(dir);
791
+ dir = nodePath.dirname(dir);
794
792
  }
795
793
  return;
796
794
  }
@@ -1389,7 +1387,8 @@ function resolveValue({ schema, name, context, formDataContext }) {
1389
1387
  }
1390
1388
  }).hasReadonlyProps;
1391
1389
  const isAnyOfNullable = schemaObject.anyOf?.some((anyOfItem) => !isReference(anyOfItem) && (anyOfItem.type === "null" || Array.isArray(anyOfItem.type) && anyOfItem.type.includes("null")));
1392
- const nullable = Array.isArray(schemaObject.type) && schemaObject.type.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
1390
+ const schemaType = schemaObject.type;
1391
+ const nullable = Array.isArray(schemaType) && schemaType.includes("null") || schemaObject.nullable === true || isAnyOfNullable ? " | null" : "";
1393
1392
  return {
1394
1393
  value: resolvedImport.name + nullable,
1395
1394
  imports: [{
@@ -1595,6 +1594,8 @@ const getSchemaAnyOf = (s) => s.anyOf;
1595
1594
  const getSchemaItems = (s) => s.items;
1596
1595
  const getSchemaRequired = (s) => s.required;
1597
1596
  const getSchemaProperties = (s) => s.properties;
1597
+ const resolveSchemaRef = (schema, context) => resolveRef(schema, context);
1598
+ const resolveResponseOrRequestRef = (schema, context) => resolveRef(schema, context);
1598
1599
  const formDataContentTypes = new Set(["multipart/form-data"]);
1599
1600
  const formUrlEncodedContentTypes = new Set(["application/x-www-form-urlencoded"]);
1600
1601
  function getResReqContentTypes({ mediaType, propName, context, isFormData, contentType }) {
@@ -1618,7 +1619,7 @@ function getResReqContentTypes({ mediaType, propName, context, isFormData, conte
1618
1619
  function getResReqTypes(responsesOrRequests, name, context, defaultType = "unknown", uniqueKey = (item) => item.value) {
1619
1620
  return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
1620
1621
  if (isReference(res)) {
1621
- const { schema: bodySchema, imports: [{ name, schemaName }] } = resolveRef(res, context);
1622
+ const { schema: bodySchema, imports: [{ name, schemaName }] } = resolveResponseOrRequestRef(res, context);
1622
1623
  const firstEntry = Object.entries(bodySchema.content ?? {}).at(0);
1623
1624
  if (!firstEntry) return [{
1624
1625
  value: name,
@@ -1706,7 +1707,7 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1706
1707
  if (propName && arr.length > 1) propName = propName + pascal(getNumberWord(index + 1));
1707
1708
  let effectivePropName = propName;
1708
1709
  if (mediaType.schema && isReference(mediaType.schema)) {
1709
- const { imports } = resolveRef(mediaType.schema, context);
1710
+ const { imports } = resolveSchemaRef(mediaType.schema, context);
1710
1711
  if (imports[0]?.name) effectivePropName = imports[0].name;
1711
1712
  }
1712
1713
  const isFormData = formDataContentTypes.has(contentType);
@@ -1836,14 +1837,14 @@ function getDefaultContentType(contentTypes) {
1836
1837
  return contentTypes[0];
1837
1838
  }
1838
1839
  function getFormDataAdditionalImports({ schemaObject, context }) {
1839
- const { schema } = resolveRef(schemaObject, context);
1840
+ const { schema } = resolveSchemaRef(schemaObject, context);
1840
1841
  if (schema.type !== "object") return [];
1841
1842
  const combinedSchemas = getSchemaOneOf(schema) ?? getSchemaAnyOf(schema);
1842
1843
  if (!combinedSchemas) return [];
1843
- return combinedSchemas.map((subSchema) => resolveRef(subSchema, context).imports[0]).filter(Boolean);
1844
+ return combinedSchemas.map((subSchema) => resolveSchemaRef(subSchema, context).imports[0]).filter(Boolean);
1844
1845
  }
1845
1846
  function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequestBodyOptional, isUrlEncoded, isRef, encoding }) {
1846
- const { schema, imports } = resolveRef(schemaObject, context);
1847
+ const { schema, imports } = resolveSchemaRef(schemaObject, context);
1847
1848
  const propName = camel(!isRef && isReference(schemaObject) ? imports[0].name : name);
1848
1849
  const additionalImports = [];
1849
1850
  const variableName = isUrlEncoded ? "formUrlEncoded" : "formData";
@@ -1853,7 +1854,7 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
1853
1854
  if (combinedSchemas) {
1854
1855
  const shouldCast = !!getSchemaOneOf(schema) || !!getSchemaAnyOf(schema);
1855
1856
  const combinedSchemasFormData = combinedSchemas.map((subSchema) => {
1856
- const { schema: combinedSchema, imports } = resolveRef(subSchema, context);
1857
+ const { schema: combinedSchema, imports } = resolveSchemaRef(subSchema, context);
1857
1858
  let newPropName = propName;
1858
1859
  let newPropDefinition = "";
1859
1860
  if (shouldCast && imports[0]) {
@@ -1889,7 +1890,7 @@ function getSchemaFormDataAndUrlEncoded({ name, schemaObject, context, isRequest
1889
1890
  let valueStr = "value";
1890
1891
  const schemaItems = getSchemaItems(schema);
1891
1892
  if (schemaItems) {
1892
- const { schema: itemSchema } = resolveRef(schemaItems, context);
1893
+ const { schema: itemSchema } = resolveSchemaRef(schemaItems, context);
1893
1894
  if (itemSchema.type === "object" || itemSchema.type === "array") valueStr = "JSON.stringify(value)";
1894
1895
  else if (itemSchema.type === "number" || itemSchema.type === "integer" || itemSchema.type === "boolean") valueStr = "value.toString()";
1895
1896
  }
@@ -1902,7 +1903,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
1902
1903
  let formDataValues = "";
1903
1904
  const schemaProps = getSchemaProperties(schema) ?? {};
1904
1905
  for (const [key, value] of Object.entries(schemaProps)) {
1905
- const { schema: property } = resolveRef(value, context);
1906
+ const { schema: property } = resolveSchemaRef(value, context);
1906
1907
  if (property.readOnly) continue;
1907
1908
  let formDataValue = "";
1908
1909
  const partContentType = (depth === 0 ? encoding?.[key] : void 0)?.contentType;
@@ -1929,7 +1930,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
1929
1930
  let hasNonPrimitiveChild = false;
1930
1931
  const propertyItems = getSchemaItems(property);
1931
1932
  if (propertyItems) {
1932
- const { schema: itemSchema } = resolveRef(propertyItems, context);
1933
+ const { schema: itemSchema } = resolveSchemaRef(propertyItems, context);
1933
1934
  if (itemSchema.type === "object" || itemSchema.type === "array") if (context.output.override.formData.arrayHandling === FormDataArrayHandling.EXPLODE) {
1934
1935
  hasNonPrimitiveChild = true;
1935
1936
  const resolvedValue = resolveSchemaPropertiesToFormData({
@@ -1997,8 +1998,7 @@ function resolveSchemaPropertiesToFormData({ schema, variableName, propName, con
1997
1998
 
1998
1999
  //#endregion
1999
2000
  //#region src/getters/body.ts
2000
- function getBody({ requestBody, operationName, context, contentType }) {
2001
- const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType);
2001
+ function buildBody(filteredBodyTypes, requestBody, operationName, context) {
2002
2002
  const imports = filteredBodyTypes.flatMap(({ imports }) => imports);
2003
2003
  const schemas = filteredBodyTypes.flatMap(({ schemas }) => schemas);
2004
2004
  const definition = filteredBodyTypes.map(({ value }) => value).join(" | ");
@@ -2036,6 +2036,40 @@ function getBody({ requestBody, operationName, context, contentType }) {
2036
2036
  }
2037
2037
  };
2038
2038
  }
2039
+ function getBody({ requestBody, operationName, context, contentType }) {
2040
+ return buildBody(filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context), contentType), requestBody, operationName, context);
2041
+ }
2042
+ /**
2043
+ * Returns per-content-type bodies when `splitByContentType` is enabled.
2044
+ * Each entry includes a `contentTypeSuffix` for generating distinct function names.
2045
+ */
2046
+ function getBodiesByContentType({ requestBody, operationName, context, contentType }) {
2047
+ const filteredBodyTypes = filterByContentType(getResReqTypes([[context.output.override.components.requestBodies.suffix, requestBody]], operationName, context, void 0, (item) => `${item.value}::${item.contentType}`), contentType);
2048
+ if (filteredBodyTypes.length <= 1) return [{
2049
+ ...buildBody(filteredBodyTypes, requestBody, operationName, context),
2050
+ contentTypeSuffix: ""
2051
+ }];
2052
+ return filteredBodyTypes.map((bodyType) => {
2053
+ const suffix = getContentTypeSuffix(bodyType.contentType);
2054
+ return {
2055
+ ...buildBody([bodyType], requestBody, operationName, context),
2056
+ contentTypeSuffix: suffix
2057
+ };
2058
+ });
2059
+ }
2060
+ const CONTENT_TYPE_SUFFIX_MAP = {
2061
+ "application/json": "Json",
2062
+ "multipart/form-data": "FormData",
2063
+ "application/x-www-form-urlencoded": "UrlEncoded",
2064
+ "text/plain": "Text",
2065
+ "application/xml": "Xml",
2066
+ "text/xml": "Xml",
2067
+ "application/octet-stream": "Blob"
2068
+ };
2069
+ function getContentTypeSuffix(contentType) {
2070
+ if (CONTENT_TYPE_SUFFIX_MAP[contentType]) return CONTENT_TYPE_SUFFIX_MAP[contentType];
2071
+ return (contentType.split("/")[1] ?? contentType).split(/[-+.]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
2072
+ }
2039
2073
 
2040
2074
  //#endregion
2041
2075
  //#region src/getters/imports.ts
@@ -2405,7 +2439,9 @@ function getScalar({ item, name, context, formDataContext }) {
2405
2439
  };
2406
2440
  }
2407
2441
  case "boolean": {
2408
- let value = "boolean" + nullable;
2442
+ let value = "boolean";
2443
+ if (enumItems && !(enumItems.includes(true) && enumItems.includes(false))) value = enumItems.map((enumItem) => `${enumItem}`).join(" | ");
2444
+ value += nullable;
2409
2445
  if (schemaConst !== void 0) value = schemaConst;
2410
2446
  return {
2411
2447
  value,
@@ -2739,12 +2775,21 @@ function resolveDiscriminators(schemas, context) {
2739
2775
  hasProperty: false,
2740
2776
  value: void 0
2741
2777
  };
2742
- const mergedEnumValues = [...((enumProperty.hasProperty && Array.isArray(enumProperty.value) ? enumProperty.value : void 0) ?? []).filter((value) => value !== mappingKey), mappingKey];
2778
+ const enumValues = enumProperty.hasProperty && Array.isArray(enumProperty.value) ? enumProperty.value : void 0;
2779
+ const propertyType = schemaProperty?.type ?? "string";
2780
+ let typedMappingKey = mappingKey;
2781
+ if (propertyType === "boolean") typedMappingKey = mappingKey === "true";
2782
+ else if (propertyType === "number" || propertyType === "integer") {
2783
+ const parsed = Number(mappingKey);
2784
+ if (!Number.isNaN(parsed)) typedMappingKey = parsed;
2785
+ }
2786
+ const mergedEnumValues = [...(enumValues ?? []).filter((value) => value !== typedMappingKey), typedMappingKey];
2743
2787
  const mergedProperty = {
2744
2788
  ...schemaProperty,
2745
- type: "string",
2789
+ type: propertyType,
2746
2790
  enum: mergedEnumValues
2747
2791
  };
2792
+ delete mergedProperty.const;
2748
2793
  subTypeSchema.properties = {
2749
2794
  ...subTypeSchema.properties,
2750
2795
  [propertyName]: mergedProperty
@@ -2777,8 +2822,10 @@ function getParameters({ parameters, context }) {
2777
2822
  header: []
2778
2823
  };
2779
2824
  for (const p of parameters) if (isReference(p)) {
2780
- const { schema: parameter, imports } = resolveRef(p, context);
2781
- if (parameter.in === "path" || parameter.in === "query" || parameter.in === "header") result[parameter.in].push({
2825
+ const { schema, imports } = resolveRef(p, context);
2826
+ const parameter = schema;
2827
+ const location = parameter.in;
2828
+ if (location === "path" || location === "query" || location === "header") result[location].push({
2782
2829
  parameter,
2783
2830
  imports
2784
2831
  });
@@ -3028,7 +3075,7 @@ function getResponse({ responses, operationName, context, contentType }) {
3028
3075
  success: success || (defaultType ?? "unknown"),
3029
3076
  errors: errors || (defaultType ?? "unknown")
3030
3077
  },
3031
- isBlob: success === "Blob",
3078
+ isBlob: groupedByStatus.success.some((t) => !!t.contentType && isBinaryContentType(t.contentType)),
3032
3079
  types: groupedByStatus,
3033
3080
  contentTypes,
3034
3081
  schemas,
@@ -3038,7 +3085,18 @@ function getResponse({ responses, operationName, context, contentType }) {
3038
3085
 
3039
3086
  //#endregion
3040
3087
  //#region src/getters/route.ts
3041
- const TEMPLATE_TAG_IN_PATH_REGEX = /\/([\w]+)(?:\$\{)/g;
3088
+ function isBaseUrlRuntime(baseUrl) {
3089
+ return isObject(baseUrl) && "runtime" in baseUrl && typeof baseUrl.runtime === "string";
3090
+ }
3091
+ /**
3092
+ * Wraps a runtime expression for generated URL template literals.
3093
+ * Pass the expression only (e.g. `process.env.API_BASE_URL`), not a `${...}` fragment.
3094
+ */
3095
+ function runtimeExpressionToUrlPrefix(expression) {
3096
+ const t = expression.trim();
3097
+ if (!t) return "";
3098
+ return "${" + t + "}";
3099
+ }
3042
3100
  const hasParam = (path) => /[^{]*{[\w*_-]*}.*/.test(path);
3043
3101
  const getRoutePath = (path) => {
3044
3102
  const matches = /([^{]*){?([\w*_-]*)}?(.*)/.exec(path);
@@ -3068,6 +3126,7 @@ function getFullRoute(route, servers, baseUrl) {
3068
3126
  const getBaseUrl = () => {
3069
3127
  if (!baseUrl) return "";
3070
3128
  if (isString(baseUrl)) return baseUrl;
3129
+ if (isBaseUrlRuntime(baseUrl)) return runtimeExpressionToUrlPrefix(baseUrl.runtime);
3071
3130
  if (baseUrl.getBaseUrlFromSpecification) {
3072
3131
  if (!servers) throw new Error("Orval is configured to use baseUrl from the specifications 'servers' field, but there exist no servers in the specification.");
3073
3132
  const server = servers.at(Math.min(baseUrl.index ?? 0, servers.length - 1));
@@ -3095,8 +3154,22 @@ function getFullRoute(route, servers, baseUrl) {
3095
3154
  }
3096
3155
  return fullRoute;
3097
3156
  }
3157
+ /**
3158
+ * Returns `GeneratorImport` entries for {@link BaseUrlRuntime.imports} when `baseUrl` is a runtime config.
3159
+ */
3160
+ function getBaseUrlRuntimeImports(baseUrl) {
3161
+ if (!baseUrl) return [];
3162
+ if (!isBaseUrlRuntime(baseUrl)) return [];
3163
+ return baseUrl.imports ?? [];
3164
+ }
3098
3165
  function getRouteAsArray(route) {
3099
- return route.replaceAll(TEMPLATE_TAG_IN_PATH_REGEX, "/$1/${").split("/").filter((i) => i !== "").map((i) => i.includes("${") ? i.replace(TEMPLATE_TAG_REGEX, "$1") : `'${i}'`).join(",").replace(",,", "");
3166
+ return route.split("/").filter((i) => i !== "").flatMap((segment) => {
3167
+ if (!segment.includes("${")) return [`'${segment}'`];
3168
+ return segment.split(/(\$\{.+?\})/g).filter(Boolean).map((part) => {
3169
+ const match = /^\$\{(.+?)\}$/.exec(part);
3170
+ return match ? match[1] : `'${part}'`;
3171
+ });
3172
+ }).join(",");
3100
3173
  }
3101
3174
 
3102
3175
  //#endregion
@@ -3435,7 +3508,7 @@ function removeComments(file) {
3435
3508
  const getAngularFilteredParamsExpression = (paramsExpression, requiredNullableParamKeys = [], preserveRequiredNullables = false) => {
3436
3509
  const filteredParamValueType = `string | number | boolean${preserveRequiredNullables ? " | null" : ""} | Array<string | number | boolean>`;
3437
3510
  const preserveNullableBranch = preserveRequiredNullables ? ` } else if (value === null && requiredNullableParamKeys.has(key)) {
3438
- filteredParams[key] = value;
3511
+ filteredParams[key] = null;
3439
3512
  ` : "";
3440
3513
  return `(() => {
3441
3514
  const requiredNullableParamKeys = new Set<string>(${JSON.stringify(requiredNullableParamKeys)});
@@ -3505,7 +3578,7 @@ function filterParams(
3505
3578
  value === null &&
3506
3579
  requiredNullableKeys.has(key)
3507
3580
  ) {
3508
- filteredParams[key] = value;
3581
+ filteredParams[key] = null;
3509
3582
  } else if (
3510
3583
  value != null &&
3511
3584
  (typeof value === 'string' ||
@@ -3855,43 +3928,15 @@ function generateSchemaDefinitions(schemaName, schema, context, suffix) {
3855
3928
 
3856
3929
  //#endregion
3857
3930
  //#region src/generators/verbs-options.ts
3858
- async function generateVerbOptions({ verb, output, operation, route, pathRoute, verbParameters = [], context }) {
3859
- const { responses, requestBody, parameters: operationParameters, tags: rawTags, deprecated: rawDeprecated, description: rawDescription, summary: rawSummary } = operation;
3860
- const tags = rawTags ?? [];
3861
- const deprecated = rawDeprecated;
3862
- const description = rawDescription;
3863
- const summary = rawSummary;
3864
- const operationId = getOperationId(operation, route, verb);
3865
- const overrideOperation = output.override.operations[operationId];
3866
- let overrideTag = {};
3867
- for (const [tag, options] of Object.entries(output.override.tags)) if (tags.includes(tag) && options) overrideTag = mergeDeep(overrideTag, options);
3868
- const override = mergeDeep(mergeDeep(output.override, overrideTag), overrideOperation ?? {});
3869
- const overrideOperationName = overrideOperation?.operationName ?? output.override.operationName;
3870
- const operationName = overrideOperationName ? overrideOperationName(operation, route, verb) : sanitize(camel(operationId), { es5keyword: true });
3931
+ async function buildVerbOption({ verb, output, operation, route, pathRoute, verbParameters = [], context, body, operationName, operationId, override, tags, deprecated, description, summary }) {
3871
3932
  const response = getResponse({
3872
- responses: responses ?? {},
3933
+ responses: operation.responses ?? {},
3873
3934
  operationName,
3874
3935
  context,
3875
3936
  contentType: override.contentType
3876
3937
  });
3877
- const body = requestBody ? getBody({
3878
- requestBody,
3879
- operationName,
3880
- context,
3881
- contentType: override.contentType
3882
- }) : {
3883
- originalSchema: {},
3884
- definition: "",
3885
- implementation: "",
3886
- imports: [],
3887
- schemas: [],
3888
- formData: "",
3889
- formUrlEncoded: "",
3890
- contentType: "",
3891
- isOptional: false
3892
- };
3893
3938
  const parameters = getParameters({
3894
- parameters: [...verbParameters, ...operationParameters ?? []],
3939
+ parameters: [...verbParameters, ...operation.parameters ?? []],
3895
3940
  context
3896
3941
  });
3897
3942
  const queryParams = getQueryParams({
@@ -3980,6 +4025,83 @@ async function generateVerbOptions({ verb, output, operation, route, pathRoute,
3980
4025
  const transformer = await dynamicImport(override.transformer, context.workspace);
3981
4026
  return transformer ? transformer(verbOption) : verbOption;
3982
4027
  }
4028
+ async function generateVerbOptions({ verb, output, operation, route, pathRoute, verbParameters = [], context }) {
4029
+ const { requestBody, tags: rawTags, deprecated: rawDeprecated, description: rawDescription, summary: rawSummary } = operation;
4030
+ const tags = rawTags ?? [];
4031
+ const deprecated = rawDeprecated;
4032
+ const description = rawDescription;
4033
+ const summary = rawSummary;
4034
+ const operationId = getOperationId(operation, route, verb);
4035
+ const overrideOperation = output.override.operations[operationId];
4036
+ let overrideTag = {};
4037
+ for (const [tag, options] of Object.entries(output.override.tags)) if (tags.includes(tag) && options) overrideTag = mergeDeep(overrideTag, options);
4038
+ const override = mergeDeep(mergeDeep(output.override, overrideTag), overrideOperation ?? {});
4039
+ const overrideOperationName = overrideOperation?.operationName ?? output.override.operationName;
4040
+ const operationName = overrideOperationName ? overrideOperationName(operation, route, verb) : sanitize(camel(operationId), { es5keyword: true });
4041
+ if (override.splitByContentType && requestBody) {
4042
+ const bodies = getBodiesByContentType({
4043
+ requestBody,
4044
+ operationName,
4045
+ context,
4046
+ contentType: override.contentType
4047
+ });
4048
+ const results = [];
4049
+ for (const bodyEntry of bodies) {
4050
+ const { contentTypeSuffix, ...body } = bodyEntry;
4051
+ const verbOption = await buildVerbOption({
4052
+ verb,
4053
+ output,
4054
+ operation,
4055
+ route,
4056
+ pathRoute,
4057
+ verbParameters,
4058
+ context,
4059
+ body,
4060
+ operationName: contentTypeSuffix ? `${operationName}With${contentTypeSuffix}` : operationName,
4061
+ operationId,
4062
+ override,
4063
+ tags,
4064
+ deprecated,
4065
+ description,
4066
+ summary
4067
+ });
4068
+ results.push(verbOption);
4069
+ }
4070
+ return results;
4071
+ }
4072
+ return [await buildVerbOption({
4073
+ verb,
4074
+ output,
4075
+ operation,
4076
+ route,
4077
+ pathRoute,
4078
+ verbParameters,
4079
+ context,
4080
+ body: requestBody ? getBody({
4081
+ requestBody,
4082
+ operationName,
4083
+ context,
4084
+ contentType: override.contentType
4085
+ }) : {
4086
+ originalSchema: {},
4087
+ definition: "",
4088
+ implementation: "",
4089
+ imports: [],
4090
+ schemas: [],
4091
+ formData: "",
4092
+ formUrlEncoded: "",
4093
+ contentType: "",
4094
+ isOptional: false
4095
+ },
4096
+ operationName,
4097
+ operationId,
4098
+ override,
4099
+ tags,
4100
+ deprecated,
4101
+ description,
4102
+ summary
4103
+ })];
4104
+ }
3983
4105
  function generateVerbsOptions({ verbs, input, output, route, pathRoute, context }) {
3984
4106
  return asyncReduce(_filteredVerbs(verbs, input.filters), async (acc, [verb, operation]) => {
3985
4107
  if (isVerb(verb)) {
@@ -3992,7 +4114,7 @@ function generateVerbsOptions({ verbs, input, output, route, pathRoute, context
3992
4114
  operation,
3993
4115
  context
3994
4116
  });
3995
- acc.push(verbOptions);
4117
+ acc.push(...verbOptions);
3996
4118
  }
3997
4119
  return acc;
3998
4120
  }, []);
@@ -4160,8 +4282,8 @@ function getSchema({ schema: { imports, model }, header, namingConvention = Nami
4160
4282
  file += model;
4161
4283
  return file;
4162
4284
  }
4163
- function getPath(path$1, name, fileExtension) {
4164
- return path.join(path$1, `${name}${fileExtension}`);
4285
+ function getPath(path, name, fileExtension) {
4286
+ return nodePath.join(path, `${name}${fileExtension}`);
4165
4287
  }
4166
4288
  function writeModelInline(acc, model) {
4167
4289
  return acc + `${model}\n`;
@@ -4210,7 +4332,7 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
4210
4332
  });
4211
4333
  }
4212
4334
  if (indexFiles) {
4213
- const schemaFilePath = path.join(schemaPath, `index${fileExtension}`);
4335
+ const schemaFilePath = nodePath.join(schemaPath, `index.ts`);
4214
4336
  await fs$1.ensureFile(schemaFilePath);
4215
4337
  const ext = fileExtension.endsWith(".ts") ? fileExtension.slice(0, -3) : fileExtension;
4216
4338
  const conventionNamesSet = new Set(Object.values(schemaGroups).map((group) => conventionName(group[0].name, namingConvention)));
@@ -4229,7 +4351,7 @@ function generateImportsForBuilder(output, imports, relativeSchemasPath) {
4229
4351
  let schemaImports;
4230
4352
  if (output.indexFiles) schemaImports = isZodSchemaOutput ? [{
4231
4353
  exports: imports.filter((i) => !i.importPath),
4232
- dependency: joinSafe(relativeSchemasPath, "index.zod")
4354
+ dependency: relativeSchemasPath
4233
4355
  }] : [{
4234
4356
  exports: imports.filter((i) => !i.importPath),
4235
4357
  dependency: relativeSchemasPath
@@ -4376,7 +4498,7 @@ interface TypedResponse<T> extends Response {
4376
4498
 
4377
4499
  //#endregion
4378
4500
  //#region src/writers/single-mode.ts
4379
- async function writeSingleMode({ builder, output, projectName, header, needSchema }) {
4501
+ async function writeSingleMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
4380
4502
  try {
4381
4503
  const { path } = getFileInfo(output.target, {
4382
4504
  backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
@@ -4438,7 +4560,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
4438
4560
  data += getTypedResponse();
4439
4561
  data += "\n";
4440
4562
  }
4441
- if (!output.schemas && needSchema) data += generateModelsInline(builder.schemas);
4563
+ if (!output.schemas && needSchema) data += generateSchemasInline ? generateSchemasInline() : generateModelsInline(builder.schemas);
4442
4564
  data += `${implementation.trim()}\n`;
4443
4565
  if (output.mock) {
4444
4566
  data += "\n\n";
@@ -4454,7 +4576,7 @@ async function writeSingleMode({ builder, output, projectName, header, needSchem
4454
4576
 
4455
4577
  //#endregion
4456
4578
  //#region src/writers/split-mode.ts
4457
- async function writeSplitMode({ builder, output, projectName, header, needSchema }) {
4579
+ async function writeSplitMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
4458
4580
  try {
4459
4581
  const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
4460
4582
  backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
@@ -4463,7 +4585,7 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
4463
4585
  const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, paramsSerializer, fetchReviver } = generateTarget(builder, output);
4464
4586
  let implementationData = header;
4465
4587
  let mockData = header;
4466
- const relativeSchemasPath = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
4588
+ const relativeSchemasPath = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
4467
4589
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
4468
4590
  const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
4469
4591
  implementationData += builder.imports({
@@ -4488,8 +4610,8 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
4488
4610
  isAllowSyntheticDefaultImports,
4489
4611
  options: isFunction(output.mock) ? void 0 : output.mock
4490
4612
  });
4491
- const schemasPath = output.schemas ? void 0 : path.join(dirname, filename + ".schemas" + extension);
4492
- if (schemasPath && needSchema) await writeGeneratedFile(schemasPath, header + generateModelsInline(builder.schemas));
4613
+ const schemasPath = output.schemas ? void 0 : nodePath.join(dirname, filename + ".schemas" + extension);
4614
+ if (schemasPath && needSchema) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
4493
4615
  if (mutators) implementationData += generateMutatorImports({
4494
4616
  mutators,
4495
4617
  implementation
@@ -4510,9 +4632,9 @@ async function writeSplitMode({ builder, output, projectName, header, needSchema
4510
4632
  implementationData += `\n${implementation}`;
4511
4633
  mockData += `\n${implementationMock}`;
4512
4634
  const implementationFilename = filename + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
4513
- const implementationPath = path.join(dirname, implementationFilename);
4635
+ const implementationPath = nodePath.join(dirname, implementationFilename);
4514
4636
  await writeGeneratedFile(implementationPath, implementationData);
4515
- const mockPath = output.mock ? path.join(dirname, filename + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
4637
+ const mockPath = output.mock ? nodePath.join(dirname, filename + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
4516
4638
  if (mockPath) await writeGeneratedFile(mockPath, mockData);
4517
4639
  return [
4518
4640
  implementationPath,
@@ -4641,7 +4763,7 @@ function generateTargetForTags(builder, options) {
4641
4763
 
4642
4764
  //#endregion
4643
4765
  //#region src/writers/split-tags-mode.ts
4644
- async function writeSplitTagsMode({ builder, output, projectName, header, needSchema }) {
4766
+ async function writeSplitTagsMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
4645
4767
  const { filename, dirname, extension } = getFileInfo(output.target, {
4646
4768
  backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
4647
4769
  extension: output.fileExtension
@@ -4649,7 +4771,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4649
4771
  const target = generateTargetForTags(builder, output);
4650
4772
  const isAllowSyntheticDefaultImports = isSyntheticDefaultImportsAllow(output.tsconfig);
4651
4773
  const mockOption = output.mock && !isFunction(output.mock) ? output.mock : void 0;
4652
- const indexFilePath = mockOption?.indexMockFiles ? path.join(dirname, "index." + getMockFileExtensionByTypeName(mockOption) + extension) : void 0;
4774
+ const indexFilePath = mockOption?.indexMockFiles ? nodePath.join(dirname, "index." + getMockFileExtensionByTypeName(mockOption) + extension) : void 0;
4653
4775
  if (indexFilePath) await fs$1.outputFile(indexFilePath, "");
4654
4776
  const tagEntries = Object.entries(target);
4655
4777
  const generatedFilePathsArray = await Promise.all(tagEntries.map(async ([tag, target]) => {
@@ -4657,9 +4779,26 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4657
4779
  const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, fetchReviver, formUrlEncoded, paramsSerializer } = target;
4658
4780
  let implementationData = header;
4659
4781
  let mockData = header;
4660
- const importerPath = path.join(dirname, tag, tag + extension);
4661
- const relativeSchemasPath = output.schemas ? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas";
4662
- const importsForBuilder = generateImportsForBuilder(output, imports, relativeSchemasPath);
4782
+ const importerPath = nodePath.join(dirname, tag, tag + extension);
4783
+ const relativeSchemasPath = output.schemas ? getRelativeImportPath(importerPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "../" + filename + ".schemas" + extension.replace(/\.ts$/, "");
4784
+ const tagNames = new Set(tagEntries.map(([t]) => t));
4785
+ const serviceSuffix = OutputClient.ANGULAR === output.client ? ".service" : "";
4786
+ const importsForBuilder = generateImportsForBuilder(output, imports.map((imp) => {
4787
+ if (!imp.importPath) return imp;
4788
+ if (!imp.importPath.startsWith(".")) return imp;
4789
+ const resolvedPath = nodePath.resolve(dirname, imp.importPath);
4790
+ const targetBasename = nodePath.basename(resolvedPath);
4791
+ let targetFile;
4792
+ if (tagNames.has(targetBasename)) {
4793
+ const tagFilename = targetBasename + serviceSuffix + extension;
4794
+ targetFile = nodePath.join(resolvedPath, tagFilename);
4795
+ } else targetFile = resolvedPath + extension;
4796
+ const adjustedPath = getRelativeImportPath(importerPath, targetFile);
4797
+ return {
4798
+ ...imp,
4799
+ importPath: adjustedPath
4800
+ };
4801
+ }), relativeSchemasPath);
4663
4802
  implementationData += builder.imports({
4664
4803
  client: output.client,
4665
4804
  implementation,
@@ -4682,8 +4821,8 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4682
4821
  isAllowSyntheticDefaultImports,
4683
4822
  options: isFunction(output.mock) ? void 0 : output.mock
4684
4823
  });
4685
- const schemasPath = output.schemas ? void 0 : path.join(dirname, filename + ".schemas" + extension);
4686
- if (schemasPath && needSchema) await writeGeneratedFile(schemasPath, header + generateModelsInline(builder.schemas));
4824
+ const schemasPath = output.schemas ? void 0 : nodePath.join(dirname, filename + ".schemas" + extension);
4825
+ if (schemasPath && needSchema) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
4687
4826
  if (mutators) implementationData += generateMutatorImports({
4688
4827
  mutators,
4689
4828
  implementation,
@@ -4720,9 +4859,9 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4720
4859
  implementationData += `\n${implementation}`;
4721
4860
  mockData += `\n${implementationMock}`;
4722
4861
  const implementationFilename = tag + (OutputClient.ANGULAR === output.client ? ".service" : "") + extension;
4723
- const implementationPath = path.join(dirname, tag, implementationFilename);
4862
+ const implementationPath = nodePath.join(dirname, tag, implementationFilename);
4724
4863
  await writeGeneratedFile(implementationPath, implementationData);
4725
- const mockPath = output.mock ? path.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
4864
+ const mockPath = output.mock ? nodePath.join(dirname, tag, tag + "." + getMockFileExtensionByTypeName(output.mock) + extension) : void 0;
4726
4865
  if (mockPath) await writeGeneratedFile(mockPath, mockData);
4727
4866
  return [
4728
4867
  implementationPath,
@@ -4745,7 +4884,7 @@ async function writeSplitTagsMode({ builder, output, projectName, header, needSc
4745
4884
 
4746
4885
  //#endregion
4747
4886
  //#region src/writers/tags-mode.ts
4748
- async function writeTagsMode({ builder, output, projectName, header, needSchema }) {
4887
+ async function writeTagsMode({ builder, output, projectName, header, needSchema, generateSchemasInline }) {
4749
4888
  const { path: targetPath, filename, dirname, extension } = getFileInfo(output.target, {
4750
4889
  backupFilename: conventionName(builder.info.title ?? "filename", output.namingConvention),
4751
4890
  extension: output.fileExtension
@@ -4756,7 +4895,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4756
4895
  try {
4757
4896
  const { imports, implementation, implementationMock, importsMock, mutators, clientMutators, formData, formUrlEncoded, fetchReviver, paramsSerializer } = target;
4758
4897
  let data = header;
4759
- const schemasPathRelative = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas";
4898
+ const schemasPathRelative = output.schemas ? getRelativeImportPath(targetPath, getFileInfo(isString(output.schemas) ? output.schemas : output.schemas.path, { extension: output.fileExtension }).dirname) : "./" + filename + ".schemas" + extension.replace(/\.ts$/, "");
4760
4899
  const normalizedImports = imports.filter((imp) => {
4761
4900
  const searchWords = [imp.alias, imp.name].filter((part) => Boolean(part?.length)).map((part) => escapeRegExp(part)).join("|");
4762
4901
  if (!searchWords) return false;
@@ -4792,8 +4931,8 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4792
4931
  options: isFunction(output.mock) ? void 0 : output.mock
4793
4932
  });
4794
4933
  }
4795
- const schemasPath = output.schemas ? void 0 : path.join(dirname, filename + ".schemas" + extension);
4796
- if (schemasPath && needSchema) await writeGeneratedFile(schemasPath, header + generateModelsInline(builder.schemas));
4934
+ const schemasPath = output.schemas ? void 0 : nodePath.join(dirname, filename + ".schemas" + extension);
4935
+ if (schemasPath && needSchema) await writeGeneratedFile(schemasPath, generateSchemasInline ? header + generateSchemasInline() : header + generateModelsInline(builder.schemas));
4797
4936
  if (mutators) data += generateMutatorImports({
4798
4937
  mutators,
4799
4938
  implementation
@@ -4817,7 +4956,7 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4817
4956
  data += "\n\n";
4818
4957
  data += implementationMock;
4819
4958
  }
4820
- const implementationPath = path.join(dirname, `${kebab(tag)}${extension}`);
4959
+ const implementationPath = nodePath.join(dirname, `${kebab(tag)}${extension}`);
4821
4960
  await writeGeneratedFile(implementationPath, data);
4822
4961
  return [implementationPath, ...schemasPath ? [schemasPath] : []];
4823
4962
  } catch (error) {
@@ -4827,5 +4966,5 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4827
4966
  }
4828
4967
 
4829
4968
  //#endregion
4830
- export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4969
+ export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, SupportedFormatter, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, escapeRegExp, filterByContentType, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBaseUrlRuntimeImports, getBodiesByContentType, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, getWarningCount, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, isVerbose, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, logVerbose, logWarning, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resetWarnings, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, setVerbose, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4831
4970
  //# sourceMappingURL=index.mjs.map