@kubb/plugin-faker 5.0.0-beta.42 → 5.0.0-beta.64
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/{Faker-SBhWTdC7.d.ts → Faker-BA4l8DTe.d.ts} +2 -2
- package/dist/{Faker-DBPx_MVh.js → Faker-DUx7jvCo.js} +10 -55
- package/dist/Faker-DUx7jvCo.js.map +1 -0
- package/dist/{Faker-DRL0W5Lt.cjs → Faker-Ds2xP2-k.cjs} +11 -62
- package/dist/Faker-Ds2xP2-k.cjs.map +1 -0
- package/dist/components.cjs +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/components.js +1 -1
- package/dist/{fakerGenerator-Duc28_FK.d.ts → fakerGenerator-BNysC6rh.d.ts} +2 -2
- package/dist/{fakerGenerator-CVOr0Pwm.cjs → fakerGenerator-BeKRKYuy.cjs} +26 -60
- package/dist/fakerGenerator-BeKRKYuy.cjs.map +1 -0
- package/dist/{fakerGenerator-DNJ61yLj.js → fakerGenerator-D5Bcy5WY.js} +25 -59
- package/dist/fakerGenerator-D5Bcy5WY.js.map +1 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +1 -1
- package/dist/generators.js +1 -1
- package/dist/index.cjs +47 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +47 -44
- package/dist/index.js.map +1 -1
- package/dist/{printerFaker-DXS861Q0.d.ts → printerFaker-BzEB43Jz.d.ts} +11 -15
- package/package.json +8 -16
- package/dist/Faker-DBPx_MVh.js.map +0 -1
- package/dist/Faker-DRL0W5Lt.cjs.map +0 -1
- package/dist/fakerGenerator-CVOr0Pwm.cjs.map +0 -1
- package/dist/fakerGenerator-DNJ61yLj.js.map +0 -1
- package/extension.yaml +0 -819
- package/src/components/Faker.tsx +0 -139
- package/src/components/index.ts +0 -1
- package/src/generators/fakerGenerator.tsx +0 -311
- package/src/generators/index.ts +0 -1
- package/src/index.ts +0 -7
- package/src/plugin.ts +0 -92
- package/src/printers/printerFaker.ts +0 -405
- package/src/resolvers/resolverFaker.ts +0 -84
- package/src/types.ts +0 -185
- package/src/utils.ts +0 -257
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
import { stringify, toRegExpString } from '@internals/utils'
|
|
2
|
-
import { ast } from '@kubb/core'
|
|
3
|
-
import type { PluginFaker, ResolverFaker } from '../types.ts'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Partial map of node-type overrides for the Faker printer. Each key is a
|
|
7
|
-
* `SchemaType` (`'string'`, `'date'`, ...) and each handler returns the
|
|
8
|
-
* Faker expression for that schema as a string. Use `this.transform` to
|
|
9
|
-
* recurse into nested schema nodes and `this.options` to read printer options.
|
|
10
|
-
*
|
|
11
|
-
* @example Override the integer handler
|
|
12
|
-
* ```ts
|
|
13
|
-
* pluginFaker({
|
|
14
|
-
* printer: {
|
|
15
|
-
* nodes: {
|
|
16
|
-
* integer() {
|
|
17
|
-
* return 'faker.number.float()'
|
|
18
|
-
* },
|
|
19
|
-
* },
|
|
20
|
-
* },
|
|
21
|
-
* })
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export type PrinterFakerNodes = ast.PrinterPartial<string, PrinterFakerOptions>
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Options passed to the Faker printer at instantiation: the parser library
|
|
28
|
-
* for date strings, the regex generator, the user-supplied schema-name
|
|
29
|
-
* mapper, and the resolver used to compute identifiers.
|
|
30
|
-
*/
|
|
31
|
-
export type PrinterFakerOptions = {
|
|
32
|
-
dateParser?: PluginFaker['resolvedOptions']['dateParser']
|
|
33
|
-
regexGenerator?: PluginFaker['resolvedOptions']['regexGenerator']
|
|
34
|
-
mapper?: PluginFaker['resolvedOptions']['mapper']
|
|
35
|
-
resolver: ResolverFaker
|
|
36
|
-
typeName?: string
|
|
37
|
-
schemaName?: string
|
|
38
|
-
nestedInObject?: boolean
|
|
39
|
-
/**
|
|
40
|
-
* Set while printing the members of a union (`oneOf`). Object properties then index their
|
|
41
|
-
* type as `(NonNullable<T> & Record<K, unknown>)[K]` instead of `NonNullable<T>[K]`, so a key
|
|
42
|
-
* carried by only some branches stays valid (a plain index would be a TS2339).
|
|
43
|
-
*/
|
|
44
|
-
nestedInUnion?: boolean
|
|
45
|
-
nodes?: PrinterFakerNodes
|
|
46
|
-
/**
|
|
47
|
-
* Names of schemas that participate in a circular dependency chain.
|
|
48
|
-
* Properties whose schema transitively references one of these are emitted
|
|
49
|
-
* as lazy getters so that user overrides via the `data` parameter prevent
|
|
50
|
-
* the recursive faker call from ever executing (avoiding stack overflow).
|
|
51
|
-
*/
|
|
52
|
-
cyclicSchemas?: ReadonlySet<string>
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Factory options for the Faker printer, defining input/output types and configuration.
|
|
57
|
-
*/
|
|
58
|
-
export type PrinterFakerFactory = ast.PrinterFactoryOptions<'faker', PrinterFakerOptions, string, string>
|
|
59
|
-
|
|
60
|
-
const fakerKeywordMapper = {
|
|
61
|
-
any: () => 'undefined',
|
|
62
|
-
unknown: () => 'undefined',
|
|
63
|
-
void: () => 'undefined',
|
|
64
|
-
number: (min?: number, max?: number) => {
|
|
65
|
-
if (max !== undefined && min !== undefined) {
|
|
66
|
-
return `faker.number.float({ min: ${min}, max: ${max} })`
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (max !== undefined) {
|
|
70
|
-
return `faker.number.float({ max: ${max} })`
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (min !== undefined) {
|
|
74
|
-
return `faker.number.float({ min: ${min} })`
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return 'faker.number.float()'
|
|
78
|
-
},
|
|
79
|
-
integer: (min?: number, max?: number) => {
|
|
80
|
-
if (max !== undefined && min !== undefined) {
|
|
81
|
-
return `faker.number.int({ min: ${min}, max: ${max} })`
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (max !== undefined) {
|
|
85
|
-
return `faker.number.int({ max: ${max} })`
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (min !== undefined) {
|
|
89
|
-
return `faker.number.int({ min: ${min} })`
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return 'faker.number.int()'
|
|
93
|
-
},
|
|
94
|
-
bigint: () => 'faker.number.bigInt()',
|
|
95
|
-
string: (min?: number, max?: number) => {
|
|
96
|
-
if (max !== undefined && min !== undefined) {
|
|
97
|
-
return `faker.string.alpha({ length: { min: ${min}, max: ${max} } })`
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (max !== undefined) {
|
|
101
|
-
return `faker.string.alpha({ length: ${max} })`
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (min !== undefined) {
|
|
105
|
-
return `faker.string.alpha({ length: ${min} })`
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return 'faker.string.alpha()'
|
|
109
|
-
},
|
|
110
|
-
boolean: () => 'faker.datatype.boolean()',
|
|
111
|
-
null: () => 'null',
|
|
112
|
-
array: (items: Array<string> = [], min?: number, max?: number) => {
|
|
113
|
-
if (items.length > 1) {
|
|
114
|
-
return `faker.helpers.arrayElements([${items.join(', ')}])`
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const item = items.at(0)
|
|
118
|
-
|
|
119
|
-
if (min !== undefined && max !== undefined) {
|
|
120
|
-
return `faker.helpers.multiple(() => (${item}), { count: { min: ${min}, max: ${max} }})`
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (min !== undefined) {
|
|
124
|
-
return `faker.helpers.multiple(() => (${item}), { count: ${min} })`
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (max !== undefined) {
|
|
128
|
-
return `faker.helpers.multiple(() => (${item}), { count: { min: 0, max: ${max} }})`
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return `faker.helpers.multiple(() => (${item}))`
|
|
132
|
-
},
|
|
133
|
-
tuple: (items: Array<string> = []) => `[${items.join(', ')}]`,
|
|
134
|
-
enum: (items: Array<string | number | boolean | undefined> = [], type = 'any') => `faker.helpers.arrayElement<${type}>([${items.join(', ')}])`,
|
|
135
|
-
union: (items: Array<string> = []) => `faker.helpers.arrayElement<any>([${items.join(', ')}])`,
|
|
136
|
-
datetime: () => 'faker.date.anytime().toISOString()',
|
|
137
|
-
date: (representation: 'date' | 'string' = 'string', parser: PluginFaker['resolvedOptions']['dateParser'] = 'faker') => {
|
|
138
|
-
if (representation === 'string') {
|
|
139
|
-
if (parser !== 'faker') {
|
|
140
|
-
return `${parser}(faker.date.anytime()).format("YYYY-MM-DD")`
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return 'faker.date.anytime().toISOString().substring(0, 10)'
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (parser !== 'faker') {
|
|
147
|
-
throw new Error(`type '${representation}' and parser '${parser}' can not work together`)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return 'faker.date.anytime()'
|
|
151
|
-
},
|
|
152
|
-
time: (representation: 'date' | 'string' = 'string', parser: PluginFaker['resolvedOptions']['dateParser'] = 'faker') => {
|
|
153
|
-
if (representation === 'string') {
|
|
154
|
-
if (parser !== 'faker') {
|
|
155
|
-
return `${parser}(faker.date.anytime()).format("HH:mm:ss")`
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return 'faker.date.anytime().toISOString().substring(11, 19)'
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (parser !== 'faker') {
|
|
162
|
-
throw new Error(`type '${representation}' and parser '${parser}' can not work together`)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return 'faker.date.anytime()'
|
|
166
|
-
},
|
|
167
|
-
uuid: () => 'faker.string.uuid()',
|
|
168
|
-
url: () => 'faker.internet.url()',
|
|
169
|
-
and: (items: Array<string> = []) => {
|
|
170
|
-
if (items.length === 0) {
|
|
171
|
-
return '{}'
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (items.length === 1) {
|
|
175
|
-
return items[0] ?? '{}'
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return `{...${items.join(', ...')}}`
|
|
179
|
-
},
|
|
180
|
-
matches: (value = '', regexGenerator: 'faker' | 'randexp' = 'faker') => {
|
|
181
|
-
if (regexGenerator === 'randexp') {
|
|
182
|
-
return `${toRegExpString(value, 'RandExp')}.gen()`
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return `faker.helpers.fromRegExp("${value}")`
|
|
186
|
-
},
|
|
187
|
-
email: () => 'faker.internet.email()',
|
|
188
|
-
blob: () => 'faker.image.url() as unknown as Blob',
|
|
189
|
-
} as const
|
|
190
|
-
|
|
191
|
-
function getEnumValues(node: ast.EnumSchemaNode): Array<string | number | boolean | undefined> {
|
|
192
|
-
if (node.namedEnumValues?.length) {
|
|
193
|
-
return node.namedEnumValues.map((item) => item.value as string | number | boolean | undefined)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return (node.enumValues ?? []) as Array<string | number | boolean | undefined>
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function parseEnumValue(value: string | number | boolean | undefined) {
|
|
200
|
-
if (typeof value === 'string') {
|
|
201
|
-
return stringify(value)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return value
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/** Reads the discriminator literal off a variant, or `undefined` when it can't be determined. */
|
|
208
|
-
function getDiscriminatorValue(member: ast.SchemaNode, discriminatorPropertyName: string) {
|
|
209
|
-
const prop = ast.narrowSchema(member, 'object')?.properties?.find((p) => p.name === discriminatorPropertyName)
|
|
210
|
-
const enumNode = prop ? ast.narrowSchema(prop.schema, 'enum') : null
|
|
211
|
-
|
|
212
|
-
return enumNode ? getEnumValues(enumNode)[0] : undefined
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Type expression for an object property's value, indexed off the parent `typeName`.
|
|
217
|
-
*
|
|
218
|
-
* In a union (`oneOf`), a key that only some branches declare turns a plain `NonNullable<T>[K]`
|
|
219
|
-
* into a TS2339 error, so union members guard the access. The breakdown is below.
|
|
220
|
-
*/
|
|
221
|
-
function indexedTypeName(typeName: string, propertyName: string, nestedInUnion?: boolean): string {
|
|
222
|
-
const key = JSON.stringify(propertyName)
|
|
223
|
-
|
|
224
|
-
// `(NonNullable<T> & Record<K, unknown>)[K]`, read inside-out:
|
|
225
|
-
// NonNullable<T> strips null and undefined from the parent type T.
|
|
226
|
-
// & Record<K, unknown> forces every branch to have key K. A branch that already declares K
|
|
227
|
-
// keeps it (`T[K] & unknown` is `T[K]`); a branch missing K gains it as `unknown`.
|
|
228
|
-
// [K] reads the key, which is now always present, so it never hits TS2339.
|
|
229
|
-
// For a single object T the intersection does nothing, leaving `T[K]`.
|
|
230
|
-
return nestedInUnion ? `(NonNullable<${typeName}> & Record<${key}, unknown>)[${key}]` : `NonNullable<${typeName}>[${key}]`
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Creates a Faker printer that generates mock data generation code from schema nodes.
|
|
235
|
-
* Handles circular references gracefully by emitting memoizing getters for cyclic properties.
|
|
236
|
-
*/
|
|
237
|
-
export const printerFaker: (options: PrinterFakerOptions) => ast.Printer<PrinterFakerFactory> = ast.definePrinter<PrinterFakerFactory>((options) => {
|
|
238
|
-
const printNested = (node: ast.SchemaNode, overrideOptions: Partial<PrinterFakerOptions> = {}): string => {
|
|
239
|
-
return (
|
|
240
|
-
printerFaker({
|
|
241
|
-
...options,
|
|
242
|
-
...overrideOptions,
|
|
243
|
-
nodes: options.nodes,
|
|
244
|
-
}).print(node) ?? 'undefined'
|
|
245
|
-
)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return {
|
|
249
|
-
name: 'faker',
|
|
250
|
-
options,
|
|
251
|
-
nodes: {
|
|
252
|
-
any: () => fakerKeywordMapper.any(),
|
|
253
|
-
unknown: () => fakerKeywordMapper.unknown(),
|
|
254
|
-
void: () => fakerKeywordMapper.void(),
|
|
255
|
-
boolean: () => fakerKeywordMapper.boolean(),
|
|
256
|
-
null: () => fakerKeywordMapper.null(),
|
|
257
|
-
string(node) {
|
|
258
|
-
if (node.pattern) {
|
|
259
|
-
return fakerKeywordMapper.matches(node.pattern, this.options.regexGenerator)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return fakerKeywordMapper.string(node.min, node.max)
|
|
263
|
-
},
|
|
264
|
-
email: () => fakerKeywordMapper.email(),
|
|
265
|
-
url: () => fakerKeywordMapper.url(),
|
|
266
|
-
uuid: () => fakerKeywordMapper.uuid(),
|
|
267
|
-
number(node) {
|
|
268
|
-
return fakerKeywordMapper.number(node.min, node.max)
|
|
269
|
-
},
|
|
270
|
-
integer(node) {
|
|
271
|
-
return fakerKeywordMapper.integer(node.min, node.max)
|
|
272
|
-
},
|
|
273
|
-
bigint: () => fakerKeywordMapper.bigint(),
|
|
274
|
-
blob: () => fakerKeywordMapper.blob(),
|
|
275
|
-
datetime: () => fakerKeywordMapper.datetime(),
|
|
276
|
-
date(node) {
|
|
277
|
-
return fakerKeywordMapper.date(node.representation ?? 'string', this.options.dateParser)
|
|
278
|
-
},
|
|
279
|
-
time(node) {
|
|
280
|
-
return fakerKeywordMapper.time(node.representation ?? 'string', this.options.dateParser)
|
|
281
|
-
},
|
|
282
|
-
ref(node) {
|
|
283
|
-
// Parser-generated refs (with $ref) carry raw schema names that need resolving.
|
|
284
|
-
// Use the canonical name from the $ref path — node.name may have been overridden
|
|
285
|
-
// (e.g. by single-member allOf flatten using the property-derived child name).
|
|
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)
|
|
288
|
-
|
|
289
|
-
if (!refName) {
|
|
290
|
-
throw new Error('Name not defined for ref node')
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (this.options.schemaName && refName === this.options.schemaName) {
|
|
294
|
-
return 'undefined as any'
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Internal helper refs (for generated response/data helpers) are already
|
|
298
|
-
// emitted with resolver output and should not be transformed twice.
|
|
299
|
-
const resolvedName = node.ref ? this.options.resolver.resolveName(refName) : refName
|
|
300
|
-
|
|
301
|
-
if (!this.options.nestedInObject) {
|
|
302
|
-
return `${resolvedName}(data)`
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
return `${resolvedName}()`
|
|
306
|
-
},
|
|
307
|
-
enum(node) {
|
|
308
|
-
return fakerKeywordMapper.enum(getEnumValues(node).map(parseEnumValue), this.options.typeName)
|
|
309
|
-
},
|
|
310
|
-
union(node): string {
|
|
311
|
-
const { discriminatorPropertyName } = node
|
|
312
|
-
const baseTypeName = this.options.typeName
|
|
313
|
-
|
|
314
|
-
const items: Array<string> = (node.members ?? [])
|
|
315
|
-
.map((member) => {
|
|
316
|
-
// For a discriminated union, narrow each variant to its own branch so nested
|
|
317
|
-
// `NonNullable<T>[K]` indexes resolve against that branch instead of the whole union.
|
|
318
|
-
const value = discriminatorPropertyName ? getDiscriminatorValue(member, discriminatorPropertyName) : undefined
|
|
319
|
-
|
|
320
|
-
if (baseTypeName && value !== undefined) {
|
|
321
|
-
const typeName = `Extract<NonNullable<${baseTypeName}>, { ${JSON.stringify(discriminatorPropertyName)}: ${parseEnumValue(value)} }>`
|
|
322
|
-
|
|
323
|
-
return printNested(member, { typeName, nestedInObject: true })
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Without a discriminator, keep the union type but guard each indexed access (see
|
|
327
|
-
// `indexedTypeName`) so a key carried by only some branches resolves to `unknown`
|
|
328
|
-
// rather than erroring with TS2339.
|
|
329
|
-
return printNested(member, { typeName: baseTypeName, nestedInObject: true, nestedInUnion: true })
|
|
330
|
-
})
|
|
331
|
-
.filter((item): item is string => Boolean(item))
|
|
332
|
-
|
|
333
|
-
return fakerKeywordMapper.union(items)
|
|
334
|
-
},
|
|
335
|
-
intersection(node): string {
|
|
336
|
-
const items: Array<string> = (node.members ?? [])
|
|
337
|
-
.map((member) =>
|
|
338
|
-
printNested(member, {
|
|
339
|
-
nestedInObject: true,
|
|
340
|
-
}),
|
|
341
|
-
)
|
|
342
|
-
.filter((item): item is string => Boolean(item))
|
|
343
|
-
|
|
344
|
-
return fakerKeywordMapper.and(items)
|
|
345
|
-
},
|
|
346
|
-
array(node): string {
|
|
347
|
-
const items: Array<string> = (node.items ?? [])
|
|
348
|
-
.map((member) =>
|
|
349
|
-
printNested(member, {
|
|
350
|
-
typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[number]` : undefined,
|
|
351
|
-
nestedInObject: true,
|
|
352
|
-
}),
|
|
353
|
-
)
|
|
354
|
-
.filter((item): item is string => Boolean(item))
|
|
355
|
-
|
|
356
|
-
return fakerKeywordMapper.array(items, node.min, node.max)
|
|
357
|
-
},
|
|
358
|
-
tuple(node): string {
|
|
359
|
-
const items: Array<string> = (node.items ?? [])
|
|
360
|
-
.map((member, index) =>
|
|
361
|
-
printNested(member, {
|
|
362
|
-
typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[${index}]` : undefined,
|
|
363
|
-
nestedInObject: true,
|
|
364
|
-
}),
|
|
365
|
-
)
|
|
366
|
-
.filter((item): item is string => Boolean(item))
|
|
367
|
-
|
|
368
|
-
return fakerKeywordMapper.tuple(items)
|
|
369
|
-
},
|
|
370
|
-
object(node): string {
|
|
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
|
-
}
|
|
377
|
-
|
|
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
|
-
}
|
|
392
|
-
|
|
393
|
-
return `"${property.name}": ${value}`
|
|
394
|
-
})
|
|
395
|
-
.join(',')
|
|
396
|
-
|
|
397
|
-
return `{${properties}}`
|
|
398
|
-
},
|
|
399
|
-
...options.nodes,
|
|
400
|
-
},
|
|
401
|
-
print(node) {
|
|
402
|
-
return this.transform(node) ?? null
|
|
403
|
-
},
|
|
404
|
-
}
|
|
405
|
-
})
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { camelCase, ensureValidVarName } from '@internals/utils'
|
|
4
|
-
import { defineResolver, KubbDriver } from '@kubb/core'
|
|
5
|
-
import type { PluginFaker } from '../types.ts'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Default resolver used by `@kubb/plugin-faker`. Decides the names and file
|
|
9
|
-
* paths for every generated mock factory. Functions and files are prefixed
|
|
10
|
-
* with `create` so `Pet` becomes `createPet`.
|
|
11
|
-
*
|
|
12
|
-
* @example Resolve a factory name
|
|
13
|
-
* ```ts
|
|
14
|
-
* import { resolverFaker } from '@kubb/plugin-faker'
|
|
15
|
-
*
|
|
16
|
-
* resolverFaker.default('list pets', 'function') // 'createListPets'
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
export const resolverFaker = defineResolver<PluginFaker>(() => {
|
|
20
|
-
return {
|
|
21
|
-
name: 'default',
|
|
22
|
-
pluginName: 'plugin-faker',
|
|
23
|
-
default(name, type) {
|
|
24
|
-
const resolvedName = camelCase(name, { isFile: type === 'file', prefix: 'create' })
|
|
25
|
-
return type === 'file' ? resolvedName : ensureValidVarName(resolvedName)
|
|
26
|
-
},
|
|
27
|
-
resolveName(name, type) {
|
|
28
|
-
return this.default(name, type)
|
|
29
|
-
},
|
|
30
|
-
resolvePathName(name, type) {
|
|
31
|
-
return this.default(name, type)
|
|
32
|
-
},
|
|
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}`
|
|
36
|
-
const filePath = this.resolvePath(
|
|
37
|
-
{
|
|
38
|
-
baseName,
|
|
39
|
-
pathMode,
|
|
40
|
-
tag,
|
|
41
|
-
path: groupPath,
|
|
42
|
-
},
|
|
43
|
-
context,
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
kind: 'File',
|
|
48
|
-
id: createHash('sha256').update(filePath).digest('hex'),
|
|
49
|
-
name: path.basename(filePath, extname),
|
|
50
|
-
path: filePath,
|
|
51
|
-
baseName,
|
|
52
|
-
extname,
|
|
53
|
-
meta: { pluginName: this.pluginName },
|
|
54
|
-
sources: [],
|
|
55
|
-
imports: [],
|
|
56
|
-
exports: [],
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
resolveParamName(node, param) {
|
|
60
|
-
return this.resolveName(`${node.operationId} ${param.in} ${param.name}`)
|
|
61
|
-
},
|
|
62
|
-
resolveDataName(node) {
|
|
63
|
-
return this.resolveName(`${node.operationId} Data`)
|
|
64
|
-
},
|
|
65
|
-
resolveResponseStatusName(node, statusCode) {
|
|
66
|
-
return this.resolveName(`${node.operationId} Status ${statusCode}`)
|
|
67
|
-
},
|
|
68
|
-
resolveResponseName(node) {
|
|
69
|
-
return this.resolveName(`${node.operationId} Response`)
|
|
70
|
-
},
|
|
71
|
-
resolveResponsesName(node) {
|
|
72
|
-
return this.resolveName(`${node.operationId} Responses`)
|
|
73
|
-
},
|
|
74
|
-
resolvePathParamsName(node, param) {
|
|
75
|
-
return this.resolveParamName(node, param)
|
|
76
|
-
},
|
|
77
|
-
resolveQueryParamsName(node, param) {
|
|
78
|
-
return this.resolveParamName(node, param)
|
|
79
|
-
},
|
|
80
|
-
resolveHeaderParamsName(node, param) {
|
|
81
|
-
return this.resolveParamName(node, param)
|
|
82
|
-
},
|
|
83
|
-
}
|
|
84
|
-
})
|
package/src/types.ts
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
|
|
2
|
-
import type { PrinterFakerNodes } from './printers/printerFaker.ts'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Resolver for Faker that provides naming methods for mock functions.
|
|
6
|
-
*/
|
|
7
|
-
export type ResolverFaker = Resolver &
|
|
8
|
-
ast.OperationParamsResolver & {
|
|
9
|
-
/**
|
|
10
|
-
* Resolves the faker function name for a schema.
|
|
11
|
-
*
|
|
12
|
-
* @example Resolving faker function names
|
|
13
|
-
* `resolver.resolveName('show pet by id') // -> 'showPetById'`
|
|
14
|
-
*/
|
|
15
|
-
resolveName(this: ResolverFaker, name: string, type?: 'file' | 'function' | 'type' | 'const'): string
|
|
16
|
-
/**
|
|
17
|
-
* Resolves the output file name for a faker module.
|
|
18
|
-
*
|
|
19
|
-
* @example Resolving faker file names
|
|
20
|
-
* `resolver.resolvePathName('show pet by id', 'file') // -> 'showPetById'`
|
|
21
|
-
*/
|
|
22
|
-
resolvePathName(this: ResolverFaker, name: string, type?: 'file' | 'function' | 'type' | 'const'): string
|
|
23
|
-
/**
|
|
24
|
-
* Resolves the faker function name for a request body.
|
|
25
|
-
*
|
|
26
|
-
* @example Resolving data function names
|
|
27
|
-
* `resolver.resolveDataName(node) // -> 'createPetsData'`
|
|
28
|
-
*/
|
|
29
|
-
resolveDataName(this: ResolverFaker, node: ast.OperationNode): string
|
|
30
|
-
/**
|
|
31
|
-
* Resolves the faker function name for a response by status code.
|
|
32
|
-
*
|
|
33
|
-
* @example Response status names
|
|
34
|
-
* `resolver.resolveResponseStatusName(node, 200) // -> 'listPetsStatus200'`
|
|
35
|
-
*/
|
|
36
|
-
resolveResponseStatusName(this: ResolverFaker, node: ast.OperationNode, statusCode: ast.StatusCode): string
|
|
37
|
-
/**
|
|
38
|
-
* Resolves the faker function name for the response union.
|
|
39
|
-
*
|
|
40
|
-
* @example Response union names
|
|
41
|
-
* `resolver.resolveResponseName(node) // -> 'listPetsResponse'`
|
|
42
|
-
*/
|
|
43
|
-
resolveResponseName(this: ResolverFaker, node: ast.OperationNode): string
|
|
44
|
-
/**
|
|
45
|
-
* Resolves the faker function name for the response collection.
|
|
46
|
-
*
|
|
47
|
-
* @example Responses collection names
|
|
48
|
-
* `resolver.resolveResponsesName(node) // -> 'listPetsResponses'`
|
|
49
|
-
*/
|
|
50
|
-
resolveResponsesName(this: ResolverFaker, node: ast.OperationNode): string
|
|
51
|
-
/**
|
|
52
|
-
* Resolves the faker function name for path parameters.
|
|
53
|
-
*
|
|
54
|
-
* @example Path parameters names
|
|
55
|
-
* `resolver.resolvePathParamsName(node, param) // -> 'showPetByIdPathPetId'`
|
|
56
|
-
*/
|
|
57
|
-
resolvePathParamsName(this: ResolverFaker, node: ast.OperationNode, param: ast.ParameterNode): string
|
|
58
|
-
/**
|
|
59
|
-
* Resolves the faker function name for query parameters.
|
|
60
|
-
*
|
|
61
|
-
* @example Query parameters names
|
|
62
|
-
* `resolver.resolveQueryParamsName(node, param) // -> 'listPetsQueryLimit'`
|
|
63
|
-
*/
|
|
64
|
-
resolveQueryParamsName(this: ResolverFaker, node: ast.OperationNode, param: ast.ParameterNode): string
|
|
65
|
-
/**
|
|
66
|
-
* Resolves the faker function name for header parameters.
|
|
67
|
-
*
|
|
68
|
-
* @example Header parameters names
|
|
69
|
-
* `resolver.resolveHeaderParamsName(node, param) // -> 'deletePetHeaderApiKey'`
|
|
70
|
-
*/
|
|
71
|
-
resolveHeaderParamsName(this: ResolverFaker, node: ast.OperationNode, param: ast.ParameterNode): string
|
|
72
|
-
}
|
|
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
|
|
85
|
-
/**
|
|
86
|
-
* Skip operations matching at least one entry in the list.
|
|
87
|
-
*/
|
|
88
|
-
exclude?: Array<Exclude>
|
|
89
|
-
/**
|
|
90
|
-
* Restrict generation to operations matching at least one entry in the list.
|
|
91
|
-
*/
|
|
92
|
-
include?: Array<Include>
|
|
93
|
-
/**
|
|
94
|
-
* Apply a different options object to operations matching a pattern.
|
|
95
|
-
*/
|
|
96
|
-
override?: Array<Override<ResolvedOptions>>
|
|
97
|
-
/**
|
|
98
|
-
* Library used to format string-represented date, time, and datetime fields.
|
|
99
|
-
* Any library exporting a default function works; Kubb adds the import for you.
|
|
100
|
-
*
|
|
101
|
-
* @default 'faker'
|
|
102
|
-
*/
|
|
103
|
-
dateParser?: 'faker' | 'dayjs' | 'moment' | (string & {})
|
|
104
|
-
/**
|
|
105
|
-
* Library used to generate strings that satisfy a regex `pattern` keyword.
|
|
106
|
-
* - `'faker'` uses `faker.helpers.fromRegExp`. No extra dependency.
|
|
107
|
-
* - `'randexp'` uses the `randexp` package. Supports a wider regex grammar.
|
|
108
|
-
*
|
|
109
|
-
* @default 'faker'
|
|
110
|
-
*/
|
|
111
|
-
regexGenerator?: 'faker' | 'randexp'
|
|
112
|
-
/**
|
|
113
|
-
* Map a schema name to a custom Faker expression. Use this when the schema name
|
|
114
|
-
* does not give Faker enough context (`'email'`, `'avatarUrl'`, `'phoneNumber'`).
|
|
115
|
-
*/
|
|
116
|
-
mapper?: Record<string, string>
|
|
117
|
-
/**
|
|
118
|
-
* Faker locale code. Switches the named import to `fakerXX` from `@faker-js/faker`
|
|
119
|
-
* so names, addresses, and phone numbers reflect the target region.
|
|
120
|
-
*
|
|
121
|
-
* @default 'en'
|
|
122
|
-
* @example German
|
|
123
|
-
* `locale: 'de'`
|
|
124
|
-
* @example Austrian German
|
|
125
|
-
* `locale: 'de_AT'`
|
|
126
|
-
* @see https://fakerjs.dev/api/localization.html
|
|
127
|
-
*/
|
|
128
|
-
locale?: string
|
|
129
|
-
/**
|
|
130
|
-
* Value passed to `faker.seed(...)`. Set this for deterministic mock output,
|
|
131
|
-
* which is useful for snapshot tests.
|
|
132
|
-
*/
|
|
133
|
-
seed?: number | Array<number>
|
|
134
|
-
/**
|
|
135
|
-
* Rename properties inside path/query/header mocks. Body mocks are unaffected.
|
|
136
|
-
*
|
|
137
|
-
* @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
|
|
138
|
-
*/
|
|
139
|
-
paramsCasing?: 'camelcase'
|
|
140
|
-
/**
|
|
141
|
-
* Custom generators that run alongside the built-in Faker generators.
|
|
142
|
-
*/
|
|
143
|
-
generators?: Array<Generator<PluginFaker>>
|
|
144
|
-
/**
|
|
145
|
-
* Override the naming of generated factory helpers. Common use: append `Mock` or
|
|
146
|
-
* `Factory` so helpers do not clash with imported types.
|
|
147
|
-
*/
|
|
148
|
-
resolver?: Partial<ResolverFaker> & ThisType<ResolverFaker>
|
|
149
|
-
/**
|
|
150
|
-
* AST visitor applied to schema and operation nodes before printing.
|
|
151
|
-
*/
|
|
152
|
-
transformer?: ast.Visitor
|
|
153
|
-
/**
|
|
154
|
-
* Replace the Faker handler for a specific schema type (`'integer'`, `'date'`, ...).
|
|
155
|
-
* Each handler returns the Faker expression as a string.
|
|
156
|
-
*/
|
|
157
|
-
printer?: {
|
|
158
|
-
nodes?: PrinterFakerNodes
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
type ResolvedOptions = {
|
|
163
|
-
output: Output
|
|
164
|
-
group: Group | null
|
|
165
|
-
exclude: NonNullable<Options['exclude']>
|
|
166
|
-
include: Options['include']
|
|
167
|
-
override: NonNullable<Options['override']>
|
|
168
|
-
dateParser: NonNullable<Options['dateParser']>
|
|
169
|
-
regexGenerator: NonNullable<Options['regexGenerator']>
|
|
170
|
-
mapper: NonNullable<Options['mapper']>
|
|
171
|
-
seed: NonNullable<Options['seed']> | undefined
|
|
172
|
-
locale: Options['locale']
|
|
173
|
-
paramsCasing: Options['paramsCasing']
|
|
174
|
-
printer: Options['printer']
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export type PluginFaker = PluginFactoryOptions<'plugin-faker', Options, ResolvedOptions, ResolverFaker>
|
|
178
|
-
|
|
179
|
-
declare global {
|
|
180
|
-
namespace Kubb {
|
|
181
|
-
interface PluginRegistry {
|
|
182
|
-
'plugin-faker': PluginFaker
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|