@kubb/plugin-faker 5.0.0-beta.99 → 5.0.1
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 +91 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +92 -23
- package/dist/index.js.map +1 -1
- package/package.json +15 -7
package/dist/index.d.ts
CHANGED
|
@@ -229,11 +229,10 @@ type Props = {
|
|
|
229
229
|
typeName: string;
|
|
230
230
|
node: ast.SchemaNode;
|
|
231
231
|
printer: ast.Printer<PrinterFakerFactory>;
|
|
232
|
-
seed?: PluginFaker['options']['seed'];
|
|
233
232
|
description?: string;
|
|
234
233
|
canOverride: boolean;
|
|
235
234
|
};
|
|
236
|
-
declare function Faker({ node, description, name, typeName, printer,
|
|
235
|
+
declare function Faker({ node, description, name, typeName, printer, canOverride }: Props): KubbReactNode;
|
|
237
236
|
//#endregion
|
|
238
237
|
//#region src/generators/fakerGenerator.d.ts
|
|
239
238
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./rolldown-runtime-C0LytTxp.js";
|
|
2
2
|
import { posix } from "node:path";
|
|
3
|
-
import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
|
|
3
|
+
import { Resolver, ast, containsCircularRef, createResolver, defineGenerator, definePlugin } from "kubb/kit";
|
|
4
4
|
import { buildParams, createFunctionParameter, createFunctionParameters, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
|
|
5
5
|
import { File, Function, jsxRenderer } from "kubb/jsx";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
|
|
@@ -561,7 +561,7 @@ const SCALAR_TYPES = /* @__PURE__ */ new Set([
|
|
|
561
561
|
"enum"
|
|
562
562
|
]);
|
|
563
563
|
const declarationPrinter = functionPrinter({ mode: "declaration" });
|
|
564
|
-
function Faker({ node, description, name, typeName, printer,
|
|
564
|
+
function Faker({ node, description, name, typeName, printer, canOverride }) {
|
|
565
565
|
const fakerText = printer.print(node) ?? "undefined";
|
|
566
566
|
const isArray = node.type === "array";
|
|
567
567
|
const isObject = OBJECT_TYPES.has(node.type);
|
|
@@ -576,8 +576,9 @@ function Faker({ node, description, name, typeName, printer, seed, canOverride }
|
|
|
576
576
|
})();
|
|
577
577
|
const { dataType, returnType: resolvedReturnType } = resolveFakerTypeUsage(node, typeName, canOverride);
|
|
578
578
|
if (!useGenericOverride) {
|
|
579
|
+
const dataParamName = /\bdata\b/.test(fakerTextWithOverride) ? "data" : "_data";
|
|
579
580
|
const params = createFunctionParameters({ params: [createFunctionParameter({
|
|
580
|
-
name:
|
|
581
|
+
name: dataParamName,
|
|
581
582
|
type: dataType,
|
|
582
583
|
optional: true
|
|
583
584
|
})] });
|
|
@@ -588,24 +589,23 @@ function Faker({ node, description, name, typeName, printer, seed, canOverride }
|
|
|
588
589
|
name,
|
|
589
590
|
isExportable: true,
|
|
590
591
|
isIndexable: true,
|
|
591
|
-
children: /* @__PURE__ */
|
|
592
|
+
children: /* @__PURE__ */ jsx(Function, {
|
|
592
593
|
export: true,
|
|
593
594
|
name,
|
|
594
595
|
JSDoc: { comments: description ? [`@description ${jsStringEscape(description)}`] : [] },
|
|
595
596
|
params: canOverride ? paramsSignature : void 0,
|
|
596
597
|
returnType: returnType ?? void 0,
|
|
597
|
-
children:
|
|
598
|
+
children: `return ${returnExpression}`
|
|
598
599
|
})
|
|
599
600
|
});
|
|
600
601
|
}
|
|
601
602
|
const functionSignature = `${description ? `/**\n * @description ${jsStringEscape(description)}\n */\n ` : ""}export function ${name}<TData extends Partial<${typeName}> = object>(data?: TData)`;
|
|
602
|
-
const seedCode = seed ? `faker.seed(${JSON.stringify(seed)})\n ` : "";
|
|
603
603
|
const { cyclicSchemas, schemaName } = printer.options;
|
|
604
|
-
const functionBody = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) =>
|
|
604
|
+
const functionBody = node.type === "object" && !!cyclicSchemas && (node.properties ?? []).some((p) => containsCircularRef(p.schema, {
|
|
605
605
|
circularSchemas: cyclicSchemas,
|
|
606
606
|
excludeName: schemaName
|
|
607
607
|
})) ? `{
|
|
608
|
-
|
|
608
|
+
const defaultFakeData = ${fakerText}
|
|
609
609
|
if (data) {
|
|
610
610
|
for (const [key, value] of Object.entries(data)) {
|
|
611
611
|
Object.defineProperty(defaultFakeData, key, { value, configurable: true, writable: true, enumerable: true })
|
|
@@ -613,7 +613,7 @@ function Faker({ node, description, name, typeName, printer, seed, canOverride }
|
|
|
613
613
|
}
|
|
614
614
|
return defaultFakeData as Omit<typeof defaultFakeData, keyof TData> & TData
|
|
615
615
|
}` : `{
|
|
616
|
-
|
|
616
|
+
const defaultFakeData = ${fakerText}
|
|
617
617
|
return {
|
|
618
618
|
...defaultFakeData,
|
|
619
619
|
...(data || {}),
|
|
@@ -647,6 +647,45 @@ function dedupeParams(params) {
|
|
|
647
647
|
//#endregion
|
|
648
648
|
//#region ../../internals/shared/src/operation.ts
|
|
649
649
|
/**
|
|
650
|
+
* Builds the `ResolverFileParams` every operation generator passes to
|
|
651
|
+
* `resolver.file`: a file named `name`, tagged by the operation's first
|
|
652
|
+
* tag (or `'default'`), at the operation's path. Centralizes the entry object
|
|
653
|
+
* that was repeated at dozens of call sites across the client and query plugins.
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```ts
|
|
657
|
+
* resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
function operationFileEntry(node, name, extname = ".ts") {
|
|
661
|
+
return {
|
|
662
|
+
name,
|
|
663
|
+
extname,
|
|
664
|
+
tag: node.tags[0] ?? "default",
|
|
665
|
+
path: node.path
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Resolves a dependency plugin's generated file for `node.operationId`, cached in `cache` (the
|
|
670
|
+
* current node's `ctx.cache`) under the resolver's own plugin name. Several dependents reading the
|
|
671
|
+
* same dependency for the same operation in one pass (a query plugin's several hook generators, the
|
|
672
|
+
* MCP handler, ...) share one computed name and path instead of each calling `resolver.file` again.
|
|
673
|
+
*
|
|
674
|
+
* @example Cache `plugin-ts`'s file for the current operation
|
|
675
|
+
* ```ts
|
|
676
|
+
* const fileTs = resolveDependencyOperationFile({ cache: ctx.cache, node, resolver: tsResolver, root, output })
|
|
677
|
+
* ```
|
|
678
|
+
*/
|
|
679
|
+
function resolveDependencyOperationFile(options) {
|
|
680
|
+
const { cache, node, resolver, root, output, group } = options;
|
|
681
|
+
return cache.ensureItem(`${resolver.pluginName}:operationFile`, () => resolver.file({
|
|
682
|
+
...operationFileEntry(node, node.operationId),
|
|
683
|
+
root,
|
|
684
|
+
output,
|
|
685
|
+
group: group ?? void 0
|
|
686
|
+
}));
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
650
689
|
* Maps a content type to the PascalCase suffix used to name per-content-type variants
|
|
651
690
|
* (e.g. `application/json` → `Json`, `application/xml` → `Xml`, `multipart/form-data` → `FormData`).
|
|
652
691
|
*/
|
|
@@ -694,16 +733,24 @@ function resolveContentTypeVariants(entries, baseName) {
|
|
|
694
733
|
};
|
|
695
734
|
});
|
|
696
735
|
}
|
|
736
|
+
const operationParameterGroupsByNode = /* @__PURE__ */ new WeakMap();
|
|
737
|
+
/**
|
|
738
|
+
* Groups an operation's parameters by location (`path`/`query`/`header`/`cookie`), deduping each
|
|
739
|
+
* group by name. Every plugin generator visiting the same `OperationNode` shares one AST instance
|
|
740
|
+
* (see `KubbDriver`), so the result is cached per node to avoid re-filtering and re-deduping the
|
|
741
|
+
* same parameters once per plugin.
|
|
742
|
+
*/
|
|
697
743
|
function getOperationParameters(node) {
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
})),
|
|
744
|
+
const cached = operationParameterGroupsByNode.get(node);
|
|
745
|
+
if (cached) return cached;
|
|
746
|
+
const groups = {
|
|
747
|
+
path: dedupeParams(node.parameters.filter((param) => param.in === "path")),
|
|
703
748
|
query: dedupeParams(node.parameters.filter((param) => param.in === "query")),
|
|
704
749
|
header: dedupeParams(node.parameters.filter((param) => param.in === "header")),
|
|
705
750
|
cookie: dedupeParams(node.parameters.filter((param) => param.in === "cookie"))
|
|
706
751
|
};
|
|
752
|
+
operationParameterGroupsByNode.set(node, groups);
|
|
753
|
+
return groups;
|
|
707
754
|
}
|
|
708
755
|
//#endregion
|
|
709
756
|
//#region ../../internals/shared/src/resolver.ts
|
|
@@ -835,6 +882,18 @@ function mapSchemaItems(node, transform) {
|
|
|
835
882
|
}
|
|
836
883
|
//#endregion
|
|
837
884
|
//#region src/printers/printerFaker.ts
|
|
885
|
+
/**
|
|
886
|
+
* Formats that put a whole number inside a `type: 'string'` schema, the way ProtoJSON encodes
|
|
887
|
+
* 64-bit integers, so the mock has to be digits rather than letters.
|
|
888
|
+
*
|
|
889
|
+
* @see https://protobuf.dev/programming-guides/json/#int64-strings
|
|
890
|
+
*/
|
|
891
|
+
const integerFormats = /* @__PURE__ */ new Set([
|
|
892
|
+
"int32",
|
|
893
|
+
"int64",
|
|
894
|
+
"uint64"
|
|
895
|
+
]);
|
|
896
|
+
const maxInt32 = 2147483647;
|
|
838
897
|
const fakerKeywordMapper = {
|
|
839
898
|
any: () => "undefined",
|
|
840
899
|
unknown: () => "undefined",
|
|
@@ -852,6 +911,10 @@ const fakerKeywordMapper = {
|
|
|
852
911
|
return "faker.number.int()";
|
|
853
912
|
},
|
|
854
913
|
bigint: () => "faker.number.bigInt()",
|
|
914
|
+
integerString: (format) => {
|
|
915
|
+
if (format === "int32") return `faker.number.int({ max: ${maxInt32} }).toString()`;
|
|
916
|
+
return "faker.number.bigInt().toString()";
|
|
917
|
+
},
|
|
855
918
|
string: (min, max) => {
|
|
856
919
|
if (max !== void 0 && min !== void 0) return `faker.string.alpha({ length: { min: ${min}, max: ${max} } })`;
|
|
857
920
|
if (max !== void 0) return `faker.string.alpha({ length: ${max} })`;
|
|
@@ -951,6 +1014,7 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
951
1014
|
null: () => fakerKeywordMapper.null(),
|
|
952
1015
|
string(node) {
|
|
953
1016
|
if (node.pattern) return fakerKeywordMapper.matches(node.pattern, this.options.regexGenerator);
|
|
1017
|
+
if (node.format && integerFormats.has(node.format)) return fakerKeywordMapper.integerString(node.format);
|
|
954
1018
|
return fakerKeywordMapper.string(node.min, node.max);
|
|
955
1019
|
},
|
|
956
1020
|
email: () => fakerKeywordMapper.email(),
|
|
@@ -1027,7 +1091,7 @@ const printerFaker = ast.createPrinter((options) => {
|
|
|
1027
1091
|
typeName: this.options.typeName ? indexedTypeName(this.options.typeName, property.name, this.options.nestedInUnion) : void 0,
|
|
1028
1092
|
nestedInObject: true
|
|
1029
1093
|
}) ?? "undefined";
|
|
1030
|
-
if (cyclicSchemas &&
|
|
1094
|
+
if (cyclicSchemas && containsCircularRef(property.schema, {
|
|
1031
1095
|
circularSchemas: cyclicSchemas,
|
|
1032
1096
|
excludeName: this.options.schemaName
|
|
1033
1097
|
})) 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 }`;
|
|
@@ -1158,13 +1222,16 @@ const fakerGenerator = defineGenerator({
|
|
|
1158
1222
|
imp.path,
|
|
1159
1223
|
imp.name
|
|
1160
1224
|
].join("-"))),
|
|
1225
|
+
seed ? /* @__PURE__ */ jsx(File.Source, {
|
|
1226
|
+
name: "faker-seed",
|
|
1227
|
+
children: `faker.seed(${JSON.stringify(seed)})`
|
|
1228
|
+
}) : void 0,
|
|
1161
1229
|
/* @__PURE__ */ jsx(Faker, {
|
|
1162
1230
|
name: meta.name,
|
|
1163
1231
|
typeName: typeReference.typeName,
|
|
1164
1232
|
description: node.description,
|
|
1165
1233
|
node,
|
|
1166
1234
|
printer: printerInstance,
|
|
1167
|
-
seed,
|
|
1168
1235
|
canOverride
|
|
1169
1236
|
})
|
|
1170
1237
|
]
|
|
@@ -1256,14 +1323,13 @@ const fakerGenerator = defineGenerator({
|
|
|
1256
1323
|
output,
|
|
1257
1324
|
group: group ?? void 0
|
|
1258
1325
|
}),
|
|
1259
|
-
typeFile:
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
path: node.path,
|
|
1326
|
+
typeFile: resolveDependencyOperationFile({
|
|
1327
|
+
cache: ctx.cache,
|
|
1328
|
+
node,
|
|
1329
|
+
resolver: tsResolver,
|
|
1264
1330
|
root,
|
|
1265
1331
|
output: pluginTs.options?.output ?? output,
|
|
1266
|
-
group: pluginTs.options?.group
|
|
1332
|
+
group: pluginTs.options?.group
|
|
1267
1333
|
})
|
|
1268
1334
|
};
|
|
1269
1335
|
function resolveMockImports(schema) {
|
|
@@ -1322,7 +1388,6 @@ const fakerGenerator = defineGenerator({
|
|
|
1322
1388
|
...printerInstance,
|
|
1323
1389
|
print: () => rewrittenFakerText
|
|
1324
1390
|
},
|
|
1325
|
-
seed,
|
|
1326
1391
|
canOverride
|
|
1327
1392
|
})
|
|
1328
1393
|
] });
|
|
@@ -1363,6 +1428,10 @@ const fakerGenerator = defineGenerator({
|
|
|
1363
1428
|
path: dateParser,
|
|
1364
1429
|
name: dateParser
|
|
1365
1430
|
}),
|
|
1431
|
+
seed ? /* @__PURE__ */ jsx(File.Source, {
|
|
1432
|
+
name: "faker-seed",
|
|
1433
|
+
children: `faker.seed(${JSON.stringify(seed)})`
|
|
1434
|
+
}) : void 0,
|
|
1366
1435
|
paramGroups.map((group) => renderEntry(group)),
|
|
1367
1436
|
responseUnits.map((unit) => renderEntry({
|
|
1368
1437
|
schema: unit.schema,
|