orval 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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![tests](https://github.com/orval-labs/orval/actions/workflows/tests.yaml/badge.svg)](https://github.com/orval-labs/orval/actions/workflows/tests.yaml)
4
4
 
5
5
  <p align="center">
6
- <img src="./logo/orval-logo-horizontal.svg?raw=true" width="500" height="160" alt="orval - Restfull Client Generator" />
6
+ <img src="https://raw.githubusercontent.com/orval-labs/orval/master/logo/orval-logo-horizontal.svg" width="500" height="160" alt="orval - Restfull Client Generator" />
7
7
  </p>
8
8
  <h1 align="center">
9
9
  Visit <a href="https://orval.dev" target="_blank">orval.dev</a> for docs, guides, API and beer!
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { c as description, i as startWatcher, l as name, n as loadConfigFile, r as generateSpec, s as normalizeOptions, t as findConfigFile, u as version } from "../config-CPV4lUaV.mjs";
2
+ import { c as description, i as startWatcher, l as name, n as loadConfigFile, r as generateSpec, s as normalizeOptions, t as findConfigFile, u as version } from "../config-CO914zjc.mjs";
3
3
  import path from "node:path";
4
4
  import { Option, program } from "@commander-js/extra-typings";
5
- import { ErrorWithTag, OutputClient, OutputMode, isString, log, logError, setVerbose, startMessage } from "@orval/core";
5
+ import { ErrorWithTag, OutputClient, OutputMode, SupportedFormatter, getWarningCount, isString, log, logError, resetWarnings, setVerbose, startMessage } from "@orval/core";
6
6
 
7
7
  //#region src/bin/orval.ts
8
8
  const orvalMessage = startMessage({
@@ -11,8 +11,9 @@ const orvalMessage = startMessage({
11
11
  description
12
12
  });
13
13
  const cli = program.name("orval").description("Instantly generate TypeScript clients from your OpenAPI specification").version(version);
14
- cli.addOption(new Option("-o, --output <path>", "output file destination").conflicts(["config", "project"])).addOption(new Option("-i, --input <path>", "input file (yaml or json openapi specs)").conflicts(["config", "project"])).addOption(new Option("-c, --config <path>", "override flags by a config file").conflicts(["input", "output"])).addOption(new Option("-p, --project <name...>", "focus one or more projects of the config").conflicts(["input", "output"])).addOption(new Option("-m, --mode <name>", "default mode that will be used").choices(Object.values(OutputMode))).option("-w, --watch [paths...]", "Watch mode, if path is not specified, it watches the input target").addOption(new Option("--client <name>", "default client that will be used").choices(Object.values(OutputClient))).option("--mock", "activate the mock").option("--clean [paths...]", "Clean output directory").option("--prettier", "Prettier generated files").option("--biome", "biome generated files").option("--tsconfig <path>", "path to your tsconfig file").option("--verbose", "Enable verbose logging").action(async (options) => {
14
+ cli.addOption(new Option("-o, --output <path>", "output file destination").conflicts(["config", "project"])).addOption(new Option("-i, --input <path>", "input file (yaml or json openapi specs)").conflicts(["config", "project"])).addOption(new Option("-c, --config <path>", "override flags by a config file").conflicts(["input", "output"])).addOption(new Option("-p, --project <name...>", "focus one or more projects of the config").conflicts(["input", "output"])).addOption(new Option("-m, --mode <name>", "default mode that will be used").choices(Object.values(OutputMode))).option("-w, --watch [paths...]", "Watch mode, if path is not specified, it watches the input target").addOption(new Option("--client <name>", "default client that will be used").choices(Object.values(OutputClient))).option("--mock", "activate the mock").option("--clean [paths...]", "Clean output directory").addOption(new Option("--formatter <name>", "Format generated files (prettier, biome, oxfmt)").choices(Object.values(SupportedFormatter))).option("--tsconfig <path>", "path to your tsconfig file").option("--verbose", "Enable verbose logging").option("--fail-on-warnings", "Exit with error code 1 when warnings are emitted").action(async (options) => {
15
15
  if (options.verbose) setVerbose(true);
16
+ resetWarnings();
16
17
  log(orvalMessage);
17
18
  if (isString(options.input) && isString(options.output)) {
18
19
  const normalizedOptions = await normalizeOptions({
@@ -20,29 +21,33 @@ cli.addOption(new Option("-o, --output <path>", "output file destination").confl
20
21
  output: {
21
22
  target: options.output,
22
23
  clean: options.clean,
23
- prettier: options.prettier,
24
- biome: options.biome,
24
+ formatter: options.formatter,
25
25
  mock: options.mock,
26
26
  client: options.client,
27
27
  mode: options.mode,
28
28
  tsconfig: options.tsconfig
29
29
  }
30
30
  });
31
+ try {
32
+ await generateSpec(process.cwd(), normalizedOptions);
33
+ } catch (error) {
34
+ if (error instanceof ErrorWithTag) logError(error.cause, error.tag);
35
+ else logError(error);
36
+ process.exit(1);
37
+ }
31
38
  if (options.watch) await startWatcher(options.watch, async () => {
39
+ resetWarnings();
32
40
  try {
33
41
  await generateSpec(process.cwd(), normalizedOptions);
34
42
  } catch (error) {
35
43
  logError(error);
36
44
  process.exit(1);
37
45
  }
46
+ if (options.failOnWarnings && getWarningCount() > 0) {
47
+ logError(`Process exited with ${getWarningCount()} warning(s) due to --fail-on-warnings flag`);
48
+ process.exit(1);
49
+ }
38
50
  }, normalizedOptions.input.target);
39
- else try {
40
- await generateSpec(process.cwd(), normalizedOptions);
41
- } catch (error) {
42
- if (error instanceof ErrorWithTag) logError(error.cause, error.tag);
43
- else logError(error);
44
- process.exit(1);
45
- }
46
51
  } else {
47
52
  const configFilePath = findConfigFile(options.config);
48
53
  const workspace = path.dirname(configFilePath);
@@ -56,20 +61,25 @@ cli.addOption(new Option("-o, --output <path>", "output file destination").confl
56
61
  let hasErrors = false;
57
62
  for (const [projectName, config] of configs) {
58
63
  const normalizedOptions = await normalizeOptions(config, workspace, options);
59
- if (options.watch === void 0) try {
64
+ try {
60
65
  await generateSpec(workspace, normalizedOptions, projectName);
61
66
  } catch (error) {
62
67
  hasErrors = true;
63
68
  logError(error, projectName);
64
69
  }
65
- else {
70
+ if (options.watch !== void 0) {
66
71
  const fileToWatch = isString(normalizedOptions.input.target) ? normalizedOptions.input.target : void 0;
67
72
  await startWatcher(options.watch, async () => {
73
+ resetWarnings();
68
74
  try {
69
75
  await generateSpec(workspace, normalizedOptions, projectName);
70
76
  } catch (error) {
71
77
  logError(error, projectName);
72
78
  }
79
+ if (options.failOnWarnings && getWarningCount() > 0) {
80
+ logError(`Process exited with ${getWarningCount()} warning(s) due to --fail-on-warnings flag`);
81
+ process.exit(1);
82
+ }
73
83
  }, fileToWatch);
74
84
  }
75
85
  }
@@ -78,6 +88,10 @@ cli.addOption(new Option("-o, --output <path>", "output file destination").confl
78
88
  process.exit(1);
79
89
  }
80
90
  }
91
+ if (options.failOnWarnings && getWarningCount() > 0) {
92
+ logError(`Process exited with ${getWarningCount()} warning(s) due to --fail-on-warnings flag`);
93
+ process.exit(1);
94
+ }
81
95
  });
82
96
  await cli.parseAsync(process.argv);
83
97
 
@@ -1 +1 @@
1
- {"version":3,"file":"orval.mjs","names":["pkg.name","pkg.version","pkg.description"],"sources":["../../src/bin/orval.ts"],"sourcesContent":["#!/usr/bin/env node\nimport path from 'node:path';\n\nimport { Option, program } from '@commander-js/extra-typings';\nimport {\n ErrorWithTag,\n isString,\n log,\n logError,\n OutputClient,\n OutputMode,\n setVerbose,\n startMessage,\n} from '@orval/core';\n\nimport pkg from '../../package.json';\nimport { generateSpec } from '../generate-spec';\nimport { findConfigFile, loadConfigFile } from '../utils/config';\nimport { normalizeOptions } from '../utils/options';\nimport { startWatcher } from '../utils/watcher';\n\nconst orvalMessage = startMessage({\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n});\nconst cli = program\n .name('orval')\n .description(\n 'Instantly generate TypeScript clients from your OpenAPI specification',\n )\n .version(pkg.version);\n\ncli\n .addOption(\n new Option('-o, --output <path>', 'output file destination').conflicts([\n 'config',\n 'project',\n ]),\n )\n .addOption(\n new Option(\n '-i, --input <path>',\n 'input file (yaml or json openapi specs)',\n ).conflicts(['config', 'project']),\n )\n .addOption(\n new Option(\n '-c, --config <path>',\n 'override flags by a config file',\n ).conflicts(['input', 'output']),\n )\n .addOption(\n new Option(\n '-p, --project <name...>',\n 'focus one or more projects of the config',\n ).conflicts(['input', 'output']),\n )\n .addOption(\n new Option('-m, --mode <name>', 'default mode that will be used').choices(\n Object.values(OutputMode),\n ),\n )\n .option(\n '-w, --watch [paths...]',\n 'Watch mode, if path is not specified, it watches the input target',\n )\n .addOption(\n new Option('--client <name>', 'default client that will be used').choices(\n Object.values(OutputClient),\n ),\n )\n .option('--mock', 'activate the mock')\n .option('--clean [paths...]', 'Clean output directory')\n .option('--prettier', 'Prettier generated files')\n .option('--biome', 'biome generated files')\n .option('--tsconfig <path>', 'path to your tsconfig file')\n .option('--verbose', 'Enable verbose logging')\n .action(async (options) => {\n if (options.verbose) {\n setVerbose(true);\n }\n\n log(orvalMessage);\n\n if (isString(options.input) && isString(options.output)) {\n const normalizedOptions = await normalizeOptions({\n input: options.input,\n output: {\n target: options.output,\n clean: options.clean,\n prettier: options.prettier,\n biome: options.biome,\n mock: options.mock,\n client: options.client,\n mode: options.mode,\n tsconfig: options.tsconfig,\n },\n });\n\n if (options.watch) {\n await startWatcher(\n options.watch,\n async () => {\n try {\n await generateSpec(process.cwd(), normalizedOptions);\n } catch (error) {\n logError(error);\n process.exit(1);\n }\n },\n normalizedOptions.input.target as string,\n );\n } else {\n try {\n await generateSpec(process.cwd(), normalizedOptions);\n } catch (error) {\n if (error instanceof ErrorWithTag) {\n logError(error.cause, error.tag);\n } else {\n logError(error);\n }\n process.exit(1);\n }\n }\n } else {\n const configFilePath = findConfigFile(options.config);\n const workspace = path.dirname(configFilePath);\n const configFile = await loadConfigFile(configFilePath);\n\n const missingProjects = options.project?.filter(\n (p) => !Object.hasOwn(configFile, p),\n );\n\n if (missingProjects?.length) {\n logError(`Project not found in config: ${missingProjects.join(', ')}`);\n process.exit(1);\n }\n\n const configs = Object.entries(configFile).filter(\n ([projectName]) =>\n // only filter by project if specified\n !Array.isArray(options.project) ||\n options.project.includes(projectName),\n );\n\n let hasErrors = false;\n for (const [projectName, config] of configs) {\n const normalizedOptions = await normalizeOptions(\n config,\n workspace,\n options,\n );\n\n if (options.watch === undefined) {\n try {\n await generateSpec(workspace, normalizedOptions, projectName);\n } catch (error) {\n hasErrors = true;\n logError(error, projectName);\n }\n } else {\n const fileToWatch = isString(normalizedOptions.input.target)\n ? normalizedOptions.input.target\n : undefined;\n\n await startWatcher(\n options.watch,\n async () => {\n try {\n await generateSpec(workspace, normalizedOptions, projectName);\n } catch (error) {\n logError(error, projectName);\n }\n },\n fileToWatch,\n );\n }\n }\n\n if (hasErrors) {\n logError('One or more project failed, see above for details');\n process.exit(1);\n }\n }\n });\n\nawait cli.parseAsync(process.argv);\n"],"mappings":"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"}
1
+ {"version":3,"file":"orval.mjs","names":["pkg.name","pkg.version","pkg.description"],"sources":["../../src/bin/orval.ts"],"sourcesContent":["#!/usr/bin/env node\nimport path from 'node:path';\n\nimport { Option, program } from '@commander-js/extra-typings';\nimport {\n ErrorWithTag,\n getWarningCount,\n isString,\n log,\n logError,\n OutputClient,\n OutputMode,\n resetWarnings,\n setVerbose,\n startMessage,\n SupportedFormatter,\n} from '@orval/core';\n\nimport pkg from '../../package.json';\nimport { generateSpec } from '../generate-spec';\nimport { findConfigFile, loadConfigFile } from '../utils/config';\nimport { normalizeOptions } from '../utils/options';\nimport { startWatcher } from '../utils/watcher';\n\nconst orvalMessage = startMessage({\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n});\nconst cli = program\n .name('orval')\n .description(\n 'Instantly generate TypeScript clients from your OpenAPI specification',\n )\n .version(pkg.version);\n\ncli\n .addOption(\n new Option('-o, --output <path>', 'output file destination').conflicts([\n 'config',\n 'project',\n ]),\n )\n .addOption(\n new Option(\n '-i, --input <path>',\n 'input file (yaml or json openapi specs)',\n ).conflicts(['config', 'project']),\n )\n .addOption(\n new Option(\n '-c, --config <path>',\n 'override flags by a config file',\n ).conflicts(['input', 'output']),\n )\n .addOption(\n new Option(\n '-p, --project <name...>',\n 'focus one or more projects of the config',\n ).conflicts(['input', 'output']),\n )\n .addOption(\n new Option('-m, --mode <name>', 'default mode that will be used').choices(\n Object.values(OutputMode),\n ),\n )\n .option(\n '-w, --watch [paths...]',\n 'Watch mode, if path is not specified, it watches the input target',\n )\n .addOption(\n new Option('--client <name>', 'default client that will be used').choices(\n Object.values(OutputClient),\n ),\n )\n .option('--mock', 'activate the mock')\n .option('--clean [paths...]', 'Clean output directory')\n .addOption(\n new Option(\n '--formatter <name>',\n 'Format generated files (prettier, biome, oxfmt)',\n ).choices(Object.values(SupportedFormatter)),\n )\n .option('--tsconfig <path>', 'path to your tsconfig file')\n .option('--verbose', 'Enable verbose logging')\n .option(\n '--fail-on-warnings',\n 'Exit with error code 1 when warnings are emitted',\n )\n .action(async (options) => {\n if (options.verbose) {\n setVerbose(true);\n }\n\n resetWarnings();\n log(orvalMessage);\n\n if (isString(options.input) && isString(options.output)) {\n const normalizedOptions = await normalizeOptions({\n input: options.input,\n output: {\n target: options.output,\n clean: options.clean,\n formatter: options.formatter,\n mock: options.mock,\n client: options.client,\n mode: options.mode,\n tsconfig: options.tsconfig,\n },\n });\n\n try {\n await generateSpec(process.cwd(), normalizedOptions);\n } catch (error) {\n if (error instanceof ErrorWithTag) {\n logError(error.cause, error.tag);\n } else {\n logError(error);\n }\n process.exit(1);\n }\n\n if (options.watch) {\n await startWatcher(\n options.watch,\n async () => {\n resetWarnings();\n try {\n await generateSpec(process.cwd(), normalizedOptions);\n } catch (error) {\n logError(error);\n process.exit(1);\n }\n if (options.failOnWarnings && getWarningCount() > 0) {\n logError(\n `Process exited with ${getWarningCount()} warning(s) due to --fail-on-warnings flag`,\n );\n process.exit(1);\n }\n },\n normalizedOptions.input.target as string,\n );\n }\n } else {\n const configFilePath = findConfigFile(options.config);\n const workspace = path.dirname(configFilePath);\n const configFile = await loadConfigFile(configFilePath);\n\n const missingProjects = options.project?.filter(\n (p) => !Object.hasOwn(configFile, p),\n );\n\n if (missingProjects?.length) {\n logError(`Project not found in config: ${missingProjects.join(', ')}`);\n process.exit(1);\n }\n\n const configs = Object.entries(configFile).filter(\n ([projectName]) =>\n // only filter by project if specified\n !Array.isArray(options.project) ||\n options.project.includes(projectName),\n );\n\n let hasErrors = false;\n for (const [projectName, config] of configs) {\n const normalizedOptions = await normalizeOptions(\n config,\n workspace,\n options,\n );\n\n try {\n await generateSpec(workspace, normalizedOptions, projectName);\n } catch (error) {\n hasErrors = true;\n logError(error, projectName);\n }\n\n if (options.watch !== undefined) {\n const fileToWatch = isString(normalizedOptions.input.target)\n ? normalizedOptions.input.target\n : undefined;\n\n await startWatcher(\n options.watch,\n async () => {\n resetWarnings();\n try {\n await generateSpec(workspace, normalizedOptions, projectName);\n } catch (error) {\n logError(error, projectName);\n }\n if (options.failOnWarnings && getWarningCount() > 0) {\n logError(\n `Process exited with ${getWarningCount()} warning(s) due to --fail-on-warnings flag`,\n );\n process.exit(1);\n }\n },\n fileToWatch,\n );\n }\n }\n\n if (hasErrors) {\n logError('One or more project failed, see above for details');\n process.exit(1);\n }\n }\n\n if (options.failOnWarnings && getWarningCount() > 0) {\n logError(\n `Process exited with ${getWarningCount()} warning(s) due to --fail-on-warnings flag`,\n );\n process.exit(1);\n }\n });\n\nawait cli.parseAsync(process.argv);\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { FormDataArrayHandling, GetterPropType, NamingConvention, OutputClient, OutputHttpClient, OutputMode, PropertySortOrder, RefComponentSuffix, asyncReduce, conventionName, createLogger, createSuccessMessage, dynamicImport, fixCrossDirectoryImports, fixRegularSchemaImports, generateComponentDefinition, generateDependencyImports, generateParameterDefinition, generateSchemasDefinition, generateVerbsOptions, getFileInfo, getFullRoute, getMockFileExtensionByTypeName, getRoute, isBoolean, isFunction, isNullish, isObject, isReference, isString, isUrl, jsDoc, log, logError, logVerbose, pascal, removeFilesAndEmptyFolders, resolveInstalledVersions, resolveRef, splitSchemasByType, upath, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode } from "@orval/core";
2
+ import { FormDataArrayHandling, GetterPropType, NamingConvention, OutputClient, OutputHttpClient, OutputMode, PropertySortOrder, RefComponentSuffix, SupportedFormatter, asyncReduce, conventionName, createSuccessMessage, dynamicImport, fixCrossDirectoryImports, fixRegularSchemaImports, generateComponentDefinition, generateDependencyImports, generateParameterDefinition, generateSchemasDefinition, generateVerbsOptions, getBaseUrlRuntimeImports, getFileInfo, getFullRoute, getMockFileExtensionByTypeName, getRoute, isBoolean, isFunction, isNullish, isObject, isReference, isString, isUrl, jsDoc, log, logError, logVerbose, logWarning, pascal, removeFilesAndEmptyFolders, resolveInstalledVersions, resolveRef, splitSchemasByType, upath, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode } from "@orval/core";
3
3
  import { bundle } from "@scalar/json-magic/bundle";
4
4
  import { fetchUrls, parseJson, parseYaml, readFiles } from "@scalar/json-magic/bundle/plugins/node";
5
5
  import { upgrade, validate } from "@scalar/openapi-parser";
@@ -15,10 +15,10 @@ import query from "@orval/query";
15
15
  import solidStart from "@orval/solid-start";
16
16
  import swr from "@orval/swr";
17
17
  import zod, { dereference, generateZodValidationSchemaDefinition, isZodVersionV4, parseZodValidationSchemaDefinition } from "@orval/zod";
18
- import { styleText } from "node:util";
19
18
  import { ExecaError, execa } from "execa";
20
19
  import fs from "fs-extra";
21
20
  import fs$1, { access } from "node:fs/promises";
21
+ import { styleText } from "node:util";
22
22
  import { parseArgsStringToArgv } from "string-argv";
23
23
  import { findUp, findUpMultiple } from "find-up";
24
24
  import yaml from "js-yaml";
@@ -29,7 +29,7 @@ import { createJiti } from "jiti";
29
29
  //#region package.json
30
30
  var name = "orval";
31
31
  var description = "A swagger client generator for typescript";
32
- var version = "8.6.2";
32
+ var version = "8.7.0";
33
33
 
34
34
  //#endregion
35
35
  //#region src/client.ts
@@ -103,7 +103,7 @@ const generateClientFooter = ({ outputClient, operationNames, hasMutator, hasAwa
103
103
  try {
104
104
  if (isFunction(outputClient)) {
105
105
  implementation = footer(operationNames);
106
- console.warn("[WARN] Passing an array of strings for operations names to the footer function is deprecated and will be removed in a future major release. Please pass them in an object instead: { operationNames: string[] }.");
106
+ logWarning("⚠️ Passing an array of strings for operations names to the footer function is deprecated and will be removed in a future major release. Please pass them in an object instead: { operationNames: string[] }.");
107
107
  } else implementation = footer({
108
108
  operationNames,
109
109
  title: titles.implementation,
@@ -154,6 +154,7 @@ const generateMock = (verbOption, options) => {
154
154
  return mock.generateMock(verbOption, options);
155
155
  };
156
156
  const generateOperations = (outputClient = DEFAULT_CLIENT, verbsOptions, options, output) => {
157
+ const baseUrlImports = getBaseUrlRuntimeImports(output.baseUrl);
157
158
  return asyncReduce(verbsOptions, async (acc, verbOption) => {
158
159
  const { client: generatorClient } = getGeneratorClient(outputClient, output);
159
160
  const client = await generatorClient(verbOption, options, outputClient, output);
@@ -170,7 +171,7 @@ const generateOperations = (outputClient = DEFAULT_CLIENT, verbsOptions, options
170
171
  }
171
172
  acc[operationKey] = {
172
173
  implementation: hasImplementation ? verbOption.doc + client.implementation : client.implementation,
173
- imports: client.imports,
174
+ imports: [...baseUrlImports, ...client.imports],
174
175
  implementationMock: generatedMock.implementation,
175
176
  importsMock: generatedMock.imports,
176
177
  tags: verbOption.tags,
@@ -521,8 +522,8 @@ async function formatWithPrettier(paths, projectTitle) {
521
522
  await fs$1.writeFile(filePath, formatted);
522
523
  } catch (error) {
523
524
  if (isMissingFileError(error)) return;
524
- if (error instanceof Error) if (error.name === "UndefinedParserError") {} else log(styleText("yellow", `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Failed to format file ${filePath}: ${error.toString()}`));
525
- else log(styleText("yellow", `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Failed to format file ${filePath}: unknown error}`));
525
+ if (error instanceof Error) if (error.name === "UndefinedParserError") {} else logWarning(`⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Failed to format file ${filePath}: ${error.toString()}`);
526
+ else logWarning(`⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Failed to format file ${filePath}: unknown error`);
526
527
  }
527
528
  }));
528
529
  return;
@@ -530,7 +531,7 @@ async function formatWithPrettier(paths, projectTitle) {
530
531
  try {
531
532
  await execa("prettier", ["--write", ...paths]);
532
533
  } catch {
533
- log(styleText("yellow", `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}prettier not found. Install it as a project dependency or globally.`));
534
+ logWarning(`⚠️ ${projectTitle ? `${projectTitle} - ` : ""}prettier not found. Install it as a project dependency or globally.`);
534
535
  }
535
536
  }
536
537
  function isMissingFileError(error) {
@@ -674,7 +675,7 @@ const maybeReplaceCatalog = async (pkg, workspace) => {
674
675
  if (!hasCatalogReferences(pkg)) return pkg;
675
676
  const catalogData = await loadPnpmWorkspaceCatalog(workspace) ?? await loadPackageJsonCatalog(workspace) ?? await loadYarnrcCatalog(workspace);
676
677
  if (!catalogData) {
677
- log(`⚠️ ${styleText("yellow", "package.json contains catalog: references, but no catalog source was found (checked: pnpm-workspace.yaml, package.json, .yarnrc.yml).")}`);
678
+ logWarning("⚠️ package.json contains catalog: references, but no catalog source was found (checked: pnpm-workspace.yaml, package.json, .yarnrc.yml).");
678
679
  return pkg;
679
680
  }
680
681
  performSubstitution(pkg.dependencies, catalogData);
@@ -686,12 +687,12 @@ const performSubstitution = (dependencies, catalogData) => {
686
687
  if (!dependencies) return;
687
688
  for (const [packageName, version] of Object.entries(dependencies)) if (version === "catalog:" || version === "catalog:default") {
688
689
  if (!catalogData.catalog) {
689
- log(`⚠️ ${styleText("yellow", `catalog: substitution for the package '${packageName}' failed as there is no default catalog.`)}`);
690
+ logWarning(`⚠️ catalog: substitution for the package '${packageName}' failed as there is no default catalog.`);
690
691
  continue;
691
692
  }
692
693
  const sub = catalogData.catalog[packageName];
693
694
  if (!sub) {
694
- log(`⚠️ ${styleText("yellow", `catalog: substitution for the package '${packageName}' failed as there is no matching package in the default catalog.`)}`);
695
+ logWarning(`⚠️ catalog: substitution for the package '${packageName}' failed as there is no matching package in the default catalog.`);
695
696
  continue;
696
697
  }
697
698
  dependencies[packageName] = sub;
@@ -699,12 +700,12 @@ const performSubstitution = (dependencies, catalogData) => {
699
700
  const catalogName = version.slice(8);
700
701
  const catalog = catalogData.catalogs?.[catalogName];
701
702
  if (!catalog) {
702
- log(`⚠️ ${styleText("yellow", `'${version}' substitution for the package '${packageName}' failed as there is no matching catalog named '${catalogName}'. (available named catalogs are: ${Object.keys(catalogData.catalogs ?? {}).join(", ")})`)}`);
703
+ logWarning(`⚠️ '${version}' substitution for the package '${packageName}' failed as there is no matching catalog named '${catalogName}'. (available named catalogs are: ${Object.keys(catalogData.catalogs ?? {}).join(", ")})`);
703
704
  continue;
704
705
  }
705
706
  const sub = catalog[packageName];
706
707
  if (!sub) {
707
- log(`⚠️ ${styleText("yellow", `'${version}' substitution for the package '${packageName}' failed as there is no package in the catalog named '${catalogName}'. (packages in the catalog are: ${Object.keys(catalog).join(", ")})`)}`);
708
+ logWarning(`⚠️ '${version}' substitution for the package '${packageName}' failed as there is no package in the catalog named '${catalogName}'. (packages in the catalog are: ${Object.keys(catalog).join(", ")})`);
708
709
  continue;
709
710
  }
710
711
  dependencies[packageName] = sub;
@@ -788,7 +789,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
788
789
  const inputOptions = isString(options.input) || Array.isArray(options.input) ? { target: options.input } : options.input;
789
790
  const outputOptions = isString(options.output) ? { target: options.output } : options.output;
790
791
  const outputWorkspace = normalizePath(outputOptions.workspace ?? "", workspace);
791
- const { clean, prettier, client, httpClient, mode, biome } = globalOptions;
792
+ const { clean, client, httpClient, mode } = globalOptions;
792
793
  const tsconfig = await loadTsconfig(outputOptions.tsconfig ?? globalOptions.tsconfig, workspace);
793
794
  const packageJson = await loadPackageJson(outputOptions.packageJson ?? globalOptions.packageJson, workspace);
794
795
  const mockOption = outputOptions.mock ?? globalOptions.mock;
@@ -831,8 +832,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
831
832
  mock,
832
833
  clean: outputOptions.clean ?? clean ?? false,
833
834
  docs: outputOptions.docs ?? false,
834
- prettier: outputOptions.prettier ?? prettier ?? false,
835
- biome: outputOptions.biome ?? biome ?? false,
835
+ formatter: outputOptions.formatter ?? globalOptions.formatter,
836
836
  tsconfig,
837
837
  packageJson,
838
838
  headers: outputOptions.headers ?? false,
@@ -910,6 +910,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
910
910
  ...outputOptions.override?.zod?.preprocess?.response ? { response: normalizeMutator(workspace, outputOptions.override.zod.preprocess.response) } : {}
911
911
  },
912
912
  generateEachHttpStatus: outputOptions.override?.zod?.generateEachHttpStatus ?? false,
913
+ useBrandedTypes: outputOptions.override?.zod?.useBrandedTypes ?? false,
913
914
  dateTimeOptions: outputOptions.override?.zod?.dateTimeOptions ?? {},
914
915
  timeOptions: outputOptions.override?.zod?.timeOptions ?? {}
915
916
  },
@@ -927,6 +928,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
927
928
  includeHttpResponseReturnType: outputOptions.override?.fetch?.includeHttpResponseReturnType ?? true,
928
929
  forceSuccessResponse: outputOptions.override?.fetch?.forceSuccessResponse ?? false,
929
930
  runtimeValidation: outputOptions.override?.fetch?.runtimeValidation ?? false,
931
+ useRuntimeFetcher: outputOptions.override?.fetch?.useRuntimeFetcher ?? false,
930
932
  ...outputOptions.override?.fetch,
931
933
  ...outputOptions.override?.fetch?.jsonReviver ? { jsonReviver: normalizeMutator(outputWorkspace, outputOptions.override.fetch.jsonReviver) } : {}
932
934
  },
@@ -935,6 +937,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
935
937
  enumGenerationType: outputOptions.override?.enumGenerationType ?? "const",
936
938
  suppressReadonlyModifier: outputOptions.override?.suppressReadonlyModifier ?? false,
937
939
  preserveReadonlyRequestBodies: outputOptions.override?.preserveReadonlyRequestBodies ?? "strip",
940
+ splitByContentType: outputOptions.override?.splitByContentType ?? false,
938
941
  aliasCombinedTypes: outputOptions.override?.aliasCombinedTypes ?? false
939
942
  },
940
943
  allParamsOptional: outputOptions.allParamsOptional ?? false,
@@ -1067,6 +1070,7 @@ function normalizeOperationsAndTags(operationsOrTags, workspace, global) {
1067
1070
  ...zod.preprocess?.response ? { response: normalizeMutator(workspace, zod.preprocess.response) } : {}
1068
1071
  },
1069
1072
  generateEachHttpStatus: zod.generateEachHttpStatus ?? false,
1073
+ useBrandedTypes: zod.useBrandedTypes ?? false,
1070
1074
  dateTimeOptions: zod.dateTimeOptions ?? {},
1071
1075
  timeOptions: zod.timeOptions ?? {}
1072
1076
  } } : {},
@@ -1081,7 +1085,7 @@ function normalizeOperationsAndTags(operationsOrTags, workspace, global) {
1081
1085
  function normalizeOutputMode(mode) {
1082
1086
  if (!mode) return OutputMode.SINGLE;
1083
1087
  if (!Object.values(OutputMode).includes(mode)) {
1084
- createLogger().warn(styleText("yellow", `Unknown provided mode => ${mode}`));
1088
+ logWarning(`⚠️ Unknown provided mode => ${mode}`);
1085
1089
  return OutputMode.SINGLE;
1086
1090
  }
1087
1091
  return mode;
@@ -1107,10 +1111,12 @@ function normalizeJSDocOptions(jsdoc = {}) {
1107
1111
  return { ...jsdoc };
1108
1112
  }
1109
1113
  function normalizeQueryOptions(queryOptions = {}, outputWorkspace, globalOptions = {}) {
1110
- if (queryOptions.options) console.warn("[WARN] Using query options is deprecated and will be removed in a future major release. Please use queryOptions or mutationOptions instead.");
1114
+ if (queryOptions.options) logWarning("⚠️ Using query options is deprecated and will be removed in a future major release. Please use queryOptions or mutationOptions instead.");
1111
1115
  return {
1112
1116
  ...isNullish(queryOptions.usePrefetch) ? {} : { usePrefetch: queryOptions.usePrefetch },
1113
1117
  ...isNullish(queryOptions.useInvalidate) ? {} : { useInvalidate: queryOptions.useInvalidate },
1118
+ ...isNullish(queryOptions.useSetQueryData) ? {} : { useSetQueryData: queryOptions.useSetQueryData },
1119
+ ...isNullish(queryOptions.useGetQueryData) ? {} : { useGetQueryData: queryOptions.useGetQueryData },
1114
1120
  ...isNullish(queryOptions.useQuery) ? {} : { useQuery: queryOptions.useQuery },
1115
1121
  ...isNullish(queryOptions.useSuspenseQuery) ? {} : { useSuspenseQuery: queryOptions.useSuspenseQuery },
1116
1122
  ...isNullish(queryOptions.useMutation) ? {} : { useMutation: queryOptions.useMutation },
@@ -1178,13 +1184,17 @@ async function startWatcher(watchOptions, watchFn, defaultTarget = ".") {
1178
1184
  const ignored = ["**/{.git,node_modules}/**"];
1179
1185
  const watchPaths = isBoolean(watchOptions) ? defaultTarget : watchOptions;
1180
1186
  log(`Watching for changes in ${Array.isArray(watchPaths) ? watchPaths.map((v) => "\"" + v + "\"").join(" | ") : "\"" + watchPaths + "\""}`);
1181
- watch(watchPaths, {
1187
+ const watcher = watch(watchPaths, {
1182
1188
  ignorePermissionErrors: true,
1183
1189
  ignored
1184
- }).on("all", (type, file) => {
1185
- log(`Change detected: ${type} ${file}`);
1186
- watchFn().catch((error) => {
1187
- logError(error);
1190
+ });
1191
+ watcher.on("ready", () => {
1192
+ log("Initial scan complete. Watching for changes...");
1193
+ watcher.on("all", (type, file) => {
1194
+ log(`Change detected: ${type} ${file}`);
1195
+ watchFn().catch((error) => {
1196
+ logError(error);
1197
+ });
1188
1198
  });
1189
1199
  });
1190
1200
  }
@@ -1228,7 +1238,7 @@ const groupSchemasByFilePath = (schemas) => {
1228
1238
  };
1229
1239
  async function writeZodSchemaIndex(schemasPath, fileExtension, header, schemaNames, namingConvention, shouldMergeExisting = false) {
1230
1240
  const importFileExtension = fileExtension.replace(/\.ts$/, "");
1231
- const indexPath = path.join(schemasPath, `index${fileExtension}`);
1241
+ const indexPath = path.join(schemasPath, `index.ts`);
1232
1242
  let existingExports = "";
1233
1243
  if (shouldMergeExisting && await fs.pathExists(indexPath)) {
1234
1244
  const existingContent = await fs.readFile(indexPath, "utf8");
@@ -1243,6 +1253,31 @@ async function writeZodSchemaIndex(schemasPath, fileExtension, header, schemaNam
1243
1253
  const uniqueExports = [...new Set(allExports.split("\n"))].filter((line) => line.trim()).toSorted().join("\n");
1244
1254
  await fs.outputFile(indexPath, `${header}\n${uniqueExports}\n`);
1245
1255
  }
1256
+ function generateZodSchemasInline(builder, output) {
1257
+ const schemasWithOpenApiDef = builder.schemas.filter((s) => s.schema);
1258
+ if (schemasWithOpenApiDef.length === 0) return "";
1259
+ const isZodV4 = !!output.packageJson && isZodVersionV4(output.packageJson);
1260
+ const strict = output.override.zod.strict.body;
1261
+ const coerce = output.override.zod.coerce.body;
1262
+ const schemas = [];
1263
+ for (const { name, schema: schemaObject } of schemasWithOpenApiDef) {
1264
+ if (!schemaObject) continue;
1265
+ const context = {
1266
+ spec: builder.spec,
1267
+ target: builder.target,
1268
+ workspace: "",
1269
+ output
1270
+ };
1271
+ const parsedZodDefinition = parseZodValidationSchemaDefinition(generateZodValidationSchemaDefinition(dereference(schemaObject, context), context, name, strict, isZodV4, { required: true }), context, coerce, strict, isZodV4);
1272
+ schemas.push({
1273
+ schemaName: name,
1274
+ consts: parsedZodDefinition.consts,
1275
+ zodExpression: parsedZodDefinition.zod
1276
+ });
1277
+ }
1278
+ if (schemas.length === 0) return "";
1279
+ return generateZodSchemaFileContent("", schemas);
1280
+ }
1246
1281
  async function writeZodSchemas(builder, schemasPath, fileExtension, header, output) {
1247
1282
  const schemasWithOpenApiDef = builder.schemas.filter((s) => s.schema);
1248
1283
  const schemasToWrite = [];
@@ -1342,6 +1377,34 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
1342
1377
 
1343
1378
  //#endregion
1344
1379
  //#region src/write-specs.ts
1380
+ async function runExternalFormatter(bin, args, projectTitle) {
1381
+ try {
1382
+ await execa(bin, args);
1383
+ } catch (error) {
1384
+ let message;
1385
+ if (error instanceof ExecaError) message = error.code === "ENOENT" ? `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}${bin} not found` : error.message;
1386
+ else if (error instanceof Error) message = error.message;
1387
+ else message = `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}${bin} failed`;
1388
+ logWarning(message);
1389
+ }
1390
+ }
1391
+ async function runFormatter(formatter, paths, projectTitle) {
1392
+ switch (formatter) {
1393
+ case SupportedFormatter.PRETTIER:
1394
+ await formatWithPrettier(paths, projectTitle);
1395
+ break;
1396
+ case SupportedFormatter.BIOME:
1397
+ await runExternalFormatter(SupportedFormatter.BIOME, [
1398
+ "check",
1399
+ "--write",
1400
+ ...paths
1401
+ ], projectTitle);
1402
+ break;
1403
+ case SupportedFormatter.OXFMT:
1404
+ await runExternalFormatter(SupportedFormatter.OXFMT, paths, projectTitle);
1405
+ break;
1406
+ }
1407
+ }
1345
1408
  function getHeader(option, info) {
1346
1409
  if (!option) return "";
1347
1410
  const header = option(info);
@@ -1351,8 +1414,8 @@ function getHeader(option, info) {
1351
1414
  * Add re-export of operation schemas from the main schemas index file.
1352
1415
  * Handles the case where the index file doesn't exist (no regular schemas).
1353
1416
  */
1354
- async function addOperationSchemasReExport(schemaPath, operationSchemasPath, fileExtension, header) {
1355
- const schemaIndexPath = path.join(schemaPath, `index${fileExtension}`);
1417
+ async function addOperationSchemasReExport(schemaPath, operationSchemasPath, header) {
1418
+ const schemaIndexPath = path.join(schemaPath, `index.ts`);
1356
1419
  const esmImportPath = upath.getRelativeImportPath(schemaIndexPath, operationSchemasPath);
1357
1420
  const exportLine = `export * from '${esmImportPath}';\n`;
1358
1421
  if (await fs.pathExists(schemaIndexPath)) {
@@ -1396,7 +1459,7 @@ async function writeSpecs(builder, workspace, options, projectName) {
1396
1459
  header,
1397
1460
  indexFiles: output.indexFiles
1398
1461
  });
1399
- if (output.indexFiles) await addOperationSchemasReExport(schemaPath, output.operationSchemas, fileExtension, header);
1462
+ if (output.indexFiles) await addOperationSchemasReExport(schemaPath, output.operationSchemas, header);
1400
1463
  }
1401
1464
  } else await writeSchemas({
1402
1465
  schemaPath,
@@ -1434,7 +1497,7 @@ async function writeSpecs(builder, workspace, options, projectName) {
1434
1497
  header,
1435
1498
  indexFiles: output.indexFiles
1436
1499
  });
1437
- if (output.indexFiles) await addOperationSchemasReExport(output.schemas.path, output.operationSchemas, fileExtension, header);
1500
+ if (output.indexFiles) await addOperationSchemasReExport(output.schemas.path, output.operationSchemas, header);
1438
1501
  }
1439
1502
  } else await writeSchemas({
1440
1503
  schemaPath: output.schemas.path,
@@ -1456,14 +1519,21 @@ async function writeSpecs(builder, workspace, options, projectName) {
1456
1519
  });
1457
1520
  }
1458
1521
  let implementationPaths = [];
1459
- if (output.target) implementationPaths = await getWriteMode(output.mode)({
1460
- builder,
1461
- workspace,
1462
- output,
1463
- projectName,
1464
- header,
1465
- needSchema: !output.schemas && output.client !== "zod"
1466
- });
1522
+ if (output.target) {
1523
+ const writeMode = getWriteMode(output.mode);
1524
+ const isZodClient = output.client === "zod";
1525
+ const hasOperations = Object.keys(builder.operations).length > 0;
1526
+ const needZodSchemasInline = isZodClient && !output.schemas && !hasOperations;
1527
+ implementationPaths = await writeMode({
1528
+ builder,
1529
+ workspace,
1530
+ output,
1531
+ projectName,
1532
+ header,
1533
+ needSchema: !output.schemas && !isZodClient || needZodSchemasInline,
1534
+ generateSchemasInline: needZodSchemasInline ? () => generateZodSchemasInline(builder, output) : void 0
1535
+ });
1536
+ }
1467
1537
  if (output.workspace) {
1468
1538
  const workspacePath = output.workspace;
1469
1539
  const indexFile = path.join(workspacePath, "index.ts");
@@ -1492,18 +1562,7 @@ async function writeSpecs(builder, workspace, options, projectName) {
1492
1562
  ...implementationPaths
1493
1563
  ];
1494
1564
  if (options.hooks.afterAllFilesWrite) await executeHook("afterAllFilesWrite", options.hooks.afterAllFilesWrite, paths);
1495
- if (output.prettier) await formatWithPrettier(paths, projectTitle);
1496
- if (output.biome) try {
1497
- await execa("biome", [
1498
- "check",
1499
- "--write",
1500
- ...paths
1501
- ]);
1502
- } catch (error) {
1503
- let message = `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}biome not found`;
1504
- if (error instanceof ExecaError && error.exitCode === 1) message = error.message;
1505
- log(styleText("yellow", message));
1506
- }
1565
+ await runFormatter(output.formatter, paths, projectTitle);
1507
1566
  if (output.docs) try {
1508
1567
  let config = {};
1509
1568
  let configPath;
@@ -1527,10 +1586,10 @@ async function writeSpecs(builder, workspace, options, projectName) {
1527
1586
  if (project) {
1528
1587
  const outputPath = app.options.getValue("out");
1529
1588
  await app.generateDocs(project, outputPath);
1530
- if (output.prettier) await formatWithPrettier([outputPath], projectTitle);
1589
+ await runFormatter(output.formatter, [outputPath], projectTitle);
1531
1590
  } else throw new Error("TypeDoc not initialized");
1532
1591
  } catch (error) {
1533
- log(styleText("yellow", error instanceof Error ? error.message : `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Unable to generate docs`));
1592
+ logWarning(error instanceof Error ? error.message : `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Unable to generate docs`);
1534
1593
  }
1535
1594
  createSuccessMessage(projectTitle);
1536
1595
  }
@@ -1630,4 +1689,4 @@ async function loadConfigFile(configFilePath) {
1630
1689
 
1631
1690
  //#endregion
1632
1691
  export { defineConfig as a, description as c, startWatcher as i, name as l, loadConfigFile as n, defineTransformer as o, generateSpec as r, normalizeOptions as s, findConfigFile as t, version as u };
1633
- //# sourceMappingURL=config-CPV4lUaV.mjs.map
1692
+ //# sourceMappingURL=config-CO914zjc.mjs.map