Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nestjs-prisma

Package Overview
Dependencies
Maintainers
1
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nestjs-prisma - npm Package Compare versions

Comparing version 0.19.0-dev.0 to 0.19.0-dev.1

4

dist/prisma-client-exception.filter.d.ts

@@ -11,4 +11,6 @@ import { ArgumentsHost, ContextType, HttpException, HttpServer } from '@nestjs/common';

constructor(applicationRef?: HttpServer, errorCodesStatusMapping?: ErrorCodesStatusMapping);
catch(exception: Prisma.PrismaClientKnownRequestError, host: ArgumentsHost): void | HttpException | Prisma.PrismaClientKnownRequestError;
catch(exception: Prisma.PrismaClientKnownRequestError | Prisma.NotFoundError, host: ArgumentsHost): void | HttpException | Prisma.PrismaClientKnownRequestError;
private catchClientKnownRequestError;
private catchNotFoundError;
exceptionShortMessage(message: string): string;
}

@@ -29,2 +29,10 @@ "use strict";

catch(exception, host) {
if (exception instanceof client_1.Prisma.PrismaClientKnownRequestError) {
return this.catchClientKnownRequestError(exception, host);
}
else if (exception instanceof client_1.Prisma.NotFoundError) {
return this.catchNotFoundError(exception, host);
}
}
catchClientKnownRequestError(exception, host) {
const statusCode = this.errorCodesStatusMapping[exception.code];

@@ -50,2 +58,16 @@ const message = `[${exception.code}]: ` + this.exceptionShortMessage(exception.message);

}
catchNotFoundError({ message }, host) {
const statusCode = common_1.HttpStatus.NOT_FOUND;
if (host.getType() === 'http') {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
response.status(statusCode).send(JSON.stringify({
statusCode,
message,
}));
}
else if (host.getType() === 'graphql') {
return new common_1.HttpException({ statusCode, message }, statusCode);
}
}
exceptionShortMessage(message) {

@@ -60,3 +82,3 @@ const shortMessage = message.substring(message.indexOf('→'));

PrismaClientExceptionFilter = __decorate([
(0, common_1.Catch)(client_1.Prisma === null || client_1.Prisma === void 0 ? void 0 : client_1.Prisma.PrismaClientKnownRequestError),
(0, common_1.Catch)(client_1.Prisma === null || client_1.Prisma === void 0 ? void 0 : client_1.Prisma.PrismaClientKnownRequestError, client_1.Prisma === null || client_1.Prisma === void 0 ? void 0 : client_1.Prisma.NotFoundError),
__metadata("design:paramtypes", [Object, Object])

@@ -63,0 +85,0 @@ ], PrismaClientExceptionFilter);

{
"name": "nestjs-prisma",
"version": "0.19.0-dev.0",
"version": "0.19.0-dev.1",
"description": "Library and schematics to add Prisma integration to a NestJS application",

@@ -13,3 +13,3 @@ "scripts": {

"changelog": "npx conventional-changelog-cli conventional-changelog -p angular -i ./CHANGELOG.md -s",
"rocket": "npm run build && npm publish --tag dev",
"rocket": "npm run build && npm publish",
"format": "prettier --write \"lib/**/*.ts\" \"schematics/**/*.ts\"",

@@ -46,21 +46,21 @@ "lint": "eslint \"{lib,schematics}/**/*.ts\" --fix"

"devDependencies": {
"@nestjs/common": "9.0.3",
"@nestjs/core": "9.0.3",
"@nestjs/platform-express": "9.0.3",
"@prisma/client": "^4.0.0",
"@nestjs/common": "9.1.2",
"@nestjs/core": "9.1.2",
"@nestjs/platform-express": "9.1.2",
"@prisma/client": "^4.4.0",
"@types/jasmine": "3.8.2",
"@types/node": "^16.11.1",
"@typescript-eslint/eslint-plugin": "5.15.0",
"@typescript-eslint/parser": "5.15.0",
"eslint": "8.11.0",
"@typescript-eslint/eslint-plugin": "5.38.1",
"@typescript-eslint/parser": "5.38.1",
"eslint": "8.24.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-prettier": "4.2.1",
"jasmine": "^3.6.3",
"prettier": "2.7.1",
"prisma": "^4.0.0",
"prisma": "^4.4.0",
"reflect-metadata": "0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.5.6",
"typescript": "~4.7.4"
"rxjs": "^7.5.7",
"typescript": "~4.8.3"
}
}

@@ -24,5 +24,15 @@ <h1 align="center">nestjs-prisma</h1>

Install the library:
### Automatic Install
```bash
Use the [nest add](https://nestjs-prisma.dev/docs/schematics) command to automatically setup the library, Prisma and Docker (optionally):
```sh
nest add nestjs-prisma
```
### Manual Install
Add `nestjs-prisma` library to your [NestJS application](https://docs.nestjs.com/#installation):
```sh
# npm

@@ -35,10 +45,11 @@ npm install nestjs-prisma

or install it automatically using the [schematics command](https://docs.nestjs.com/cli/usages#nest-add):
Furthermore, setup [Prisma](https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgres#set-up-prisma) in your NestJS application, if you haven't already.
```bash
nest add nestjs-prisma
```sh
npm i -D prisma
npm install @prisma/client
npx prisma init
```
Besides installing the library, the [schematics](#schematics) allows to configure Prisma, Docker and even a custom `PrismaService`.
## Basic usage

@@ -58,3 +69,3 @@

Use the `PrismaService` via dependency injection in your controller, resolver, services, guards and more:
Use the `PrismaService` via dependency injection in your controller, resolver, services, guards and more:

@@ -83,480 +94,6 @@ ```ts

### Shutdown Hook
## Documentation
Handle Prisma [shutdown](https://docs.nestjs.com/recipes/prisma#issues-with-enableshutdownhooks) signal to shutdown your Nest application.
Visit our [official documentation](https://nestjs-prisma.dev/docs/installation).
```ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { PrismaService } from 'nestjs-prisma';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// enable shutdown hook
const prismaService: PrismaService = app.get(PrismaService);
prismaService.enableShutdownHooks(app);
await app.listen(3000);
}
bootstrap();
```
### Prisma Middleware
Apply [Prisma Middlewares](https://www.prisma.io/docs/concepts/components/prisma-client/middleware) with `PrismaModule`
```ts
import { Module } from '@nestjs/common';
import { PrismaModule } from 'nestjs-prisma';
@Module({
imports: [
PrismaModule.forRoot({
prismaServiceOptions: {
middlewares: [
async (params, next) => {
// Before query: change params
const result = await next(params);
// After query: result
return result;
},
], // see example loggingMiddleware below
},
}),
],
})
export class AppModule {}
```
Here is an example for using a [Logging middleware](https://www.prisma.io/docs/concepts/components/prisma-client/middleware/logging-middleware).
Create your Prisma Middleware and export it as a `function`
```ts
// src/logging-middleware.ts
import { Prisma } from '@prisma/client';
export function loggingMiddleware(): Prisma.Middleware {
return async (params, next) => {
const before = Date.now();
const result = await next(params);
const after = Date.now();
console.log(
`Query ${params.model}.${params.action} took ${after - before}ms`,
);
return result;
};
}
```
Now import your middleware and add the function into the `middlewares` array.
```ts
import { Module } from '@nestjs/common';
import { PrismaModule } from 'nestjs-prisma';
import { loggingMiddleware } from './logging-middleware';
@Module({
imports: [
PrismaModule.forRoot({
prismaServiceOptions: {
middlewares: [loggingMiddleware()],
},
}),
],
})
export class AppModule {}
```
Try out the built in [Logging Middleware](#logging-middleware).
## Configure `PrismaModule`
`PrismaModule` allows to be used [globally](https://docs.nestjs.com/modules#global-modules) and to pass options to the `PrismaClient`.
```ts
import { Module } from '@nestjs/common';
import { PrismaModule } from 'nestjs-prisma';
@Module({
imports: [
PrismaModule.forRoot({
isGlobal: true,
prismaServiceOptions: {
prismaOptions: { log: ['info'] },
explicitConnect: true,
},
}),
],
})
export class AppModule {}
```
Additionally, `PrismaModule` provides a `forRootAsync` to pass options asynchronously. One option is to use a factory function:
```ts
import { Module } from '@nestjs/common';
import { PrismaModule } from 'nestjs-prisma';
@Module({
imports: [
PrismaModule.forRootAsync({
isGlobal: true,
useFactory: () => ({
prismaOptions: {
log: ['info', 'query'],
},
explicitConnect: false,
}),
}),
],
})
export class AppModule {}
```
You can inject dependencies such as `ConfigModule` to load options from .env files.
```ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { PrismaModule } from 'nestjs-prisma';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
PrismaModule.forRootAsync({
isGlobal: true,
useFactory: async (configService: ConfigService) => {
return {
prismaOptions: {
log: [configService.get('log')],
datasources: {
db: {
url: configService.get('DATABASE_URL'),
},
},
},
explicitConnect: configService.get('explicit'),
};
},
inject: [ConfigService],
}),
],
})
export class AppModule {}
```
Alternatively, you can use a class instead of a factory:
```ts
import { Module } from '@nestjs/common';
import { PrismaModule } from 'nestjs-prisma';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
PrismaModule.forRootAsync({
isGlobal: true,
useClass: PrismaConfigService,
}),
],
})
export class AppModule {}
```
Create the `PrismaConfigService` and extend it with the `PrismaOptionsFactory`
```ts
import { Injectable } from '@nestjs/common';
import { PrismaOptionsFactory, PrismaServiceOptions } from 'nestjs-prisma';
@Injectable()
export class PrismaConfigService implements PrismaOptionsFactory {
constructor() {
// TODO inject any other service here like the `ConfigService`
}
createPrismaOptions(): PrismaServiceOptions | Promise<PrismaServiceOptions> {
return {
prismaOptions: {
log: ['info', 'query'],
},
explicitConnect: true,
};
}
}
```
## PrismaClientExceptionFilter
`nestjs-prisma` provides a `PrismaClientExceptionFilter` to catch unhandled [PrismaClientKnownRequestError](https://www.prisma.io/docs/reference/api-reference/error-reference#prisma-client-query-engine) and returns different HttpStatus codes instead of `500 Internal server error`. The exception filter supports REST (Express/Fasitfy) and GraphQL.
To use the filter you have the following two options.
1. Instantiate the filter in your `main.ts` and pass the `HttpAdapterHost`
```ts
//src/main.ts
import { ValidationPipe } from '@nestjs/common';
import { HttpAdapterHost, NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { PrismaClientExceptionFilter } from 'nestjs-prisma';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const { httpAdapter } = app.get(HttpAdapterHost);
app.useGlobalFilters(new PrismaClientExceptionFilter(httpAdapter));
await app.listen(3000);
}
bootstrap();
```
Optionally, provide your own error code mapping via the constructor:
```ts
//src/main.ts
import { ValidationPipe } from '@nestjs/common';
import { HttpAdapterHost, NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { PrismaClientExceptionFilter } from 'nestjs-prisma';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const { httpAdapter } = app.get(HttpAdapterHost);
app.useGlobalFilters(
new PrismaClientExceptionFilter(httpAdapter, {
// Prisma Error Code: HTTP Status Response
P2000: HttpStatus.BAD_REQUEST,
P2002: HttpStatus.CONFLICT,
P2025: HttpStatus.NOT_FOUND,
}),
);
await app.listen(3000);
}
bootstrap();
```
See the list of [Prisma CLient Errors](https://www.prisma.io/docs/reference/api-reference/error-reference#prisma-client-query-engine) in the Prisma docs.
This will override the default error code mapping:
| Error Code |  Http Status |
| ----------------------------------------------------------------------------------------------------------------- | ----------------- |
| P2000 - "The provided value for the column is too long for the column's type. Column: {column_name}" | Bad Request - 400 |
| P2002 - "Unique constraint failed on the {constraint}" | Conflict - 409 |
| P2025 - "An operation failed because it depends on one or more records that were required but not found. {cause}" | Not Found - 404 |
2. Use `APP_FILTER` token in any module
```ts
//src/app.module.ts
import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { PrismaClientExceptionFilter } from 'nestjs-prisma';
@Module({
providers: [
{
provide: APP_FILTER,
useClass: PrismaClientExceptionFilter,
},
],
})
export class AppModule {}
```
## Logging Middleware
`nestjs-prisma` provides a `loggingMiddleware` to log the query execution time.
```ts
import { Module } from '@nestjs/common';
import { PrismaModule, loggingMiddleware } from 'nestjs-prisma';
@Module({
imports: [
PrismaModule.forRoot({
prismaServiceOptions: {
middlewares: [loggingMiddleware()],
},
}),
],
})
export class AppModule {}
```
The default log messages are looking as follows.
```
Prisma Query User.findUnique took 6ms
Prisma Query User.create took 4ms
Prisma Query Product.findMany took 10ms
```
Customize the logging middleware by providing your own `logger`, `logLevel` and `logMessage`.
```ts
import { Module } from '@nestjs/common';
import { PrismaModule, loggingMiddleware, QueryInfo } from 'nestjs-prisma';
@Module({
imports: [
PrismaModule.forRoot({
prismaServiceOptions: {
middlewares: [
loggingMiddleware({
logger: new Logger('PrismaMiddleware'),
logLevel: 'log', // default is `debug`
logMessage: (query: QueryInfo) =>
`[Prisma Query] ${query.model}.${query.action} - ${query.executionTime}ms`,
}),
],
},
}),
],
})
export class AppModule {}
```
The customized log messages are looking as follows.
```
[Nest] 51348 - 29/07/2022, 10:08:41 LOG [PrismaMiddleware] [Prisma Query] User.findUnique - 4ms
[Nest] 51348 - 29/07/2022, 10:08:50 LOG [PrismaMiddleware] [Prisma Query] User.create - 6ms
[Nest] 51348 - 29/07/2022, 10:09:13 LOG [PrismaMiddleware] [Prisma Query] Product.findMany - 9ms
```
Change the log level from your `.env` file using the [@nestjs/config](https://docs.nestjs.com/techniques/configuration) module. Add `PRISMA_QUERY_LOG_LEVEL` to your `.env` file with one of the log levels (`log`, `debug`, `warn`, `error`).
```ts
import { Module } from '@nestjs/common';
import { PrismaModule, loggingMiddleware, QueryInfo } from 'nestjs-prisma';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
PrismaModule.forRootAsync({
useFactory: (config: ConfigService) => {
return {
middlewares: [
loggingMiddleware({
logger: new Logger('PrismaMiddleware'),
logLevel: config.get('PRISMA_QUERY_LOG_LEVEL'),
}),
],
prismaOptions: { log: ['warn', 'error'] },
};
},
inject: [ConfigService],
}),
],
})
export class AppModule {}
```
## Schematics
The schematics automatically performs [additional steps](https://github.com/notiz-dev/nestjs-prisma/blob/main/schematics/nestjs-prisma/index.ts#L35-L42) to configure Prisma and Docker in your project.
- Initialize Prisma `npx prisma init --datasource-provider postgres|...`
- Add Prisma npm scripts to your `package.json`
- Add seed script for Prisma
- Generate custom `PrismaService` and `PrismaModule` (optionally)
- Add `Dockerfile` and `docker-compose.yml` (optionally)
- Excludes `prisma` directory from build via `tsconfig.build.json`
Example output of the schematics:
```bash
✔ Package installation in progress... ☕
Starting library setup...
? Which datasource provider do you want to use for `prisma init`? postgresql
? Do you like to Dockerize your application? (Supports postgresql and mysql) Yes
✅️ Added prisma@latest
✅️ Added @prisma/client@latest
✅️ Added Prisma scripts [6]
✅️ Added Prisma Seed script
✅️ Added Docker file
✅️ Added Docker Compose and .env
✅️ Add "prisma" directory to "excludes" in tsconfig.build.json
CREATE .dockerignore (42 bytes)
CREATE Dockerfile (455 bytes)
CREATE .env (642 bytes)
CREATE docker-compose.yml (497 bytes)
UPDATE package.json (2754 bytes)
UPDATE tsconfig.build.json (130 bytes)
✔ Packages installed successfully.
✔ Packages installed successfully.
✅️ Initialized Prisma - Datasource postgresql
```
### Generate **custom** `PrismaService` and `PrismaModule`
```bash
nest add nestjs-prisma --addPrismaService
```
Add the flag `--addPrismaService` if you like to generate your own `PrismaService` and `PrismaModule` for further customizations. Add `PrismaModule` to the `imports` section in your `AppModule` or other modules to gain access to `PrismaService`.
```ts
import { Module } from '@nestjs/common';
import { PrismaModule } from './prisma/prisma.module';
@Module({
imports: [PrismaModule],
})
export class AppModule {}
```
> **Note**: It is safe to remove `nestjs-prisma` as dependency otherwise you have two import suggestions for `PrismaService` and `PrismaModule`.
### Schematic options
All available options to passe to the schematic command:
| Flag | Description | Type | Default |
| ------------------------ | ----------------------------------------------------------------------- | --------- | -------- |
| `datasourceProvider` | Specifies the datasource provider for prisma init and docker. | `boolean` | Prompted |
| `addDocker` | Create a Dockerfile and docker-compose.yaml. | `boolean` | Prompted |
| `addPrismaService` | Create a Prisma service extending the Prisma Client and module. | `boolean` | `false` |
| `dockerNodeImageVersion` | Node version for the builder and runner image. | `string` | `14` |
| `name` | The name for the Prisma service extending the Prisma Client and module. | `string` | `Prisma` |
| `prismaVersion` | The Prisma version to be installed. | `string` | `latest` |
| `skipInstall` | Skip installing dependency packages. | `boolean` | `false` |
| `skipPrismaInit` | Skip initializing Prisma. | `boolean` | `false` |
You can pass additional flags to customize the schematic. For example, if you want to install a different version for **Prisma** use `--prismaVersion` flag:
```bash
nest add nestjs-prisma --prismaVersion 3.2.1
```
If you want to skip installing dependencies use `--skipInstall` flag:
```bash
nest add nestjs-prisma --skipInstall
```
Add `Dockerfile` and `docker-compose.yaml`, you can even use a different `node` version (`14-alpine` or `16`).
> Currently uses **PostgreSQL** as a default database in `docker-compose.yaml`.
```bash
nest add nestjs-prisma --addDocker --dockerNodeImageVersion 14-alpine
```
## Contributing

@@ -566,5 +103,7 @@

The code is split up into two directories:
The code is split up into three directories:
```
+-- docs
+-- examples
+-- lib

@@ -574,3 +113,8 @@ +-- schematics

The `docs` directory contains an astro website and the [docs content](./docs/src/pages/docs) pages.
The `examples` directory contains example applications.
The `lib` directory contains everything exposed by `nestjs-prisma` as a library.
The `schematics` directory contains the blue prints for installing the library with the schematic command.

@@ -577,0 +121,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc