Functional Programming with NestJS, Prisma.
immutable, pure, stateless.
A production ready typescript backend repository utilized those libraries:
- NestJS : A progressive Node.js framework
- Prisma : Next-generation Node.js and TypeScript ORM
- eslint-plugin-functional disable mutation and promote functional programming lint.
- Integration Prisma with NestJS.
- Generate Prisma Module and using DI.
- First My Database Query
Adding Prisma to the Nest project.
First, install prisma
CLI in dev dependency, @prisma/client
in dependency.
Init command creates new ```prisma`` directory.
Command
yarn add -D prisma npx prisma init yarn add @prisma/client
Use this prisma schema example.
schema.prisma
file is declared a PSL(Prisma Schema Language).
For this repository, you'll create a community
model.
Adding the community
model in schema.prisma
.
model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) email String @unique name String? role Role @default(USER) posts Post[] } model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt published Boolean @default(false) title String @db.VarChar(255) author User? @relation(fields: [authorId], references: [id]) authorId Int? } enum Role { USER ADMIN }
Migration your Postgres database file for your dev environment using Prisma Migrate.
Use the prisma migrate dev
command to complete your first prisma migration.
Command
npx prisma migrate dev
Then, You maybe have new directory (prisma/migrations) for migration history.
Prisma set up complete and can access database.
To integration prisma into nestJS, generate a module and service used prismaClient.
Command
nest generate module prisma nest generate service prisma
Q1. How to use Prisma Service
inside Prisma Module
in another module ?
A1. Add Prisma Service
to module export list and DI Prisma Module
in other module.
If use @Global()
decorator for Prisma Module
, Only import the Prisma Module
once.
Prisma Module
// src/prisma/prisma.module.ts import { Global, Module } from '@nestjs/common'; import { PrismaService } from './prisma.service'; @Global() // generate Global Module @Module({ providers: [PrismaService], exports: [PrismaService], // for DI }) export class PrismaModule {}
Prisma Service
// src/prisma/prisma.service.ts import { Injectable } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient { constructor() { super(); } }
Command
nest generate module user nest generate service user nest generate controller user
Use ```Prisma Service`` in user repository.
src/user/user.repository.ts
import { Injectable } from '@nestjs/common'; import { PrismaService } from '@prismaModule/prisma.service'; @Injectable() export class UserRepository { constructor(private prisma: PrismaService) {} getUsers() { return this.prisma.user.findMany(); } }
PrismaClient
has two connect database mode.
- lazy : connect for the first request
- explicit : call
prisma.$connect()
assignment - Implement expllict prisma connect for nestJS LifeCycle OnModuleInit, OnModuleDestory.
- Set
PrismaClient
log level.
solution
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { constructor() { super({ log: [ { emit: 'stdout', level: 'query' }, { emit: 'stdout', level: 'error' }, ], }); } async onModuleInit() { await this.$connect(); } async onModuleDestroy() { await this.$disconnect(); } }
- Add prisma command in package.json.
command
"prisma":{ "seed": "ts-node prisma/seed/index.ts" },
- Add seed Data to the prisma/seed directory using Prisma.validator.
code
import { Prisma } from '@prisma/client'; export const users = Prisma.validator<Prisma.UserCreateManyArgs>()({ data: [ { name: 'y0on2q', email: '[email protected]', active: 1, role: 'ADMIN', }, { name: 'currying', email: '[email protected]', active: 0, role: 'USER', }, { name: 'monad', email: 'monad@monad,com', active: 1, role: 'USER', }, ], });
- Add main seed file to the prisma/seed directory.
code
import { PrismaClient } from '@prisma/client'; import { users } from './user.seed'; const prisma = new PrismaClient(); const main = async () => { await prisma.user.createMany(users); }; main() .catch(e => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });
- Run Prisma db seed command
command
npx prisma db seed
- Run Prisma studio and view seeding data.
command
npx prisma studio