From 1300ddd994bfec307c8e8379785a69013ae17325 Mon Sep 17 00:00:00 2001 From: Zen Software Date: Mon, 30 Jan 2023 13:45:04 -0700 Subject: [PATCH] feat(prisma): make resolvers testable with PrismaSelectService undefined --- apps/api/src/app/graphql/resolvers/User.ts | 25 ++++++++--------- apps/api/src/app/prisma/index.ts | 2 +- apps/api/src/app/prisma/prisma-select-args.ts | 25 ----------------- .../src/app/prisma/prisma-select.service.ts | 25 +++++++++++++++++ apps/api/src/app/prisma/prisma.module.ts | 5 ++-- tools/templates/graphql-resolvers.ts | 27 ++++++++++--------- 6 files changed, 56 insertions(+), 53 deletions(-) delete mode 100644 apps/api/src/app/prisma/prisma-select-args.ts create mode 100644 apps/api/src/app/prisma/prisma-select.service.ts diff --git a/apps/api/src/app/graphql/resolvers/User.ts b/apps/api/src/app/graphql/resolvers/User.ts index 3faa5b4fd..72f3ff84f 100644 --- a/apps/api/src/app/graphql/resolvers/User.ts +++ b/apps/api/src/app/graphql/resolvers/User.ts @@ -6,7 +6,7 @@ import { GraphQLResolveInfo } from 'graphql'; import { gql } from 'graphql-tag'; import { AppAbility, AuthService, DEFAULT_FIELDS_TOKEN } from '../../auth'; -import { DefaultFields, PrismaSelectArgs, PrismaService, User } from '../../prisma'; +import { DefaultFields, PrismaSelectService, PrismaService, User } from '../../prisma'; import { AggregateUserArgs, CreateOneUserArgs, @@ -34,6 +34,7 @@ export class UserResolver { constructor( @Inject(DEFAULT_FIELDS_TOKEN) private readonly defaultFields: DefaultFields, private readonly prisma: PrismaService, + private readonly prismaSelect: PrismaSelectService, private readonly auth: AuthService ) {} @@ -55,7 +56,7 @@ export class UserResolver { @CaslAbility() ability: AppAbility ) { const record = await this.prisma.user.findUnique( - PrismaSelectArgs(info, args, this.defaultFields) + this.prismaSelect.getArgs(info, args, this.defaultFields) ); if (ability.cannot('read', subject('User', record as User))) throw new ForbiddenException(); return record; @@ -68,7 +69,7 @@ export class UserResolver { @CaslAbility() ability: AppAbility ) { const record = await this.prisma.user.findFirst( - PrismaSelectArgs(info, args, this.defaultFields) + this.prismaSelect.getArgs(info, args, this.defaultFields) ); if (ability.cannot('read', subject('User', record as User))) throw new ForbiddenException(); return record; @@ -81,7 +82,7 @@ export class UserResolver { @CaslAbility() ability: AppAbility ) { const records = await this.prisma.user.findMany( - PrismaSelectArgs(info, args, this.defaultFields) + this.prismaSelect.getArgs(info, args, this.defaultFields) ); for (const record of records) { if (ability.cannot('read', subject('User', record))) throw new ForbiddenException(); @@ -96,7 +97,7 @@ export class UserResolver { @CaslAbility() ability: AppAbility ) { if (ability.cannot('read', 'User')) throw new ForbiddenException(); - return this.prisma.user.count(PrismaSelectArgs(info, args)); + return this.prisma.user.count(this.prismaSelect.getArgs(info, args)); } @Query() @@ -106,7 +107,7 @@ export class UserResolver { @CaslAbility() ability: AppAbility ) { if (ability.cannot('read', 'User')) throw new ForbiddenException(); - return this.prisma.user.aggregate(PrismaSelectArgs(info, args)); + return this.prisma.user.aggregate(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -116,7 +117,7 @@ export class UserResolver { @CaslAbility() ability: AppAbility ) { if (ability.cannot('create', subject('User', args.data as any))) throw new ForbiddenException(); - return this.prisma.user.create(PrismaSelectArgs(info, args)); + return this.prisma.user.create(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -130,7 +131,7 @@ export class UserResolver { select: this.defaultFields.User, }); if (ability.cannot('update', subject('User', record as User))) throw new ForbiddenException(); - return this.prisma.user.update(PrismaSelectArgs(info, args)); + return this.prisma.user.update(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -146,7 +147,7 @@ export class UserResolver { for (const record of records) { if (ability.cannot('update', subject('User', record as User))) throw new ForbiddenException(); } - return this.prisma.user.updateMany(PrismaSelectArgs(info, args)); + return this.prisma.user.updateMany(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -165,7 +166,7 @@ export class UserResolver { ) { throw new ForbiddenException(); } - return this.prisma.user.upsert(PrismaSelectArgs(info, args)); + return this.prisma.user.upsert(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -179,7 +180,7 @@ export class UserResolver { select: this.defaultFields.User, }); if (ability.cannot('delete', subject('User', record as User))) throw new ForbiddenException(); - return this.prisma.user.delete(PrismaSelectArgs(info, args)); + return this.prisma.user.delete(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -195,6 +196,6 @@ export class UserResolver { for (const record of records) { if (ability.cannot('delete', subject('User', record as User))) throw new ForbiddenException(); } - return this.prisma.user.deleteMany(PrismaSelectArgs(info, args)); + return this.prisma.user.deleteMany(this.prismaSelect.getArgs(info, args)); } } diff --git a/apps/api/src/app/prisma/index.ts b/apps/api/src/app/prisma/index.ts index a777ada53..663f0fb2c 100644 --- a/apps/api/src/app/prisma/index.ts +++ b/apps/api/src/app/prisma/index.ts @@ -1,5 +1,5 @@ export * from './default-fields'; export * from './generated'; -export * from './prisma-select-args'; +export * from './prisma-select.service'; export * from './prisma.module'; export * from './prisma.service'; diff --git a/apps/api/src/app/prisma/prisma-select-args.ts b/apps/api/src/app/prisma/prisma-select-args.ts deleted file mode 100644 index 1802cfa35..000000000 --- a/apps/api/src/app/prisma/prisma-select-args.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { PrismaSelect } from '@paljs/plugins'; -import { GraphQLResolveInfo } from 'graphql'; - -import { PalDefaultFields } from './default-fields'; -import { Prisma } from './generated'; - -export function PrismaSelectArgs( - info: GraphQLResolveInfo, - args: object, - defaultFields?: PalDefaultFields -) { - const result = new PrismaSelect(info, { - defaultFields: defaultFields as any, - dmmf: [Prisma.dmmf], - }).value; - - if (!result.select || Object.keys(result.select).length > 0) { - return { - ...args, - ...result, - }; - } - - return args; -} diff --git a/apps/api/src/app/prisma/prisma-select.service.ts b/apps/api/src/app/prisma/prisma-select.service.ts new file mode 100644 index 000000000..9ff5f3652 --- /dev/null +++ b/apps/api/src/app/prisma/prisma-select.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@nestjs/common'; +import { PrismaSelect } from '@paljs/plugins'; +import { GraphQLResolveInfo } from 'graphql'; + +import { PalDefaultFields } from './default-fields'; +import { Prisma } from './generated'; + +@Injectable() +export class PrismaSelectService { + getArgs(info: GraphQLResolveInfo, args: object, defaultFields?: PalDefaultFields) { + const result = new PrismaSelect(info, { + defaultFields: defaultFields as any, + dmmf: [Prisma.dmmf], + }).value; + + if (!result.select || Object.keys(result.select).length > 0) { + return { + ...args, + ...result, + }; + } + + return args; + } +} diff --git a/apps/api/src/app/prisma/prisma.module.ts b/apps/api/src/app/prisma/prisma.module.ts index 54327ba02..74e01540a 100644 --- a/apps/api/src/app/prisma/prisma.module.ts +++ b/apps/api/src/app/prisma/prisma.module.ts @@ -1,9 +1,10 @@ import { Module } from '@nestjs/common'; +import { PrismaSelectService } from './prisma-select.service'; import { PrismaService } from './prisma.service'; @Module({ - providers: [PrismaService], - exports: [PrismaService], + providers: [PrismaService, PrismaSelectService], + exports: [PrismaService, PrismaSelectService], }) export class PrismaModule {} diff --git a/tools/templates/graphql-resolvers.ts b/tools/templates/graphql-resolvers.ts index 5dc0d8071..82611b19d 100644 --- a/tools/templates/graphql-resolvers.ts +++ b/tools/templates/graphql-resolvers.ts @@ -8,7 +8,7 @@ import { CaslAbility, CaslGuard } from '@zen/nest-auth'; import { GraphQLResolveInfo } from 'graphql'; import { AppAbility, DEFAULT_FIELDS_TOKEN } from '../../auth'; -import { DefaultFields, PrismaSelectArgs, PrismaService, ${name} } from '../../prisma'; +import { DefaultFields, PrismaSelectService, PrismaService, ${name} } from '../../prisma'; import { Aggregate${name}Args, CreateOne${name}Args, @@ -42,7 +42,8 @@ export const typeDefs = null; export class ${name}Resolver { constructor( @Inject(DEFAULT_FIELDS_TOKEN) private readonly defaultFields: DefaultFields, - private readonly prisma: PrismaService + private readonly prisma: PrismaService, + private readonly prismaSelect: PrismaSelectService ) {} @Query() @@ -52,7 +53,7 @@ export class ${name}Resolver { @CaslAbility() ability: AppAbility ) { const record = await this.prisma.${lowercase(name)}.findUnique( - PrismaSelectArgs(info, args, this.defaultFields) + this.prismaSelect.getArgs(info, args, this.defaultFields) ); if (ability.cannot('read', subject('${name}', record as ${name}))) throw new ForbiddenException(); return record; @@ -65,7 +66,7 @@ export class ${name}Resolver { @CaslAbility() ability: AppAbility ) { const record = await this.prisma.${lowercase(name)}.findFirst( - PrismaSelectArgs(info, args, this.defaultFields) + this.prismaSelect.getArgs(info, args, this.defaultFields) ); if (ability.cannot('read', subject('${name}', record as ${name}))) throw new ForbiddenException(); return record; @@ -78,7 +79,7 @@ export class ${name}Resolver { @CaslAbility() ability: AppAbility ) { const records = await this.prisma.${lowercase(name)}.findMany( - PrismaSelectArgs(info, args, this.defaultFields) + this.prismaSelect.getArgs(info, args, this.defaultFields) ); for (const record of records) { if (ability.cannot('read', subject('${name}', record))) throw new ForbiddenException(); @@ -93,7 +94,7 @@ export class ${name}Resolver { @CaslAbility() ability: AppAbility ) { if (ability.cannot('read', '${name}')) throw new ForbiddenException(); - return this.prisma.${lowercase(name)}.count(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.count(this.prismaSelect.getArgs(info, args)); } @Query() @@ -103,7 +104,7 @@ export class ${name}Resolver { @CaslAbility() ability: AppAbility ) { if (ability.cannot('read', '${name}')) throw new ForbiddenException(); - return this.prisma.${lowercase(name)}.aggregate(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.aggregate(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -113,7 +114,7 @@ export class ${name}Resolver { @CaslAbility() ability: AppAbility ) { if (ability.cannot('create', subject('${name}', args.data as any))) throw new ForbiddenException(); - return this.prisma.${lowercase(name)}.create(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.create(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -127,7 +128,7 @@ export class ${name}Resolver { select: this.defaultFields.${name}, }); if (ability.cannot('update', subject('${name}', record as ${name}))) throw new ForbiddenException(); - return this.prisma.${lowercase(name)}.update(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.update(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -143,7 +144,7 @@ export class ${name}Resolver { for (const record of records) { if (ability.cannot('update', subject('${name}', record as ${name}))) throw new ForbiddenException(); } - return this.prisma.${lowercase(name)}.updateMany(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.updateMany(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -162,7 +163,7 @@ export class ${name}Resolver { ) { throw new ForbiddenException(); } - return this.prisma.${lowercase(name)}.upsert(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.upsert(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -176,7 +177,7 @@ export class ${name}Resolver { select: this.defaultFields.${name}, }); if (ability.cannot('delete', subject('${name}', record as ${name}))) throw new ForbiddenException(); - return this.prisma.${lowercase(name)}.delete(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.delete(this.prismaSelect.getArgs(info, args)); } @Mutation() @@ -192,7 +193,7 @@ export class ${name}Resolver { for (const record of records) { if (ability.cannot('delete', subject('${name}', record as ${name}))) throw new ForbiddenException(); } - return this.prisma.${lowercase(name)}.deleteMany(PrismaSelectArgs(info, args)); + return this.prisma.${lowercase(name)}.deleteMany(this.prismaSelect.getArgs(info, args)); } } `;