@orval/mock 8.34.0 → 8.35.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,4 +1,4 @@
1
- import { EnumGeneration, OutputMockType, OutputMode, PropertySortOrder, camelPathParamName, compareNatural, compareVersions, escapeRegExp, generalJSTypesWithArray, generateDependencyImports, getKey, getOperationTagKey, getRefInfo, getRequiredKeys, getStringLiteralType, isBoolean, isFunction, isMswMock, isNumber, isObject, isReference, isString, jsStringLiteralEscape, mergeDeep, pascal, resolveRef, safeNumericConstraint, stringify, toColonRoutePath } from "@orval/core";
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
2
  import { prop } from "remeda";
3
3
  //#region src/mock-types.ts
4
4
  function isStrictMock(mockOptions) {
@@ -436,11 +436,12 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
436
436
  return {
437
437
  value: "faker.helpers.arrayElement([{}, null])",
438
438
  imports: [],
439
- name: schemaItem.name
439
+ name: schemaItem.name,
440
+ nullWrapped: true
440
441
  };
441
442
  }
442
443
  const baseItem = schemaItem;
443
- return combineSchemasMock({
444
+ const combined = combineSchemasMock({
444
445
  item: {
445
446
  anyOf: nonNullTypes.map((type) => ({
446
447
  ...baseItem,
@@ -459,6 +460,10 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
459
460
  existingReferencedAllOfRefs,
460
461
  splitMockImplementations
461
462
  });
463
+ return nonNullTypes.includes("null") ? {
464
+ ...combined,
465
+ nullWrapped: true
466
+ } : combined;
462
467
  }
463
468
  if (itemProperties) {
464
469
  let value = !combine || combine.separator === "oneOf" || combine.separator === "anyOf" ? "{" : "";
@@ -471,7 +476,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
471
476
  const propertyScalars = entries.map(([key, prop]) => {
472
477
  if (combine?.includedProperties.includes(key)) return;
473
478
  const isRequired = mockOptions?.required ?? (Array.isArray(itemRequired) ? itemRequired : []).includes(key);
474
- const hasNullable = "nullable" in prop && prop.nullable === true;
479
+ const hasNullable = !isReference(prop) && isSchemaNullable(prop);
475
480
  const refName = isReference(prop) ? getReferenceName$1(prop.$ref, context) : "";
476
481
  const isRecursiveRef = !!refName && existingReferencedProperties.includes(refName);
477
482
  if (isRecursiveRef) {
@@ -513,6 +518,7 @@ function getMockObject({ item, mockOptions, operationId, tags, combine, context,
513
518
  }
514
519
  const hasDefault = "default" in prop && prop.default !== void 0;
515
520
  if (!isRequired && !resolvedValue.overrided && !hasDefault) {
521
+ if (resolvedValue.nullWrapped) return `${keyDefinition}: ${resolvedValue.value}`;
516
522
  const omitValue = mockOptions?.nonNullable || !hasNullable ? "undefined" : "null";
517
523
  return `${keyDefinition}: faker.helpers.arrayElement([${resolvedValue.value}, ${omitValue}])`;
518
524
  }
@@ -639,7 +645,6 @@ function isAmbiguousInlineItemContext(operationId, parentName) {
639
645
  return !parentName.toLowerCase().includes(operationId.toLowerCase());
640
646
  }
641
647
  function isNullableArrayItem(schema) {
642
- if (schema.nullable === true) return true;
643
648
  return Array.isArray(schema.type) && schema.type.includes("null");
644
649
  }
645
650
  function isResolvedSchemaObjectLike(schema) {
@@ -1085,7 +1090,8 @@ function getMockScalar({ item, imports, mockOptions, operationId, tags, combine,
1085
1090
  case "null": return {
1086
1091
  value: "null",
1087
1092
  imports: [],
1088
- name: item.name
1093
+ name: item.name,
1094
+ nullWrapped: true
1089
1095
  };
1090
1096
  default:
1091
1097
  if (item.enum) {
@@ -1243,11 +1249,21 @@ function resolveRefTarget(ref, context) {
1243
1249
  if (!Array.isArray(refPaths)) return void 0;
1244
1250
  return prop(context.spec, ...refPaths);
1245
1251
  }
1246
- /** OpenAPI 3.0 `nullable: true` or 3.1 `type` unions that include `null`. */
1252
+ /**
1253
+ * Whether a schema accepts `null`, in any of the spellings orval sees.
1254
+ *
1255
+ * Delegates to core's {@link isSchemaNullable} rather than keeping a second,
1256
+ * narrower copy: this one knew only the 3.0 `nullable` keyword and a 3.1 `type`
1257
+ * union, so a schema nullable through a bare `type: 'null'`, a `null` member of
1258
+ * an `enum`, or a `{ type: 'null' }` branch of a `oneOf`/`anyOf` read as
1259
+ * non-nullable here while the type generator emitted `| null` (#4141).
1260
+ *
1261
+ * Kept as a thin wrapper because callers pass `unknown` — resolved `$ref`
1262
+ * targets and mock schemas that are not typed as Schema Objects.
1263
+ */
1247
1264
  function isNullableSchema(schema) {
1248
1265
  if (!schema || typeof schema !== "object") return false;
1249
- const { type, nullable } = schema;
1250
- return nullable === true || Array.isArray(type) && type.includes("null");
1266
+ return isSchemaNullable(schema);
1251
1267
  }
1252
1268
  /** When `nonNullableOption` is true (`override.mock.nonNullable`), omit the null branch. */
1253
1269
  function getNullable(value, nullable, nonNullableOption) {
@@ -1318,7 +1334,7 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
1318
1334
  path: schemaReference.path,
1319
1335
  isRef: true,
1320
1336
  required: [...schemaRef?.required ?? [], ...getRequiredKeys(schemaReference, name)],
1321
- ...schemaReference.nullable === void 0 ? {} : { nullable: schemaReference.nullable }
1337
+ ...Array.isArray(schemaReference.type) ? { type: schemaReference.type } : {}
1322
1338
  };
1323
1339
  if (combine?.separator === "allOf" && newSchema.discriminator && newSchema.oneOf) {
1324
1340
  const parentDiscriminator = newSchema.discriminator;
@@ -1350,7 +1366,9 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
1350
1366
  values: true,
1351
1367
  schemaFactory: true
1352
1368
  };
1353
- const isObjectLike = newSchema.type === "object" || !!newSchema.allOf || resolvesToObjectLike(newSchema, context);
1369
+ const targetNullable = !!schemaRef && isNullableSchema(schemaRef);
1370
+ const siteNullable = isNullableSchema(schemaReference);
1371
+ const isObjectLike = !targetNullable && (newSchema.type === "object" || !!newSchema.allOf || resolvesToObjectLike(newSchema, context));
1354
1372
  const mockTypeName = getStrictMockTypeName(pascal(name));
1355
1373
  const strictMockTypeImport = isStrictMock(mockOptions) && isObjectLike ? {
1356
1374
  name: mockTypeName,
@@ -1358,12 +1376,14 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
1358
1376
  schemaFactory: true
1359
1377
  } : void 0;
1360
1378
  const strictObjectCast = isStrictMock(mockOptions) && isObjectLike ? ` as ${mockTypeName}` : "";
1379
+ const callValue = isObjectLike ? `{ ...${factoryName}()${strictObjectCast} }` : `${factoryName}()`;
1380
+ const delegatesNullable = targetNullable || siteNullable;
1361
1381
  return {
1362
- value: getNullable(isObjectLike ? `{ ...${factoryName}()${strictObjectCast} }` : `${factoryName}()`, Boolean(newSchema.nullable), mockOptions?.nonNullable),
1382
+ value: getNullable(callValue, siteNullable && !targetNullable, mockOptions?.nonNullable),
1363
1383
  imports: strictMockTypeImport ? [factoryImport, strictMockTypeImport] : [factoryImport],
1364
1384
  name: newSchema.name,
1365
1385
  type: getType(newSchema),
1366
- nullWrapped: Boolean(newSchema.nullable) && !mockOptions?.nonNullable
1386
+ nullWrapped: delegatesNullable && !mockOptions?.nonNullable
1367
1387
  };
1368
1388
  }
1369
1389
  const importsBefore = imports.length;
@@ -1396,7 +1416,7 @@ function resolveMockValue({ schema, mockOptions, operationId, tags, combine, con
1396
1416
  const func = formatMockFactoryDeclaration(funcName, param, returnType, `{${scalar.value.startsWith("...") ? "" : "..."}${scalar.value}, ...${overrideVarName}}`, returnCast, { terminateStatement: true });
1397
1417
  splitMockImplementations.push(func);
1398
1418
  }
1399
- scalar.value = newSchema.nullable ? `${funcName}()` : `{...${funcName}()}`;
1419
+ scalar.value = isNullableSchema(newSchema) ? `${funcName}()` : `{...${funcName}()}`;
1400
1420
  const typeImport = {
1401
1421
  name: newSchema.name,
1402
1422
  values: false
@@ -1569,7 +1589,8 @@ function combineSchemasMock({ item, separator, mockOptions, operationId, tags, c
1569
1589
  value: finalValue,
1570
1590
  imports: combineImports,
1571
1591
  name: item.name,
1572
- includedProperties
1592
+ includedProperties,
1593
+ nullWrapped: isSchemaNullable(item) && !mockOptions?.nonNullable
1573
1594
  };
1574
1595
  }
1575
1596
  //#endregion