@kubb/plugin-faker 5.2.1 → 5.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Exclude, Group, Include, Output, OutputOptions, Override, PluginType, Resolver, ResolverPatch, ast } from "kubb/kit";
2
2
  import { KubbReactNode } from "kubb/jsx";
3
- //#region src/types.d.ts
4
3
  /**
5
4
  * Resolver for Faker that provides naming methods for mock functions.
6
5
  *
@@ -172,8 +171,6 @@ declare global {
172
171
  }
173
172
  }
174
173
  }
175
- //#endregion
176
- //#region src/printers/printerFaker.d.ts
177
174
  /**
178
175
  * Partial map of node-type overrides for the Faker printer. Each key is a
179
176
  * `SchemaType` (`'string'`, `'date'`, ...) and each handler returns the
@@ -231,8 +228,6 @@ type PrinterFakerFactory = ast.PrinterFactoryOptions<'faker', PrinterFakerOption
231
228
  * Handles circular references gracefully by emitting memoizing getters for cyclic properties.
232
229
  */
233
230
  export declare const printerFaker: (options: PrinterFakerOptions) => ast.Printer<PrinterFakerFactory>;
234
- //#endregion
235
- //#region src/components/Faker.d.ts
236
231
  type Props = {
237
232
  name: string;
238
233
  typeName: string;
@@ -241,10 +236,9 @@ type Props = {
241
236
  description?: string;
242
237
  canOverride: boolean;
243
238
  typeMode?: PluginFaker['resolvedOptions']['typeMode'];
239
+ keysToOmit?: Array<string> | null;
244
240
  };
245
- export declare function Faker({ node, description, name, typeName, printer, canOverride, typeMode }: Props): KubbReactNode;
246
- //#endregion
247
- //#region src/generators/fakerGenerator.d.ts
241
+ export declare function Faker({ node, description, name, typeName, printer, canOverride, typeMode, keysToOmit }: Props): KubbReactNode;
248
242
  /**
249
243
  * Built-in generator for `@kubb/plugin-faker`. Emits one `createX` factory
250
244
  * per schema in the spec plus per-operation request/response factories. Each
@@ -252,8 +246,6 @@ export declare function Faker({ node, description, name, typeName, printer, canO
252
246
  * `@kubb/plugin-ts`.
253
247
  */
254
248
  export declare const fakerGenerator: import("kubb/kit").Generator<PluginFaker, unknown>;
255
- //#endregion
256
- //#region src/plugin.d.ts
257
249
  /**
258
250
  * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and
259
251
  * cross-plugin dependency references.
@@ -284,8 +276,6 @@ export declare const pluginFakerName = "plugin-faker";
284
276
  * ```
285
277
  */
286
278
  export declare const pluginFaker: import("kubb/kit").PluginFactory<PluginFaker>;
287
- //#endregion
288
- //#region src/resolvers/resolverFaker.d.ts
289
279
  /**
290
280
  * Default resolver used by `@kubb/plugin-faker`. Decides the names and file
291
281
  * paths for every generated mock factory. Functions and files are prefixed
@@ -299,6 +289,5 @@ export declare const pluginFaker: import("kubb/kit").PluginFactory<PluginFaker>;
299
289
  * ```
300
290
  */
301
291
  export declare const resolverFaker: ResolverFaker;
302
- //#endregion
303
292
  export { type PluginFaker, type PrinterFakerFactory, type PrinterFakerNodes, type PrinterFakerOptions, type ResolverFaker, pluginFaker as default };
304
293
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Exclude, Group, Include, Output, OutputOptions, Override, PluginType, Resolver, ResolverPatch, ast } from "kubb/kit";
2
2
  import { KubbReactNode } from "kubb/jsx";
3
- //#region src/types.d.ts
4
3
  /**
5
4
  * Resolver for Faker that provides naming methods for mock functions.
6
5
  *
@@ -172,8 +171,6 @@ declare global {
172
171
  }
173
172
  }
174
173
  }
175
- //#endregion
176
- //#region src/printers/printerFaker.d.ts
177
174
  /**
178
175
  * Partial map of node-type overrides for the Faker printer. Each key is a
179
176
  * `SchemaType` (`'string'`, `'date'`, ...) and each handler returns the
@@ -231,8 +228,6 @@ type PrinterFakerFactory = ast.PrinterFactoryOptions<'faker', PrinterFakerOption
231
228
  * Handles circular references gracefully by emitting memoizing getters for cyclic properties.
232
229
  */
233
230
  export declare const printerFaker: (options: PrinterFakerOptions) => ast.Printer<PrinterFakerFactory>;
234
- //#endregion
235
- //#region src/components/Faker.d.ts
236
231
  type Props = {
237
232
  name: string;
238
233
  typeName: string;
@@ -241,10 +236,9 @@ type Props = {
241
236
  description?: string;
242
237
  canOverride: boolean;
243
238
  typeMode?: PluginFaker['resolvedOptions']['typeMode'];
239
+ keysToOmit?: Array<string> | null;
244
240
  };
245
- export declare function Faker({ node, description, name, typeName, printer, canOverride, typeMode }: Props): KubbReactNode;
246
- //#endregion
247
- //#region src/generators/fakerGenerator.d.ts
241
+ export declare function Faker({ node, description, name, typeName, printer, canOverride, typeMode, keysToOmit }: Props): KubbReactNode;
248
242
  /**
249
243
  * Built-in generator for `@kubb/plugin-faker`. Emits one `createX` factory
250
244
  * per schema in the spec plus per-operation request/response factories. Each
@@ -252,8 +246,6 @@ export declare function Faker({ node, description, name, typeName, printer, canO
252
246
  * `@kubb/plugin-ts`.
253
247
  */
254
248
  export declare const fakerGenerator: import("kubb/kit").Generator<PluginFaker, unknown>;
255
- //#endregion
256
- //#region src/plugin.d.ts
257
249
  /**
258
250
  * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and
259
251
  * cross-plugin dependency references.
@@ -284,8 +276,6 @@ export declare const pluginFakerName = "plugin-faker";
284
276
  * ```
285
277
  */
286
278
  export declare const pluginFaker: import("kubb/kit").PluginFactory<PluginFaker>;
287
- //#endregion
288
- //#region src/resolvers/resolverFaker.d.ts
289
279
  /**
290
280
  * Default resolver used by `@kubb/plugin-faker`. Decides the names and file
291
281
  * paths for every generated mock factory. Functions and files are prefixed
@@ -299,6 +289,5 @@ export declare const pluginFaker: import("kubb/kit").PluginFactory<PluginFaker>;
299
289
  * ```
300
290
  */
301
291
  export declare const resolverFaker: ResolverFaker;
302
- //#endregion
303
292
  export { type PluginFaker, type PrinterFakerFactory, type PrinterFakerNodes, type PrinterFakerOptions, type ResolverFaker, pluginFaker as default };
304
293
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,10 +1,9 @@
1
1
  import { posix } from "node:path";
2
- import { Diagnostics, Resolver, addGenerator, ast, containsCircularRef, createResolver, defineExtension, defineGenerator, setMacros, setResolver } from "kubb/kit";
2
+ import { Diagnostics, Resolver, addGenerator, ast, containsCircularRef, createResolver, defineExtension, defineGenerator, setMacros, setResolver, syncSchemaRef } from "kubb/kit";
3
3
  import { File, Function, jsxRenderer } from "kubb/jsx";
4
4
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
5
5
  import { buildParams, enumTypeName, pluginTsName } from "@kubb/plugin-ts";
6
- //#endregion
7
- //#region ../../internals/utils/src/casing.ts
6
+ // ../../internals/utils/src/casing.ts
8
7
  /**
9
8
  * Shared implementation for camelCase and PascalCase conversion.
10
9
  * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
@@ -41,8 +40,7 @@ function toCamelOrPascal(text, pascal) {
41
40
  function camelCase(text, { prefix = "", suffix = "" } = {}) {
42
41
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
43
42
  }
44
- //#endregion
45
- //#region ../../internals/utils/src/reserved.ts
43
+ // ../../internals/utils/src/reserved.ts
46
44
  /**
47
45
  * JavaScript and Java reserved words.
48
46
  * @link https://github.com/jonschlinkert/reserved/blob/master/index.js
@@ -50,6 +48,7 @@ function camelCase(text, { prefix = "", suffix = "" } = {}) {
50
48
  const reservedWords = /* @__PURE__ */ new Set([
51
49
  "abstract",
52
50
  "arguments",
51
+ "await",
53
52
  "boolean",
54
53
  "break",
55
54
  "byte",
@@ -180,8 +179,7 @@ function ensureValidVarName(name) {
180
179
  function isIdentifier(name) {
181
180
  return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
182
181
  }
183
- //#endregion
184
- //#region ../../internals/utils/src/strings.ts
182
+ // ../../internals/utils/src/strings.ts
185
183
  /**
186
184
  * Wraps a value in single quotes for emitting a single-quoted JavaScript string literal, escaping
187
185
  * any backslash or single quote in the content.
@@ -242,6 +240,34 @@ function stringify(value) {
242
240
  function jsDocEscape(input) {
243
241
  return `${input}`.replace(/^(\s*)@/gm, "$1\\@");
244
242
  }
243
+ const NEEDS_UNICODE = /(?<!\\)(?:\\\\)*\\[pPu]\{|[\u{10000}-\u{10FFFF}]/u;
244
+ const KEPT_ESCAPE = /[A-Za-z0-9^$\\.*+?()[\]{}|/]/;
245
+ /**
246
+ * Drops the backslash from escapes that the `u` flag rejects: an escaped punctuation character that is
247
+ * not a syntax character, and `\-` outside a class. Both match the same character without the backslash.
248
+ */
249
+ function dropIdentityEscapes(pattern) {
250
+ let inClass = false;
251
+ return pattern.replace(/\\(.)|[[\]]/gs, (match, escaped) => {
252
+ if (escaped === void 0) {
253
+ inClass = match === "[";
254
+ return match;
255
+ }
256
+ return KEPT_ESCAPE.test(escaped) || escaped === "-" && inClass ? match : escaped;
257
+ });
258
+ }
259
+ /**
260
+ * Builds the `RegExp` for a pattern, adding the `u` flag when it uses `\p{...}`, `\P{...}` or `\u{...}`, or
261
+ * holds a character outside the BMP. A pattern that is not valid under `u` keeps the flags it came with.
262
+ */
263
+ function toRegExp(pattern, flags) {
264
+ if (flags?.includes("u") || !NEEDS_UNICODE.test(pattern)) return new RegExp(pattern, flags);
265
+ try {
266
+ return new RegExp(dropIdentityEscapes(pattern), `${flags ?? ""}u`);
267
+ } catch {
268
+ return new RegExp(pattern, flags);
269
+ }
270
+ }
245
271
  /**
246
272
  * Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
247
273
  * Inline flags expressed as a `^(?im)` prefix are extracted and applied to the resulting expression.
@@ -258,13 +284,11 @@ function toRegExpString(text, func = "RegExp") {
258
284
  const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i);
259
285
  const replacementTarget = match?.[1] ?? "";
260
286
  const matchedFlags = match?.[2];
261
- const cleaned = raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, "");
262
- const { source, flags } = new RegExp(cleaned, matchedFlags);
287
+ const { source, flags } = toRegExp(raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, ""), matchedFlags);
263
288
  if (func === null) return `/${source}/${flags}`;
264
289
  return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
265
290
  }
266
- //#endregion
267
- //#region ../../internals/utils/src/codegen.ts
291
+ // ../../internals/utils/src/codegen.ts
268
292
  const INDENT = " ";
269
293
  /**
270
294
  * Indents every non-empty line of `text` by one indent level, leaving blank lines empty.
@@ -301,8 +325,7 @@ function buildObject(entries) {
301
325
  if (entries.length === 0) return "{}";
302
326
  return `{\n${entries.map((entry) => `${indentLines(entry)},`).join("\n")}\n}`;
303
327
  }
304
- //#endregion
305
- //#region ../../internals/utils/src/fs.ts
328
+ // ../../internals/utils/src/fs.ts
306
329
  function toSlash(p) {
307
330
  if (p.startsWith("\\\\?\\")) return p;
308
331
  return p.replaceAll("\\", "/");
@@ -344,8 +367,7 @@ function toFilePath(name, caseLast = camelCase) {
344
367
  const parts = name.split(/\.(?=[a-zA-Z])/);
345
368
  return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
346
369
  }
347
- //#endregion
348
- //#region src/utils.ts
370
+ // src/utils.ts
349
371
  /**
350
372
  * Returns the `@faker-js/faker` named export for a locale code.
351
373
  *
@@ -396,6 +418,18 @@ const NON_INLINABLE_RESPONSE_TYPES = /* @__PURE__ */ new Set([
396
418
  function canOverrideSchema(node) {
397
419
  return !NON_OVERRIDABLE_TYPES.has(node.type);
398
420
  }
421
+ /**
422
+ * Whether a schema can supply object properties when merging faker values.
423
+ */
424
+ function isObjectSchema(node, seen = /* @__PURE__ */ new Set()) {
425
+ const resolved = ast.resolveRef(node);
426
+ if (seen.has(resolved)) return false;
427
+ seen.add(resolved);
428
+ if (ast.narrowSchema(resolved, ast.schemaTypes.object) || ast.narrowSchema(resolved, ast.schemaTypes.ref)) return true;
429
+ const composition = ast.narrowSchema(resolved, ast.schemaTypes.intersection) ?? ast.narrowSchema(resolved, ast.schemaTypes.union);
430
+ if (!composition) return false;
431
+ return composition.type === ast.schemaTypes.intersection && !composition.members?.length || (composition.members ?? []).some((member) => isObjectSchema(member, seen));
432
+ }
399
433
  function shouldInlineSingleResponseSchema(schema) {
400
434
  return !NON_INLINABLE_RESPONSE_TYPES.has(schema.type);
401
435
  }
@@ -407,11 +441,16 @@ function buildResponseUnionSchema(node, resolver) {
407
441
  const responses = node.responses.filter((response) => response.content?.[0]?.schema);
408
442
  if (!responses.length) return null;
409
443
  if (responses.length === 1) {
410
- const schema = responses[0].content?.[0]?.schema;
444
+ const schemas = responses[0].content?.flatMap((content) => content.schema ? [content.schema] : []) ?? [];
445
+ const schema = schemas.length > 1 ? ast.factory.createSchema({
446
+ type: "union",
447
+ members: schemas
448
+ }) : schemas[0];
411
449
  if (schema && shouldInlineSingleResponseSchema(schema)) return schema;
412
450
  return ast.factory.createSchema({
413
451
  type: "ref",
414
- name: resolver.response.status(node, responses[0].statusCode)
452
+ name: resolver.response.status(node, responses[0].statusCode),
453
+ schema: responses[0].content?.length === 1 ? schema : void 0
415
454
  });
416
455
  }
417
456
  return ast.factory.createSchema({
@@ -480,7 +519,8 @@ function getScalarType(node, typeName) {
480
519
  * Determines the data type, return type, and whether it uses the type name.
481
520
  */
482
521
  function resolveFakerTypeUsage(node, typeName, canOverride) {
483
- const scalarType = SCALAR_TYPES.has(node.type) ? `${getScalarType(node, typeName)}${node.nullable ? " | null" : ""}` : void 0;
522
+ const resolvedNode = ast.resolveRef(node);
523
+ const scalarType = SCALAR_TYPES.has(resolvedNode.type) ? `${getScalarType(resolvedNode, typeName)}${node.nullable || resolvedNode.nullable ? " | null" : ""}` : void 0;
484
524
  const dataType = scalarType ?? `Partial<${typeName}>`;
485
525
  const returnType = scalarType ?? (canOverride ? typeName : null);
486
526
  return {
@@ -489,28 +529,27 @@ function resolveFakerTypeUsage(node, typeName, canOverride) {
489
529
  usesTypeName: canOverride && dataType.includes(typeName) || Boolean(returnType?.includes(typeName))
490
530
  };
491
531
  }
492
- //#endregion
493
- //#region src/components/Faker.tsx
494
- const OBJECT_TYPES = /* @__PURE__ */ new Set(["object", "intersection"]);
495
- function Faker({ node, description, name, typeName, printer, canOverride, typeMode = "inferred" }) {
532
+ // src/components/Faker.tsx
533
+ function Faker({ node, description, name, typeName, printer, canOverride, typeMode = "inferred", keysToOmit }) {
496
534
  const fakerText = printer.print(node) ?? "undefined";
497
535
  const isArray = node.type === "array";
498
- const isObject = OBJECT_TYPES.has(node.type);
536
+ const isObject = !!ast.narrowSchema(node, ast.schemaTypes.object) || node.type === ast.schemaTypes.intersection && isObjectSchema(node);
537
+ const isValueIntersection = node.type === ast.schemaTypes.intersection && !isObject;
499
538
  const isTuple = node.type === "tuple";
500
539
  const isScalar = SCALAR_TYPES.has(node.type);
501
540
  const isUnion = node.type === "union";
502
- const useObjectOverride = canOverride && isObject;
541
+ const useObjectOverride = canOverride && (isObject || !!keysToOmit?.length);
503
542
  const fakerTextWithOverride = (() => {
504
543
  if (canOverride && node.type === "tuple") return `data && data.length === ${node.items?.length ?? 0} && !data.includes(undefined) ? data : ${fakerText}`;
505
544
  if (canOverride && isArray) return `[\n ...${fakerText},\n ...(data || []).filter((item) => item !== undefined),\n]`;
506
- if (canOverride && (isScalar || isUnion)) return node.nullable ? `data !== undefined ? data : ${fakerText}` : `data ?? ${fakerText}`;
545
+ if (canOverride && (isScalar || isUnion || isValueIntersection)) return node.nullable ? `data !== undefined ? data : ${fakerText}` : `data ?? ${fakerText}`;
507
546
  return fakerText;
508
547
  })();
509
548
  const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
510
549
  if (!useObjectOverride) {
511
550
  const paramsSignature = `${/\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data"}?: ${dataType}`;
512
551
  const returnType = resolvedReturnType;
513
- const returnExpression = canOverride && !!returnType && (node.type === "ref" || isArray || isTuple || isUnion) ? `${isTuple || isUnion ? `(${fakerTextWithOverride})` : fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride;
552
+ const returnExpression = canOverride && !!returnType && (node.type === "ref" && !SCALAR_TYPES.has(ast.resolveRef(node).type) || isArray || isTuple || isUnion) ? `${isTuple || isUnion ? `(${fakerTextWithOverride})` : fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride;
514
553
  return /* @__PURE__ */ jsx(File.Source, {
515
554
  name,
516
555
  isExportable: true,
@@ -525,18 +564,21 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
525
564
  })
526
565
  });
527
566
  }
528
- const returnType = typeMode === "schema" ? typeName : "Omit<typeof defaultFakeData, keyof NoInfer<TData>> & NoInfer<TData>";
529
567
  const { cyclicSchemas, schemaName } = printer.options;
530
- const functionBody = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) => containsCircularRef(p.schema, {
568
+ const isCyclic = !!schemaName && !!cyclicSchemas?.has(schemaName);
569
+ const returnType = typeMode === "schema" ? typeName : `Omit<${isCyclic ? typeName : "typeof defaultFakeData"}, keyof NoInfer<TData>> & NoInfer<TData>`;
570
+ const hasGetters = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) => containsCircularRef(p.schema, {
531
571
  circularSchemas: cyclicSchemas,
532
572
  excludeName: schemaName
533
- })) ? `const defaultFakeData = ${fakerText}
573
+ }));
574
+ const declaration = `const ${keysToOmit?.length ? `{ ${keysToOmit.map((key, index) => `${objectKey(key)}: _omit${index}`).join(", ")}, ...defaultFakeData }` : "defaultFakeData"} = ${fakerText}`;
575
+ const functionBody = hasGetters ? `${declaration}
534
576
  if (data) {
535
577
  for (const [key, value] of Object.entries(data)) {
536
578
  Object.defineProperty(defaultFakeData, key, { value, configurable: true, writable: true, enumerable: true })
537
579
  }
538
580
  }
539
- return defaultFakeData as ${returnType}` : `const defaultFakeData = ${fakerText}
581
+ return defaultFakeData as ${returnType}` : `${declaration}
540
582
  return {
541
583
  ...defaultFakeData,
542
584
  ...(data || {}),
@@ -551,13 +593,12 @@ return {
551
593
  JSDoc: { comments: description ? [`@description ${jsDocEscape(description)}`] : [] },
552
594
  generics: typeMode === "schema" ? void 0 : `TData extends Partial<${typeName}> = object`,
553
595
  params: typeMode === "schema" ? `data?: Partial<${typeName}>` : "data?: TData",
554
- returnType: typeMode === "schema" ? typeName : void 0,
596
+ returnType: typeMode === "schema" || isCyclic ? returnType : void 0,
555
597
  children: functionBody
556
598
  })
557
599
  });
558
600
  }
559
- //#endregion
560
- //#region ../../internals/shared/src/operation.ts
601
+ // ../../internals/shared/src/operation.ts
561
602
  /**
562
603
  * Builds the `ResolverFileParams` every operation generator passes to
563
604
  * `resolver.file`: a file named `name`, tagged by the operation's first
@@ -672,17 +713,24 @@ function getOperationParameters(node) {
672
713
  operationParameterGroupsByNode.set(node, groups);
673
714
  return groups;
674
715
  }
675
- //#endregion
676
- //#region ../../internals/shared/src/resolver.ts
716
+ // ../../internals/shared/src/resolver.ts
677
717
  /**
678
- * Resolves a single operation parameter name with the
679
- * `<operationId> <in> <name>` template.
718
+ * Builds the allocation key for a declaration an operation owns. `scope` names which declaration
719
+ * it is, so two of them never share an allocation even when a custom resolver gives both the same
720
+ * name. Leave `scope` empty for the operation's own declaration.
680
721
  *
681
722
  * @example
682
- * `operationParamName.call(resolver, node, param) // → 'DeletePetPathPetId'`
723
+ * ```ts
724
+ * resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
725
+ * ```
683
726
  */
684
- function operationParamName(node, param) {
685
- return this.name(`${node.operationId} ${param.in} ${param.name}`);
727
+ function operationKey(node, ...scope) {
728
+ return [
729
+ "operation",
730
+ node.method,
731
+ node.path,
732
+ ...scope.map(String)
733
+ ];
686
734
  }
687
735
  /**
688
736
  * Builds the shared `param` namespace. Spread the result into `createResolver`
@@ -695,15 +743,33 @@ function operationParamName(node, param) {
695
743
  */
696
744
  function createOperationParamResolver() {
697
745
  return {
698
- name: operationParamName,
746
+ name(node, param) {
747
+ const name = this.name(`${node.operationId} ${param.in} ${param.name}`);
748
+ return this.resolveName({
749
+ key: operationKey(node, "param", "name", param.in, param.name),
750
+ name
751
+ });
752
+ },
699
753
  path(node) {
700
- return this.name(`${node.operationId} Path`);
754
+ const name = this.name(`${node.operationId} Path`);
755
+ return this.resolveName({
756
+ key: operationKey(node, "param", "path"),
757
+ name
758
+ });
701
759
  },
702
760
  query(node) {
703
- return this.name(`${node.operationId} Query`);
761
+ const name = this.name(`${node.operationId} Query`);
762
+ return this.resolveName({
763
+ key: operationKey(node, "param", "query"),
764
+ name
765
+ });
704
766
  },
705
767
  headers(node) {
706
- return this.name(`${node.operationId} Headers`);
768
+ const name = this.name(`${node.operationId} Headers`);
769
+ return this.resolveName({
770
+ key: operationKey(node, "param", "headers"),
771
+ name
772
+ });
707
773
  }
708
774
  };
709
775
  }
@@ -720,16 +786,32 @@ function createOperationParamResolver() {
720
786
  function createOperationResponseResolver() {
721
787
  return {
722
788
  status(node, statusCode) {
723
- return this.name(`${node.operationId} Status ${statusCode}`);
789
+ const name = this.name(`${node.operationId} Status ${statusCode}`);
790
+ return this.resolveName({
791
+ key: operationKey(node, "response", "status", statusCode),
792
+ name
793
+ });
724
794
  },
725
795
  body(node) {
726
- return this.name(`${node.operationId} Body`);
796
+ const name = this.name(`${node.operationId} Body`);
797
+ return this.resolveName({
798
+ key: operationKey(node, "response", "body"),
799
+ name
800
+ });
727
801
  },
728
802
  responses(node) {
729
- return this.name(`${node.operationId} Responses`);
803
+ const name = this.name(`${node.operationId} Responses`);
804
+ return this.resolveName({
805
+ key: operationKey(node, "response", "responses"),
806
+ name
807
+ });
730
808
  },
731
809
  response(node) {
732
- return this.name(`${node.operationId} Response`);
810
+ const name = this.name(`${node.operationId} Response`);
811
+ return this.resolveName({
812
+ key: operationKey(node, "response", "response"),
813
+ name
814
+ });
733
815
  }
734
816
  };
735
817
  }
@@ -747,8 +829,7 @@ function createCasedFile(caseLast) {
747
829
  return `${toFilePath(name, caseLast)}${extname}`;
748
830
  } };
749
831
  }
750
- //#endregion
751
- //#region ../../internals/shared/src/group.ts
832
+ // ../../internals/shared/src/group.ts
752
833
  /**
753
834
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
754
835
  * shared default naming so every plugin groups output consistently:
@@ -778,8 +859,7 @@ function createGroupConfig(group) {
778
859
  name: group.name ? group.name : defaultName
779
860
  };
780
861
  }
781
- //#endregion
782
- //#region ../../internals/shared/src/schemaTraversal.ts
862
+ // ../../internals/shared/src/schemaTraversal.ts
783
863
  /**
784
864
  * Maps each member of a union or intersection schema to its transformed output, pairing every
785
865
  * result with the original member.
@@ -800,8 +880,7 @@ function mapSchemaItems(node, transform) {
800
880
  output: transform(schema)
801
881
  }));
802
882
  }
803
- //#endregion
804
- //#region src/utils/imports.ts
883
+ // src/utils/imports.ts
805
884
  function escapeRegExp(value) {
806
885
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
807
886
  }
@@ -849,8 +928,7 @@ function aliasConflictingImports(imports, reservedNames) {
849
928
  function rewriteAliasedImports(text, aliases) {
850
929
  return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
851
930
  }
852
- //#endregion
853
- //#region src/printers/printerFaker.ts
931
+ // src/printers/printerFaker.ts
854
932
  /**
855
933
  * Formats that put a whole number inside a `type: 'string'` schema, the way ProtoJSON encodes
856
934
  * 64-bit integers, so the mock has to be digits rather than letters.
@@ -986,7 +1064,9 @@ const printerFaker = ast.createPrinter((options) => {
986
1064
  },
987
1065
  enum(node) {
988
1066
  const { typeName } = this.options;
989
- return `faker.helpers.arrayElement${typeName ? `<${typeName}>` : ""}([${ast.getSchemaLiteralValues(node).map(parseEnumValue).join(", ")}])`;
1067
+ const values = ast.getSchemaLiteralValues(node);
1068
+ if (values.length === 1 && values[0] !== null && typeof values[0] === "object") return JSON.stringify(values[0]);
1069
+ return `faker.helpers.arrayElement${typeName ? `<${typeName}>` : ""}([${values.map(parseEnumValue).join(", ")}])`;
990
1070
  },
991
1071
  union(node) {
992
1072
  const { discriminatorPropertyName } = node;
@@ -1010,9 +1090,14 @@ const printerFaker = ast.createPrinter((options) => {
1010
1090
  }).map(({ output }) => output).filter((item) => Boolean(item)).join(", ")}])`;
1011
1091
  },
1012
1092
  intersection(node) {
1013
- const items = mapSchemaMembers(node, (member) => printNested(member, { nestedInObject: true })).map(({ output }) => output).filter((item) => Boolean(item) && item !== "undefined");
1093
+ const objectMembers = (node.members ?? []).filter((member) => isObjectSchema(member));
1094
+ const members = objectMembers.length ? objectMembers : node.members;
1095
+ const items = mapSchemaMembers({
1096
+ ...node,
1097
+ members
1098
+ }, (member) => printNested(member, { nestedInObject: true })).map(({ output }) => output).filter((item) => Boolean(item) && item !== "undefined");
1014
1099
  if (items.length === 0) return "{}";
1015
- return items.length === 1 ? items[0] : `{...${items.join(", ...")}}`;
1100
+ return !objectMembers.length || items.length === 1 ? items.at(-1) : `{...${items.join(", ...")}}`;
1016
1101
  },
1017
1102
  array(node) {
1018
1103
  const items = mapSchemaItems(node, (member) => printNested(member, {
@@ -1035,7 +1120,13 @@ const printerFaker = ast.createPrinter((options) => {
1035
1120
  },
1036
1121
  object(node) {
1037
1122
  const cyclicSchemas = this.options.cyclicSchemas;
1038
- return buildObject((node.properties ?? []).map((property) => {
1123
+ const keySchema = node.propertyNames && syncSchemaRef(node.propertyNames);
1124
+ const valueSchema = node.additionalProperties;
1125
+ const recordProperties = keySchema?.type === "enum" && typeof valueSchema === "object" ? ast.getSchemaLiteralValues(keySchema).filter((key) => typeof key === "string" && !node.properties.some((property) => property.name === key)).map((name) => ast.factory.createProperty({
1126
+ name,
1127
+ schema: valueSchema
1128
+ })) : [];
1129
+ return buildObject([...node.properties, ...recordProperties].map((property) => {
1039
1130
  const value = printNested(property.schema, {
1040
1131
  typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : void 0,
1041
1132
  nestedInObject: true
@@ -1051,8 +1142,7 @@ const printerFaker = ast.createPrinter((options) => {
1051
1142
  overrides: options.nodes
1052
1143
  };
1053
1144
  });
1054
- //#endregion
1055
- //#region src/generators/fakerGenerator.tsx
1145
+ // src/generators/fakerGenerator.tsx
1056
1146
  /**
1057
1147
  * Built-in generator for `@kubb/plugin-faker`. Emits one `createX` factory
1058
1148
  * per schema in the spec plus per-operation request/response factories. Each
@@ -1224,7 +1314,7 @@ const fakerGenerator = defineGenerator({
1224
1314
  name: baseName,
1225
1315
  typeName: tsBaseName,
1226
1316
  description,
1227
- skipImportNames: []
1317
+ keysToOmit: primary.keysToOmit
1228
1318
  }];
1229
1319
  }
1230
1320
  const variants = resolveContentTypeVariants(entries, baseName);
@@ -1241,7 +1331,7 @@ const fakerGenerator = defineGenerator({
1241
1331
  name: variant.name,
1242
1332
  typeName: getPerContentTypeName(tsBaseName, variant.suffix),
1243
1333
  description,
1244
- skipImportNames: []
1334
+ keysToOmit: variant.keysToOmit
1245
1335
  })), {
1246
1336
  schema: unionSchema,
1247
1337
  name: baseName,
@@ -1291,8 +1381,15 @@ const fakerGenerator = defineGenerator({
1291
1381
  group: group ?? void 0
1292
1382
  }).filter((entry) => entry.path !== meta.file.path);
1293
1383
  }
1294
- function renderEntry({ schema, name, typeName, description, skipImportNames = [] }) {
1384
+ function renderEntry({ schema, name, typeName, description, keysToOmit, skipImportNames = [] }) {
1295
1385
  if (!schema) return null;
1386
+ if (schema.type === ast.schemaTypes.object && keysToOmit?.length) {
1387
+ schema = {
1388
+ ...schema,
1389
+ properties: schema.properties.filter((property) => !keysToOmit?.includes(property.name))
1390
+ };
1391
+ keysToOmit = void 0;
1392
+ }
1296
1393
  const canOverride = canOverrideSchema(schema);
1297
1394
  const printerInstance = printerFaker({
1298
1395
  resolver,
@@ -1301,7 +1398,8 @@ const fakerGenerator = defineGenerator({
1301
1398
  dateParser,
1302
1399
  regexGenerator,
1303
1400
  nodes: printer?.nodes,
1304
- cyclicSchemas
1401
+ cyclicSchemas,
1402
+ nestedInObject: !!keysToOmit?.length
1305
1403
  });
1306
1404
  const fakerText = printerInstance.print(schema) ?? "undefined";
1307
1405
  const { imports, aliases } = aliasConflictingImports(filterUsedImports(resolveMockImports(schema), fakerText, skipImportNames), localHelperNames);
@@ -1340,7 +1438,8 @@ const fakerGenerator = defineGenerator({
1340
1438
  print: () => rewrittenFakerText
1341
1439
  },
1342
1440
  canOverride,
1343
- typeMode
1441
+ typeMode,
1442
+ keysToOmit
1344
1443
  })
1345
1444
  ] });
1346
1445
  }
@@ -1397,17 +1496,14 @@ const fakerGenerator = defineGenerator({
1397
1496
  });
1398
1497
  }
1399
1498
  });
1400
- //#endregion
1401
- //#region kubb-extension.json
1499
+ // kubb-extension.json
1402
1500
  var compatibility = {
1403
- "kubb": ">=5.8.3",
1501
+ "kubb": ">=5.14.6",
1404
1502
  "node": ">=22.22"
1405
1503
  };
1406
- //#endregion
1407
- //#region package.json
1408
- var version = "5.2.1";
1409
- //#endregion
1410
- //#region src/resolvers/resolverFaker.ts
1504
+ // package.json
1505
+ var version = "5.2.2";
1506
+ // src/resolvers/resolverFaker.ts
1411
1507
  /**
1412
1508
  * Default resolver used by `@kubb/plugin-faker`. Decides the names and file
1413
1509
  * paths for every generated mock factory. Functions and files are prefixed
@@ -1429,8 +1525,7 @@ const resolverFaker = createResolver({
1429
1525
  param: createOperationParamResolver(),
1430
1526
  response: createOperationResponseResolver()
1431
1527
  });
1432
- //#endregion
1433
- //#region src/plugin.ts
1528
+ // src/plugin.ts
1434
1529
  /**
1435
1530
  * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and
1436
1531
  * cross-plugin dependency references.
@@ -1491,7 +1586,6 @@ const pluginFaker = defineExtension({
1491
1586
  };
1492
1587
  }
1493
1588
  });
1494
- //#endregion
1495
1589
  export { Faker, pluginFaker as default, pluginFaker, fakerGenerator, pluginFakerName, printerFaker, resolverFaker };
1496
1590
 
1497
1591
  //# sourceMappingURL=index.js.map