@kubb/plugin-faker 5.1.6 → 5.1.7
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 +204 -294
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +205 -295
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "./rolldown-runtime-C0LytTxp.js";
|
|
2
2
|
import { posix } from "node:path";
|
|
3
|
-
import { Resolver, addGenerator, ast, containsCircularRef, createResolver, defineExtension, defineGenerator, setMacros, setResolver } from "kubb/kit";
|
|
4
|
-
import { buildParams, createFunctionParameter, createFunctionParameters, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
|
|
3
|
+
import { Diagnostics, Resolver, addGenerator, assertPluginOption, ast, containsCircularRef, createResolver, defineExtension, defineGenerator, setMacros, setResolver } from "kubb/kit";
|
|
5
4
|
import { File, Function, jsxRenderer } from "kubb/jsx";
|
|
6
5
|
import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
|
|
6
|
+
import { buildParams, enumTypeName, pluginTsName } from "@kubb/plugin-ts";
|
|
7
7
|
//#region ../../internals/utils/src/casing.ts
|
|
8
8
|
/**
|
|
9
9
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -305,6 +305,24 @@ function buildObject(entries) {
|
|
|
305
305
|
}
|
|
306
306
|
//#endregion
|
|
307
307
|
//#region ../../internals/utils/src/fs.ts
|
|
308
|
+
function toSlash(p) {
|
|
309
|
+
if (p.startsWith("\\\\?\\")) return p;
|
|
310
|
+
return p.replaceAll("\\", "/");
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Returns the relative path from `rootDir` to `filePath`, always using forward slashes
|
|
314
|
+
* and prefixed with `./` when not already traversing upward.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```ts
|
|
318
|
+
* getRelativePath('/src/components', '/src/components/Button.tsx') // './Button.tsx'
|
|
319
|
+
* getRelativePath('/src/components', '/src/utils/helpers.ts') // '../utils/helpers.ts'
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
function getRelativePath(rootDir, filePath) {
|
|
323
|
+
const relativePath = posix.relative(toSlash(rootDir), toSlash(filePath));
|
|
324
|
+
return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
|
|
325
|
+
}
|
|
308
326
|
/**
|
|
309
327
|
* Builds a nested file path from a dotted name. Splits on dots that precede a letter
|
|
310
328
|
* (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
|
|
@@ -329,51 +347,6 @@ function toFilePath(name, caseLast = camelCase) {
|
|
|
329
347
|
return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
|
|
330
348
|
}
|
|
331
349
|
//#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
|
|
377
350
|
//#region src/utils.ts
|
|
378
351
|
/**
|
|
379
352
|
* Returns the `@faker-js/faker` named export for a locale code.
|
|
@@ -397,54 +370,36 @@ function localeToFakerImport(locale) {
|
|
|
397
370
|
return `faker${parts.join("_")}`;
|
|
398
371
|
}
|
|
399
372
|
/**
|
|
373
|
+
* Schema types a factory cannot override with `data`: they print a constant or have no faker value.
|
|
374
|
+
*/
|
|
375
|
+
const NON_OVERRIDABLE_TYPES = /* @__PURE__ */ new Set([
|
|
376
|
+
"any",
|
|
377
|
+
"unknown",
|
|
378
|
+
"void",
|
|
379
|
+
"null",
|
|
380
|
+
"never",
|
|
381
|
+
"ipv4",
|
|
382
|
+
"ipv6"
|
|
383
|
+
]);
|
|
384
|
+
/**
|
|
385
|
+
* Schema types a single response cannot inline: they reference or compose other schemas.
|
|
386
|
+
*/
|
|
387
|
+
const NON_INLINABLE_RESPONSE_TYPES = /* @__PURE__ */ new Set([
|
|
388
|
+
"object",
|
|
389
|
+
"intersection",
|
|
390
|
+
"ref",
|
|
391
|
+
"never",
|
|
392
|
+
"ipv4",
|
|
393
|
+
"ipv6"
|
|
394
|
+
]);
|
|
395
|
+
/**
|
|
400
396
|
* Determines if a schema node can be overridden during faker generation.
|
|
401
397
|
*/
|
|
402
398
|
function canOverrideSchema(node) {
|
|
403
|
-
return (
|
|
404
|
-
"array",
|
|
405
|
-
"tuple",
|
|
406
|
-
"object",
|
|
407
|
-
"intersection",
|
|
408
|
-
"union",
|
|
409
|
-
"enum",
|
|
410
|
-
"ref",
|
|
411
|
-
"string",
|
|
412
|
-
"email",
|
|
413
|
-
"url",
|
|
414
|
-
"uuid",
|
|
415
|
-
"number",
|
|
416
|
-
"integer",
|
|
417
|
-
"bigint",
|
|
418
|
-
"boolean",
|
|
419
|
-
"date",
|
|
420
|
-
"time",
|
|
421
|
-
"datetime",
|
|
422
|
-
"blob"
|
|
423
|
-
])).has(node.type);
|
|
399
|
+
return !NON_OVERRIDABLE_TYPES.has(node.type);
|
|
424
400
|
}
|
|
425
401
|
function shouldInlineSingleResponseSchema(schema) {
|
|
426
|
-
return (
|
|
427
|
-
"any",
|
|
428
|
-
"unknown",
|
|
429
|
-
"void",
|
|
430
|
-
"null",
|
|
431
|
-
"array",
|
|
432
|
-
"tuple",
|
|
433
|
-
"string",
|
|
434
|
-
"email",
|
|
435
|
-
"url",
|
|
436
|
-
"uuid",
|
|
437
|
-
"number",
|
|
438
|
-
"integer",
|
|
439
|
-
"bigint",
|
|
440
|
-
"boolean",
|
|
441
|
-
"date",
|
|
442
|
-
"time",
|
|
443
|
-
"datetime",
|
|
444
|
-
"blob",
|
|
445
|
-
"enum",
|
|
446
|
-
"union"
|
|
447
|
-
])).has(schema.type);
|
|
402
|
+
return !NON_INLINABLE_RESPONSE_TYPES.has(schema.type);
|
|
448
403
|
}
|
|
449
404
|
/**
|
|
450
405
|
* Builds a response schema as a union of all response statuses.
|
|
@@ -473,7 +428,7 @@ function buildResponseUnionSchema(node, resolver) {
|
|
|
473
428
|
})
|
|
474
429
|
});
|
|
475
430
|
}
|
|
476
|
-
const SCALAR_TYPES
|
|
431
|
+
const SCALAR_TYPES = /* @__PURE__ */ new Set([
|
|
477
432
|
"string",
|
|
478
433
|
"email",
|
|
479
434
|
"url",
|
|
@@ -488,10 +443,6 @@ const SCALAR_TYPES$1 = /* @__PURE__ */ new Set([
|
|
|
488
443
|
"blob",
|
|
489
444
|
"enum"
|
|
490
445
|
]);
|
|
491
|
-
function toRelativeImportPath(from, to) {
|
|
492
|
-
const relativePath = posix.relative(posix.dirname(from), to);
|
|
493
|
-
return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
|
|
494
|
-
}
|
|
495
446
|
/**
|
|
496
447
|
* Resolves a type reference, determining if it needs an import statement or inline type reference.
|
|
497
448
|
* Takes into account whether the type can be overridden and the file paths.
|
|
@@ -499,7 +450,7 @@ function toRelativeImportPath(from, to) {
|
|
|
499
450
|
function resolveTypeReference({ node, canOverride, name, typeName, filePath, typeFilePath }) {
|
|
500
451
|
const { usesTypeName } = resolveFakerTypeUsage(node, typeName, canOverride);
|
|
501
452
|
if (!usesTypeName) return { typeName };
|
|
502
|
-
if (name === typeName) return { typeName: `import('${
|
|
453
|
+
if (name === typeName) return { typeName: `import('${getRelativePath(posix.dirname(filePath), typeFilePath)}').${typeName}` };
|
|
503
454
|
return {
|
|
504
455
|
importPath: typeFilePath,
|
|
505
456
|
typeName
|
|
@@ -523,28 +474,17 @@ function getScalarType(node, typeName) {
|
|
|
523
474
|
case "time": return node.representation === "date" ? "Date" : "string";
|
|
524
475
|
case "datetime": return "string";
|
|
525
476
|
case "blob": return "Blob";
|
|
526
|
-
case "enum": return typeName;
|
|
527
477
|
default: return typeName;
|
|
528
478
|
}
|
|
529
479
|
}
|
|
530
480
|
/**
|
|
531
|
-
* A nullable scalar inlines its primitive instead of naming the generated type, so the
|
|
532
|
-
* nullability the type plugin emitted has to be reapplied here. Non-scalars keep `typeName`,
|
|
533
|
-
* which already carries it.
|
|
534
|
-
*/
|
|
535
|
-
function withNullability(type, node) {
|
|
536
|
-
return node.nullable ? `${type} | null` : type;
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
481
|
* Resolves faker type usage information for a schema.
|
|
540
482
|
* Determines the data type, return type, and whether it uses the type name.
|
|
541
483
|
*/
|
|
542
484
|
function resolveFakerTypeUsage(node, typeName, canOverride) {
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
let returnType = canOverride ? typeName : null;
|
|
547
|
-
if (isScalar) returnType = withNullability(getScalarType(node, typeName), node);
|
|
485
|
+
const scalarType = SCALAR_TYPES.has(node.type) ? `${getScalarType(node, typeName)}${node.nullable ? " | null" : ""}` : void 0;
|
|
486
|
+
const dataType = scalarType ?? `Partial<${typeName}>`;
|
|
487
|
+
const returnType = scalarType ?? (canOverride ? typeName : null);
|
|
548
488
|
return {
|
|
549
489
|
dataType,
|
|
550
490
|
returnType,
|
|
@@ -554,22 +494,6 @@ function resolveFakerTypeUsage(node, typeName, canOverride) {
|
|
|
554
494
|
//#endregion
|
|
555
495
|
//#region src/components/Faker.tsx
|
|
556
496
|
const OBJECT_TYPES = /* @__PURE__ */ new Set(["object", "intersection"]);
|
|
557
|
-
const SCALAR_TYPES = /* @__PURE__ */ new Set([
|
|
558
|
-
"string",
|
|
559
|
-
"email",
|
|
560
|
-
"url",
|
|
561
|
-
"uuid",
|
|
562
|
-
"number",
|
|
563
|
-
"integer",
|
|
564
|
-
"bigint",
|
|
565
|
-
"boolean",
|
|
566
|
-
"date",
|
|
567
|
-
"time",
|
|
568
|
-
"datetime",
|
|
569
|
-
"blob",
|
|
570
|
-
"enum"
|
|
571
|
-
]);
|
|
572
|
-
const declarationPrinter = functionPrinter({ mode: "declaration" });
|
|
573
497
|
function Faker({ node, description, name, typeName, printer, canOverride, typeMode = "inferred" }) {
|
|
574
498
|
const fakerText = printer.print(node) ?? "undefined";
|
|
575
499
|
const isArray = node.type === "array";
|
|
@@ -586,13 +510,7 @@ function Faker({ node, description, name, typeName, printer, canOverride, typeMo
|
|
|
586
510
|
})();
|
|
587
511
|
const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
|
|
588
512
|
if (!useObjectOverride) {
|
|
589
|
-
const
|
|
590
|
-
const params = createFunctionParameters({ params: [createFunctionParameter({
|
|
591
|
-
name: dataParamName,
|
|
592
|
-
type: dataType,
|
|
593
|
-
optional: true
|
|
594
|
-
})] });
|
|
595
|
-
const paramsSignature = declarationPrinter.print(params) ?? "";
|
|
513
|
+
const paramsSignature = `${/\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data"}?: ${dataType}`;
|
|
596
514
|
const returnType = resolvedReturnType;
|
|
597
515
|
const returnExpression = canOverride && !!returnType && (node.type === "ref" || isArray || isTuple || isUnion) ? `${isTuple || isUnion ? `(${fakerTextWithOverride})` : fakerTextWithOverride} as ${returnType}` : fakerTextWithOverride;
|
|
598
516
|
return /* @__PURE__ */ jsx(File.Source, {
|
|
@@ -641,24 +559,6 @@ return {
|
|
|
641
559
|
});
|
|
642
560
|
}
|
|
643
561
|
//#endregion
|
|
644
|
-
//#region ../../internals/shared/src/params.ts
|
|
645
|
-
/**
|
|
646
|
-
* Drops parameters that share the same name, keeping the first.
|
|
647
|
-
*
|
|
648
|
-
* A malformed spec can declare the same parameter name twice within one `in` location. Both would
|
|
649
|
-
* resolve to the same output property, so emitting both would yield an object type with a duplicate
|
|
650
|
-
* member, which TypeScript rejects. This is a defensive guard against that case, not a casing guard:
|
|
651
|
-
* parameter names flow through unchanged, so no two distinct names ever collide here anymore.
|
|
652
|
-
*/
|
|
653
|
-
function dedupeParams(params) {
|
|
654
|
-
const seen = /* @__PURE__ */ new Set();
|
|
655
|
-
return params.filter((param) => {
|
|
656
|
-
if (seen.has(param.name)) return false;
|
|
657
|
-
seen.add(param.name);
|
|
658
|
-
return true;
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
//#endregion
|
|
662
562
|
//#region ../../internals/shared/src/operation.ts
|
|
663
563
|
/**
|
|
664
564
|
* Builds the `ResolverFileParams` every operation generator passes to
|
|
@@ -757,11 +657,19 @@ const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
|
|
|
757
657
|
function getOperationParameters(node) {
|
|
758
658
|
const cached = operationParameterGroupsByNode.get(node);
|
|
759
659
|
if (cached) return cached;
|
|
660
|
+
const group = (location) => {
|
|
661
|
+
const seen = /* @__PURE__ */ new Set();
|
|
662
|
+
return node.parameters.filter((param) => {
|
|
663
|
+
if (param.in !== location || seen.has(param.name)) return false;
|
|
664
|
+
seen.add(param.name);
|
|
665
|
+
return true;
|
|
666
|
+
});
|
|
667
|
+
};
|
|
760
668
|
const groups = {
|
|
761
|
-
path:
|
|
762
|
-
query:
|
|
763
|
-
header:
|
|
764
|
-
cookie:
|
|
669
|
+
path: group("path"),
|
|
670
|
+
query: group("query"),
|
|
671
|
+
header: group("header"),
|
|
672
|
+
cookie: group("cookie")
|
|
765
673
|
};
|
|
766
674
|
operationParameterGroupsByNode.set(node, groups);
|
|
767
675
|
return groups;
|
|
@@ -842,20 +750,6 @@ function createCasedFile(caseLast) {
|
|
|
842
750
|
} };
|
|
843
751
|
}
|
|
844
752
|
//#endregion
|
|
845
|
-
//#region ../../internals/shared/src/refs.ts
|
|
846
|
-
/**
|
|
847
|
-
* Collects the resolved target name of every pointer-carrying ref in a schema tree, in
|
|
848
|
-
* first-occurrence order. Use this for name-only checks (e.g. redeclaration detection) where
|
|
849
|
-
* `resolver.imports` would resolve file paths that are then discarded.
|
|
850
|
-
*/
|
|
851
|
-
function collectRefNames(schema) {
|
|
852
|
-
return ast.collectSync(schema, { schema: (node) => {
|
|
853
|
-
const refNode = ast.narrowSchema(node, "ref");
|
|
854
|
-
if (!refNode?.ref) return null;
|
|
855
|
-
return ast.resolveRefName(refNode);
|
|
856
|
-
} });
|
|
857
|
-
}
|
|
858
|
-
//#endregion
|
|
859
753
|
//#region ../../internals/shared/src/group.ts
|
|
860
754
|
/**
|
|
861
755
|
* Builds the `group` config a Kubb plugin passes to `ctx.setOptions`, applying the
|
|
@@ -909,6 +803,51 @@ function mapSchemaItems(node, transform) {
|
|
|
909
803
|
}));
|
|
910
804
|
}
|
|
911
805
|
//#endregion
|
|
806
|
+
//#region src/utils/imports.ts
|
|
807
|
+
function escapeRegExp(value) {
|
|
808
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
809
|
+
}
|
|
810
|
+
function getImportNames(entry) {
|
|
811
|
+
return (Array.isArray(entry.name) ? entry.name : [entry.name]).map((name) => {
|
|
812
|
+
if (typeof name === "string") return name;
|
|
813
|
+
return name.name ?? name.propertyName;
|
|
814
|
+
}).filter((name) => Boolean(name));
|
|
815
|
+
}
|
|
816
|
+
function filterUsedImports(imports, text, skipImportNames = []) {
|
|
817
|
+
const skip = new Set(skipImportNames);
|
|
818
|
+
return imports.filter((entry) => {
|
|
819
|
+
return getImportNames(entry).some((name) => {
|
|
820
|
+
if (skip.has(name)) return false;
|
|
821
|
+
return new RegExp(`\\b${escapeRegExp(name)}\\b(?=\\s*[<(])`).test(text);
|
|
822
|
+
});
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
function aliasConflictingImports(imports, reservedNames) {
|
|
826
|
+
const reservedNameSet = new Set(reservedNames);
|
|
827
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
828
|
+
return {
|
|
829
|
+
imports: imports.map((entry) => {
|
|
830
|
+
const aliasedNames = (Array.isArray(entry.name) ? entry.name : [entry.name]).map((item) => {
|
|
831
|
+
if (typeof item !== "string" || !reservedNameSet.has(item)) return item;
|
|
832
|
+
const alias = `${item}Schema`;
|
|
833
|
+
aliases.set(item, alias);
|
|
834
|
+
return {
|
|
835
|
+
propertyName: item,
|
|
836
|
+
name: alias
|
|
837
|
+
};
|
|
838
|
+
});
|
|
839
|
+
return aliasedNames.some((item) => typeof item === "object" && item.name) ? {
|
|
840
|
+
...entry,
|
|
841
|
+
name: aliasedNames
|
|
842
|
+
} : entry;
|
|
843
|
+
}),
|
|
844
|
+
aliases
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
function rewriteAliasedImports(text, aliases) {
|
|
848
|
+
return Array.from(aliases).reduce((acc, [name, alias]) => acc.replace(new RegExp(`\\b${escapeRegExp(name)}\\b`, "g"), alias), text);
|
|
849
|
+
}
|
|
850
|
+
//#endregion
|
|
912
851
|
//#region src/printers/printerFaker.ts
|
|
913
852
|
/**
|
|
914
853
|
* Formats that put a whole number inside a `type: 'string'` schema, the way ProtoJSON encodes
|
|
@@ -922,77 +861,32 @@ const integerFormats = /* @__PURE__ */ new Set([
|
|
|
922
861
|
"uint64"
|
|
923
862
|
]);
|
|
924
863
|
const maxInt32 = 2147483647;
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
},
|
|
952
|
-
boolean: () => "faker.datatype.boolean()",
|
|
953
|
-
null: () => "null",
|
|
954
|
-
array: (items = [], min, max) => {
|
|
955
|
-
if (items.length > 1) return `faker.helpers.arrayElements([${items.join(", ")}])`;
|
|
956
|
-
const item = items.at(0);
|
|
957
|
-
if (min !== void 0 && max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: ${min}, max: ${max} }})`;
|
|
958
|
-
if (min !== void 0) return `faker.helpers.multiple(() => (${item}), { count: ${min} })`;
|
|
959
|
-
if (max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: 0, max: ${max} }})`;
|
|
960
|
-
return `faker.helpers.multiple(() => (${item}))`;
|
|
961
|
-
},
|
|
962
|
-
tuple: (items = []) => `[${items.join(", ")}]`,
|
|
963
|
-
enum: (items = [], type) => `faker.helpers.arrayElement${type ? `<${type}>` : ""}([${items.join(", ")}])`,
|
|
964
|
-
union: (items = []) => `faker.helpers.arrayElement([${items.join(", ")}])`,
|
|
965
|
-
datetime: () => "faker.date.anytime().toISOString()",
|
|
966
|
-
date: (representation = "string", parser = "faker") => {
|
|
967
|
-
if (representation === "string") {
|
|
968
|
-
if (parser !== "faker") return `${parser}(faker.date.anytime()).format("YYYY-MM-DD")`;
|
|
969
|
-
return "faker.date.anytime().toISOString().substring(0, 10)";
|
|
970
|
-
}
|
|
971
|
-
if (parser !== "faker") throw new Error(`type '${representation}' and parser '${parser}' can not work together`);
|
|
972
|
-
return "faker.date.anytime()";
|
|
973
|
-
},
|
|
974
|
-
time: (representation = "string", parser = "faker") => {
|
|
975
|
-
if (representation === "string") {
|
|
976
|
-
if (parser !== "faker") return `${parser}(faker.date.anytime()).format("HH:mm:ss")`;
|
|
977
|
-
return "faker.date.anytime().toISOString().substring(11, 19)";
|
|
978
|
-
}
|
|
979
|
-
if (parser !== "faker") throw new Error(`type '${representation}' and parser '${parser}' can not work together`);
|
|
980
|
-
return "faker.date.anytime()";
|
|
981
|
-
},
|
|
982
|
-
uuid: () => "faker.string.uuid()",
|
|
983
|
-
url: () => "faker.internet.url()",
|
|
984
|
-
and: (items = []) => {
|
|
985
|
-
if (items.length === 0) return "{}";
|
|
986
|
-
if (items.length === 1) return items[0] ?? "{}";
|
|
987
|
-
return `{...${items.join(", ...")}}`;
|
|
988
|
-
},
|
|
989
|
-
matches: (value = "", regexGenerator = "faker") => {
|
|
990
|
-
if (regexGenerator === "randexp") return `${toRegExpString(value, "RandExp")}.gen()`;
|
|
991
|
-
return `faker.helpers.fromRegExp(${toRegExpString(value, null)})`;
|
|
992
|
-
},
|
|
993
|
-
email: () => "faker.internet.email()",
|
|
994
|
-
blob: () => "faker.image.url() as unknown as Blob"
|
|
995
|
-
};
|
|
864
|
+
/**
|
|
865
|
+
* `faker.number.float()` or `faker.number.int()`, with `min` and `max` passed only when set.
|
|
866
|
+
*/
|
|
867
|
+
function numberCall(kind, min, max) {
|
|
868
|
+
const args = [min !== void 0 && `min: ${min}`, max !== void 0 && `max: ${max}`].filter(Boolean).join(", ");
|
|
869
|
+
return `faker.number.${kind}(${args ? `{ ${args} }` : ""})`;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* A `date` or `time` value: an ISO substring, a `dateParser` call, or a `Date` when `representation` is `'date'`.
|
|
873
|
+
*/
|
|
874
|
+
function dateTimeCall(representation, { format, substring }, parser = "faker", schemaName) {
|
|
875
|
+
if (representation === "string") return parser !== "faker" ? `${parser}(faker.date.anytime()).format("${format}")` : `faker.date.anytime().toISOString().substring(${substring})`;
|
|
876
|
+
if (parser !== "faker") throw new Diagnostics.Error({
|
|
877
|
+
code: Diagnostics.code.invalidPluginOptions,
|
|
878
|
+
severity: "error",
|
|
879
|
+
message: `Option \`dateParser: '${parser}'\` cannot format the adapter's \`dateType: 'date'\` values${schemaName ? ` in schema "${schemaName}"` : ""}.`,
|
|
880
|
+
help: "Set adapterOas({ dateType: 'string' }) or remove `dateParser`.",
|
|
881
|
+
location: { kind: "config" },
|
|
882
|
+
plugin: "plugin-faker"
|
|
883
|
+
});
|
|
884
|
+
return "faker.date.anytime()";
|
|
885
|
+
}
|
|
886
|
+
function matches(value, regexGenerator = "faker") {
|
|
887
|
+
if (regexGenerator === "randexp") return `${toRegExpString(value, "RandExp")}.gen()`;
|
|
888
|
+
return `faker.helpers.fromRegExp(${toRegExpString(value, null)})`;
|
|
889
|
+
}
|
|
996
890
|
function parseEnumValue(value) {
|
|
997
891
|
if (typeof value === "string") return stringify(value);
|
|
998
892
|
return value;
|
|
@@ -1038,49 +932,60 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
1038
932
|
name: "faker",
|
|
1039
933
|
options,
|
|
1040
934
|
nodes: {
|
|
1041
|
-
any: () =>
|
|
1042
|
-
unknown: () =>
|
|
1043
|
-
void: () =>
|
|
1044
|
-
boolean: () =>
|
|
1045
|
-
null: () =>
|
|
935
|
+
any: () => "undefined",
|
|
936
|
+
unknown: () => "undefined",
|
|
937
|
+
void: () => "undefined",
|
|
938
|
+
boolean: () => "faker.datatype.boolean()",
|
|
939
|
+
null: () => "null",
|
|
1046
940
|
string(node) {
|
|
1047
|
-
if (node.pattern) return
|
|
1048
|
-
if (node.format && integerFormats.has(node.format)) return
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
uuid: () => fakerKeywordMapper.uuid(),
|
|
1054
|
-
number(node) {
|
|
1055
|
-
return fakerKeywordMapper.number(node.min, node.max);
|
|
941
|
+
if (node.pattern) return matches(node.pattern, this.options.regexGenerator);
|
|
942
|
+
if (node.format && integerFormats.has(node.format)) return node.format === "int32" ? `faker.number.int({ max: ${maxInt32} }).toString()` : "faker.number.bigInt().toString()";
|
|
943
|
+
const { min, max } = node;
|
|
944
|
+
if (min !== void 0 && max !== void 0) return `faker.string.alpha({ length: { min: ${min}, max: ${max} } })`;
|
|
945
|
+
if (max !== void 0 || min !== void 0) return `faker.string.alpha({ length: ${max ?? min} })`;
|
|
946
|
+
return "faker.string.alpha()";
|
|
1056
947
|
},
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
948
|
+
email: () => "faker.internet.email()",
|
|
949
|
+
url: () => "faker.internet.url()",
|
|
950
|
+
uuid: () => "faker.string.uuid()",
|
|
951
|
+
number: (node) => numberCall("float", node.min, node.max),
|
|
952
|
+
integer: (node) => numberCall("int", node.min, node.max),
|
|
953
|
+
bigint: () => "faker.number.bigInt()",
|
|
954
|
+
blob: () => "faker.image.url() as unknown as Blob",
|
|
955
|
+
datetime: () => "faker.date.anytime().toISOString()",
|
|
1063
956
|
date(node) {
|
|
1064
|
-
return
|
|
957
|
+
return dateTimeCall(node.representation ?? "string", {
|
|
958
|
+
format: "YYYY-MM-DD",
|
|
959
|
+
substring: "0, 10"
|
|
960
|
+
}, this.options.dateParser, this.options.schemaName);
|
|
1065
961
|
},
|
|
1066
962
|
time(node) {
|
|
1067
|
-
return
|
|
963
|
+
return dateTimeCall(node.representation ?? "string", {
|
|
964
|
+
format: "HH:mm:ss",
|
|
965
|
+
substring: "11, 19"
|
|
966
|
+
}, this.options.dateParser, this.options.schemaName);
|
|
1068
967
|
},
|
|
1069
968
|
ref(node) {
|
|
1070
969
|
const refName = ast.resolveRefName(node);
|
|
1071
|
-
if (!refName) throw new Error(
|
|
970
|
+
if (!refName) throw new Diagnostics.Error({
|
|
971
|
+
code: Diagnostics.code.pluginFailed,
|
|
972
|
+
severity: "error",
|
|
973
|
+
message: `Ref node "${node.ref ?? node.name ?? "unknown"}"${this.options.schemaName ? ` in schema "${this.options.schemaName}"` : ""} has no name.`,
|
|
974
|
+
plugin: "plugin-faker"
|
|
975
|
+
});
|
|
1072
976
|
if (this.options.schemaName && refName === this.options.schemaName) return this.options.typeName ? `undefined as unknown as ${this.options.typeName}` : "undefined as unknown";
|
|
1073
977
|
const resolvedName = node.ref ? this.options.resolver.name(refName) : refName;
|
|
1074
978
|
if (!this.options.nestedInObject) return `${resolvedName}(data)`;
|
|
1075
979
|
return `${resolvedName}()`;
|
|
1076
980
|
},
|
|
1077
981
|
enum(node) {
|
|
1078
|
-
|
|
982
|
+
const { typeName } = this.options;
|
|
983
|
+
return `faker.helpers.arrayElement${typeName ? `<${typeName}>` : ""}([${ast.getSchemaLiteralValues(node).map(parseEnumValue).join(", ")}])`;
|
|
1079
984
|
},
|
|
1080
985
|
union(node) {
|
|
1081
986
|
const { discriminatorPropertyName } = node;
|
|
1082
987
|
const baseTypeName = this.options.typeName;
|
|
1083
|
-
|
|
988
|
+
return `faker.helpers.arrayElement([${mapSchemaMembers(node, (member) => {
|
|
1084
989
|
const value = discriminatorPropertyName ? getDiscriminatorValue(member, discriminatorPropertyName) : void 0;
|
|
1085
990
|
if (baseTypeName && value !== void 0) {
|
|
1086
991
|
const typeName = `Extract<NonNullable<${baseTypeName}>, { ${JSON.stringify(discriminatorPropertyName)}: ${parseEnumValue(value)} }>`;
|
|
@@ -1095,26 +1000,31 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
1095
1000
|
nestedInObject: true,
|
|
1096
1001
|
nestedInUnion: true
|
|
1097
1002
|
});
|
|
1098
|
-
}).map(({ output }) => output).filter((item) => Boolean(item))
|
|
1099
|
-
return fakerKeywordMapper.union(items);
|
|
1003
|
+
}).map(({ output }) => output).filter((item) => Boolean(item)).join(", ")}])`;
|
|
1100
1004
|
},
|
|
1101
1005
|
intersection(node) {
|
|
1102
1006
|
const items = mapSchemaMembers(node, (member) => printNested(member, { nestedInObject: true })).map(({ output }) => output).filter((item) => Boolean(item) && item !== "undefined");
|
|
1103
|
-
|
|
1007
|
+
if (items.length === 0) return "{}";
|
|
1008
|
+
return items.length === 1 ? items[0] : `{...${items.join(", ...")}}`;
|
|
1104
1009
|
},
|
|
1105
1010
|
array(node) {
|
|
1106
1011
|
const items = mapSchemaItems(node, (member) => printNested(member, {
|
|
1107
1012
|
typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[number]` : void 0,
|
|
1108
1013
|
nestedInObject: true
|
|
1109
1014
|
})).map(({ output }) => output).filter((item) => Boolean(item));
|
|
1110
|
-
return
|
|
1015
|
+
if (items.length > 1) return `faker.helpers.arrayElements([${items.join(", ")}])`;
|
|
1016
|
+
const { min, max } = node;
|
|
1017
|
+
const item = items[0];
|
|
1018
|
+
if (min !== void 0 && max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: ${min}, max: ${max} }})`;
|
|
1019
|
+
if (min !== void 0) return `faker.helpers.multiple(() => (${item}), { count: ${min} })`;
|
|
1020
|
+
if (max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: 0, max: ${max} }})`;
|
|
1021
|
+
return `faker.helpers.multiple(() => (${item}))`;
|
|
1111
1022
|
},
|
|
1112
1023
|
tuple(node) {
|
|
1113
|
-
|
|
1024
|
+
return `[${(node.items ?? []).map((member, index) => printNested(member, {
|
|
1114
1025
|
typeName: this.options.typeName ? `NonNullable<${this.options.typeName}>[${index}]` : void 0,
|
|
1115
1026
|
nestedInObject: true
|
|
1116
|
-
})).filter((item) => Boolean(item))
|
|
1117
|
-
return fakerKeywordMapper.tuple(items);
|
|
1027
|
+
})).filter((item) => Boolean(item)).join(", ")}]`;
|
|
1118
1028
|
},
|
|
1119
1029
|
object(node) {
|
|
1120
1030
|
const cyclicSchemas = this.options.cyclicSchemas;
|
|
@@ -1131,10 +1041,7 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
1131
1041
|
}));
|
|
1132
1042
|
}
|
|
1133
1043
|
},
|
|
1134
|
-
overrides: options.nodes
|
|
1135
|
-
print(node) {
|
|
1136
|
-
return this.transform(node) ?? null;
|
|
1137
|
-
}
|
|
1044
|
+
overrides: options.nodes
|
|
1138
1045
|
};
|
|
1139
1046
|
});
|
|
1140
1047
|
//#endregion
|
|
@@ -1156,9 +1063,12 @@ const fakerGenerator = defineGenerator({
|
|
|
1156
1063
|
const tsResolver = ctx.driver.getResolver(pluginTsName);
|
|
1157
1064
|
const schemaName = node.name;
|
|
1158
1065
|
const isEnumSchema = !!ast.narrowSchema(node, ast.schemaTypes.enum);
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
|
|
1066
|
+
const schemaTypeName = enumTypeName({
|
|
1067
|
+
resolver: tsResolver,
|
|
1068
|
+
name: schemaName,
|
|
1069
|
+
enumOptions: pluginTs.options?.enum,
|
|
1070
|
+
isEnum: isEnumSchema
|
|
1071
|
+
});
|
|
1162
1072
|
const meta = {
|
|
1163
1073
|
name: resolver.name(schemaName),
|
|
1164
1074
|
file: resolver.file({
|
|
@@ -1339,7 +1249,7 @@ const fakerGenerator = defineGenerator({
|
|
|
1339
1249
|
description: node.requestBody?.description ?? schema.description
|
|
1340
1250
|
}));
|
|
1341
1251
|
const responseName = resolver.response.response(node);
|
|
1342
|
-
const hasResponseNameCollision = new Set(node.responses.flatMap((response) => (response.content ?? []).flatMap((entry) => entry.schema ?
|
|
1252
|
+
const hasResponseNameCollision = new Set(node.responses.flatMap((response) => (response.content ?? []).flatMap((entry) => entry.schema ? ast.collectImportedRefNames(entry.schema).map((name) => resolver.name(name)) : []))).has(responseName);
|
|
1343
1253
|
const localHelperNames = /* @__PURE__ */ new Set([
|
|
1344
1254
|
...paramGroups.map((group) => group.name),
|
|
1345
1255
|
...responseUnits.map((unit) => unit.name),
|
|
@@ -1468,20 +1378,8 @@ const fakerGenerator = defineGenerator({
|
|
|
1468
1378
|
children: `faker.seed(${JSON.stringify(seed)})`
|
|
1469
1379
|
}) : void 0,
|
|
1470
1380
|
paramGroups.map((group) => renderEntry(group)),
|
|
1471
|
-
responseUnits.map((unit) => renderEntry(
|
|
1472
|
-
|
|
1473
|
-
name: unit.name,
|
|
1474
|
-
typeName: unit.typeName,
|
|
1475
|
-
description: unit.description,
|
|
1476
|
-
skipImportNames: unit.skipImportNames
|
|
1477
|
-
})),
|
|
1478
|
-
dataUnits.map((unit) => renderEntry({
|
|
1479
|
-
schema: unit.schema,
|
|
1480
|
-
name: unit.name,
|
|
1481
|
-
typeName: unit.typeName,
|
|
1482
|
-
description: unit.description,
|
|
1483
|
-
skipImportNames: unit.skipImportNames
|
|
1484
|
-
})),
|
|
1381
|
+
responseUnits.map((unit) => renderEntry(unit)),
|
|
1382
|
+
dataUnits.map((unit) => renderEntry(unit)),
|
|
1485
1383
|
!hasResponseNameCollision && renderEntry({
|
|
1486
1384
|
schema: buildResponseUnionSchema(node, resolver),
|
|
1487
1385
|
name: responseName,
|
|
@@ -1500,7 +1398,7 @@ var compatibility = {
|
|
|
1500
1398
|
};
|
|
1501
1399
|
//#endregion
|
|
1502
1400
|
//#region package.json
|
|
1503
|
-
var version = "5.1.
|
|
1401
|
+
var version = "5.1.7";
|
|
1504
1402
|
//#endregion
|
|
1505
1403
|
//#region src/resolvers/resolverFaker.ts
|
|
1506
1404
|
/**
|
|
@@ -1568,6 +1466,18 @@ const pluginFaker = defineExtension({
|
|
|
1568
1466
|
path: "mocks",
|
|
1569
1467
|
barrel: { type: "named" }
|
|
1570
1468
|
}, seed, locale = "en", group, exclude = [], include, override = [], typeMode = "inferred", dateParser = "faker", regexGenerator = "faker", printer, resolver: userResolver, macros: userMacros } = options;
|
|
1469
|
+
assertPluginOption({
|
|
1470
|
+
plugin: pluginFakerName,
|
|
1471
|
+
option: "typeMode",
|
|
1472
|
+
value: typeMode,
|
|
1473
|
+
allowed: ["inferred", "schema"]
|
|
1474
|
+
});
|
|
1475
|
+
assertPluginOption({
|
|
1476
|
+
plugin: pluginFakerName,
|
|
1477
|
+
option: "regexGenerator",
|
|
1478
|
+
value: regexGenerator,
|
|
1479
|
+
allowed: ["faker", "randexp"]
|
|
1480
|
+
});
|
|
1571
1481
|
setResolver(userResolver ? Resolver.merge(resolverFaker, userResolver) : resolverFaker);
|
|
1572
1482
|
if (userMacros?.length) setMacros(userMacros);
|
|
1573
1483
|
addGenerator(fakerGenerator);
|