diff --git a/.cli.prettierignore b/.cli.prettierignore new file mode 100644 index 000000000..4debdd61f --- /dev/null +++ b/.cli.prettierignore @@ -0,0 +1,15 @@ +tsconfig*.json + +build +lib +package + +coverage +tests/artifacts + +.docusaurus + +**/prisma/generated/**/* +**/prisma/migrations/**/* +prisma-client-mock.js +prisma-client-mock.d.ts diff --git a/.prettierignore b/.prettierignore index cc8217eec..3300b9d1c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,8 +1,14 @@ tsconfig*.json -lib/**/* -package/**/* -tests/artifacts + +build +lib +package + coverage +# tests/artifacts + +.docusaurus + **/prisma/generated/**/* **/prisma/migrations/**/* prisma-client-mock.js diff --git a/docs/basics/configuration.md b/docs/basics/configuration.md index 412d057a8..873f9c616 100644 --- a/docs/basics/configuration.md +++ b/docs/basics/configuration.md @@ -50,3 +50,39 @@ generator typegraphql { emitTranspiledCode = true } ``` + +## Formatting generated code + +By default, the generated code is formatted by TypeScript compiler while emitting. + +However, if you prefer some other code style, you can provide `formatGeneratedCode` generator option to format the codebase with [Prettier](https://prettier.io/): + +```prisma {4} +generator typegraphql { + provider = "typegraphql-prisma" + output = "../prisma/generated/type-graphql" + formatGeneratedCode = "prettier" +} +``` + +Prettier will look for the configuration file in your project tree and use it to format the generated code. If no config file detected, default settings will be applied. + +:::caution +Be aware that formatting code by Prettier has a quite huge impact on the generation time, so use it with caution. +::: + +If you git-ignore the generated files or you don't want to read the generated source code, you can ignore the generated code style and disable the formatting at all - by providing `false` value to `formatGeneratedCode` generator option: + +```prisma {4} +generator typegraphql { + provider = "typegraphql-prisma" + output = "../prisma/generated/type-graphql" + formatGeneratedCode = false +} +``` + +This way you can save even up to 33% of the generation process time. + +:::info +When the generator is configured to emit transpiled code, the generated JS code is always formatted by TypeScript compiler and you can't change it to Prettier or disable the formatting by the `formatGeneratedCode` option. +::: diff --git a/experiments/postgres/prisma/generated/client/schema.prisma b/experiments/postgres/prisma/generated/client/schema.prisma index 5e80d6c7d..ec47ae620 100644 --- a/experiments/postgres/prisma/generated/client/schema.prisma +++ b/experiments/postgres/prisma/generated/client/schema.prisma @@ -24,6 +24,7 @@ generator typegraphql { contextPrismaKey = "prismaClient" useSimpleInputs = true emitRedundantTypesInfo = true + formatGeneratedCode = "tsc" } // Role enum comment diff --git a/experiments/postgres/prisma/schema.prisma b/experiments/postgres/prisma/schema.prisma index 5e80d6c7d..ec47ae620 100644 --- a/experiments/postgres/prisma/schema.prisma +++ b/experiments/postgres/prisma/schema.prisma @@ -24,6 +24,7 @@ generator typegraphql { contextPrismaKey = "prismaClient" useSimpleInputs = true emitRedundantTypesInfo = true + formatGeneratedCode = "tsc" } // Role enum comment diff --git a/package.json b/package.json index c7f6dab42..1dfbab2d9 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,11 @@ "check:type": "tsc --noEmit", "check:experiments:postgres": "cd ./experiments/postgres && tsc --noEmit", "check:experiments:mongodb": "cd ./experiments/mongodb && tsc --noEmit", - "check:format": "prettier --check ./**/*.{js,json,ts,tsx}", + "check:format": "prettier --ignore-path ./.cli.prettierignore --check ./**/*.{js,json,ts,tsx}", "test": "ts-node ./tests/helpers/setup-tests.ts && jest --watch --verbose", "test:integration": "ts-node ./tests/helpers/setup-tests.ts && env-cmd jest --watch --verbose --config ./jest.config.integration.ts", "test:ci": "ts-node ./tests/helpers/setup-tests.ts && jest --coverage --verbose --runInBand && jest --coverage --verbose --runInBand --config ./jest.config.integration.ts", - "format": "prettier --write ./**/*.{js,json,ts,tsx}" + "format": "prettier --ignore-path ./.cli.prettierignore --write ./**/*.{js,json,ts,tsx}" }, "bin": { "typegraphql-prisma": "lib/generator.js" @@ -39,7 +39,7 @@ "devDependencies": { "@jest/types": "^29.5.0", "@prisma/client": "~4.12.0", - "@prisma/fetch-engine": "4.12.0", + "@prisma/fetch-engine": "~4.12.0", "@types/graphql-fields": "^1.3.5", "@types/jest": "^29.5.0", "@types/node": "^18.15.11", diff --git a/src/cli/helpers.ts b/src/cli/helpers.ts index 8d8dffd5e..0cfefb1b0 100644 --- a/src/cli/helpers.ts +++ b/src/cli/helpers.ts @@ -1,11 +1,15 @@ export function parseStringBoolean(stringBoolean: string | undefined) { - return stringBoolean ? stringBoolean === "true" : undefined; + return stringBoolean === "true" + ? true + : stringBoolean === "false" + ? false + : undefined; } export function parseStringArray( stringArray: string | undefined, optionPropertyName: string, - allowedValues?: TAllowedValue[], + allowedValues?: readonly TAllowedValue[], ): TAllowedValue[] | undefined { if (!stringArray) { return undefined; @@ -22,3 +26,19 @@ export function parseStringArray( } return parsedArray as TAllowedValue[]; } + +export function parseStringEnum( + stringEnum: string | undefined, + optionPropertyName: string, + allowedValues: readonly TAllowedValue[], +): TAllowedValue | undefined { + if (!stringEnum) { + return undefined; + } + if (!allowedValues.includes(stringEnum as any)) { + throw new Error( + `Invalid "${optionPropertyName}" option value "${stringEnum}" provided for TypeGraphQL generator.`, + ); + } + return stringEnum as TAllowedValue; +} diff --git a/src/cli/prisma-generator.ts b/src/cli/prisma-generator.ts index 931bf03e4..f552adca2 100644 --- a/src/cli/prisma-generator.ts +++ b/src/cli/prisma-generator.ts @@ -10,7 +10,11 @@ import { InternalGeneratorOptions, } from "../generator/options"; import { ALL_EMIT_BLOCK_KINDS } from "../generator/emit-block"; -import { parseStringBoolean, parseStringArray } from "./helpers"; +import { + parseStringBoolean, + parseStringArray, + parseStringEnum, +} from "./helpers"; export async function generate(options: GeneratorOptions) { const outputDir = parseEnvValue(options.generator.output!); @@ -56,6 +60,13 @@ export async function generate(options: GeneratorOptions) { generatorConfig.omitOutputFieldsByDefault, "omitOutputFieldsByDefault", ), + formatGeneratedCode: + parseStringBoolean(generatorConfig.formatGeneratedCode) ?? + parseStringEnum( + generatorConfig.formatGeneratedCode, + "formatGeneratedCode", + ["prettier", "tsc"] as const, + ), }; const internalConfig: InternalGeneratorOptions = { outputDirPath: outputDir, diff --git a/src/generator/generate-code.ts b/src/generator/generate-code.ts index bdb75fabe..509fc7d89 100644 --- a/src/generator/generate-code.ts +++ b/src/generator/generate-code.ts @@ -1,6 +1,9 @@ import { DMMF as PrismaDMMF } from "@prisma/client/runtime"; import { Project, ScriptTarget, ModuleKind, CompilerOptions } from "ts-morph"; import path from "path"; +import { exec } from "node:child_process"; +import { promisify } from "node:util"; +const execa = promisify(exec); import { noop, toUnixPath } from "./helpers"; import generateEnumFromDef from "./enum"; @@ -76,6 +79,7 @@ export default async function generateCode( baseOptions.prismaClientPath.includes("node_modules") ? "@prisma/client" : undefined, + formatGeneratedCode: baseOptions.formatGeneratedCode ?? "tsc", // default for backward compatibility }; const baseDirPath = options.outputDirPath; @@ -527,9 +531,14 @@ export default async function generateCode( if (emitTranspiledCode) { await project.emit(); } else { - for (const file of project.getSourceFiles()) { - file.formatText({ indentSize: 2 }); + if (options.formatGeneratedCode === "tsc") { + for (const file of project.getSourceFiles()) { + file.formatText({ indentSize: 2 }); + } } await project.save(); + if (options.formatGeneratedCode === "prettier") { + await execa(`npx prettier --write ${baseDirPath}`); + } } } diff --git a/src/generator/options.ts b/src/generator/options.ts index 90f9f70ce..99b168295 100644 --- a/src/generator/options.ts +++ b/src/generator/options.ts @@ -14,6 +14,7 @@ export interface ExternalGeneratorOptions { useSimpleInputs?: boolean; omitInputFieldsByDefault?: string[]; omitOutputFieldsByDefault?: string[]; + formatGeneratedCode?: boolean | "prettier" | "tsc"; } export interface InternalGeneratorOptions { diff --git a/tests/regression/__snapshots__/crud.ts.snap b/tests/regression/__snapshots__/crud.ts.snap index 5d6a125bc..dc497534e 100644 --- a/tests/regression/__snapshots__/crud.ts.snap +++ b/tests/regression/__snapshots__/crud.ts.snap @@ -2359,6 +2359,435 @@ exports.UserCrudResolver = UserCrudResolver; " `; +exports[`crud when formatGeneratedCode is set to 'prettier' should properly format generated files for resolver classes: UserCrudResolver 1`] = ` +"import * as TypeGraphQL from \\"type-graphql\\"; +import type { GraphQLResolveInfo } from \\"graphql\\"; +import { AggregateUserArgs } from \\"./args/AggregateUserArgs\\"; +import { CreateManyUserArgs } from \\"./args/CreateManyUserArgs\\"; +import { CreateOneUserArgs } from \\"./args/CreateOneUserArgs\\"; +import { DeleteManyUserArgs } from \\"./args/DeleteManyUserArgs\\"; +import { DeleteOneUserArgs } from \\"./args/DeleteOneUserArgs\\"; +import { FindFirstUserArgs } from \\"./args/FindFirstUserArgs\\"; +import { FindFirstUserOrThrowArgs } from \\"./args/FindFirstUserOrThrowArgs\\"; +import { FindManyUserArgs } from \\"./args/FindManyUserArgs\\"; +import { FindUniqueUserArgs } from \\"./args/FindUniqueUserArgs\\"; +import { FindUniqueUserOrThrowArgs } from \\"./args/FindUniqueUserOrThrowArgs\\"; +import { GroupByUserArgs } from \\"./args/GroupByUserArgs\\"; +import { UpdateManyUserArgs } from \\"./args/UpdateManyUserArgs\\"; +import { UpdateOneUserArgs } from \\"./args/UpdateOneUserArgs\\"; +import { UpsertOneUserArgs } from \\"./args/UpsertOneUserArgs\\"; +import { + transformInfoIntoPrismaArgs, + getPrismaFromContext, + transformCountFieldIntoSelectRelationsCount, +} from \\"../../../helpers\\"; +import { User } from \\"../../../models/User\\"; +import { AffectedRowsOutput } from \\"../../outputs/AffectedRowsOutput\\"; +import { AggregateUser } from \\"../../outputs/AggregateUser\\"; +import { UserGroupBy } from \\"../../outputs/UserGroupBy\\"; + +@TypeGraphQL.Resolver(_of => User) +export class UserCrudResolver { + @TypeGraphQL.Query(_returns => AggregateUser, { + nullable: false, + }) + async aggregateUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: AggregateUserArgs, + ): Promise { + return getPrismaFromContext(ctx).user.aggregate({ + ...args, + ...transformInfoIntoPrismaArgs(info), + }); + } + + @TypeGraphQL.Mutation(_returns => AffectedRowsOutput, { + nullable: false, + }) + async createManyUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: CreateManyUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.createMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: false, + }) + async createOneUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: CreateOneUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.create({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => AffectedRowsOutput, { + nullable: false, + }) + async deleteManyUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: DeleteManyUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.deleteMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: true, + }) + async deleteOneUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: DeleteOneUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.delete({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true, + }) + async findFirstUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: FindFirstUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findFirst({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true, + }) + async findFirstUserOrThrow( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: FindFirstUserOrThrowArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findFirstOrThrow({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => [User], { + nullable: false, + }) + async users( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: FindManyUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true, + }) + async user( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: FindUniqueUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findUnique({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true, + }) + async getUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: FindUniqueUserOrThrowArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findUniqueOrThrow({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => [UserGroupBy], { + nullable: false, + }) + async groupByUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: GroupByUserArgs, + ): Promise { + const { _count, _avg, _sum, _min, _max } = + transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.groupBy({ + ...args, + ...Object.fromEntries( + Object.entries({ _count, _avg, _sum, _min, _max }).filter( + ([_, v]) => v != null, + ), + ), + }); + } + + @TypeGraphQL.Mutation(_returns => AffectedRowsOutput, { + nullable: false, + }) + async updateManyUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: UpdateManyUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.updateMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: true, + }) + async updateOneUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: UpdateOneUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.update({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: false, + }) + async upsertOneUser( + @TypeGraphQL.Ctx() ctx: any, + @TypeGraphQL.Info() info: GraphQLResolveInfo, + @TypeGraphQL.Args() args: UpsertOneUserArgs, + ): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.upsert({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } +} +" +`; + +exports[`crud when formatGeneratedCode is set to false should not format generated files for resolver classes: UserCrudResolver 1`] = ` +"import * as TypeGraphQL from \\"type-graphql\\"; +import type { GraphQLResolveInfo } from \\"graphql\\"; +import { AggregateUserArgs } from \\"./args/AggregateUserArgs\\"; +import { CreateManyUserArgs } from \\"./args/CreateManyUserArgs\\"; +import { CreateOneUserArgs } from \\"./args/CreateOneUserArgs\\"; +import { DeleteManyUserArgs } from \\"./args/DeleteManyUserArgs\\"; +import { DeleteOneUserArgs } from \\"./args/DeleteOneUserArgs\\"; +import { FindFirstUserArgs } from \\"./args/FindFirstUserArgs\\"; +import { FindFirstUserOrThrowArgs } from \\"./args/FindFirstUserOrThrowArgs\\"; +import { FindManyUserArgs } from \\"./args/FindManyUserArgs\\"; +import { FindUniqueUserArgs } from \\"./args/FindUniqueUserArgs\\"; +import { FindUniqueUserOrThrowArgs } from \\"./args/FindUniqueUserOrThrowArgs\\"; +import { GroupByUserArgs } from \\"./args/GroupByUserArgs\\"; +import { UpdateManyUserArgs } from \\"./args/UpdateManyUserArgs\\"; +import { UpdateOneUserArgs } from \\"./args/UpdateOneUserArgs\\"; +import { UpsertOneUserArgs } from \\"./args/UpsertOneUserArgs\\"; +import { transformInfoIntoPrismaArgs, getPrismaFromContext, transformCountFieldIntoSelectRelationsCount } from \\"../../../helpers\\"; +import { User } from \\"../../../models/User\\"; +import { AffectedRowsOutput } from \\"../../outputs/AffectedRowsOutput\\"; +import { AggregateUser } from \\"../../outputs/AggregateUser\\"; +import { UserGroupBy } from \\"../../outputs/UserGroupBy\\"; + +@TypeGraphQL.Resolver(_of => User) +export class UserCrudResolver { + @TypeGraphQL.Query(_returns => AggregateUser, { + nullable: false + }) + async aggregateUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: AggregateUserArgs): Promise { + return getPrismaFromContext(ctx).user.aggregate({ + ...args, + ...transformInfoIntoPrismaArgs(info), + }); + } + + @TypeGraphQL.Mutation(_returns => AffectedRowsOutput, { + nullable: false + }) + async createManyUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: CreateManyUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.createMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: false + }) + async createOneUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: CreateOneUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.create({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => AffectedRowsOutput, { + nullable: false + }) + async deleteManyUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: DeleteManyUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.deleteMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: true + }) + async deleteOneUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: DeleteOneUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.delete({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true + }) + async findFirstUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: FindFirstUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findFirst({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true + }) + async findFirstUserOrThrow(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: FindFirstUserOrThrowArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findFirstOrThrow({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => [User], { + nullable: false + }) + async users(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: FindManyUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true + }) + async user(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: FindUniqueUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findUnique({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => User, { + nullable: true + }) + async getUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: FindUniqueUserOrThrowArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.findUniqueOrThrow({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Query(_returns => [UserGroupBy], { + nullable: false + }) + async groupByUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: GroupByUserArgs): Promise { + const { _count, _avg, _sum, _min, _max } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.groupBy({ + ...args, + ...Object.fromEntries( + Object.entries({ _count, _avg, _sum, _min, _max }).filter(([_, v]) => v != null) + ), + }); + } + + @TypeGraphQL.Mutation(_returns => AffectedRowsOutput, { + nullable: false + }) + async updateManyUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: UpdateManyUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.updateMany({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: true + }) + async updateOneUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: UpdateOneUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.update({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } + + @TypeGraphQL.Mutation(_returns => User, { + nullable: false + }) + async upsertOneUser(@TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo, @TypeGraphQL.Args() args: UpsertOneUserArgs): Promise { + const { _count } = transformInfoIntoPrismaArgs(info); + return getPrismaFromContext(ctx).user.upsert({ + ...args, + ...(_count && transformCountFieldIntoSelectRelationsCount(_count)), + }); + } +} +" +`; + exports[`crud when model is renamed should properly generate actions resolver classes for prisma model: AggregateClientResolver 1`] = ` "import * as TypeGraphQL from \\"type-graphql\\"; import type { GraphQLResolveInfo } from \\"graphql\\"; diff --git a/tests/regression/crud.ts b/tests/regression/crud.ts index 506ee3b38..bd8a95950 100644 --- a/tests/regression/crud.ts +++ b/tests/regression/crud.ts @@ -699,6 +699,52 @@ describe("crud", () => { }, 20000); }); + describe("when formatGeneratedCode is set to 'prettier'", () => { + it("should properly format generated files for resolver classes", async () => { + const schema = /* prisma */ ` + model User { + intIdField Int @id @default(autoincrement()) + uniqueStringField String @unique + optionalStringField String? + dateField DateTime + } + `; + + await generateCodeFromSchema(schema, { + outputDirPath, + formatGeneratedCode: "prettier", + }); + const userCrudResolverTSFile = await readGeneratedFile( + "/resolvers/crud/User/UserCrudResolver.ts", + ); + + expect(userCrudResolverTSFile).toMatchSnapshot("UserCrudResolver"); + }, 20000); + }); + + describe("when formatGeneratedCode is set to false", () => { + it("should not format generated files for resolver classes", async () => { + const schema = /* prisma */ ` + model User { + intIdField Int @id @default(autoincrement()) + uniqueStringField String @unique + optionalStringField String? + dateField DateTime + } + `; + + await generateCodeFromSchema(schema, { + outputDirPath, + formatGeneratedCode: false, + }); + const userCrudResolverTSFile = await readGeneratedFile( + "/resolvers/crud/User/UserCrudResolver.ts", + ); + + expect(userCrudResolverTSFile).toMatchSnapshot("UserCrudResolver"); + }, 20000); + }); + describe("when emitRedundantTypesInfo is set to true", () => { it("should properly generate type info for @Args decorator", async () => { const schema = /* prisma */ `