@kubb/plugin-faker 5.2.1 → 5.2.3

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
@@ -2,51 +2,12 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- //#endregion
6
5
  let node_path = require("node:path");
7
6
  let kubb_kit = require("kubb/kit");
8
7
  let kubb_jsx = require("kubb/jsx");
9
8
  let kubb_jsx_jsx_runtime = require("kubb/jsx/jsx-runtime");
10
9
  let _kubb_plugin_ts = require("@kubb/plugin-ts");
11
- //#region ../../internals/utils/src/casing.ts
12
- /**
13
- * Shared implementation for camelCase and PascalCase conversion.
14
- * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
15
- * and capitalizes each word according to `pascal`.
16
- *
17
- * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
18
- */
19
- function convert(text, pascal) {
20
- return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
21
- if (word.length > 1 && word === word.toUpperCase()) return word;
22
- return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
23
- }).join("").replace(/[^a-zA-Z0-9]/g, "");
24
- }
25
- const cache = /* @__PURE__ */ new Map();
26
- const cacheLimit = 1e4;
27
- function toCamelOrPascal(text, pascal) {
28
- const key = `${pascal ? "P" : "c"}${text}`;
29
- const cached = cache.get(key);
30
- if (cached !== void 0) return cached;
31
- const result = convert(text, pascal);
32
- if (cache.size >= cacheLimit) cache.clear();
33
- cache.set(key, result);
34
- return result;
35
- }
36
- /**
37
- * Converts `text` to camelCase.
38
- *
39
- * @example Word boundaries
40
- * `camelCase('hello-world') // 'helloWorld'`
41
- *
42
- * @example With a prefix
43
- * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
44
- */
45
- function camelCase(text, { prefix = "", suffix = "" } = {}) {
46
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
47
- }
48
- //#endregion
49
- //#region ../../internals/utils/src/reserved.ts
10
+ // ../../internals/utils/src/reserved.ts
50
11
  /**
51
12
  * JavaScript and Java reserved words.
52
13
  * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
@@ -54,6 +15,7 @@ function camelCase(text, { prefix = "", suffix = "" } = {}) {
54
15
  const reservedWords = /* @__PURE__ */ new Set([
55
16
  "abstract",
56
17
  "arguments",
18
+ "await",
57
19
  "boolean",
58
20
  "break",
59
21
  "byte",
@@ -184,8 +146,7 @@ function ensureValidVarName(name) {
184
146
  function isIdentifier(name) {
185
147
  return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
186
148
  }
187
- //#endregion
188
- //#region ../../internals/utils/src/strings.ts
149
+ // ../../internals/utils/src/strings.ts
189
150
  /**
190
151
  * Wraps a value in single quotes for emitting a single-quoted JavaScript string literal, escaping
191
152
  * any backslash or single quote in the content.
@@ -246,6 +207,34 @@ function stringify(value) {
246
207
  function jsDocEscape(input) {
247
208
  return `${input}`.replace(/^(\s*)@/gm, "$1\\@");
248
209
  }
210
+ const NEEDS_UNICODE = /(?<!\\)(?:\\\\)*\\[pPu]\{|[\u{10000}-\u{10FFFF}]/u;
211
+ const KEPT_ESCAPE = /[A-Za-z0-9^$\\.*+?()[\]{}|/]/;
212
+ /**
213
+ * Drops the backslash from escapes that the `u` flag rejects: an escaped punctuation character that is
214
+ * not a syntax character, and `\-` outside a class. Both match the same character without the backslash.
215
+ */
216
+ function dropIdentityEscapes(pattern) {
217
+ let inClass = false;
218
+ return pattern.replace(/\\(.)|[[\]]/gs, (match, escaped) => {
219
+ if (escaped === void 0) {
220
+ inClass = match === "[";
221
+ return match;
222
+ }
223
+ return KEPT_ESCAPE.test(escaped) || escaped === "-" && inClass ? match : escaped;
224
+ });
225
+ }
226
+ /**
227
+ * Builds the `RegExp` for a pattern, adding the `u` flag when it uses `\p{...}`, `\P{...}` or `\u{...}`, or
228
+ * holds a character outside the BMP. A pattern that is not valid under `u` keeps the flags it came with.
229
+ */
230
+ function toRegExp(pattern, flags) {
231
+ if (flags?.includes("u") || !NEEDS_UNICODE.test(pattern)) return new RegExp(pattern, flags);
232
+ try {
233
+ return new RegExp(dropIdentityEscapes(pattern), `${flags ?? ""}u`);
234
+ } catch {
235
+ return new RegExp(pattern, flags);
236
+ }
237
+ }
249
238
  /**
250
239
  * Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
251
240
  * Inline flags expressed as a `^(?im)` prefix are extracted and applied to the resulting expression.
@@ -262,13 +251,11 @@ function toRegExpString(text, func = "RegExp") {
262
251
  const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i);
263
252
  const replacementTarget = match?.[1] ?? "";
264
253
  const matchedFlags = match?.[2];
265
- const cleaned = raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, "");
266
- const { source, flags } = new RegExp(cleaned, matchedFlags);
254
+ const { source, flags } = toRegExp(raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, ""), matchedFlags);
267
255
  if (func === null) return `/${source}/${flags}`;
268
256
  return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
269
257
  }
270
- //#endregion
271
- //#region ../../internals/utils/src/codegen.ts
258
+ // ../../internals/utils/src/codegen.ts
272
259
  const INDENT = " ";
273
260
  /**
274
261
  * Indents every non-empty line of `text` by one indent level, leaving blank lines empty.
@@ -305,8 +292,7 @@ function buildObject(entries) {
305
292
  if (entries.length === 0) return "{}";
306
293
  return `{\n${entries.map((entry) => `${indentLines(entry)},`).join("\n")}\n}`;
307
294
  }
308
- //#endregion
309
- //#region ../../internals/utils/src/fs.ts
295
+ // ../../internals/utils/src/fs.ts
310
296
  function toSlash(p) {
311
297
  if (p.startsWith("\\\\?\\")) return p;
312
298
  return p.replaceAll("\\", "/");
@@ -344,12 +330,11 @@ function getRelativePath(rootDir, filePath) {
344
330
  * @example Suffix applied to the final segment only
345
331
  * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
346
332
  */
347
- function toFilePath(name, caseLast = camelCase) {
333
+ function toFilePath(name, caseLast = kubb_kit.camelCase) {
348
334
  const parts = name.split(/\.(?=[a-zA-Z])/);
349
- return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
335
+ return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : (0, kubb_kit.camelCase)(part)).filter(Boolean).join("/");
350
336
  }
351
- //#endregion
352
- //#region src/utils.ts
337
+ // src/utils.ts
353
338
  /**
354
339
  * Returns the `@faker-js/faker` named export for a locale code.
355
340
  *
@@ -400,6 +385,18 @@ const NON_INLINABLE_RESPONSE_TYPES = /* @__PURE__ */ new Set([
400
385
  function canOverrideSchema(node) {
401
386
  return !NON_OVERRIDABLE_TYPES.has(node.type);
402
387
  }
388
+ /**
389
+ * Whether a schema can supply object properties when merging faker values.
390
+ */
391
+ function isObjectSchema(node, seen = /* @__PURE__ */ new Set()) {
392
+ const resolved = kubb_kit.ast.resolveRef(node);
393
+ if (seen.has(resolved)) return false;
394
+ seen.add(resolved);
395
+ if (kubb_kit.ast.narrowSchema(resolved, kubb_kit.ast.schemaTypes.object) || kubb_kit.ast.narrowSchema(resolved, kubb_kit.ast.schemaTypes.ref)) return true;
396
+ const composition = kubb_kit.ast.narrowSchema(resolved, kubb_kit.ast.schemaTypes.intersection) ?? kubb_kit.ast.narrowSchema(resolved, kubb_kit.ast.schemaTypes.union);
397
+ if (!composition) return false;
398
+ return composition.type === kubb_kit.ast.schemaTypes.intersection && !composition.members?.length || (composition.members ?? []).some((member) => isObjectSchema(member, seen));
399
+ }
403
400
  function shouldInlineSingleResponseSchema(schema) {
404
401
  return !NON_INLINABLE_RESPONSE_TYPES.has(schema.type);
405
402
  }
@@ -411,11 +408,16 @@ function buildResponseUnionSchema(node, resolver) {
411
408
  const responses = node.responses.filter((response) => response.content?.[0]?.schema);
412
409
  if (!responses.length) return null;
413
410
  if (responses.length === 1) {
414
- const schema = responses[0].content?.[0]?.schema;
411
+ const schemas = responses[0].content?.flatMap((content) => content.schema ? [content.schema] : []) ?? [];
412
+ const schema = schemas.length > 1 ? kubb_kit.ast.factory.createSchema({
413
+ type: "union",
414
+ members: schemas
415
+ }) : schemas[0];
415
416
  if (schema && shouldInlineSingleResponseSchema(schema)) return schema;
416
417
  return kubb_kit.ast.factory.createSchema({
417
418
  type: "ref",
418
- name: resolver.response.status(node, responses[0].statusCode)
419
+ name: resolver.response.status(node, responses[0].statusCode),
420
+ schema: responses[0].content?.length === 1 ? schema : void 0
419
421
  });
420
422
  }
421
423
  return kubb_kit.ast.factory.createSchema({
@@ -484,7 +486,8 @@ function getScalarType(node, typeName) {
484
486
  * Determines the data type, return type, and whether it uses the type name.
485
487
  */
486
488
  function resolveFakerTypeUsage(node, typeName, canOverride) {
487
- const scalarType = SCALAR_TYPES.has(node.type) ? `${getScalarType(node, typeName)}${node.nullable ? " | null" : ""}` : void 0;
489
+ const resolvedNode = kubb_kit.ast.resolveRef(node);
490
+ const scalarType = SCALAR_TYPES.has(resolvedNode.type) ? `${getScalarType(resolvedNode, typeName)}${node.nullable || resolvedNode.nullable ? " | null" : ""}` : void 0;
488
491
  const dataType = scalarType ?? `Partial<${typeName}>`;
489
492
  const returnType = scalarType ?? (canOverride ? typeName : null);
490
493
  return {
@@ -493,28 +496,27 @@ function resolveFakerTypeUsage(node, typeName, canOverride) {
493
496
  usesTypeName: canOverride && dataType.includes(typeName) || Boolean(returnType?.includes(typeName))
494
497
  };
495
498
  }
496
- //#endregion
497
- //#region src/components/Faker.tsx
498
- const OBJECT_TYPES = /* @__PURE__ */ new Set(["object", "intersection"]);
499
- function Faker({ node, description, name, typeName, printer, canOverride, typeMode = "inferred" }) {
499
+ // src/components/Faker.tsx
500
+ function Faker({ node, description, name, typeName, printer, canOverride, typeMode = "inferred", keysToOmit }) {
500
501
  const fakerText = printer.print(node) ?? "undefined";
501
502
  const isArray = node.type === "array";
502
- const isObject = OBJECT_TYPES.has(node.type);
503
+ const isObject = !!kubb_kit.ast.narrowSchema(node, kubb_kit.ast.schemaTypes.object) || node.type === kubb_kit.ast.schemaTypes.intersection && isObjectSchema(node);
504
+ const isValueIntersection = node.type === kubb_kit.ast.schemaTypes.intersection && !isObject;
503
505
  const isTuple = node.type === "tuple";
504
506
  const isScalar = SCALAR_TYPES.has(node.type);
505
507
  const isUnion = node.type === "union";
506
- const useObjectOverride = canOverride && isObject;
508
+ const useObjectOverride = canOverride && (isObject || !!keysToOmit?.length);
507
509
  const fakerTextWithOverride = (() => {
508
510
  if (canOverride && node.type === "tuple") return `data && data.length === ${node.items?.length ?? 0} && !data.includes(undefined) ? data : ${fakerText}`;
509
511
  if (canOverride && isArray) return `[\n ...${fakerText},\n ...(data || []).filter((item) => item !== undefined),\n]`;
510
- if (canOverride && (isScalar || isUnion)) return node.nullable ? `data !== undefined ? data : ${fakerText}` : `data ?? ${fakerText}`;
512
+ if (canOverride && (isScalar || isUnion || isValueIntersection)) return node.nullable ? `data !== undefined ? data : ${fakerText}` : `data ?? ${fakerText}`;
511
513
  return fakerText;
512
514
  })();
513
515
  const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
514
516
  if (!useObjectOverride) {
515
517
  const paramsSignature = `${/\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data"}?: ${dataType}`;
516
518
  const returnType = resolvedReturnType;
517
- const returnExpression = canOverride && !!returnType && (node.type === "ref" || isArray || isTuple || isUnion) ? `${isTuple || isUnion ? `(${fakerTextWithOverride})` : fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride;
519
+ const returnExpression = canOverride && !!returnType && (node.type === "ref" && !SCALAR_TYPES.has(kubb_kit.ast.resolveRef(node).type) || isArray || isTuple || isUnion) ? `${isTuple || isUnion ? `(${fakerTextWithOverride})` : fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride;
518
520
  return /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Source, {
519
521
  name,
520
522
  isExportable: true,
@@ -529,18 +531,21 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
529
531
  })
530
532
  });
531
533
  }
532
- const returnType = typeMode === "schema" ? typeName : "Omit<typeof defaultFakeData, keyof NoInfer<TData>> & NoInfer<TData>";
533
534
  const { cyclicSchemas, schemaName } = printer.options;
534
- const functionBody = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) => (0, kubb_kit.containsCircularRef)(p.schema, {
535
+ const isCyclic = !!schemaName && !!cyclicSchemas?.has(schemaName);
536
+ const returnType = typeMode === "schema" ? typeName : `Omit<${isCyclic ? typeName : "typeof defaultFakeData"}, keyof NoInfer<TData>> & NoInfer<TData>`;
537
+ const hasGetters = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) => (0, kubb_kit.containsCircularRef)(p.schema, {
535
538
  circularSchemas: cyclicSchemas,
536
539
  excludeName: schemaName
537
- })) ? `const defaultFakeData = ${fakerText}
540
+ }));
541
+ const declaration = `const ${keysToOmit?.length ? `{ ${keysToOmit.map((key, index) => `${objectKey(key)}: _omit${index}`).join(", ")}, ...defaultFakeData }` : "defaultFakeData"} = ${fakerText}`;
542
+ const functionBody = hasGetters ? `${declaration}
538
543
  if (data) {
539
544
  for (const [key, value] of Object.entries(data)) {
540
545
  Object.defineProperty(defaultFakeData, key, { value, configurable: true, writable: true, enumerable: true })
541
546
  }
542
547
  }
543
- return defaultFakeData as ${returnType}` : `const defaultFakeData = ${fakerText}
548
+ return defaultFakeData as ${returnType}` : `${declaration}
544
549
  return {
545
550
  ...defaultFakeData,
546
551
  ...(data || {}),
@@ -555,13 +560,12 @@ return {
555
560
  JSDoc: { comments: description ? [`@description ${jsDocEscape(description)}`] : [] },
556
561
  generics: typeMode === "schema" ? void 0 : `TData extends Partial<${typeName}> = object`,
557
562
  params: typeMode === "schema" ? `data?: Partial<${typeName}>` : "data?: TData",
558
- returnType: typeMode === "schema" ? typeName : void 0,
563
+ returnType: typeMode === "schema" || isCyclic ? returnType : void 0,
559
564
  children: functionBody
560
565
  })
561
566
  });
562
567
  }
563
- //#endregion
564
- //#region ../../internals/shared/src/operation.ts
568
+ // ../../internals/shared/src/operation.ts
565
569
  /**
566
570
  * Builds the `ResolverFileParams` every operation generator passes to
567
571
  * `resolver.file`: a file named `name`, tagged by the operation's first
@@ -676,17 +680,24 @@ function getOperationParameters(node) {
676
680
  operationParameterGroupsByNode.set(node, groups);
677
681
  return groups;
678
682
  }
679
- //#endregion
680
- //#region ../../internals/shared/src/resolver.ts
683
+ // ../../internals/shared/src/resolver.ts
681
684
  /**
682
- * Resolves a single operation parameter name with the
683
- * `<operationId> <in> <name>` template.
685
+ * Builds the allocation key for a declaration an operation owns. `scope` names which declaration
686
+ * it is, so two of them never share an allocation even when a custom resolver gives both the same
687
+ * name. Leave `scope` empty for the operation's own declaration.
684
688
  *
685
689
  * @example
686
- * `operationParamName.call(resolver, node, param) // → 'DeletePetPathPetId'`
690
+ * ```ts
691
+ * resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
692
+ * ```
687
693
  */
688
- function operationParamName(node, param) {
689
- return this.name(`${node.operationId} ${param.in} ${param.name}`);
694
+ function operationKey(node, ...scope) {
695
+ return [
696
+ "operation",
697
+ node.method,
698
+ node.path,
699
+ ...scope.map(String)
700
+ ];
690
701
  }
691
702
  /**
692
703
  * Builds the shared `param` namespace. Spread the result into `createResolver`
@@ -699,15 +710,33 @@ function operationParamName(node, param) {
699
710
  */
700
711
  function createOperationParamResolver() {
701
712
  return {
702
- name: operationParamName,
713
+ name(node, param) {
714
+ const name = this.name(`${node.operationId} ${param.in} ${param.name}`);
715
+ return this.resolveName({
716
+ key: operationKey(node, "param", "name", param.in, param.name),
717
+ name
718
+ });
719
+ },
703
720
  path(node) {
704
- return this.name(`${node.operationId} Path`);
721
+ const name = this.name(`${node.operationId} Path`);
722
+ return this.resolveName({
723
+ key: operationKey(node, "param", "path"),
724
+ name
725
+ });
705
726
  },
706
727
  query(node) {
707
- return this.name(`${node.operationId} Query`);
728
+ const name = this.name(`${node.operationId} Query`);
729
+ return this.resolveName({
730
+ key: operationKey(node, "param", "query"),
731
+ name
732
+ });
708
733
  },
709
734
  headers(node) {
710
- return this.name(`${node.operationId} Headers`);
735
+ const name = this.name(`${node.operationId} Headers`);
736
+ return this.resolveName({
737
+ key: operationKey(node, "param", "headers"),
738
+ name
739
+ });
711
740
  }
712
741
  };
713
742
  }
@@ -724,16 +753,32 @@ function createOperationParamResolver() {
724
753
  function createOperationResponseResolver() {
725
754
  return {
726
755
  status(node, statusCode) {
727
- return this.name(`${node.operationId} Status ${statusCode}`);
756
+ const name = this.name(`${node.operationId} Status ${statusCode}`);
757
+ return this.resolveName({
758
+ key: operationKey(node, "response", "status", statusCode),
759
+ name
760
+ });
728
761
  },
729
762
  body(node) {
730
- return this.name(`${node.operationId} Body`);
763
+ const name = this.name(`${node.operationId} Body`);
764
+ return this.resolveName({
765
+ key: operationKey(node, "response", "body"),
766
+ name
767
+ });
731
768
  },
732
769
  responses(node) {
733
- return this.name(`${node.operationId} Responses`);
770
+ const name = this.name(`${node.operationId} Responses`);
771
+ return this.resolveName({
772
+ key: operationKey(node, "response", "responses"),
773
+ name
774
+ });
734
775
  },
735
776
  response(node) {
736
- return this.name(`${node.operationId} Response`);
777
+ const name = this.name(`${node.operationId} Response`);
778
+ return this.resolveName({
779
+ key: operationKey(node, "response", "response"),
780
+ name
781
+ });
737
782
  }
738
783
  };
739
784
  }
@@ -748,11 +793,10 @@ function createOperationResponseResolver() {
748
793
  */
749
794
  function createCasedFile(caseLast) {
750
795
  return { baseName({ name, extname }) {
751
- return `${toFilePath(name, caseLast)}${extname}`;
796
+ return this.memo(`file:${name}\0${extname}`, () => `${toFilePath(name, caseLast)}${extname}`);
752
797
  } };
753
798
  }
754
- //#endregion
755
- //#region ../../internals/shared/src/group.ts
799
+ // ../../internals/shared/src/group.ts
756
800
  /**
757
801
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
758
802
  * shared default naming so every plugin groups output consistently:
@@ -775,15 +819,14 @@ function createGroupConfig(group) {
775
819
  if (!group) return null;
776
820
  const defaultName = (ctx) => {
777
821
  if (group.type === "path") return `${ctx.group.split("/")[1]}`;
778
- return camelCase(ctx.group);
822
+ return (0, kubb_kit.camelCase)(ctx.group);
779
823
  };
780
824
  return {
781
825
  ...group,
782
826
  name: group.name ? group.name : defaultName
783
827
  };
784
828
  }
785
- //#endregion
786
- //#region ../../internals/shared/src/schemaTraversal.ts
829
+ // ../../internals/shared/src/schemaTraversal.ts
787
830
  /**
788
831
  * Maps each member of a union or intersection schema to its transformed output, pairing every
789
832
  * result with the original member.
@@ -804,8 +847,7 @@ function mapSchemaItems(node, transform) {
804
847
  output: transform(schema)
805
848
  }));
806
849
  }
807
- //#endregion
808
- //#region src/utils/imports.ts
850
+ // src/utils/imports.ts
809
851
  function escapeRegExp(value) {
810
852
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
811
853
  }
@@ -853,8 +895,7 @@ function aliasConflictingImports(imports, reservedNames) {
853
895
  function rewriteAliasedImports(text, aliases) {
854
896
  return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
855
897
  }
856
- //#endregion
857
- //#region src/printers/printerFaker.ts
898
+ // src/printers/printerFaker.ts
858
899
  /**
859
900
  * Formats that put a whole number inside a `type: 'string'` schema, the way ProtoJSON encodes
860
901
  * 64-bit integers, so the mock has to be digits rather than letters.
@@ -990,7 +1031,9 @@ const printerFaker = kubb_kit.ast.createPrinter((options) => {
990
1031
  },
991
1032
  enum(node) {
992
1033
  const { typeName } = this.options;
993
- return `faker.helpers.arrayElement${typeName ? `<${typeName}>` : ""}([${kubb_kit.ast.getSchemaLiteralValues(node).map(parseEnumValue).join(", ")}])`;
1034
+ const values = kubb_kit.ast.getSchemaLiteralValues(node);
1035
+ if (values.length === 1 && values[0] !== null && typeof values[0] === "object") return JSON.stringify(values[0]);
1036
+ return `faker.helpers.arrayElement${typeName ? `<${typeName}>` : ""}([${values.map(parseEnumValue).join(", ")}])`;
994
1037
  },
995
1038
  union(node) {
996
1039
  const { discriminatorPropertyName } = node;
@@ -1014,9 +1057,14 @@ const printerFaker = kubb_kit.ast.createPrinter((options) => {
1014
1057
  }).map(({ output }) => output).filter((item) => Boolean(item)).join(", ")}])`;
1015
1058
  },
1016
1059
  intersection(node) {
1017
- const items = mapSchemaMembers(node, (member) => printNested(member, { nestedInObject: true })).map(({ output }) => output).filter((item) => Boolean(item) && item !== "undefined");
1060
+ const objectMembers = (node.members ?? []).filter((member) => isObjectSchema(member));
1061
+ const members = objectMembers.length ? objectMembers : node.members;
1062
+ const items = mapSchemaMembers({
1063
+ ...node,
1064
+ members
1065
+ }, (member) => printNested(member, { nestedInObject: true })).map(({ output }) => output).filter((item) => Boolean(item) && item !== "undefined");
1018
1066
  if (items.length === 0) return "{}";
1019
- return items.length === 1 ? items[0] : `{...${items.join(", ...")}}`;
1067
+ return !objectMembers.length || items.length === 1 ? items.at(-1) : `{...${items.join(", ...")}}`;
1020
1068
  },
1021
1069
  array(node) {
1022
1070
  const items = mapSchemaItems(node, (member) => printNested(member, {
@@ -1039,7 +1087,13 @@ const printerFaker = kubb_kit.ast.createPrinter((options) => {
1039
1087
  },
1040
1088
  object(node) {
1041
1089
  const cyclicSchemas = this.options.cyclicSchemas;
1042
- return buildObject((node.properties ?? []).map((property) => {
1090
+ const keySchema = node.propertyNames && (0, kubb_kit.syncSchemaRef)(node.propertyNames);
1091
+ const valueSchema = node.additionalProperties;
1092
+ const recordProperties = keySchema?.type === "enum" && typeof valueSchema === "object" ? kubb_kit.ast.getSchemaLiteralValues(keySchema).filter((key) => typeof key === "string" && !node.properties.some((property) => property.name === key)).map((name) => kubb_kit.ast.factory.createProperty({
1093
+ name,
1094
+ schema: valueSchema
1095
+ })) : [];
1096
+ return buildObject([...node.properties, ...recordProperties].map((property) => {
1043
1097
  const value = printNested(property.schema, {
1044
1098
  typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : void 0,
1045
1099
  nestedInObject: true
@@ -1055,8 +1109,7 @@ const printerFaker = kubb_kit.ast.createPrinter((options) => {
1055
1109
  overrides: options.nodes
1056
1110
  };
1057
1111
  });
1058
- //#endregion
1059
- //#region src/generators/fakerGenerator.tsx
1112
+ // src/generators/fakerGenerator.tsx
1060
1113
  /**
1061
1114
  * Built-in generator for `@kubb/plugin-faker`. Emits one `createX` factory
1062
1115
  * per schema in the spec plus per-operation request/response factories. Each
@@ -1228,7 +1281,7 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1228
1281
  name: baseName,
1229
1282
  typeName: tsBaseName,
1230
1283
  description,
1231
- skipImportNames: []
1284
+ keysToOmit: primary.keysToOmit
1232
1285
  }];
1233
1286
  }
1234
1287
  const variants = resolveContentTypeVariants(entries, baseName);
@@ -1245,7 +1298,7 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1245
1298
  name: variant.name,
1246
1299
  typeName: getPerContentTypeName(tsBaseName, variant.suffix),
1247
1300
  description,
1248
- skipImportNames: []
1301
+ keysToOmit: variant.keysToOmit
1249
1302
  })), {
1250
1303
  schema: unionSchema,
1251
1304
  name: baseName,
@@ -1295,8 +1348,15 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1295
1348
  group: group ?? void 0
1296
1349
  }).filter((entry) => entry.path !== meta.file.path);
1297
1350
  }
1298
- function renderEntry({ schema, name, typeName, description, skipImportNames = [] }) {
1351
+ function renderEntry({ schema, name, typeName, description, keysToOmit, skipImportNames = [] }) {
1299
1352
  if (!schema) return null;
1353
+ if (schema.type === kubb_kit.ast.schemaTypes.object && keysToOmit?.length) {
1354
+ schema = {
1355
+ ...schema,
1356
+ properties: schema.properties.filter((property) => !keysToOmit?.includes(property.name))
1357
+ };
1358
+ keysToOmit = void 0;
1359
+ }
1300
1360
  const canOverride = canOverrideSchema(schema);
1301
1361
  const printerInstance = printerFaker({
1302
1362
  resolver,
@@ -1305,7 +1365,8 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1305
1365
  dateParser,
1306
1366
  regexGenerator,
1307
1367
  nodes: printer?.nodes,
1308
- cyclicSchemas
1368
+ cyclicSchemas,
1369
+ nestedInObject: !!keysToOmit?.length
1309
1370
  });
1310
1371
  const fakerText = printerInstance.print(schema) ?? "undefined";
1311
1372
  const { imports, aliases } = aliasConflictingImports(filterUsedImports(resolveMockImports(schema), fakerText, skipImportNames), localHelperNames);
@@ -1344,7 +1405,8 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1344
1405
  print: () => rewrittenFakerText
1345
1406
  },
1346
1407
  canOverride,
1347
- typeMode
1408
+ typeMode,
1409
+ keysToOmit
1348
1410
  })
1349
1411
  ] });
1350
1412
  }
@@ -1401,17 +1463,14 @@ const fakerGenerator = (0, kubb_kit.defineGenerator)({
1401
1463
  });
1402
1464
  }
1403
1465
  });
1404
- //#endregion
1405
- //#region kubb-extension.json
1466
+ // kubb-extension.json
1406
1467
  var compatibility = {
1407
- "kubb": ">=5.8.3",
1468
+ "kubb": ">=5.14.6",
1408
1469
  "node": ">=22.22"
1409
1470
  };
1410
- //#endregion
1411
- //#region package.json
1412
- var version = "5.2.1";
1413
- //#endregion
1414
- //#region src/resolvers/resolverFaker.ts
1471
+ // package.json
1472
+ var version = "5.2.3";
1473
+ // src/resolvers/resolverFaker.ts
1415
1474
  /**
1416
1475
  * Default resolver used by `@kubb/plugin-faker`. Decides the names and file
1417
1476
  * paths for every generated mock factory. Functions and files are prefixed
@@ -1427,14 +1486,13 @@ var version = "5.2.1";
1427
1486
  const resolverFaker = (0, kubb_kit.createResolver)({
1428
1487
  pluginName: "plugin-faker",
1429
1488
  name(name) {
1430
- return ensureValidVarName(camelCase(name, { prefix: "create" }));
1489
+ return this.memo(`name:${name}`, () => ensureValidVarName((0, kubb_kit.camelCase)(name, { prefix: "create" })));
1431
1490
  },
1432
- file: createCasedFile((part) => camelCase(part, { prefix: "create" })),
1491
+ file: createCasedFile((part) => (0, kubb_kit.camelCase)(part, { prefix: "create" })),
1433
1492
  param: createOperationParamResolver(),
1434
1493
  response: createOperationResponseResolver()
1435
1494
  });
1436
- //#endregion
1437
- //#region src/plugin.ts
1495
+ // src/plugin.ts
1438
1496
  /**
1439
1497
  * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and
1440
1498
  * cross-plugin dependency references.
@@ -1495,7 +1553,6 @@ const pluginFaker = (0, kubb_kit.defineExtension)({
1495
1553
  };
1496
1554
  }
1497
1555
  });
1498
- //#endregion
1499
1556
  exports.Faker = Faker;
1500
1557
  exports.default = pluginFaker;
1501
1558
  exports.fakerGenerator = fakerGenerator;