@kubb/plugin-faker 5.0.0-beta.84 → 5.0.0-beta.85
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 +493 -368
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +69 -110
- package/dist/index.js +492 -345
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,10 +1,379 @@
|
|
|
1
1
|
import "./rolldown-runtime-C0LytTxp.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { posix } from "node:path";
|
|
3
|
+
import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
|
|
4
|
+
import { buildParams, createFunctionParameter, createFunctionParameters, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
|
|
4
5
|
import { File, Function, jsxRenderer } from "kubb/jsx";
|
|
5
|
-
import path, { posix } from "node:path";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
|
|
7
|
-
|
|
7
|
+
//#region ../../internals/utils/src/casing.ts
|
|
8
|
+
/**
|
|
9
|
+
* Shared implementation for camelCase and PascalCase conversion.
|
|
10
|
+
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
11
|
+
* and capitalizes each word according to `pascal`.
|
|
12
|
+
*
|
|
13
|
+
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
14
|
+
*/
|
|
15
|
+
function toCamelOrPascal(text, pascal) {
|
|
16
|
+
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
17
|
+
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
18
|
+
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
19
|
+
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Converts `text` to camelCase.
|
|
23
|
+
*
|
|
24
|
+
* @example Word boundaries
|
|
25
|
+
* `camelCase('hello-world') // 'helloWorld'`
|
|
26
|
+
*
|
|
27
|
+
* @example With a prefix
|
|
28
|
+
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
29
|
+
*/
|
|
30
|
+
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
31
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
35
|
+
/**
|
|
36
|
+
* JavaScript and Java reserved words.
|
|
37
|
+
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
38
|
+
*/
|
|
39
|
+
const reservedWords = /* @__PURE__ */ new Set([
|
|
40
|
+
"abstract",
|
|
41
|
+
"arguments",
|
|
42
|
+
"boolean",
|
|
43
|
+
"break",
|
|
44
|
+
"byte",
|
|
45
|
+
"case",
|
|
46
|
+
"catch",
|
|
47
|
+
"char",
|
|
48
|
+
"class",
|
|
49
|
+
"const",
|
|
50
|
+
"continue",
|
|
51
|
+
"debugger",
|
|
52
|
+
"default",
|
|
53
|
+
"delete",
|
|
54
|
+
"do",
|
|
55
|
+
"double",
|
|
56
|
+
"else",
|
|
57
|
+
"enum",
|
|
58
|
+
"eval",
|
|
59
|
+
"export",
|
|
60
|
+
"extends",
|
|
61
|
+
"false",
|
|
62
|
+
"final",
|
|
63
|
+
"finally",
|
|
64
|
+
"float",
|
|
65
|
+
"for",
|
|
66
|
+
"function",
|
|
67
|
+
"goto",
|
|
68
|
+
"if",
|
|
69
|
+
"implements",
|
|
70
|
+
"import",
|
|
71
|
+
"in",
|
|
72
|
+
"instanceof",
|
|
73
|
+
"int",
|
|
74
|
+
"interface",
|
|
75
|
+
"let",
|
|
76
|
+
"long",
|
|
77
|
+
"native",
|
|
78
|
+
"new",
|
|
79
|
+
"null",
|
|
80
|
+
"package",
|
|
81
|
+
"private",
|
|
82
|
+
"protected",
|
|
83
|
+
"public",
|
|
84
|
+
"return",
|
|
85
|
+
"short",
|
|
86
|
+
"static",
|
|
87
|
+
"super",
|
|
88
|
+
"switch",
|
|
89
|
+
"synchronized",
|
|
90
|
+
"this",
|
|
91
|
+
"throw",
|
|
92
|
+
"throws",
|
|
93
|
+
"transient",
|
|
94
|
+
"true",
|
|
95
|
+
"try",
|
|
96
|
+
"typeof",
|
|
97
|
+
"var",
|
|
98
|
+
"void",
|
|
99
|
+
"volatile",
|
|
100
|
+
"while",
|
|
101
|
+
"with",
|
|
102
|
+
"yield",
|
|
103
|
+
"Array",
|
|
104
|
+
"Date",
|
|
105
|
+
"hasOwnProperty",
|
|
106
|
+
"Infinity",
|
|
107
|
+
"isFinite",
|
|
108
|
+
"isNaN",
|
|
109
|
+
"isPrototypeOf",
|
|
110
|
+
"length",
|
|
111
|
+
"Math",
|
|
112
|
+
"name",
|
|
113
|
+
"NaN",
|
|
114
|
+
"Number",
|
|
115
|
+
"Object",
|
|
116
|
+
"prototype",
|
|
117
|
+
"String",
|
|
118
|
+
"toString",
|
|
119
|
+
"undefined",
|
|
120
|
+
"valueOf"
|
|
121
|
+
]);
|
|
122
|
+
/**
|
|
123
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* isValidVarName('status') // true
|
|
128
|
+
* isValidVarName('class') // false (reserved word)
|
|
129
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
function isValidVarName(name) {
|
|
133
|
+
if (!name || reservedWords.has(name)) return false;
|
|
134
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
138
|
+
* otherwise prefixes it with `_` so the result is a valid identifier.
|
|
139
|
+
*
|
|
140
|
+
* Useful for sanitizing OpenAPI schema names or operation IDs that start with
|
|
141
|
+
* a digit (e.g. `409`, `504AccountCancel`) before using them as exported
|
|
142
|
+
* variable, type, or function names.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* ensureValidVarName('409') // '_409'
|
|
147
|
+
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
148
|
+
* ensureValidVarName('Pet') // 'Pet'
|
|
149
|
+
* ensureValidVarName('class') // '_class'
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
function ensureValidVarName(name) {
|
|
153
|
+
if (!name || isValidVarName(name)) return name;
|
|
154
|
+
return `_${name}`;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Returns `true` when `name` is syntactically a valid identifier, ignoring reserved words.
|
|
158
|
+
*
|
|
159
|
+
* Reserved words and globals (`class`, `name`, `Date`, …) are valid as bare object-literal keys
|
|
160
|
+
* even though they are not valid variable names, so use this (not {@link isValidVarName}) when
|
|
161
|
+
* deciding whether an object key needs quoting.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```ts
|
|
165
|
+
* isIdentifier('name') // true
|
|
166
|
+
* isIdentifier('x-total')// false
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
function isIdentifier(name) {
|
|
170
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region ../../internals/utils/src/strings.ts
|
|
174
|
+
/**
|
|
175
|
+
* Wraps a value in single quotes for emitting a single-quoted JavaScript string literal, escaping
|
|
176
|
+
* any backslash or single quote in the content.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* singleQuote('foo') // "'foo'"
|
|
181
|
+
* singleQuote("o'clock") // "'o\\'clock'"
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
function singleQuote(value) {
|
|
185
|
+
if (value === void 0 || value === null) return "''";
|
|
186
|
+
return `'${String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Strips a single matching pair of `"..."`, `'...'`, or `` `...` `` from both ends of `text`.
|
|
190
|
+
* Returns the string unchanged when no balanced quote pair is found.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```ts
|
|
194
|
+
* trimQuotes('"hello"') // 'hello'
|
|
195
|
+
* trimQuotes('hello') // 'hello'
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
function trimQuotes(text) {
|
|
199
|
+
if (text.length >= 2) {
|
|
200
|
+
const first = text[0];
|
|
201
|
+
const last = text[text.length - 1];
|
|
202
|
+
if (first === "\"" && last === "\"" || first === "'" && last === "'" || first === "`" && last === "`") return text.slice(1, -1);
|
|
203
|
+
}
|
|
204
|
+
return text;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Serializes a primitive to a single-quoted string literal, stripping any surrounding quotes first.
|
|
208
|
+
*
|
|
209
|
+
* Escaping runs through `JSON.stringify`, then the result switches to single quotes so the generated
|
|
210
|
+
* code matches the repo style without a formatter.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```ts
|
|
214
|
+
* stringify('hello') // "'hello'"
|
|
215
|
+
* stringify('"hello"') // "'hello'"
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
function stringify(value) {
|
|
219
|
+
if (value === void 0 || value === null) return "''";
|
|
220
|
+
return `'${JSON.stringify(trimQuotes(value.toString())).slice(1, -1).replace(/\\"/g, "\"").replace(/'/g, "\\'")}'`;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Escapes characters that are not allowed inside JS string literals, covering quotes, backslashes,
|
|
224
|
+
* and the Unicode line terminators U+2028 and U+2029.
|
|
225
|
+
*
|
|
226
|
+
* @see http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* jsStringEscape('say "hi"\nbye') // 'say \\"hi\\"\\nbye'
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
function jsStringEscape(input) {
|
|
234
|
+
return `${input}`.replace(/["'\\\n\r\u2028\u2029]/g, (character) => {
|
|
235
|
+
switch (character) {
|
|
236
|
+
case "\"":
|
|
237
|
+
case "'":
|
|
238
|
+
case "\\": return `\\${character}`;
|
|
239
|
+
case "\n": return "\\n";
|
|
240
|
+
case "\r": return "\\r";
|
|
241
|
+
case "\u2028": return "\\u2028";
|
|
242
|
+
case "\u2029": return "\\u2029";
|
|
243
|
+
default: return "";
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Converts a pattern string into a `new RegExp(...)` constructor call or a regex literal string.
|
|
249
|
+
* Inline flags expressed as a `^(?im)` prefix are extracted and applied to the resulting expression.
|
|
250
|
+
* Pass `null` as the second argument to emit a `/pattern/flags` literal instead.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```ts
|
|
254
|
+
* toRegExpString('^(?im)foo') // 'new RegExp("^foo", "im")'
|
|
255
|
+
* toRegExpString('^(?im)foo', null) // '/^foo/im'
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
function toRegExpString(text, func = "RegExp") {
|
|
259
|
+
const raw = trimQuotes(text);
|
|
260
|
+
const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i);
|
|
261
|
+
const replacementTarget = match?.[1] ?? "";
|
|
262
|
+
const matchedFlags = match?.[2];
|
|
263
|
+
const cleaned = raw.replace(/^\\?\//, "").replace(/\\?\/$/, "").replace(replacementTarget, "");
|
|
264
|
+
const { source, flags } = new RegExp(cleaned, matchedFlags);
|
|
265
|
+
if (func === null) return `/${source}/${flags}`;
|
|
266
|
+
return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
|
|
267
|
+
}
|
|
268
|
+
//#endregion
|
|
269
|
+
//#region ../../internals/utils/src/codegen.ts
|
|
270
|
+
const INDENT = " ";
|
|
271
|
+
/**
|
|
272
|
+
* Indents every non-empty line of `text` by one indent level, leaving blank lines empty.
|
|
273
|
+
*/
|
|
274
|
+
function indentLines(text) {
|
|
275
|
+
if (!text) return "";
|
|
276
|
+
return text.split("\n").map((line) => line.trim() ? `${INDENT}${line}` : "").join("\n");
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Renders an object key, quoting it with single quotes only when it is not a valid identifier.
|
|
280
|
+
* Reserved words and globals (`name`, `class`, …) are valid bare keys and stay unquoted.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```ts
|
|
284
|
+
* objectKey('name') // 'name'
|
|
285
|
+
* objectKey('x-total') // "'x-total'"
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
function objectKey(name) {
|
|
289
|
+
return isIdentifier(name) ? name : singleQuote(name);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Assembles a multi-line object literal from already-rendered `entries`, indenting each entry one
|
|
293
|
+
* level and closing the brace at column zero. Entries that are themselves multi-line objects indent
|
|
294
|
+
* cumulatively. Each entry ends with a trailing comma to match the formatter's multi-line style.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* ```ts
|
|
298
|
+
* buildObject(['id: z.number()', 'name: z.string()'])
|
|
299
|
+
* // '{\n id: z.number(),\n name: z.string(),\n}'
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
function buildObject(entries) {
|
|
303
|
+
if (entries.length === 0) return "{}";
|
|
304
|
+
return `{\n${entries.map((entry) => `${indentLines(entry)},`).join("\n")}\n}`;
|
|
305
|
+
}
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region ../../internals/utils/src/fs.ts
|
|
308
|
+
/**
|
|
309
|
+
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
310
|
+
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
311
|
+
* every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
|
|
312
|
+
*
|
|
313
|
+
* Empty segments are dropped before joining. They arise when the name starts with a dot
|
|
314
|
+
* followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
|
|
315
|
+
* an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
|
|
316
|
+
* absolute path, letting generated files escape the configured output directory.
|
|
317
|
+
*
|
|
318
|
+
* @example Nested path from a dotted name
|
|
319
|
+
* `toFilePath('pet.petId') // 'pet/petId'`
|
|
320
|
+
*
|
|
321
|
+
* @example PascalCase the final segment
|
|
322
|
+
* `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
|
|
323
|
+
*
|
|
324
|
+
* @example Suffix applied to the final segment only
|
|
325
|
+
* `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
|
|
326
|
+
*/
|
|
327
|
+
function toFilePath(name, caseLast = camelCase) {
|
|
328
|
+
const parts = name.split(/\.(?=[a-zA-Z])/);
|
|
329
|
+
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
330
|
+
}
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region ../../internals/utils/src/imports.ts
|
|
333
|
+
function escapeRegExp(value) {
|
|
334
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
335
|
+
}
|
|
336
|
+
function getImportNames(entry) {
|
|
337
|
+
return (Array.isArray(entry.name) ? entry.name : [entry.name]).map((name) => {
|
|
338
|
+
if (typeof name === "string") return name;
|
|
339
|
+
return name.name ?? name.propertyName;
|
|
340
|
+
}).filter((name) => Boolean(name));
|
|
341
|
+
}
|
|
342
|
+
function filterUsedImports(imports, text, skipImportNames = []) {
|
|
343
|
+
const skip = new Set(skipImportNames);
|
|
344
|
+
return imports.filter((entry) => {
|
|
345
|
+
return getImportNames(entry).some((name) => {
|
|
346
|
+
if (skip.has(name)) return false;
|
|
347
|
+
return new RegExp(`\\b${escapeRegExp(name)}\\b(?=\\s*\\()`).test(text);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
function aliasConflictingImports(imports, reservedNames) {
|
|
352
|
+
const reservedNameSet = new Set(reservedNames);
|
|
353
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
354
|
+
return {
|
|
355
|
+
imports: imports.map((entry) => {
|
|
356
|
+
const aliasedNames = (Array.isArray(entry.name) ? entry.name : [entry.name]).map((item) => {
|
|
357
|
+
if (typeof item !== "string" || !reservedNameSet.has(item)) return item;
|
|
358
|
+
const alias = `${item}Schema`;
|
|
359
|
+
aliases.set(item, alias);
|
|
360
|
+
return {
|
|
361
|
+
propertyName: item,
|
|
362
|
+
name: alias
|
|
363
|
+
};
|
|
364
|
+
});
|
|
365
|
+
return aliasedNames.some((item) => typeof item === "object" && item.name) ? {
|
|
366
|
+
...entry,
|
|
367
|
+
name: aliasedNames
|
|
368
|
+
} : entry;
|
|
369
|
+
}),
|
|
370
|
+
aliases
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
function rewriteAliasedImports(text, aliases) {
|
|
374
|
+
return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
|
|
375
|
+
}
|
|
376
|
+
//#endregion
|
|
8
377
|
//#region src/utils.ts
|
|
9
378
|
/**
|
|
10
379
|
* Returns the `@faker-js/faker` named export for a locale code.
|
|
@@ -53,17 +422,6 @@ function canOverrideSchema(node) {
|
|
|
53
422
|
"blob"
|
|
54
423
|
])).has(node.type);
|
|
55
424
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Resolves a parameter name based on its location (path, query, header, etc.) using the provided resolver.
|
|
58
|
-
*/
|
|
59
|
-
function resolveParamNameByLocation(resolver, node, param) {
|
|
60
|
-
switch (param.in) {
|
|
61
|
-
case "path": return resolver.resolvePathParamsName(node, param);
|
|
62
|
-
case "query": return resolver.resolveQueryParamsName(node, param);
|
|
63
|
-
case "header": return resolver.resolveHeaderParamsName(node, param);
|
|
64
|
-
default: return resolver.resolveParamName(node, param);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
425
|
function shouldInlineSingleResponseSchema(schema) {
|
|
68
426
|
return (/* @__PURE__ */ new Set([
|
|
69
427
|
"any",
|
|
@@ -100,14 +458,14 @@ function buildResponseUnionSchema(node, resolver) {
|
|
|
100
458
|
if (schema && shouldInlineSingleResponseSchema(schema)) return schema;
|
|
101
459
|
return ast.factory.createSchema({
|
|
102
460
|
type: "ref",
|
|
103
|
-
name: resolver.
|
|
461
|
+
name: resolver.response.status(node, responses[0].statusCode)
|
|
104
462
|
});
|
|
105
463
|
}
|
|
106
464
|
return ast.factory.createSchema({
|
|
107
465
|
type: "union",
|
|
108
466
|
members: responses.map((response) => ast.factory.createSchema({
|
|
109
467
|
type: "ref",
|
|
110
|
-
name: resolver.
|
|
468
|
+
name: resolver.response.status(node, response.statusCode)
|
|
111
469
|
}))
|
|
112
470
|
});
|
|
113
471
|
}
|
|
@@ -235,14 +593,14 @@ function Faker({ node, description, name, typeName, printer, seed, canOverride }
|
|
|
235
593
|
children: /* @__PURE__ */ jsxs(Function, {
|
|
236
594
|
export: true,
|
|
237
595
|
name,
|
|
238
|
-
JSDoc: { comments: description ? [`@description ${
|
|
596
|
+
JSDoc: { comments: description ? [`@description ${jsStringEscape(description)}`] : [] },
|
|
239
597
|
params: canOverride ? paramsSignature : void 0,
|
|
240
598
|
returnType: returnType ?? void 0,
|
|
241
599
|
children: [seed ? /* @__PURE__ */ jsxs(Fragment, { children: [`faker.seed(${JSON.stringify(seed)})`, /* @__PURE__ */ jsx("br", {})] }) : void 0, `return ${returnExpression}`]
|
|
242
600
|
})
|
|
243
601
|
});
|
|
244
602
|
}
|
|
245
|
-
const functionSignature = `${description ? `/**\n * @description ${
|
|
603
|
+
const functionSignature = `${description ? `/**\n * @description ${jsStringEscape(description)}\n */\n ` : ""}export function ${name}<TData extends Partial<${typeName}> = object>(data?: TData)`;
|
|
246
604
|
const seedCode = seed ? `faker.seed(${JSON.stringify(seed)})\n ` : "";
|
|
247
605
|
const { cyclicSchemas, schemaName } = printer.options;
|
|
248
606
|
const functionBody = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) => ast.containsCircularRef(p.schema, {
|
|
@@ -271,226 +629,6 @@ function Faker({ node, description, name, typeName, printer, seed, canOverride }
|
|
|
271
629
|
});
|
|
272
630
|
}
|
|
273
631
|
//#endregion
|
|
274
|
-
//#region ../../internals/utils/src/casing.ts
|
|
275
|
-
/**
|
|
276
|
-
* Shared implementation for camelCase and PascalCase conversion.
|
|
277
|
-
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
278
|
-
* and capitalizes each word according to `pascal`.
|
|
279
|
-
*
|
|
280
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
281
|
-
*/
|
|
282
|
-
function toCamelOrPascal(text, pascal) {
|
|
283
|
-
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
284
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
285
|
-
return (i === 0 && !pascal ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1);
|
|
286
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Converts `text` to camelCase.
|
|
290
|
-
*
|
|
291
|
-
* @example Word boundaries
|
|
292
|
-
* `camelCase('hello-world') // 'helloWorld'`
|
|
293
|
-
*
|
|
294
|
-
* @example With a prefix
|
|
295
|
-
* `camelCase('tag', { prefix: 'create' }) // 'createTag'`
|
|
296
|
-
*/
|
|
297
|
-
function camelCase(text, { prefix = "", suffix = "" } = {}) {
|
|
298
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
299
|
-
}
|
|
300
|
-
//#endregion
|
|
301
|
-
//#region ../../internals/utils/src/fs.ts
|
|
302
|
-
/**
|
|
303
|
-
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
304
|
-
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
305
|
-
* every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
|
|
306
|
-
*
|
|
307
|
-
* Empty segments are dropped before joining. They arise when the name starts with a dot
|
|
308
|
-
* followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
|
|
309
|
-
* an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
|
|
310
|
-
* absolute path, letting generated files escape the configured output directory.
|
|
311
|
-
*
|
|
312
|
-
* @example Nested path from a dotted name
|
|
313
|
-
* `toFilePath('pet.petId') // 'pet/petId'`
|
|
314
|
-
*
|
|
315
|
-
* @example PascalCase the final segment
|
|
316
|
-
* `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
|
|
317
|
-
*
|
|
318
|
-
* @example Suffix applied to the final segment only
|
|
319
|
-
* `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
|
|
320
|
-
*/
|
|
321
|
-
function toFilePath(name, caseLast = camelCase) {
|
|
322
|
-
const parts = name.split(/\.(?=[a-zA-Z])/);
|
|
323
|
-
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
324
|
-
}
|
|
325
|
-
//#endregion
|
|
326
|
-
//#region ../../internals/utils/src/imports.ts
|
|
327
|
-
function escapeRegExp(value) {
|
|
328
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
329
|
-
}
|
|
330
|
-
function getImportNames(entry) {
|
|
331
|
-
return (Array.isArray(entry.name) ? entry.name : [entry.name]).map((name) => {
|
|
332
|
-
if (typeof name === "string") return name;
|
|
333
|
-
return name.name ?? name.propertyName;
|
|
334
|
-
}).filter((name) => Boolean(name));
|
|
335
|
-
}
|
|
336
|
-
function filterUsedImports(imports, text, skipImportNames = []) {
|
|
337
|
-
const skip = new Set(skipImportNames);
|
|
338
|
-
return imports.filter((entry) => {
|
|
339
|
-
return getImportNames(entry).some((name) => {
|
|
340
|
-
if (skip.has(name)) return false;
|
|
341
|
-
return new RegExp(`\\b${escapeRegExp(name)}\\b(?=\\s*\\()`).test(text);
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
function aliasConflictingImports(imports, reservedNames) {
|
|
346
|
-
const reservedNameSet = new Set(reservedNames);
|
|
347
|
-
const aliases = /* @__PURE__ */ new Map();
|
|
348
|
-
return {
|
|
349
|
-
imports: imports.map((entry) => {
|
|
350
|
-
const aliasedNames = (Array.isArray(entry.name) ? entry.name : [entry.name]).map((item) => {
|
|
351
|
-
if (typeof item !== "string" || !reservedNameSet.has(item)) return item;
|
|
352
|
-
const alias = `${item}Schema`;
|
|
353
|
-
aliases.set(item, alias);
|
|
354
|
-
return {
|
|
355
|
-
propertyName: item,
|
|
356
|
-
name: alias
|
|
357
|
-
};
|
|
358
|
-
});
|
|
359
|
-
return aliasedNames.some((item) => typeof item === "object" && item.name) ? {
|
|
360
|
-
...entry,
|
|
361
|
-
name: aliasedNames
|
|
362
|
-
} : entry;
|
|
363
|
-
}),
|
|
364
|
-
aliases
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
function rewriteAliasedImports(text, aliases) {
|
|
368
|
-
return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
|
|
369
|
-
}
|
|
370
|
-
//#endregion
|
|
371
|
-
//#region ../../internals/utils/src/reserved.ts
|
|
372
|
-
/**
|
|
373
|
-
* JavaScript and Java reserved words.
|
|
374
|
-
* @link https://github.com/jonschlinkert/reserved/blob/master/index.js
|
|
375
|
-
*/
|
|
376
|
-
const reservedWords = /* @__PURE__ */ new Set([
|
|
377
|
-
"abstract",
|
|
378
|
-
"arguments",
|
|
379
|
-
"boolean",
|
|
380
|
-
"break",
|
|
381
|
-
"byte",
|
|
382
|
-
"case",
|
|
383
|
-
"catch",
|
|
384
|
-
"char",
|
|
385
|
-
"class",
|
|
386
|
-
"const",
|
|
387
|
-
"continue",
|
|
388
|
-
"debugger",
|
|
389
|
-
"default",
|
|
390
|
-
"delete",
|
|
391
|
-
"do",
|
|
392
|
-
"double",
|
|
393
|
-
"else",
|
|
394
|
-
"enum",
|
|
395
|
-
"eval",
|
|
396
|
-
"export",
|
|
397
|
-
"extends",
|
|
398
|
-
"false",
|
|
399
|
-
"final",
|
|
400
|
-
"finally",
|
|
401
|
-
"float",
|
|
402
|
-
"for",
|
|
403
|
-
"function",
|
|
404
|
-
"goto",
|
|
405
|
-
"if",
|
|
406
|
-
"implements",
|
|
407
|
-
"import",
|
|
408
|
-
"in",
|
|
409
|
-
"instanceof",
|
|
410
|
-
"int",
|
|
411
|
-
"interface",
|
|
412
|
-
"let",
|
|
413
|
-
"long",
|
|
414
|
-
"native",
|
|
415
|
-
"new",
|
|
416
|
-
"null",
|
|
417
|
-
"package",
|
|
418
|
-
"private",
|
|
419
|
-
"protected",
|
|
420
|
-
"public",
|
|
421
|
-
"return",
|
|
422
|
-
"short",
|
|
423
|
-
"static",
|
|
424
|
-
"super",
|
|
425
|
-
"switch",
|
|
426
|
-
"synchronized",
|
|
427
|
-
"this",
|
|
428
|
-
"throw",
|
|
429
|
-
"throws",
|
|
430
|
-
"transient",
|
|
431
|
-
"true",
|
|
432
|
-
"try",
|
|
433
|
-
"typeof",
|
|
434
|
-
"var",
|
|
435
|
-
"void",
|
|
436
|
-
"volatile",
|
|
437
|
-
"while",
|
|
438
|
-
"with",
|
|
439
|
-
"yield",
|
|
440
|
-
"Array",
|
|
441
|
-
"Date",
|
|
442
|
-
"hasOwnProperty",
|
|
443
|
-
"Infinity",
|
|
444
|
-
"isFinite",
|
|
445
|
-
"isNaN",
|
|
446
|
-
"isPrototypeOf",
|
|
447
|
-
"length",
|
|
448
|
-
"Math",
|
|
449
|
-
"name",
|
|
450
|
-
"NaN",
|
|
451
|
-
"Number",
|
|
452
|
-
"Object",
|
|
453
|
-
"prototype",
|
|
454
|
-
"String",
|
|
455
|
-
"toString",
|
|
456
|
-
"undefined",
|
|
457
|
-
"valueOf"
|
|
458
|
-
]);
|
|
459
|
-
/**
|
|
460
|
-
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
461
|
-
*
|
|
462
|
-
* @example
|
|
463
|
-
* ```ts
|
|
464
|
-
* isValidVarName('status') // true
|
|
465
|
-
* isValidVarName('class') // false (reserved word)
|
|
466
|
-
* isValidVarName('42foo') // false (starts with digit)
|
|
467
|
-
* ```
|
|
468
|
-
*/
|
|
469
|
-
function isValidVarName(name) {
|
|
470
|
-
if (!name || reservedWords.has(name)) return false;
|
|
471
|
-
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* Returns `name` when it's a syntactically valid JavaScript variable name,
|
|
475
|
-
* otherwise prefixes it with `_` so the result is a valid identifier.
|
|
476
|
-
*
|
|
477
|
-
* Useful for sanitizing OpenAPI schema names or operation IDs that start with
|
|
478
|
-
* a digit (e.g. `409`, `504AccountCancel`) before using them as exported
|
|
479
|
-
* variable, type, or function names.
|
|
480
|
-
*
|
|
481
|
-
* @example
|
|
482
|
-
* ```ts
|
|
483
|
-
* ensureValidVarName('409') // '_409'
|
|
484
|
-
* ensureValidVarName('504AccountCancel') // '_504AccountCancel'
|
|
485
|
-
* ensureValidVarName('Pet') // 'Pet'
|
|
486
|
-
* ensureValidVarName('class') // '_class'
|
|
487
|
-
* ```
|
|
488
|
-
*/
|
|
489
|
-
function ensureValidVarName(name) {
|
|
490
|
-
if (!name || isValidVarName(name)) return name;
|
|
491
|
-
return `_${name}`;
|
|
492
|
-
}
|
|
493
|
-
//#endregion
|
|
494
632
|
//#region ../../internals/shared/src/params.ts
|
|
495
633
|
const caseParamsCache = /* @__PURE__ */ new WeakMap();
|
|
496
634
|
/**
|
|
@@ -511,6 +649,23 @@ function caseParams(params, casing) {
|
|
|
511
649
|
caseParamsCache.set(params, result);
|
|
512
650
|
return result;
|
|
513
651
|
}
|
|
652
|
+
/**
|
|
653
|
+
* Drops parameters that collapse to the same property identity once camelCased, keeping the first.
|
|
654
|
+
*
|
|
655
|
+
* Some specs declare the same parameter twice under different casings (for example AWS S3 lists both
|
|
656
|
+
* `max-uploads` and `MaxUploads`). Both resolve to one output property, so emitting both would yield
|
|
657
|
+
* an object type with a duplicate member, which TypeScript rejects. De-duplicate by the camelCased
|
|
658
|
+
* identity so the resulting group is collision-free regardless of the names each caller carries.
|
|
659
|
+
*/
|
|
660
|
+
function dedupeByCasedName(params) {
|
|
661
|
+
const seen = /* @__PURE__ */ new Set();
|
|
662
|
+
return params.filter((param) => {
|
|
663
|
+
const key = camelCase(param.name);
|
|
664
|
+
if (seen.has(key)) return false;
|
|
665
|
+
seen.add(key);
|
|
666
|
+
return true;
|
|
667
|
+
});
|
|
668
|
+
}
|
|
514
669
|
//#endregion
|
|
515
670
|
//#region ../../internals/shared/src/operation.ts
|
|
516
671
|
/**
|
|
@@ -561,6 +716,15 @@ function resolveContentTypeVariants(entries, baseName) {
|
|
|
561
716
|
};
|
|
562
717
|
});
|
|
563
718
|
}
|
|
719
|
+
function getOperationParameters(node, options = {}) {
|
|
720
|
+
const params = caseParams(node.parameters, options.paramsCasing === "original" ? void 0 : "camelcase");
|
|
721
|
+
return {
|
|
722
|
+
path: dedupeByCasedName(params.filter((param) => param.in === "path")),
|
|
723
|
+
query: dedupeByCasedName(params.filter((param) => param.in === "query")),
|
|
724
|
+
header: dedupeByCasedName(params.filter((param) => param.in === "header")),
|
|
725
|
+
cookie: dedupeByCasedName(params.filter((param) => param.in === "cookie"))
|
|
726
|
+
};
|
|
727
|
+
}
|
|
564
728
|
//#endregion
|
|
565
729
|
//#region ../../internals/shared/src/group.ts
|
|
566
730
|
/**
|
|
@@ -655,7 +819,7 @@ const fakerKeywordMapper = {
|
|
|
655
819
|
return `{...${items.join(", ...")}}`;
|
|
656
820
|
},
|
|
657
821
|
matches: (value = "", regexGenerator = "faker") => {
|
|
658
|
-
if (regexGenerator === "randexp") return `${
|
|
822
|
+
if (regexGenerator === "randexp") return `${toRegExpString(value, "RandExp")}.gen()`;
|
|
659
823
|
return `faker.helpers.fromRegExp("${value}")`;
|
|
660
824
|
},
|
|
661
825
|
email: () => "faker.internet.email()",
|
|
@@ -666,7 +830,7 @@ function getEnumValues(node) {
|
|
|
666
830
|
return node.enumValues ?? [];
|
|
667
831
|
}
|
|
668
832
|
function parseEnumValue(value) {
|
|
669
|
-
if (typeof value === "string") return
|
|
833
|
+
if (typeof value === "string") return stringify(value);
|
|
670
834
|
return value;
|
|
671
835
|
}
|
|
672
836
|
/**
|
|
@@ -734,7 +898,7 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
734
898
|
const refName = node.ref ? this.options.nameMapping?.get(node.ref) ?? ast.extractRefName(node.ref) ?? node.name ?? node.schema?.name : node.name ?? node.schema?.name;
|
|
735
899
|
if (!refName) throw new Error("Name not defined for ref node");
|
|
736
900
|
if (this.options.schemaName && refName === this.options.schemaName) return this.options.typeName ? `undefined as unknown as ${this.options.typeName}` : "undefined as unknown";
|
|
737
|
-
const resolvedName = node.ref ? this.options.resolver.
|
|
901
|
+
const resolvedName = node.ref ? this.options.resolver.name(refName) : refName;
|
|
738
902
|
if (!this.options.nestedInObject) return `${resolvedName}(data)`;
|
|
739
903
|
return `${resolvedName}()`;
|
|
740
904
|
},
|
|
@@ -778,7 +942,7 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
778
942
|
},
|
|
779
943
|
object(node) {
|
|
780
944
|
const cyclicSchemas = this.options.cyclicSchemas;
|
|
781
|
-
|
|
945
|
+
return buildObject((node.properties ?? []).map((property) => {
|
|
782
946
|
const value = printNested(property.schema, {
|
|
783
947
|
typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : void 0,
|
|
784
948
|
nestedInObject: true
|
|
@@ -786,10 +950,9 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
786
950
|
if (cyclicSchemas && ast.containsCircularRef(property.schema, {
|
|
787
951
|
circularSchemas: cyclicSchemas,
|
|
788
952
|
excludeName: this.options.schemaName
|
|
789
|
-
})) return `get ${
|
|
790
|
-
return `${
|
|
791
|
-
});
|
|
792
|
-
return ast.buildObject(entries);
|
|
953
|
+
})) return `get ${objectKey(property.name)}() { const _value = ${value}; Object.defineProperty(this, ${JSON.stringify(property.name)}, { value: _value, configurable: true, writable: true, enumerable: true }); return _value }`;
|
|
954
|
+
return `${objectKey(property.name)}: ${value}`;
|
|
955
|
+
}));
|
|
793
956
|
},
|
|
794
957
|
...options.nodes
|
|
795
958
|
},
|
|
@@ -819,22 +982,20 @@ const fakerGenerator = defineGenerator({
|
|
|
819
982
|
const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum);
|
|
820
983
|
const tsEnumType = pluginTs.options?.enum?.type;
|
|
821
984
|
const tsEnumTypeSuffix = pluginTs.options?.enum?.typeSuffix ?? "Key";
|
|
822
|
-
const schemaTypeName = isEnumSchema && tsEnumType === "asConst" ? tsResolver.
|
|
985
|
+
const schemaTypeName = isEnumSchema && tsEnumType === "asConst" ? tsResolver.enum.keyName({ name: schemaName }, tsEnumTypeSuffix) : tsResolver.name(schemaName);
|
|
823
986
|
const meta = {
|
|
824
|
-
name: resolver.
|
|
825
|
-
file: resolver.
|
|
987
|
+
name: resolver.name(schemaName),
|
|
988
|
+
file: resolver.file({
|
|
826
989
|
name: schemaName,
|
|
827
|
-
extname: ".ts"
|
|
828
|
-
}, {
|
|
990
|
+
extname: ".ts",
|
|
829
991
|
root,
|
|
830
992
|
output,
|
|
831
993
|
group: group ?? void 0
|
|
832
994
|
}),
|
|
833
995
|
typeName: schemaTypeName,
|
|
834
|
-
typeFile: tsResolver.
|
|
996
|
+
typeFile: tsResolver.file({
|
|
835
997
|
name: schemaName,
|
|
836
|
-
extname: ".ts"
|
|
837
|
-
}, {
|
|
998
|
+
extname: ".ts",
|
|
838
999
|
root,
|
|
839
1000
|
output: pluginTs.options?.output ?? output,
|
|
840
1001
|
group: pluginTs.options?.group ?? void 0
|
|
@@ -862,11 +1023,10 @@ const fakerGenerator = defineGenerator({
|
|
|
862
1023
|
typeFilePath: meta.typeFile.path
|
|
863
1024
|
});
|
|
864
1025
|
const usedImports = filterUsedImports(adapter.getImports(node, (schemaName) => ({
|
|
865
|
-
name: resolver.
|
|
866
|
-
path: resolver.
|
|
1026
|
+
name: resolver.name(schemaName),
|
|
1027
|
+
path: resolver.file({
|
|
867
1028
|
name: schemaName,
|
|
868
|
-
extname: ".ts"
|
|
869
|
-
}, {
|
|
1029
|
+
extname: ".ts",
|
|
870
1030
|
root,
|
|
871
1031
|
output,
|
|
872
1032
|
group: group ?? void 0
|
|
@@ -876,7 +1036,7 @@ const fakerGenerator = defineGenerator({
|
|
|
876
1036
|
baseName: meta.file.baseName,
|
|
877
1037
|
path: meta.file.path,
|
|
878
1038
|
meta: meta.file.meta,
|
|
879
|
-
banner: resolver.
|
|
1039
|
+
banner: resolver.default.banner(ctx.meta, {
|
|
880
1040
|
output,
|
|
881
1041
|
config,
|
|
882
1042
|
file: {
|
|
@@ -884,7 +1044,7 @@ const fakerGenerator = defineGenerator({
|
|
|
884
1044
|
baseName: meta.file.baseName
|
|
885
1045
|
}
|
|
886
1046
|
}),
|
|
887
|
-
footer: resolver.
|
|
1047
|
+
footer: resolver.default.footer(ctx.meta, {
|
|
888
1048
|
output,
|
|
889
1049
|
config,
|
|
890
1050
|
file: {
|
|
@@ -941,10 +1101,31 @@ const fakerGenerator = defineGenerator({
|
|
|
941
1101
|
const pluginTs = ctx.driver.getPlugin(pluginTsName);
|
|
942
1102
|
if (!pluginTs) return;
|
|
943
1103
|
const tsResolver = ctx.driver.getResolver(pluginTsName);
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1104
|
+
const params = caseParams(node.parameters, "camelcase");
|
|
1105
|
+
const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters({
|
|
1106
|
+
...node,
|
|
1107
|
+
parameters: params
|
|
1108
|
+
}, { paramsCasing: "original" });
|
|
1109
|
+
const paramGroups = [
|
|
1110
|
+
{
|
|
1111
|
+
params: pathParams,
|
|
1112
|
+
name: resolver.param.path,
|
|
1113
|
+
typeName: tsResolver.param.path
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
params: queryParams,
|
|
1117
|
+
name: resolver.param.query,
|
|
1118
|
+
typeName: tsResolver.param.query
|
|
1119
|
+
},
|
|
1120
|
+
{
|
|
1121
|
+
params: headerParams,
|
|
1122
|
+
name: resolver.param.headers,
|
|
1123
|
+
typeName: tsResolver.param.headers
|
|
1124
|
+
}
|
|
1125
|
+
].filter((group) => group.params.length > 0).map((group) => ({
|
|
1126
|
+
schema: buildParams({ params: group.params }),
|
|
1127
|
+
name: group.name(node, group.params[0]),
|
|
1128
|
+
typeName: group.typeName(node, group.params[0])
|
|
948
1129
|
}));
|
|
949
1130
|
function expandContentUnits(entries, baseName, tsBaseName, description, decorate) {
|
|
950
1131
|
const withSchema = entries.filter((entry) => entry.schema);
|
|
@@ -981,36 +1162,34 @@ const fakerGenerator = defineGenerator({
|
|
|
981
1162
|
skipImportNames: variants.map((variant) => variant.name)
|
|
982
1163
|
}];
|
|
983
1164
|
}
|
|
984
|
-
const responseUnits = node.responses.flatMap((response) => expandContentUnits(response.content ?? [], resolver.
|
|
985
|
-
const dataUnits = expandContentUnits(node.requestBody?.content ?? [], resolver.
|
|
1165
|
+
const responseUnits = node.responses.flatMap((response) => expandContentUnits(response.content ?? [], resolver.response.status(node, response.statusCode), tsResolver.response.status(node, response.statusCode), response.description));
|
|
1166
|
+
const dataUnits = expandContentUnits(node.requestBody?.content ?? [], resolver.response.body(node), tsResolver.response.body(node), node.requestBody?.description, (schema) => ({
|
|
986
1167
|
...schema,
|
|
987
1168
|
description: node.requestBody?.description ?? schema.description
|
|
988
1169
|
}));
|
|
989
|
-
const responseName = resolver.
|
|
1170
|
+
const responseName = resolver.response.response(node);
|
|
990
1171
|
const localHelperNames = /* @__PURE__ */ new Set([
|
|
991
|
-
...
|
|
1172
|
+
...paramGroups.map((group) => group.name),
|
|
992
1173
|
...responseUnits.map((unit) => unit.name),
|
|
993
1174
|
...dataUnits.map((unit) => unit.name),
|
|
994
1175
|
responseName
|
|
995
1176
|
]);
|
|
996
1177
|
const cyclicSchemas = new Set(ctx.meta.circularNames);
|
|
997
1178
|
const meta = {
|
|
998
|
-
file: resolver.
|
|
1179
|
+
file: resolver.file({
|
|
999
1180
|
name: node.operationId,
|
|
1000
1181
|
extname: ".ts",
|
|
1001
1182
|
tag: node.tags[0] ?? "default",
|
|
1002
|
-
path: node.path
|
|
1003
|
-
}, {
|
|
1183
|
+
path: node.path,
|
|
1004
1184
|
root,
|
|
1005
1185
|
output,
|
|
1006
1186
|
group: group ?? void 0
|
|
1007
1187
|
}),
|
|
1008
|
-
typeFile: tsResolver.
|
|
1188
|
+
typeFile: tsResolver.file({
|
|
1009
1189
|
name: node.operationId,
|
|
1010
1190
|
extname: ".ts",
|
|
1011
1191
|
tag: node.tags[0] ?? "default",
|
|
1012
|
-
path: node.path
|
|
1013
|
-
}, {
|
|
1192
|
+
path: node.path,
|
|
1014
1193
|
root,
|
|
1015
1194
|
output: pluginTs.options?.output ?? output,
|
|
1016
1195
|
group: pluginTs.options?.group ?? void 0
|
|
@@ -1018,11 +1197,10 @@ const fakerGenerator = defineGenerator({
|
|
|
1018
1197
|
};
|
|
1019
1198
|
function resolveMockImports(schema) {
|
|
1020
1199
|
return adapter.getImports(schema, (schemaName) => ({
|
|
1021
|
-
name: resolver.
|
|
1022
|
-
path: resolver.
|
|
1200
|
+
name: resolver.name(schemaName),
|
|
1201
|
+
path: resolver.file({
|
|
1023
1202
|
name: schemaName,
|
|
1024
|
-
extname: ".ts"
|
|
1025
|
-
}, {
|
|
1203
|
+
extname: ".ts",
|
|
1026
1204
|
root,
|
|
1027
1205
|
output,
|
|
1028
1206
|
group: group ?? void 0
|
|
@@ -1087,7 +1265,7 @@ const fakerGenerator = defineGenerator({
|
|
|
1087
1265
|
baseName: meta.file.baseName,
|
|
1088
1266
|
path: meta.file.path,
|
|
1089
1267
|
meta: meta.file.meta,
|
|
1090
|
-
banner: resolver.
|
|
1268
|
+
banner: resolver.default.banner(ctx.meta, {
|
|
1091
1269
|
output,
|
|
1092
1270
|
config,
|
|
1093
1271
|
file: {
|
|
@@ -1095,7 +1273,7 @@ const fakerGenerator = defineGenerator({
|
|
|
1095
1273
|
baseName: meta.file.baseName
|
|
1096
1274
|
}
|
|
1097
1275
|
}),
|
|
1098
|
-
footer: resolver.
|
|
1276
|
+
footer: resolver.default.footer(ctx.meta, {
|
|
1099
1277
|
output,
|
|
1100
1278
|
config,
|
|
1101
1279
|
file: {
|
|
@@ -1119,11 +1297,7 @@ const fakerGenerator = defineGenerator({
|
|
|
1119
1297
|
path: dateParser,
|
|
1120
1298
|
name: dateParser
|
|
1121
1299
|
}),
|
|
1122
|
-
|
|
1123
|
-
schema: param.schema,
|
|
1124
|
-
name,
|
|
1125
|
-
typeName
|
|
1126
|
-
})),
|
|
1300
|
+
paramGroups.map((group) => renderEntry(group)),
|
|
1127
1301
|
responseUnits.map((unit) => renderEntry({
|
|
1128
1302
|
schema: unit.schema,
|
|
1129
1303
|
name: unit.name,
|
|
@@ -1141,7 +1315,7 @@ const fakerGenerator = defineGenerator({
|
|
|
1141
1315
|
renderEntry({
|
|
1142
1316
|
schema: buildResponseUnionSchema(node, resolver),
|
|
1143
1317
|
name: responseName,
|
|
1144
|
-
typeName: tsResolver.
|
|
1318
|
+
typeName: tsResolver.response.response(node),
|
|
1145
1319
|
skipImportNames: responseUnits.map((unit) => unit.name)
|
|
1146
1320
|
})
|
|
1147
1321
|
]
|
|
@@ -1159,69 +1333,45 @@ const fakerGenerator = defineGenerator({
|
|
|
1159
1333
|
* ```ts
|
|
1160
1334
|
* import { resolverFaker } from '@kubb/plugin-faker'
|
|
1161
1335
|
*
|
|
1162
|
-
* resolverFaker.
|
|
1336
|
+
* resolverFaker.name('list pets') // 'createListPets'
|
|
1163
1337
|
* ```
|
|
1164
1338
|
*/
|
|
1165
|
-
const resolverFaker =
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
resolvePathName(name, type) {
|
|
1177
|
-
return this.default(name, type);
|
|
1178
|
-
},
|
|
1179
|
-
resolveFile({ name, extname, tag, path: groupPath }, context) {
|
|
1180
|
-
const inputBaseName = `${context.output.mode === "file" ? "" : this.resolveName(name, "file")}${extname}`;
|
|
1181
|
-
const filePath = this.resolvePath({
|
|
1182
|
-
baseName: inputBaseName,
|
|
1183
|
-
tag,
|
|
1184
|
-
path: groupPath
|
|
1185
|
-
}, context);
|
|
1186
|
-
const baseName = path.basename(filePath);
|
|
1187
|
-
return {
|
|
1188
|
-
kind: "File",
|
|
1189
|
-
id: createHash("sha256").update(filePath).digest("hex"),
|
|
1190
|
-
name: path.basename(filePath, extname),
|
|
1191
|
-
path: filePath,
|
|
1192
|
-
baseName,
|
|
1193
|
-
extname,
|
|
1194
|
-
meta: { pluginName: this.pluginName },
|
|
1195
|
-
sources: [],
|
|
1196
|
-
imports: [],
|
|
1197
|
-
exports: []
|
|
1198
|
-
};
|
|
1199
|
-
},
|
|
1200
|
-
resolveParamName(node, param) {
|
|
1201
|
-
return this.resolveName(`${node.operationId} ${param.in} ${param.name}`);
|
|
1202
|
-
},
|
|
1203
|
-
resolveDataName(node) {
|
|
1204
|
-
return this.resolveName(`${node.operationId} Data`);
|
|
1339
|
+
const resolverFaker = createResolver({
|
|
1340
|
+
pluginName: "plugin-faker",
|
|
1341
|
+
name(name) {
|
|
1342
|
+
return ensureValidVarName(camelCase(name, { prefix: "create" }));
|
|
1343
|
+
},
|
|
1344
|
+
file: { baseName({ name, extname }) {
|
|
1345
|
+
return `${toFilePath(name, (part) => camelCase(part, { prefix: "create" }))}${extname}`;
|
|
1346
|
+
} },
|
|
1347
|
+
param: {
|
|
1348
|
+
name(node, param) {
|
|
1349
|
+
return this.name(`${node.operationId} ${param.in} ${param.name}`);
|
|
1205
1350
|
},
|
|
1206
|
-
|
|
1207
|
-
return this.
|
|
1351
|
+
path(node) {
|
|
1352
|
+
return this.name(`${node.operationId} Path`);
|
|
1208
1353
|
},
|
|
1209
|
-
|
|
1210
|
-
return this.
|
|
1354
|
+
query(node) {
|
|
1355
|
+
return this.name(`${node.operationId} Query`);
|
|
1211
1356
|
},
|
|
1212
|
-
|
|
1213
|
-
return this.
|
|
1357
|
+
headers(node) {
|
|
1358
|
+
return this.name(`${node.operationId} Headers`);
|
|
1359
|
+
}
|
|
1360
|
+
},
|
|
1361
|
+
response: {
|
|
1362
|
+
status(node, statusCode) {
|
|
1363
|
+
return this.name(`${node.operationId} Status ${statusCode}`);
|
|
1214
1364
|
},
|
|
1215
|
-
|
|
1216
|
-
return this.
|
|
1365
|
+
body(node) {
|
|
1366
|
+
return this.name(`${node.operationId} Body`);
|
|
1217
1367
|
},
|
|
1218
|
-
|
|
1219
|
-
return this.
|
|
1368
|
+
response(node) {
|
|
1369
|
+
return this.name(`${node.operationId} Response`);
|
|
1220
1370
|
},
|
|
1221
|
-
|
|
1222
|
-
return this.
|
|
1371
|
+
responses(node) {
|
|
1372
|
+
return this.name(`${node.operationId} Responses`);
|
|
1223
1373
|
}
|
|
1224
|
-
}
|
|
1374
|
+
}
|
|
1225
1375
|
});
|
|
1226
1376
|
//#endregion
|
|
1227
1377
|
//#region src/plugin.ts
|
|
@@ -1277,10 +1427,7 @@ const pluginFaker = definePlugin((options) => {
|
|
|
1277
1427
|
regexGenerator,
|
|
1278
1428
|
printer
|
|
1279
1429
|
});
|
|
1280
|
-
ctx.setResolver(userResolver ?
|
|
1281
|
-
...resolverFaker,
|
|
1282
|
-
...userResolver
|
|
1283
|
-
} : resolverFaker);
|
|
1430
|
+
ctx.setResolver(userResolver ? Resolver.merge(resolverFaker, userResolver) : resolverFaker);
|
|
1284
1431
|
if (userMacros?.length) ctx.setMacros(userMacros);
|
|
1285
1432
|
ctx.addGenerator(fakerGenerator);
|
|
1286
1433
|
} }
|