@kubb/plugin-faker 5.0.0-beta.42 → 5.0.0-beta.56

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.
Files changed (35) hide show
  1. package/dist/{Faker-SBhWTdC7.d.ts → Faker-A5UuxwJj.d.ts} +2 -2
  2. package/dist/{Faker-DBPx_MVh.js → Faker-CHh0JtBG.js} +4 -46
  3. package/dist/Faker-CHh0JtBG.js.map +1 -0
  4. package/dist/{Faker-DRL0W5Lt.cjs → Faker-CcGjn5ZM.cjs} +5 -53
  5. package/dist/Faker-CcGjn5ZM.cjs.map +1 -0
  6. package/dist/components.cjs +1 -1
  7. package/dist/components.d.ts +1 -1
  8. package/dist/components.js +1 -1
  9. package/dist/{fakerGenerator-DNJ61yLj.js → fakerGenerator-DDNsdbH2.js} +16 -50
  10. package/dist/fakerGenerator-DDNsdbH2.js.map +1 -0
  11. package/dist/{fakerGenerator-CVOr0Pwm.cjs → fakerGenerator-DrwGWYwv.cjs} +17 -51
  12. package/dist/fakerGenerator-DrwGWYwv.cjs.map +1 -0
  13. package/dist/{fakerGenerator-Duc28_FK.d.ts → fakerGenerator-KKVr-CA2.d.ts} +2 -2
  14. package/dist/generators.cjs +1 -1
  15. package/dist/generators.d.ts +1 -1
  16. package/dist/generators.js +1 -1
  17. package/dist/index.cjs +45 -42
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +3 -3
  20. package/dist/index.js +45 -42
  21. package/dist/index.js.map +1 -1
  22. package/dist/{printerFaker-DXS861Q0.d.ts → printerFaker-CMCJT3FB.d.ts} +9 -13
  23. package/package.json +8 -15
  24. package/src/components/Faker.tsx +1 -1
  25. package/src/generators/fakerGenerator.tsx +12 -16
  26. package/src/plugin.ts +2 -2
  27. package/src/printers/printerFaker.ts +23 -25
  28. package/src/resolvers/resolverFaker.ts +8 -8
  29. package/src/types.ts +8 -12
  30. package/src/utils.ts +1 -1
  31. package/dist/Faker-DBPx_MVh.js.map +0 -1
  32. package/dist/Faker-DRL0W5Lt.cjs.map +0 -1
  33. package/dist/fakerGenerator-CVOr0Pwm.cjs.map +0 -1
  34. package/dist/fakerGenerator-DNJ61yLj.js.map +0 -1
  35. package/extension.yaml +0 -819
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import "./chunk-C0LytTxp.js";
2
- import { n as printerFaker, t as fakerGenerator } from "./fakerGenerator-DNJ61yLj.js";
3
- import { t as Faker } from "./Faker-DBPx_MVh.js";
4
- import path from "node:path";
5
- import { KubbDriver, definePlugin, defineResolver } from "@kubb/core";
2
+ import { t as Faker } from "./Faker-CHh0JtBG.js";
3
+ import { n as printerFaker, t as fakerGenerator } from "./fakerGenerator-DDNsdbH2.js";
4
+ import { definePlugin, defineResolver } from "@kubb/core";
6
5
  import { pluginTsName } from "@kubb/plugin-ts";
6
+ import path from "node:path";
7
7
  import { createHash } from "node:crypto";
8
8
  //#region ../../internals/utils/src/casing.ts
9
9
  /**
@@ -16,36 +16,45 @@ import { createHash } from "node:crypto";
16
16
  function toCamelOrPascal(text, pascal) {
17
17
  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) => {
18
18
  if (word.length > 1 && word === word.toUpperCase()) return word;
19
- if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
20
- return word.charAt(0).toUpperCase() + word.slice(1);
19
+ return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
21
20
  }).join("").replace(/[^a-zA-Z0-9]/g, "");
22
21
  }
23
22
  /**
24
- * Splits `text` on `.` and applies `transformPart` to each segment.
25
- * The last segment receives `isLast = true`, all earlier segments receive `false`.
26
- * Segments are joined with `/` to form a file path.
23
+ * Converts `text` to camelCase.
24
+ *
25
+ * @example Word boundaries
26
+ * `camelCase('hello-world') // 'helloWorld'`
27
27
  *
28
- * Only splits on dots followed by a letter so that version numbers
29
- * embedded in operationIds (e.g. `v2025.0`) are kept intact.
28
+ * @example With a prefix
29
+ * `camelCase('tag', { prefix: 'create' }) // 'createTag'`
30
30
  */
31
- function applyToFileParts(text, transformPart) {
32
- const parts = text.split(/\.(?=[a-zA-Z])/);
33
- return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
31
+ function camelCase(text, { prefix = "", suffix = "" } = {}) {
32
+ return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
34
33
  }
34
+ //#endregion
35
+ //#region ../../internals/utils/src/fs.ts
35
36
  /**
36
- * Converts `text` to camelCase.
37
- * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
37
+ * Builds a nested file path from a dotted name. Splits on dots that precede a letter
38
+ * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
39
+ * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
38
40
  *
39
- * @example
40
- * camelCase('hello-world') // 'helloWorld'
41
- * camelCase('pet.petId', { isFile: true }) // 'pet/petId'
41
+ * Empty segments are dropped before joining. They arise when the name starts with a dot
42
+ * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
43
+ * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
44
+ * absolute path, letting generated files escape the configured output directory.
45
+ *
46
+ * @example Nested path from a dotted name
47
+ * `toFilePath('pet.petId') // 'pet/petId'`
48
+ *
49
+ * @example PascalCase the final segment
50
+ * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
51
+ *
52
+ * @example Suffix applied to the final segment only
53
+ * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
42
54
  */
43
- function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
44
- if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
45
- prefix,
46
- suffix
47
- } : {}));
48
- return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
55
+ function toFilePath(name, caseLast = camelCase) {
56
+ const parts = name.split(/\.(?=[a-zA-Z])/);
57
+ return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
49
58
  }
50
59
  //#endregion
51
60
  //#region ../../internals/utils/src/reserved.ts
@@ -177,26 +186,24 @@ function ensureValidVarName(name) {
177
186
  * shared default naming so every plugin groups output consistently:
178
187
  *
179
188
  * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
180
- * - other groups use `${camelCase(group)}${suffix}` (e.g. `petController`).
189
+ * - other groups use the camelCased group (`pet store``petStore`).
181
190
  *
182
191
  * A user-provided `group.name` always wins over the default namer, so callers stay in
183
192
  * control of their output folders. Returns `null` when grouping is disabled, matching the
184
193
  * per-plugin convention.
185
194
  *
186
195
  * @param group - The user-supplied group option, or `undefined` to disable grouping.
187
- * @param options.suffix - Appended to non-`path` group names, e.g. `'Controller'` or `'Requests'`.
188
196
  *
189
197
  * @example
190
198
  * ```ts
191
- * createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-client, …
192
- * createGroupConfig(group, { suffix: 'Requests' }) // plugin-cypress, plugin-mcp
199
+ * createGroupConfig(group) // shared across every plugin
193
200
  * ```
194
201
  */
195
- function createGroupConfig(group, options) {
202
+ function createGroupConfig(group) {
196
203
  if (!group) return null;
197
204
  const defaultName = (ctx) => {
198
205
  if (group.type === "path") return `${ctx.group.split("/")[1]}`;
199
- return `${camelCase(ctx.group)}${options.suffix}`;
206
+ return camelCase(ctx.group);
200
207
  };
201
208
  return {
202
209
  ...group,
@@ -222,11 +229,8 @@ const resolverFaker = defineResolver(() => {
222
229
  name: "default",
223
230
  pluginName: "plugin-faker",
224
231
  default(name, type) {
225
- const resolvedName = camelCase(name, {
226
- isFile: type === "file",
227
- prefix: "create"
228
- });
229
- return type === "file" ? resolvedName : ensureValidVarName(resolvedName);
232
+ if (type === "file") return toFilePath(name, (part) => camelCase(part, { prefix: "create" }));
233
+ return ensureValidVarName(camelCase(name, { prefix: "create" }));
230
234
  },
231
235
  resolveName(name, type) {
232
236
  return this.default(name, type);
@@ -235,14 +239,13 @@ const resolverFaker = defineResolver(() => {
235
239
  return this.default(name, type);
236
240
  },
237
241
  resolveFile({ name, extname, tag, path: groupPath }, context) {
238
- const pathMode = KubbDriver.getMode(path.resolve(context.root, context.output.path));
239
- const baseName = `${pathMode === "single" ? "" : this.resolveName(name, "file")}${extname}`;
242
+ const inputBaseName = `${context.output.mode === "file" ? "" : this.resolveName(name, "file")}${extname}`;
240
243
  const filePath = this.resolvePath({
241
- baseName,
242
- pathMode,
244
+ baseName: inputBaseName,
243
245
  tag,
244
246
  path: groupPath
245
247
  }, context);
248
+ const baseName = path.basename(filePath);
246
249
  return {
247
250
  kind: "File",
248
251
  id: createHash("sha256").update(filePath).digest("hex"),
@@ -316,9 +319,9 @@ const pluginFakerName = "plugin-faker";
316
319
  const pluginFaker = definePlugin((options) => {
317
320
  const { output = {
318
321
  path: "mocks",
319
- barrelType: "named"
322
+ barrel: { type: "named" }
320
323
  }, seed, locale = "en", group, exclude = [], include, override = [], mapper = {}, dateParser = "faker", generators: userGenerators = [], regexGenerator = "faker", paramsCasing, printer, resolver: userResolver, transformer: userTransformer } = options;
321
- const groupConfig = createGroupConfig(group, { suffix: "Controller" });
324
+ const groupConfig = createGroupConfig(group);
322
325
  return {
323
326
  name: pluginFakerName,
324
327
  options,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/reserved.ts","../../../internals/shared/src/group.ts","../src/resolvers/resolverFaker.ts","../src/plugin.ts"],"sourcesContent":["type Options = {\n /**\n * When `true`, dot-separated segments are split on `.` and joined with `/` after casing.\n */\n isFile?: boolean\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const normalized = text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n\n const words = normalized.split(/[\\s\\-_./\\\\:]+/).filter(Boolean)\n\n return words\n .map((word, i) => {\n const allUpper = word.length > 1 && word === word.toUpperCase()\n if (allUpper) return word\n if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1)\n return word.charAt(0).toUpperCase() + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Splits `text` on `.` and applies `transformPart` to each segment.\n * The last segment receives `isLast = true`, all earlier segments receive `false`.\n * Segments are joined with `/` to form a file path.\n *\n * Only splits on dots followed by a letter so that version numbers\n * embedded in operationIds (e.g. `v2025.0`) are kept intact.\n */\nfunction applyToFileParts(text: string, transformPart: (part: string, isLast: boolean) => string): string {\n const parts = text.split(/\\.(?=[a-zA-Z])/)\n return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join('/')\n}\n\n/**\n * Converts `text` to camelCase.\n * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.\n *\n * @example\n * camelCase('hello-world') // 'helloWorld'\n * camelCase('pet.petId', { isFile: true }) // 'pet/petId'\n */\nexport function camelCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? { prefix, suffix } : {}))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.\n *\n * @example\n * pascalCase('hello-world') // 'HelloWorld'\n * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'\n */\nexport function pascalCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => (isLast ? pascalCase(part, { prefix, suffix }) : camelCase(part)))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example\n * snakeCase('helloWorld') // 'hello_world'\n * snakeCase('Hello-World') // 'hello_world'\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example\n * screamingSnakeCase('helloWorld') // 'HELLO_WORLD'\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n *\n * @example\n * ```ts\n * isValidVarName('status') // true\n * isValidVarName('class') // false (reserved word)\n * isValidVarName('42foo') // false (starts with digit)\n * ```\n */\nexport function isValidVarName(name: string): boolean {\n if (!name || reservedWords.has(name as 'valueOf')) {\n return false\n }\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n\n/**\n * Returns `name` when it's a syntactically valid JavaScript variable name,\n * otherwise prefixes it with `_` so the result is a valid identifier.\n *\n * Useful for sanitizing OpenAPI schema names or operation IDs that start with\n * a digit (e.g. `409`, `504AccountCancel`) before using them as exported\n * variable, type, or function names.\n *\n * @example\n * ```ts\n * ensureValidVarName('409') // '_409'\n * ensureValidVarName('504AccountCancel') // '_504AccountCancel'\n * ensureValidVarName('Pet') // 'Pet'\n * ensureValidVarName('class') // '_class'\n * ```\n */\nexport function ensureValidVarName(name: string): string {\n if (!name || isValidVarName(name)) {\n return name\n }\n return `_${name}`\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from '@kubb/core'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use `${camelCase(group)}${suffix}` (e.g. `petController`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n * @param options.suffix - Appended to non-`path` group names, e.g. `'Controller'` or `'Requests'`.\n *\n * @example\n * ```ts\n * createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-client, …\n * createGroupConfig(group, { suffix: 'Requests' }) // plugin-cypress, plugin-mcp\n * ```\n */\nexport function createGroupConfig(group: Group | undefined, options: { suffix: string }): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return `${camelCase(ctx.group)}${options.suffix}`\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { createHash } from 'node:crypto'\nimport path from 'node:path'\nimport { camelCase, ensureValidVarName } from '@internals/utils'\nimport { defineResolver, KubbDriver } from '@kubb/core'\nimport type { PluginFaker } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-faker`. Decides the names and file\n * paths for every generated mock factory. Functions and files are prefixed\n * with `create` so `Pet` becomes `createPet`.\n *\n * @example Resolve a factory name\n * ```ts\n * import { resolverFaker } from '@kubb/plugin-faker'\n *\n * resolverFaker.default('list pets', 'function') // 'createListPets'\n * ```\n */\nexport const resolverFaker = defineResolver<PluginFaker>(() => {\n return {\n name: 'default',\n pluginName: 'plugin-faker',\n default(name, type) {\n const resolvedName = camelCase(name, { isFile: type === 'file', prefix: 'create' })\n return type === 'file' ? resolvedName : ensureValidVarName(resolvedName)\n },\n resolveName(name, type) {\n return this.default(name, type)\n },\n resolvePathName(name, type) {\n return this.default(name, type)\n },\n resolveFile({ name, extname, tag, path: groupPath }, context) {\n const pathMode = KubbDriver.getMode(path.resolve(context.root, context.output.path))\n const baseName = `${pathMode === 'single' ? '' : this.resolveName(name, 'file')}${extname}` as `${string}.${string}`\n const filePath = this.resolvePath(\n {\n baseName,\n pathMode,\n tag,\n path: groupPath,\n },\n context,\n )\n\n return {\n kind: 'File',\n id: createHash('sha256').update(filePath).digest('hex'),\n name: path.basename(filePath, extname),\n path: filePath,\n baseName,\n extname,\n meta: { pluginName: this.pluginName },\n sources: [],\n imports: [],\n exports: [],\n }\n },\n resolveParamName(node, param) {\n return this.resolveName(`${node.operationId} ${param.in} ${param.name}`)\n },\n resolveDataName(node) {\n return this.resolveName(`${node.operationId} Data`)\n },\n resolveResponseStatusName(node, statusCode) {\n return this.resolveName(`${node.operationId} Status ${statusCode}`)\n },\n resolveResponseName(node) {\n return this.resolveName(`${node.operationId} Response`)\n },\n resolveResponsesName(node) {\n return this.resolveName(`${node.operationId} Responses`)\n },\n resolvePathParamsName(node, param) {\n return this.resolveParamName(node, param)\n },\n resolveQueryParamsName(node, param) {\n return this.resolveParamName(node, param)\n },\n resolveHeaderParamsName(node, param) {\n return this.resolveParamName(node, param)\n },\n }\n})\n","import { createGroupConfig } from '@internals/shared'\nimport { definePlugin } from '@kubb/core'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { fakerGenerator } from './generators/fakerGenerator.tsx'\nimport { resolverFaker } from './resolvers/resolverFaker.ts'\nimport type { PluginFaker } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginFakerName = 'plugin-faker' satisfies PluginFaker['name']\n\n/**\n * Generates one mock-data factory per OpenAPI schema using Faker.js. Call\n * `createPet()` to get a realistic `Pet` object. Useful for tests, Storybook,\n * and local development without a running backend.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginFaker } from '@kubb/plugin-faker'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginFaker({\n * output: { path: './mocks' },\n * seed: [100],\n * }),\n * ],\n * })\n * ```\n */\nexport const pluginFaker = definePlugin<PluginFaker>((options) => {\n const {\n output = { path: 'mocks', barrelType: 'named' },\n seed,\n locale = 'en',\n group,\n exclude = [],\n include,\n override = [],\n mapper = {},\n dateParser = 'faker',\n generators: userGenerators = [],\n regexGenerator = 'faker',\n paramsCasing,\n printer,\n resolver: userResolver,\n transformer: userTransformer,\n } = options\n\n const groupConfig = createGroupConfig(group, { suffix: 'Controller' })\n\n return {\n name: pluginFakerName,\n options,\n dependencies: [pluginTsName],\n hooks: {\n 'kubb:plugin:setup'(ctx) {\n ctx.setOptions({\n output,\n seed,\n locale,\n exclude,\n include,\n override,\n group: groupConfig,\n mapper,\n dateParser,\n regexGenerator,\n paramsCasing,\n printer,\n })\n ctx.setResolver(userResolver ? { ...resolverFaker, ...userResolver } : resolverFaker)\n if (userTransformer) {\n ctx.setTransformer(userTransformer)\n }\n ctx.addGenerator(fakerGenerator)\n for (const generator of userGenerators) {\n ctx.addGenerator(generator)\n }\n },\n },\n }\n})\n\nexport default pluginFaker\n"],"mappings":";;;;;;;;;;;;;;;AAsBA,SAAS,gBAAgB,MAAc,QAAyB;CAS9D,OARmB,KAChB,KAAK,EACL,QAAQ,qBAAqB,OAAO,EACpC,QAAQ,yBAAyB,OAAO,EACxC,QAAQ,gBAAgB,OAEJ,EAAE,MAAM,eAAe,EAAE,OAAO,OAE5C,EACR,KAAK,MAAM,MAAM;EAEhB,IADiB,KAAK,SAAS,KAAK,SAAS,KAAK,YAAY,GAChD,OAAO;EACrB,IAAI,MAAM,KAAK,CAAC,QAAQ,OAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;EAC1E,OAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;CACpD,CAAC,EACA,KAAK,EAAE,EACP,QAAQ,iBAAiB,EAAE;AAChC;;;;;;;;;AAUA,SAAS,iBAAiB,MAAc,eAAkE;CACxG,MAAM,QAAQ,KAAK,MAAM,gBAAgB;CACzC,OAAO,MAAM,KAAK,MAAM,MAAM,cAAc,MAAM,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,KAAK,GAAG;AACrF;;;;;;;;;AAUA,SAAgB,UAAU,MAAc,EAAE,QAAQ,SAAS,IAAI,SAAS,OAAgB,CAAC,GAAW;CAClG,IAAI,QACF,OAAO,iBAAiB,OAAO,MAAM,WAAW,UAAU,MAAM,SAAS;EAAE;EAAQ;CAAO,IAAI,CAAC,CAAC,CAAC;CAGnG,OAAO,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,KAAK;AAC7D;;;;;;;ACjEA,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAU;;;;;;;;;;;AAYV,SAAgB,eAAe,MAAuB;CACpD,IAAI,CAAC,QAAQ,cAAc,IAAI,IAAiB,GAC9C,OAAO;CAET,OAAO,6BAA6B,KAAK,IAAI;AAC/C;;;;;;;;;;;;;;;;;AAkBA,SAAgB,mBAAmB,MAAsB;CACvD,IAAI,CAAC,QAAQ,eAAe,IAAI,GAC9B,OAAO;CAET,OAAO,IAAI;AACb;;;;;;;;;;;;;;;;;;;;;;;ACvGA,SAAgB,kBAAkB,OAA0B,SAA2C;CACrG,IAAI,CAAC,OACH,OAAO;CAGT,MAAM,eAAe,QAAmC;EACtD,IAAI,MAAM,SAAS,QACjB,OAAO,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE;EAGjC,OAAO,GAAG,UAAU,IAAI,KAAK,IAAI,QAAQ;CAC3C;CAEA,OAAO;EACL,GAAG;EACH,MAAM,MAAM,OAAO,MAAM,OAAO;CAClC;AACF;;;;;;;;;;;;;;;ACtBA,MAAa,gBAAgB,qBAAkC;CAC7D,OAAO;EACL,MAAM;EACN,YAAY;EACZ,QAAQ,MAAM,MAAM;GAClB,MAAM,eAAe,UAAU,MAAM;IAAE,QAAQ,SAAS;IAAQ,QAAQ;GAAS,CAAC;GAClF,OAAO,SAAS,SAAS,eAAe,mBAAmB,YAAY;EACzE;EACA,YAAY,MAAM,MAAM;GACtB,OAAO,KAAK,QAAQ,MAAM,IAAI;EAChC;EACA,gBAAgB,MAAM,MAAM;GAC1B,OAAO,KAAK,QAAQ,MAAM,IAAI;EAChC;EACA,YAAY,EAAE,MAAM,SAAS,KAAK,MAAM,aAAa,SAAS;GAC5D,MAAM,WAAW,WAAW,QAAQ,KAAK,QAAQ,QAAQ,MAAM,QAAQ,OAAO,IAAI,CAAC;GACnF,MAAM,WAAW,GAAG,aAAa,WAAW,KAAK,KAAK,YAAY,MAAM,MAAM,IAAI;GAClF,MAAM,WAAW,KAAK,YACpB;IACE;IACA;IACA;IACA,MAAM;GACR,GACA,OACF;GAEA,OAAO;IACL,MAAM;IACN,IAAI,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;IACtD,MAAM,KAAK,SAAS,UAAU,OAAO;IACrC,MAAM;IACN;IACA;IACA,MAAM,EAAE,YAAY,KAAK,WAAW;IACpC,SAAS,CAAC;IACV,SAAS,CAAC;IACV,SAAS,CAAC;GACZ;EACF;EACA,iBAAiB,MAAM,OAAO;GAC5B,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,GAAG,MAAM,GAAG,GAAG,MAAM,MAAM;EACzE;EACA,gBAAgB,MAAM;GACpB,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,MAAM;EACpD;EACA,0BAA0B,MAAM,YAAY;GAC1C,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,UAAU,YAAY;EACpE;EACA,oBAAoB,MAAM;GACxB,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,UAAU;EACxD;EACA,qBAAqB,MAAM;GACzB,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,WAAW;EACzD;EACA,sBAAsB,MAAM,OAAO;GACjC,OAAO,KAAK,iBAAiB,MAAM,KAAK;EAC1C;EACA,uBAAuB,MAAM,OAAO;GAClC,OAAO,KAAK,iBAAiB,MAAM,KAAK;EAC1C;EACA,wBAAwB,MAAM,OAAO;GACnC,OAAO,KAAK,iBAAiB,MAAM,KAAK;EAC1C;CACF;AACF,CAAC;;;;;;;ACxED,MAAa,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;AA0B/B,MAAa,cAAc,cAA2B,YAAY;CAChE,MAAM,EACJ,SAAS;EAAE,MAAM;EAAS,YAAY;CAAQ,GAC9C,MACA,SAAS,MACT,OACA,UAAU,CAAC,GACX,SACA,WAAW,CAAC,GACZ,SAAS,CAAC,GACV,aAAa,SACb,YAAY,iBAAiB,CAAC,GAC9B,iBAAiB,SACjB,cACA,SACA,UAAU,cACV,aAAa,oBACX;CAEJ,MAAM,cAAc,kBAAkB,OAAO,EAAE,QAAQ,aAAa,CAAC;CAErE,OAAO;EACL,MAAM;EACN;EACA,cAAc,CAAC,YAAY;EAC3B,OAAO,EACL,oBAAoB,KAAK;GACvB,IAAI,WAAW;IACb;IACA;IACA;IACA;IACA;IACA;IACA,OAAO;IACP;IACA;IACA;IACA;IACA;GACF,CAAC;GACD,IAAI,YAAY,eAAe;IAAE,GAAG;IAAe,GAAG;GAAa,IAAI,aAAa;GACpF,IAAI,iBACF,IAAI,eAAe,eAAe;GAEpC,IAAI,aAAa,cAAc;GAC/B,KAAK,MAAM,aAAa,gBACtB,IAAI,aAAa,SAAS;EAE9B,EACF;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/fs.ts","../../../internals/utils/src/reserved.ts","../../../internals/shared/src/group.ts","../src/resolvers/resolverFaker.ts","../src/plugin.ts"],"sourcesContent":["type Options = {\n /**\n * Text prepended before casing is applied.\n */\n prefix?: string\n /**\n * Text appended before casing is applied.\n */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n return text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n .split(/[\\s\\-_./\\\\:]+/)\n .filter(Boolean)\n .map((word, i) => {\n if (word.length > 1 && word === word.toUpperCase()) return word\n const head = i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()\n return head + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Converts `text` to camelCase.\n *\n * @example Word boundaries\n * `camelCase('hello-world') // 'helloWorld'`\n *\n * @example With a prefix\n * `camelCase('tag', { prefix: 'create' }) // 'createTag'`\n */\nexport function camelCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n *\n * @example Word boundaries\n * `pascalCase('hello-world') // 'HelloWorld'`\n *\n * @example With a suffix\n * `pascalCase('tag', { suffix: 'schema' }) // 'TagSchema'`\n */\nexport function pascalCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example From camelCase\n * `snakeCase('helloWorld') // 'hello_world'`\n *\n * @example From mixed separators\n * `snakeCase('Hello-World') // 'hello_world'`\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example From camelCase\n * `screamingSnakeCase('helloWorld') // 'HELLO_WORLD'`\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Options = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","import { posix } from 'node:path'\nimport { camelCase } from './casing.ts'\n\nfunction toSlash(p: string): string {\n if (p.startsWith('\\\\\\\\?\\\\')) return p\n return p.replaceAll('\\\\', '/')\n}\n\n/**\n * Returns the relative path from `rootDir` to `filePath`, always using forward slashes\n * and prefixed with `./` when not already traversing upward.\n *\n * @example\n * ```ts\n * getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'\n * getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'\n * ```\n */\nexport function getRelativePath(rootDir?: string | null, filePath?: string | null): string {\n if (!rootDir || !filePath) {\n throw new Error(`Root and file should be filled in when retrieving the relativePath, ${rootDir || ''} ${filePath || ''}`)\n }\n\n const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath))\n\n return relativePath.startsWith('../') ? relativePath : `./${relativePath}`\n}\n\n/**\n * Builds a nested file path from a dotted name. Splits on dots that precede a letter\n * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases\n * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.\n *\n * Empty segments are dropped before joining. They arise when the name starts with a dot\n * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to\n * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an\n * absolute path, letting generated files escape the configured output directory.\n *\n * @example Nested path from a dotted name\n * `toFilePath('pet.petId') // 'pet/petId'`\n *\n * @example PascalCase the final segment\n * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`\n *\n * @example Suffix applied to the final segment only\n * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`\n */\nexport function toFilePath(name: string, caseLast: (part: string) => string = camelCase): string {\n const parts = name.split(/\\.(?=[a-zA-Z])/)\n return parts\n .map((part, i) => (i === parts.length - 1 ? caseLast(part) : camelCase(part)))\n .filter(Boolean)\n .join('/')\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n *\n * @example\n * ```ts\n * isValidVarName('status') // true\n * isValidVarName('class') // false (reserved word)\n * isValidVarName('42foo') // false (starts with digit)\n * ```\n */\nexport function isValidVarName(name: string): boolean {\n if (!name || reservedWords.has(name as 'valueOf')) {\n return false\n }\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n}\n\n/**\n * Returns `name` when it's a syntactically valid JavaScript variable name,\n * otherwise prefixes it with `_` so the result is a valid identifier.\n *\n * Useful for sanitizing OpenAPI schema names or operation IDs that start with\n * a digit (e.g. `409`, `504AccountCancel`) before using them as exported\n * variable, type, or function names.\n *\n * @example\n * ```ts\n * ensureValidVarName('409') // '_409'\n * ensureValidVarName('504AccountCancel') // '_504AccountCancel'\n * ensureValidVarName('Pet') // 'Pet'\n * ensureValidVarName('class') // '_class'\n * ```\n */\nexport function ensureValidVarName(name: string): string {\n if (!name || isValidVarName(name)) {\n return name\n }\n return `_${name}`\n}\n","import { camelCase } from '@internals/utils'\nimport type { Group } from '@kubb/core'\n\n/**\n * Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the\n * shared default naming so every plugin groups output consistently:\n *\n * - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).\n * - other groups use the camelCased group (`pet store` → `petStore`).\n *\n * A user-provided `group.name` always wins over the default namer, so callers stay in\n * control of their output folders. Returns `null` when grouping is disabled, matching the\n * per-plugin convention.\n *\n * @param group - The user-supplied group option, or `undefined` to disable grouping.\n *\n * @example\n * ```ts\n * createGroupConfig(group) // shared across every plugin\n * ```\n */\nexport function createGroupConfig(group: Group | undefined): Group | null {\n if (!group) {\n return null\n }\n\n const defaultName = (ctx: { group: string }): string => {\n if (group.type === 'path') {\n return `${ctx.group.split('/')[1]}`\n }\n\n return camelCase(ctx.group)\n }\n\n return {\n ...group,\n name: group.name ? group.name : defaultName,\n } satisfies Group\n}\n","import { createHash } from 'node:crypto'\nimport path from 'node:path'\nimport { camelCase, ensureValidVarName, toFilePath } from '@internals/utils'\nimport { defineResolver } from '@kubb/core'\nimport type { PluginFaker } from '../types.ts'\n\n/**\n * Default resolver used by `@kubb/plugin-faker`. Decides the names and file\n * paths for every generated mock factory. Functions and files are prefixed\n * with `create` so `Pet` becomes `createPet`.\n *\n * @example Resolve a factory name\n * ```ts\n * import { resolverFaker } from '@kubb/plugin-faker'\n *\n * resolverFaker.default('list pets', 'function') // 'createListPets'\n * ```\n */\nexport const resolverFaker = defineResolver<PluginFaker>(() => {\n return {\n name: 'default',\n pluginName: 'plugin-faker',\n default(name, type) {\n if (type === 'file') return toFilePath(name, (part) => camelCase(part, { prefix: 'create' }))\n return ensureValidVarName(camelCase(name, { prefix: 'create' }))\n },\n resolveName(name, type) {\n return this.default(name, type)\n },\n resolvePathName(name, type) {\n return this.default(name, type)\n },\n resolveFile({ name, extname, tag, path: groupPath }, context) {\n const resolvedName = context.output.mode === 'file' ? '' : this.resolveName(name, 'file')\n const inputBaseName = `${resolvedName}${extname}` as `${string}.${string}`\n const filePath = this.resolvePath(\n {\n baseName: inputBaseName,\n tag,\n path: groupPath,\n },\n context,\n )\n const baseName = path.basename(filePath) as `${string}.${string}`\n\n return {\n kind: 'File',\n id: createHash('sha256').update(filePath).digest('hex'),\n name: path.basename(filePath, extname),\n path: filePath,\n baseName,\n extname,\n meta: { pluginName: this.pluginName },\n sources: [],\n imports: [],\n exports: [],\n }\n },\n resolveParamName(node, param) {\n return this.resolveName(`${node.operationId} ${param.in} ${param.name}`)\n },\n resolveDataName(node) {\n return this.resolveName(`${node.operationId} Data`)\n },\n resolveResponseStatusName(node, statusCode) {\n return this.resolveName(`${node.operationId} Status ${statusCode}`)\n },\n resolveResponseName(node) {\n return this.resolveName(`${node.operationId} Response`)\n },\n resolveResponsesName(node) {\n return this.resolveName(`${node.operationId} Responses`)\n },\n resolvePathParamsName(node, param) {\n return this.resolveParamName(node, param)\n },\n resolveQueryParamsName(node, param) {\n return this.resolveParamName(node, param)\n },\n resolveHeaderParamsName(node, param) {\n return this.resolveParamName(node, param)\n },\n }\n})\n","import { createGroupConfig } from '@internals/shared'\nimport { definePlugin } from '@kubb/core'\nimport { pluginTsName } from '@kubb/plugin-ts'\nimport { fakerGenerator } from './generators/fakerGenerator.tsx'\nimport { resolverFaker } from './resolvers/resolverFaker.ts'\nimport type { PluginFaker } from './types.ts'\n\n/**\n * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and\n * cross-plugin dependency references.\n */\nexport const pluginFakerName = 'plugin-faker' satisfies PluginFaker['name']\n\n/**\n * Generates one mock-data factory per OpenAPI schema using Faker.js. Call\n * `createPet()` to get a realistic `Pet` object. Useful for tests, Storybook,\n * and local development without a running backend.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { pluginTs } from '@kubb/plugin-ts'\n * import { pluginFaker } from '@kubb/plugin-faker'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [\n * pluginTs(),\n * pluginFaker({\n * output: { path: './mocks' },\n * seed: [100],\n * }),\n * ],\n * })\n * ```\n */\nexport const pluginFaker = definePlugin<PluginFaker>((options) => {\n const {\n output = { path: 'mocks', barrel: { type: 'named' } },\n seed,\n locale = 'en',\n group,\n exclude = [],\n include,\n override = [],\n mapper = {},\n dateParser = 'faker',\n generators: userGenerators = [],\n regexGenerator = 'faker',\n paramsCasing,\n printer,\n resolver: userResolver,\n transformer: userTransformer,\n } = options\n\n const groupConfig = createGroupConfig(group)\n\n return {\n name: pluginFakerName,\n options,\n dependencies: [pluginTsName],\n hooks: {\n 'kubb:plugin:setup'(ctx) {\n ctx.setOptions({\n output,\n seed,\n locale,\n exclude,\n include,\n override,\n group: groupConfig,\n mapper,\n dateParser,\n regexGenerator,\n paramsCasing,\n printer,\n })\n ctx.setResolver(userResolver ? { ...resolverFaker, ...userResolver } : resolverFaker)\n if (userTransformer) {\n ctx.setTransformer(userTransformer)\n }\n ctx.addGenerator(fakerGenerator)\n for (const generator of userGenerators) {\n ctx.addGenerator(generator)\n }\n },\n },\n }\n})\n\nexport default pluginFaker\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,SAAS,gBAAgB,MAAc,QAAyB;CAC9D,OAAO,KACJ,KAAK,CAAC,CACN,QAAQ,qBAAqB,OAAO,CAAC,CACrC,QAAQ,yBAAyB,OAAO,CAAC,CACzC,QAAQ,gBAAgB,OAAO,CAAC,CAChC,MAAM,eAAe,CAAC,CACtB,OAAO,OAAO,CAAC,CACf,KAAK,MAAM,MAAM;EAChB,IAAI,KAAK,SAAS,KAAK,SAAS,KAAK,YAAY,GAAG,OAAO;EAE3D,QADa,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,KAC9E,KAAK,MAAM,CAAC;CAC5B,CAAC,CAAC,CACD,KAAK,EAAE,CAAC,CACR,QAAQ,iBAAiB,EAAE;AAChC;;;;;;;;;;AAWA,SAAgB,UAAU,MAAc,EAAE,SAAS,IAAI,SAAS,OAAgB,CAAC,GAAW;CAC1F,OAAO,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,UAAU,KAAK;AAC7D;;;;;;;;;;;;;;;;;;;;;;ACCA,SAAgB,WAAW,MAAc,WAAqC,WAAmB;CAC/F,MAAM,QAAQ,KAAK,MAAM,gBAAgB;CACzC,OAAO,MACJ,KAAK,MAAM,MAAO,MAAM,MAAM,SAAS,IAAI,SAAS,IAAI,IAAI,UAAU,IAAI,CAAE,CAAC,CAC7E,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;AACb;;;;;;;ACjDA,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAU;;;;;;;;;;;AAYV,SAAgB,eAAe,MAAuB;CACpD,IAAI,CAAC,QAAQ,cAAc,IAAI,IAAiB,GAC9C,OAAO;CAET,OAAO,6BAA6B,KAAK,IAAI;AAC/C;;;;;;;;;;;;;;;;;AAkBA,SAAgB,mBAAmB,MAAsB;CACvD,IAAI,CAAC,QAAQ,eAAe,IAAI,GAC9B,OAAO;CAET,OAAO,IAAI;AACb;;;;;;;;;;;;;;;;;;;;;ACzGA,SAAgB,kBAAkB,OAAwC;CACxE,IAAI,CAAC,OACH,OAAO;CAGT,MAAM,eAAe,QAAmC;EACtD,IAAI,MAAM,SAAS,QACjB,OAAO,GAAG,IAAI,MAAM,MAAM,GAAG,CAAC,CAAC;EAGjC,OAAO,UAAU,IAAI,KAAK;CAC5B;CAEA,OAAO;EACL,GAAG;EACH,MAAM,MAAM,OAAO,MAAM,OAAO;CAClC;AACF;;;;;;;;;;;;;;;ACpBA,MAAa,gBAAgB,qBAAkC;CAC7D,OAAO;EACL,MAAM;EACN,YAAY;EACZ,QAAQ,MAAM,MAAM;GAClB,IAAI,SAAS,QAAQ,OAAO,WAAW,OAAO,SAAS,UAAU,MAAM,EAAE,QAAQ,SAAS,CAAC,CAAC;GAC5F,OAAO,mBAAmB,UAAU,MAAM,EAAE,QAAQ,SAAS,CAAC,CAAC;EACjE;EACA,YAAY,MAAM,MAAM;GACtB,OAAO,KAAK,QAAQ,MAAM,IAAI;EAChC;EACA,gBAAgB,MAAM,MAAM;GAC1B,OAAO,KAAK,QAAQ,MAAM,IAAI;EAChC;EACA,YAAY,EAAE,MAAM,SAAS,KAAK,MAAM,aAAa,SAAS;GAE5D,MAAM,gBAAgB,GADD,QAAQ,OAAO,SAAS,SAAS,KAAK,KAAK,YAAY,MAAM,MAAM,IAChD;GACxC,MAAM,WAAW,KAAK,YACpB;IACE,UAAU;IACV;IACA,MAAM;GACR,GACA,OACF;GACA,MAAM,WAAW,KAAK,SAAS,QAAQ;GAEvC,OAAO;IACL,MAAM;IACN,IAAI,WAAW,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC,CAAC,OAAO,KAAK;IACtD,MAAM,KAAK,SAAS,UAAU,OAAO;IACrC,MAAM;IACN;IACA;IACA,MAAM,EAAE,YAAY,KAAK,WAAW;IACpC,SAAS,CAAC;IACV,SAAS,CAAC;IACV,SAAS,CAAC;GACZ;EACF;EACA,iBAAiB,MAAM,OAAO;GAC5B,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,GAAG,MAAM,GAAG,GAAG,MAAM,MAAM;EACzE;EACA,gBAAgB,MAAM;GACpB,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,MAAM;EACpD;EACA,0BAA0B,MAAM,YAAY;GAC1C,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,UAAU,YAAY;EACpE;EACA,oBAAoB,MAAM;GACxB,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,UAAU;EACxD;EACA,qBAAqB,MAAM;GACzB,OAAO,KAAK,YAAY,GAAG,KAAK,YAAY,WAAW;EACzD;EACA,sBAAsB,MAAM,OAAO;GACjC,OAAO,KAAK,iBAAiB,MAAM,KAAK;EAC1C;EACA,uBAAuB,MAAM,OAAO;GAClC,OAAO,KAAK,iBAAiB,MAAM,KAAK;EAC1C;EACA,wBAAwB,MAAM,OAAO;GACnC,OAAO,KAAK,iBAAiB,MAAM,KAAK;EAC1C;CACF;AACF,CAAC;;;;;;;ACxED,MAAa,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;AA0B/B,MAAa,cAAc,cAA2B,YAAY;CAChE,MAAM,EACJ,SAAS;EAAE,MAAM;EAAS,QAAQ,EAAE,MAAM,QAAQ;CAAE,GACpD,MACA,SAAS,MACT,OACA,UAAU,CAAC,GACX,SACA,WAAW,CAAC,GACZ,SAAS,CAAC,GACV,aAAa,SACb,YAAY,iBAAiB,CAAC,GAC9B,iBAAiB,SACjB,cACA,SACA,UAAU,cACV,aAAa,oBACX;CAEJ,MAAM,cAAc,kBAAkB,KAAK;CAE3C,OAAO;EACL,MAAM;EACN;EACA,cAAc,CAAC,YAAY;EAC3B,OAAO,EACL,oBAAoB,KAAK;GACvB,IAAI,WAAW;IACb;IACA;IACA;IACA;IACA;IACA;IACA,OAAO;IACP;IACA;IACA;IACA;IACA;GACF,CAAC;GACD,IAAI,YAAY,eAAe;IAAE,GAAG;IAAe,GAAG;GAAa,IAAI,aAAa;GACpF,IAAI,iBACF,IAAI,eAAe,eAAe;GAEpC,IAAI,aAAa,cAAc;GAC/B,KAAK,MAAM,aAAa,gBACtB,IAAI,aAAa,SAAS;EAE9B,EACF;CACF;AACF,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { t as __name } from "./chunk-C0LytTxp.js";
2
- import { Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver, ast } from "@kubb/core";
2
+ import { Exclude, Generator, Group, Include, Output, OutputOptions, Override, PluginFactoryOptions, Resolver, ast } from "@kubb/core";
3
3
 
4
4
  //#region src/types.d.ts
5
5
  /**
@@ -70,17 +70,13 @@ type ResolverFaker = Resolver & ast.OperationParamsResolver & {
70
70
  */
71
71
  resolveHeaderParamsName(this: ResolverFaker, node: ast.OperationNode, param: ast.ParameterNode): string;
72
72
  };
73
- type Options = {
74
- /**
75
- * Where the generated mock factories are written and how they are exported.
76
- *
77
- * @default { path: 'mocks', barrel: { type: 'named' } }
78
- */
79
- output?: Output;
80
- /**
81
- * Split generated files into subfolders based on the operation's tag.
82
- */
83
- group?: Group;
73
+ /**
74
+ * Where the generated mock factories are written and how they are exported, plus the optional
75
+ * `group` strategy. The `group` option organizes `output.mode: 'directory'` output into per-tag or per-path subdirectories.
76
+ *
77
+ * @default { path: 'mocks', barrel: { type: 'named' } }
78
+ */
79
+ type Options = OutputOptions & {
84
80
  /**
85
81
  * Skip operations matching at least one entry in the list.
86
82
  */
@@ -240,4 +236,4 @@ type PrinterFakerFactory = ast.PrinterFactoryOptions<'faker', PrinterFakerOption
240
236
  declare const printerFaker: (options: PrinterFakerOptions) => ast.Printer<PrinterFakerFactory>;
241
237
  //#endregion
242
238
  export { Options as a, printerFaker as i, PrinterFakerNodes as n, PluginFaker as o, PrinterFakerOptions as r, ResolverFaker as s, PrinterFakerFactory as t };
243
- //# sourceMappingURL=printerFaker-DXS861Q0.d.ts.map
239
+ //# sourceMappingURL=printerFaker-CMCJT3FB.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-faker",
3
- "version": "5.0.0-beta.42",
3
+ "version": "5.0.0-beta.56",
4
4
  "description": "Generate Faker.js mock data factories from your OpenAPI schemas. Produces realistic seed data, test fixtures, and datasets for development and testing.",
5
5
  "keywords": [
6
6
  "code-generation",
@@ -26,7 +26,6 @@
26
26
  "files": [
27
27
  "src",
28
28
  "dist",
29
- "extension.yaml",
30
29
  "!/**/**.test.**",
31
30
  "!/**/__tests__/**",
32
31
  "!/**/__snapshots__/**"
@@ -66,30 +65,24 @@
66
65
  "registry": "https://registry.npmjs.org/"
67
66
  },
68
67
  "dependencies": {
69
- "@kubb/core": "5.0.0-beta.42",
70
- "@kubb/renderer-jsx": "5.0.0-beta.42",
71
- "@kubb/plugin-ts": "5.0.0-beta.42"
68
+ "@kubb/ast": "5.0.0-beta.55",
69
+ "@kubb/core": "5.0.0-beta.55",
70
+ "@kubb/renderer-jsx": "5.0.0-beta.55",
71
+ "@kubb/plugin-ts": "5.0.0-beta.56"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@internals/shared": "0.0.0",
75
75
  "@internals/utils": "0.0.0"
76
76
  },
77
77
  "peerDependencies": {
78
- "@kubb/renderer-jsx": "5.0.0-beta.42"
78
+ "@kubb/renderer-jsx": "5.0.0-beta.55"
79
79
  },
80
- "size-limit": [
81
- {
82
- "path": "./dist/*.js",
83
- "limit": "510 KiB",
84
- "gzip": true
85
- }
86
- ],
87
80
  "engines": {
88
81
  "node": ">=22"
89
82
  },
90
83
  "scripts": {
91
- "build": "tsdown && size-limit",
92
- "clean": "npx rimraf ./dist",
84
+ "build": "tsdown",
85
+ "clean": "node -e \"require('node:fs').rmSync('./dist', {recursive:true,force:true})\"",
93
86
  "lint": "oxlint .",
94
87
  "lint:fix": "oxlint --fix .",
95
88
  "release": "pnpm publish --no-git-check",
@@ -1,4 +1,4 @@
1
- import { jsStringEscape } from '@internals/utils'
1
+ import { jsStringEscape } from '@kubb/ast/utils'
2
2
  import { ast } from '@kubb/core'
3
3
  import { functionPrinter } from '@kubb/plugin-ts'
4
4
  import { File, Function } from '@kubb/renderer-jsx'
@@ -2,7 +2,7 @@ import { getPerContentTypeName, resolveContentTypeVariants } from '@internals/sh
2
2
  import { aliasConflictingImports, filterUsedImports, rewriteAliasedImports } from '@internals/utils'
3
3
  import { ast, defineGenerator } from '@kubb/core'
4
4
  import { pluginTsName } from '@kubb/plugin-ts'
5
- import { File, jsxRendererSync } from '@kubb/renderer-jsx'
5
+ import { File, jsxRenderer } from '@kubb/renderer-jsx'
6
6
  import { Faker } from '../components/Faker.tsx'
7
7
  import { printerFaker } from '../printers/printerFaker.ts'
8
8
  import type { PluginFaker } from '../types.ts'
@@ -16,7 +16,7 @@ import { buildResponseUnionSchema, canOverrideSchema, localeToFakerImport, resol
16
16
  */
17
17
  export const fakerGenerator = defineGenerator<PluginFaker>({
18
18
  name: 'faker',
19
- renderer: jsxRendererSync,
19
+ renderer: jsxRenderer,
20
20
  schema(node, ctx) {
21
21
  const { adapter, config, resolver, root } = ctx
22
22
  const { output, group, dateParser, regexGenerator, mapper, seed, locale, printer } = ctx.options
@@ -29,14 +29,11 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
29
29
  const tsResolver = ctx.driver.getResolver(pluginTsName)
30
30
 
31
31
  const schemaName = node.name
32
- const mode = ctx.getMode(output)
33
32
  const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum)
34
- const tsEnumType = pluginTs.options?.enumType
35
- const tsEnumTypeSuffix = pluginTs.options?.enumTypeSuffix ?? 'Key'
33
+ const tsEnumType = pluginTs.options?.enum?.type
34
+ const tsEnumTypeSuffix = pluginTs.options?.enum?.typeSuffix ?? 'Key'
36
35
  const schemaTypeName =
37
- isEnumSchema && (tsEnumType === 'asConst' || tsEnumType === 'asPascalConst')
38
- ? tsResolver.resolveEnumKeyName({ name: schemaName }, tsEnumTypeSuffix)
39
- : tsResolver.resolveTypeName(schemaName)
36
+ isEnumSchema && tsEnumType === 'asConst' ? tsResolver.resolveEnumKeyName({ name: schemaName }, tsEnumTypeSuffix) : tsResolver.resolveTypeName(schemaName)
40
37
  const meta = {
41
38
  name: resolver.resolveName(schemaName),
42
39
  file: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group: group ?? undefined }),
@@ -68,12 +65,10 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
68
65
  typeFilePath: meta.typeFile.path,
69
66
  })
70
67
 
71
- const imports = adapter
72
- .getImports(node, (schemaName) => ({
73
- name: resolver.resolveName(schemaName),
74
- path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group: group ?? undefined }).path,
75
- }))
76
- .filter((entry) => entry.path !== meta.file.path)
68
+ const imports = adapter.getImports(node, (schemaName) => ({
69
+ name: resolver.resolveName(schemaName),
70
+ path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group: group ?? undefined }).path,
71
+ }))
77
72
  const usedImports = filterUsedImports(imports, fakerText)
78
73
 
79
74
  return (
@@ -88,8 +83,9 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
88
83
  {regexGenerator === 'randexp' && <File.Import name={'RandExp'} path={'randexp'} />}
89
84
  {dateParser !== 'faker' && <File.Import path={dateParser} name={dateParser} />}
90
85
  {typeReference.importPath && <File.Import isTypeOnly root={meta.file.path} path={typeReference.importPath} name={[meta.typeName]} />}
91
- {mode === 'split' &&
92
- usedImports.map((imp) => <File.Import key={[schemaName, imp.path, imp.name].join('-')} root={meta.file.path} path={imp.path} name={imp.name} />)}
86
+ {usedImports.map((imp) => (
87
+ <File.Import key={[schemaName, imp.path, imp.name].join('-')} root={meta.file.path} path={imp.path} name={imp.name} />
88
+ ))}
93
89
  <Faker
94
90
  name={meta.name}
95
91
  typeName={typeReference.typeName}
package/src/plugin.ts CHANGED
@@ -37,7 +37,7 @@ export const pluginFakerName = 'plugin-faker' satisfies PluginFaker['name']
37
37
  */
38
38
  export const pluginFaker = definePlugin<PluginFaker>((options) => {
39
39
  const {
40
- output = { path: 'mocks', barrelType: 'named' },
40
+ output = { path: 'mocks', barrel: { type: 'named' } },
41
41
  seed,
42
42
  locale = 'en',
43
43
  group,
@@ -54,7 +54,7 @@ export const pluginFaker = definePlugin<PluginFaker>((options) => {
54
54
  transformer: userTransformer,
55
55
  } = options
56
56
 
57
- const groupConfig = createGroupConfig(group, { suffix: 'Controller' })
57
+ const groupConfig = createGroupConfig(group)
58
58
 
59
59
  return {
60
60
  name: pluginFakerName,
@@ -1,4 +1,4 @@
1
- import { stringify, toRegExpString } from '@internals/utils'
1
+ import { buildObject, extractRefName, objectKey, stringify, toRegExpString } from '@kubb/ast/utils'
2
2
  import { ast } from '@kubb/core'
3
3
  import type { PluginFaker, ResolverFaker } from '../types.ts'
4
4
 
@@ -284,7 +284,7 @@ export const printerFaker: (options: PrinterFakerOptions) => ast.Printer<Printer
284
284
  // Use the canonical name from the $ref path — node.name may have been overridden
285
285
  // (e.g. by single-member allOf flatten using the property-derived child name).
286
286
  // Inline refs (without $ref) from faker utils already carry resolved helper names.
287
- const refName = node.ref ? (ast.extractRefName(node.ref) ?? node.name ?? node.schema?.name) : (node.name ?? node.schema?.name)
287
+ const refName = node.ref ? (extractRefName(node.ref) ?? node.name ?? node.schema?.name) : (node.name ?? node.schema?.name)
288
288
 
289
289
  if (!refName) {
290
290
  throw new Error('Name not defined for ref node')
@@ -369,32 +369,30 @@ export const printerFaker: (options: PrinterFakerOptions) => ast.Printer<Printer
369
369
  },
370
370
  object(node): string {
371
371
  const cyclicSchemas = this.options.cyclicSchemas
372
- const properties = (node.properties ?? [])
373
- .map((property): string => {
374
- if (this.options.mapper && Object.hasOwn(this.options.mapper, property.name)) {
375
- return `"${property.name}": ${this.options.mapper[property.name]}`
376
- }
372
+ const entries = (node.properties ?? []).map((property): string => {
373
+ if (this.options.mapper && Object.hasOwn(this.options.mapper, property.name)) {
374
+ return `${objectKey(property.name)}: ${this.options.mapper[property.name]}`
375
+ }
376
+
377
+ const value: string =
378
+ printNested(property.schema, {
379
+ typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : undefined,
380
+ nestedInObject: true,
381
+ }) ?? 'undefined'
377
382
 
378
- const value: string =
379
- printNested(property.schema, {
380
- typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : undefined,
381
- nestedInObject: true,
382
- }) ?? 'undefined'
383
-
384
- // When the property's schema transitively references a schema that is
385
- // part of a circular dependency (other than the current schema itself),
386
- // emit a memoizing lazy getter. On first access it computes the value,
387
- // replaces itself with a plain data property via Object.defineProperty,
388
- // and returns the cached value – so every subsequent read is stable.
389
- if (cyclicSchemas && ast.containsCircularRef(property.schema, { circularSchemas: cyclicSchemas, excludeName: this.options.schemaName })) {
390
- return `get ${property.name}() { const _value = ${value}; Object.defineProperty(this, ${JSON.stringify(property.name)}, { value: _value, configurable: true, writable: true, enumerable: true }); return _value }`
391
- }
383
+ // When the property's schema transitively references a schema that is
384
+ // part of a circular dependency (other than the current schema itself),
385
+ // emit a memoizing lazy getter. On first access it computes the value,
386
+ // replaces itself with a plain data property via Object.defineProperty,
387
+ // and returns the cached value – so every subsequent read is stable.
388
+ if (cyclicSchemas && ast.containsCircularRef(property.schema, { circularSchemas: cyclicSchemas, excludeName: this.options.schemaName })) {
389
+ return `get ${objectKey(property.name)}() { const _value = ${value}; Object.defineProperty(this, ${JSON.stringify(property.name)}, { value: _value, configurable: true, writable: true, enumerable: true }); return _value }`
390
+ }
392
391
 
393
- return `"${property.name}": ${value}`
394
- })
395
- .join(',')
392
+ return `${objectKey(property.name)}: ${value}`
393
+ })
396
394
 
397
- return `{${properties}}`
395
+ return buildObject(entries)
398
396
  },
399
397
  ...options.nodes,
400
398
  },
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto'
2
2
  import path from 'node:path'
3
- import { camelCase, ensureValidVarName } from '@internals/utils'
4
- import { defineResolver, KubbDriver } from '@kubb/core'
3
+ import { camelCase, ensureValidVarName, toFilePath } from '@internals/utils'
4
+ import { defineResolver } from '@kubb/core'
5
5
  import type { PluginFaker } from '../types.ts'
6
6
 
7
7
  /**
@@ -21,8 +21,8 @@ export const resolverFaker = defineResolver<PluginFaker>(() => {
21
21
  name: 'default',
22
22
  pluginName: 'plugin-faker',
23
23
  default(name, type) {
24
- const resolvedName = camelCase(name, { isFile: type === 'file', prefix: 'create' })
25
- return type === 'file' ? resolvedName : ensureValidVarName(resolvedName)
24
+ if (type === 'file') return toFilePath(name, (part) => camelCase(part, { prefix: 'create' }))
25
+ return ensureValidVarName(camelCase(name, { prefix: 'create' }))
26
26
  },
27
27
  resolveName(name, type) {
28
28
  return this.default(name, type)
@@ -31,17 +31,17 @@ export const resolverFaker = defineResolver<PluginFaker>(() => {
31
31
  return this.default(name, type)
32
32
  },
33
33
  resolveFile({ name, extname, tag, path: groupPath }, context) {
34
- const pathMode = KubbDriver.getMode(path.resolve(context.root, context.output.path))
35
- const baseName = `${pathMode === 'single' ? '' : this.resolveName(name, 'file')}${extname}` as `${string}.${string}`
34
+ const resolvedName = context.output.mode === 'file' ? '' : this.resolveName(name, 'file')
35
+ const inputBaseName = `${resolvedName}${extname}` as `${string}.${string}`
36
36
  const filePath = this.resolvePath(
37
37
  {
38
- baseName,
39
- pathMode,
38
+ baseName: inputBaseName,
40
39
  tag,
41
40
  path: groupPath,
42
41
  },
43
42
  context,
44
43
  )
44
+ const baseName = path.basename(filePath) as `${string}.${string}`
45
45
 
46
46
  return {
47
47
  kind: 'File',
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
1
+ import type { ast, Exclude, Generator, Group, Include, Output, OutputOptions, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
2
2
  import type { PrinterFakerNodes } from './printers/printerFaker.ts'
3
3
 
4
4
  /**
@@ -71,17 +71,13 @@ export type ResolverFaker = Resolver &
71
71
  resolveHeaderParamsName(this: ResolverFaker, node: ast.OperationNode, param: ast.ParameterNode): string
72
72
  }
73
73
 
74
- export type Options = {
75
- /**
76
- * Where the generated mock factories are written and how they are exported.
77
- *
78
- * @default { path: 'mocks', barrel: { type: 'named' } }
79
- */
80
- output?: Output
81
- /**
82
- * Split generated files into subfolders based on the operation's tag.
83
- */
84
- group?: Group
74
+ /**
75
+ * Where the generated mock factories are written and how they are exported, plus the optional
76
+ * `group` strategy. The `group` option organizes `output.mode: 'directory'` output into per-tag or per-path subdirectories.
77
+ *
78
+ * @default { path: 'mocks', barrel: { type: 'named' } }
79
+ */
80
+ export type Options = OutputOptions & {
85
81
  /**
86
82
  * Skip operations matching at least one entry in the list.
87
83
  */
package/src/utils.ts CHANGED
@@ -188,7 +188,7 @@ export function resolveTypeReference({
188
188
  * Maps a schema node type to its corresponding scalar type representation.
189
189
  * Returns the type name for enums or the base type (string, number, etc.) for primitives.
190
190
  */
191
- export function getScalarType(node: ast.SchemaNode, typeName: string): string {
191
+ function getScalarType(node: ast.SchemaNode, typeName: string): string {
192
192
  switch (node.type) {
193
193
  case 'string':
194
194
  case 'email':