@kubb/plugin-faker 5.4.0-canary.20261111T115959 → 5.4.0
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 +248 -285
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +248 -285
- package/dist/index.js.map +1 -1
- package/docs/options.md +1 -1
- package/kubb-extension.json +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
let node_path = require("node:path");
|
|
6
5
|
let _kubb_kit = require("@kubb/kit");
|
|
6
|
+
let node_path = require("node:path");
|
|
7
7
|
let _kubb_renderer_jsx = require("@kubb/renderer-jsx");
|
|
8
8
|
let _kubb_renderer_jsx_jsx_runtime = require("@kubb/renderer-jsx/jsx-runtime");
|
|
9
9
|
let _kubb_plugin_ts = require("@kubb/plugin-ts");
|
|
@@ -146,67 +146,76 @@ function ensureValidVarName(name) {
|
|
|
146
146
|
function isIdentifier(name) {
|
|
147
147
|
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
148
148
|
}
|
|
149
|
-
// ../../internals/utils/src/
|
|
149
|
+
// ../../internals/utils/src/codegen.ts
|
|
150
150
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
151
|
+
* Assembles a multi-line object literal from already-rendered `entries`, indenting each entry one
|
|
152
|
+
* level and closing the brace at column zero. Entries that are themselves multi-line objects indent
|
|
153
|
+
* cumulatively. Each entry ends with a trailing comma to match the formatter's multi-line style.
|
|
153
154
|
*
|
|
154
155
|
* @example
|
|
155
156
|
* ```ts
|
|
156
|
-
*
|
|
157
|
-
*
|
|
157
|
+
* buildObject(['id: z.number()', 'name: z.string()'])
|
|
158
|
+
* // '{\n id: z.number(),\n name: z.string(),\n}'
|
|
158
159
|
* ```
|
|
159
160
|
*/
|
|
160
|
-
function
|
|
161
|
-
if (
|
|
162
|
-
return `
|
|
161
|
+
function buildObject(entries) {
|
|
162
|
+
if (entries.length === 0) return "{}";
|
|
163
|
+
return `{\n${entries.map((entry) => `${_kubb_kit.text.indent({ text: entry })},`).join("\n")}\n}`;
|
|
163
164
|
}
|
|
164
165
|
/**
|
|
165
|
-
*
|
|
166
|
-
* Returns the string unchanged when no balanced quote pair is found.
|
|
166
|
+
* An object key, quoted only when it is not identifier-shaped. Reserved words such as `class` stay bare.
|
|
167
167
|
*
|
|
168
168
|
* @example
|
|
169
169
|
* ```ts
|
|
170
|
-
*
|
|
171
|
-
* trimQuotes('hello') // 'hello'
|
|
170
|
+
* objectKey('x-total') // "'x-total'"
|
|
172
171
|
* ```
|
|
173
172
|
*/
|
|
174
|
-
function
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return
|
|
173
|
+
function objectKey(name) {
|
|
174
|
+
return isIdentifier(name) ? name : _kubb_kit.text.quote(name);
|
|
175
|
+
}
|
|
176
|
+
// ../../internals/utils/src/fs.ts
|
|
177
|
+
function toSlash(p) {
|
|
178
|
+
if (p.startsWith("\\\\?\\")) return p;
|
|
179
|
+
return p.replaceAll("\\", "/");
|
|
181
180
|
}
|
|
182
181
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* Escaping runs through `JSON.stringify`, then the result switches to single quotes so the generated
|
|
186
|
-
* code matches the repo style without a formatter.
|
|
182
|
+
* Returns the relative path from `rootDir` to `filePath`, always using forward slashes
|
|
183
|
+
* and prefixed with `./` when not already traversing upward.
|
|
187
184
|
*
|
|
188
185
|
* @example
|
|
189
186
|
* ```ts
|
|
190
|
-
*
|
|
191
|
-
*
|
|
187
|
+
* getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'
|
|
188
|
+
* getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'
|
|
192
189
|
* ```
|
|
193
190
|
*/
|
|
194
|
-
function
|
|
195
|
-
|
|
196
|
-
return
|
|
191
|
+
function getRelativePath(rootDir, filePath) {
|
|
192
|
+
const relativePath = node_path.posix.relative(toSlash(rootDir), toSlash(filePath));
|
|
193
|
+
return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
|
|
197
194
|
}
|
|
198
195
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
196
|
+
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
197
|
+
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
198
|
+
* every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
|
|
201
199
|
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
200
|
+
* Empty segments are dropped before joining. They arise when the name starts with a dot
|
|
201
|
+
* followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
|
|
202
|
+
* an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
|
|
203
|
+
* absolute path, letting generated files escape the configured output directory.
|
|
204
|
+
*
|
|
205
|
+
* @example Nested path from a dotted name
|
|
206
|
+
* `toFilePath('pet.petId') // 'pet/petId'`
|
|
207
|
+
*
|
|
208
|
+
* @example PascalCase the final segment
|
|
209
|
+
* `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
|
|
210
|
+
*
|
|
211
|
+
* @example Suffix applied to the final segment only
|
|
212
|
+
* `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
|
|
206
213
|
*/
|
|
207
|
-
function
|
|
208
|
-
|
|
214
|
+
function toFilePath(name, caseLast = _kubb_kit.casing.camel) {
|
|
215
|
+
const parts = name.split(/\.(?=[a-zA-Z])/);
|
|
216
|
+
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : _kubb_kit.casing.camel(part)).filter(Boolean).join("/");
|
|
209
217
|
}
|
|
218
|
+
// ../../internals/utils/src/strings.ts
|
|
210
219
|
const NEEDS_UNICODE = /(?<!\\)(?:\\\\)*\\[pPu]\{|[\u{10000}-\u{10FFFF}]/u;
|
|
211
220
|
const KEPT_ESCAPE = /[A-Za-z0-9^$\\.*+?()[\]{}|/]/;
|
|
212
221
|
/**
|
|
@@ -246,8 +255,8 @@ function toRegExp(pattern, flags) {
|
|
|
246
255
|
* toRegExpString('^(?im)foo', null) // '/^foo/im'
|
|
247
256
|
* ```
|
|
248
257
|
*/
|
|
249
|
-
function toRegExpString(
|
|
250
|
-
const raw =
|
|
258
|
+
function toRegExpString(pattern, func = "RegExp") {
|
|
259
|
+
const raw = _kubb_kit.text.unquote(pattern);
|
|
251
260
|
const match = raw.match(/^\^(\(\?([igmsuy]+)\))/i);
|
|
252
261
|
const replacementTarget = match?.[1] ?? "";
|
|
253
262
|
const matchedFlags = match?.[2];
|
|
@@ -255,84 +264,17 @@ function toRegExpString(text, func = "RegExp") {
|
|
|
255
264
|
if (func === null) return `/${source}/${flags}`;
|
|
256
265
|
return `new ${func}(${JSON.stringify(source)}${flags ? `, ${JSON.stringify(flags)}` : ""})`;
|
|
257
266
|
}
|
|
258
|
-
// ../../internals/utils/src/codegen.ts
|
|
259
|
-
const INDENT = " ";
|
|
260
|
-
/**
|
|
261
|
-
* Indents every non-empty line of `text` by one indent level, leaving blank lines empty.
|
|
262
|
-
*/
|
|
263
|
-
function indentLines(text) {
|
|
264
|
-
if (!text) return "";
|
|
265
|
-
return text.split("\n").map((line) => line.trim() ? `${INDENT}${line}` : "").join("\n");
|
|
266
|
-
}
|
|
267
267
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* @example
|
|
272
|
-
* ```ts
|
|
273
|
-
* objectKey('name') // 'name'
|
|
274
|
-
* objectKey('x-total') // "'x-total'"
|
|
275
|
-
* ```
|
|
276
|
-
*/
|
|
277
|
-
function objectKey(name) {
|
|
278
|
-
return isIdentifier(name) ? name : singleQuote(name);
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Assembles a multi-line object literal from already-rendered `entries`, indenting each entry one
|
|
282
|
-
* level and closing the brace at column zero. Entries that are themselves multi-line objects indent
|
|
283
|
-
* cumulatively. Each entry ends with a trailing comma to match the formatter's multi-line style.
|
|
284
|
-
*
|
|
285
|
-
* @example
|
|
286
|
-
* ```ts
|
|
287
|
-
* buildObject(['id: z.number()', 'name: z.string()'])
|
|
288
|
-
* // '{\n id: z.number(),\n name: z.string(),\n}'
|
|
289
|
-
* ```
|
|
290
|
-
*/
|
|
291
|
-
function buildObject(entries) {
|
|
292
|
-
if (entries.length === 0) return "{}";
|
|
293
|
-
return `{\n${entries.map((entry) => `${indentLines(entry)},`).join("\n")}\n}`;
|
|
294
|
-
}
|
|
295
|
-
// ../../internals/utils/src/fs.ts
|
|
296
|
-
function toSlash(p) {
|
|
297
|
-
if (p.startsWith("\\\\?\\")) return p;
|
|
298
|
-
return p.replaceAll("\\", "/");
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Returns the relative path from `rootDir` to `filePath`, always using forward slashes
|
|
302
|
-
* and prefixed with `./` when not already traversing upward.
|
|
268
|
+
* Escapes an `@` at the start of a line, so a multi-line description can't start a new JSDoc tag.
|
|
269
|
+
* Editors render `\@` as `@` in hovers.
|
|
303
270
|
*
|
|
304
271
|
* @example
|
|
305
272
|
* ```ts
|
|
306
|
-
*
|
|
307
|
-
* getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'
|
|
273
|
+
* jsDocEscape('intro\n@example value') // 'intro\n\\@example value'
|
|
308
274
|
* ```
|
|
309
275
|
*/
|
|
310
|
-
function
|
|
311
|
-
|
|
312
|
-
return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
316
|
-
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
317
|
-
* every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
|
|
318
|
-
*
|
|
319
|
-
* Empty segments are dropped before joining. They arise when the name starts with a dot
|
|
320
|
-
* followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
|
|
321
|
-
* an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
|
|
322
|
-
* absolute path, letting generated files escape the configured output directory.
|
|
323
|
-
*
|
|
324
|
-
* @example Nested path from a dotted name
|
|
325
|
-
* `toFilePath('pet.petId') // 'pet/petId'`
|
|
326
|
-
*
|
|
327
|
-
* @example PascalCase the final segment
|
|
328
|
-
* `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
|
|
329
|
-
*
|
|
330
|
-
* @example Suffix applied to the final segment only
|
|
331
|
-
* `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
|
|
332
|
-
*/
|
|
333
|
-
function toFilePath(name, caseLast = _kubb_kit.camelCase) {
|
|
334
|
-
const parts = name.split(/\.(?=[a-zA-Z])/);
|
|
335
|
-
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : (0, _kubb_kit.camelCase)(part)).filter(Boolean).join("/");
|
|
276
|
+
function jsDocEscape(input) {
|
|
277
|
+
return `${input}`.replace(/^(\s*)@/gm, "$1\\@");
|
|
336
278
|
}
|
|
337
279
|
// ../../internals/shared/src/operation.ts
|
|
338
280
|
/**
|
|
@@ -399,19 +341,12 @@ function resolveOperationFile(options) {
|
|
|
399
341
|
return file;
|
|
400
342
|
});
|
|
401
343
|
}
|
|
402
|
-
function baseContentType(contentType) {
|
|
403
|
-
return contentType.split(";")[0].trim().toLowerCase();
|
|
404
|
-
}
|
|
405
344
|
/**
|
|
406
|
-
*
|
|
407
|
-
* `application/x-ndjson`, `application/json-seq`, or any media type with an OpenAPI 3.2 `itemSchema`.
|
|
345
|
+
* How a content entry is framed as a stream: `'events'` for Server-Sent Events, `'lines'` for JSON Lines.
|
|
408
346
|
*/
|
|
409
|
-
function
|
|
410
|
-
|
|
411
|
-
return
|
|
412
|
-
}
|
|
413
|
-
function isJsonContentType(baseType) {
|
|
414
|
-
return baseType === "application/json" || baseType.endsWith("+json") || baseType === "text/json";
|
|
347
|
+
function getStreamFraming(entry) {
|
|
348
|
+
if (_kubb_kit.ast.mediaType.getBase(entry) === "text/event-stream") return "events";
|
|
349
|
+
return entry.stream && _kubb_kit.ast.mediaType.isStream(entry) ? "lines" : void 0;
|
|
415
350
|
}
|
|
416
351
|
/**
|
|
417
352
|
* Parser for one response content entry.
|
|
@@ -422,10 +357,10 @@ function isJsonContentType(baseType) {
|
|
|
422
357
|
* `image/*`, `audio/*`, and `video/*` are blobs.
|
|
423
358
|
*/
|
|
424
359
|
function responseTypeForContent(entry) {
|
|
425
|
-
const baseType =
|
|
360
|
+
const baseType = _kubb_kit.ast.mediaType.getBase(entry);
|
|
426
361
|
if (!baseType) return void 0;
|
|
427
|
-
if (
|
|
428
|
-
if (
|
|
362
|
+
if (getStreamFraming(entry)) return "stream";
|
|
363
|
+
if (_kubb_kit.ast.mediaType.isJson(baseType)) return void 0;
|
|
429
364
|
if (entry.schema?.type === "blob") return "blob";
|
|
430
365
|
if (baseType.startsWith("text/")) return "text";
|
|
431
366
|
if (isBinaryContentType(baseType)) return "blob";
|
|
@@ -463,14 +398,14 @@ function getPerContentTypeName(baseName, suffix) {
|
|
|
463
398
|
function toResponseContent(entry, entries = [entry]) {
|
|
464
399
|
const { contentType, schema } = entry;
|
|
465
400
|
if (!schema || entry.stream) return entry;
|
|
466
|
-
const baseType =
|
|
467
|
-
const resolved = _kubb_kit.ast.
|
|
401
|
+
const baseType = _kubb_kit.ast.mediaType.getBase(contentType);
|
|
402
|
+
const resolved = _kubb_kit.ast.ref.getSchema(schema);
|
|
468
403
|
if (isBinaryContentType(baseType)) return resolved.type === "blob" ? entry : {
|
|
469
404
|
...entry,
|
|
470
405
|
schema: _kubb_kit.ast.factory.createSchema({ type: "blob" }),
|
|
471
406
|
keysToOmit: null
|
|
472
407
|
};
|
|
473
|
-
const isPlainMediaType = Boolean(baseType) && !
|
|
408
|
+
const isPlainMediaType = Boolean(baseType) && !_kubb_kit.ast.mediaType.isJson(baseType) && !baseType.includes("*");
|
|
474
409
|
if (resolved.type === "blob") return isPlainMediaType && !entries.every((item) => item.schema?.type === "blob") ? {
|
|
475
410
|
...entry,
|
|
476
411
|
schema: _kubb_kit.ast.factory.createSchema({ type: "string" }),
|
|
@@ -513,56 +448,15 @@ function resolveContentTypeVariants(entries, baseName) {
|
|
|
513
448
|
};
|
|
514
449
|
});
|
|
515
450
|
}
|
|
516
|
-
const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
|
|
517
|
-
/**
|
|
518
|
-
* An OpenAPI 3.2 `querystring` parameter is the whole query string, so a form-encoded object becomes one query parameter
|
|
519
|
-
* per property, typed and serialized like any other.
|
|
520
|
-
* Another content type, such as JSON, stays one parameter named after it, and the runtime sends its value as the whole query string.
|
|
521
|
-
*/
|
|
522
|
-
function spreadQuerystring(param) {
|
|
523
|
-
const schema = param.schema.type === "ref" ? param.schema.schema : param.schema;
|
|
524
|
-
const formEncoded = !param.contentType || param.contentType.split(";")[0].trim().toLowerCase() === "application/x-www-form-urlencoded";
|
|
525
|
-
if (schema?.type !== "object" || !formEncoded) return [param];
|
|
526
|
-
return schema.properties.map((property) => _kubb_kit.ast.factory.createParameter({
|
|
527
|
-
name: property.name,
|
|
528
|
-
in: "query",
|
|
529
|
-
schema: property.schema,
|
|
530
|
-
required: param.required && property.required
|
|
531
|
-
}));
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
|
|
535
|
-
* group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
|
|
536
|
-
* (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
|
|
537
|
-
* same parameters once per plugin.
|
|
538
|
-
*/
|
|
539
|
-
function getOperationParameters(node) {
|
|
540
|
-
const cached = operationParameterGroupsByNode.get(node);
|
|
541
|
-
if (cached) return cached;
|
|
542
|
-
const dedupe = (params) => {
|
|
543
|
-
const seen = /* @__PURE__ */ new Set();
|
|
544
|
-
return params.filter((param) => {
|
|
545
|
-
if (seen.has(param.name)) return false;
|
|
546
|
-
seen.add(param.name);
|
|
547
|
-
return true;
|
|
548
|
-
});
|
|
549
|
-
};
|
|
550
|
-
const group = (location) => dedupe(node.parameters.filter((param) => param.in === location));
|
|
551
|
-
const groups = {
|
|
552
|
-
path: group("path"),
|
|
553
|
-
query: dedupe([...group("query"), ...group("querystring").flatMap(spreadQuerystring)]),
|
|
554
|
-
header: group("header"),
|
|
555
|
-
cookie: group("cookie")
|
|
556
|
-
};
|
|
557
|
-
operationParameterGroupsByNode.set(node, groups);
|
|
558
|
-
return groups;
|
|
559
|
-
}
|
|
560
451
|
// ../../internals/shared/src/resolver.ts
|
|
561
452
|
/**
|
|
562
453
|
* Builds the allocation key for a declaration an operation owns. `scope` names which declaration
|
|
563
454
|
* it is, so two of them never share an allocation even when a custom resolver gives both the same
|
|
564
455
|
* name. Leave `scope` empty for the operation's own declaration.
|
|
565
456
|
*
|
|
457
|
+
* The key starts from the operation's input `pointer`, which macros keep, so a plugin whose macro
|
|
458
|
+
* rewrites the method or path still resolves another plugin's names for the same operation.
|
|
459
|
+
*
|
|
566
460
|
* @example
|
|
567
461
|
* ```ts
|
|
568
462
|
* resolver.resolveName({ key: operationKey(node, 'response', 'status', 404), name })
|
|
@@ -571,8 +465,7 @@ function getOperationParameters(node) {
|
|
|
571
465
|
function operationKey(node, ...scope) {
|
|
572
466
|
return [
|
|
573
467
|
"operation",
|
|
574
|
-
node.method,
|
|
575
|
-
node.path,
|
|
468
|
+
...node.pointer ? [node.pointer] : [node.method, node.path],
|
|
576
469
|
...scope.map(String)
|
|
577
470
|
];
|
|
578
471
|
}
|
|
@@ -643,6 +536,13 @@ function createOperationResponseResolver() {
|
|
|
643
536
|
name
|
|
644
537
|
});
|
|
645
538
|
},
|
|
539
|
+
headers(node, statusCode) {
|
|
540
|
+
const name = this.name(`${node.operationId} Status ${statusCode} Headers`);
|
|
541
|
+
return this.resolveName({
|
|
542
|
+
key: operationKey(node, "response", "headers", statusCode),
|
|
543
|
+
name
|
|
544
|
+
});
|
|
545
|
+
},
|
|
646
546
|
body(node) {
|
|
647
547
|
const name = this.name(`${node.operationId} Body`);
|
|
648
548
|
return this.resolveName({
|
|
@@ -684,58 +584,7 @@ function createCasedFile(caseLast) {
|
|
|
684
584
|
* Names of the schemas in a circular reference chain, computed once per build.
|
|
685
585
|
*/
|
|
686
586
|
function getCircularNames(ctx) {
|
|
687
|
-
return ctx.memo("circularNames:set", () => _kubb_kit.ast.
|
|
688
|
-
}
|
|
689
|
-
// ../../internals/shared/src/group.ts
|
|
690
|
-
/**
|
|
691
|
-
* Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
|
|
692
|
-
* shared default naming so every plugin groups output consistently:
|
|
693
|
-
*
|
|
694
|
-
* - `path` groups use the second path segment (`/pet/findByStatus` → `pet`).
|
|
695
|
-
* - other groups use the camelCased group (`pet store` → `petStore`).
|
|
696
|
-
*
|
|
697
|
-
* A user-provided `group.name` always wins over the default namer, so callers stay in
|
|
698
|
-
* control of their output folders. Returns `null` when grouping is disabled, matching the
|
|
699
|
-
* per-plugin convention.
|
|
700
|
-
*
|
|
701
|
-
* @param group - The user-supplied group option, or `undefined` to disable grouping.
|
|
702
|
-
*
|
|
703
|
-
* @example
|
|
704
|
-
* ```ts
|
|
705
|
-
* createGroupConfig(group) // shared across every plugin
|
|
706
|
-
* ```
|
|
707
|
-
*/
|
|
708
|
-
function createGroupConfig(group) {
|
|
709
|
-
if (!group) return null;
|
|
710
|
-
const defaultName = (ctx) => {
|
|
711
|
-
if (group.type === "path") return `${ctx.group.split("/")[1]}`;
|
|
712
|
-
return (0, _kubb_kit.camelCase)(ctx.group);
|
|
713
|
-
};
|
|
714
|
-
return {
|
|
715
|
-
...group,
|
|
716
|
-
name: group.name ? group.name : defaultName
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
// ../../internals/shared/src/schemaTraversal.ts
|
|
720
|
-
/**
|
|
721
|
-
* Maps each member of a union or intersection schema to its transformed output, pairing every
|
|
722
|
-
* result with the original member.
|
|
723
|
-
*/
|
|
724
|
-
function mapSchemaMembers(node, transform) {
|
|
725
|
-
return (node.members ?? []).map((schema) => ({
|
|
726
|
-
schema,
|
|
727
|
-
output: transform(schema)
|
|
728
|
-
}));
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* Maps each item of an array or tuple schema to its transformed output, pairing every result with
|
|
732
|
-
* the original item.
|
|
733
|
-
*/
|
|
734
|
-
function mapSchemaItems(node, transform) {
|
|
735
|
-
return (node.items ?? []).map((schema) => ({
|
|
736
|
-
schema,
|
|
737
|
-
output: transform(schema)
|
|
738
|
-
}));
|
|
587
|
+
return ctx.memo("circularNames:set", () => _kubb_kit.ast.graph.getCircularNames(ctx.driver.inputNode?.schemas ?? []));
|
|
739
588
|
}
|
|
740
589
|
// src/utils.ts
|
|
741
590
|
/**
|
|
@@ -792,26 +641,29 @@ function canOverrideSchema(node) {
|
|
|
792
641
|
* Whether a schema can supply object properties when merging faker values.
|
|
793
642
|
*/
|
|
794
643
|
function isObjectSchema(node, seen = /* @__PURE__ */ new Set()) {
|
|
795
|
-
const resolved = _kubb_kit.ast.
|
|
644
|
+
const resolved = _kubb_kit.ast.ref.getSchema(node);
|
|
796
645
|
if (seen.has(resolved)) return false;
|
|
797
646
|
seen.add(resolved);
|
|
798
|
-
if (_kubb_kit.ast.
|
|
799
|
-
const composition = _kubb_kit.ast.
|
|
647
|
+
if (_kubb_kit.ast.schema.narrow(resolved, _kubb_kit.ast.schema.types.object) || _kubb_kit.ast.schema.narrow(resolved, _kubb_kit.ast.schema.types.ref)) return true;
|
|
648
|
+
const composition = _kubb_kit.ast.schema.narrow(resolved, _kubb_kit.ast.schema.types.intersection) ?? _kubb_kit.ast.schema.narrow(resolved, _kubb_kit.ast.schema.types.union);
|
|
800
649
|
if (!composition) return false;
|
|
801
|
-
return composition.type === _kubb_kit.ast.
|
|
650
|
+
return composition.type === _kubb_kit.ast.schema.types.intersection && !composition.members?.length || (composition.members ?? []).some((member) => isObjectSchema(member, seen));
|
|
802
651
|
}
|
|
803
652
|
function shouldInlineSingleResponseSchema(schema) {
|
|
804
653
|
return !NON_INLINABLE_RESPONSE_TYPES.has(schema.type);
|
|
805
654
|
}
|
|
806
655
|
/**
|
|
807
|
-
* Builds a response schema as a union of
|
|
656
|
+
* Builds a response schema as a union of the success response statuses, like the `<Operation>Response` type of
|
|
657
|
+
* `@kubb/plugin-ts`, so the mock never is an error body. Falls back to every response when no success response has a schema.
|
|
808
658
|
* Returns null if no responses are provided, or embeds single simple responses inline.
|
|
809
659
|
*/
|
|
810
660
|
function buildResponseUnionSchema(node, resolver) {
|
|
811
|
-
const
|
|
661
|
+
const withSchema = node.responses.map((response) => ({
|
|
812
662
|
...response,
|
|
813
663
|
content: response.content?.map((entry, _, content) => toResponseContent(entry, content))
|
|
814
664
|
})).filter((response) => response.content?.[0]?.schema);
|
|
665
|
+
const success = withSchema.filter((response) => _kubb_kit.ast.http.status.isSuccess(response));
|
|
666
|
+
const responses = success.length > 0 ? success : withSchema;
|
|
815
667
|
if (!responses.length) return null;
|
|
816
668
|
if (responses.length === 1) {
|
|
817
669
|
const schemas = responses[0].content?.flatMap((content) => content.schema ? [content.schema] : []) ?? [];
|
|
@@ -892,7 +744,7 @@ function getScalarType(node, typeName) {
|
|
|
892
744
|
* Determines the data type, return type, and whether it uses the type name.
|
|
893
745
|
*/
|
|
894
746
|
function resolveFakerTypeUsage(node, typeName, canOverride) {
|
|
895
|
-
const resolvedNode = _kubb_kit.ast.
|
|
747
|
+
const resolvedNode = _kubb_kit.ast.ref.getSchema(node);
|
|
896
748
|
const scalarType = SCALAR_TYPES.has(resolvedNode.type) ? `${getScalarType(resolvedNode, typeName)}${node.nullable || resolvedNode.nullable ? " | null" : ""}` : void 0;
|
|
897
749
|
const dataType = scalarType ?? `Partial<${typeName}>`;
|
|
898
750
|
const returnType = scalarType ?? (canOverride ? typeName : null);
|
|
@@ -911,8 +763,8 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
|
|
|
911
763
|
imp.name
|
|
912
764
|
].join("-")));
|
|
913
765
|
const isArray = node.type === "array";
|
|
914
|
-
const isObject = !!_kubb_kit.ast.
|
|
915
|
-
const isValueIntersection = node.type === _kubb_kit.ast.
|
|
766
|
+
const isObject = !!_kubb_kit.ast.schema.narrow(node, _kubb_kit.ast.schema.types.object) || node.type === _kubb_kit.ast.schema.types.intersection && isObjectSchema(node);
|
|
767
|
+
const isValueIntersection = node.type === _kubb_kit.ast.schema.types.intersection && !isObject;
|
|
916
768
|
const isTuple = node.type === "tuple";
|
|
917
769
|
const isScalar = SCALAR_TYPES.has(node.type);
|
|
918
770
|
const isUnion = node.type === "union";
|
|
@@ -921,13 +773,14 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
|
|
|
921
773
|
if (canOverride && node.type === "tuple") return `data && data.length === ${node.items?.length ?? 0} && !data.includes(undefined) ? data : ${fakerText}`;
|
|
922
774
|
if (canOverride && isArray) return `[\n ...${fakerText},\n ...(data || []).filter((item) => item !== undefined),\n]`;
|
|
923
775
|
if (canOverride && (isScalar || isUnion || isValueIntersection)) return node.nullable ? `data !== undefined ? data : ${fakerText}` : `data ?? ${fakerText}`;
|
|
776
|
+
if (canOverride && node.type === "ref" && node.nullable && SCALAR_TYPES.has(_kubb_kit.ast.ref.getSchema(node).type)) return `data === null ? data : ${fakerText}`;
|
|
924
777
|
return fakerText;
|
|
925
778
|
})();
|
|
926
779
|
const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
|
|
927
780
|
if (!useObjectOverride) {
|
|
928
781
|
const paramsSignature = `${/\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data"}?: ${dataType}`;
|
|
929
782
|
const returnType = resolvedReturnType;
|
|
930
|
-
const returnExpression = canOverride && !!returnType && (node.type === "ref" && !SCALAR_TYPES.has(_kubb_kit.ast.
|
|
783
|
+
const returnExpression = canOverride && !!returnType && (node.type === "ref" && !SCALAR_TYPES.has(_kubb_kit.ast.ref.getSchema(node).type) || isArray || isTuple || isUnion) ? `${isTuple || isUnion ? `(${fakerTextWithOverride})` : fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride;
|
|
931
784
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [imports, /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
932
785
|
name,
|
|
933
786
|
isExportable: true,
|
|
@@ -945,10 +798,11 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
|
|
|
945
798
|
const { cyclicSchemas, schemaName } = printer.options;
|
|
946
799
|
const isCyclic = !!schemaName && !!cyclicSchemas?.has(schemaName);
|
|
947
800
|
const returnType = typeMode === "schema" ? typeName : `Omit<${isCyclic ? typeName : "typeof defaultFakeData"}, keyof NoInfer<TData>> & NoInfer<TData>`;
|
|
948
|
-
const hasGetters = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) =>
|
|
801
|
+
const hasGetters = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) => _kubb_kit.ast.graph.containsCircular(p.schema, {
|
|
949
802
|
circularSchemas: cyclicSchemas,
|
|
950
803
|
excludeName: schemaName
|
|
951
804
|
}));
|
|
805
|
+
const castThroughUnknown = (node.type !== "object" || node.min !== void 0) && typeMode !== "schema";
|
|
952
806
|
const declaration = `const ${keysToOmit?.length ? `{ ${keysToOmit.map((key, index) => `${objectKey(key)}: _omit${index}`).join(", ")}, ...defaultFakeData }` : "defaultFakeData"} = ${fakerText}`;
|
|
953
807
|
const functionBody = hasGetters ? `${declaration}
|
|
954
808
|
if (data) {
|
|
@@ -960,7 +814,7 @@ return defaultFakeData as ${returnType}` : `${declaration}
|
|
|
960
814
|
return {
|
|
961
815
|
...defaultFakeData,
|
|
962
816
|
...(data || {}),
|
|
963
|
-
} as ${returnType}`;
|
|
817
|
+
} as ${castThroughUnknown ? "unknown as " : ""}${returnType}`;
|
|
964
818
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx_jsx_runtime.Fragment, { children: [imports, /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsx)(_kubb_renderer_jsx.File.Source, {
|
|
965
819
|
name,
|
|
966
820
|
isExportable: true,
|
|
@@ -1037,11 +891,38 @@ const integerFormats = /* @__PURE__ */ new Set([
|
|
|
1037
891
|
"uint64"
|
|
1038
892
|
]);
|
|
1039
893
|
const maxInt32 = 2147483647;
|
|
894
|
+
const maxValueByFormat = {
|
|
895
|
+
int32: maxInt32,
|
|
896
|
+
uint32: 4294967295
|
|
897
|
+
};
|
|
898
|
+
function isCyclicRef(node, { schemaName, cyclicSchemas }) {
|
|
899
|
+
if (node.type !== "ref" || !schemaName) return false;
|
|
900
|
+
const refName = _kubb_kit.ast.ref.getName(node);
|
|
901
|
+
return refName === schemaName || Boolean(refName && cyclicSchemas?.has(schemaName) && cyclicSchemas.has(refName));
|
|
902
|
+
}
|
|
1040
903
|
/**
|
|
1041
|
-
* `faker.number.float()` or `faker.number.
|
|
904
|
+
* `faker.number.float()`, `faker.number.int()` or `faker.number.bigInt()`, with `min` and `max` passed only when set,
|
|
905
|
+
* moved inside an exclusive bound, or needed so a lone bound does not contradict faker's default for the other.
|
|
1042
906
|
*/
|
|
1043
|
-
function numberCall(kind, min, max) {
|
|
1044
|
-
const
|
|
907
|
+
function numberCall(kind, { min, max, exclusive, multipleOf }) {
|
|
908
|
+
const isWhole = kind !== "float";
|
|
909
|
+
const grid = isWhole && !Number.isInteger(multipleOf) ? void 0 : multipleOf;
|
|
910
|
+
const { min: lower, max: upper } = _kubb_kit.ast.schema.getNumberBounds({
|
|
911
|
+
min,
|
|
912
|
+
max,
|
|
913
|
+
exclusive,
|
|
914
|
+
integer: isWhole,
|
|
915
|
+
step: grid
|
|
916
|
+
});
|
|
917
|
+
const span = 100 * (grid ?? 1);
|
|
918
|
+
const maxValue = kind === "float" && lower !== void 0 && upper === void 0 && (lower >= 1 || grid !== void 0) ? lower + span : upper;
|
|
919
|
+
const minValue = maxValue !== void 0 && lower === void 0 && (isWhole ? maxValue < 0 : maxValue <= 0) ? maxValue - span : lower;
|
|
920
|
+
const suffix = kind === "bigInt" ? "n" : "";
|
|
921
|
+
const args = [
|
|
922
|
+
minValue !== void 0 && `min: ${minValue}${suffix}`,
|
|
923
|
+
maxValue !== void 0 && `max: ${maxValue}${suffix}`,
|
|
924
|
+
grid !== void 0 && `multipleOf: ${grid}${suffix}`
|
|
925
|
+
].filter(Boolean).join(", ");
|
|
1045
926
|
return `faker.number.${kind}(${args ? `{ ${args} }` : ""})`;
|
|
1046
927
|
}
|
|
1047
928
|
/**
|
|
@@ -1059,12 +940,58 @@ function dateTimeCall(representation, { format, substring }, parser = "faker", s
|
|
|
1059
940
|
});
|
|
1060
941
|
return "faker.date.anytime()";
|
|
1061
942
|
}
|
|
943
|
+
const encodingCalls = /* @__PURE__ */ new Map([["base64", "btoa(faker.string.alpha())"], ["base64url", "faker.string.alphanumeric(8)"]]);
|
|
944
|
+
const stringFormatCalls = /* @__PURE__ */ new Map([
|
|
945
|
+
["jwt", "faker.internet.jwt()"],
|
|
946
|
+
["ulid", "faker.string.ulid()"],
|
|
947
|
+
["iban", "faker.finance.iban()"],
|
|
948
|
+
["duration", "'P1D'"],
|
|
949
|
+
["hostname", "faker.internet.domainName()"]
|
|
950
|
+
]);
|
|
951
|
+
const classEscapes = new Map([
|
|
952
|
+
["d", "0-9"],
|
|
953
|
+
["w", "A-Za-z0-9_"],
|
|
954
|
+
...Array.from("-!@#$&()`.+,\"", (char) => [char, char])
|
|
955
|
+
]);
|
|
956
|
+
function toFakerPattern(pattern) {
|
|
957
|
+
let result = "";
|
|
958
|
+
let inClass = false;
|
|
959
|
+
let classStart = -1;
|
|
960
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
961
|
+
const char = pattern[index];
|
|
962
|
+
const next = pattern[index + 1];
|
|
963
|
+
if (char === "\\" && next !== void 0) {
|
|
964
|
+
index++;
|
|
965
|
+
if (inClass && next === "-") {
|
|
966
|
+
if (result[classStart] !== "-") result = `${result.slice(0, classStart)}-${result.slice(classStart)}`;
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
const classMembers = classEscapes.get(next);
|
|
970
|
+
if (classMembers === void 0) {
|
|
971
|
+
result += `\\${next}`;
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
result += inClass ? classMembers : `[${classMembers}]`;
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
if (char === "[" && !inClass) {
|
|
978
|
+
inClass = true;
|
|
979
|
+
result += next === "^" ? "[^" : "[";
|
|
980
|
+
if (next === "^") index++;
|
|
981
|
+
classStart = result.length;
|
|
982
|
+
continue;
|
|
983
|
+
}
|
|
984
|
+
if (char === "]") inClass = false;
|
|
985
|
+
result += char;
|
|
986
|
+
}
|
|
987
|
+
return result.replace(/\{(\d+),\}/g, (_, min) => `{${min},${Number(min) + 10}}`);
|
|
988
|
+
}
|
|
1062
989
|
function matches(value, regexGenerator = "faker") {
|
|
1063
990
|
if (regexGenerator === "randexp") return `${toRegExpString(value, "RandExp")}.gen()`;
|
|
1064
|
-
return `faker.helpers.fromRegExp(${toRegExpString(value, null)})`;
|
|
991
|
+
return `faker.helpers.fromRegExp(${toRegExpString(toFakerPattern(value), null)})`;
|
|
1065
992
|
}
|
|
1066
993
|
function parseEnumValue(value) {
|
|
1067
|
-
if (typeof value === "string") return
|
|
994
|
+
if (typeof value === "string") return _kubb_kit.text.quote(value);
|
|
1068
995
|
return value;
|
|
1069
996
|
}
|
|
1070
997
|
/**
|
|
@@ -1075,11 +1002,11 @@ function parseEnumValue(value) {
|
|
|
1075
1002
|
* (a `ref` to the enum shared by every branch, say) identifies no branch and narrows nothing.
|
|
1076
1003
|
*/
|
|
1077
1004
|
function getDiscriminator(member, discriminatorPropertyName) {
|
|
1078
|
-
for (const property of _kubb_kit.ast.
|
|
1005
|
+
for (const property of _kubb_kit.ast.schema.findProperties({
|
|
1079
1006
|
node: member,
|
|
1080
1007
|
propertyName: discriminatorPropertyName
|
|
1081
1008
|
})) {
|
|
1082
|
-
const values = _kubb_kit.ast.
|
|
1009
|
+
const values = _kubb_kit.ast.schema.getLiterals(property.schema);
|
|
1083
1010
|
if (values.length === 1) return {
|
|
1084
1011
|
value: values[0],
|
|
1085
1012
|
required: property.required
|
|
@@ -1096,11 +1023,14 @@ function indexedTypeName(typeName, propertyName, nestedInUnion) {
|
|
|
1096
1023
|
const key = JSON.stringify(propertyName);
|
|
1097
1024
|
return nestedInUnion ? `(NonNullable<${typeName}> & Record<${key}, unknown>)[${key}]` : `NonNullable<${typeName}>[${key}]`;
|
|
1098
1025
|
}
|
|
1026
|
+
function itemTypeName(typeName, nestedInUnion) {
|
|
1027
|
+
return nestedInUnion ? `Extract<NonNullable<${typeName}>, ReadonlyArray<unknown>>[number]` : `NonNullable<${typeName}>[number]`;
|
|
1028
|
+
}
|
|
1099
1029
|
/**
|
|
1100
1030
|
* Creates a Faker printer that generates mock data generation code from schema nodes.
|
|
1101
1031
|
* Handles circular references gracefully by emitting memoizing getters for cyclic properties.
|
|
1102
1032
|
*/
|
|
1103
|
-
const printerFaker = _kubb_kit.
|
|
1033
|
+
const printerFaker = (0, _kubb_kit.createPrinter)((options) => {
|
|
1104
1034
|
const printNested = (node, overrideOptions = {}) => {
|
|
1105
1035
|
return printerFaker({
|
|
1106
1036
|
...options,
|
|
@@ -1120,18 +1050,33 @@ const printerFaker = _kubb_kit.ast.createPrinter((options) => {
|
|
|
1120
1050
|
string(node) {
|
|
1121
1051
|
if (node.pattern) return matches(node.pattern, this.options.regexGenerator);
|
|
1122
1052
|
if (node.format && integerFormats.has(node.format)) return node.format === "int32" ? `faker.number.int({ max: ${maxInt32} }).toString()` : "faker.number.bigInt().toString()";
|
|
1053
|
+
const formatCall = stringFormatCalls.get(node.format);
|
|
1054
|
+
if (formatCall) return formatCall;
|
|
1055
|
+
const contentSchema = _kubb_kit.ast.schema.getEmbeddedJson(node);
|
|
1056
|
+
if (contentSchema) return `JSON.stringify(${printNested(contentSchema, {
|
|
1057
|
+
typeName: void 0,
|
|
1058
|
+
nestedInObject: true,
|
|
1059
|
+
nestedInUnion: false
|
|
1060
|
+
})})`;
|
|
1061
|
+
const encodingCall = encodingCalls.get(node.content?.encoding?.toLowerCase());
|
|
1062
|
+
if (encodingCall) return encodingCall;
|
|
1123
1063
|
const { min, max } = node;
|
|
1124
|
-
if (
|
|
1125
|
-
if (
|
|
1064
|
+
if (max !== void 0) return `faker.string.alpha({ length: { min: ${min ?? Math.min(1, max)}, max: ${Math.min(max, (min ?? 0) + 100)} } })`;
|
|
1065
|
+
if (min !== void 0) return `faker.string.alpha({ length: ${min} })`;
|
|
1126
1066
|
return "faker.string.alpha()";
|
|
1127
1067
|
},
|
|
1128
1068
|
email: () => "faker.internet.email()",
|
|
1129
1069
|
url: () => "faker.internet.url()",
|
|
1130
1070
|
uuid: () => "faker.string.uuid()",
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1071
|
+
ipv4: () => "faker.internet.ipv4()",
|
|
1072
|
+
ipv6: () => "faker.internet.ipv6()",
|
|
1073
|
+
number: (node) => numberCall("float", node),
|
|
1074
|
+
integer: (node) => numberCall("int", node.format && node.format in maxValueByFormat ? {
|
|
1075
|
+
...node,
|
|
1076
|
+
max: Math.min(node.max ?? Infinity, maxValueByFormat[node.format])
|
|
1077
|
+
} : node),
|
|
1078
|
+
bigint: (node) => numberCall("bigInt", node),
|
|
1079
|
+
blob: () => "new Blob([faker.string.alpha()])",
|
|
1135
1080
|
datetime(node) {
|
|
1136
1081
|
const parser = this.options.dateParser ?? "faker";
|
|
1137
1082
|
if (parser === "faker") return "faker.date.anytime().toISOString()";
|
|
@@ -1150,28 +1095,30 @@ const printerFaker = _kubb_kit.ast.createPrinter((options) => {
|
|
|
1150
1095
|
}, this.options.dateParser, this.options.schemaName);
|
|
1151
1096
|
},
|
|
1152
1097
|
ref(node) {
|
|
1153
|
-
const refName = _kubb_kit.ast.
|
|
1098
|
+
const refName = _kubb_kit.ast.ref.getName(node);
|
|
1154
1099
|
if (!refName) throw new _kubb_kit.Diagnostics.Error({
|
|
1155
1100
|
code: _kubb_kit.Diagnostics.code.pluginFailed,
|
|
1156
1101
|
severity: "error",
|
|
1157
1102
|
message: `Ref node "${node.ref ?? node.name ?? "unknown"}"${this.options.schemaName ? ` in schema "${this.options.schemaName}"` : ""} has no name.`,
|
|
1158
1103
|
plugin: "plugin-faker"
|
|
1159
1104
|
});
|
|
1160
|
-
if (
|
|
1105
|
+
if (isCyclicRef(node, this.options)) return this.options.typeName ? `undefined as unknown as ${this.options.typeName}` : "undefined as unknown";
|
|
1161
1106
|
const resolvedName = node.ref ? this.options.resolver.name(refName) : refName;
|
|
1162
|
-
if (!this.options.nestedInObject && canOverrideSchema(_kubb_kit.ast.
|
|
1107
|
+
if (!this.options.nestedInObject && canOverrideSchema(_kubb_kit.ast.ref.getSchema(node))) return `${resolvedName}(data)`;
|
|
1163
1108
|
return `${resolvedName}()`;
|
|
1164
1109
|
},
|
|
1165
1110
|
enum(node) {
|
|
1166
1111
|
const { typeName } = this.options;
|
|
1167
|
-
const values = _kubb_kit.ast.
|
|
1112
|
+
const values = _kubb_kit.ast.schema.getLiterals(node);
|
|
1168
1113
|
if (values.length === 1 && values[0] !== null && typeof values[0] === "object") return JSON.stringify(values[0]);
|
|
1169
|
-
return `faker.helpers.arrayElement
|
|
1114
|
+
return `faker.helpers.arrayElement([${values.map(parseEnumValue).join(", ")}]${typeName ? ` as Array<${typeName}>` : ""})`;
|
|
1170
1115
|
},
|
|
1171
1116
|
union(node) {
|
|
1172
1117
|
const { discriminatorPropertyName } = node;
|
|
1173
1118
|
const baseTypeName = this.options.typeName;
|
|
1174
|
-
|
|
1119
|
+
const isCyclicMember = (member) => isCyclicRef(member, this.options) || member.type === "intersection" && (member.members ?? []).some((part) => isCyclicRef(part, this.options));
|
|
1120
|
+
const acyclicMembers = (node.members ?? []).filter((member) => !isCyclicMember(member));
|
|
1121
|
+
return `faker.helpers.arrayElement([${((acyclicMembers.length ? acyclicMembers : node.members) ?? []).map((member) => {
|
|
1175
1122
|
const discriminator = discriminatorPropertyName ? getDiscriminator(member, discriminatorPropertyName) : void 0;
|
|
1176
1123
|
if (baseTypeName && discriminator) {
|
|
1177
1124
|
const key = `${JSON.stringify(discriminatorPropertyName)}${discriminator.required ? "" : "?"}`;
|
|
@@ -1187,29 +1134,31 @@ const printerFaker = _kubb_kit.ast.createPrinter((options) => {
|
|
|
1187
1134
|
nestedInObject: true,
|
|
1188
1135
|
nestedInUnion: true
|
|
1189
1136
|
});
|
|
1190
|
-
}).
|
|
1137
|
+
}).filter((item) => Boolean(item)).join(", ")}])`;
|
|
1191
1138
|
},
|
|
1192
1139
|
intersection(node) {
|
|
1193
1140
|
const objectMembers = (node.members ?? []).filter((member) => isObjectSchema(member));
|
|
1194
|
-
const
|
|
1195
|
-
const items =
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1141
|
+
const memberRank = (member) => member.type === "ref" ? 0 : member.type === "union" ? 2 : 1;
|
|
1142
|
+
const items = ((objectMembers.length ? objectMembers.toSorted((a, b) => memberRank(a) - memberRank(b)) : node.members) ?? []).map((member) => printNested(member, {
|
|
1143
|
+
nestedInObject: true,
|
|
1144
|
+
...member.type === "ref" && _kubb_kit.ast.ref.getName(member) !== this.options.schemaName ? { cyclicSchemas: void 0 } : {}
|
|
1145
|
+
})).filter((item) => Boolean(item) && item !== "undefined");
|
|
1199
1146
|
if (items.length === 0) return "{}";
|
|
1200
1147
|
return !objectMembers.length || items.length === 1 ? items.at(-1) : `{...${items.join(", ...")}}`;
|
|
1201
1148
|
},
|
|
1202
1149
|
array(node) {
|
|
1203
|
-
|
|
1204
|
-
|
|
1150
|
+
if (node.items?.length === 1 && isCyclicRef(node.items[0], this.options)) return this.options.typeName ? `[] as ${this.options.typeName}` : "[]";
|
|
1151
|
+
const items = (node.items ?? []).map((member) => printNested(member, {
|
|
1152
|
+
typeName: this.options.typeName ? itemTypeName(this.options.typeName, this.options.nestedInUnion) : void 0,
|
|
1205
1153
|
nestedInObject: true
|
|
1206
|
-
})).
|
|
1154
|
+
})).filter((item) => Boolean(item));
|
|
1207
1155
|
if (items.length > 1) return `faker.helpers.arrayElements([${items.join(", ")}])`;
|
|
1208
1156
|
const { min, max } = node;
|
|
1209
1157
|
const item = items[0];
|
|
1210
|
-
|
|
1158
|
+
const countRange = max === void 0 ? void 0 : `{ min: ${min ?? 0}, max: ${Math.min(max, (min ?? 0) + 100)} }`;
|
|
1159
|
+
if (node.unique) return `faker.helpers.uniqueArray(() => (${item}), ${countRange ? `faker.number.int(${countRange})` : min ?? 3})`;
|
|
1160
|
+
if (countRange) return `faker.helpers.multiple(() => (${item}), { count: ${countRange}})`;
|
|
1211
1161
|
if (min !== void 0) return `faker.helpers.multiple(() => (${item}), { count: ${min} })`;
|
|
1212
|
-
if (max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: 0, max: ${max} }})`;
|
|
1213
1162
|
return `faker.helpers.multiple(() => (${item}))`;
|
|
1214
1163
|
},
|
|
1215
1164
|
tuple(node) {
|
|
@@ -1220,18 +1169,30 @@ const printerFaker = _kubb_kit.ast.createPrinter((options) => {
|
|
|
1220
1169
|
},
|
|
1221
1170
|
object(node) {
|
|
1222
1171
|
const cyclicSchemas = this.options.cyclicSchemas;
|
|
1223
|
-
const keySchema = node.propertyNames &&
|
|
1172
|
+
const keySchema = node.propertyNames && _kubb_kit.ast.ref.mergeSchema(node.propertyNames);
|
|
1224
1173
|
const valueSchema = node.additionalProperties;
|
|
1225
|
-
const recordProperties = keySchema?.type === "enum" && typeof valueSchema === "object" ? _kubb_kit.ast.
|
|
1174
|
+
const recordProperties = keySchema?.type === "enum" && typeof valueSchema === "object" ? _kubb_kit.ast.schema.getLiterals(keySchema).filter((key) => typeof key === "string" && !node.properties.some((property) => property.name === key)).map((name) => _kubb_kit.ast.factory.createProperty({
|
|
1226
1175
|
name,
|
|
1227
1176
|
schema: valueSchema
|
|
1228
1177
|
})) : [];
|
|
1229
|
-
|
|
1178
|
+
const properties = [...node.properties, ...recordProperties];
|
|
1179
|
+
const keptProperties = node.max === void 0 ? properties : properties.toSorted((a, b) => Number(b.required) - Number(a.required)).slice(0, node.max);
|
|
1180
|
+
const declaredNames = new Set(properties.map((property) => property.name));
|
|
1181
|
+
const extras = [];
|
|
1182
|
+
for (let index = 1; typeof valueSchema === "object" && keptProperties.length + extras.length < (node.min ?? 0); index++) {
|
|
1183
|
+
const name = `additionalProperty${index}`;
|
|
1184
|
+
if (!declaredNames.has(name)) extras.push(_kubb_kit.ast.factory.createProperty({
|
|
1185
|
+
name,
|
|
1186
|
+
schema: valueSchema
|
|
1187
|
+
}));
|
|
1188
|
+
}
|
|
1189
|
+
return buildObject([...keptProperties, ...extras].map((property) => {
|
|
1230
1190
|
const value = printNested(property.schema, {
|
|
1231
1191
|
typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : void 0,
|
|
1232
|
-
nestedInObject: true
|
|
1192
|
+
nestedInObject: true,
|
|
1193
|
+
...property.required && property.schema.type === "ref" ? { cyclicSchemas: void 0 } : {}
|
|
1233
1194
|
}) ?? "undefined";
|
|
1234
|
-
if (cyclicSchemas &&
|
|
1195
|
+
if (cyclicSchemas && _kubb_kit.ast.graph.containsCircular(property.schema, {
|
|
1235
1196
|
circularSchemas: cyclicSchemas,
|
|
1236
1197
|
excludeName: this.options.schemaName
|
|
1237
1198
|
})) 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 }`;
|
|
@@ -1259,7 +1220,7 @@ const fakerGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1259
1220
|
if (!node.name) return;
|
|
1260
1221
|
const tsResolver = ctx.driver.getResolver(_kubb_plugin_ts.pluginTsName);
|
|
1261
1222
|
const schemaName = node.name;
|
|
1262
|
-
const isEnumSchema = !!_kubb_kit.ast.
|
|
1223
|
+
const isEnumSchema = !!_kubb_kit.ast.schema.narrow(node, _kubb_kit.ast.schema.types.enum);
|
|
1263
1224
|
const schemaTypeName = (0, _kubb_plugin_ts.enumTypeName)({
|
|
1264
1225
|
resolver: tsResolver,
|
|
1265
1226
|
name: schemaName,
|
|
@@ -1308,7 +1269,8 @@ const fakerGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1308
1269
|
node,
|
|
1309
1270
|
root,
|
|
1310
1271
|
output,
|
|
1311
|
-
group: group ?? void 0
|
|
1272
|
+
group: group ?? void 0,
|
|
1273
|
+
checks: true
|
|
1312
1274
|
}), fakerText);
|
|
1313
1275
|
return /* @__PURE__ */ (0, _kubb_renderer_jsx_jsx_runtime.jsxs)(_kubb_renderer_jsx.File, {
|
|
1314
1276
|
baseName: meta.file.baseName,
|
|
@@ -1382,7 +1344,7 @@ const fakerGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1382
1344
|
const { output, group, dateParser, regexGenerator, seed, locale, printer, typeMode } = ctx.options;
|
|
1383
1345
|
const pluginTs = ctx.requirePlugin(_kubb_plugin_ts.pluginTsName);
|
|
1384
1346
|
const tsResolver = ctx.driver.getResolver(_kubb_plugin_ts.pluginTsName);
|
|
1385
|
-
const { path: pathParams, query: queryParams, header: headerParams, cookie: cookieParams } =
|
|
1347
|
+
const { path: pathParams, query: queryParams, header: headerParams, cookie: cookieParams } = _kubb_kit.ast.http.groupParameters(node);
|
|
1386
1348
|
const paramGroups = [
|
|
1387
1349
|
{
|
|
1388
1350
|
params: pathParams,
|
|
@@ -1451,7 +1413,7 @@ const fakerGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1451
1413
|
description: node.requestBody?.description ?? schema.description
|
|
1452
1414
|
}));
|
|
1453
1415
|
const responseName = resolver.response.response(node);
|
|
1454
|
-
const hasResponseNameCollision = new Set(
|
|
1416
|
+
const hasResponseNameCollision = new Set(_kubb_kit.ast.http.responses.getImportedNames(node.responses).map((name) => resolver.name(name))).has(responseName);
|
|
1455
1417
|
const localHelperNames = /* @__PURE__ */ new Set([
|
|
1456
1418
|
...paramGroups.map((group) => group.name),
|
|
1457
1419
|
...responseUnits.map((unit) => unit.name),
|
|
@@ -1482,12 +1444,13 @@ const fakerGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1482
1444
|
node: schema,
|
|
1483
1445
|
root,
|
|
1484
1446
|
output,
|
|
1485
|
-
group: group ?? void 0
|
|
1447
|
+
group: group ?? void 0,
|
|
1448
|
+
checks: true
|
|
1486
1449
|
}).filter((entry) => entry.path !== meta.file.path);
|
|
1487
1450
|
}
|
|
1488
1451
|
function renderEntry({ schema, name, typeName, description, keysToOmit, skipImportNames = [] }) {
|
|
1489
1452
|
if (!schema) return null;
|
|
1490
|
-
if (schema.type === _kubb_kit.ast.
|
|
1453
|
+
if (schema.type === _kubb_kit.ast.schema.types.object && keysToOmit?.length) {
|
|
1491
1454
|
schema = {
|
|
1492
1455
|
...schema,
|
|
1493
1456
|
properties: schema.properties.filter((property) => !keysToOmit?.includes(property.name))
|
|
@@ -1602,11 +1565,11 @@ const fakerGenerator = (0, _kubb_kit.defineGenerator)({
|
|
|
1602
1565
|
});
|
|
1603
1566
|
// kubb-extension.json
|
|
1604
1567
|
var compatibility = {
|
|
1605
|
-
"kubb": ">=5.
|
|
1568
|
+
"kubb": ">=5.18.4",
|
|
1606
1569
|
"node": ">=22.22"
|
|
1607
1570
|
};
|
|
1608
1571
|
// package.json
|
|
1609
|
-
var version = "5.4.0
|
|
1572
|
+
var version = "5.4.0";
|
|
1610
1573
|
// src/resolvers/resolverFaker.ts
|
|
1611
1574
|
/**
|
|
1612
1575
|
* Default resolver used by `@kubb/plugin-faker`. Decides the names and file
|
|
@@ -1623,9 +1586,9 @@ var version = "5.4.0-canary.20261111T115959";
|
|
|
1623
1586
|
const resolverFaker = (0, _kubb_kit.createResolver)({
|
|
1624
1587
|
pluginName: "plugin-faker",
|
|
1625
1588
|
name(name) {
|
|
1626
|
-
return this.memo(`name:${name}`, () => ensureValidVarName(
|
|
1589
|
+
return this.memo(`name:${name}`, () => ensureValidVarName(_kubb_kit.casing.camel(name, { prefix: "create" })));
|
|
1627
1590
|
},
|
|
1628
|
-
file: createCasedFile((part) =>
|
|
1591
|
+
file: createCasedFile((part) => _kubb_kit.casing.camel(part, { prefix: "create" })),
|
|
1629
1592
|
param: createOperationParamResolver(),
|
|
1630
1593
|
response: createOperationResponseResolver()
|
|
1631
1594
|
});
|
|
@@ -1683,7 +1646,7 @@ const pluginFaker = (0, _kubb_kit.defineExtension)({
|
|
|
1683
1646
|
include,
|
|
1684
1647
|
override,
|
|
1685
1648
|
typeMode,
|
|
1686
|
-
group:
|
|
1649
|
+
group: group ?? null,
|
|
1687
1650
|
dateParser,
|
|
1688
1651
|
regexGenerator,
|
|
1689
1652
|
printer
|