@kubb/plugin-faker 5.2.0 → 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
  *
@@ -397,10 +419,16 @@ function canOverrideSchema(node) {
397
419
  return !NON_OVERRIDABLE_TYPES.has(node.type);
398
420
  }
399
421
  /**
400
- * Follows a ref, including alias chains, to the schema it resolves to. Unresolved refs are returned as is.
422
+ * Whether a schema can supply object properties when merging faker values.
401
423
  */
402
- function resolveRefTarget(node) {
403
- return node.type === "ref" && node.schema ? resolveRefTarget(node.schema) : node;
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));
404
432
  }
405
433
  function shouldInlineSingleResponseSchema(schema) {
406
434
  return !NON_INLINABLE_RESPONSE_TYPES.has(schema.type);
@@ -413,11 +441,16 @@ function buildResponseUnionSchema(node, resolver) {
413
441
  const responses = node.responses.filter((response) => response.content?.[0]?.schema);
414
442
  if (!responses.length) return null;
415
443
  if (responses.length === 1) {
416
- 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];
417
449
  if (schema && shouldInlineSingleResponseSchema(schema)) return schema;
418
450
  return ast.factory.createSchema({
419
451
  type: "ref",
420
- 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
421
454
  });
422
455
  }
423
456
  return ast.factory.createSchema({
@@ -486,7 +519,8 @@ function getScalarType(node, typeName) {
486
519
  * Determines the data type, return type, and whether it uses the type name.
487
520
  */
488
521
  function resolveFakerTypeUsage(node, typeName, canOverride) {
489
- 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;
490
524
  const dataType = scalarType ?? `Partial<${typeName}>`;
491
525
  const returnType = scalarType ?? (canOverride ? typeName : null);
492
526
  return {
@@ -495,28 +529,27 @@ function resolveFakerTypeUsage(node, typeName, canOverride) {
495
529
  usesTypeName: canOverride && dataType.includes(typeName) || Boolean(returnType?.includes(typeName))
496
530
  };
497
531
  }
498
- //#endregion
499
- //#region src/components/Faker.tsx
500
- const OBJECT_TYPES = /* @__PURE__ */ new Set(["object", "intersection"]);
501
- 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 }) {
502
534
  const fakerText = printer.print(node) ?? "undefined";
503
535
  const isArray = node.type === "array";
504
- 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;
505
538
  const isTuple = node.type === "tuple";
506
539
  const isScalar = SCALAR_TYPES.has(node.type);
507
540
  const isUnion = node.type === "union";
508
- const useObjectOverride = canOverride && isObject;
541
+ const useObjectOverride = canOverride && (isObject || !!keysToOmit?.length);
509
542
  const fakerTextWithOverride = (() => {
510
543
  if (canOverride && node.type === "tuple") return `data && data.length === ${node.items?.length ?? 0} && !data.includes(undefined) ? data : ${fakerText}`;
511
544
  if (canOverride && isArray) return `[\n ...${fakerText},\n ...(data || []).filter((item) => item !== undefined),\n]`;
512
- 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}`;
513
546
  return fakerText;
514
547
  })();
515
548
  const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
516
549
  if (!useObjectOverride) {
517
550
  const paramsSignature = `${/\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data"}?: ${dataType}`;
518
551
  const returnType = resolvedReturnType;
519
- 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;
520
553
  return /* @__PURE__ */ jsx(File.Source, {
521
554
  name,
522
555
  isExportable: true,
@@ -531,18 +564,21 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
531
564
  })
532
565
  });
533
566
  }
534
- const returnType = typeMode === "schema" ? typeName : "Omit<typeof defaultFakeData, keyof NoInfer<TData>> & NoInfer<TData>";
535
567
  const { cyclicSchemas, schemaName } = printer.options;
536
- 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, {
537
571
  circularSchemas: cyclicSchemas,
538
572
  excludeName: schemaName
539
- })) ? `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}
540
576
  if (data) {
541
577
  for (const [key, value] of Object.entries(data)) {
542
578
  Object.defineProperty(defaultFakeData, key, { value, configurable: true, writable: true, enumerable: true })
543
579
  }
544
580
  }
545
- return defaultFakeData as ${returnType}` : `const defaultFakeData = ${fakerText}
581
+ return defaultFakeData as ${returnType}` : `${declaration}
546
582
  return {
547
583
  ...defaultFakeData,
548
584
  ...(data || {}),
@@ -557,13 +593,12 @@ return {
557
593
  JSDoc: { comments: description ? [`@description ${jsDocEscape(description)}`] : [] },
558
594
  generics: typeMode === "schema" ? void 0 : `TData extends Partial<${typeName}> = object`,
559
595
  params: typeMode === "schema" ? `data?: Partial<${typeName}>` : "data?: TData",
560
- returnType: typeMode === "schema" ? typeName : void 0,
596
+ returnType: typeMode === "schema" || isCyclic ? returnType : void 0,
561
597
  children: functionBody
562
598
  })
563
599
  });
564
600
  }
565
- //#endregion
566
- //#region ../../internals/shared/src/operation.ts
601
+ // ../../internals/shared/src/operation.ts
567
602
  /**
568
603
  * Builds the `ResolverFileParams` every operation generator passes to
569
604
  * `resolver.file`: a file named `name`, tagged by the operation's first
@@ -678,17 +713,24 @@ function getOperationParameters(node) {
678
713
  operationParameterGroupsByNode.set(node, groups);
679
714
  return groups;
680
715
  }
681
- //#endregion
682
- //#region ../../internals/shared/src/resolver.ts
716
+ // ../../internals/shared/src/resolver.ts
683
717
  /**
684
- * Resolves a single operation parameter name with the
685
- * `<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.
686
721
  *
687
722
  * @example
688
- * `operationParamName.call(resolver, node, param) // → 'DeletePetPathPetId'`
723
+ * ```ts
724
+ * resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
725
+ * ```
689
726
  */
690
- function operationParamName(node, param) {
691
- 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
+ ];
692
734
  }
693
735
  /**
694
736
  * Builds the shared `param` namespace. Spread the result into `createResolver`
@@ -701,15 +743,33 @@ function operationParamName(node, param) {
701
743
  */
702
744
  function createOperationParamResolver() {
703
745
  return {
704
- 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
+ },
705
753
  path(node) {
706
- 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
+ });
707
759
  },
708
760
  query(node) {
709
- 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
+ });
710
766
  },
711
767
  headers(node) {
712
- 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
+ });
713
773
  }
714
774
  };
715
775
  }
@@ -726,16 +786,32 @@ function createOperationParamResolver() {
726
786
  function createOperationResponseResolver() {
727
787
  return {
728
788
  status(node, statusCode) {
729
- 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
+ });
730
794
  },
731
795
  body(node) {
732
- 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
+ });
733
801
  },
734
802
  responses(node) {
735
- 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
+ });
736
808
  },
737
809
  response(node) {
738
- 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
+ });
739
815
  }
740
816
  };
741
817
  }
@@ -753,8 +829,7 @@ function createCasedFile(caseLast) {
753
829
  return `${toFilePath(name, caseLast)}${extname}`;
754
830
  } };
755
831
  }
756
- //#endregion
757
- //#region ../../internals/shared/src/group.ts
832
+ // ../../internals/shared/src/group.ts
758
833
  /**
759
834
  * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
760
835
  * shared default naming so every plugin groups output consistently:
@@ -784,8 +859,7 @@ function createGroupConfig(group) {
784
859
  name: group.name ? group.name : defaultName
785
860
  };
786
861
  }
787
- //#endregion
788
- //#region ../../internals/shared/src/schemaTraversal.ts
862
+ // ../../internals/shared/src/schemaTraversal.ts
789
863
  /**
790
864
  * Maps each member of a union or intersection schema to its transformed output, pairing every
791
865
  * result with the original member.
@@ -806,8 +880,7 @@ function mapSchemaItems(node, transform) {
806
880
  output: transform(schema)
807
881
  }));
808
882
  }
809
- //#endregion
810
- //#region src/utils/imports.ts
883
+ // src/utils/imports.ts
811
884
  function escapeRegExp(value) {
812
885
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
813
886
  }
@@ -855,8 +928,7 @@ function aliasConflictingImports(imports, reservedNames) {
855
928
  function rewriteAliasedImports(text, aliases) {
856
929
  return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
857
930
  }
858
- //#endregion
859
- //#region src/printers/printerFaker.ts
931
+ // src/printers/printerFaker.ts
860
932
  /**
861
933
  * Formats that put a whole number inside a `type: 'string'` schema, the way ProtoJSON encodes
862
934
  * 64-bit integers, so the mock has to be digits rather than letters.
@@ -987,12 +1059,14 @@ const printerFaker = ast.createPrinter((options) => {
987
1059
  });
988
1060
  if (this.options.schemaName && refName === this.options.schemaName) return this.options.typeName ? `undefined as unknown as ${this.options.typeName}` : "undefined as unknown";
989
1061
  const resolvedName = node.ref ? this.options.resolver.name(refName) : refName;
990
- if (!this.options.nestedInObject && canOverrideSchema(resolveRefTarget(node))) return `${resolvedName}(data)`;
1062
+ if (!this.options.nestedInObject && canOverrideSchema(ast.resolveRef(node))) return `${resolvedName}(data)`;
991
1063
  return `${resolvedName}()`;
992
1064
  },
993
1065
  enum(node) {
994
1066
  const { typeName } = this.options;
995
- 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(", ")}])`;
996
1070
  },
997
1071
  union(node) {
998
1072
  const { discriminatorPropertyName } = node;
@@ -1016,9 +1090,14 @@ const printerFaker = ast.createPrinter((options) => {
1016
1090
  }).map(({ output }) => output).filter((item) => Boolean(item)).join(", ")}])`;
1017
1091
  },
1018
1092
  intersection(node) {
1019
- 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");
1020
1099
  if (items.length === 0) return "{}";
1021
- return items.length === 1 ? items[0] : `{...${items.join(", ...")}}`;
1100
+ return !objectMembers.length || items.length === 1 ? items.at(-1) : `{...${items.join(", ...")}}`;
1022
1101
  },
1023
1102
  array(node) {
1024
1103
  const items = mapSchemaItems(node, (member) => printNested(member, {
@@ -1041,7 +1120,13 @@ const printerFaker = ast.createPrinter((options) => {
1041
1120
  },
1042
1121
  object(node) {
1043
1122
  const cyclicSchemas = this.options.cyclicSchemas;
1044
- 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) => {
1045
1130
  const value = printNested(property.schema, {
1046
1131
  typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : void 0,
1047
1132
  nestedInObject: true
@@ -1057,8 +1142,7 @@ const printerFaker = ast.createPrinter((options) => {
1057
1142
  overrides: options.nodes
1058
1143
  };
1059
1144
  });
1060
- //#endregion
1061
- //#region src/generators/fakerGenerator.tsx
1145
+ // src/generators/fakerGenerator.tsx
1062
1146
  /**
1063
1147
  * Built-in generator for `@kubb/plugin-faker`. Emits one `createX` factory
1064
1148
  * per schema in the spec plus per-operation request/response factories. Each
@@ -1230,7 +1314,7 @@ const fakerGenerator = defineGenerator({
1230
1314
  name: baseName,
1231
1315
  typeName: tsBaseName,
1232
1316
  description,
1233
- skipImportNames: []
1317
+ keysToOmit: primary.keysToOmit
1234
1318
  }];
1235
1319
  }
1236
1320
  const variants = resolveContentTypeVariants(entries, baseName);
@@ -1247,7 +1331,7 @@ const fakerGenerator = defineGenerator({
1247
1331
  name: variant.name,
1248
1332
  typeName: getPerContentTypeName(tsBaseName, variant.suffix),
1249
1333
  description,
1250
- skipImportNames: []
1334
+ keysToOmit: variant.keysToOmit
1251
1335
  })), {
1252
1336
  schema: unionSchema,
1253
1337
  name: baseName,
@@ -1297,8 +1381,15 @@ const fakerGenerator = defineGenerator({
1297
1381
  group: group ?? void 0
1298
1382
  }).filter((entry) => entry.path !== meta.file.path);
1299
1383
  }
1300
- function renderEntry({ schema, name, typeName, description, skipImportNames = [] }) {
1384
+ function renderEntry({ schema, name, typeName, description, keysToOmit, skipImportNames = [] }) {
1301
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
+ }
1302
1393
  const canOverride = canOverrideSchema(schema);
1303
1394
  const printerInstance = printerFaker({
1304
1395
  resolver,
@@ -1307,7 +1398,8 @@ const fakerGenerator = defineGenerator({
1307
1398
  dateParser,
1308
1399
  regexGenerator,
1309
1400
  nodes: printer?.nodes,
1310
- cyclicSchemas
1401
+ cyclicSchemas,
1402
+ nestedInObject: !!keysToOmit?.length
1311
1403
  });
1312
1404
  const fakerText = printerInstance.print(schema) ?? "undefined";
1313
1405
  const { imports, aliases } = aliasConflictingImports(filterUsedImports(resolveMockImports(schema), fakerText, skipImportNames), localHelperNames);
@@ -1346,7 +1438,8 @@ const fakerGenerator = defineGenerator({
1346
1438
  print: () => rewrittenFakerText
1347
1439
  },
1348
1440
  canOverride,
1349
- typeMode
1441
+ typeMode,
1442
+ keysToOmit
1350
1443
  })
1351
1444
  ] });
1352
1445
  }
@@ -1403,17 +1496,14 @@ const fakerGenerator = defineGenerator({
1403
1496
  });
1404
1497
  }
1405
1498
  });
1406
- //#endregion
1407
- //#region kubb-extension.json
1499
+ // kubb-extension.json
1408
1500
  var compatibility = {
1409
- "kubb": ">=5.8.3",
1501
+ "kubb": ">=5.14.6",
1410
1502
  "node": ">=22.22"
1411
1503
  };
1412
- //#endregion
1413
- //#region package.json
1414
- var version = "5.2.0";
1415
- //#endregion
1416
- //#region src/resolvers/resolverFaker.ts
1504
+ // package.json
1505
+ var version = "5.2.2";
1506
+ // src/resolvers/resolverFaker.ts
1417
1507
  /**
1418
1508
  * Default resolver used by `@kubb/plugin-faker`. Decides the names and file
1419
1509
  * paths for every generated mock factory. Functions and files are prefixed
@@ -1435,8 +1525,7 @@ const resolverFaker = createResolver({
1435
1525
  param: createOperationParamResolver(),
1436
1526
  response: createOperationResponseResolver()
1437
1527
  });
1438
- //#endregion
1439
- //#region src/plugin.ts
1528
+ // src/plugin.ts
1440
1529
  /**
1441
1530
  * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and
1442
1531
  * cross-plugin dependency references.
@@ -1497,7 +1586,6 @@ const pluginFaker = defineExtension({
1497
1586
  };
1498
1587
  }
1499
1588
  });
1500
- //#endregion
1501
1589
  export { Faker, pluginFaker as default, pluginFaker, fakerGenerator, pluginFakerName, printerFaker, resolverFaker };
1502
1590
 
1503
1591
  //# sourceMappingURL=index.js.map