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

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 (37) hide show
  1. package/README.md +26 -5
  2. package/dist/{Faker-CdyPfOPg.d.ts → Faker-BaLJxPyl.d.ts} +2 -2
  3. package/dist/{Faker-fcQEB9i5.js → Faker-DwIc_lta.js} +38 -100
  4. package/dist/Faker-DwIc_lta.js.map +1 -0
  5. package/dist/{Faker-BgleOzVN.cjs → Faker-XuyEQflW.cjs} +37 -123
  6. package/dist/Faker-XuyEQflW.cjs.map +1 -0
  7. package/dist/components.cjs +1 -1
  8. package/dist/components.d.ts +1 -1
  9. package/dist/components.js +1 -1
  10. package/dist/{fakerGenerator-VJEVzLjc.cjs → fakerGenerator-BBr2WsG8.cjs} +236 -60
  11. package/dist/fakerGenerator-BBr2WsG8.cjs.map +1 -0
  12. package/dist/{fakerGenerator-D7daHCh6.js → fakerGenerator-BDNxA7KY.js} +235 -59
  13. package/dist/fakerGenerator-BDNxA7KY.js.map +1 -0
  14. package/dist/fakerGenerator-DSvAJTq3.d.ts +15 -0
  15. package/dist/generators.cjs +1 -1
  16. package/dist/generators.d.ts +1 -1
  17. package/dist/generators.js +1 -1
  18. package/dist/index.cjs +213 -42
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.ts +33 -12
  21. package/dist/index.js +214 -43
  22. package/dist/index.js.map +1 -1
  23. package/dist/{printerFaker-CJiwzoto.d.ts → printerFaker-Bhwq62d1.d.ts} +63 -26
  24. package/extension.yaml +817 -0
  25. package/package.json +9 -13
  26. package/src/components/Faker.tsx +50 -64
  27. package/src/generators/fakerGenerator.tsx +107 -67
  28. package/src/plugin.ts +25 -21
  29. package/src/printers/printerFaker.ts +80 -16
  30. package/src/resolvers/resolverFaker.ts +29 -37
  31. package/src/types.ts +36 -23
  32. package/src/utils.ts +6 -105
  33. package/dist/Faker-BgleOzVN.cjs.map +0 -1
  34. package/dist/Faker-fcQEB9i5.js.map +0 -1
  35. package/dist/fakerGenerator-C3Ho3BaI.d.ts +0 -9
  36. package/dist/fakerGenerator-D7daHCh6.js.map +0 -1
  37. package/dist/fakerGenerator-VJEVzLjc.cjs.map +0 -1
package/package.json CHANGED
@@ -1,12 +1,10 @@
1
1
  {
2
2
  "name": "@kubb/plugin-faker",
3
- "version": "5.0.0-beta.3",
4
- "description": "Faker.js data generator plugin for Kubb, creating realistic mock data from OpenAPI specifications for development and testing.",
3
+ "version": "5.0.0-beta.31",
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
- "code-generator",
6
+ "code-generation",
7
7
  "codegen",
8
- "data-generation",
9
- "development",
10
8
  "faker",
11
9
  "faker.js",
12
10
  "fakerjs",
@@ -14,11 +12,8 @@
14
12
  "kubb",
15
13
  "mock-data",
16
14
  "mocks",
17
- "oas",
18
15
  "openapi",
19
- "plugins",
20
16
  "swagger",
21
- "testing",
22
17
  "typescript"
23
18
  ],
24
19
  "license": "MIT",
@@ -31,7 +26,7 @@
31
26
  "files": [
32
27
  "src",
33
28
  "dist",
34
- "plugin.json",
29
+ "extension.yaml",
35
30
  "!/**/**.test.**",
36
31
  "!/**/__tests__/**",
37
32
  "!/**/__snapshots__/**"
@@ -71,15 +66,16 @@
71
66
  "registry": "https://registry.npmjs.org/"
72
67
  },
73
68
  "dependencies": {
74
- "@kubb/core": "5.0.0-beta.3",
75
- "@kubb/renderer-jsx": "5.0.0-beta.3",
76
- "@kubb/plugin-ts": "5.0.0-beta.3"
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"
77
72
  },
78
73
  "devDependencies": {
74
+ "@internals/shared": "0.0.0",
79
75
  "@internals/utils": "0.0.0"
80
76
  },
81
77
  "peerDependencies": {
82
- "@kubb/renderer-jsx": "5.0.0-beta.3"
78
+ "@kubb/renderer-jsx": "5.0.0-beta.31"
83
79
  },
84
80
  "size-limit": [
85
81
  {
@@ -44,71 +44,17 @@ export function Faker({ node, description, name, typeName, printer, seed, canOve
44
44
  const isTuple = node.type === 'tuple'
45
45
  const isScalar = SCALAR_TYPES.has(node.type)
46
46
 
47
- let fakerTextWithOverride = fakerText
48
- let useGenericOverride = false
49
-
50
- if (canOverride && isObject) {
51
- useGenericOverride = true
52
- }
53
-
54
- if (canOverride && isTuple) {
55
- fakerTextWithOverride = `data || ${fakerText}`
56
- }
57
-
58
- if (canOverride && isArray) {
59
- fakerTextWithOverride = `[
60
- ...${fakerText},
61
- ...(data || [])
62
- ]`
63
- }
64
-
65
- if (canOverride && isScalar) {
66
- fakerTextWithOverride = `data ?? ${fakerText}`
67
- }
47
+ const useGenericOverride = canOverride && isObject
48
+ const fakerTextWithOverride = (() => {
49
+ if (canOverride && isTuple) return `data || ${fakerText}`
50
+ if (canOverride && isArray) return `[\n ...${fakerText},\n ...(data || [])\n]`
51
+ if (canOverride && isScalar) return `data ?? ${fakerText}`
52
+ return fakerText
53
+ })()
68
54
 
69
55
  const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride)
70
56
 
71
- let functionSignature = ''
72
- let functionBody = ''
73
-
74
- if (useGenericOverride) {
75
- // Generate function with defaultFakeData structure
76
- const jsdoc = description ? `/**\n * @description ${jsStringEscape(description)}\n */\n ` : ''
77
- functionSignature = `${jsdoc}export function ${name}(data?: Partial<${typeName}>): Required<${typeName}>`
78
-
79
- const seedCode = seed ? `faker.seed(${JSON.stringify(seed)})\n ` : ''
80
-
81
- // When the object node has properties that transitively reference a cyclic schema,
82
- // the printer emits memoizing getters for those properties. Spreading the object
83
- // literal would immediately invoke those getters, triggering recursive faker calls
84
- // and causing a stack overflow. Detect this upfront via ast helpers so we can
85
- // use Object.defineProperty-based merging instead of spread.
86
- const { cyclicSchemas, schemaName } = printer.options
87
- const hasGetters =
88
- node.type === 'object' &&
89
- !!cyclicSchemas &&
90
- (node.properties ?? []).some((p) => ast.containsCircularRef(p.schema, { circularSchemas: cyclicSchemas, excludeName: schemaName }))
91
-
92
- if (hasGetters) {
93
- functionBody = `{
94
- ${seedCode}const defaultFakeData = ${fakerText}
95
- if (data) {
96
- for (const [key, value] of Object.entries(data)) {
97
- Object.defineProperty(defaultFakeData, key, { value, configurable: true, writable: true, enumerable: true })
98
- }
99
- }
100
- return defaultFakeData as Required<${typeName}>
101
- }`
102
- } else {
103
- functionBody = `{
104
- ${seedCode}const defaultFakeData = ${fakerText}
105
- return {
106
- ...defaultFakeData,
107
- ...(data || {}),
108
- } as Required<${typeName}>
109
- }`
110
- }
111
- } else {
57
+ if (!useGenericOverride) {
112
58
  const usesData = /\bdata\b/.test(fakerTextWithOverride)
113
59
  const dataParamName = usesData ? 'data' : '_data'
114
60
  const params = ast.createFunctionParameters({
@@ -123,6 +69,11 @@ export function Faker({ node, description, name, typeName, printer, seed, canOve
123
69
  const paramsSignature = declarationPrinter.print(params) ?? ''
124
70
  const returnType = resolvedReturnType
125
71
 
72
+ // A `ref` wrapper delegates to another faker. Object fakers are now generic and
73
+ // widen to `Partial<T>` when called with a `Partial<T>`-typed argument, so cast
74
+ // back to the wrapper's declared return type to keep it assignable.
75
+ const returnExpression = node.type === 'ref' && canOverride && returnType ? `${fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride
76
+
126
77
  return (
127
78
  <File.Source name={name} isExportable isIndexable>
128
79
  <Function
@@ -130,7 +81,7 @@ export function Faker({ node, description, name, typeName, printer, seed, canOve
130
81
  name={name}
131
82
  JSDoc={{ comments: description ? [`@description ${jsStringEscape(description)}`] : [] }}
132
83
  params={canOverride ? paramsSignature : undefined}
133
- returnType={returnType}
84
+ returnType={returnType ?? undefined}
134
85
  >
135
86
  {seed ? (
136
87
  <>
@@ -138,12 +89,47 @@ export function Faker({ node, description, name, typeName, printer, seed, canOve
138
89
  <br />
139
90
  </>
140
91
  ) : undefined}
141
- {`return ${fakerTextWithOverride}`}
92
+ {`return ${returnExpression}`}
142
93
  </Function>
143
94
  </File.Source>
144
95
  )
145
96
  }
146
97
 
98
+ // Generate function with defaultFakeData structure
99
+ const jsdoc = description ? `/**\n * @description ${jsStringEscape(description)}\n */\n ` : ''
100
+ const functionSignature = `${jsdoc}export function ${name}<TData extends Partial<${typeName}> = object>(data?: TData)`
101
+
102
+ const seedCode = seed ? `faker.seed(${JSON.stringify(seed)})\n ` : ''
103
+
104
+ // When the object node has properties that transitively reference a cyclic schema,
105
+ // the printer emits memoizing getters for those properties. Spreading the object
106
+ // literal would immediately invoke those getters, triggering recursive faker calls
107
+ // and causing a stack overflow. Detect this upfront via ast helpers so we can
108
+ // use Object.defineProperty-based merging instead of spread.
109
+ const { cyclicSchemas, schemaName } = printer.options
110
+ const hasGetters =
111
+ node.type === 'object' &&
112
+ !!cyclicSchemas &&
113
+ (node.properties ?? []).some((p) => ast.containsCircularRef(p.schema, { circularSchemas: cyclicSchemas, excludeName: schemaName }))
114
+
115
+ const functionBody = hasGetters
116
+ ? `{
117
+ ${seedCode}const defaultFakeData = ${fakerText}
118
+ if (data) {
119
+ for (const [key, value] of Object.entries(data)) {
120
+ Object.defineProperty(defaultFakeData, key, { value, configurable: true, writable: true, enumerable: true })
121
+ }
122
+ }
123
+ return defaultFakeData as Omit<typeof defaultFakeData, keyof TData> & TData
124
+ }`
125
+ : `{
126
+ ${seedCode}const defaultFakeData = ${fakerText}
127
+ return {
128
+ ...defaultFakeData,
129
+ ...(data || {}),
130
+ } as Omit<typeof defaultFakeData, keyof TData> & TData
131
+ }`
132
+
147
133
  return (
148
134
  <File.Source name={name} isExportable isIndexable>
149
135
  {functionSignature}
@@ -1,49 +1,53 @@
1
+ import { getPerContentTypeName, resolveContentTypeVariants } from '@internals/shared'
2
+ import { aliasConflictingImports, filterUsedImports, rewriteAliasedImports } from '@internals/utils'
1
3
  import { ast, defineGenerator } from '@kubb/core'
2
4
  import { pluginTsName } from '@kubb/plugin-ts'
3
- import { File, jsxRenderer } from '@kubb/renderer-jsx'
5
+ import { File, jsxRendererSync } from '@kubb/renderer-jsx'
4
6
  import { Faker } from '../components/Faker.tsx'
5
7
  import { printerFaker } from '../printers/printerFaker.ts'
6
8
  import type { PluginFaker } from '../types.ts'
7
- import {
8
- aliasConflictingImports,
9
- buildResponseUnionSchema,
10
- canOverrideSchema,
11
- filterUsedImports,
12
- localeToFakerImport,
13
- resolveParamNameByLocation,
14
- resolveSchemaRef,
15
- resolveTypeReference,
16
- rewriteAliasedImports,
17
- } from '../utils.ts'
9
+ import { buildResponseUnionSchema, canOverrideSchema, localeToFakerImport, resolveParamNameByLocation, resolveTypeReference } from '../utils.ts'
18
10
 
11
+ /**
12
+ * Built-in generator for `@kubb/plugin-faker`. Emits one `createX` factory
13
+ * per schema in the spec plus per-operation request/response factories. Each
14
+ * factory returns a value matching the corresponding TypeScript type from
15
+ * `@kubb/plugin-ts`.
16
+ */
19
17
  export const fakerGenerator = defineGenerator<PluginFaker>({
20
18
  name: 'faker',
21
- renderer: jsxRenderer,
19
+ renderer: jsxRendererSync,
22
20
  schema(node, ctx) {
23
21
  const { adapter, config, resolver, root } = ctx
24
22
  const { output, group, dateParser, regexGenerator, mapper, seed, locale, printer } = ctx.options
25
23
  const pluginTs = ctx.driver.getPlugin(pluginTsName)
26
24
 
27
- if (!node.name || !pluginTs || !adapter.inputNode) {
25
+ if (!node.name || !pluginTs) {
28
26
  return
29
27
  }
30
28
 
31
29
  const tsResolver = ctx.driver.getResolver(pluginTsName)
32
30
 
33
- const schemaNode = resolveSchemaRef(node, adapter.inputNode.schemas)
34
- const schemaName = schemaNode.name ?? node.name
31
+ const schemaName = node.name
35
32
  const mode = ctx.getMode(output)
33
+ const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum)
34
+ const tsEnumType = pluginTs.options?.enumType
35
+ const tsEnumTypeSuffix = pluginTs.options?.enumTypeSuffix ?? 'Key'
36
+ const schemaTypeName =
37
+ isEnumSchema && (tsEnumType === 'asConst' || tsEnumType === 'asPascalConst')
38
+ ? tsResolver.resolveEnumKeyName({ name: schemaName }, tsEnumTypeSuffix)
39
+ : tsResolver.resolveTypeName(schemaName)
36
40
  const meta = {
37
41
  name: resolver.resolveName(schemaName),
38
- file: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }),
39
- typeName: tsResolver.resolveTypeName(schemaName),
42
+ file: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group: group ?? undefined }),
43
+ typeName: schemaTypeName,
40
44
  typeFile: tsResolver.resolveFile(
41
45
  { name: schemaName, extname: '.ts' },
42
- { root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group },
46
+ { root, output: pluginTs.options?.output ?? output, group: pluginTs.options?.group ?? undefined },
43
47
  ),
44
48
  } as const
45
- const canOverride = canOverrideSchema(schemaNode)
46
- const cyclicSchemas = adapter.inputNode ? ast.findCircularSchemas(adapter.inputNode.schemas) : undefined
49
+ const canOverride = canOverrideSchema(node)
50
+ const cyclicSchemas = new Set<string>(ctx.meta.circularNames)
47
51
  const printerInstance = printerFaker({
48
52
  resolver,
49
53
  schemaName,
@@ -54,9 +58,9 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
54
58
  nodes: printer?.nodes,
55
59
  cyclicSchemas,
56
60
  })
57
- const fakerText = printerInstance.print(schemaNode) ?? 'undefined'
61
+ const fakerText = printerInstance.print(node) ?? 'undefined'
58
62
  const typeReference = resolveTypeReference({
59
- node: schemaNode,
63
+ node,
60
64
  canOverride,
61
65
  name: meta.name,
62
66
  typeName: meta.typeName,
@@ -65,9 +69,9 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
65
69
  })
66
70
 
67
71
  const imports = adapter
68
- .getImports(schemaNode, (schemaName) => ({
72
+ .getImports(node, (schemaName) => ({
69
73
  name: resolver.resolveName(schemaName),
70
- path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
74
+ path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group: group ?? undefined }).path,
71
75
  }))
72
76
  .filter((entry) => entry.path !== meta.file.path)
73
77
  const usedImports = filterUsedImports(imports, fakerText)
@@ -77,8 +81,8 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
77
81
  baseName={meta.file.baseName}
78
82
  path={meta.file.path}
79
83
  meta={meta.file.meta}
80
- banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
81
- footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
84
+ banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
85
+ footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
82
86
  >
83
87
  <File.Import name={locale ? [{ propertyName: localeToFakerImport(locale), name: 'faker' }] : ['faker']} path="@faker-js/faker" />
84
88
  {regexGenerator === 'randexp' && <File.Import name={'RandExp'} path={'randexp'} />}
@@ -89,8 +93,8 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
89
93
  <Faker
90
94
  name={meta.name}
91
95
  typeName={typeReference.typeName}
92
- description={schemaNode.description}
93
- node={schemaNode}
96
+ description={node.description}
97
+ node={node}
94
98
  printer={printerInstance}
95
99
  seed={seed}
96
100
  canOverride={canOverride}
@@ -115,31 +119,66 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
115
119
  name: resolveParamNameByLocation(resolver, node, param),
116
120
  typeName: resolveParamNameByLocation(tsResolver, node, param),
117
121
  }))
118
- const responseEntries = node.responses.map((response) => ({
119
- response,
120
- name: resolver.resolveResponseStatusName(node, response.statusCode),
121
- typeName: tsResolver.resolveResponseStatusName(node, response.statusCode),
122
- }))
123
- const dataEntry = node.requestBody?.content?.[0]?.schema
124
- ? {
125
- schema: {
126
- ...node.requestBody.content![0]!.schema!,
127
- description: node.requestBody.description ?? node.requestBody.content![0]!.schema!.description,
128
- },
129
- name: resolver.resolveDataName(node),
130
- typeName: tsResolver.resolveDataName(node),
131
- description: node.requestBody.description ?? node.requestBody.content![0]!.schema!.description,
132
- }
133
- : null
122
+ type RenderUnit = { schema: ast.SchemaNode | null; name: string; typeName: string; description?: string; skipImportNames: Array<string> }
123
+
124
+ // Expands a content array into render units: one faker per content type plus a union faker
125
+ // (named `baseName`) when more than one content type carries a schema, else a single faker.
126
+ function expandContentUnits(
127
+ entries: Array<{ contentType: string; schema?: ast.SchemaNode | null }>,
128
+ baseName: string,
129
+ tsBaseName: string,
130
+ description: string | undefined,
131
+ decorate?: (schema: ast.SchemaNode) => ast.SchemaNode,
132
+ ): Array<RenderUnit> {
133
+ const withSchema = entries.filter((entry) => entry.schema)
134
+ if (withSchema.length <= 1) {
135
+ const primary = withSchema[0] ?? entries[0]
136
+ if (!primary?.schema) return []
137
+ return [{ schema: decorate ? decorate(primary.schema) : primary.schema, name: baseName, typeName: tsBaseName, description, skipImportNames: [] }]
138
+ }
139
+ const variants = resolveContentTypeVariants(entries, baseName)
140
+ const unionSchema = ast.createSchema({ type: 'union', members: variants.map((variant) => ast.createSchema({ type: 'ref', name: variant.name })) })
141
+ return [
142
+ ...variants.map((variant) => ({
143
+ schema: decorate ? decorate(variant.schema) : variant.schema,
144
+ name: variant.name,
145
+ typeName: getPerContentTypeName(tsBaseName, variant.suffix),
146
+ description,
147
+ skipImportNames: [],
148
+ })),
149
+ { schema: unionSchema, name: baseName, typeName: tsBaseName, description, skipImportNames: variants.map((variant) => variant.name) },
150
+ ]
151
+ }
152
+
153
+ const responseUnits = node.responses.flatMap((response) =>
154
+ expandContentUnits(
155
+ response.content ?? [],
156
+ resolver.resolveResponseStatusName(node, response.statusCode),
157
+ tsResolver.resolveResponseStatusName(node, response.statusCode),
158
+ response.description,
159
+ ),
160
+ )
161
+ const dataUnits = expandContentUnits(
162
+ node.requestBody?.content ?? [],
163
+ resolver.resolveDataName(node),
164
+ tsResolver.resolveDataName(node),
165
+ node.requestBody?.description,
166
+ (schema) => ({ ...schema, description: node.requestBody?.description ?? schema.description }),
167
+ )
134
168
  const responseName = resolver.resolveResponseName(node)
135
169
  const localHelperNames = new Set([
136
170
  ...paramEntries.map((entry) => entry.name),
137
- ...responseEntries.map((entry) => entry.name),
138
- ...(dataEntry ? [dataEntry.name] : []),
171
+ ...responseUnits.map((unit) => unit.name),
172
+ ...dataUnits.map((unit) => unit.name),
139
173
  responseName,
140
174
  ])
175
+ const cyclicSchemas = new Set<string>(ctx.meta.circularNames)
176
+
141
177
  const meta = {
142
- file: resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group }),
178
+ file: resolver.resolveFile(
179
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
180
+ { root, output, group: group ?? undefined },
181
+ ),
143
182
  typeFile: tsResolver.resolveFile(
144
183
  {
145
184
  name: node.operationId,
@@ -150,7 +189,7 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
150
189
  {
151
190
  root,
152
191
  output: pluginTs.options?.output ?? output,
153
- group: pluginTs.options?.group,
192
+ group: pluginTs.options?.group ?? undefined,
154
193
  },
155
194
  ),
156
195
  } as const
@@ -159,7 +198,7 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
159
198
  return adapter
160
199
  .getImports(schema, (schemaName) => ({
161
200
  name: resolver.resolveName(schemaName),
162
- path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group }).path,
201
+ path: resolver.resolveFile({ name: schemaName, extname: '.ts' }, { root, output, group: group ?? undefined }).path,
163
202
  }))
164
203
  .filter((entry) => entry.path !== meta.file.path)
165
204
  }
@@ -182,7 +221,6 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
182
221
  }
183
222
 
184
223
  const canOverride = canOverrideSchema(schema)
185
- const cyclicSchemas = adapter.inputNode ? ast.findCircularSchemas(adapter.inputNode.schemas) : undefined
186
224
  const printerInstance = printerFaker({
187
225
  resolver,
188
226
  schemaName: name,
@@ -230,8 +268,8 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
230
268
  baseName={meta.file.baseName}
231
269
  path={meta.file.path}
232
270
  meta={meta.file.meta}
233
- banner={resolver.resolveBanner(adapter.inputNode, { output, config })}
234
- footer={resolver.resolveFooter(adapter.inputNode, { output, config })}
271
+ banner={resolver.resolveBanner(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
272
+ footer={resolver.resolveFooter(ctx.meta, { output, config, file: { path: meta.file.path, baseName: meta.file.baseName } })}
235
273
  >
236
274
  <File.Import name={locale ? [{ propertyName: localeToFakerImport(locale), name: 'faker' }] : ['faker']} path="@faker-js/faker" />
237
275
  {regexGenerator === 'randexp' && <File.Import name={'RandExp'} path={'randexp'} />}
@@ -243,27 +281,29 @@ export const fakerGenerator = defineGenerator<PluginFaker>({
243
281
  typeName,
244
282
  }),
245
283
  )}
246
- {responseEntries.map(({ response, name, typeName }) =>
284
+ {responseUnits.map((unit) =>
247
285
  renderEntry({
248
- schema: response.schema,
249
- name,
250
- typeName,
251
- description: response.description,
286
+ schema: unit.schema,
287
+ name: unit.name,
288
+ typeName: unit.typeName,
289
+ description: unit.description,
290
+ skipImportNames: unit.skipImportNames,
291
+ }),
292
+ )}
293
+ {dataUnits.map((unit) =>
294
+ renderEntry({
295
+ schema: unit.schema,
296
+ name: unit.name,
297
+ typeName: unit.typeName,
298
+ description: unit.description,
299
+ skipImportNames: unit.skipImportNames,
252
300
  }),
253
301
  )}
254
- {dataEntry
255
- ? renderEntry({
256
- schema: dataEntry.schema,
257
- name: dataEntry.name,
258
- typeName: dataEntry.typeName,
259
- description: dataEntry.description,
260
- })
261
- : null}
262
302
  {renderEntry({
263
303
  schema: buildResponseUnionSchema(node, resolver),
264
304
  name: responseName,
265
305
  typeName: tsResolver.resolveResponseName(node),
266
- skipImportNames: responseEntries.map(({ name }) => name),
306
+ skipImportNames: responseUnits.map((unit) => unit.name),
267
307
  })}
268
308
  </File>
269
309
  )
package/src/plugin.ts CHANGED
@@ -1,22 +1,39 @@
1
- import { camelCase } from '@internals/utils'
2
- import { definePlugin, type Group } from '@kubb/core'
1
+ import { createGroupConfig } from '@internals/shared'
2
+ import { definePlugin } from '@kubb/core'
3
3
  import { pluginTsName } from '@kubb/plugin-ts'
4
4
  import { fakerGenerator } from './generators/fakerGenerator.tsx'
5
5
  import { resolverFaker } from './resolvers/resolverFaker.ts'
6
6
  import type { PluginFaker } from './types.ts'
7
7
 
8
8
  /**
9
- * Canonical plugin name for `@kubb/plugin-faker`, used in driver lookups and warnings.
9
+ * Canonical plugin name for `@kubb/plugin-faker`. Used for driver lookups and
10
+ * cross-plugin dependency references.
10
11
  */
11
12
  export const pluginFakerName = 'plugin-faker' satisfies PluginFaker['name']
12
13
 
13
14
  /**
14
- * Generates Faker mock data factories from OpenAPI/AST specification.
15
- *
16
- * Creates randomized test data and mock helpers from schema definitions.
15
+ * Generates one mock-data factory per OpenAPI schema using Faker.js. Call
16
+ * `createPet()` to get a realistic `Pet` object. Useful for tests, Storybook,
17
+ * and local development without a running backend.
17
18
  *
18
19
  * @example
19
- * `import pluginFaker from '@kubb/plugin-faker'; export default defineConfig({ plugins: [pluginFaker({ output: { path: 'mocks' } })], })`
20
+ * ```ts
21
+ * import { defineConfig } from 'kubb'
22
+ * import { pluginTs } from '@kubb/plugin-ts'
23
+ * import { pluginFaker } from '@kubb/plugin-faker'
24
+ *
25
+ * export default defineConfig({
26
+ * input: { path: './petStore.yaml' },
27
+ * output: { path: './src/gen' },
28
+ * plugins: [
29
+ * pluginTs(),
30
+ * pluginFaker({
31
+ * output: { path: './mocks' },
32
+ * seed: [100],
33
+ * }),
34
+ * ],
35
+ * })
36
+ * ```
20
37
  */
21
38
  export const pluginFaker = definePlugin<PluginFaker>((options) => {
22
39
  const {
@@ -37,20 +54,7 @@ export const pluginFaker = definePlugin<PluginFaker>((options) => {
37
54
  transformer: userTransformer,
38
55
  } = options
39
56
 
40
- const groupConfig = group
41
- ? ({
42
- ...group,
43
- name: group.name
44
- ? group.name
45
- : (ctx: { group: string }) => {
46
- if (group.type === 'path') {
47
- return `${ctx.group.split('/')[1]}`
48
- }
49
-
50
- return `${camelCase(ctx.group)}Controller`
51
- },
52
- } satisfies Group)
53
- : undefined
57
+ const groupConfig = createGroupConfig(group, { suffix: 'Controller', honorName: true })
54
58
 
55
59
  return {
56
60
  name: pluginFakerName,