@kubb/plugin-faker 5.1.6 → 5.1.9

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.cjs CHANGED
@@ -5,9 +5,9 @@ Object.defineProperties(exports, {
5
5
  //#endregion
6
6
  let node_path = require("node:path");
7
7
  let kubb_kit = require("kubb/kit");
8
- let _kubb_plugin_ts = require("@kubb/plugin-ts");
9
8
  let kubb_jsx = require("kubb/jsx");
10
9
  let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
10
+ let _kubb_plugin_ts = require("@kubb/plugin-ts");
11
11
  //#region ../../internals/utils/src/casing.ts
12
12
  /**
13
13
  * Shared implementation for camelCase and PascalCase conversion.
@@ -309,6 +309,24 @@ function buildObject(entries) {
309
309
  }
310
310
  //#endregion
311
311
  //#region ../../internals/utils/src/fs.ts
312
+ function toSlash(p) {
313
+ if (p.startsWith("\\\\?\\")) return p;
314
+ return p.replaceAll("\\", "/");
315
+ }
316
+ /**
317
+ * Returns the relative path from `rootDir` to `filePath`, always using forward slashes
318
+ * and prefixed with `./` when not already traversing upward.
319
+ *
320
+ * @example
321
+ * ```ts
322
+ * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'
323
+ * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'
324
+ * ```
325
+ */
326
+ function getRelativePath(rootDir, filePath) {
327
+ const relativePath = node_path.posix.relative(toSlash(rootDir), toSlash(filePath));
328
+ return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
329
+ }
312
330
  /**
313
331
  * Builds a nested file path from a dotted name. Splits on dots that precede a letter
314
332
  * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
@@ -333,51 +351,6 @@ function toFilePath(name, caseLast = camelCase) {
333
351
  return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
334
352
  }
335
353
  //#endregion
336
- //#region ../../internals/utils/src/imports.ts
337
- function escapeRegExp(value) {
338
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
339
- }
340
- function getImportNames(entry) {
341
- return (Array.isArray(entry.name) ? entry.name : [entry.name]).map((name) => {
342
- if (typeof name === "string") return name;
343
- return name.name ?? name.propertyName;
344
- }).filter((name) => Boolean(name));
345
- }
346
- function filterUsedImports(imports, text, skipImportNames = []) {
347
- const skip = new Set(skipImportNames);
348
- return imports.filter((entry) => {
349
- return getImportNames(entry).some((name) => {
350
- if (skip.has(name)) return false;
351
- return new RegExp(`\\b${escapeRegExp(name)}\\b(?=\\s*[<(])`).test(text);
352
- });
353
- });
354
- }
355
- function aliasConflictingImports(imports, reservedNames) {
356
- const reservedNameSet = new Set(reservedNames);
357
- const aliases = /* @__PURE__ */ new Map();
358
- return {
359
- imports: imports.map((entry) => {
360
- const aliasedNames = (Array.isArray(entry.name) ? entry.name : [entry.name]).map((item) => {
361
- if (typeof item !== "string" || !reservedNameSet.has(item)) return item;
362
- const alias = `${item}Schema`;
363
- aliases.set(item, alias);
364
- return {
365
- propertyName: item,
366
- name: alias
367
- };
368
- });
369
- return aliasedNames.some((item) => typeof item === "object" && item.name) ? {
370
- ...entry,
371
- name: aliasedNames
372
- } : entry;
373
- }),
374
- aliases
375
- };
376
- }
377
- function rewriteAliasedImports(text, aliases) {
378
- return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
379
- }
380
- //#endregion
381
354
  //#region src/utils.ts
382
355
  /**
383
356
  * Returns the `@faker-js/faker` named export for a locale code.
@@ -401,54 +374,36 @@ function localeToFakerImport(locale) {
401
374
  return `faker${parts.join("_")}`;
402
375
  }
403
376
  /**
377
+ * Schema types a factory cannot override with `data`: they print a constant or have no faker value.
378
+ */
379
+ const NON_OVERRIDABLE_TYPES = /* @__PURE__ */ new Set([
380
+ "any",
381
+ "unknown",
382
+ "void",
383
+ "null",
384
+ "never",
385
+ "ipv4",
386
+ "ipv6"
387
+ ]);
388
+ /**
389
+ * Schema types a single response cannot inline: they reference or compose other schemas.
390
+ */
391
+ const NON_INLINABLE_RESPONSE_TYPES = /* @__PURE__ */ new Set([
392
+ "object",
393
+ "intersection",
394
+ "ref",
395
+ "never",
396
+ "ipv4",
397
+ "ipv6"
398
+ ]);
399
+ /**
404
400
  * Determines if a schema node can be overridden during faker generation.
405
401
  */
406
402
  function canOverrideSchema(node) {
407
- return (/* @__PURE__ */ new Set([
408
- "array",
409
- "tuple",
410
- "object",
411
- "intersection",
412
- "union",
413
- "enum",
414
- "ref",
415
- "string",
416
- "email",
417
- "url",
418
- "uuid",
419
- "number",
420
- "integer",
421
- "bigint",
422
- "boolean",
423
- "date",
424
- "time",
425
- "datetime",
426
- "blob"
427
- ])).has(node.type);
403
+ return !NON_OVERRIDABLE_TYPES.has(node.type);
428
404
  }
429
405
  function shouldInlineSingleResponseSchema(schema) {
430
- return (/* @__PURE__ */ new Set([
431
- "any",
432
- "unknown",
433
- "void",
434
- "null",
435
- "array",
436
- "tuple",
437
- "string",
438
- "email",
439
- "url",
440
- "uuid",
441
- "number",
442
- "integer",
443
- "bigint",
444
- "boolean",
445
- "date",
446
- "time",
447
- "datetime",
448
- "blob",
449
- "enum",
450
- "union"
451
- ])).has(schema.type);
406
+ return !NON_INLINABLE_RESPONSE_TYPES.has(schema.type);
452
407
  }
453
408
  /**
454
409
  * Builds a response schema as a union of all response statuses.
@@ -477,7 +432,7 @@ function buildResponseUnionSchema(node, resolver) {
477
432
  })
478
433
  });
479
434
  }
480
- const SCALAR_TYPES$1 = /* @__PURE__ */ new Set([
435
+ const SCALAR_TYPES = /* @__PURE__ */ new Set([
481
436
  "string",
482
437
  "email",
483
438
  "url",
@@ -492,10 +447,6 @@ const SCALAR_TYPES$1 = /* @__PURE__ */ new Set([
492
447
  "blob",
493
448
  "enum"
494
449
  ]);
495
- function toRelativeImportPath(from, to) {
496
- const relativePath = node_path.posix.relative(node_path.posix.dirname(from), to);
497
- return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
498
- }
499
450
  /**
500
451
  * Resolves a type reference, determining if it needs an import statement or inline type reference.
501
452
  * Takes into account whether the type can be overridden and the file paths.
@@ -503,7 +454,7 @@ function toRelativeImportPath(from, to) {
503
454
  function resolveTypeReference({ node, canOverride, name, typeName, filePath, typeFilePath }) {
504
455
  const { usesTypeName } = resolveFakerTypeUsage(node, typeName, canOverride);
505
456
  if (!usesTypeName) return { typeName };
506
- if (name === typeName) return { typeName: `import('${toRelativeImportPath(filePath, typeFilePath)}').${typeName}` };
457
+ if (name === typeName) return { typeName: `import('${getRelativePath(node_path.posix.dirname(filePath), typeFilePath)}').${typeName}` };
507
458
  return {
508
459
  importPath: typeFilePath,
509
460
  typeName
@@ -527,28 +478,17 @@ function getScalarType(node, typeName) {
527
478
  case "time": return node.representation === "date" ? "Date" : "string";
528
479
  case "datetime": return "string";
529
480
  case "blob": return "Blob";
530
- case "enum": return typeName;
531
481
  default: return typeName;
532
482
  }
533
483
  }
534
484
  /**
535
- * A nullable scalar inlines its primitive instead of naming the generated type, so the
536
- * nullability the type plugin emitted has to be reapplied here. Non-scalars keep `typeName`,
537
- * which already carries it.
538
- */
539
- function withNullability(type, node) {
540
- return node.nullable ? `${type} | null` : type;
541
- }
542
- /**
543
485
  * Resolves faker type usage information for a schema.
544
486
  * Determines the data type, return type, and whether it uses the type name.
545
487
  */
546
488
  function resolveFakerTypeUsage(node, typeName, canOverride) {
547
- const isScalar = SCALAR_TYPES$1.has(node.type);
548
- let dataType = `Partial<${typeName}>`;
549
- if (isScalar) dataType = withNullability(getScalarType(node, typeName), node);
550
- let returnType = canOverride ? typeName : null;
551
- if (isScalar) returnType = withNullability(getScalarType(node, typeName), node);
489
+ const scalarType = SCALAR_TYPES.has(node.type) ? `${getScalarType(node, typeName)}${node.nullable ? " | null" : ""}` : void 0;
490
+ const dataType = scalarType ?? `Partial<${typeName}>`;
491
+ const returnType = scalarType ?? (canOverride ? typeName : null);
552
492
  return {
553
493
  dataType,
554
494
  returnType,
@@ -558,22 +498,6 @@ function resolveFakerTypeUsage(node, typeName, canOverride) {
558
498
  //#endregion
559
499
  //#region src/components/Faker.tsx
560
500
  const OBJECT_TYPES = /* @__PURE__ */ new Set(["object", "intersection"]);
561
- const SCALAR_TYPES = /* @__PURE__ */ new Set([
562
- "string",
563
- "email",
564
- "url",
565
- "uuid",
566
- "number",
567
- "integer",
568
- "bigint",
569
- "boolean",
570
- "date",
571
- "time",
572
- "datetime",
573
- "blob",
574
- "enum"
575
- ]);
576
- const declarationPrinter = (0, _kubb_plugin_ts.functionPrinter)({ mode: "declaration" });
577
501
  function Faker({ node, description, name, typeName, printer, canOverride, typeMode = "inferred" }) {
578
502
  const fakerText = printer.print(node) ?? "undefined";
579
503
  const isArray = node.type === "array";
@@ -590,13 +514,7 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
590
514
  })();
591
515
  const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
592
516
  if (!useObjectOverride) {
593
- const dataParamName = /\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data";
594
- const params = (0, _kubb_plugin_ts.createFunctionParameters)({ params: [(0, _kubb_plugin_ts.createFunctionParameter)({
595
- name: dataParamName,
596
- type: dataType,
597
- optional: true
598
- })] });
599
- const paramsSignature = declarationPrinter.print(params) ?? "";
517
+ const paramsSignature = `${/\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data"}?: ${dataType}`;
600
518
  const returnType = resolvedReturnType;
601
519
  const returnExpression = canOverride && !!returnType && (node.type === "ref" || isArray || isTuple || isUnion) ? `${isTuple || isUnion ? `(${fakerTextWithOverride})` : fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride;
602
520
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
@@ -645,24 +563,6 @@ return {
645
563
  });
646
564
  }
647
565
  //#endregion
648
- //#region ../../internals/shared/src/params.ts
649
- /**
650
- * Drops parameters that share the same name, keeping the first.
651
- *
652
- * A malformed spec can declare the same parameter name twice within one `in` location. Both would
653
- * resolve to the same output property, so emitting both would yield an object type with a duplicate
654
- * member, which TypeScript rejects. This is a defensive guard against that case, not a casing guard:
655
- * parameter names flow through unchanged, so no two distinct names ever collide here anymore.
656
- */
657
- function dedupeParams(params) {
658
- const seen = /* @__PURE__ */ new Set();
659
- return params.filter((param) => {
660
- if (seen.has(param.name)) return false;
661
- seen.add(param.name);
662
- return true;
663
- });
664
- }
665
- //#endregion
666
566
  //#region ../../internals/shared/src/operation.ts
667
567
  /**
668
568
  * Builds the `ResolverFileParams` every operation generator passes to
@@ -761,11 +661,19 @@ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
761
661
  function getOperationParameters(node) {
762
662
  const cached = operationParameterGroupsByNode.get(node);
763
663
  if (cached) return cached;
664
+ const group = (location) => {
665
+ const seen = /* @__PURE__ */ new Set();
666
+ return node.parameters.filter((param) => {
667
+ if (param.in !== location || seen.has(param.name)) return false;
668
+ seen.add(param.name);
669
+ return true;
670
+ });
671
+ };
764
672
  const groups = {
765
- path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
766
- query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
767
- header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
768
- cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
673
+ path: group("path"),
674
+ query: group("query"),
675
+ header: group("header"),
676
+ cookie: group("cookie")
769
677
  };
770
678
  operationParameterGroupsByNode.set(node, groups);
771
679
  return groups;
@@ -846,20 +754,6 @@ function createCasedFile(caseLast) {
846
754
  } };
847
755
  }
848
756
  //#endregion
849
- //#region ../../internals/shared/src/refs.ts
850
- /**
851
- * Collects the resolved target name of every pointer-carrying ref in a schema tree, in
852
- * first-occurrence order. Use this for name-only checks (e.g. redeclaration detection) where
853
- * `resolver.imports` would resolve file paths that are then discarded.
854
- */
855
- function collectRefNames(schema) {
856
- return kubb_kit.ast.collectSync(schema, { schema: (node) => {
857
- const refNode = kubb_kit.ast.narrowSchema(node, "ref");
858
- if (!refNode?.ref) return null;
859
- return kubb_kit.ast.resolveRefName(refNode);
860
- } });
861
- }
862
- //#endregion
863
757
  //#region ../../internals/shared/src/group.ts
864
758
  /**
865
759
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
@@ -913,6 +807,51 @@ function mapSchemaItems(node, transform) {
913
807
  }));
914
808
  }
915
809
  //#endregion
810
+ //#region src/utils/imports.ts
811
+ function escapeRegExp(value) {
812
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
813
+ }
814
+ function getImportNames(entry) {
815
+ return (Array.isArray(entry.name) ? entry.name : [entry.name]).map((name) => {
816
+ if (typeof name === "string") return name;
817
+ return name.name ?? name.propertyName;
818
+ }).filter((name) => Boolean(name));
819
+ }
820
+ function filterUsedImports(imports, text, skipImportNames = []) {
821
+ const skip = new Set(skipImportNames);
822
+ return imports.filter((entry) => {
823
+ return getImportNames(entry).some((name) => {
824
+ if (skip.has(name)) return false;
825
+ return new RegExp(`\\b${escapeRegExp(name)}\\b(?=\\s*[<(])`).test(text);
826
+ });
827
+ });
828
+ }
829
+ function aliasConflictingImports(imports, reservedNames) {
830
+ const reservedNameSet = new Set(reservedNames);
831
+ const aliases = /* @__PURE__ */ new Map();
832
+ return {
833
+ imports: imports.map((entry) => {
834
+ const aliasedNames = (Array.isArray(entry.name) ? entry.name : [entry.name]).map((item) => {
835
+ if (typeof item !== "string" || !reservedNameSet.has(item)) return item;
836
+ const alias = `${item}Schema`;
837
+ aliases.set(item, alias);
838
+ return {
839
+ propertyName: item,
840
+ name: alias
841
+ };
842
+ });
843
+ return aliasedNames.some((item) => typeof item === "object" && item.name) ? {
844
+ ...entry,
845
+ name: aliasedNames
846
+ } : entry;
847
+ }),
848
+ aliases
849
+ };
850
+ }
851
+ function rewriteAliasedImports(text, aliases) {
852
+ return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
853
+ }
854
+ //#endregion
916
855
  //#region src/printers/printerFaker.ts
917
856
  /**
918
857
  * Formats that put a whole number inside a `type: 'string'` schema, the way ProtoJSON encodes
@@ -926,77 +865,32 @@ const integerFormats = /* @__PURE__ */ new Set([
926
865
  "uint64"
927
866
  ]);
928
867
  const maxInt32 = 2147483647;
929
- const fakerKeywordMapper = {
930
- any: () => "undefined",
931
- unknown: () => "undefined",
932
- void: () => "undefined",
933
- number: (min, max) => {
934
- if (max !== void 0 && min !== void 0) return `faker.number.float({ min: ${min}, max: ${max} })`;
935
- if (max !== void 0) return `faker.number.float({ max: ${max} })`;
936
- if (min !== void 0) return `faker.number.float({ min: ${min} })`;
937
- return "faker.number.float()";
938
- },
939
- integer: (min, max) => {
940
- if (max !== void 0 && min !== void 0) return `faker.number.int({ min: ${min}, max: ${max} })`;
941
- if (max !== void 0) return `faker.number.int({ max: ${max} })`;
942
- if (min !== void 0) return `faker.number.int({ min: ${min} })`;
943
- return "faker.number.int()";
944
- },
945
- bigint: () => "faker.number.bigInt()",
946
- integerString: (format) => {
947
- if (format === "int32") return `faker.number.int({ max: ${maxInt32} }).toString()`;
948
- return "faker.number.bigInt().toString()";
949
- },
950
- string: (min, max) => {
951
- if (max !== void 0 && min !== void 0) return `faker.string.alpha({ length: { min: ${min}, max: ${max} } })`;
952
- if (max !== void 0) return `faker.string.alpha({ length: ${max} })`;
953
- if (min !== void 0) return `faker.string.alpha({ length: ${min} })`;
954
- return "faker.string.alpha()";
955
- },
956
- boolean: () => "faker.datatype.boolean()",
957
- null: () => "null",
958
- array: (items = [], min, max) => {
959
- if (items.length > 1) return `faker.helpers.arrayElements([${items.join(", ")}])`;
960
- const item = items.at(0);
961
- if (min !== void 0 && max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: ${min}, max: ${max} }})`;
962
- if (min !== void 0) return `faker.helpers.multiple(() => (${item}), { count: ${min} })`;
963
- if (max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: 0, max: ${max} }})`;
964
- return `faker.helpers.multiple(() => (${item}))`;
965
- },
966
- tuple: (items = []) => `[${items.join(", ")}]`,
967
- enum: (items = [], type) => `faker.helpers.arrayElement${type ? `<${type}>` : ""}([${items.join(", ")}])`,
968
- union: (items = []) => `faker.helpers.arrayElement([${items.join(", ")}])`,
969
- datetime: () => "faker.date.anytime().toISOString()",
970
- date: (representation = "string", parser = "faker") => {
971
- if (representation === "string") {
972
- if (parser !== "faker") return `${parser}(faker.date.anytime()).format("YYYY-MM-DD")`;
973
- return "faker.date.anytime().toISOString().substring(0, 10)";
974
- }
975
- if (parser !== "faker") throw new Error(`type '${representation}' and parser '${parser}' can not work together`);
976
- return "faker.date.anytime()";
977
- },
978
- time: (representation = "string", parser = "faker") => {
979
- if (representation === "string") {
980
- if (parser !== "faker") return `${parser}(faker.date.anytime()).format("HH:mm:ss")`;
981
- return "faker.date.anytime().toISOString().substring(11, 19)";
982
- }
983
- if (parser !== "faker") throw new Error(`type '${representation}' and parser '${parser}' can not work together`);
984
- return "faker.date.anytime()";
985
- },
986
- uuid: () => "faker.string.uuid()",
987
- url: () => "faker.internet.url()",
988
- and: (items = []) => {
989
- if (items.length === 0) return "{}";
990
- if (items.length === 1) return items[0] ?? "{}";
991
- return `{...${items.join(", ...")}}`;
992
- },
993
- matches: (value = "", regexGenerator = "faker") => {
994
- if (regexGenerator === "randexp") return `${toRegExpString(value, "RandExp")}.gen()`;
995
- return `faker.helpers.fromRegExp(${toRegExpString(value, null)})`;
996
- },
997
- email: () => "faker.internet.email()",
998
- blob: () => "faker.image.url() as unknown as Blob"
999
- };
868
+ /**
869
+ * `faker.number.float()` or `faker.number.int()`, with `min` and `max` passed only when set.
870
+ */
871
+ function numberCall(kind, min, max) {
872
+ const args = [min !== void 0 && `min: ${min}`, max !== void 0 && `max: ${max}`].filter(Boolean).join(", ");
873
+ return `faker.number.${kind}(${args ? `{ ${args} }` : ""})`;
874
+ }
875
+ /**
876
+ * A `date` or `time` value: an ISO substring, a `dateParser` call, or a `Date` when `representation` is `'date'`.
877
+ */
878
+ function dateTimeCall(representation, { format, substring }, parser = "faker", schemaName) {
879
+ if (representation === "string") return parser !== "faker" ? `${parser}(faker.date.anytime()).format("${format}")` : `faker.date.anytime().toISOString().substring(${substring})`;
880
+ if (parser !== "faker") throw new kubb_kit.Diagnostics.Error({
881
+ code: kubb_kit.Diagnostics.code.invalidPluginOptions,
882
+ severity: "error",
883
+ message: `Option \`dateParser: '${parser}'\` cannot format the adapter's \`dateType: 'date'\` values${schemaName ? ` in schema "${schemaName}"` : ""}.`,
884
+ help: "Set adapterOas({ dateType: 'string' }) or remove `dateParser`.",
885
+ location: { kind: "config" },
886
+ plugin: "plugin-faker"
887
+ });
888
+ return "faker.date.anytime()";
889
+ }
890
+ function matches(value, regexGenerator = "faker") {
891
+ if (regexGenerator === "randexp") return `${toRegExpString(value, "RandExp")}.gen()`;
892
+ return `faker.helpers.fromRegExp(${toRegExpString(value, null)})`;
893
+ }
1000
894
  function parseEnumValue(value) {
1001
895
  if (typeof value === "string") return stringify(value);
1002
896
  return value;
@@ -1042,49 +936,60 @@ const printerFaker = kubb_kit.ast.createPrinter((options) => {
1042
936
  name: "faker",
1043
937
  options,
1044
938
  nodes: {
1045
- any: () => fakerKeywordMapper.any(),
1046
- unknown: () => fakerKeywordMapper.unknown(),
1047
- void: () => fakerKeywordMapper.void(),
1048
- boolean: () => fakerKeywordMapper.boolean(),
1049
- null: () => fakerKeywordMapper.null(),
939
+ any: () => "undefined",
940
+ unknown: () => "undefined",
941
+ void: () => "undefined",
942
+ boolean: () => "faker.datatype.boolean()",
943
+ null: () => "null",
1050
944
  string(node) {
1051
- if (node.pattern) return fakerKeywordMapper.matches(node.pattern, this.options.regexGenerator);
1052
- if (node.format && integerFormats.has(node.format)) return fakerKeywordMapper.integerString(node.format);
1053
- return fakerKeywordMapper.string(node.min, node.max);
1054
- },
1055
- email: () => fakerKeywordMapper.email(),
1056
- url: () => fakerKeywordMapper.url(),
1057
- uuid: () => fakerKeywordMapper.uuid(),
1058
- number(node) {
1059
- return fakerKeywordMapper.number(node.min, node.max);
945
+ if (node.pattern) return matches(node.pattern, this.options.regexGenerator);
946
+ if (node.format && integerFormats.has(node.format)) return node.format === "int32" ? `faker.number.int({ max: ${maxInt32} }).toString()` : "faker.number.bigInt().toString()";
947
+ const { min, max } = node;
948
+ if (min !== void 0 && max !== void 0) return `faker.string.alpha({ length: { min: ${min}, max: ${max} } })`;
949
+ if (max !== void 0 || min !== void 0) return `faker.string.alpha({ length: ${max ?? min} })`;
950
+ return "faker.string.alpha()";
1060
951
  },
1061
- integer(node) {
1062
- return fakerKeywordMapper.integer(node.min, node.max);
1063
- },
1064
- bigint: () => fakerKeywordMapper.bigint(),
1065
- blob: () => fakerKeywordMapper.blob(),
1066
- datetime: () => fakerKeywordMapper.datetime(),
952
+ email: () => "faker.internet.email()",
953
+ url: () => "faker.internet.url()",
954
+ uuid: () => "faker.string.uuid()",
955
+ number: (node) => numberCall("float", node.min, node.max),
956
+ integer: (node) => numberCall("int", node.min, node.max),
957
+ bigint: () => "faker.number.bigInt()",
958
+ blob: () => "faker.image.url() as unknown as Blob",
959
+ datetime: () => "faker.date.anytime().toISOString()",
1067
960
  date(node) {
1068
- return fakerKeywordMapper.date(node.representation ?? "string", this.options.dateParser);
961
+ return dateTimeCall(node.representation ?? "string", {
962
+ format: "YYYY-MM-DD",
963
+ substring: "0, 10"
964
+ }, this.options.dateParser, this.options.schemaName);
1069
965
  },
1070
966
  time(node) {
1071
- return fakerKeywordMapper.time(node.representation ?? "string", this.options.dateParser);
967
+ return dateTimeCall(node.representation ?? "string", {
968
+ format: "HH:mm:ss",
969
+ substring: "11, 19"
970
+ }, this.options.dateParser, this.options.schemaName);
1072
971
  },
1073
972
  ref(node) {
1074
973
  const refName = kubb_kit.ast.resolveRefName(node);
1075
- if (!refName) throw new Error("Name not defined for ref node");
974
+ if (!refName) throw new kubb_kit.Diagnostics.Error({
975
+ code: kubb_kit.Diagnostics.code.pluginFailed,
976
+ severity: "error",
977
+ message: `Ref node "${node.ref ?? node.name ?? "unknown"}"${this.options.schemaName ? ` in schema "${this.options.schemaName}"` : ""} has no name.`,
978
+ plugin: "plugin-faker"
979
+ });
1076
980
  if (this.options.schemaName && refName === this.options.schemaName) return this.options.typeName ? `undefined as unknown as ${this.options.typeName}` : "undefined as unknown";
1077
981
  const resolvedName = node.ref ? this.options.resolver.name(refName) : refName;
1078
982
  if (!this.options.nestedInObject) return `${resolvedName}(data)`;
1079
983
  return `${resolvedName}()`;
1080
984
  },
1081
985
  enum(node) {
1082
- return fakerKeywordMapper.enum(kubb_kit.ast.getSchemaLiteralValues(node).map(parseEnumValue), this.options.typeName);
986
+ const { typeName } = this.options;
987
+ return `faker.helpers.arrayElement${typeName ? `<${typeName}>` : ""}([${kubb_kit.ast.getSchemaLiteralValues(node).map(parseEnumValue).join(", ")}])`;
1083
988
  },
1084
989
  union(node) {
1085
990
  const { discriminatorPropertyName } = node;
1086
991
  const baseTypeName = this.options.typeName;
1087
- const items = mapSchemaMembers(node, (member) => {
992
+ return `faker.helpers.arrayElement([${mapSchemaMembers(node, (member) => {
1088
993
  const value = discriminatorPropertyName ? getDiscriminatorValue(member, discriminatorPropertyName) : void 0;
1089
994
  if (baseTypeName && value !== void 0) {
1090
995
  const typeName = `Extract<NonNullable<${baseTypeName}>, { ${JSON.stringify(discriminatorPropertyName)}: ${parseEnumValue(value)} }>`;
@@ -1099,26 +1004,31 @@ const printerFaker = kubb_kit.ast.createPrinter((options) => {
1099
1004
  nestedInObject: true,
1100
1005
  nestedInUnion: true
1101
1006
  });
1102
- }).map(({ output }) => output).filter((item) => Boolean(item));
1103
- return fakerKeywordMapper.union(items);
1007
+ }).map(({ output }) => output).filter((item) => Boolean(item)).join(", ")}])`;
1104
1008
  },
1105
1009
  intersection(node) {
1106
1010
  const items = mapSchemaMembers(node, (member) => printNested(member, { nestedInObject: true })).map(({ output }) => output).filter((item) => Boolean(item) && item !== "undefined");
1107
- return fakerKeywordMapper.and(items);
1011
+ if (items.length === 0) return "{}";
1012
+ return items.length === 1 ? items[0] : `{...${items.join(", ...")}}`;
1108
1013
  },
1109
1014
  array(node) {
1110
1015
  const items = mapSchemaItems(node, (member) => printNested(member, {
1111
1016
  typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[number]` : void 0,
1112
1017
  nestedInObject: true
1113
1018
  })).map(({ output }) => output).filter((item) => Boolean(item));
1114
- return fakerKeywordMapper.array(items, node.min, node.max);
1019
+ if (items.length > 1) return `faker.helpers.arrayElements([${items.join(", ")}])`;
1020
+ const { min, max } = node;
1021
+ const item = items[0];
1022
+ if (min !== void 0 && max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: ${min}, max: ${max} }})`;
1023
+ if (min !== void 0) return `faker.helpers.multiple(() => (${item}), { count: ${min} })`;
1024
+ if (max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: 0, max: ${max} }})`;
1025
+ return `faker.helpers.multiple(() => (${item}))`;
1115
1026
  },
1116
1027
  tuple(node) {
1117
- const items = (node.items ?? []).map((member, index) => printNested(member, {
1028
+ return `[${(node.items ?? []).map((member, index) => printNested(member, {
1118
1029
  typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[${index}]` : void 0,
1119
1030
  nestedInObject: true
1120
- })).filter((item) => Boolean(item));
1121
- return fakerKeywordMapper.tuple(items);
1031
+ })).filter((item) => Boolean(item)).join(", ")}]`;
1122
1032
  },
1123
1033
  object(node) {
1124
1034
  const cyclicSchemas = this.options.cyclicSchemas;
@@ -1135,10 +1045,7 @@ const printerFaker = kubb_kit.ast.createPrinter((options) => {
1135
1045
  }));
1136
1046
  }
1137
1047
  },
1138
- overrides: options.nodes,
1139
- print(node) {
1140
- return this.transform(node) ?? null;
1141
- }
1048
+ overrides: options.nodes
1142
1049
  };
1143
1050
  });
1144
1051
  //#endregion
@@ -1160,9 +1067,12 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1160
1067
  const tsResolver = ctx.driver.getResolver(_kubb_plugin_ts.pluginTsName);
1161
1068
  const schemaName = node.name;
1162
1069
  const isEnumSchema = !!kubb_kit.ast.narrowSchema(node, kubb_kit.ast.schemaTypes.enum);
1163
- const tsEnumType = pluginTs.options?.enum?.type;
1164
- const tsEnumTypeSuffix = pluginTs.options?.enum?.typeSuffix ?? "Key";
1165
- const schemaTypeName = isEnumSchema && tsEnumType === "asConst" ? tsResolver.enum.keyName({ name: schemaName }, tsEnumTypeSuffix) : tsResolver.name(schemaName);
1070
+ const schemaTypeName = (0, _kubb_plugin_ts.enumTypeName)({
1071
+ resolver: tsResolver,
1072
+ name: schemaName,
1073
+ enumOptions: pluginTs.options?.enum,
1074
+ isEnum: isEnumSchema
1075
+ });
1166
1076
  const meta = {
1167
1077
  name: resolver.name(schemaName),
1168
1078
  file: resolver.file({
@@ -1343,7 +1253,7 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1343
1253
  description: node.requestBody?.description ?? schema.description
1344
1254
  }));
1345
1255
  const responseName = resolver.response.response(node);
1346
- const hasResponseNameCollision = new Set(node.responses.flatMap((response) => (response.content ?? []).flatMap((entry) => entry.schema ? collectRefNames(entry.schema).map((name) => resolver.name(name)) : []))).has(responseName);
1256
+ const hasResponseNameCollision = new Set(node.responses.flatMap((response) => (response.content ?? []).flatMap((entry) => entry.schema ? kubb_kit.ast.collectImportedRefNames(entry.schema).map((name) => resolver.name(name)) : []))).has(responseName);
1347
1257
  const localHelperNames = /* @__PURE__ */ new Set([
1348
1258
  ...paramGroups.map((group) => group.name),
1349
1259
  ...responseUnits.map((unit) => unit.name),
@@ -1472,20 +1382,8 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1472
1382
  children: `faker.seed(${JSON.stringify(seed)})`
1473
1383
  }) : void 0,
1474
1384
  paramGroups.map((group) => renderEntry(group)),
1475
- responseUnits.map((unit) => renderEntry({
1476
- schema: unit.schema,
1477
- name: unit.name,
1478
- typeName: unit.typeName,
1479
- description: unit.description,
1480
- skipImportNames: unit.skipImportNames
1481
- })),
1482
- dataUnits.map((unit) => renderEntry({
1483
- schema: unit.schema,
1484
- name: unit.name,
1485
- typeName: unit.typeName,
1486
- description: unit.description,
1487
- skipImportNames: unit.skipImportNames
1488
- })),
1385
+ responseUnits.map((unit) => renderEntry(unit)),
1386
+ dataUnits.map((unit) => renderEntry(unit)),
1489
1387
  !hasResponseNameCollision && renderEntry({
1490
1388
  schema: buildResponseUnionSchema(node, resolver),
1491
1389
  name: responseName,
@@ -1500,11 +1398,11 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1500
1398
  //#region kubb-extension.json
1501
1399
  var compatibility = {
1502
1400
  "kubb": ">=5.8.3",
1503
- "node": ">=22"
1401
+ "node": ">=22.12"
1504
1402
  };
1505
1403
  //#endregion
1506
1404
  //#region package.json
1507
- var version = "5.1.6";
1405
+ var version = "5.1.9";
1508
1406
  //#endregion
1509
1407
  //#region src/resolvers/resolverFaker.ts
1510
1408
  /**
@@ -1572,6 +1470,18 @@ const pluginFaker = (0, kubb_kit.defineExtension)({
1572
1470
  path: "mocks",
1573
1471
  barrel: { type: "named" }
1574
1472
  }, seed, locale = "en", group, exclude = [], include, override = [], typeMode = "inferred", dateParser = "faker", regexGenerator = "faker", printer, resolver: userResolver, macros: userMacros } = options;
1473
+ (0, kubb_kit.assertPluginOption)({
1474
+ plugin: pluginFakerName,
1475
+ option: "typeMode",
1476
+ value: typeMode,
1477
+ allowed: ["inferred", "schema"]
1478
+ });
1479
+ (0, kubb_kit.assertPluginOption)({
1480
+ plugin: pluginFakerName,
1481
+ option: "regexGenerator",
1482
+ value: regexGenerator,
1483
+ allowed: ["faker", "randexp"]
1484
+ });
1575
1485
  (0, kubb_kit.setResolver)(userResolver ? kubb_kit.Resolver.merge(resolverFaker, userResolver) : resolverFaker);
1576
1486
  if (userMacros?.length) (0, kubb_kit.setMacros)(userMacros);
1577
1487
  (0, kubb_kit.addGenerator)(fakerGenerator);