orval 8.6.2 → 8.8.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-NZlQKlzn.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":";;;;;;;AAqBA,MAAM,eAAe,aAAa;CAC1BA;CACGC;CACIC;CACd,CAAC;AACF,MAAM,MAAM,QACT,KAAK,QAAQ,CACb,YACC,wEACD,CACA,QAAQD,QAAY;AAEvB,IACG,UACC,IAAI,OAAO,uBAAuB,0BAA0B,CAAC,UAAU,CACrE,UACA,UACD,CAAC,CACH,CACA,UACC,IAAI,OACF,sBACA,0CACD,CAAC,UAAU,CAAC,UAAU,UAAU,CAAC,CACnC,CACA,UACC,IAAI,OACF,uBACA,kCACD,CAAC,UAAU,CAAC,SAAS,SAAS,CAAC,CACjC,CACA,UACC,IAAI,OACF,2BACA,2CACD,CAAC,UAAU,CAAC,SAAS,SAAS,CAAC,CACjC,CACA,UACC,IAAI,OAAO,qBAAqB,iCAAiC,CAAC,QAChE,OAAO,OAAO,WAAW,CAC1B,CACF,CACA,OACC,0BACA,oEACD,CACA,UACC,IAAI,OAAO,mBAAmB,mCAAmC,CAAC,QAChE,OAAO,OAAO,aAAa,CAC5B,CACF,CACA,OAAO,UAAU,oBAAoB,CACrC,OAAO,sBAAsB,yBAAyB,CACtD,OAAO,cAAc,2BAA2B,CAChD,OAAO,WAAW,wBAAwB,CAC1C,OAAO,qBAAqB,6BAA6B,CACzD,OAAO,aAAa,yBAAyB,CAC7C,OAAO,OAAO,YAAY;AACzB,KAAI,QAAQ,QACV,YAAW,KAAK;AAGlB,KAAI,aAAa;AAEjB,KAAI,SAAS,QAAQ,MAAM,IAAI,SAAS,QAAQ,OAAO,EAAE;EACvD,MAAM,oBAAoB,MAAM,iBAAiB;GAC/C,OAAO,QAAQ;GACf,QAAQ;IACN,QAAQ,QAAQ;IAChB,OAAO,QAAQ;IACf,UAAU,QAAQ;IAClB,OAAO,QAAQ;IACf,MAAM,QAAQ;IACd,QAAQ,QAAQ;IAChB,MAAM,QAAQ;IACd,UAAU,QAAQ;IACnB;GACF,CAAC;AAEF,MAAI,QAAQ,MACV,OAAM,aACJ,QAAQ,OACR,YAAY;AACV,OAAI;AACF,UAAM,aAAa,QAAQ,KAAK,EAAE,kBAAkB;YAC7C,OAAO;AACd,aAAS,MAAM;AACf,YAAQ,KAAK,EAAE;;KAGnB,kBAAkB,MAAM,OACzB;MAED,KAAI;AACF,SAAM,aAAa,QAAQ,KAAK,EAAE,kBAAkB;WAC7C,OAAO;AACd,OAAI,iBAAiB,aACnB,UAAS,MAAM,OAAO,MAAM,IAAI;OAEhC,UAAS,MAAM;AAEjB,WAAQ,KAAK,EAAE;;QAGd;EACL,MAAM,iBAAiB,eAAe,QAAQ,OAAO;EACrD,MAAM,YAAY,KAAK,QAAQ,eAAe;EAC9C,MAAM,aAAa,MAAM,eAAe,eAAe;EAEvD,MAAM,kBAAkB,QAAQ,SAAS,QACtC,MAAM,CAAC,OAAO,OAAO,YAAY,EAAE,CACrC;AAED,MAAI,iBAAiB,QAAQ;AAC3B,YAAS,gCAAgC,gBAAgB,KAAK,KAAK,GAAG;AACtE,WAAQ,KAAK,EAAE;;EAGjB,MAAM,UAAU,OAAO,QAAQ,WAAW,CAAC,QACxC,CAAC,iBAEA,CAAC,MAAM,QAAQ,QAAQ,QAAQ,IAC/B,QAAQ,QAAQ,SAAS,YAAY,CACxC;EAED,IAAI,YAAY;AAChB,OAAK,MAAM,CAAC,aAAa,WAAW,SAAS;GAC3C,MAAM,oBAAoB,MAAM,iBAC9B,QACA,WACA,QACD;AAED,OAAI,QAAQ,UAAU,OACpB,KAAI;AACF,UAAM,aAAa,WAAW,mBAAmB,YAAY;YACtD,OAAO;AACd,gBAAY;AACZ,aAAS,OAAO,YAAY;;QAEzB;IACL,MAAM,cAAc,SAAS,kBAAkB,MAAM,OAAO,GACxD,kBAAkB,MAAM,SACxB;AAEJ,UAAM,aACJ,QAAQ,OACR,YAAY;AACV,SAAI;AACF,YAAM,aAAa,WAAW,mBAAmB,YAAY;cACtD,OAAO;AACd,eAAS,OAAO,YAAY;;OAGhC,YACD;;;AAIL,MAAI,WAAW;AACb,YAAS,oDAAoD;AAC7D,WAAQ,KAAK,EAAE;;;EAGnB;AAEJ,MAAM,IAAI,WAAW,QAAQ,KAAK"}
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.8.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,
@@ -878,6 +878,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
878
878
  }
879
879
  },
880
880
  hono: normalizeHonoOptions(outputOptions.override?.hono, workspace),
881
+ mcp: normalizeMcpOptions(outputOptions.override?.mcp, workspace),
881
882
  jsDoc: normalizeJSDocOptions(outputOptions.override?.jsDoc),
882
883
  query: globalQueryOptions,
883
884
  zod: {
@@ -910,6 +911,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
910
911
  ...outputOptions.override?.zod?.preprocess?.response ? { response: normalizeMutator(workspace, outputOptions.override.zod.preprocess.response) } : {}
911
912
  },
912
913
  generateEachHttpStatus: outputOptions.override?.zod?.generateEachHttpStatus ?? false,
914
+ useBrandedTypes: outputOptions.override?.zod?.useBrandedTypes ?? false,
913
915
  dateTimeOptions: outputOptions.override?.zod?.dateTimeOptions ?? {},
914
916
  timeOptions: outputOptions.override?.zod?.timeOptions ?? {}
915
917
  },
@@ -927,6 +929,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
927
929
  includeHttpResponseReturnType: outputOptions.override?.fetch?.includeHttpResponseReturnType ?? true,
928
930
  forceSuccessResponse: outputOptions.override?.fetch?.forceSuccessResponse ?? false,
929
931
  runtimeValidation: outputOptions.override?.fetch?.runtimeValidation ?? false,
932
+ useRuntimeFetcher: outputOptions.override?.fetch?.useRuntimeFetcher ?? false,
930
933
  ...outputOptions.override?.fetch,
931
934
  ...outputOptions.override?.fetch?.jsonReviver ? { jsonReviver: normalizeMutator(outputWorkspace, outputOptions.override.fetch.jsonReviver) } : {}
932
935
  },
@@ -935,6 +938,7 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
935
938
  enumGenerationType: outputOptions.override?.enumGenerationType ?? "const",
936
939
  suppressReadonlyModifier: outputOptions.override?.suppressReadonlyModifier ?? false,
937
940
  preserveReadonlyRequestBodies: outputOptions.override?.preserveReadonlyRequestBodies ?? "strip",
941
+ splitByContentType: outputOptions.override?.splitByContentType ?? false,
938
942
  aliasCombinedTypes: outputOptions.override?.aliasCombinedTypes ?? false
939
943
  },
940
944
  allParamsOptional: outputOptions.allParamsOptional ?? false,
@@ -1067,6 +1071,7 @@ function normalizeOperationsAndTags(operationsOrTags, workspace, global) {
1067
1071
  ...zod.preprocess?.response ? { response: normalizeMutator(workspace, zod.preprocess.response) } : {}
1068
1072
  },
1069
1073
  generateEachHttpStatus: zod.generateEachHttpStatus ?? false,
1074
+ useBrandedTypes: zod.useBrandedTypes ?? false,
1070
1075
  dateTimeOptions: zod.dateTimeOptions ?? {},
1071
1076
  timeOptions: zod.timeOptions ?? {}
1072
1077
  } } : {},
@@ -1081,7 +1086,7 @@ function normalizeOperationsAndTags(operationsOrTags, workspace, global) {
1081
1086
  function normalizeOutputMode(mode) {
1082
1087
  if (!mode) return OutputMode.SINGLE;
1083
1088
  if (!Object.values(OutputMode).includes(mode)) {
1084
- createLogger().warn(styleText("yellow", `Unknown provided mode => ${mode}`));
1089
+ logWarning(`⚠️ Unknown provided mode => ${mode}`);
1085
1090
  return OutputMode.SINGLE;
1086
1091
  }
1087
1092
  return mode;
@@ -1103,14 +1108,26 @@ function normalizeHonoOptions(hono = {}, workspace) {
1103
1108
  validatorOutputPath: hono.validatorOutputPath ? path.resolve(workspace, hono.validatorOutputPath) : ""
1104
1109
  };
1105
1110
  }
1111
+ function normalizeMcpServerOptions(server, workspace) {
1112
+ return {
1113
+ path: path.resolve(workspace, server.path),
1114
+ name: server.name,
1115
+ default: server.default ?? !server.name
1116
+ };
1117
+ }
1118
+ function normalizeMcpOptions(mcp = {}, workspace) {
1119
+ return { ...mcp.server ? { server: normalizeMcpServerOptions(mcp.server, workspace) } : {} };
1120
+ }
1106
1121
  function normalizeJSDocOptions(jsdoc = {}) {
1107
1122
  return { ...jsdoc };
1108
1123
  }
1109
1124
  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.");
1125
+ 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
1126
  return {
1112
1127
  ...isNullish(queryOptions.usePrefetch) ? {} : { usePrefetch: queryOptions.usePrefetch },
1113
1128
  ...isNullish(queryOptions.useInvalidate) ? {} : { useInvalidate: queryOptions.useInvalidate },
1129
+ ...isNullish(queryOptions.useSetQueryData) ? {} : { useSetQueryData: queryOptions.useSetQueryData },
1130
+ ...isNullish(queryOptions.useGetQueryData) ? {} : { useGetQueryData: queryOptions.useGetQueryData },
1114
1131
  ...isNullish(queryOptions.useQuery) ? {} : { useQuery: queryOptions.useQuery },
1115
1132
  ...isNullish(queryOptions.useSuspenseQuery) ? {} : { useSuspenseQuery: queryOptions.useSuspenseQuery },
1116
1133
  ...isNullish(queryOptions.useMutation) ? {} : { useMutation: queryOptions.useMutation },
@@ -1178,13 +1195,17 @@ async function startWatcher(watchOptions, watchFn, defaultTarget = ".") {
1178
1195
  const ignored = ["**/{.git,node_modules}/**"];
1179
1196
  const watchPaths = isBoolean(watchOptions) ? defaultTarget : watchOptions;
1180
1197
  log(`Watching for changes in ${Array.isArray(watchPaths) ? watchPaths.map((v) => "\"" + v + "\"").join(" | ") : "\"" + watchPaths + "\""}`);
1181
- watch(watchPaths, {
1198
+ const watcher = watch(watchPaths, {
1182
1199
  ignorePermissionErrors: true,
1183
1200
  ignored
1184
- }).on("all", (type, file) => {
1185
- log(`Change detected: ${type} ${file}`);
1186
- watchFn().catch((error) => {
1187
- logError(error);
1201
+ });
1202
+ watcher.on("ready", () => {
1203
+ log("Initial scan complete. Watching for changes...");
1204
+ watcher.on("all", (type, file) => {
1205
+ log(`Change detected: ${type} ${file}`);
1206
+ watchFn().catch((error) => {
1207
+ logError(error);
1208
+ });
1188
1209
  });
1189
1210
  });
1190
1211
  }
@@ -1228,7 +1249,7 @@ const groupSchemasByFilePath = (schemas) => {
1228
1249
  };
1229
1250
  async function writeZodSchemaIndex(schemasPath, fileExtension, header, schemaNames, namingConvention, shouldMergeExisting = false) {
1230
1251
  const importFileExtension = fileExtension.replace(/\.ts$/, "");
1231
- const indexPath = path.join(schemasPath, `index${fileExtension}`);
1252
+ const indexPath = path.join(schemasPath, `index.ts`);
1232
1253
  let existingExports = "";
1233
1254
  if (shouldMergeExisting && await fs.pathExists(indexPath)) {
1234
1255
  const existingContent = await fs.readFile(indexPath, "utf8");
@@ -1243,6 +1264,31 @@ async function writeZodSchemaIndex(schemasPath, fileExtension, header, schemaNam
1243
1264
  const uniqueExports = [...new Set(allExports.split("\n"))].filter((line) => line.trim()).toSorted().join("\n");
1244
1265
  await fs.outputFile(indexPath, `${header}\n${uniqueExports}\n`);
1245
1266
  }
1267
+ function generateZodSchemasInline(builder, output) {
1268
+ const schemasWithOpenApiDef = builder.schemas.filter((s) => s.schema);
1269
+ if (schemasWithOpenApiDef.length === 0) return "";
1270
+ const isZodV4 = !!output.packageJson && isZodVersionV4(output.packageJson);
1271
+ const strict = output.override.zod.strict.body;
1272
+ const coerce = output.override.zod.coerce.body;
1273
+ const schemas = [];
1274
+ for (const { name, schema: schemaObject } of schemasWithOpenApiDef) {
1275
+ if (!schemaObject) continue;
1276
+ const context = {
1277
+ spec: builder.spec,
1278
+ target: builder.target,
1279
+ workspace: "",
1280
+ output
1281
+ };
1282
+ const parsedZodDefinition = parseZodValidationSchemaDefinition(generateZodValidationSchemaDefinition(dereference(schemaObject, context), context, name, strict, isZodV4, { required: true }), context, coerce, strict, isZodV4);
1283
+ schemas.push({
1284
+ schemaName: name,
1285
+ consts: parsedZodDefinition.consts,
1286
+ zodExpression: parsedZodDefinition.zod
1287
+ });
1288
+ }
1289
+ if (schemas.length === 0) return "";
1290
+ return generateZodSchemaFileContent("", schemas);
1291
+ }
1246
1292
  async function writeZodSchemas(builder, schemasPath, fileExtension, header, output) {
1247
1293
  const schemasWithOpenApiDef = builder.schemas.filter((s) => s.schema);
1248
1294
  const schemasToWrite = [];
@@ -1342,6 +1388,34 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
1342
1388
 
1343
1389
  //#endregion
1344
1390
  //#region src/write-specs.ts
1391
+ async function runExternalFormatter(bin, args, projectTitle) {
1392
+ try {
1393
+ await execa(bin, args);
1394
+ } catch (error) {
1395
+ let message;
1396
+ if (error instanceof ExecaError) message = error.code === "ENOENT" ? `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}${bin} not found` : error.message;
1397
+ else if (error instanceof Error) message = error.message;
1398
+ else message = `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}${bin} failed`;
1399
+ logWarning(message);
1400
+ }
1401
+ }
1402
+ async function runFormatter(formatter, paths, projectTitle) {
1403
+ switch (formatter) {
1404
+ case SupportedFormatter.PRETTIER:
1405
+ await formatWithPrettier(paths, projectTitle);
1406
+ break;
1407
+ case SupportedFormatter.BIOME:
1408
+ await runExternalFormatter(SupportedFormatter.BIOME, [
1409
+ "check",
1410
+ "--write",
1411
+ ...paths
1412
+ ], projectTitle);
1413
+ break;
1414
+ case SupportedFormatter.OXFMT:
1415
+ await runExternalFormatter(SupportedFormatter.OXFMT, paths, projectTitle);
1416
+ break;
1417
+ }
1418
+ }
1345
1419
  function getHeader(option, info) {
1346
1420
  if (!option) return "";
1347
1421
  const header = option(info);
@@ -1351,8 +1425,8 @@ function getHeader(option, info) {
1351
1425
  * Add re-export of operation schemas from the main schemas index file.
1352
1426
  * Handles the case where the index file doesn't exist (no regular schemas).
1353
1427
  */
1354
- async function addOperationSchemasReExport(schemaPath, operationSchemasPath, fileExtension, header) {
1355
- const schemaIndexPath = path.join(schemaPath, `index${fileExtension}`);
1428
+ async function addOperationSchemasReExport(schemaPath, operationSchemasPath, header) {
1429
+ const schemaIndexPath = path.join(schemaPath, `index.ts`);
1356
1430
  const esmImportPath = upath.getRelativeImportPath(schemaIndexPath, operationSchemasPath);
1357
1431
  const exportLine = `export * from '${esmImportPath}';\n`;
1358
1432
  if (await fs.pathExists(schemaIndexPath)) {
@@ -1396,7 +1470,7 @@ async function writeSpecs(builder, workspace, options, projectName) {
1396
1470
  header,
1397
1471
  indexFiles: output.indexFiles
1398
1472
  });
1399
- if (output.indexFiles) await addOperationSchemasReExport(schemaPath, output.operationSchemas, fileExtension, header);
1473
+ if (output.indexFiles) await addOperationSchemasReExport(schemaPath, output.operationSchemas, header);
1400
1474
  }
1401
1475
  } else await writeSchemas({
1402
1476
  schemaPath,
@@ -1434,7 +1508,7 @@ async function writeSpecs(builder, workspace, options, projectName) {
1434
1508
  header,
1435
1509
  indexFiles: output.indexFiles
1436
1510
  });
1437
- if (output.indexFiles) await addOperationSchemasReExport(output.schemas.path, output.operationSchemas, fileExtension, header);
1511
+ if (output.indexFiles) await addOperationSchemasReExport(output.schemas.path, output.operationSchemas, header);
1438
1512
  }
1439
1513
  } else await writeSchemas({
1440
1514
  schemaPath: output.schemas.path,
@@ -1456,14 +1530,21 @@ async function writeSpecs(builder, workspace, options, projectName) {
1456
1530
  });
1457
1531
  }
1458
1532
  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
- });
1533
+ if (output.target) {
1534
+ const writeMode = getWriteMode(output.mode);
1535
+ const isZodClient = output.client === "zod";
1536
+ const hasOperations = Object.keys(builder.operations).length > 0;
1537
+ const needZodSchemasInline = isZodClient && !output.schemas && !hasOperations;
1538
+ implementationPaths = await writeMode({
1539
+ builder,
1540
+ workspace,
1541
+ output,
1542
+ projectName,
1543
+ header,
1544
+ needSchema: !output.schemas && !isZodClient || needZodSchemasInline,
1545
+ generateSchemasInline: needZodSchemasInline ? () => generateZodSchemasInline(builder, output) : void 0
1546
+ });
1547
+ }
1467
1548
  if (output.workspace) {
1468
1549
  const workspacePath = output.workspace;
1469
1550
  const indexFile = path.join(workspacePath, "index.ts");
@@ -1492,18 +1573,7 @@ async function writeSpecs(builder, workspace, options, projectName) {
1492
1573
  ...implementationPaths
1493
1574
  ];
1494
1575
  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
- }
1576
+ await runFormatter(output.formatter, paths, projectTitle);
1507
1577
  if (output.docs) try {
1508
1578
  let config = {};
1509
1579
  let configPath;
@@ -1527,10 +1597,10 @@ async function writeSpecs(builder, workspace, options, projectName) {
1527
1597
  if (project) {
1528
1598
  const outputPath = app.options.getValue("out");
1529
1599
  await app.generateDocs(project, outputPath);
1530
- if (output.prettier) await formatWithPrettier([outputPath], projectTitle);
1600
+ await runFormatter(output.formatter, [outputPath], projectTitle);
1531
1601
  } else throw new Error("TypeDoc not initialized");
1532
1602
  } catch (error) {
1533
- log(styleText("yellow", error instanceof Error ? error.message : `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Unable to generate docs`));
1603
+ logWarning(error instanceof Error ? error.message : `⚠️ ${projectTitle ? `${projectTitle} - ` : ""}Unable to generate docs`);
1534
1604
  }
1535
1605
  createSuccessMessage(projectTitle);
1536
1606
  }
@@ -1630,4 +1700,4 @@ async function loadConfigFile(configFilePath) {
1630
1700
 
1631
1701
  //#endregion
1632
1702
  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
1703
+ //# sourceMappingURL=config-NZlQKlzn.mjs.map