orval 8.15.0 → 8.17.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/bin/orval.mjs +1 -1
- package/dist/bin/orval.mjs.map +1 -1
- package/dist/{config-CVTlXJY3.mjs → config-DKT1smAv.mjs} +77 -21
- package/dist/config-DKT1smAv.mjs.map +1 -0
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +46 -70
- package/dist/config-CVTlXJY3.mjs.map +0 -1
package/dist/bin/orval.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
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-DKT1smAv.mjs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { Option, program } from "@commander-js/extra-typings";
|
|
5
5
|
import { ErrorWithTag, OutputClient, OutputMode, SupportedFormatter, getWarningCount, isString, log, logError, resetWarnings, setVerbose, startMessage } from "@orval/core";
|
package/dist/bin/orval.mjs.map
CHANGED
|
@@ -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 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 mock generation (msw handlers + faker factories)')\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":";;;;;;AAwBA,MAAM,eAAe,aAAa;CAC1BA;CACGC;CACIC;
|
|
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 mock generation (msw handlers + faker factories)')\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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"}
|
|
@@ -5,7 +5,7 @@ import { fetchUrls, parseJson, parseYaml, readFiles } from "@scalar/json-magic/b
|
|
|
5
5
|
import { upgrade, validate } from "@scalar/openapi-parser";
|
|
6
6
|
import { isNullish as isNullish$1, pick, unique } from "remeda";
|
|
7
7
|
import * as mock from "@orval/mock";
|
|
8
|
-
import { generateFakerForSchemas, generateMockImports, getDefaultMockOptionsForType } from "@orval/mock";
|
|
8
|
+
import { dedupeStrictMockTypeDeclarations, generateFakerForSchemas, generateMockImports, getDefaultMockOptionsForType } from "@orval/mock";
|
|
9
9
|
import angular from "@orval/angular";
|
|
10
10
|
import axios from "@orval/axios";
|
|
11
11
|
import effect from "@orval/effect";
|
|
@@ -28,8 +28,8 @@ import fs$2 from "node:fs";
|
|
|
28
28
|
import { createJiti } from "jiti";
|
|
29
29
|
//#region package.json
|
|
30
30
|
var name = "orval";
|
|
31
|
+
var version = "8.17.0";
|
|
31
32
|
var description = "A swagger client generator for typescript";
|
|
32
|
-
var version = "8.15.0";
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region src/client.ts
|
|
35
35
|
const DEFAULT_CLIENT = OutputClient.AXIOS;
|
|
@@ -172,7 +172,8 @@ const generateOperations = (outputClient = DEFAULT_CLIENT, verbsOptions, options
|
|
|
172
172
|
return {
|
|
173
173
|
type: isFunction(entry) ? OutputMockType.MSW : entry.type,
|
|
174
174
|
implementation: generated.implementation,
|
|
175
|
-
imports: generated.imports
|
|
175
|
+
imports: generated.imports,
|
|
176
|
+
strictMockSchemaTypeNames: generated.strictMockSchemaTypeNames
|
|
176
177
|
};
|
|
177
178
|
});
|
|
178
179
|
const hasImplementation = client.implementation.trim().length > 0;
|
|
@@ -266,6 +267,7 @@ async function getApiBuilder({ input, output, context }) {
|
|
|
266
267
|
footer: generateClientFooter,
|
|
267
268
|
imports: generateClientImports,
|
|
268
269
|
importsMock: generateMockImports,
|
|
270
|
+
finalizeMockImplementation: dedupeStrictMockTypeDeclarations,
|
|
269
271
|
extraFiles
|
|
270
272
|
};
|
|
271
273
|
}
|
|
@@ -275,11 +277,12 @@ function filterSpecComponents(spec, input) {
|
|
|
275
277
|
const filters = input.filters;
|
|
276
278
|
if (!filters?.tags || filters.schemas) return spec;
|
|
277
279
|
const referenced = collectReferencedComponents(spec, filters.tags, filters.mode);
|
|
280
|
+
const allSchemas = spec.components?.schemas ?? {};
|
|
278
281
|
return {
|
|
279
282
|
...spec,
|
|
280
283
|
components: {
|
|
281
284
|
...spec.components,
|
|
282
|
-
schemas:
|
|
285
|
+
schemas: filters.includeUnreferencedSchemas ? allSchemas : pick(allSchemas, referenced.schemas),
|
|
283
286
|
responses: pick(spec.components?.responses ?? {}, referenced.responses),
|
|
284
287
|
parameters: pick(spec.components?.parameters ?? {}, referenced.parameters),
|
|
285
288
|
requestBodies: pick(spec.components?.requestBodies ?? {}, referenced.requestBodies)
|
|
@@ -337,16 +340,12 @@ function getApiSchemas({ input, output, target, workspace, spec }) {
|
|
|
337
340
|
//#endregion
|
|
338
341
|
//#region src/import-specs.ts
|
|
339
342
|
async function resolveSpec(input, { parserOptions, transformer, workspace, unsafeDisableValidation = false }) {
|
|
340
|
-
const dereferencedData =
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
],
|
|
347
|
-
treeShake: false
|
|
348
|
-
}));
|
|
349
|
-
const transformedData = transformer ? await applyInputTransformer(dereferencedData, transformer, workspace) : dereferencedData;
|
|
343
|
+
const dereferencedData = await bundleAndDereferenceExternalRefs(input, parserOptions);
|
|
344
|
+
let transformedData = dereferencedData;
|
|
345
|
+
if (transformer) {
|
|
346
|
+
const applied = await applyInputTransformer(dereferencedData, transformer, workspace);
|
|
347
|
+
transformedData = hasExternalRef(applied) ? await bundleAndDereferenceExternalRefs(applied, parserOptions, isString(input) ? input : void 0) : applied;
|
|
348
|
+
}
|
|
350
349
|
if (unsafeDisableValidation) logWarning("🚨 OpenAPI spec validation is disabled.\n Code generation with invalid specs is not guaranteed to work and may break in minor updates.\n Bug reports with validation disabled will not be accepted.");
|
|
351
350
|
else {
|
|
352
351
|
validateComponentKeys(transformedData);
|
|
@@ -365,6 +364,39 @@ async function applyInputTransformer(data, transformer, workspace) {
|
|
|
365
364
|
}
|
|
366
365
|
return result;
|
|
367
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Bundle external references into the document and then resolve the `x-ext`
|
|
369
|
+
* entries that `@scalar/json-magic` produces. Shared by the initial pass and
|
|
370
|
+
* the post-transformer pass (#3327); `origin` lets the second pass resolve refs
|
|
371
|
+
* relative to the original spec file when the input is an in-memory object.
|
|
372
|
+
*/
|
|
373
|
+
async function bundleAndDereferenceExternalRefs(input, parserOptions, origin) {
|
|
374
|
+
return dereferenceExternalRef(await bundle(input, {
|
|
375
|
+
plugins: [
|
|
376
|
+
readFiles(),
|
|
377
|
+
fetchUrls({ headers: parserOptions?.headers }),
|
|
378
|
+
parseJson(),
|
|
379
|
+
parseYaml()
|
|
380
|
+
],
|
|
381
|
+
treeShake: false,
|
|
382
|
+
...origin ? { origin } : {}
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Report whether any `$ref` in the document points to an external document.
|
|
387
|
+
* Per the JSON Reference rules a ref is external when it does not start with
|
|
388
|
+
* `#` (an in-document pointer). Used to decide whether a transformer introduced
|
|
389
|
+
* new external refs that need a second bundle pass (#3327) — when it did not,
|
|
390
|
+
* the already-bundled spec is returned untouched.
|
|
391
|
+
*/
|
|
392
|
+
function hasExternalRef(obj) {
|
|
393
|
+
if (Array.isArray(obj)) return obj.some((item) => hasExternalRef(item));
|
|
394
|
+
if (isObject(obj)) {
|
|
395
|
+
if ("$ref" in obj && isString(obj.$ref) && !obj.$ref.startsWith("#")) return true;
|
|
396
|
+
return Object.values(obj).some((value) => hasExternalRef(value));
|
|
397
|
+
}
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
368
400
|
async function importSpecs(workspace, options, projectName) {
|
|
369
401
|
const { input, output } = options;
|
|
370
402
|
return importOpenApi({
|
|
@@ -851,9 +883,15 @@ function createFormData(workspace, formData) {
|
|
|
851
883
|
function normalizeSchemasOption(schemas, workspace) {
|
|
852
884
|
if (!schemas) return;
|
|
853
885
|
if (isString(schemas)) return normalizePath(schemas, workspace);
|
|
886
|
+
if (schemas.importPath !== void 0 && !schemas.importPath) throw new Error(`schemas.importPath must be a non-empty package specifier (e.g. '@acme/models'). Received an empty string.`);
|
|
887
|
+
if (schemas.importPath?.trim() === "") throw new Error(`schemas.importPath must be a non-empty package specifier (e.g. '@acme/models'). Received a whitespace-only string.`);
|
|
888
|
+
if (schemas.importPath && schemas.importPath.trim() !== schemas.importPath) throw new Error(`schemas.importPath must be a non-empty package specifier (e.g. '@acme/models'). Received a value with leading or trailing whitespace: "${schemas.importPath}"`);
|
|
889
|
+
if (schemas.importPath?.startsWith(".")) throw new Error(`schemas.importPath must be a package specifier (e.g. '@acme/models'), not a relative path. Received: "${schemas.importPath}"`);
|
|
890
|
+
if (schemas.importPath && (path.isAbsolute(schemas.importPath) || /^[A-Za-z]:[\\/]/.test(schemas.importPath) || schemas.importPath.startsWith("\\\\"))) throw new Error(`schemas.importPath must be a package specifier (e.g. '@acme/models'), not an absolute path. Received: "${schemas.importPath}"`);
|
|
854
891
|
return {
|
|
855
892
|
path: normalizePath(schemas.path, workspace),
|
|
856
|
-
type: schemas.type
|
|
893
|
+
type: schemas.type,
|
|
894
|
+
importPath: schemas.importPath
|
|
857
895
|
};
|
|
858
896
|
}
|
|
859
897
|
function normalizeEffectOptions(effect) {
|
|
@@ -901,11 +939,14 @@ async function normalizeOptions(optionsExport, workspace = process.cwd(), global
|
|
|
901
939
|
};
|
|
902
940
|
else if (mocksOption && typeof mocksOption === "object") {
|
|
903
941
|
if (!Array.isArray(mocksOption.generators)) throw new TypeError("mock.generators must be an array of generator entries (e.g. [{ type: \"msw\" }]).");
|
|
942
|
+
const sharedMockPath = mocksOption.path && isString(mocksOption.path) ? normalizePath(mocksOption.path, outputWorkspace) : void 0;
|
|
904
943
|
mocks = {
|
|
905
944
|
indexMockFiles: mocksOption.indexMockFiles ?? false,
|
|
945
|
+
path: sharedMockPath,
|
|
906
946
|
generators: mocksOption.generators.map((m) => isFunction(m) ? m : {
|
|
907
947
|
...getDefaultMockOptionsForType(m.type),
|
|
908
|
-
...m
|
|
948
|
+
...m,
|
|
949
|
+
path: m.path && isString(m.path) ? normalizePath(m.path, outputWorkspace) : sharedMockPath
|
|
909
950
|
})
|
|
910
951
|
};
|
|
911
952
|
}
|
|
@@ -1261,7 +1302,7 @@ function normalizeMcpServerOptions(server, workspace) {
|
|
|
1261
1302
|
};
|
|
1262
1303
|
}
|
|
1263
1304
|
function normalizeMcpOptions(mcp = {}, workspace) {
|
|
1264
|
-
return
|
|
1305
|
+
return mcp.server ? { server: normalizeMcpServerOptions(mcp.server, workspace) } : {};
|
|
1265
1306
|
}
|
|
1266
1307
|
function normalizeJSDocOptions(jsdoc = {}) {
|
|
1267
1308
|
return { ...jsdoc };
|
|
@@ -1816,6 +1857,7 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
|
|
|
1816
1857
|
const strict = output.override.zod.strict.body;
|
|
1817
1858
|
const coerce = output.override.zod.coerce.body;
|
|
1818
1859
|
const useReusableSchemas = output.override.zod.generateReusableSchemas === true;
|
|
1860
|
+
const useNamedParameters = output.override.useNamedParameters ?? false;
|
|
1819
1861
|
const uniqueVerbsSchemas = dedupeSchemasByName(verbOptionsArray.flatMap((verbOption) => {
|
|
1820
1862
|
const operation = verbOption.originalOperation;
|
|
1821
1863
|
const shouldGenerate = {
|
|
@@ -1836,6 +1878,15 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
|
|
|
1836
1878
|
encoding: bodyMedia?.encoding
|
|
1837
1879
|
}] : [];
|
|
1838
1880
|
const parameters = operation.parameters;
|
|
1881
|
+
const pathParams = parameters?.filter((p) => "in" in p && p.in === "path");
|
|
1882
|
+
const pathParamsSchemas = useNamedParameters && shouldGenerate.param && pathParams && pathParams.length > 0 ? [{
|
|
1883
|
+
name: `${pascal(verbOption.operationName)}PathParameters`,
|
|
1884
|
+
schema: {
|
|
1885
|
+
type: "object",
|
|
1886
|
+
properties: Object.fromEntries(pathParams.filter((p) => "schema" in p && p.schema).map((p) => [p.name, useReusableSchemas ? p.schema : dereference(p.schema, zodContext)])),
|
|
1887
|
+
required: pathParams.filter((p) => p.required).map((p) => p.name).filter((name) => name !== void 0)
|
|
1888
|
+
}
|
|
1889
|
+
}] : [];
|
|
1839
1890
|
const queryParams = parameters?.filter((p) => "in" in p && p.in === "query");
|
|
1840
1891
|
const queryParamsSchemas = shouldGenerate.query && queryParams && queryParams.length > 0 ? [{
|
|
1841
1892
|
name: `${pascal(verbOption.operationName)}Params`,
|
|
@@ -1860,6 +1911,7 @@ async function writeZodSchemasFromVerbs(verbOptions, schemasPath, fileExtension,
|
|
|
1860
1911
|
})) : [];
|
|
1861
1912
|
return dedupeSchemasByName([
|
|
1862
1913
|
...bodySchemas,
|
|
1914
|
+
...pathParamsSchemas,
|
|
1863
1915
|
...queryParamsSchemas,
|
|
1864
1916
|
...headerParamsSchemas,
|
|
1865
1917
|
...responseSchemas
|
|
@@ -1964,13 +2016,17 @@ async function writeFakerSchemaMocks(builder, options, header) {
|
|
|
1964
2016
|
if (!fakerEntry) return;
|
|
1965
2017
|
const schemasWithDef = builder.schemas.filter((s) => !!s.schema);
|
|
1966
2018
|
if (schemasWithDef.length === 0) return;
|
|
1967
|
-
const { implementation, imports } = generateFakerForSchemas(schemasWithDef, {
|
|
2019
|
+
const { implementation, imports, strictMockSchemaTypeNames } = generateFakerForSchemas(schemasWithDef, {
|
|
1968
2020
|
spec: builder.spec,
|
|
1969
2021
|
target: builder.target,
|
|
1970
2022
|
workspace: "",
|
|
1971
2023
|
output
|
|
1972
2024
|
}, fakerEntry);
|
|
1973
2025
|
if (!implementation.trim()) return;
|
|
2026
|
+
const finalizedImplementation = builder.finalizeMockImplementation ? builder.finalizeMockImplementation(implementation, {
|
|
2027
|
+
mockOptions: output.override.mock,
|
|
2028
|
+
strictSchemaTypeNames: strictMockSchemaTypeNames
|
|
2029
|
+
}) : implementation;
|
|
1974
2030
|
let filePath;
|
|
1975
2031
|
let schemaImportPath;
|
|
1976
2032
|
const fileExtension = output.fileExtension || ".ts";
|
|
@@ -1996,7 +2052,7 @@ async function writeFakerSchemaMocks(builder, options, header) {
|
|
|
1996
2052
|
bucket.push(imp);
|
|
1997
2053
|
grouped.set(key, bucket);
|
|
1998
2054
|
}
|
|
1999
|
-
const content = `${header}${generateDependencyImports(
|
|
2055
|
+
const content = `${header}${generateDependencyImports(finalizedImplementation, [{
|
|
2000
2056
|
exports: [{
|
|
2001
2057
|
name: "faker",
|
|
2002
2058
|
values: true
|
|
@@ -2005,7 +2061,7 @@ async function writeFakerSchemaMocks(builder, options, header) {
|
|
|
2005
2061
|
}, ...[...grouped.entries()].map(([dependency, exports]) => ({
|
|
2006
2062
|
exports,
|
|
2007
2063
|
dependency
|
|
2008
|
-
}))], void 0, !!output.schemas, false)}\n\n${
|
|
2064
|
+
}))], void 0, !!output.schemas, false)}\n\n${finalizedImplementation}`;
|
|
2009
2065
|
await writeGeneratedFile(filePath, content);
|
|
2010
2066
|
return filePath;
|
|
2011
2067
|
}
|
|
@@ -2270,4 +2326,4 @@ async function loadConfigFile(configFilePath) {
|
|
|
2270
2326
|
//#endregion
|
|
2271
2327
|
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 };
|
|
2272
2328
|
|
|
2273
|
-
//# sourceMappingURL=config-
|
|
2329
|
+
//# sourceMappingURL=config-DKT1smAv.mjs.map
|