diff --git a/README.md b/README.md index 6bb86a89..5fda147e 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,11 @@ Prisma generator for model factories. - [Getting started](#getting-started) - [Usage of factories](#usage-of-factories) - [Field default values](#field-default-values) + - [Use sequence for scalar fields](#use-sequence-for-scalar-fields) - [Required relation](#required-relation) - [Connection helper](#connection-helper) - [Build input data only](#build-input-data-only) + - [has-many / has-one relation](#has-many--has-one-relation) - [Generator configuration](#generator-configuration) - [Tips](#tips) - [Works with jest-prisma](#works-with-jest-prisma) @@ -264,6 +266,32 @@ await PostFactory.create(); console.log(await prisma.user.count()); // -> 1 ``` +### has-many / has-one relation + +Sometimes, you may want a user data whose has post record. You can use `PostFactory.buildCreateInput` too. + +```ts +await UserFactory.create({ + posts: { + create: [await PostFactory.buildCreateInput()], + }, +}); + +console.log(await prisma.post.count()); // -> 1 +``` + +Note: In the above example, `PostFactory.buildCreateInput()` resolves JSON data such as: + +```ts +{ + id: "...", + title: "...", + author: { ... } // Derived from PostFactory defaultData +} +``` + +The `author` field is not allowed in `prisma.user.create` context. So `UserFactory` automatically filters the `author` field out in `.create` method. + ## Generator configuration The following options are available: diff --git a/examples/example-prj/src/__generated__/fabbrica/index.js b/examples/example-prj/src/__generated__/fabbrica/index.js index f8f42db1..59750bcf 100644 --- a/examples/example-prj/src/__generated__/fabbrica/index.js +++ b/examples/example-prj/src/__generated__/fabbrica/index.js @@ -5,11 +5,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.definePostFactory = exports.defineUserFactory = exports.resetSequence = exports.initialize = void 0; const clientHolder_1 = require("@quramy/prisma-fabbrica/lib/clientHolder"); +const relations_1 = require("@quramy/prisma-fabbrica/lib/relations"); const gen_1 = __importDefault(require("@quramy/prisma-fabbrica/lib/scalar/gen")); const helpers_1 = require("@quramy/prisma-fabbrica/lib/helpers"); var prisma_fabbrica_1 = require("@quramy/prisma-fabbrica"); Object.defineProperty(exports, "initialize", { enumerable: true, get: function () { return prisma_fabbrica_1.initialize; } }); Object.defineProperty(exports, "resetSequence", { enumerable: true, get: function () { return prisma_fabbrica_1.resetSequence; } }); +const modelFieldDefinitions = [{ + name: "User", + fields: [{ + name: "posts", + type: "Post", + relationName: "PostToUser" + }] + }, { + name: "Post", + fields: [{ + name: "author", + type: "User", + relationName: "PostToUser" + }] + }]; function autoGenerateUserScalarsOrEnums({ seq }) { return { id: gen_1.default.String({ modelName: "User", fieldName: "id", isId: true, isUnique: false, seq }), @@ -19,6 +35,7 @@ function autoGenerateUserScalarsOrEnums({ seq }) { function defineUserFactoryInternal({ defaultData: defaultDataResolver }) { const seqKey = {}; const getSeq = () => (0, helpers_1.getSequenceCounter)(seqKey); + const screen = (0, relations_1.createScreener)("User", modelFieldDefinitions); const buildCreateInput = async (inputData = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq }); @@ -32,7 +49,7 @@ function defineUserFactoryInternal({ defaultData: defaultDataResolver }) { id: inputData.id }); const create = async (inputData = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await (0, clientHolder_1.getClient)().user.create({ data }); }; const createForConnect = (inputData = {}) => create(inputData).then(pickForConnect); @@ -60,6 +77,7 @@ function autoGeneratePostScalarsOrEnums({ seq }) { function definePostFactoryInternal({ defaultData: defaultDataResolver }) { const seqKey = {}; const getSeq = () => (0, helpers_1.getSequenceCounter)(seqKey); + const screen = (0, relations_1.createScreener)("Post", modelFieldDefinitions); const buildCreateInput = async (inputData = {}) => { const seq = getSeq(); const requiredScalarData = autoGeneratePostScalarsOrEnums({ seq }); @@ -77,7 +95,7 @@ function definePostFactoryInternal({ defaultData: defaultDataResolver }) { id: inputData.id }); const create = async (inputData = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await (0, clientHolder_1.getClient)().post.create({ data }); }; const createForConnect = (inputData = {}) => create(inputData).then(pickForConnect); diff --git a/examples/example-prj/src/sample.test.ts b/examples/example-prj/src/sample.test.ts index a7737143..a7832b57 100644 --- a/examples/example-prj/src/sample.test.ts +++ b/examples/example-prj/src/sample.test.ts @@ -23,6 +23,16 @@ describe("factories", () => { const user = await prisma.user.findUnique({ where: { id: "user001" } }); expect(user).toEqual({ id: "user001", name: "Quramy" }); }); + + it("creates record with children relation", async () => { + await UserFactory.create({ + posts: { + create: [await PostFactory.buildCreateInput()], + }, + }); + const created = await prisma.user.findFirst({ include: { posts: true } }); + expect(created?.posts.length).toBe(1); + }); }); describe("PostFactory", () => { diff --git a/packages/prisma-fabbrica/src/helpers/createJSONLiteral.ts b/packages/prisma-fabbrica/src/helpers/createJSONLiteral.ts new file mode 100644 index 00000000..00e12814 --- /dev/null +++ b/packages/prisma-fabbrica/src/helpers/createJSONLiteral.ts @@ -0,0 +1,42 @@ +import ts from "typescript"; +import { ast } from "./astShorthand"; + +type Primitive = string | boolean | number; + +type JSONObjLike = { + [key: string]: Primitive | JSONObjLike | JSONObjLike[]; +}; + +type JSONLike = JSONObjLike | JSONObjLike[]; + +function createArrayLitreral(obj: ReadonlyArray): ts.ArrayLiteralExpression { + return ast.arrayLiteralExpression(obj.map(createObjectLiteral)); +} + +function createObjectLiteral(obj: JSONObjLike): ts.ObjectLiteralExpression { + return ast.objectLiteralExpression( + Object.entries(obj).map(([k, v]) => + ast.propertyAssignment( + k, + typeof v === "string" + ? ast.stringLiteral(v) + : typeof v === "number" + ? ast.numericLiteral(v) + : typeof v === "boolean" + ? v + ? ast.true() + : ast.false() + : Array.isArray(v) + ? createArrayLitreral(v) + : typeof v === "object" + ? createObjectLiteral(v) + : (null as never), + ), + ), + true, + ); +} + +export function createJSONLiteral(obj: JSONLike): ts.Expression { + return Array.isArray(obj) ? createArrayLitreral(obj) : createObjectLiteral(obj); +} diff --git a/packages/prisma-fabbrica/src/helpers/index.ts b/packages/prisma-fabbrica/src/helpers/index.ts index 79ffdbfb..a6f4fa91 100644 --- a/packages/prisma-fabbrica/src/helpers/index.ts +++ b/packages/prisma-fabbrica/src/helpers/index.ts @@ -2,3 +2,5 @@ export * from "./valueResolver"; export * from "./stringConverter"; export * from "./astShorthand"; export * from "./sequence"; +export * from "./selectors"; +export * from "./createJSONLiteral"; diff --git a/packages/prisma-fabbrica/src/helpers/selectors.ts b/packages/prisma-fabbrica/src/helpers/selectors.ts new file mode 100644 index 00000000..33e76ab7 --- /dev/null +++ b/packages/prisma-fabbrica/src/helpers/selectors.ts @@ -0,0 +1,3 @@ +export function byName(name: string | { readonly name: string }) { + return (x: T) => x.name === (typeof name === "string" ? name : name.name); +} diff --git a/packages/prisma-fabbrica/src/relations/index.ts b/packages/prisma-fabbrica/src/relations/index.ts new file mode 100644 index 00000000..73498494 --- /dev/null +++ b/packages/prisma-fabbrica/src/relations/index.ts @@ -0,0 +1 @@ +export * from "./screen"; diff --git a/packages/prisma-fabbrica/src/relations/screen.test.ts b/packages/prisma-fabbrica/src/relations/screen.test.ts new file mode 100644 index 00000000..ef18fea2 --- /dev/null +++ b/packages/prisma-fabbrica/src/relations/screen.test.ts @@ -0,0 +1,138 @@ +import { DMMF } from "@prisma/generator-helper"; +import { getDMMF } from "@prisma/internals"; +import { createFieldDefinitions, createScreener } from "./screen"; + +describe(createScreener, () => { + let document: DMMF.Document; + let subject: (data: T) => T; + describe("For User - Post releation", () => { + beforeEach(async () => { + document = await getDMMF({ + datamodel: ` + model User { + id Int @id + posts Post[] + } + model Post { + id Int @id + authorId Int + author User @relation(fields: [authorId], references: [id]) + } + `, + }); + }); + + describe("User screen", () => { + beforeEach(() => { + subject = createScreener("User", createFieldDefinitions(document.datamodel.models)); + }); + it("screens author in posts create relation", () => { + expect( + subject({ + id: "", + posts: { + create: [{ id: "", author: {} }], + }, + }), + ).toEqual({ + id: "", + posts: { + create: [{ id: "" }], + }, + }); + }); + + it("screens author in posts connectOrCreate relation", () => { + expect( + subject({ + id: "", + posts: { + connectOrCreate: [{ where: { id: "" }, create: { id: "", author: {} } }], + }, + }), + ).toEqual({ + id: "", + posts: { + connectOrCreate: [{ where: { id: "" }, create: { id: "" } }], + }, + }); + }); + + it("does nothing for connect", () => { + expect( + subject({ + id: "", + posts: { + connect: [{ id: "", name: "" }], + }, + }), + ).toEqual({ + id: "", + posts: { + connect: [{ id: "", name: "" }], + }, + }); + }); + }); + + describe("Post screen", () => { + beforeEach(() => { + subject = createScreener("Post", createFieldDefinitions(document.datamodel.models)); + }); + + it("screening posts in user create relation", () => { + expect( + subject({ + id: "", + author: { + create: { id: "", posts: [] }, + }, + }), + ).toEqual({ + id: "", + author: { + create: { id: "" }, + }, + }); + }); + + it("screening posts in user connectOrCreate relation", () => { + expect( + subject({ + id: "", + author: { + connectOrCreate: { + where: { id: "" }, + create: { id: "", posts: [] }, + }, + }, + }), + ).toEqual({ + id: "", + author: { + connectOrCreate: { + where: { id: "" }, + create: { id: "" }, + }, + }, + }); + }); + + it("does nothing for connect", () => { + expect( + subject({ + id: "", + author: { + connect: { id: "", name: "" }, + }, + }), + ).toEqual({ + id: "", + author: { + connect: { id: "", name: "" }, + }, + }); + }); + }); + }); +}); diff --git a/packages/prisma-fabbrica/src/relations/screen.ts b/packages/prisma-fabbrica/src/relations/screen.ts new file mode 100644 index 00000000..2073d001 --- /dev/null +++ b/packages/prisma-fabbrica/src/relations/screen.ts @@ -0,0 +1,107 @@ +import { DMMF } from "@prisma/generator-helper"; +import { byName } from "../helpers"; + +export type ModelWithFields = { + name: string; + fields: { + name: string; + type: string; + relationName: string; + }[]; +}; + +function isCreateChild(def: any): def is { create: Record } { + return typeof def.create === "object" && !Array.isArray(def.create); +} + +function isCreateChildrenList(def: any): def is { create: Record[] } { + return typeof def.create === "object" && Array.isArray(def.create); +} + +function isCorCChild(def: any): def is { connectOrCreate: { where: unknown; create: Record } } { + return typeof def.connectOrCreate === "object" && !Array.isArray(def.connectOrCreate); +} + +function isCorCChildrenList( + def: any, +): def is { connectOrCreate: { where: unknown; create: Record }[] } { + return typeof def.connectOrCreate === "object" && Array.isArray(def.connectOrCreate); +} + +export function createFieldDefinitions(models: DMMF.Model[]): ModelWithFields[] { + return models.map(m => ({ + name: m.name, + fields: m.fields + .filter(f => f.kind === "object") + .map(f => ({ + name: f.name, + type: f.type, + relationName: f.relationName ?? "", + })), + })); +} + +function removeProperties(propertyNames: readonly string[], target: Record) { + for (const name of propertyNames) { + delete target[name]; + } + return target; +} + +export function createScreener(modelName: string, fieldDefinitions: readonly ModelWithFields[]) { + const screenInternal = (parentModelName: string, createInput: any): any => { + const result = Object.keys(createInput).reduce((acc, fieldName) => { + const fieldDef = fieldDefinitions.find(byName(parentModelName))?.fields.find(byName(fieldName)); + if (fieldDef) { + const nextModel = fieldDefinitions.find(byName(fieldDef.type))!; + const fieldNamesToBeRemoved = + fieldDefinitions + .find(byName(nextModel.name)) + ?.fields.filter(f => f.relationName === fieldDef.relationName) + .map(f => f.name) ?? []; + const connectionDefinition = createInput[fieldName] as + | undefined + | { + create?: unknown; + connect?: unknown; + connectOrCreate?: unknown; + }; + if (!connectionDefinition) return acc; + const modifiedConnectionDefinition = { ...connectionDefinition }; + if (isCreateChild(connectionDefinition)) { + modifiedConnectionDefinition.create = removeProperties( + fieldNamesToBeRemoved, + screenInternal(nextModel.name, connectionDefinition.create), + ); + } else if (isCreateChildrenList(connectionDefinition)) { + modifiedConnectionDefinition.create = connectionDefinition.create + .map(screenInternal.bind(null, nextModel.name)) + .map(removeProperties.bind(null, fieldNamesToBeRemoved)); + } + if (isCorCChild(connectionDefinition)) { + modifiedConnectionDefinition.connectOrCreate = { + ...connectionDefinition.connectOrCreate, + create: removeProperties( + fieldNamesToBeRemoved, + screenInternal(nextModel.name, connectionDefinition.connectOrCreate.create), + ), + }; + } else if (isCorCChildrenList(connectionDefinition)) { + modifiedConnectionDefinition.connectOrCreate = connectionDefinition.connectOrCreate.map(def => ({ + ...def, + create: removeProperties(fieldNamesToBeRemoved, screenInternal(nextModel.name, def.create)), + })); + } + return { + ...acc, + [fieldName]: modifiedConnectionDefinition, + }; + } else { + return { ...acc, [fieldName]: createInput[fieldName] }; + } + }, {} as any); + return result; + }; + const screen = (createInput: T) => screenInternal(modelName, createInput) as T; + return screen; +} diff --git a/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap b/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap index 45341bf8..f3d266e0 100644 --- a/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap +++ b/packages/prisma-fabbrica/src/templates/__snapshots__/getSourceFile.test.ts.snap @@ -5,12 +5,17 @@ exports[`getSourceFile generates TypeScript AST 1`] = ` import { Prisma } from "@prisma/client"; import type { PrismaClient } from "@prisma/client"; import { getClient } from "@quramy/prisma-fabbrica/lib/clientHolder"; +import { ModelWithFields, createScreener } from "@quramy/prisma-fabbrica/lib/relations"; import scalarFieldValueGenerator from "@quramy/prisma-fabbrica/lib/scalar/gen"; import { Resolver, normalizeResolver, getSequenceCounter } from "@quramy/prisma-fabbrica/lib/helpers"; export { initialize, resetSequence } from "@quramy/prisma-fabbrica"; type BuildDataOptions = { readonly seq: number; }; +const modelFieldDefinitions: ModelWithFields[] = [{ + name: "User", + fields: [] + }]; type UserScalarOrEnumFields = { id: number; name: string; @@ -33,6 +38,7 @@ function autoGenerateUserScalarsOrEnums({ seq }: { function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("User", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq }); @@ -46,7 +52,7 @@ function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFac id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().user.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); diff --git a/packages/prisma-fabbrica/src/templates/index.ts b/packages/prisma-fabbrica/src/templates/index.ts index 9944e354..3098457b 100644 --- a/packages/prisma-fabbrica/src/templates/index.ts +++ b/packages/prisma-fabbrica/src/templates/index.ts @@ -1,11 +1,8 @@ import { DMMF } from "@prisma/generator-helper"; import ts from "typescript"; import { template } from "talt"; -import { camelize, ast } from "../helpers"; - -function byName(name: string | { readonly name: string }) { - return (x: T) => x.name === (typeof name === "string" ? name : name.name); -} +import { camelize, ast, byName, createJSONLiteral } from "../helpers"; +import { createFieldDefinitions } from "../relations"; export function findPrsimaCreateInputTypeFromModelName(document: DMMF.Document, modelName: string) { const search = `${modelName}CreateInput`; @@ -68,6 +65,7 @@ export const header = (prismaClientModuleSpecifier: string) => import { Prisma } from ${() => ast.stringLiteral(prismaClientModuleSpecifier)}; import type { PrismaClient } from ${() => ast.stringLiteral(prismaClientModuleSpecifier)}; import { getClient } from "@quramy/prisma-fabbrica/lib/clientHolder"; + import { ModelWithFields, createScreener } from "@quramy/prisma-fabbrica/lib/relations"; import scalarFieldValueGenerator from "@quramy/prisma-fabbrica/lib/scalar/gen"; import { Resolver, normalizeResolver, getSequenceCounter } from "@quramy/prisma-fabbrica/lib/helpers"; export { initialize, resetSequence } from "@quramy/prisma-fabbrica"; @@ -82,6 +80,11 @@ export const importStatement = (specifier: string, prismaClientModuleSpecifier: import { ${() => ast.identifier(specifier)} } from ${() => ast.stringLiteral(prismaClientModuleSpecifier)}; `(); +export const modelFieldDefinitions = (models: DMMF.Model[]) => + template.statement` + const modelFieldDefinitions: ModelWithFields[] = ${() => createJSONLiteral(createFieldDefinitions(models))} +`(); + export const scalarFieldType = ( model: DMMF.Model, fieldName: string, @@ -267,6 +270,7 @@ export const defineModelFactoryInernal = (model: DMMF.Model, inputType: DMMF.Inp const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener(${() => ast.stringLiteral(model.name)}, modelFieldDefinitions); const buildCreateInput = async ( inputData: Partial = {} @@ -309,7 +313,7 @@ export const defineModelFactoryInernal = (model: DMMF.Model, inputType: DMMF.Inp const create = async ( inputData: Partial = {} ) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().MODEL_KEY.create({ data }); }; @@ -373,6 +377,7 @@ export function getSourceFile({ ...modelNames.map(modelName => importStatement(modelName, prismaClientModuleSpecifier)), ...enums.map(enumName => importStatement(enumName, prismaClientModuleSpecifier)), ...header(prismaClientModuleSpecifier).statements, + modelFieldDefinitions(document.datamodel.models), ...document.datamodel.models .map(model => ({ model, createInputType: findPrsimaCreateInputTypeFromModelName(document, model.name) })) .flatMap(({ model, createInputType }) => [ diff --git a/packages/ts-compile-testing/fixtures/field-variation/__generated__/fabbrica/index.ts b/packages/ts-compile-testing/fixtures/field-variation/__generated__/fabbrica/index.ts index 07085cde..1d944913 100644 --- a/packages/ts-compile-testing/fixtures/field-variation/__generated__/fabbrica/index.ts +++ b/packages/ts-compile-testing/fixtures/field-variation/__generated__/fabbrica/index.ts @@ -4,12 +4,20 @@ import { Role } from "./../client"; import { Prisma } from "./../client"; import type { PrismaClient } from "./../client"; import { getClient } from "@quramy/prisma-fabbrica/lib/clientHolder"; +import { ModelWithFields, createScreener } from "@quramy/prisma-fabbrica/lib/relations"; import scalarFieldValueGenerator from "@quramy/prisma-fabbrica/lib/scalar/gen"; import { Resolver, normalizeResolver, getSequenceCounter } from "@quramy/prisma-fabbrica/lib/helpers"; export { initialize, resetSequence } from "@quramy/prisma-fabbrica"; type BuildDataOptions = { readonly seq: number; }; +const modelFieldDefinitions: ModelWithFields[] = [{ + name: "User", + fields: [] + }, { + name: "ComplexIdModel", + fields: [] + }]; type UserScalarOrEnumFields = { id: string; role: Role; @@ -34,6 +42,7 @@ function autoGenerateUserScalarsOrEnums({ seq }: { function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("User", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq }); @@ -47,7 +56,7 @@ function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFac id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().user.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); @@ -84,6 +93,7 @@ function autoGenerateComplexIdModelScalarsOrEnums({ seq }: { function defineComplexIdModelFactoryInternal({ defaultData: defaultDataResolver }: ComplexIdModelFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("ComplexIdModel", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateComplexIdModelScalarsOrEnums({ seq }); @@ -98,7 +108,7 @@ function defineComplexIdModelFactoryInternal({ defaultData: defaultDataResolver lastName: inputData.lastName }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().complexIdModel.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); diff --git a/packages/ts-compile-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts b/packages/ts-compile-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts index 6c84c1e8..5e184126 100644 --- a/packages/ts-compile-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts +++ b/packages/ts-compile-testing/fixtures/relations-many-to-many/__generated__/fabbrica/index.ts @@ -3,12 +3,28 @@ import { Category } from "./../client"; import { Prisma } from "./../client"; import type { PrismaClient } from "./../client"; import { getClient } from "@quramy/prisma-fabbrica/lib/clientHolder"; +import { ModelWithFields, createScreener } from "@quramy/prisma-fabbrica/lib/relations"; import scalarFieldValueGenerator from "@quramy/prisma-fabbrica/lib/scalar/gen"; import { Resolver, normalizeResolver, getSequenceCounter } from "@quramy/prisma-fabbrica/lib/helpers"; export { initialize, resetSequence } from "@quramy/prisma-fabbrica"; type BuildDataOptions = { readonly seq: number; }; +const modelFieldDefinitions: ModelWithFields[] = [{ + name: "Post", + fields: [{ + name: "categories", + type: "Category", + relationName: "CategoryToPost" + }] + }, { + name: "Category", + fields: [{ + name: "posts", + type: "Post", + relationName: "CategoryToPost" + }] + }]; type PostScalarOrEnumFields = { id: string; title: string; @@ -32,6 +48,7 @@ function autoGeneratePostScalarsOrEnums({ seq }: { function definePostFactoryInternal({ defaultData: defaultDataResolver }: PostFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("Post", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGeneratePostScalarsOrEnums({ seq }); @@ -45,7 +62,7 @@ function definePostFactoryInternal({ defaultData: defaultDataResolver }: PostFac id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().post.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); @@ -83,6 +100,7 @@ function autoGenerateCategoryScalarsOrEnums({ seq }: { function defineCategoryFactoryInternal({ defaultData: defaultDataResolver }: CategoryFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("Category", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateCategoryScalarsOrEnums({ seq }); @@ -96,7 +114,7 @@ function defineCategoryFactoryInternal({ defaultData: defaultDataResolver }: Cat id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().category.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); diff --git a/packages/ts-compile-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts b/packages/ts-compile-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts index 416e9b41..2ae79b4e 100644 --- a/packages/ts-compile-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts +++ b/packages/ts-compile-testing/fixtures/relations-one-to-many/__generated__/fabbrica/index.ts @@ -4,12 +4,47 @@ import { Review } from "./../client"; import { Prisma } from "./../client"; import type { PrismaClient } from "./../client"; import { getClient } from "@quramy/prisma-fabbrica/lib/clientHolder"; +import { ModelWithFields, createScreener } from "@quramy/prisma-fabbrica/lib/relations"; import scalarFieldValueGenerator from "@quramy/prisma-fabbrica/lib/scalar/gen"; import { Resolver, normalizeResolver, getSequenceCounter } from "@quramy/prisma-fabbrica/lib/helpers"; export { initialize, resetSequence } from "@quramy/prisma-fabbrica"; type BuildDataOptions = { readonly seq: number; }; +const modelFieldDefinitions: ModelWithFields[] = [{ + name: "User", + fields: [{ + name: "posts", + type: "Post", + relationName: "PostToUser" + }, { + name: "reviews", + type: "Review", + relationName: "ReviewToUser" + }] + }, { + name: "Post", + fields: [{ + name: "author", + type: "User", + relationName: "PostToUser" + }, { + name: "reviews", + type: "Review", + relationName: "PostToReview" + }] + }, { + name: "Review", + fields: [{ + name: "post", + type: "Post", + relationName: "PostToReview" + }, { + name: "reviewer", + type: "User", + relationName: "ReviewToUser" + }] + }]; type UserScalarOrEnumFields = { id: string; name: string; @@ -34,6 +69,7 @@ function autoGenerateUserScalarsOrEnums({ seq }: { function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("User", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq }); @@ -47,7 +83,7 @@ function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFac id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().user.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); @@ -93,6 +129,7 @@ function autoGeneratePostScalarsOrEnums({ seq }: { function definePostFactoryInternal({ defaultData: defaultDataResolver }: PostFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("Post", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGeneratePostScalarsOrEnums({ seq }); @@ -110,7 +147,7 @@ function definePostFactoryInternal({ defaultData: defaultDataResolver }: PostFac id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().post.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); @@ -163,6 +200,7 @@ function autoGenerateReviewScalarsOrEnums({ seq }: { function defineReviewFactoryInternal({ defaultData: defaultDataResolver }: ReviewFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("Review", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateReviewScalarsOrEnums({ seq }); @@ -183,7 +221,7 @@ function defineReviewFactoryInternal({ defaultData: defaultDataResolver }: Revie id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().review.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); diff --git a/packages/ts-compile-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts b/packages/ts-compile-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts index 2c0d90e7..41972426 100644 --- a/packages/ts-compile-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts +++ b/packages/ts-compile-testing/fixtures/relations-one-to-one/__generated__/fabbrica/index.ts @@ -3,12 +3,28 @@ import { Profile } from "./../client"; import { Prisma } from "./../client"; import type { PrismaClient } from "./../client"; import { getClient } from "@quramy/prisma-fabbrica/lib/clientHolder"; +import { ModelWithFields, createScreener } from "@quramy/prisma-fabbrica/lib/relations"; import scalarFieldValueGenerator from "@quramy/prisma-fabbrica/lib/scalar/gen"; import { Resolver, normalizeResolver, getSequenceCounter } from "@quramy/prisma-fabbrica/lib/helpers"; export { initialize, resetSequence } from "@quramy/prisma-fabbrica"; type BuildDataOptions = { readonly seq: number; }; +const modelFieldDefinitions: ModelWithFields[] = [{ + name: "User", + fields: [{ + name: "profile", + type: "Profile", + relationName: "ProfileToUser" + }] + }, { + name: "Profile", + fields: [{ + name: "user", + type: "User", + relationName: "ProfileToUser" + }] + }]; type UserScalarOrEnumFields = { id: string; name: string; @@ -39,6 +55,7 @@ function autoGenerateUserScalarsOrEnums({ seq }: { function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("User", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq }); @@ -56,7 +73,7 @@ function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFac id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().user.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); @@ -98,6 +115,7 @@ function autoGenerateProfileScalarsOrEnums({ seq }: { function defineProfileFactoryInternal({ defaultData: defaultDataResolver }: ProfileFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("Profile", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateProfileScalarsOrEnums({ seq }); @@ -115,7 +133,7 @@ function defineProfileFactoryInternal({ defaultData: defaultDataResolver }: Prof id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().profile.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect); diff --git a/packages/ts-compile-testing/fixtures/simple-model/__generated__/fabbrica/index.ts b/packages/ts-compile-testing/fixtures/simple-model/__generated__/fabbrica/index.ts index 13eff060..ec586ba9 100644 --- a/packages/ts-compile-testing/fixtures/simple-model/__generated__/fabbrica/index.ts +++ b/packages/ts-compile-testing/fixtures/simple-model/__generated__/fabbrica/index.ts @@ -2,12 +2,17 @@ import { User } from "./../client"; import { Prisma } from "./../client"; import type { PrismaClient } from "./../client"; import { getClient } from "@quramy/prisma-fabbrica/lib/clientHolder"; +import { ModelWithFields, createScreener } from "@quramy/prisma-fabbrica/lib/relations"; import scalarFieldValueGenerator from "@quramy/prisma-fabbrica/lib/scalar/gen"; import { Resolver, normalizeResolver, getSequenceCounter } from "@quramy/prisma-fabbrica/lib/helpers"; export { initialize, resetSequence } from "@quramy/prisma-fabbrica"; type BuildDataOptions = { readonly seq: number; }; +const modelFieldDefinitions: ModelWithFields[] = [{ + name: "User", + fields: [] + }]; type UserScalarOrEnumFields = { id: string; name: string; @@ -30,6 +35,7 @@ function autoGenerateUserScalarsOrEnums({ seq }: { function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFactoryDefineOptions) { const seqKey = {}; const getSeq = () => getSequenceCounter(seqKey); + const screen = createScreener("User", modelFieldDefinitions); const buildCreateInput = async (inputData: Partial = {}) => { const seq = getSeq(); const requiredScalarData = autoGenerateUserScalarsOrEnums({ seq }); @@ -43,7 +49,7 @@ function defineUserFactoryInternal({ defaultData: defaultDataResolver }: UserFac id: inputData.id }); const create = async (inputData: Partial = {}) => { - const data = await buildCreateInput(inputData); + const data = await buildCreateInput(inputData).then(screen); return await getClient().user.create({ data }); }; const createForConnect = (inputData: Partial = {}) => create(inputData).then(pickForConnect);