@orval/mock 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/index.d.mts +15 -4
- package/dist/index.mjs +231 -33
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -31
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ClientMockGeneratorBuilder, ContextSpec, FakerMockOptions, GenerateMockImports, GeneratorImport, GeneratorOptions, GeneratorSchema, GeneratorVerbOptions, GlobalMockOptions, MswMockOptions } from "@orval/core";
|
|
1
|
+
import { ClientMockGeneratorBuilder, ContextSpec, FakerMockOptions, FinalizeMockImplementationOptions, GenerateMockImports, GeneratorImport, GeneratorOptions, GeneratorSchema, GeneratorVerbOptions, GlobalMockOptions, MswMockOptions } from "@orval/core";
|
|
3
2
|
|
|
4
3
|
//#region src/faker/index.d.ts
|
|
5
4
|
/**
|
|
@@ -18,6 +17,7 @@ declare function generateFaker(generatorVerbOptions: GeneratorVerbOptions, gener
|
|
|
18
17
|
interface GenerateFakerForSchemasResult {
|
|
19
18
|
implementation: string;
|
|
20
19
|
imports: GeneratorImport[];
|
|
20
|
+
strictMockSchemaTypeNames?: string[];
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Builds the contents of a consolidated faker mock file for every entry under
|
|
@@ -30,6 +30,17 @@ interface GenerateFakerForSchemasResult {
|
|
|
30
30
|
*/
|
|
31
31
|
declare function generateFakerForSchemas(schemas: GeneratorSchema[], context: ContextSpec, options: GlobalMockOptions): GenerateFakerForSchemasResult;
|
|
32
32
|
//#endregion
|
|
33
|
+
//#region src/mock-types.d.ts
|
|
34
|
+
declare function buildStrictMockTypeFileHeader(schemaTypeNames: Iterable<string>): string;
|
|
35
|
+
/**
|
|
36
|
+
* Prepends shared strict-mock helper types and each `{Schema}Mock` alias once at
|
|
37
|
+
* the top of a mock file. Generators pass `strictSchemaTypeNames`; no scraping.
|
|
38
|
+
*
|
|
39
|
+
* Not idempotent — callers must invoke this exactly once per aggregated mock
|
|
40
|
+
* file (writers and `writeFakerSchemaMocks`), not from import hooks.
|
|
41
|
+
*/
|
|
42
|
+
declare function dedupeStrictMockTypeDeclarations(implementation: string, options?: FinalizeMockImplementationOptions): string;
|
|
43
|
+
//#endregion
|
|
33
44
|
//#region src/msw/index.d.ts
|
|
34
45
|
declare const generateMSWImports: GenerateMockImports;
|
|
35
46
|
declare function generateMSW(generatorVerbOptions: GeneratorVerbOptions, generatorOptions: GeneratorOptions): ClientMockGeneratorBuilder;
|
|
@@ -55,7 +66,7 @@ declare const generateMockImports: GenerateMockImports;
|
|
|
55
66
|
*/
|
|
56
67
|
declare function generateMock(generatorVerbOptions: GeneratorVerbOptions, generatorOptions: Omit<GeneratorOptions, 'mock'> & {
|
|
57
68
|
mock: GlobalMockOptions;
|
|
58
|
-
}):
|
|
69
|
+
}): import("@orval/core").ClientMockGeneratorBuilder;
|
|
59
70
|
//#endregion
|
|
60
|
-
export { DEFAULT_FAKER_OPTIONS, DEFAULT_MSW_OPTIONS, type GenerateFakerForSchemasResult, generateFaker, generateFakerForSchemas, generateFakerImports, generateMSW, generateMSWImports, generateMock, generateMockImports, getDefaultMockOptionsForType };
|
|
71
|
+
export { DEFAULT_FAKER_OPTIONS, DEFAULT_MSW_OPTIONS, type GenerateFakerForSchemasResult, buildStrictMockTypeFileHeader, dedupeStrictMockTypeDeclarations, generateFaker, generateFakerForSchemas, generateFakerImports, generateMSW, generateMSWImports, generateMock, generateMockImports, getDefaultMockOptionsForType };
|
|
61
72
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,134 @@
|
|
|
1
|
-
import { DefaultTag, EnumGeneration, OutputMockType, OutputMode, PropertySortOrder, camel, compareVersions,
|
|
1
|
+
import { DefaultTag, EnumGeneration, OutputMockType, OutputMode, PropertySortOrder, camel, compareVersions, escapeRegExp, generalJSTypesWithArray, generateDependencyImports, getKey, getRefInfo, isBoolean, isFunction, isMswMock, isNumber, isObject, isReference, isSchema, isString, jsStringLiteralEscape, kebab, mergeDeep, pascal, resolveRef, sanitize, stringify } from "@orval/core";
|
|
2
2
|
import { prop } from "remeda";
|
|
3
|
+
//#region src/mock-types.ts
|
|
4
|
+
function isStrictMock(mockOptions) {
|
|
5
|
+
return Boolean(mockOptions && mockOptions.required && mockOptions.nonNullable);
|
|
6
|
+
}
|
|
7
|
+
function getStrictMockTypeName(typeName) {
|
|
8
|
+
return `${typeName}Mock`;
|
|
9
|
+
}
|
|
10
|
+
function getStrictMockHelperTypeDeclarations() {
|
|
11
|
+
return `export type KeysWithNull<O> = {
|
|
12
|
+
[K in keyof O]-?: null extends O[K] ? K : never;
|
|
13
|
+
}[keyof O];
|
|
14
|
+
|
|
15
|
+
export type MockWithNullableOverrides<
|
|
16
|
+
T,
|
|
17
|
+
O extends Partial<T>,
|
|
18
|
+
M extends Record<keyof T, unknown>,
|
|
19
|
+
> = Omit<M, Extract<KeysWithNull<O>, keyof T>> & {
|
|
20
|
+
[K in Extract<KeysWithNull<O>, keyof T>]: M[K] | null;
|
|
21
|
+
};`;
|
|
22
|
+
}
|
|
23
|
+
function getStrictMockTypeDeclaration(typeName) {
|
|
24
|
+
return `export type ${getStrictMockTypeName(typeName)} = {\n [K in keyof Required<${typeName}>]: NonNullable<Required<${typeName}>[K]>;\n};`;
|
|
25
|
+
}
|
|
26
|
+
function getStrictMockTypeDeclarations(typeNames) {
|
|
27
|
+
const unique = [...new Set(typeNames)];
|
|
28
|
+
if (unique.length === 0) return "";
|
|
29
|
+
return unique.map((typeName) => getStrictMockTypeDeclaration(typeName)).join("\n\n");
|
|
30
|
+
}
|
|
31
|
+
function getMockFactoryReturnType(typeName, mockOptions) {
|
|
32
|
+
return isStrictMock(mockOptions) ? getStrictMockTypeName(typeName) : typeName;
|
|
33
|
+
}
|
|
34
|
+
function getMockFactorySignatureParts(typeName, mockOptions, options = {}) {
|
|
35
|
+
const isOverridable = options.isOverridable ?? false;
|
|
36
|
+
const overrideType = options.overrideType ?? `Partial<${typeName}>`;
|
|
37
|
+
const mockTypeName = getStrictMockTypeName(typeName);
|
|
38
|
+
if (!isOverridable) return {
|
|
39
|
+
param: "",
|
|
40
|
+
returnType: getMockFactoryReturnType(typeName, mockOptions),
|
|
41
|
+
returnCast: ""
|
|
42
|
+
};
|
|
43
|
+
if (isStrictMock(mockOptions)) return {
|
|
44
|
+
param: `<O extends ${overrideType} = {}>(overrideResponse?: O)`,
|
|
45
|
+
returnType: `MockWithNullableOverrides<${typeName}, O, ${mockTypeName}>`,
|
|
46
|
+
returnCast: ` as MockWithNullableOverrides<${typeName}, O, ${mockTypeName}>`
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
param: `overrideResponse: ${overrideType} = {}`,
|
|
50
|
+
returnType: typeName,
|
|
51
|
+
returnCast: ""
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function getSimpleSchemaReturnType(returnType, schemaTypeNames) {
|
|
55
|
+
const trimmed = returnType.trim();
|
|
56
|
+
return schemaTypeNames.includes(trimmed) ? trimmed : void 0;
|
|
57
|
+
}
|
|
58
|
+
function formatMockFactoryDeclaration(factoryName, param, returnType, body, returnCast, options) {
|
|
59
|
+
return `${param ? param.startsWith("<") ? `export const ${factoryName} = ${param}` : `export const ${factoryName} = (${param})` : `export const ${factoryName} = ()`}${options?.omitReturnType || !returnType ? "" : `: ${returnType}`} => (${body})${returnCast}${returnCast || options?.terminateStatement ? ";" : ""}`;
|
|
60
|
+
}
|
|
61
|
+
function getSchemaTypeNamesFromResponses(responses) {
|
|
62
|
+
const names = /* @__PURE__ */ new Set();
|
|
63
|
+
for (const response of responses) {
|
|
64
|
+
for (const imp of response.imports) {
|
|
65
|
+
if (imp.values || imp.schemaFactory) continue;
|
|
66
|
+
const importName = imp.alias ?? imp.name;
|
|
67
|
+
if (/^[A-Z]\w*$/.test(importName)) names.add(importName);
|
|
68
|
+
}
|
|
69
|
+
const { value } = response;
|
|
70
|
+
if (!value) continue;
|
|
71
|
+
const baseType = value.endsWith("[]") ? value.slice(0, -2) : value;
|
|
72
|
+
if (/^[A-Z]\w*$/.test(baseType)) names.add(baseType);
|
|
73
|
+
}
|
|
74
|
+
return [...names];
|
|
75
|
+
}
|
|
76
|
+
function buildStrictMockTypeFileHeader(schemaTypeNames) {
|
|
77
|
+
const schemaBlock = getStrictMockTypeDeclarations([...new Set(schemaTypeNames)]);
|
|
78
|
+
return [getStrictMockHelperTypeDeclarations(), schemaBlock].filter(Boolean).join("\n\n");
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Prepends shared strict-mock helper types and each `{Schema}Mock` alias once at
|
|
82
|
+
* the top of a mock file. Generators pass `strictSchemaTypeNames`; no scraping.
|
|
83
|
+
*
|
|
84
|
+
* Not idempotent — callers must invoke this exactly once per aggregated mock
|
|
85
|
+
* file (writers and `writeFakerSchemaMocks`), not from import hooks.
|
|
86
|
+
*/
|
|
87
|
+
function dedupeStrictMockTypeDeclarations(implementation, options = {}) {
|
|
88
|
+
if (!isStrictMock(options.mockOptions)) return implementation;
|
|
89
|
+
const schemaTypeNames = options.strictSchemaTypeNames ? [...new Set(options.strictSchemaTypeNames)] : [];
|
|
90
|
+
if (schemaTypeNames.length === 0) return implementation;
|
|
91
|
+
return `${buildStrictMockTypeFileHeader(schemaTypeNames)}\n\n${implementation.trimStart()}`;
|
|
92
|
+
}
|
|
93
|
+
function applyStrictMockReturnType(returnType, schemaTypeNames) {
|
|
94
|
+
if (schemaTypeNames.length === 0) return returnType;
|
|
95
|
+
let result = returnType;
|
|
96
|
+
const sorted = [...schemaTypeNames].toSorted((a, b) => b.length - a.length);
|
|
97
|
+
for (const name of sorted) result = result.replaceAll(new RegExp(String.raw`\b${escapeRegExp(name)}\b`, "g"), getStrictMockTypeName(name));
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
const STRICT_MOCK_SCHEMA_TYPE_FROM_OVERRIDES = /MockWithNullableOverrides<([A-Z]\w*),/g;
|
|
101
|
+
const STRICT_MOCK_SCHEMA_TYPE_FROM_OVERRIDE_ALIAS = /MockWithNullableOverrides<[^,]+,\s*[^,]+,\s*([A-Z]\w*Mock)>/g;
|
|
102
|
+
const STRICT_MOCK_SCHEMA_TYPE_FROM_MOCK_ALIAS_RETURN = /\): ([A-Z]\w*Mock)(?:\[\]|;)/g;
|
|
103
|
+
/** Inverse of {@link getStrictMockTypeName}: `PetMock` → `Pet`, `WidgetMockMock` → `WidgetMock`. */
|
|
104
|
+
function getSchemaTypeNameFromStrictMockAlias(alias) {
|
|
105
|
+
return alias.endsWith("Mock") ? alias.slice(0, -4) : alias;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Collect schema type names referenced by strict mock factories in generated
|
|
109
|
+
* implementation text (nested split factories, array item helpers, etc.).
|
|
110
|
+
*
|
|
111
|
+
* This reverse-parses emitted factory syntax and is therefore coupled to the
|
|
112
|
+
* current `formatMockFactoryDeclaration` / `getMockFactorySignatureParts`
|
|
113
|
+
* shape. The structurally robust alternative is to record each nested item's
|
|
114
|
+
* schema name where split factories are generated (array-item / faker getters,
|
|
115
|
+
* where the `$ref` name is known) and thread it into `strictMockSchemaTypeNames`.
|
|
116
|
+
*/
|
|
117
|
+
function collectStrictMockSchemaTypeNamesFromImplementation(implementation) {
|
|
118
|
+
const names = /* @__PURE__ */ new Set();
|
|
119
|
+
for (const match of implementation.matchAll(STRICT_MOCK_SCHEMA_TYPE_FROM_OVERRIDES)) names.add(match[1]);
|
|
120
|
+
for (const pattern of [STRICT_MOCK_SCHEMA_TYPE_FROM_OVERRIDE_ALIAS, STRICT_MOCK_SCHEMA_TYPE_FROM_MOCK_ALIAS_RETURN]) for (const match of implementation.matchAll(pattern)) names.add(getSchemaTypeNameFromStrictMockAlias(match[1]));
|
|
121
|
+
return [...names];
|
|
122
|
+
}
|
|
123
|
+
function mergeStrictMockSchemaTypeNames(...groups) {
|
|
124
|
+
const names = /* @__PURE__ */ new Set();
|
|
125
|
+
for (const group of groups) {
|
|
126
|
+
if (!group) continue;
|
|
127
|
+
for (const name of group) names.add(name);
|
|
128
|
+
}
|
|
129
|
+
return names.size > 0 ? [...names] : void 0;
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
3
132
|
//#region src/delay.ts
|
|
4
133
|
const getDelay = (override, options) => {
|
|
5
134
|
const mswOptions = options && isMswMock(options) ? options : void 0;
|
|
@@ -55,7 +184,7 @@ function getReferenceName$1(ref, context) {
|
|
|
55
184
|
if (!ref) return "";
|
|
56
185
|
return getRefInfo(ref, context).name;
|
|
57
186
|
}
|
|
58
|
-
function getMockObject({ item, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, splitMockImplementations, allowOverride = false }) {
|
|
187
|
+
function getMockObject({ item, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, existingReferencedAllOfRefs = [], splitMockImplementations, allowOverride = false }) {
|
|
59
188
|
if (isReference(item)) return resolveMockValue({
|
|
60
189
|
schema: {
|
|
61
190
|
...item,
|
|
@@ -68,6 +197,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
|
|
|
68
197
|
context,
|
|
69
198
|
imports,
|
|
70
199
|
existingReferencedProperties,
|
|
200
|
+
existingReferencedAllOfRefs,
|
|
71
201
|
splitMockImplementations
|
|
72
202
|
});
|
|
73
203
|
const schemaItem = item;
|
|
@@ -88,6 +218,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
|
|
|
88
218
|
context,
|
|
89
219
|
imports,
|
|
90
220
|
existingReferencedProperties,
|
|
221
|
+
existingReferencedAllOfRefs,
|
|
91
222
|
splitMockImplementations
|
|
92
223
|
});
|
|
93
224
|
if (Array.isArray(itemType)) {
|
|
@@ -108,6 +239,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
|
|
|
108
239
|
context,
|
|
109
240
|
imports,
|
|
110
241
|
existingReferencedProperties,
|
|
242
|
+
existingReferencedAllOfRefs,
|
|
111
243
|
splitMockImplementations
|
|
112
244
|
});
|
|
113
245
|
}
|
|
@@ -140,6 +272,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
|
|
|
140
272
|
context,
|
|
141
273
|
imports,
|
|
142
274
|
existingReferencedProperties,
|
|
275
|
+
existingReferencedAllOfRefs: [],
|
|
143
276
|
splitMockImplementations
|
|
144
277
|
});
|
|
145
278
|
imports.push(...resolvedValue.imports);
|
|
@@ -187,6 +320,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
|
|
|
187
320
|
context,
|
|
188
321
|
imports,
|
|
189
322
|
existingReferencedProperties,
|
|
323
|
+
existingReferencedAllOfRefs: [],
|
|
190
324
|
splitMockImplementations
|
|
191
325
|
});
|
|
192
326
|
return {
|
|
@@ -211,9 +345,12 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
|
|
|
211
345
|
*/
|
|
212
346
|
function getArrayItemMockFileScope(context, tags) {
|
|
213
347
|
const mode = context.output.mode;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
348
|
+
const mockType = context.activeMockOutputType ?? OutputMockType.MSW;
|
|
349
|
+
let base;
|
|
350
|
+
if (mode === OutputMode.TAGS || mode === OutputMode.TAGS_SPLIT) base = `tag:${kebab(tags.length > 0 ? tags[0] : DefaultTag)}`;
|
|
351
|
+
else if (mode === OutputMode.SPLIT) base = "split";
|
|
352
|
+
else base = "single";
|
|
353
|
+
return `${base}:${mockType}`;
|
|
217
354
|
}
|
|
218
355
|
function getFileLevelExtractedFactories(context, scope) {
|
|
219
356
|
context.arrayItemMockFactories ??= /* @__PURE__ */ new Map();
|
|
@@ -224,11 +361,11 @@ function getFileLevelExtractedFactories(context, scope) {
|
|
|
224
361
|
return factories;
|
|
225
362
|
}
|
|
226
363
|
/**
|
|
227
|
-
* True when
|
|
228
|
-
*
|
|
364
|
+
* True when any mock generator entry opts into reusable array-item mock
|
|
365
|
+
* factories for object-like array item schemas in operation responses.
|
|
229
366
|
*/
|
|
230
367
|
function shouldExtractArrayItemFactories(context) {
|
|
231
|
-
return
|
|
368
|
+
return context.output.mock.generators.some((g) => !isFunction(g) && g.arrayItems === true);
|
|
232
369
|
}
|
|
233
370
|
/**
|
|
234
371
|
* True when `schemas: true` already emits a consolidated factory for this
|
|
@@ -327,7 +464,12 @@ function extractArrayItemMock({ items, propertyName, parentName, operationId, ta
|
|
|
327
464
|
const { factoryName, typeName } = names;
|
|
328
465
|
const fileLevelFactories = getFileLevelExtractedFactories(context, getArrayItemMockFileScope(context, tags));
|
|
329
466
|
if (!(fileLevelFactories.has(factoryName) || splitMockImplementations.some((f) => f.includes(`export const ${factoryName}`)))) {
|
|
330
|
-
const
|
|
467
|
+
const mockOptions = context.output.override.mock;
|
|
468
|
+
const { param, returnType, returnCast } = getMockFactorySignatureParts(typeName, mockOptions, {
|
|
469
|
+
isOverridable: true,
|
|
470
|
+
overrideType: `Partial<${typeName}>`
|
|
471
|
+
});
|
|
472
|
+
const func = formatMockFactoryDeclaration(factoryName, param, returnType, `{${mapValue.startsWith("...") ? "" : "..."}${mapValue}, ...${overrideVarName}}`, returnCast, { terminateStatement: true });
|
|
331
473
|
splitMockImplementations.push(func);
|
|
332
474
|
fileLevelFactories.add(factoryName);
|
|
333
475
|
}
|
|
@@ -336,7 +478,7 @@ function extractArrayItemMock({ items, propertyName, parentName, operationId, ta
|
|
|
336
478
|
}
|
|
337
479
|
//#endregion
|
|
338
480
|
//#region src/faker/getters/scalar.ts
|
|
339
|
-
function getMockScalar({ item, imports, mockOptions, operationId, tags, combine, context, existingReferencedProperties, splitMockImplementations, allowOverride = false }) {
|
|
481
|
+
function getMockScalar({ item, imports, mockOptions, operationId, tags, combine, context, existingReferencedProperties, existingReferencedAllOfRefs = [], splitMockImplementations, allowOverride = false }) {
|
|
340
482
|
const safeMockOptions = mockOptions ?? {};
|
|
341
483
|
const nonNullableOption = safeMockOptions.nonNullable;
|
|
342
484
|
if (item.isRef) existingReferencedProperties = [...existingReferencedProperties, item.name];
|
|
@@ -458,6 +600,7 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
|
|
|
458
600
|
context,
|
|
459
601
|
imports,
|
|
460
602
|
existingReferencedProperties,
|
|
603
|
+
existingReferencedAllOfRefs,
|
|
461
604
|
splitMockImplementations
|
|
462
605
|
});
|
|
463
606
|
if (enums) return {
|
|
@@ -559,6 +702,7 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
|
|
|
559
702
|
context,
|
|
560
703
|
imports,
|
|
561
704
|
existingReferencedProperties,
|
|
705
|
+
existingReferencedAllOfRefs,
|
|
562
706
|
splitMockImplementations,
|
|
563
707
|
allowOverride
|
|
564
708
|
});
|
|
@@ -590,7 +734,7 @@ function getItemType(item) {
|
|
|
590
734
|
}
|
|
591
735
|
function getEnum(item, imports, context, existingReferencedProperties, type) {
|
|
592
736
|
if (!item.enum) return "";
|
|
593
|
-
let enumValue = `[${item.enum.filter((e) => e !== null).map((e) => type === "string" || type === void 0 && isString(e) ? `'${
|
|
737
|
+
let enumValue = `[${item.enum.filter((e) => e !== null).map((e) => type === "string" || type === void 0 && isString(e) ? `'${jsStringLiteralEscape(e)}'` : e).join(",")}]`;
|
|
594
738
|
if (context.output.override.enumGenerationType === EnumGeneration.ENUM) if (item.isRef || existingReferencedProperties.length === 0) {
|
|
595
739
|
enumValue += ` as ${item.name}${item.name.endsWith("[]") ? "" : "[]"}`;
|
|
596
740
|
imports.push({ name: item.name });
|
|
@@ -622,7 +766,8 @@ function stripArrayMarkerSegments(s) {
|
|
|
622
766
|
function resolveMockOverride(properties = {}, item, nonNullableOption) {
|
|
623
767
|
const path = item.path ?? `#.${item.name}`;
|
|
624
768
|
const normalizedPath = stripArrayMarkerSegments(path);
|
|
625
|
-
const
|
|
769
|
+
const entries = Object.entries(properties);
|
|
770
|
+
let property = entries.find(([key]) => {
|
|
626
771
|
if (isRegex(key)) {
|
|
627
772
|
const regex = new RegExp(key.slice(1, -1));
|
|
628
773
|
if (regex.test(item.name) || regex.test(path)) return true;
|
|
@@ -630,6 +775,7 @@ function resolveMockOverride(properties = {}, item, nonNullableOption) {
|
|
|
630
775
|
if (`#.${stripArrayMarkerSegments(key)}` === normalizedPath) return true;
|
|
631
776
|
return false;
|
|
632
777
|
});
|
|
778
|
+
if (!property) property = entries.find(([key]) => !isRegex(key) && !key.includes(".") && key === item.name);
|
|
633
779
|
if (!property) return;
|
|
634
780
|
return {
|
|
635
781
|
value: getNullable(property[1], isNullableSchema(item), nonNullableOption),
|
|
@@ -696,7 +842,7 @@ function hasOverrideTouchingSchema(schemaProperties, mockOptions, operationId, t
|
|
|
696
842
|
});
|
|
697
843
|
});
|
|
698
844
|
}
|
|
699
|
-
function resolveMockValue({ schema, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, splitMockImplementations, allowOverride }) {
|
|
845
|
+
function resolveMockValue({ schema, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, existingReferencedAllOfRefs = [], splitMockImplementations, allowOverride }) {
|
|
700
846
|
if (isReference(schema)) {
|
|
701
847
|
const schemaReference = schema;
|
|
702
848
|
const { name, refPaths } = getRefInfo(typeof schema.$ref === "string" ? schema.$ref : "", context);
|
|
@@ -757,6 +903,7 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
|
|
|
757
903
|
context,
|
|
758
904
|
imports,
|
|
759
905
|
existingReferencedProperties,
|
|
906
|
+
existingReferencedAllOfRefs,
|
|
760
907
|
splitMockImplementations,
|
|
761
908
|
allowOverride
|
|
762
909
|
});
|
|
@@ -764,9 +911,13 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
|
|
|
764
911
|
const funcName = `get${pascal(operationId)}Response${pascal(newSchema.name)}Mock`;
|
|
765
912
|
if (!splitMockImplementations.some((f) => f.includes(`export const ${funcName}`))) {
|
|
766
913
|
const discriminatedProperty = newSchema.discriminator?.propertyName;
|
|
767
|
-
let
|
|
768
|
-
if (discriminatedProperty)
|
|
769
|
-
const
|
|
914
|
+
let overrideType = `Partial<${newSchema.name}>`;
|
|
915
|
+
if (discriminatedProperty) overrideType = `Omit<${overrideType}, '${discriminatedProperty}'>`;
|
|
916
|
+
const { param, returnType, returnCast } = getMockFactorySignatureParts(newSchema.name, mockOptions, {
|
|
917
|
+
isOverridable: true,
|
|
918
|
+
overrideType
|
|
919
|
+
});
|
|
920
|
+
const func = formatMockFactoryDeclaration(funcName, param, returnType, `{${scalar.value.startsWith("...") ? "" : "..."}${scalar.value}, ...${overrideVarName}}`, returnCast, { terminateStatement: true });
|
|
770
921
|
splitMockImplementations.push(func);
|
|
771
922
|
}
|
|
772
923
|
scalar.value = newSchema.nullable ? `${funcName}()` : `{...${funcName}()}`;
|
|
@@ -787,6 +938,7 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
|
|
|
787
938
|
context,
|
|
788
939
|
imports,
|
|
789
940
|
existingReferencedProperties,
|
|
941
|
+
existingReferencedAllOfRefs,
|
|
790
942
|
splitMockImplementations,
|
|
791
943
|
allowOverride
|
|
792
944
|
}),
|
|
@@ -817,7 +969,7 @@ function getReferenceName(ref, context) {
|
|
|
817
969
|
if (!ref) return "";
|
|
818
970
|
return getRefInfo(ref, context).name;
|
|
819
971
|
}
|
|
820
|
-
function combineSchemasMock({ item, separator, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, splitMockImplementations }) {
|
|
972
|
+
function combineSchemasMock({ item, separator, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, existingReferencedAllOfRefs = [], splitMockImplementations }) {
|
|
821
973
|
const combineImports = [];
|
|
822
974
|
const includedProperties = [...combine?.includedProperties ?? []];
|
|
823
975
|
const separatorItems = item[separator] ?? [];
|
|
@@ -854,6 +1006,7 @@ function combineSchemasMock({ item, separator, mockOptions, operationId, tags, c
|
|
|
854
1006
|
context,
|
|
855
1007
|
imports,
|
|
856
1008
|
existingReferencedProperties,
|
|
1009
|
+
existingReferencedAllOfRefs,
|
|
857
1010
|
splitMockImplementations
|
|
858
1011
|
}) : void 0;
|
|
859
1012
|
includedProperties.push(...itemResolvedValue?.includedProperties ?? []);
|
|
@@ -867,7 +1020,7 @@ function combineSchemasMock({ item, separator, mockOptions, operationId, tags, c
|
|
|
867
1020
|
let value = separator === "allOf" ? "" : "faker.helpers.arrayElement([";
|
|
868
1021
|
for (const val of separatorItems) {
|
|
869
1022
|
const refName = isReference(val) ? getReferenceName(val.$ref, context) : "";
|
|
870
|
-
if (separator === "allOf" ? refName && (refName === item.name || existingReferencedProperties.includes(refName) && !item.isRef) : refName && existingReferencedProperties.includes(refName)) {
|
|
1023
|
+
if (separator === "allOf" ? refName && (refName === item.name || existingReferencedProperties.includes(refName) && !item.isRef || existingReferencedAllOfRefs.includes(refName)) : refName && existingReferencedProperties.includes(refName)) {
|
|
871
1024
|
if (separatorItems.length === 1) value = "undefined";
|
|
872
1025
|
continue;
|
|
873
1026
|
}
|
|
@@ -897,6 +1050,7 @@ function combineSchemasMock({ item, separator, mockOptions, operationId, tags, c
|
|
|
897
1050
|
context,
|
|
898
1051
|
imports,
|
|
899
1052
|
existingReferencedProperties,
|
|
1053
|
+
existingReferencedAllOfRefs: separator === "allOf" && refName ? [...existingReferencedAllOfRefs, refName] : [],
|
|
900
1054
|
splitMockImplementations
|
|
901
1055
|
});
|
|
902
1056
|
combineImports.push(...resolvedValue.imports);
|
|
@@ -992,6 +1146,7 @@ function getMockWithoutFunc(spec, override) {
|
|
|
992
1146
|
numberMin: override?.mock?.numberMin,
|
|
993
1147
|
numberMax: override?.mock?.numberMax,
|
|
994
1148
|
required: override?.mock?.required,
|
|
1149
|
+
nonNullable: override?.mock?.nonNullable,
|
|
995
1150
|
fractionDigits: override?.mock?.fractionDigits,
|
|
996
1151
|
...override?.mock?.properties ? { properties: getMockPropertiesWithoutFunc(override.mock.properties, spec) } : {},
|
|
997
1152
|
...override?.mock?.format ? { format: getMockPropertiesWithoutFunc(override.mock.format, spec) } : {},
|
|
@@ -1190,7 +1345,28 @@ function generateDefinition(name, route, getResponseMockFunctionNameBase, handle
|
|
|
1190
1345
|
const overrideResponseType = `Partial<Extract<${nonVoidMockReturnType}, object>>`;
|
|
1191
1346
|
const shouldPreferJsonResponse = hasJsonContentType && !hasStringReturnType;
|
|
1192
1347
|
const needsRuntimeContentTypeSwitch = isTextResponse && hasJsonContentType && hasStringReturnType && mockReturnType !== "string";
|
|
1193
|
-
const
|
|
1348
|
+
const mockOptionsFromOverride = override.mock;
|
|
1349
|
+
const strictMock = isStrictMock(mockOptionsFromOverride);
|
|
1350
|
+
const schemaTypeNames = strictMock ? getSchemaTypeNamesFromResponses(responses) : [];
|
|
1351
|
+
const strictMockReturnType = strictMock ? applyStrictMockReturnType(nonVoidMockReturnType, schemaTypeNames) : nonVoidMockReturnType;
|
|
1352
|
+
const simpleSchemaReturnType = strictMock ? getSimpleSchemaReturnType(nonVoidMockReturnType, schemaTypeNames) : void 0;
|
|
1353
|
+
let mockFactoryParam = "";
|
|
1354
|
+
let mockFactoryReturnType = nonVoidMockReturnType;
|
|
1355
|
+
let mockFactoryReturnCast = "";
|
|
1356
|
+
if (isResponseOverridable) if (strictMock && simpleSchemaReturnType) {
|
|
1357
|
+
const signature = getMockFactorySignatureParts(simpleSchemaReturnType, mockOptionsFromOverride, {
|
|
1358
|
+
isOverridable: true,
|
|
1359
|
+
overrideType: overrideResponseType
|
|
1360
|
+
});
|
|
1361
|
+
mockFactoryParam = signature.param;
|
|
1362
|
+
mockFactoryReturnType = signature.returnType;
|
|
1363
|
+
mockFactoryReturnCast = signature.returnCast;
|
|
1364
|
+
} else {
|
|
1365
|
+
mockFactoryParam = `overrideResponse: ${overrideResponseType} = {}`;
|
|
1366
|
+
mockFactoryReturnType = strictMock ? strictMockReturnType : nonVoidMockReturnType;
|
|
1367
|
+
}
|
|
1368
|
+
else if (strictMock) mockFactoryReturnType = strictMockReturnType;
|
|
1369
|
+
const mockImplementation = isReturnHttpResponse ? `${mockImplementations}${formatMockFactoryDeclaration(getResponseMockFunctionName, mockFactoryParam, mockFactoryReturnType, value, mockFactoryReturnCast, { omitReturnType: Boolean(mockData) })}\n\n` : mockImplementations;
|
|
1194
1370
|
const delay = getDelay(override, isFunction(mock) ? void 0 : mock);
|
|
1195
1371
|
const infoParam = "info";
|
|
1196
1372
|
const resolvedResponseExpr = `overrideResponse !== undefined
|
|
@@ -1260,35 +1436,40 @@ export const ${handlerName} = (overrideResponse?: ${mockReturnType} | ((${infoPa
|
|
|
1260
1436
|
handlerName,
|
|
1261
1437
|
handler: handlerImplementation
|
|
1262
1438
|
},
|
|
1263
|
-
imports: includeResponseImports
|
|
1439
|
+
imports: includeResponseImports,
|
|
1440
|
+
strictMockSchemaTypeNames: strictMock ? mergeStrictMockSchemaTypeNames(schemaTypeNames, collectStrictMockSchemaTypeNamesFromImplementation(mockImplementation)) : void 0
|
|
1264
1441
|
};
|
|
1265
1442
|
}
|
|
1266
1443
|
function generateMSW(generatorVerbOptions, generatorOptions) {
|
|
1267
1444
|
const { pathRoute, override, mock } = generatorOptions;
|
|
1268
|
-
const {
|
|
1445
|
+
const { operationName, response } = generatorVerbOptions;
|
|
1269
1446
|
const overrideBaseUrl = override.mock && "baseUrl" in override.mock ? override.mock.baseUrl : void 0;
|
|
1270
1447
|
const mockBaseUrl = mock && isMswMock(mock) ? mock.baseUrl : void 0;
|
|
1271
1448
|
const route = getRouteMSW(pathRoute, overrideBaseUrl ?? mockBaseUrl);
|
|
1272
|
-
const handlerName = `get${pascal(
|
|
1273
|
-
const getResponseMockFunctionName = `get${pascal(
|
|
1449
|
+
const handlerName = `get${pascal(operationName)}MockHandler`;
|
|
1450
|
+
const getResponseMockFunctionName = `get${pascal(operationName)}ResponseMock`;
|
|
1274
1451
|
const splitMockImplementations = [];
|
|
1275
1452
|
const baseDefinition = generateDefinition("", route, getResponseMockFunctionName, handlerName, generatorVerbOptions, generatorOptions, response.definition.success, response.types.success[0]?.key ?? "200", response.imports, response.types.success, response.contentTypes, splitMockImplementations);
|
|
1276
1453
|
const mockImplementations = [baseDefinition.implementation.function];
|
|
1277
1454
|
const handlerImplementations = [baseDefinition.implementation.handler];
|
|
1278
1455
|
const imports = [...baseDefinition.imports];
|
|
1456
|
+
const strictMockSchemaTypeNames = new Set(baseDefinition.strictMockSchemaTypeNames);
|
|
1279
1457
|
if (generatorOptions.mock && isObject(generatorOptions.mock) && generatorOptions.mock.generateEachHttpStatus) for (const statusResponse of [...response.types.success, ...response.types.errors]) {
|
|
1280
1458
|
const definition = generateDefinition(statusResponse.key, route, getResponseMockFunctionName, handlerName, generatorVerbOptions, generatorOptions, statusResponse.value, statusResponse.key, response.imports, [statusResponse], [statusResponse.contentType], splitMockImplementations);
|
|
1281
1459
|
mockImplementations.push(definition.implementation.function);
|
|
1282
1460
|
handlerImplementations.push(definition.implementation.handler);
|
|
1283
1461
|
imports.push(...definition.imports);
|
|
1462
|
+
for (const name of definition.strictMockSchemaTypeNames ?? []) strictMockSchemaTypeNames.add(name);
|
|
1284
1463
|
}
|
|
1464
|
+
const aggregatedStrictNames = [...strictMockSchemaTypeNames];
|
|
1285
1465
|
return {
|
|
1286
1466
|
implementation: {
|
|
1287
1467
|
function: mockImplementations.join("\n"),
|
|
1288
1468
|
handlerName,
|
|
1289
1469
|
handler: handlerImplementations.join("\n")
|
|
1290
1470
|
},
|
|
1291
|
-
imports
|
|
1471
|
+
imports,
|
|
1472
|
+
strictMockSchemaTypeNames: aggregatedStrictNames.length > 0 ? aggregatedStrictNames : void 0
|
|
1292
1473
|
};
|
|
1293
1474
|
}
|
|
1294
1475
|
//#endregion
|
|
@@ -1325,7 +1506,8 @@ function generateFaker(generatorVerbOptions, generatorOptions) {
|
|
|
1325
1506
|
handler: "",
|
|
1326
1507
|
handlerName: ""
|
|
1327
1508
|
},
|
|
1328
|
-
imports: result.imports
|
|
1509
|
+
imports: result.imports,
|
|
1510
|
+
strictMockSchemaTypeNames: result.strictMockSchemaTypeNames
|
|
1329
1511
|
};
|
|
1330
1512
|
}
|
|
1331
1513
|
/**
|
|
@@ -1339,10 +1521,11 @@ function generateFaker(generatorVerbOptions, generatorOptions) {
|
|
|
1339
1521
|
*/
|
|
1340
1522
|
function generateFakerForSchemas(schemas, context, options) {
|
|
1341
1523
|
const factories = [];
|
|
1524
|
+
const strictMockTypeNames = /* @__PURE__ */ new Set();
|
|
1342
1525
|
const allImports = [];
|
|
1343
1526
|
const splitMockImplementations = [];
|
|
1344
1527
|
const localFactoryNames = new Set(schemas.filter((s) => !!s.schema).map((s) => `get${pascal(s.name)}Mock`));
|
|
1345
|
-
const mockOptions = context.output.override
|
|
1528
|
+
const mockOptions = getMockWithoutFunc(context.spec, context.output.override);
|
|
1346
1529
|
for (const generatorSchema of schemas) {
|
|
1347
1530
|
const { name, schema } = generatorSchema;
|
|
1348
1531
|
if (!schema) continue;
|
|
@@ -1365,7 +1548,12 @@ function generateFakerForSchemas(schemas, context, options) {
|
|
|
1365
1548
|
});
|
|
1366
1549
|
allImports.push(...result.imports, ...factoryImports);
|
|
1367
1550
|
const typeName = pascal(name);
|
|
1368
|
-
const
|
|
1551
|
+
const { param, returnType, returnCast } = getMockFactorySignatureParts(typeName, mockOptions, {
|
|
1552
|
+
isOverridable: result.value.includes("overrideResponse"),
|
|
1553
|
+
overrideType: `Partial<${typeName}>`
|
|
1554
|
+
});
|
|
1555
|
+
const factory = formatMockFactoryDeclaration(factoryName, param, returnType, result.value, returnCast);
|
|
1556
|
+
if (isStrictMock(mockOptions)) strictMockTypeNames.add(typeName);
|
|
1369
1557
|
factories.push(factory);
|
|
1370
1558
|
allImports.push({
|
|
1371
1559
|
name: pascal(name),
|
|
@@ -1384,9 +1572,12 @@ function generateFakerForSchemas(schemas, context, options) {
|
|
|
1384
1572
|
if (!existing.values && imp.values) mergedImports.set(key, imp);
|
|
1385
1573
|
}
|
|
1386
1574
|
const uniqueImports = [...mergedImports.values()];
|
|
1575
|
+
const implementation = [...splitMockImplementations, ...factories].filter(Boolean).join("\n\n");
|
|
1576
|
+
const aggregatedStrictNames = [...strictMockTypeNames];
|
|
1387
1577
|
return {
|
|
1388
|
-
implementation
|
|
1389
|
-
imports: uniqueImports
|
|
1578
|
+
implementation,
|
|
1579
|
+
imports: uniqueImports,
|
|
1580
|
+
strictMockSchemaTypeNames: aggregatedStrictNames.length > 0 ? aggregatedStrictNames : void 0
|
|
1390
1581
|
};
|
|
1391
1582
|
}
|
|
1392
1583
|
//#endregion
|
|
@@ -1428,12 +1619,19 @@ const generateMockImports = (importOptions) => {
|
|
|
1428
1619
|
* `output.mock.generators` is dispatched here individually.
|
|
1429
1620
|
*/
|
|
1430
1621
|
function generateMock(generatorVerbOptions, generatorOptions) {
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1622
|
+
const { context } = generatorOptions;
|
|
1623
|
+
const previousActiveMockOutputType = context.activeMockOutputType;
|
|
1624
|
+
context.activeMockOutputType = generatorOptions.mock.type;
|
|
1625
|
+
try {
|
|
1626
|
+
switch (generatorOptions.mock.type) {
|
|
1627
|
+
case OutputMockType.FAKER: return generateFaker(generatorVerbOptions, generatorOptions);
|
|
1628
|
+
default: return generateMSW(generatorVerbOptions, generatorOptions);
|
|
1629
|
+
}
|
|
1630
|
+
} finally {
|
|
1631
|
+
context.activeMockOutputType = previousActiveMockOutputType;
|
|
1434
1632
|
}
|
|
1435
1633
|
}
|
|
1436
1634
|
//#endregion
|
|
1437
|
-
export { DEFAULT_FAKER_OPTIONS, DEFAULT_MSW_OPTIONS, generateFaker, generateFakerForSchemas, generateFakerImports, generateMSW, generateMSWImports, generateMock, generateMockImports, getDefaultMockOptionsForType };
|
|
1635
|
+
export { DEFAULT_FAKER_OPTIONS, DEFAULT_MSW_OPTIONS, buildStrictMockTypeFileHeader, dedupeStrictMockTypeDeclarations, generateFaker, generateFakerForSchemas, generateFakerImports, generateMSW, generateMSWImports, generateMock, generateMockImports, getDefaultMockOptionsForType };
|
|
1438
1636
|
|
|
1439
1637
|
//# sourceMappingURL=index.mjs.map
|