nestjs-query
- DRY – querying, sorting and paging is handled by this lib.
- Easier time with CRUD operations in GraphQL.
- No n+1 problem.
- “Connections” compliant pagination schema.
nestjs-query
+ TypeORM + ExpressJS + PostgreSQL
-
pnpm add @ptc-org/nestjs-query-core @ptc-org/nestjs-query-graphql @ptc-org/nestjs-query-typeorm @nestjs/typeorm @nestjs/common @nestjs/graphql @nestjs/apollo @nestjs/config @apollo/server graphql graphql-subscriptions class-transformer class-validator dataloader typeorm pg
-
cd typeorm/apps/borprobe-nest nest g resource alert-type nest g resource alert
-
Open your
*.entity.ts
and modify it to use TypeORM and acts as youObject
type.[!TIP]
It’s always easy to merge your Custom Object Type defined for GraphQL with your persistence layer (in our case the entity we need for TypeORM). But it is no that easy to decouple them. But since here I am experimenting I will merge them from the get go. But you might wanna think twice before jumping into coding in a real world project.
- For create we can use the one generated by
@ptc-org/nestjs-query-graphql
but it will have things likeid
,createdAt
, andupdatedAt
which ain’t required. So let’s modifydto/*.input.ts
to reflect our desired DTO. - Configure your NestJS app as it is described here.
- Config your TypeORM according to NestJS doc.
-
Config your
NestjsQueryGraphQLModule
for each module:import { Module } from "@nestjs/common"; import { NestjsQueryGraphQLModule } from "@ptc-org/nestjs-query-graphql"; import { NestjsQueryTypeOrmModule } from "@ptc-org/nestjs-query-typeorm"; import { AlertTypeResolver } from "./alert-type.resolver"; import { AlertTypeService } from "./alert-type.service"; import { CreateAlertTypeInput } from "./dto/create-alert-type.input"; import { AlertType } from "./entities/alert-type.entity"; @Module({ imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [NestjsQueryTypeOrmModule.forFeature([AlertType])], resolvers: [ { EntityClass: AlertType, DTOClass: AlertType, CreateDTOClass: CreateAlertTypeInput, }, ], }), ], providers: [AlertTypeResolver, AlertTypeService], }) export class AlertTypeModule {}
[!NOTE]
No need for
TypeOrmModule.forFeature([AlertType]),
sinceNestjsQueryTypeOrmModule
will register your entity with TypeORM. - Then we need to take care of
AppModule
, import and config:ConfigModule
.TypeOrmModule
.GraphQLModule
.AlertModule
.AlertTypeModule
.
-
Generate migration for TypeORM:
nx migration:gen botprobe-nest --name init
-
Run the generated migrations:
nx migration:run botprobe-nest
[!TIP]
Create new empty migration with:
nx migration:create botprobe-nest --name init
BTW I have written a post for migration in TypeORM in dev.to here.
Extracting User ID off of the Decoded JWT Token
-
Create
AuthModule
:nest g module auth nest g service auth nest g guard auth nest g decorator auth
- Rename the newly created decorator to
get-user.decorator.ts
and move it to adecorators
directory. - Rename the guard to
jwt-auth.guard.ts
and move it to aguards
folder. - Same for service, rename it to
auth.service.ts
and move it toservices
directory. - Create a new directory called
strategies
and inside it create a file calledjwt.strategy.ts
.
- Rename the newly created decorator to
-
We need to config JWT and Auth module. thus we’re gonna create configs:
auth.config.ts
.jwt-module.config.ts
.
-
Add the guard globally to a module if you need to protect the every resolver in that module:
@Module({ imports: [ NestjsQueryGraphQLModule.forFeature({ resolvers: [ { + guards: [GraphqlJwtAuthGuard], }, ], }), ], }) export class AlertModule {}
-
Create a new hook
apps/botprobe-nest/src/alert/hooks/before-create-alert.hook.ts
:https://github.com/kasir-barati/nestjs-materials/blob/main/typeorm/apps/botprobe-nest/src/alert/hooks/before-create-alert.hook.ts
This hook will be executed before the request reaching resolver. Thus we can inside it easily access context and extract user ID from it, and finally attach it to the
input
.