@kubb/plugin-faker 5.0.0-beta.31 → 5.0.0-beta.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -321,7 +321,7 @@ const pluginFaker = (0, _kubb_core.definePlugin)((options) => {
321
321
  const { output = {
322
322
  path: "mocks",
323
323
  barrelType: "named"
324
- }, seed, locale, group, exclude = [], include, override = [], mapper = {}, dateParser = "faker", generators: userGenerators = [], regexGenerator = "faker", paramsCasing, printer, resolver: userResolver, transformer: userTransformer } = options;
324
+ }, seed, locale = "en", group, exclude = [], include, override = [], mapper = {}, dateParser = "faker", generators: userGenerators = [], regexGenerator = "faker", paramsCasing, printer, resolver: userResolver, transformer: userTransformer } = options;
325
325
  const groupConfig = createGroupConfig(group, {
326
326
  suffix: "Controller",
327
327
  honorName: true
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["KubbDriver","path","pluginTsName","fakerGenerator"],"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 * Returns `null` when grouping is disabled, matching the 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 * @param options.honorName - When `true`, a user-provided `group.name` overrides the default namer.\n *\n * @example\n * ```ts\n * createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-zod\n * createGroupConfig(group, { suffix: 'Controller', honorName: true }) // plugin-faker, plugin-client, …\n * createGroupConfig(group, { suffix: 'Requests', honorName: true }) // plugin-cypress, plugin-mcp\n * ```\n */\nexport function createGroupConfig(group: Group | undefined, options: { suffix: string; honorName?: boolean }): 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: options.honorName && 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,\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', honorName: true })\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":"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"}
1
+ {"version":3,"file":"index.cjs","names":["KubbDriver","path","pluginTsName","fakerGenerator"],"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 * Returns `null` when grouping is disabled, matching the 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 * @param options.honorName - When `true`, a user-provided `group.name` overrides the default namer.\n *\n * @example\n * ```ts\n * createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-zod\n * createGroupConfig(group, { suffix: 'Controller', honorName: true }) // plugin-faker, plugin-client, …\n * createGroupConfig(group, { suffix: 'Requests', honorName: true }) // plugin-cypress, plugin-mcp\n * ```\n */\nexport function createGroupConfig(group: Group | undefined, options: { suffix: string; honorName?: boolean }): 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: options.honorName && 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', honorName: true })\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":"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"}
package/dist/index.js CHANGED
@@ -317,7 +317,7 @@ const pluginFaker = definePlugin((options) => {
317
317
  const { output = {
318
318
  path: "mocks",
319
319
  barrelType: "named"
320
- }, seed, locale, group, exclude = [], include, override = [], mapper = {}, dateParser = "faker", generators: userGenerators = [], regexGenerator = "faker", paramsCasing, printer, resolver: userResolver, transformer: userTransformer } = options;
320
+ }, seed, locale = "en", group, exclude = [], include, override = [], mapper = {}, dateParser = "faker", generators: userGenerators = [], regexGenerator = "faker", paramsCasing, printer, resolver: userResolver, transformer: userTransformer } = options;
321
321
  const groupConfig = createGroupConfig(group, {
322
322
  suffix: "Controller",
323
323
  honorName: true
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 * Returns `null` when grouping is disabled, matching the 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 * @param options.honorName - When `true`, a user-provided `group.name` overrides the default namer.\n *\n * @example\n * ```ts\n * createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-zod\n * createGroupConfig(group, { suffix: 'Controller', honorName: true }) // plugin-faker, plugin-client, …\n * createGroupConfig(group, { suffix: 'Requests', honorName: true }) // plugin-cypress, plugin-mcp\n * ```\n */\nexport function createGroupConfig(group: Group | undefined, options: { suffix: string; honorName?: boolean }): 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: options.honorName && 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,\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', honorName: true })\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":"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"}
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 * Returns `null` when grouping is disabled, matching the 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 * @param options.honorName - When `true`, a user-provided `group.name` overrides the default namer.\n *\n * @example\n * ```ts\n * createGroupConfig(group, { suffix: 'Controller' }) // plugin-ts, plugin-zod\n * createGroupConfig(group, { suffix: 'Controller', honorName: true }) // plugin-faker, plugin-client, …\n * createGroupConfig(group, { suffix: 'Requests', honorName: true }) // plugin-cypress, plugin-mcp\n * ```\n */\nexport function createGroupConfig(group: Group | undefined, options: { suffix: string; honorName?: boolean }): 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: options.honorName && 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', honorName: true })\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":"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"}
package/extension.yaml CHANGED
@@ -483,7 +483,9 @@ options:
483
483
  required: false
484
484
  default: "'en'"
485
485
  description: |
486
- Faker locale used for generated mock values. Switches the named import to `fakerXX` from `@faker-js/faker`.
486
+ Faker locale used for generated mock values. Switches the named import to `fakerXX` from `@faker-js/faker` so names, addresses, and phone numbers reflect the target region.
487
+
488
+ Defaults to `'en'`, which imports `fakerEN`.
487
489
  tip: |
488
490
  See [Faker.js localization](https://fakerjs.dev/api/localization.html) for the full list of locale codes.
489
491
  examples:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-faker",
3
- "version": "5.0.0-beta.31",
3
+ "version": "5.0.0-beta.33",
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",
@@ -66,16 +66,16 @@
66
66
  "registry": "https://registry.npmjs.org/"
67
67
  },
68
68
  "dependencies": {
69
- "@kubb/core": "5.0.0-beta.31",
70
- "@kubb/renderer-jsx": "5.0.0-beta.31",
71
- "@kubb/plugin-ts": "5.0.0-beta.31"
69
+ "@kubb/core": "5.0.0-beta.33",
70
+ "@kubb/renderer-jsx": "5.0.0-beta.33",
71
+ "@kubb/plugin-ts": "5.0.0-beta.33"
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.31"
78
+ "@kubb/renderer-jsx": "5.0.0-beta.33"
79
79
  },
80
80
  "size-limit": [
81
81
  {
package/src/plugin.ts CHANGED
@@ -39,7 +39,7 @@ export const pluginFaker = definePlugin<PluginFaker>((options) => {
39
39
  const {
40
40
  output = { path: 'mocks', barrelType: 'named' },
41
41
  seed,
42
- locale,
42
+ locale = 'en',
43
43
  group,
44
44
  exclude = [],
45
45
  include,