@kubb/plugin-faker 5.0.0-beta.4 → 5.0.0-beta.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -22
- package/dist/{Faker-CdyPfOPg.d.ts → Faker-A5UuxwJj.d.ts} +3 -3
- package/dist/{Faker-fcQEB9i5.js → Faker-CHh0JtBG.js} +41 -145
- package/dist/Faker-CHh0JtBG.js.map +1 -0
- package/dist/{Faker-BgleOzVN.cjs → Faker-CcGjn5ZM.cjs} +40 -174
- package/dist/Faker-CcGjn5ZM.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-D7daHCh6.js → fakerGenerator-DDNsdbH2.js} +237 -94
- package/dist/fakerGenerator-DDNsdbH2.js.map +1 -0
- package/dist/{fakerGenerator-VJEVzLjc.cjs → fakerGenerator-DrwGWYwv.cjs} +240 -97
- package/dist/fakerGenerator-DrwGWYwv.cjs.map +1 -0
- package/dist/fakerGenerator-KKVr-CA2.d.ts +14 -0
- package/dist/generators.cjs +1 -1
- package/dist/generators.d.ts +1 -1
- package/dist/generators.js +1 -1
- package/dist/index.cjs +240 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +35 -15
- package/dist/index.js +241 -70
- package/dist/index.js.map +1 -1
- package/dist/{printerFaker-CJiwzoto.d.ts → printerFaker-CMCJT3FB.d.ts} +68 -35
- package/package.json +12 -22
- package/src/components/Faker.tsx +51 -65
- package/src/generators/fakerGenerator.tsx +108 -72
- package/src/plugin.ts +27 -23
- package/src/printers/printerFaker.ts +102 -40
- package/src/resolvers/resolverFaker.ts +31 -39
- package/src/types.ts +40 -31
- package/src/utils.ts +7 -106
- package/dist/Faker-BgleOzVN.cjs.map +0 -1
- package/dist/Faker-fcQEB9i5.js.map +0 -1
- package/dist/fakerGenerator-C3Ho3BaI.d.ts +0 -9
- package/dist/fakerGenerator-D7daHCh6.js.map +0 -1
- package/dist/fakerGenerator-VJEVzLjc.cjs.map +0 -1
- package/extension.yaml +0 -364
- /package/dist/{chunk--u3MIqq1.js → chunk-C0LytTxp.js} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as __name } from "./chunk
|
|
2
|
-
import { Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver, ast } from "@kubb/core";
|
|
1
|
+
import { t as __name } from "./chunk-C0LytTxp.js";
|
|
2
|
+
import { Exclude, Generator, Group, Include, Output, OutputOptions, Override, PluginFactoryOptions, Resolver, ast } from "@kubb/core";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
5
5
|
/**
|
|
@@ -41,6 +41,13 @@ type ResolverFaker = Resolver & ast.OperationParamsResolver & {
|
|
|
41
41
|
* `resolver.resolveResponseName(node) // -> 'listPetsResponse'`
|
|
42
42
|
*/
|
|
43
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;
|
|
44
51
|
/**
|
|
45
52
|
* Resolves the faker function name for path parameters.
|
|
46
53
|
*
|
|
@@ -63,82 +70,84 @@ type ResolverFaker = Resolver & ast.OperationParamsResolver & {
|
|
|
63
70
|
*/
|
|
64
71
|
resolveHeaderParamsName(this: ResolverFaker, node: ast.OperationNode, param: ast.ParameterNode): string;
|
|
65
72
|
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
* Group the Faker mocks based on the provided name.
|
|
74
|
-
*/
|
|
75
|
-
group?: Group;
|
|
73
|
+
/**
|
|
74
|
+
* Where the generated mock factories are written and how they are exported, plus the optional
|
|
75
|
+
* `group` strategy. The `group` option organizes `output.mode: 'directory'` output into per-tag or per-path subdirectories.
|
|
76
|
+
*
|
|
77
|
+
* @default { path: 'mocks', barrel: { type: 'named' } }
|
|
78
|
+
*/
|
|
79
|
+
type Options = OutputOptions & {
|
|
76
80
|
/**
|
|
77
|
-
*
|
|
81
|
+
* Skip operations matching at least one entry in the list.
|
|
78
82
|
*/
|
|
79
83
|
exclude?: Array<Exclude>;
|
|
80
84
|
/**
|
|
81
|
-
*
|
|
85
|
+
* Restrict generation to operations matching at least one entry in the list.
|
|
82
86
|
*/
|
|
83
87
|
include?: Array<Include>;
|
|
84
88
|
/**
|
|
85
|
-
*
|
|
89
|
+
* Apply a different options object to operations matching a pattern.
|
|
86
90
|
*/
|
|
87
91
|
override?: Array<Override<ResolvedOptions>>;
|
|
88
92
|
/**
|
|
89
|
-
*
|
|
93
|
+
* Library used to format string-represented date, time, and datetime fields.
|
|
94
|
+
* Any library exporting a default function works; Kubb adds the import for you.
|
|
90
95
|
*
|
|
91
96
|
* @default 'faker'
|
|
92
97
|
*/
|
|
93
98
|
dateParser?: 'faker' | 'dayjs' | 'moment' | (string & {});
|
|
94
99
|
/**
|
|
95
|
-
*
|
|
100
|
+
* Library used to generate strings that satisfy a regex `pattern` keyword.
|
|
101
|
+
* - `'faker'` uses `faker.helpers.fromRegExp`. No extra dependency.
|
|
102
|
+
* - `'randexp'` uses the `randexp` package. Supports a wider regex grammar.
|
|
96
103
|
*
|
|
97
104
|
* @default 'faker'
|
|
98
105
|
*/
|
|
99
106
|
regexGenerator?: 'faker' | 'randexp';
|
|
100
107
|
/**
|
|
101
|
-
*
|
|
108
|
+
* Map a schema name to a custom Faker expression. Use this when the schema name
|
|
109
|
+
* does not give Faker enough context (`'email'`, `'avatarUrl'`, `'phoneNumber'`).
|
|
102
110
|
*/
|
|
103
111
|
mapper?: Record<string, string>;
|
|
104
112
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* and phone numbers reflect the target region.
|
|
113
|
+
* Faker locale code. Switches the named import to `fakerXX` from `@faker-js/faker`
|
|
114
|
+
* so names, addresses, and phone numbers reflect the target region.
|
|
108
115
|
*
|
|
109
116
|
* @default 'en'
|
|
110
|
-
*
|
|
111
117
|
* @example German
|
|
112
118
|
* `locale: 'de'`
|
|
113
|
-
*
|
|
114
119
|
* @example Austrian German
|
|
115
120
|
* `locale: 'de_AT'`
|
|
116
|
-
*
|
|
117
121
|
* @see https://fakerjs.dev/api/localization.html
|
|
118
122
|
*/
|
|
119
123
|
locale?: string;
|
|
120
124
|
/**
|
|
121
|
-
*
|
|
125
|
+
* Value passed to `faker.seed(...)`. Set this for deterministic mock output,
|
|
126
|
+
* which is useful for snapshot tests.
|
|
122
127
|
*/
|
|
123
|
-
seed?: number | number
|
|
128
|
+
seed?: number | Array<number>;
|
|
124
129
|
/**
|
|
125
|
-
*
|
|
130
|
+
* Rename properties inside path/query/header mocks. Body mocks are unaffected.
|
|
131
|
+
*
|
|
132
|
+
* @note Must match the value of `paramsCasing` on `@kubb/plugin-ts`.
|
|
126
133
|
*/
|
|
127
134
|
paramsCasing?: 'camelcase';
|
|
128
135
|
/**
|
|
129
|
-
*
|
|
136
|
+
* Custom generators that run alongside the built-in Faker generators.
|
|
130
137
|
*/
|
|
131
138
|
generators?: Array<Generator<PluginFaker>>;
|
|
132
139
|
/**
|
|
133
|
-
* Override naming
|
|
140
|
+
* Override the naming of generated factory helpers. Common use: append `Mock` or
|
|
141
|
+
* `Factory` so helpers do not clash with imported types.
|
|
134
142
|
*/
|
|
135
143
|
resolver?: Partial<ResolverFaker> & ThisType<ResolverFaker>;
|
|
136
144
|
/**
|
|
137
|
-
* AST visitor to
|
|
145
|
+
* AST visitor applied to schema and operation nodes before printing.
|
|
138
146
|
*/
|
|
139
147
|
transformer?: ast.Visitor;
|
|
140
148
|
/**
|
|
141
|
-
*
|
|
149
|
+
* Replace the Faker handler for a specific schema type (`'integer'`, `'date'`, ...).
|
|
150
|
+
* Each handler returns the Faker expression as a string.
|
|
142
151
|
*/
|
|
143
152
|
printer?: {
|
|
144
153
|
nodes?: PrinterFakerNodes;
|
|
@@ -146,7 +155,7 @@ type Options = {
|
|
|
146
155
|
};
|
|
147
156
|
type ResolvedOptions = {
|
|
148
157
|
output: Output;
|
|
149
|
-
group: Group |
|
|
158
|
+
group: Group | null;
|
|
150
159
|
exclude: NonNullable<Options['exclude']>;
|
|
151
160
|
include: Options['include'];
|
|
152
161
|
override: NonNullable<Options['override']>;
|
|
@@ -169,11 +178,29 @@ declare global {
|
|
|
169
178
|
//#endregion
|
|
170
179
|
//#region src/printers/printerFaker.d.ts
|
|
171
180
|
/**
|
|
172
|
-
* Partial
|
|
181
|
+
* Partial map of node-type overrides for the Faker printer. Each key is a
|
|
182
|
+
* `SchemaType` (`'string'`, `'date'`, ...) and each handler returns the
|
|
183
|
+
* Faker expression for that schema as a string. Use `this.transform` to
|
|
184
|
+
* recurse into nested schema nodes and `this.options` to read printer options.
|
|
185
|
+
*
|
|
186
|
+
* @example Override the integer handler
|
|
187
|
+
* ```ts
|
|
188
|
+
* pluginFaker({
|
|
189
|
+
* printer: {
|
|
190
|
+
* nodes: {
|
|
191
|
+
* integer() {
|
|
192
|
+
* return 'faker.number.float()'
|
|
193
|
+
* },
|
|
194
|
+
* },
|
|
195
|
+
* },
|
|
196
|
+
* })
|
|
197
|
+
* ```
|
|
173
198
|
*/
|
|
174
199
|
type PrinterFakerNodes = ast.PrinterPartial<string, PrinterFakerOptions>;
|
|
175
200
|
/**
|
|
176
|
-
*
|
|
201
|
+
* Options passed to the Faker printer at instantiation: the parser library
|
|
202
|
+
* for date strings, the regex generator, the user-supplied schema-name
|
|
203
|
+
* mapper, and the resolver used to compute identifiers.
|
|
177
204
|
*/
|
|
178
205
|
type PrinterFakerOptions = {
|
|
179
206
|
dateParser?: PluginFaker['resolvedOptions']['dateParser'];
|
|
@@ -183,6 +210,12 @@ type PrinterFakerOptions = {
|
|
|
183
210
|
typeName?: string;
|
|
184
211
|
schemaName?: string;
|
|
185
212
|
nestedInObject?: boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Set while printing the members of a union (`oneOf`). Object properties then index their
|
|
215
|
+
* type as `(NonNullable<T> & Record<K, unknown>)[K]` instead of `NonNullable<T>[K]`, so a key
|
|
216
|
+
* carried by only some branches stays valid (a plain index would be a TS2339).
|
|
217
|
+
*/
|
|
218
|
+
nestedInUnion?: boolean;
|
|
186
219
|
nodes?: PrinterFakerNodes;
|
|
187
220
|
/**
|
|
188
221
|
* Names of schemas that participate in a circular dependency chain.
|
|
@@ -203,4 +236,4 @@ type PrinterFakerFactory = ast.PrinterFactoryOptions<'faker', PrinterFakerOption
|
|
|
203
236
|
declare const printerFaker: (options: PrinterFakerOptions) => ast.Printer<PrinterFakerFactory>;
|
|
204
237
|
//#endregion
|
|
205
238
|
export { Options as a, printerFaker as i, PrinterFakerNodes as n, PluginFaker as o, PrinterFakerOptions as r, ResolverFaker as s, PrinterFakerFactory as t };
|
|
206
|
-
//# sourceMappingURL=printerFaker-
|
|
239
|
+
//# sourceMappingURL=printerFaker-CMCJT3FB.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/plugin-faker",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
4
|
-
"description": "Faker.js data
|
|
3
|
+
"version": "5.0.0-beta.56",
|
|
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-
|
|
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,6 @@
|
|
|
31
26
|
"files": [
|
|
32
27
|
"src",
|
|
33
28
|
"dist",
|
|
34
|
-
"extension.yaml",
|
|
35
29
|
"!/**/**.test.**",
|
|
36
30
|
"!/**/__tests__/**",
|
|
37
31
|
"!/**/__snapshots__/**"
|
|
@@ -71,33 +65,29 @@
|
|
|
71
65
|
"registry": "https://registry.npmjs.org/"
|
|
72
66
|
},
|
|
73
67
|
"dependencies": {
|
|
74
|
-
"@kubb/
|
|
75
|
-
"@kubb/
|
|
76
|
-
"@kubb/
|
|
68
|
+
"@kubb/ast": "5.0.0-beta.55",
|
|
69
|
+
"@kubb/core": "5.0.0-beta.55",
|
|
70
|
+
"@kubb/renderer-jsx": "5.0.0-beta.55",
|
|
71
|
+
"@kubb/plugin-ts": "5.0.0-beta.56"
|
|
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.
|
|
78
|
+
"@kubb/renderer-jsx": "5.0.0-beta.55"
|
|
83
79
|
},
|
|
84
|
-
"size-limit": [
|
|
85
|
-
{
|
|
86
|
-
"path": "./dist/*.js",
|
|
87
|
-
"limit": "510 KiB",
|
|
88
|
-
"gzip": true
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
80
|
"engines": {
|
|
92
81
|
"node": ">=22"
|
|
93
82
|
},
|
|
94
83
|
"scripts": {
|
|
95
|
-
"build": "tsdown
|
|
96
|
-
"clean": "
|
|
84
|
+
"build": "tsdown",
|
|
85
|
+
"clean": "node -e \"require('node:fs').rmSync('./dist', {recursive:true,force:true})\"",
|
|
97
86
|
"lint": "oxlint .",
|
|
98
87
|
"lint:fix": "oxlint --fix .",
|
|
99
88
|
"release": "pnpm publish --no-git-check",
|
|
100
89
|
"release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
|
|
90
|
+
"release:stage": "pnpm stage publish --no-git-check",
|
|
101
91
|
"start": "tsdown --watch",
|
|
102
92
|
"test": "vitest --passWithNoTests",
|
|
103
93
|
"typecheck": "tsc -p ./tsconfig.json --noEmit --emitDeclarationOnly false"
|
package/src/components/Faker.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsStringEscape } from '@
|
|
1
|
+
import { jsStringEscape } from '@kubb/ast/utils'
|
|
2
2
|
import { ast } from '@kubb/core'
|
|
3
3
|
import { functionPrinter } from '@kubb/plugin-ts'
|
|
4
4
|
import { File, Function } from '@kubb/renderer-jsx'
|
|
@@ -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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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 ${
|
|
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}
|