UNPKG

@kubb/plugin-faker

Version:

Faker.js data generator plugin for Kubb, creating realistic mock data from OpenAPI specifications for development and testing.

304 lines (301 loc) 11.9 kB
import transformers from "@kubb/core/transformers"; import { SchemaGenerator, isKeyword, schemaKeywords } from "@kubb/plugin-oas"; import { File, Function, FunctionParams } from "@kubb/react-fabric"; import { jsx, jsxs } from "@kubb/react-fabric/jsx-runtime"; //#region src/parser.ts const fakerKeywordMapper = { any: () => "undefined", unknown: () => "undefined", void: () => "undefined", number: (min, max) => { if (max !== void 0 && min !== void 0) return `faker.number.float({ min: ${min}, max: ${max} })`; if (max !== void 0) return `faker.number.float({ max: ${max} })`; if (min !== void 0) return `faker.number.float({ min: ${min} })`; return "faker.number.float()"; }, integer: (min, max) => { if (max !== void 0 && min !== void 0) return `faker.number.int({ min: ${min}, max: ${max} })`; if (max !== void 0) return `faker.number.int({ max: ${max} })`; if (min !== void 0) return `faker.number.int({ min: ${min} })`; return "faker.number.int()"; }, string: (min, max) => { if (max !== void 0 && min !== void 0) return `faker.string.alpha({ length: { min: ${min}, max: ${max} } })`; if (max !== void 0) return `faker.string.alpha({ length: ${max} })`; if (min !== void 0) return `faker.string.alpha({ length: ${min} })`; return "faker.string.alpha()"; }, boolean: () => "faker.datatype.boolean()", undefined: () => "undefined", null: () => "null", array: (items = [], min, max) => { if (items.length > 1) return `faker.helpers.arrayElements([${items.join(", ")}])`; const item = items.at(0); if (min !== void 0 && max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: ${min}, max: ${max} }})`; if (min !== void 0) return `faker.helpers.multiple(() => (${item}), { count: ${min} })`; if (max !== void 0) return `faker.helpers.multiple(() => (${item}), { count: { min: 0, max: ${max} }})`; return `faker.helpers.multiple(() => (${item}))`; }, tuple: (items = []) => `[${items.join(", ")}]`, enum: (items = [], type = "any") => `faker.helpers.arrayElement<${type}>([${items.join(", ")}])`, union: (items = []) => `faker.helpers.arrayElement<any>([${items.join(", ")}])`, datetime: () => "faker.date.anytime().toISOString()", date: (type = "string", parser = "faker") => { if (type === "string") { if (parser !== "faker") return `${parser}(faker.date.anytime()).format("YYYY-MM-DD")`; return "faker.date.anytime().toISOString().substring(0, 10)"; } if (parser !== "faker") throw new Error(`type '${type}' and parser '${parser}' can not work together`); return "faker.date.anytime()"; }, time: (type = "string", parser = "faker") => { if (type === "string") { if (parser !== "faker") return `${parser}(faker.date.anytime()).format("HH:mm:ss")`; return "faker.date.anytime().toISOString().substring(11, 19)"; } if (parser !== "faker") throw new Error(`type '${type}' and parser '${parser}' can not work together`); return "faker.date.anytime()"; }, uuid: () => "faker.string.uuid()", url: () => "faker.internet.url()", and: (items = []) => `Object.assign({}, ${items.join(", ")})`, object: () => "object", ref: () => "ref", matches: (value = "", regexGenerator = "faker") => { if (regexGenerator === "randexp") return `${transformers.toRegExpString(value, "RandExp")}.gen()`; return `faker.helpers.fromRegExp("${value}")`; }, email: () => "faker.internet.email()", firstName: () => "faker.person.firstName()", lastName: () => "faker.person.lastName()", password: () => "faker.internet.password()", phone: () => "faker.phone.number()", blob: () => "faker.image.url() as unknown as Blob", default: void 0, describe: void 0, const: (value) => value ?? "", max: void 0, min: void 0, nullable: void 0, nullish: void 0, optional: void 0, readOnly: void 0, writeOnly: void 0, deprecated: void 0, example: void 0, schema: void 0, catchall: void 0, name: void 0, interface: void 0, exclusiveMaximum: void 0, exclusiveMinimum: void 0 }; /** * @link based on https://github.com/cellular/oazapfts/blob/7ba226ebb15374e8483cc53e7532f1663179a22c/src/codegen/generate.ts#L398 */ function schemaKeywordSorter(_a, b) { if (b.keyword === "null") return -1; return 0; } function joinItems(items) { switch (items.length) { case 0: return "undefined"; case 1: return items[0]; default: return fakerKeywordMapper.union(items); } } function parse({ schema, current, parent, name, siblings }, options) { const value = fakerKeywordMapper[current.keyword]; if (!value) return; if (isKeyword(current, schemaKeywords.union)) { if (Array.isArray(current.args) && !current.args.length) return ""; return fakerKeywordMapper.union(current.args.map((it) => parse({ schema, parent: current, name, current: it, siblings }, { ...options, canOverride: false })).filter(Boolean)); } if (isKeyword(current, schemaKeywords.and)) return fakerKeywordMapper.and(current.args.map((it) => parse({ schema, parent: current, current: it, siblings }, { ...options, canOverride: false })).filter(Boolean)); if (isKeyword(current, schemaKeywords.array)) return fakerKeywordMapper.array(current.args.items.map((it) => parse({ schema, parent: current, current: it, siblings }, { ...options, typeName: `NonNullable<${options.typeName}>[number]`, canOverride: false })).filter(Boolean), current.args.min, current.args.max); if (isKeyword(current, schemaKeywords.enum)) { if (parent ? isKeyword(parent, schemaKeywords.tuple) : false) return fakerKeywordMapper.enum(current.args.items.map((schema$1) => { if (schema$1.format === "number") return schema$1.value; if (schema$1.format === "boolean") return schema$1.value; return transformers.stringify(schema$1.value); })); return fakerKeywordMapper.enum(current.args.items.map((schema$1) => { if (schema$1.format === "number") return schema$1.value; if (schema$1.format === "boolean") return schema$1.value; return transformers.stringify(schema$1.value); }), name ? options.typeName : void 0); } if (isKeyword(current, schemaKeywords.ref)) { if (!current.args?.name) throw new Error(`Name not defined for keyword ${current.keyword}`); if (options.canOverride) return `${current.args.name}(data)`; return `${current.args.name}()`; } if (isKeyword(current, schemaKeywords.object)) return `{${Object.entries(current.args?.properties || {}).filter((item) => { const schema$1 = item[1]; return schema$1 && typeof schema$1.map === "function"; }).map(([name$1, schemas]) => { const mappedName = schemas.find((schema$1) => schema$1.keyword === schemaKeywords.name)?.args || name$1; if (options.mapper?.[mappedName]) return `"${name$1}": ${options.mapper?.[mappedName]}`; return `"${name$1}": ${joinItems(schemas.sort(schemaKeywordSorter).map((it) => parse({ schema, name: name$1, parent: current, current: it, siblings: schemas }, { ...options, typeName: `NonNullable<${options.typeName}>[${JSON.stringify(name$1)}]`, canOverride: false })).filter(Boolean))}`; }).join(",")}}`; if (isKeyword(current, schemaKeywords.tuple)) { if (Array.isArray(current.args.items)) return fakerKeywordMapper.tuple(current.args.items.map((it) => parse({ schema, parent: current, current: it, siblings }, { ...options, canOverride: false })).filter(Boolean)); return parse({ schema, parent: current, current: current.args.items, siblings }, { ...options, canOverride: false }); } if (isKeyword(current, schemaKeywords.const)) { if (current.args.format === "number" && current.args.name !== void 0) return fakerKeywordMapper.const(current.args.name?.toString()); return fakerKeywordMapper.const(transformers.stringify(current.args.value)); } if (isKeyword(current, schemaKeywords.matches) && current.args) return fakerKeywordMapper.matches(current.args, options.regexGenerator); if (isKeyword(current, schemaKeywords.null) || isKeyword(current, schemaKeywords.undefined) || isKeyword(current, schemaKeywords.any)) return value() || ""; if (isKeyword(current, schemaKeywords.string)) { if (siblings) { const minSchema = SchemaGenerator.find(siblings, schemaKeywords.min); const maxSchema = SchemaGenerator.find(siblings, schemaKeywords.max); return fakerKeywordMapper.string(minSchema?.args, maxSchema?.args); } return fakerKeywordMapper.string(); } if (isKeyword(current, schemaKeywords.number)) { if (siblings) { const minSchema = SchemaGenerator.find(siblings, schemaKeywords.min); const maxSchema = SchemaGenerator.find(siblings, schemaKeywords.max); return fakerKeywordMapper.number(minSchema?.args, maxSchema?.args); } return fakerKeywordMapper.number(); } if (isKeyword(current, schemaKeywords.integer)) { if (siblings) { const minSchema = SchemaGenerator.find(siblings, schemaKeywords.min); const maxSchema = SchemaGenerator.find(siblings, schemaKeywords.max); return fakerKeywordMapper.integer(minSchema?.args, maxSchema?.args); } return fakerKeywordMapper.integer(); } if (isKeyword(current, schemaKeywords.datetime)) return fakerKeywordMapper.datetime(); if (isKeyword(current, schemaKeywords.date)) return fakerKeywordMapper.date(current.args.type, options.dateParser); if (isKeyword(current, schemaKeywords.time)) return fakerKeywordMapper.time(current.args.type, options.dateParser); if (current.keyword in fakerKeywordMapper && "args" in current) { const value$1 = fakerKeywordMapper[current.keyword]; return value$1(JSON.stringify(current.args)); } if (current.keyword in fakerKeywordMapper) return value(); } //#endregion //#region src/components/Faker.tsx function Faker({ tree, description, name, typeName, seed, regexGenerator, canOverride, mapper, dateParser }) { const fakerText = joinItems(tree.map((schema, _index, siblings) => parse({ name, schema, parent: void 0, current: schema, siblings }, { typeName, regexGenerator, mapper, canOverride, dateParser })).filter(Boolean)); const isArray = fakerText.startsWith("faker.helpers.arrayElements") || fakerText.startsWith("faker.helpers.multiple"); const isObject = fakerText.startsWith("{"); const isTuple = fakerText.startsWith("faker.helpers.arrayElement"); const isSimpleString = name === "string"; const isSimpleInt = name === "integer"; const isSimpleFloat = name === "float"; let fakerTextWithOverride = fakerText; if (canOverride && isObject) fakerTextWithOverride = `{ ...${fakerText}, ...data || {} }`; if (canOverride && isTuple) fakerTextWithOverride = `data || ${fakerText}`; if (canOverride && isArray) fakerTextWithOverride = `[ ...${fakerText}, ...data || [] ]`; if (canOverride && isSimpleString) fakerTextWithOverride = "data ?? faker.string.alpha()"; if (canOverride && isSimpleInt) fakerTextWithOverride = "data ?? faker.number.int()"; if (canOverride && isSimpleFloat) fakerTextWithOverride = "data ?? faker.number.float()"; let type = `Partial<${typeName}>`; if (isArray) type = typeName; else if (isSimpleString) type = name; else if (isSimpleInt || isSimpleFloat) type = "number"; const params = FunctionParams.factory({ data: { type, optional: true } }); let returnType = canOverride ? typeName : void 0; if (isSimpleString || isSimpleInt || isSimpleFloat) returnType = type; return /* @__PURE__ */ jsx(File.Source, { name, isExportable: true, isIndexable: true, children: /* @__PURE__ */ jsxs(Function, { export: true, name, JSDoc: { comments: [description ? `@description ${transformers.jsStringEscape(description)}` : void 0].filter(Boolean) }, params: canOverride ? params.toConstructor() : void 0, returnType, children: [ seed ? `faker.seed(${JSON.stringify(seed)})` : void 0, /* @__PURE__ */ jsx("br", {}), `return ${fakerTextWithOverride}` ] }) }); } //#endregion export { Faker as t }; //# sourceMappingURL=components-DUQvu8JV.js.map