@orval/mock 8.36.0 → 8.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,9 @@
1
- import { EnumGeneration, OutputMockType, OutputMode, PropertySortOrder, camelPathParamName, compareNatural, compareVersions, escapeRegExp, generalJSTypesWithArray, generateDependencyImports, getKey, getOperationTagKey, getRefInfo, getRequiredKeys, getStringLiteralType, isBoolean, isFunction, isMswMock, isNumber, isObject, isReference, isSchemaNullable, isString, jsStringLiteralEscape, mergeDeep, pascal, resolveRef, safeNumericConstraint, stringify, toColonRoutePath } from "@orval/core";
2
- import { prop } from "remeda";
1
+ import { EnumGeneration, OutputMockType, OutputMode, PropertySortOrder, camelPathParamName, compareNatural, compareVersions, escapeRegExp, generalJSTypesWithArray, generateDependencyImports, getAtPath, getKey, getOperationTagKey, getRefInfo, getRequiredKeys, getStringLiteralType, isBoolean, isFunction, isInlineSchema, isMswMock, isNullOnlyEnum, isNumber, isObject, isSchemaNullable, isString, jsStringLiteralEscape, mergeDeep, pascal, resolveRef, safeNumericConstraint, stringify, toColonRoutePath, toJsLiteral, toObjectSchema } from "@orval/core";
3
2
  //#region src/mock-types.ts
3
+ function asObjectSchema(schema) {
4
+ if (!schema || typeof schema !== "object") return;
5
+ return schema;
6
+ }
4
7
  function isStrictMock(mockOptions) {
5
8
  return Boolean(mockOptions && mockOptions.required && mockOptions.nonNullable);
6
9
  }
@@ -21,23 +24,25 @@ export type MockWithNullableOverrides<
21
24
  };`;
22
25
  }
23
26
  function classifyStrictMockSchemaType(schema, context) {
24
- if (!schema) return "object";
25
- if (schema.format === "binary" || schema.contentMediaType === "application/octet-stream" && !schema.contentEncoding) return "binary";
26
- if (typeof schema.$ref === "string") {
27
+ const objectSchema = asObjectSchema(schema);
28
+ if (!objectSchema) return "object";
29
+ if (objectSchema.format === "binary" || objectSchema.contentMediaType === "application/octet-stream" && !objectSchema.contentEncoding) return "binary";
30
+ if (typeof objectSchema.$ref === "string") {
27
31
  if (context) {
28
- const { schema: resolved } = resolveRef(schema, context);
32
+ const { schema: resolved } = resolveRef(objectSchema, context);
29
33
  return classifyStrictMockSchemaType(resolved, context);
30
34
  }
31
35
  return "object";
32
36
  }
33
- if (schema.type === "object" || schema.properties || isComposedObjectSchema(schema)) return "object";
37
+ if (objectSchema.type === "object" || objectSchema.properties || isComposedObjectSchema(objectSchema)) return "object";
34
38
  return "alias";
35
39
  }
36
40
  function isComposedObjectSchema(schema) {
37
41
  const branches = schema.oneOf ?? schema.anyOf ?? schema.allOf;
38
42
  if (!branches?.length) return false;
39
43
  return branches.some((branch) => {
40
- const item = branch;
44
+ const item = asObjectSchema(branch);
45
+ if (!item) return false;
41
46
  if (typeof item.$ref === "string" || item.type === "object" || item.properties) return true;
42
47
  return isComposedObjectSchema(item);
43
48
  });
@@ -62,23 +67,24 @@ function strictMockResolvedImportMatches(typeName, resolvedImport, importBareNam
62
67
  return importBareName !== void 0 && importBareName === resolvedName;
63
68
  }
64
69
  function resolveStrictMockSchemaForTypeName(typeName, originalSchema, context, importBareName) {
65
- if (!originalSchema) return;
66
- if (!context) return originalSchema;
67
- const branches = originalSchema.oneOf ?? originalSchema.anyOf ?? originalSchema.allOf;
70
+ const objectSchema = asObjectSchema(originalSchema);
71
+ if (!objectSchema) return;
72
+ if (!context) return objectSchema;
73
+ const branches = objectSchema.oneOf ?? objectSchema.anyOf ?? objectSchema.allOf;
68
74
  if (branches?.length) {
69
75
  for (const branch of branches) {
70
- if (typeof branch.$ref !== "string") continue;
76
+ if (typeof branch !== "object" || branch === null || !("$ref" in branch) || typeof branch.$ref !== "string") continue;
71
77
  const resolved = resolveRef(branch, context);
72
78
  if (strictMockResolvedImportMatches(typeName, resolved.imports[0], importBareName)) return resolved.schema;
73
79
  }
74
80
  return;
75
81
  }
76
- if (typeof originalSchema.$ref === "string") {
77
- const resolved = resolveRef(originalSchema, context);
82
+ if (typeof objectSchema.$ref === "string") {
83
+ const resolved = resolveRef(objectSchema, context);
78
84
  if (strictMockResolvedImportMatches(typeName, resolved.imports[0], importBareName)) return resolved.schema;
79
85
  return;
80
86
  }
81
- return originalSchema;
87
+ return objectSchema;
82
88
  }
83
89
  function getMockFactoryReturnType(typeName, mockOptions) {
84
90
  return isStrictMock(mockOptions) ? getStrictMockTypeName(typeName) : typeName;
@@ -140,10 +146,9 @@ function getStrictMockSchemaKindsFromResponses(responses, context) {
140
146
  if (!value || !response.originalSchema) continue;
141
147
  const baseType = value.endsWith("[]") ? value.slice(0, -2) : value;
142
148
  if (!/^[A-Z]\w*$/.test(baseType)) continue;
143
- const schema = response.originalSchema;
144
- if (value.endsWith("[]") && schema.type === "array" && schema.items) {
145
- const items = schema.items;
146
- kinds[baseType] = classifyStrictMockSchemaType(items, context);
149
+ const schema = asObjectSchema(response.originalSchema);
150
+ if (value.endsWith("[]") && schema?.type === "array" && schema.items && typeof schema.items === "object") {
151
+ kinds[baseType] = classifyStrictMockSchemaType(schema.items, context);
147
152
  continue;
148
153
  }
149
154
  kinds[baseType] = classifyStrictMockSchemaType(resolveStrictMockSchemaForTypeName(baseType, response.originalSchema, context) ?? response.originalSchema, context);
@@ -214,46 +219,6 @@ function mergeStrictMockSchemaKinds(...groups) {
214
219
  return Object.keys(merged).length > 0 ? merged : void 0;
215
220
  }
216
221
  //#endregion
217
- //#region src/faker/imports.ts
218
- /**
219
- * Appends entries added to `source` since `sinceIndex`. Uses indexed push
220
- * instead of spread so large import batches (common with `schemas: true`
221
- * delegation on wide objects) do not overflow the call stack.
222
- */
223
- function appendImportsDelta(target, source, sinceIndex) {
224
- for (let i = sinceIndex; i < source.length; i++) target.push(source[i]);
225
- }
226
- /**
227
- * Merge imports returned from mock resolution when the shared imports array
228
- * was not mutated in place. Enum mocks and nested object factories return
229
- * their imports separately; schema-factory delegation mutates `sharedImports`
230
- * directly and must not be merged again from `resolvedImports`.
231
- */
232
- function mergeReturnedMockImports(sharedImports, sharedBefore, resolvedImports) {
233
- if (sharedImports.length === sharedBefore) appendImportsDelta(sharedImports, resolvedImports, 0);
234
- }
235
- /** Recover type imports referenced by nested oneOf split mock helpers. */
236
- function collectSplitMockTypeImports(implementations) {
237
- const seen = /* @__PURE__ */ new Set();
238
- const imports = [];
239
- const addType = (name) => {
240
- if (!name || seen.has(name)) return;
241
- seen.add(name);
242
- imports.push({
243
- name,
244
- values: false
245
- });
246
- };
247
- for (const impl of implementations) {
248
- for (const match of impl.matchAll(/export const get\w+Mock = \(\s*overrideResponse: Partial<(\w+)[^)]*\):\s*(\w+)\s*=>/g)) {
249
- addType(match[1]);
250
- addType(match[2]);
251
- }
252
- for (const match of impl.matchAll(/export const get\w+Mock[\s\S]*?MockWithNullableOverrides<(?:Extract<(\w+),[^>]+>|(\w+)),/g)) addType(match[1] ?? match[2]);
253
- }
254
- return imports;
255
- }
256
- //#endregion
257
222
  //#region src/delay.ts
258
223
  const getDelay = (override, options) => {
259
224
  const mswOptions = options && isMswMock(options) ? options : void 0;
@@ -268,12 +233,12 @@ const getDelay = (override, options) => {
268
233
  //#region src/faker/getters/all-of-required.ts
269
234
  function derefAllOfMember(member, context, seen) {
270
235
  let current = member;
271
- while (current && typeof current === "object" && isReference(current)) {
236
+ while (current && typeof current === "object" && "$ref" in current && typeof current.$ref === "string") {
272
237
  const ref = current.$ref;
273
- if (typeof ref !== "string" || seen.has(ref)) return;
238
+ if (seen.has(ref)) return;
274
239
  seen.add(ref);
275
240
  const { refPaths } = getRefInfo(ref, context);
276
- current = Array.isArray(refPaths) ? prop(context.spec, ...refPaths) : void 0;
241
+ current = Array.isArray(refPaths) ? getAtPath(context.spec, refPaths) : void 0;
277
242
  }
278
243
  return current && typeof current === "object" ? current : void 0;
279
244
  }
@@ -340,6 +305,161 @@ const DEFAULT_FORMAT_MOCK = {
340
305
  };
341
306
  const DEFAULT_OBJECT_KEY_MOCK = "faker.string.alphanumeric(5)";
342
307
  //#endregion
308
+ //#region src/faker/format-example-value.ts
309
+ const DATE_FORMATS = /* @__PURE__ */ new Set(["date", "date-time"]);
310
+ function isDateFormat(format) {
311
+ return format !== void 0 && DATE_FORMATS.has(format);
312
+ }
313
+ function isSchemaObject(schema) {
314
+ return typeof schema === "object" && schema !== null && !Array.isArray(schema);
315
+ }
316
+ function resolveSchema(schema, context) {
317
+ if (!schema || typeof schema !== "object") return;
318
+ if (typeof schema.$ref === "string") {
319
+ const resolved = resolveRef(schema, context).schema;
320
+ return resolved && typeof resolved === "object" ? resolved : void 0;
321
+ }
322
+ return schema;
323
+ }
324
+ function mergePropertySchemas(...schemas) {
325
+ const merged = {};
326
+ for (const schema of schemas) {
327
+ if (!schema?.properties) continue;
328
+ for (const [key, prop] of Object.entries(schema.properties)) if (isSchemaObject(prop)) merged[key] = prop;
329
+ }
330
+ return merged;
331
+ }
332
+ function getEffectiveScalarFormat(resolved, context) {
333
+ if (!resolved) return;
334
+ if (isDateFormat(resolved.format)) return resolved.format;
335
+ const oneOf = resolved.oneOf;
336
+ const anyOf = resolved.anyOf;
337
+ for (const variant of [...oneOf ?? [], ...anyOf ?? []]) {
338
+ const resolvedVariant = resolveSchema(isSchemaObject(variant) ? variant : void 0, context);
339
+ if (isDateFormat(resolvedVariant?.format)) return resolvedVariant.format;
340
+ }
341
+ }
342
+ /**
343
+ * Resolves compositional schemas (allOf / oneOf / anyOf) so example formatting
344
+ * can see property formats on nested and referenced types.
345
+ */
346
+ function resolveExampleSchema(schema, context, seenRefs = /* @__PURE__ */ new Set()) {
347
+ if (!schema || typeof schema !== "object") return;
348
+ if (typeof schema.$ref === "string") {
349
+ const ref = schema.$ref;
350
+ if (seenRefs.has(ref)) {
351
+ const resolved = resolveRef(schema, context).schema;
352
+ return resolved && typeof resolved === "object" ? resolved : void 0;
353
+ }
354
+ seenRefs = new Set(seenRefs).add(ref);
355
+ }
356
+ const resolved = resolveSchema(schema, context);
357
+ if (!resolved) return;
358
+ const allOf = resolved.allOf;
359
+ const oneOf = resolved.oneOf;
360
+ const anyOf = resolved.anyOf;
361
+ const compositors = [
362
+ ...allOf ?? [],
363
+ ...oneOf ?? [],
364
+ ...anyOf ?? []
365
+ ];
366
+ const properties = mergePropertySchemas(resolved, ...compositors.map((sub) => resolveExampleSchema(sub, context, seenRefs)));
367
+ const baseResolved = resolved;
368
+ if (resolved.type === "array" && isSchemaObject(resolved.items)) {
369
+ const items = resolveExampleSchema(resolved.items, context, seenRefs);
370
+ const itemProperties = items?.properties;
371
+ const normalizedItems = itemProperties && Object.keys(itemProperties).length > 0 ? {
372
+ type: "object",
373
+ properties: itemProperties
374
+ } : items;
375
+ return {
376
+ ...baseResolved,
377
+ ...Object.keys(properties).length > 0 ? { properties } : {},
378
+ items: normalizedItems ?? resolved.items
379
+ };
380
+ }
381
+ if (Object.keys(properties).length > 0) return {
382
+ ...baseResolved,
383
+ properties
384
+ };
385
+ if (compositors.length > 0 && (oneOf ?? anyOf)) {
386
+ const variantProperties = mergePropertySchemas(...compositors.map((sub) => resolveExampleSchema(sub, context, seenRefs)));
387
+ if (Object.keys(variantProperties).length > 0) return {
388
+ type: "object",
389
+ properties: variantProperties
390
+ };
391
+ }
392
+ const scalarFormat = getEffectiveScalarFormat(resolved, context);
393
+ if (scalarFormat) return {
394
+ ...baseResolved,
395
+ format: scalarFormat
396
+ };
397
+ return resolved;
398
+ }
399
+ function formatLiteralValue(example, schema, context) {
400
+ if (example === null) return "null";
401
+ if (example === void 0) return "undefined";
402
+ const resolved = resolveExampleSchema(schema, context);
403
+ if (Array.isArray(example)) {
404
+ const itemsSchema = resolved?.type === "array" && isSchemaObject(resolved.items) ? resolveExampleSchema(resolved.items, context) : resolved;
405
+ return `[${example.map((item) => formatLiteralValue(item, itemsSchema, context)).join(", ")}]`;
406
+ }
407
+ if (typeof example === "object") {
408
+ const properties = resolved?.properties ?? {};
409
+ return `{ ${Object.entries(example).map(([key, value]) => {
410
+ const propSchema = properties[key];
411
+ const resolvedProp = isSchemaObject(propSchema) ? resolveExampleSchema(propSchema, context) : void 0;
412
+ return `${/^[a-zA-Z_$][\w$]*$/.test(key) ? key : JSON.stringify(key)}: ${formatLiteralValue(value, resolvedProp, context)}`;
413
+ }).join(", ")} }`;
414
+ }
415
+ if (context.output.override.useDates && typeof example === "string" && isDateFormat(getEffectiveScalarFormat(resolved, context))) return `new Date(${JSON.stringify(example)})`;
416
+ return JSON.stringify(example);
417
+ }
418
+ function formatSchemaExampleValue(example, schema, context) {
419
+ if (!context.output.override.useDates || schema === void 0) return JSON.stringify(example);
420
+ return formatLiteralValue(example, schema, context);
421
+ }
422
+ //#endregion
423
+ //#region src/faker/imports.ts
424
+ /**
425
+ * Appends entries added to `source` since `sinceIndex`. Uses indexed push
426
+ * instead of spread so large import batches (common with `schemas: true`
427
+ * delegation on wide objects) do not overflow the call stack.
428
+ */
429
+ function appendImportsDelta(target, source, sinceIndex) {
430
+ for (let i = sinceIndex; i < source.length; i++) target.push(source[i]);
431
+ }
432
+ /**
433
+ * Merge imports returned from mock resolution when the shared imports array
434
+ * was not mutated in place. Enum mocks and nested object factories return
435
+ * their imports separately; schema-factory delegation mutates `sharedImports`
436
+ * directly and must not be merged again from `resolvedImports`.
437
+ */
438
+ function mergeReturnedMockImports(sharedImports, sharedBefore, resolvedImports) {
439
+ if (sharedImports.length === sharedBefore) appendImportsDelta(sharedImports, resolvedImports, 0);
440
+ }
441
+ /** Recover type imports referenced by nested oneOf split mock helpers. */
442
+ function collectSplitMockTypeImports(implementations) {
443
+ const seen = /* @__PURE__ */ new Set();
444
+ const imports = [];
445
+ const addType = (name) => {
446
+ if (!name || seen.has(name)) return;
447
+ seen.add(name);
448
+ imports.push({
449
+ name,
450
+ values: false
451
+ });
452
+ };
453
+ for (const impl of implementations) {
454
+ for (const match of impl.matchAll(/export const get\w+Mock = \(\s*overrideResponse: Partial<(\w+)[^)]*\):\s*(\w+)\s*=>/g)) {
455
+ addType(match[1]);
456
+ addType(match[2]);
457
+ }
458
+ for (const match of impl.matchAll(/export const get\w+Mock[\s\S]*?MockWithNullableOverrides<(?:Extract<(\w+),[^>]+>|(\w+)),/g)) addType(match[1] ?? match[2]);
459
+ }
460
+ return imports;
461
+ }
462
+ //#endregion
343
463
  //#region src/faker/getters/object.ts
344
464
  const overrideVarName = "overrideResponse";
345
465
  function wrapRootNullableObjectValue(value, schemaItem, mockOptions, combine) {
@@ -362,13 +482,13 @@ function reExpansionWouldCollapse(ref, context, existingReferencedProperties, no
362
482
  const targetRequired = target?.required;
363
483
  if (!targetProperties || !Array.isArray(targetRequired)) return false;
364
484
  return Object.entries(targetProperties).some(([key, property]) => {
365
- if (!targetRequired.includes(key) || !isReference(property)) return false;
485
+ if (!targetRequired.includes(key) || isInlineSchema(property)) return false;
366
486
  if (!existingReferencedProperties.includes(getReferenceName$1(property.$ref, context))) return false;
367
487
  return nonNullable || !isNullableRefTarget(property.$ref, context);
368
488
  });
369
489
  }
370
490
  function getMockObject({ item, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, existingReferencedAllOfRefs = [], splitMockImplementations, allowOverride = false }) {
371
- if (isReference(item)) return resolveMockValue({
491
+ if (typeof item.$ref === "string") return resolveMockValue({
372
492
  schema: {
373
493
  ...item,
374
494
  name: item.name,
@@ -476,14 +596,14 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
476
596
  const propertyScalars = entries.map(([key, prop]) => {
477
597
  if (combine?.includedProperties.includes(key)) return;
478
598
  const isRequired = mockOptions?.required ?? (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
479
- const hasNullable = !isReference(prop) && isSchemaNullable(prop);
480
- const refName = isReference(prop) ? getReferenceName$1(prop.$ref, context) : "";
599
+ const hasNullable = isInlineSchema(prop) && isSchemaNullable(prop);
600
+ const refName = !isInlineSchema(prop) ? getReferenceName$1(prop.$ref, context) : "";
481
601
  const isRecursiveRef = !!refName && existingReferencedProperties.includes(refName);
482
602
  if (isRecursiveRef) {
483
603
  if (!isRequired) return;
484
604
  const keyDefinition = getKey(key);
485
- if (!mockOptions?.nonNullable && (hasNullable || isReference(prop) && isNullableRefTarget(prop.$ref, context))) return `${keyDefinition}: null`;
486
- if (new Set(existingReferencedProperties).size !== existingReferencedProperties.length || isReference(prop) && reExpansionWouldCollapse(prop.$ref, context, existingReferencedProperties, mockOptions?.nonNullable)) {
605
+ if (!mockOptions?.nonNullable && (hasNullable || !isInlineSchema(prop) && isNullableRefTarget(prop.$ref, context))) return `${keyDefinition}: null`;
606
+ if (new Set(existingReferencedProperties).size !== existingReferencedProperties.length || !isInlineSchema(prop) && reExpansionWouldCollapse(prop.$ref, context, existingReferencedProperties, mockOptions?.nonNullable)) {
487
607
  imports.push({ name: refName });
488
608
  return `${keyDefinition}: {} as unknown as ${refName}`;
489
609
  }
@@ -516,13 +636,14 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
516
636
  imports.push({ name: refName });
517
637
  return `${keyDefinition}: {} as unknown as ${refName}`;
518
638
  }
519
- const hasDefault = "default" in prop && prop.default !== void 0;
639
+ const hasDefault = typeof prop === "object" && prop !== null && "default" in prop && prop.default !== void 0;
520
640
  if (!isRequired && !resolvedValue.overrided && !hasDefault) {
521
641
  if (resolvedValue.nullWrapped) return `${keyDefinition}: ${resolvedValue.value}`;
522
642
  const omitValue = mockOptions?.nonNullable || !hasNullable ? "undefined" : "null";
643
+ if (omitValue === "undefined" && mockOptions?.exactOptional) return `...(faker.datatype.boolean() ? {${keyDefinition}: ${resolvedValue.value}} : {})`;
523
644
  return `${keyDefinition}: faker.helpers.arrayElement([${resolvedValue.value}, ${omitValue}])`;
524
645
  }
525
- if (Array.isArray(prop.type) && prop.type.includes("null") && !resolvedValue.nullWrapped && !resolvedValue.overrided && !mockOptions?.nonNullable) return `${keyDefinition}: faker.helpers.arrayElement([${resolvedValue.value}, null])`;
646
+ if (typeof prop === "object" && prop !== null && "type" in prop && Array.isArray(prop.type) && prop.type.includes("null") && !resolvedValue.nullWrapped && !resolvedValue.overrided && !mockOptions?.nonNullable) return `${keyDefinition}: faker.helpers.arrayElement([${resolvedValue.value}, null])`;
526
647
  return `${keyDefinition}: ${resolvedValue.value}`;
527
648
  }).filter(Boolean);
528
649
  if (allowOverride) propertyScalars.push(`...${overrideVarName}`);
@@ -548,7 +669,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
548
669
  };
549
670
  }
550
671
  const additionalProperties = itemAdditionalProperties;
551
- if (isReference(additionalProperties) && existingReferencedProperties.includes(getReferenceName$1(additionalProperties.$ref, context))) {
672
+ if (!isInlineSchema(additionalProperties) && existingReferencedProperties.includes(getReferenceName$1(additionalProperties.$ref, context))) {
552
673
  const { value: finalValue, nullWrapped } = wrapRootNullableObjectValue(`{}`, schemaItem, mockOptions, combine);
553
674
  return {
554
675
  value: finalValue,
@@ -661,11 +782,12 @@ function shouldExtractArrayItem(items, context, operationId, parentName) {
661
782
  const itemsRef = extractItemsRef(items);
662
783
  if (itemsRef) try {
663
784
  const { schema } = resolveRef({ $ref: itemsRef }, context);
785
+ if (typeof schema !== "object" || schema === null) return false;
664
786
  return isResolvedSchemaObjectLike(schema);
665
787
  } catch {
666
788
  return false;
667
789
  }
668
- if (isReference(items)) return false;
790
+ if (!isInlineSchema(items)) return false;
669
791
  const schema = items;
670
792
  if (isNullableArrayItem(schema)) return false;
671
793
  if (schema.oneOf || schema.anyOf) return false;
@@ -746,115 +868,6 @@ function extractArrayItemMock({ items, propertyName, parentName, operationId, ta
746
868
  return `{...${factoryName}()${isStrictMock(mockOptions) ? ` as ${getStrictMockTypeName(typeName)}` : ""}}`;
747
869
  }
748
870
  //#endregion
749
- //#region src/faker/format-example-value.ts
750
- const DATE_FORMATS = /* @__PURE__ */ new Set(["date", "date-time"]);
751
- function isDateFormat(format) {
752
- return format !== void 0 && DATE_FORMATS.has(format);
753
- }
754
- function isSchemaObject(schema) {
755
- return typeof schema === "object" && schema !== null && !Array.isArray(schema);
756
- }
757
- function resolveSchema(schema, context) {
758
- if (!schema) return;
759
- if (isReference(schema)) return resolveRef(schema, context).schema;
760
- return schema;
761
- }
762
- function mergePropertySchemas(...schemas) {
763
- const merged = {};
764
- for (const schema of schemas) {
765
- if (!schema?.properties) continue;
766
- for (const [key, prop] of Object.entries(schema.properties)) if (isSchemaObject(prop)) merged[key] = prop;
767
- }
768
- return merged;
769
- }
770
- function getEffectiveScalarFormat(resolved, context) {
771
- if (!resolved) return;
772
- if (isDateFormat(resolved.format)) return resolved.format;
773
- const oneOf = resolved.oneOf;
774
- const anyOf = resolved.anyOf;
775
- for (const variant of [...oneOf ?? [], ...anyOf ?? []]) {
776
- const resolvedVariant = resolveSchema(isReference(variant) || isSchemaObject(variant) ? variant : void 0, context);
777
- if (isDateFormat(resolvedVariant?.format)) return resolvedVariant.format;
778
- }
779
- }
780
- /**
781
- * Resolves compositional schemas (allOf / oneOf / anyOf) so example formatting
782
- * can see property formats on nested and referenced types.
783
- */
784
- function resolveExampleSchema(schema, context, seenRefs = /* @__PURE__ */ new Set()) {
785
- if (!schema) return;
786
- if (isReference(schema)) {
787
- const ref = schema.$ref;
788
- if (ref && seenRefs.has(ref)) return resolveRef(schema, context).schema;
789
- if (ref) seenRefs = new Set(seenRefs).add(ref);
790
- }
791
- const resolved = resolveSchema(schema, context);
792
- if (!resolved) return;
793
- const allOf = resolved.allOf;
794
- const oneOf = resolved.oneOf;
795
- const anyOf = resolved.anyOf;
796
- const compositors = [
797
- ...allOf ?? [],
798
- ...oneOf ?? [],
799
- ...anyOf ?? []
800
- ];
801
- const properties = mergePropertySchemas(resolved, ...compositors.map((sub) => resolveExampleSchema(sub, context, seenRefs)));
802
- const baseResolved = resolved;
803
- if (resolved.type === "array" && isSchemaObject(resolved.items)) {
804
- const items = resolveExampleSchema(resolved.items, context, seenRefs);
805
- const itemProperties = items?.properties;
806
- const normalizedItems = itemProperties && Object.keys(itemProperties).length > 0 ? {
807
- type: "object",
808
- properties: itemProperties
809
- } : items;
810
- return {
811
- ...baseResolved,
812
- ...Object.keys(properties).length > 0 ? { properties } : {},
813
- items: normalizedItems ?? resolved.items
814
- };
815
- }
816
- if (Object.keys(properties).length > 0) return {
817
- ...baseResolved,
818
- properties
819
- };
820
- if (compositors.length > 0 && (oneOf ?? anyOf)) {
821
- const variantProperties = mergePropertySchemas(...compositors.map((sub) => resolveExampleSchema(sub, context, seenRefs)));
822
- if (Object.keys(variantProperties).length > 0) return {
823
- type: "object",
824
- properties: variantProperties
825
- };
826
- }
827
- const scalarFormat = getEffectiveScalarFormat(resolved, context);
828
- if (scalarFormat) return {
829
- ...baseResolved,
830
- format: scalarFormat
831
- };
832
- return resolved;
833
- }
834
- function formatLiteralValue(example, schema, context) {
835
- if (example === null) return "null";
836
- if (example === void 0) return "undefined";
837
- const resolved = resolveExampleSchema(schema, context);
838
- if (Array.isArray(example)) {
839
- const itemsSchema = resolved?.type === "array" && isSchemaObject(resolved.items) ? resolveExampleSchema(resolved.items, context) : resolved;
840
- return `[${example.map((item) => formatLiteralValue(item, itemsSchema, context)).join(", ")}]`;
841
- }
842
- if (typeof example === "object") {
843
- const properties = resolved?.properties ?? {};
844
- return `{ ${Object.entries(example).map(([key, value]) => {
845
- const propSchema = properties[key];
846
- const resolvedProp = isSchemaObject(propSchema) ? resolveExampleSchema(propSchema, context) : void 0;
847
- return `${/^[a-zA-Z_$][\w$]*$/.test(key) ? key : JSON.stringify(key)}: ${formatLiteralValue(value, resolvedProp, context)}`;
848
- }).join(", ")} }`;
849
- }
850
- if (context.output.override.useDates && typeof example === "string" && isDateFormat(getEffectiveScalarFormat(resolved, context))) return `new Date(${JSON.stringify(example)})`;
851
- return JSON.stringify(example);
852
- }
853
- function formatSchemaExampleValue(example, schema, context) {
854
- if (!context.output.override.useDates || schema === void 0) return JSON.stringify(example);
855
- return formatLiteralValue(example, schema, context);
856
- }
857
- //#endregion
858
871
  //#region src/faker/getters/scalar.ts
859
872
  function getMockScalar({ item, imports, mockOptions, operationId, tags, combine, context, existingReferencedProperties, existingReferencedAllOfRefs = [], splitMockImplementations, allowOverride = false }) {
860
873
  const safeMockOptions = mockOptions ?? {};
@@ -884,6 +897,18 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
884
897
  overrided: true
885
898
  };
886
899
  }
900
+ if (isNullOnlyEnum(item)) return {
901
+ value: "null",
902
+ imports: [],
903
+ name: item.name,
904
+ nullWrapped: true
905
+ };
906
+ if ("const" in item && item.type === void 0) return {
907
+ value: toJsLiteral(item.const),
908
+ imports: [],
909
+ name: item.name,
910
+ nullWrapped: item.const === null
911
+ };
887
912
  const formatOverrides = safeMockOptions.format ?? {};
888
913
  const ALL_FORMAT = {
889
914
  ...DEFAULT_FORMAT_MOCK,
@@ -934,7 +959,10 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
934
959
  value = getNullable(`faker.number.float(${floatParts.length > 0 ? `{${floatParts.join(", ")}}` : ""})`, isNullable, nonNullableOption);
935
960
  }
936
961
  const numberImports = [];
937
- if (item.enum) value = getEnum(item, numberImports, context, existingReferencedProperties, "number");
962
+ if (item.enum) value = getEnum(item, numberImports, context, existingReferencedProperties, {
963
+ type: "number",
964
+ exactOptional: safeMockOptions.exactOptional
965
+ });
938
966
  else if ("const" in item) value = JSON.stringify(item.const);
939
967
  return {
940
968
  value,
@@ -947,7 +975,10 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
947
975
  case "boolean": {
948
976
  let value = "faker.datatype.boolean()";
949
977
  const booleanImports = [];
950
- if (item.enum) value = getEnum(item, booleanImports, context, existingReferencedProperties, "boolean");
978
+ if (item.enum) value = getEnum(item, booleanImports, context, existingReferencedProperties, {
979
+ type: "boolean",
980
+ exactOptional: safeMockOptions.exactOptional
981
+ });
951
982
  else if ("const" in item) value = JSON.stringify(item.const);
952
983
  return {
953
984
  value,
@@ -986,18 +1017,19 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
986
1017
  name: item.name
987
1018
  };
988
1019
  }
989
- if (!item.items) return {
1020
+ if (!item.items || typeof item.items !== "object") return {
990
1021
  value: "[]",
991
1022
  imports: [],
992
1023
  name: item.name
993
1024
  };
994
- const itemsRef = extractItemsRef(item.items);
1025
+ const itemsSchema = item.items;
1026
+ const itemsRef = extractItemsRef(itemsSchema);
995
1027
  if (itemsRef && existingReferencedProperties.includes(getRefInfo(itemsRef, context).name)) return {
996
1028
  value: "[]",
997
1029
  imports: [],
998
1030
  name: item.name
999
1031
  };
1000
- const resolvedItems = itemsRef && !("$ref" in item.items) ? { $ref: itemsRef } : item.items;
1032
+ const resolvedItems = itemsRef && !("$ref" in itemsSchema) ? { $ref: itemsRef } : itemsSchema;
1001
1033
  const { value, enums, imports: resolvedImports } = resolveMockValue({
1002
1034
  schema: {
1003
1035
  ...resolvedItems,
@@ -1076,7 +1108,10 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
1076
1108
  if (strMin !== void 0 && strMax !== void 0) strLenParts.push(`min: ${strMin}`, `max: ${strMax}`);
1077
1109
  let value = `faker.string.alpha(${strLenParts.length > 0 ? `{length: {${strLenParts.join(", ")}}}` : ""})`;
1078
1110
  const stringImports = [];
1079
- if (item.enum) value = getEnum(item, stringImports, context, existingReferencedProperties, "string");
1111
+ if (item.enum) value = getEnum(item, stringImports, context, existingReferencedProperties, {
1112
+ type: "string",
1113
+ exactOptional: safeMockOptions.exactOptional
1114
+ });
1080
1115
  else if (item.pattern) value = `faker.helpers.fromRegExp(${JSON.stringify(item.pattern)})`;
1081
1116
  else if ("const" in item) value = JSON.stringify(item.const);
1082
1117
  return {
@@ -1097,7 +1132,7 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
1097
1132
  if (item.enum) {
1098
1133
  const enumImports = [];
1099
1134
  return {
1100
- value: getEnum(item, enumImports, context, existingReferencedProperties),
1135
+ value: getEnum(item, enumImports, context, existingReferencedProperties, { exactOptional: safeMockOptions.exactOptional }),
1101
1136
  enums: item.enum,
1102
1137
  imports: enumImports,
1103
1138
  name: item.name
@@ -1122,14 +1157,14 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
1122
1157
  }
1123
1158
  }
1124
1159
  function extractItemsRef(items) {
1125
- if (isReference(items)) return items.$ref;
1160
+ if (!isInlineSchema(items)) return items.$ref;
1126
1161
  for (const key of [
1127
1162
  "allOf",
1128
1163
  "oneOf",
1129
1164
  "anyOf"
1130
1165
  ]) {
1131
1166
  const composed = items[key];
1132
- if (Array.isArray(composed) && composed.length === 1 && isReference(composed[0])) return composed[0].$ref;
1167
+ if (Array.isArray(composed) && composed.length === 1 && !isInlineSchema(composed[0])) return composed[0].$ref;
1133
1168
  }
1134
1169
  }
1135
1170
  function getItemType(item) {
@@ -1180,7 +1215,7 @@ function safeTypeIdentifier(name) {
1180
1215
  const identifier = name.endsWith("[]") ? name.slice(0, -2) : name;
1181
1216
  return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(identifier) ? identifier : void 0;
1182
1217
  }
1183
- function getEnum(item, imports, context, existingReferencedProperties, type) {
1218
+ function getEnum(item, imports, context, existingReferencedProperties, { type, exactOptional } = {}) {
1184
1219
  if (!item.enum) return "";
1185
1220
  let enumValue = `[${item.enum.filter((e) => e !== null).map((e) => formatEnumMember(e)).join(",")}]`;
1186
1221
  if (context.output.override.enumGenerationType === EnumGeneration.ENUM) {
@@ -1196,7 +1231,8 @@ function getEnum(item, imports, context, existingReferencedProperties, type) {
1196
1231
  if (!parentReference) return "";
1197
1232
  const parentIdentifier = safeTypeIdentifier(parentReference);
1198
1233
  if (parentIdentifier) {
1199
- enumValue += ` as ${parentIdentifier}[${getStringLiteralType(item.name)}]`;
1234
+ const indexedType = `${parentIdentifier}[${getStringLiteralType(item.name)}]`;
1235
+ enumValue += exactOptional ? ` as Exclude<${indexedType}, undefined>` : ` as ${indexedType}`;
1200
1236
  if (!item.path?.endsWith("[]")) enumValue += "[]";
1201
1237
  imports.push({ name: parentIdentifier });
1202
1238
  } else enumValue += " as const";
@@ -1247,7 +1283,7 @@ function resolveRefTarget(ref, context) {
1247
1283
  if (!fragment) return void 0;
1248
1284
  const { refPaths } = getRefInfo(ref, context);
1249
1285
  if (!Array.isArray(refPaths)) return void 0;
1250
- return prop(context.spec, ...refPaths);
1286
+ return getAtPath(context.spec, refPaths);
1251
1287
  }
1252
1288
  /**
1253
1289
  * Whether a schema accepts `null`, in any of the spellings orval sees.
@@ -1323,7 +1359,7 @@ function hasOverrideTouchingSchema(schemaProperties, mockOptions, operationId, t
1323
1359
  });
1324
1360
  }
1325
1361
  function resolveMockValue({ schema, mockOptions, operationId, tags, combine, context, imports, existingReferencedProperties, existingReferencedAllOfRefs = [], splitMockImplementations, allowOverride }) {
1326
- if (isReference(schema)) {
1362
+ if (!isInlineSchema(schema)) {
1327
1363
  const schemaReference = schema;
1328
1364
  const schemaRefPath = typeof schema.$ref === "string" ? schema.$ref : "";
1329
1365
  const { name, refPaths } = getRefInfo(schemaRefPath, context);
@@ -1334,7 +1370,7 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
1334
1370
  path: schemaReference.path,
1335
1371
  isRef: true,
1336
1372
  required: [...schemaRef?.required ?? [], ...getRequiredKeys(schemaReference, name)],
1337
- ...Array.isArray(schemaReference.type) ? { type: schemaReference.type } : {}
1373
+ ..."type" in schemaReference && Array.isArray(schemaReference.type) ? { type: schemaReference.type } : {}
1338
1374
  };
1339
1375
  if (combine?.separator === "allOf" && newSchema.discriminator && newSchema.oneOf) {
1340
1376
  const parentDiscriminator = newSchema.discriminator;
@@ -1451,12 +1487,12 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
1451
1487
  };
1452
1488
  }
1453
1489
  function getType(schema) {
1454
- if (isReference(schema)) return;
1490
+ if (!isInlineSchema(schema)) return;
1455
1491
  return schema.type ?? (schema.properties ? "object" : schema.items ? "array" : void 0);
1456
1492
  }
1457
1493
  function resolvesToObjectLike(schema, context, seen = /* @__PURE__ */ new Set()) {
1458
1494
  let resolved;
1459
- if (isReference(schema)) {
1495
+ if (!isInlineSchema(schema)) {
1460
1496
  if (typeof schema.$ref !== "string" || seen.has(schema.$ref)) return false;
1461
1497
  seen = new Set(seen).add(schema.$ref);
1462
1498
  resolved = resolveRefTarget(schema.$ref, context);
@@ -1478,7 +1514,7 @@ function combineSchemasMock({ item, separator, mockOptions, operationId, tags, c
1478
1514
  const includedProperties = [...combine?.includedProperties ?? []];
1479
1515
  const separatorItems = item[separator] ?? [];
1480
1516
  const itemRequired = item.required;
1481
- const isRefAndNotExisting = isReference(item) && !existingReferencedProperties.includes(item.name);
1517
+ const isRefAndNotExisting = typeof item.$ref === "string" && !existingReferencedProperties.includes(item.name);
1482
1518
  const discriminator = item.discriminator;
1483
1519
  const itemProperties = item.properties;
1484
1520
  const discriminatorPropertyName = separator === "oneOf" && discriminator?.mapping && discriminator.propertyName && itemProperties && discriminator.propertyName in itemProperties ? discriminator.propertyName : void 0;
@@ -1526,9 +1562,10 @@ function combineSchemasMock({ item, separator, mockOptions, operationId, tags, c
1526
1562
  includedProperties.push(...itemResolvedValue?.includedProperties ?? []);
1527
1563
  combineImports.push(...itemResolvedValue?.imports ?? []);
1528
1564
  let containsOnlyPrimitiveValues = true;
1565
+ let hasNullMember = false;
1529
1566
  let value = separator === "allOf" ? "" : "faker.helpers.arrayElement([";
1530
1567
  for (const val of separatorItems) {
1531
- const refName = isReference(val) ? getReferenceName(val.$ref, context) : "";
1568
+ const refName = isInlineSchema(val) ? "" : getReferenceName(val.$ref, context);
1532
1569
  if (separator === "allOf" ? refName && (refName === item.name || existingReferencedProperties.includes(refName) && !item.isRef || existingReferencedAllOfRefs.includes(refName)) : refName && existingReferencedProperties.includes(refName)) {
1533
1570
  if (separatorItems.length === 1) value = "undefined";
1534
1571
  continue;
@@ -1580,6 +1617,10 @@ function combineSchemasMock({ item, separator, mockOptions, operationId, tags, c
1580
1617
  continue;
1581
1618
  }
1582
1619
  }
1620
+ if (separator !== "allOf" && resolvedValue.value === "null") {
1621
+ if (hasNullMember) continue;
1622
+ hasNullMember = true;
1623
+ }
1583
1624
  value += `${resolvedValue.value},`;
1584
1625
  }
1585
1626
  let finalValue = value === "undefined" || separator !== "allOf" && value === "faker.helpers.arrayElement([" ? "undefined" : `${separator === "allOf" && !containsOnlyPrimitiveValues ? "{" : ""}${value}${separator === "allOf" ? containsOnlyPrimitiveValues ? "" : "}" : "])"}`;
@@ -1638,6 +1679,7 @@ function getMockWithoutFunc(spec, override) {
1638
1679
  numberMax: override?.mock?.numberMax,
1639
1680
  required: override?.mock?.required,
1640
1681
  nonNullable: override?.mock?.nonNullable,
1682
+ exactOptional: override?.mock?.exactOptional,
1641
1683
  fractionDigits: override?.mock?.fractionDigits,
1642
1684
  ...override?.mock?.properties ? { properties: getMockPropertiesWithoutFunc(override.mock.properties, spec) } : {},
1643
1685
  ...override?.mock?.format ? { format: getMockPropertiesWithoutFunc(override.mock.format, spec) } : {},
@@ -1694,8 +1736,9 @@ function getResponsesMockDefinition({ operationId, tags, returnType, responses,
1694
1736
  for (const response of responses) {
1695
1737
  const { value: definition, example, examples, imports, isRef } = response;
1696
1738
  let { originalSchema } = response;
1739
+ const schemaObject = originalSchema && typeof originalSchema === "object" ? originalSchema : void 0;
1697
1740
  if (context.output.override.mock?.useExamples || mockOptions?.useExamples) {
1698
- const exampleValue = unwrapExampleValue(example ?? originalSchema?.example ?? getExampleEntries(examples)[0] ?? getExampleEntries(originalSchema?.examples)[0]);
1741
+ const exampleValue = unwrapExampleValue(example ?? schemaObject?.example ?? getExampleEntries(examples)[0] ?? getExampleEntries(schemaObject?.examples)[0]);
1699
1742
  if (exampleValue !== void 0) {
1700
1743
  const formatted = formatSchemaExampleValue(exampleValue, originalSchema, context);
1701
1744
  result.definitions.push(transformer ? transformer(formatted, returnType) : formatted);
@@ -1712,7 +1755,7 @@ function getResponsesMockDefinition({ operationId, tags, returnType, responses,
1712
1755
  format: "binary"
1713
1756
  };
1714
1757
  else if (!originalSchema) continue;
1715
- const resolvedSchema = resolveRef(originalSchema, context).schema;
1758
+ const resolvedSchema = toObjectSchema(resolveRef(originalSchema, context).schema);
1716
1759
  const responseImports = imports ? [...imports] : [];
1717
1760
  const importsBefore = responseImports.length;
1718
1761
  const scalar = getMockScalar({
@@ -1845,7 +1888,11 @@ function generateDefinition(name, route, getResponseMockFunctionNameBase, handle
1845
1888
  const hasTextLikeContentType = contentTypes.some((ct) => isTextLikeContentType(ct));
1846
1889
  const isExactlyStringReturnType = isTypeExactlyString(returnType);
1847
1890
  const isTextResponse = isExactlyStringReturnType && hasTextLikeContentType || contentTypesByPreference.some((ct) => isTextLikeContentType(ct));
1848
- const isSchemaBinary = (r) => r.originalSchema?.format === "binary" || r.originalSchema?.contentMediaType === "application/octet-stream" && !r.originalSchema.contentEncoding;
1891
+ const isSchemaBinary = (r) => {
1892
+ const schema = r.originalSchema;
1893
+ if (!schema || typeof schema !== "object") return false;
1894
+ return schema.format === "binary" || schema.contentMediaType === "application/octet-stream" && !schema.contentEncoding;
1895
+ };
1849
1896
  const isBinaryResponse = preferredContentTypeMatch ? responsesByPreference.some((r) => isSchemaBinary(r)) : contentTypesByPreference.some((ct) => isBinaryLikeContentType(ct)) || responsesByPreference.some((r) => isSchemaBinary(r));
1850
1897
  const isReturnHttpResponse = value && value !== "undefined";
1851
1898
  const getResponseMockFunctionName = `${getResponseMockFunctionNameBase}${pascal(name)}`;