sungjin

Add Nestjs Backend Server with Prisma setup, User Authentication

1 +# Environment variables declared in this file are automatically made available to Prisma.
2 +# See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables
3 +
4 +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server and MongoDB (Preview).
5 +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
6 +
7 +DATABASE_URL="postgresql://postgres:12345@localhost:5432/postgres"
...\ No newline at end of file ...\ No newline at end of file
1 +module.exports = {
2 + parser: '@typescript-eslint/parser',
3 + parserOptions: {
4 + project: 'tsconfig.json',
5 + sourceType: 'module',
6 + },
7 + plugins: ['@typescript-eslint/eslint-plugin'],
8 + extends: [
9 + 'plugin:@typescript-eslint/recommended',
10 + 'plugin:prettier/recommended',
11 + ],
12 + root: true,
13 + env: {
14 + node: true,
15 + jest: true,
16 + },
17 + ignorePatterns: ['.eslintrc.js'],
18 + rules: {
19 + '@typescript-eslint/interface-name-prefix': 'off',
20 + '@typescript-eslint/explicit-function-return-type': 'off',
21 + '@typescript-eslint/explicit-module-boundary-types': 'off',
22 + '@typescript-eslint/no-explicit-any': 'off',
23 + },
24 +};
1 +# compiled output
2 +/dist
3 +/node_modules
4 +
5 +# Logs
6 +logs
7 +*.log
8 +npm-debug.log*
9 +pnpm-debug.log*
10 +yarn-debug.log*
11 +yarn-error.log*
12 +lerna-debug.log*
13 +
14 +# OS
15 +.DS_Store
16 +
17 +# Tests
18 +/coverage
19 +/.nyc_output
20 +
21 +# IDEs and editors
22 +/.idea
23 +.project
24 +.classpath
25 +.c9/
26 +*.launch
27 +.settings/
28 +*.sublime-workspace
29 +
30 +# IDE - VSCode
31 +.vscode/*
32 +!.vscode/settings.json
33 +!.vscode/tasks.json
34 +!.vscode/launch.json
35 +!.vscode/extensions.json
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "singleQuote": true,
3 + "trailingComma": "all"
4 +}
...\ No newline at end of file ...\ No newline at end of file
1 +<p align="center">
2 + <a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo_text.svg" width="320" alt="Nest Logo" /></a>
3 +</p>
4 +
5 +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 +[circleci-url]: https://circleci.com/gh/nestjs/nest
7 +
8 + <p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
9 + <p align="center">
10 +<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
11 +<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
12 +<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
13 +<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
14 +<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
15 +<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
16 +<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
17 +<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
18 + <a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
19 + <a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
20 + <a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
21 +</p>
22 + <!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
23 + [![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
24 +
25 +## Description
26 +
27 +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 +
29 +## Installation
30 +
31 +```bash
32 +$ npm install
33 +```
34 +
35 +## Running the app
36 +
37 +```bash
38 +# development
39 +$ npm run start
40 +
41 +# watch mode
42 +$ npm run start:dev
43 +
44 +# production mode
45 +$ npm run start:prod
46 +```
47 +
48 +## Test
49 +
50 +```bash
51 +# unit tests
52 +$ npm run test
53 +
54 +# e2e tests
55 +$ npm run test:e2e
56 +
57 +# test coverage
58 +$ npm run test:cov
59 +```
60 +
61 +## Support
62 +
63 +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64 +
65 +## Stay in touch
66 +
67 +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 +- Website - [https://nestjs.com](https://nestjs.com/)
69 +- Twitter - [@nestframework](https://twitter.com/nestframework)
70 +
71 +## License
72 +
73 +Nest is [MIT licensed](LICENSE).
1 +{
2 + "collection": "@nestjs/schematics",
3 + "sourceRoot": "src"
4 +}
This diff could not be displayed because it is too large.
1 +{
2 + "name": "learn-in-web-backend",
3 + "version": "0.0.1",
4 + "description": "",
5 + "author": "",
6 + "private": true,
7 + "license": "UNLICENSED",
8 + "scripts": {
9 + "prebuild": "rimraf dist",
10 + "build": "nest build",
11 + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 + "start": "nest start",
13 + "start:dev": "nest start --watch",
14 + "start:debug": "nest start --debug --watch",
15 + "start:prod": "node dist/main",
16 + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 + "test": "jest",
18 + "test:watch": "jest --watch",
19 + "test:cov": "jest --coverage",
20 + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 + "test:e2e": "jest --config ./test/jest-e2e.json",
22 + "migrate:dev": "npx prisma migrate dev",
23 + "migrate:dev:create": "npx prisma migrate dev --create-only",
24 + "migrate:deploy": "npx prisma migrate deploy",
25 + "prisma:generate": "npx prisma generate",
26 + "prisma:studio": "npx prisma studio",
27 + "prisma:seed": "npx prisma db seed --preview-feature"
28 + },
29 + "dependencies": {
30 + "@nestjs/common": "^8.0.0",
31 + "@nestjs/core": "^8.0.0",
32 + "@nestjs/jwt": "^8.0.0",
33 + "@nestjs/platform-express": "^8.0.0",
34 + "@prisma/client": "^3.4.2",
35 + "bcrypt": "^5.0.1",
36 + "nestjs-prisma": "^0.14.3",
37 + "reflect-metadata": "^0.1.13",
38 + "rimraf": "^3.0.2",
39 + "rxjs": "^7.2.0"
40 + },
41 + "devDependencies": {
42 + "@nestjs/cli": "^8.0.0",
43 + "@nestjs/schematics": "^8.0.0",
44 + "@nestjs/testing": "^8.0.0",
45 + "@types/bcrypt": "^5.0.0",
46 + "@types/express": "^4.17.13",
47 + "@types/jest": "^27.0.1",
48 + "@types/node": "^16.0.0",
49 + "@types/supertest": "^2.0.11",
50 + "@typescript-eslint/eslint-plugin": "^5.0.0",
51 + "@typescript-eslint/parser": "^5.0.0",
52 + "eslint": "^8.0.1",
53 + "eslint-config-prettier": "^8.3.0",
54 + "eslint-plugin-prettier": "^4.0.0",
55 + "jest": "^27.2.5",
56 + "prettier": "^2.3.2",
57 + "prisma": "latest",
58 + "source-map-support": "^0.5.20",
59 + "supertest": "^6.1.3",
60 + "ts-jest": "^27.0.3",
61 + "ts-loader": "^9.2.3",
62 + "ts-node": "^10.0.0",
63 + "tsconfig-paths": "^3.10.1",
64 + "typescript": "^4.3.5"
65 + },
66 + "jest": {
67 + "moduleFileExtensions": [
68 + "js",
69 + "json",
70 + "ts"
71 + ],
72 + "rootDir": "src",
73 + "testRegex": ".*\\.spec\\.ts$",
74 + "transform": {
75 + "^.+\\.(t|j)s$": "ts-jest"
76 + },
77 + "collectCoverageFrom": [
78 + "**/*.(t|j)s"
79 + ],
80 + "coverageDirectory": "../coverage",
81 + "testEnvironment": "node"
82 + },
83 + "prisma": {
84 + "seed": "ts-node prisma/seed.ts"
85 + }
86 +}
1 +-- CreateEnum
2 +CREATE TYPE "Level" AS ENUM ('LOW', 'MEDIUM', 'HIGH');
3 +
4 +-- CreateEnum
5 +CREATE TYPE "Role" AS ENUM ('USER', 'ADMIN');
6 +
7 +-- CreateTable
8 +CREATE TABLE "User" (
9 + "id" UUID NOT NULL DEFAULT gen_random_uuid(),
10 + "email" TEXT NOT NULL,
11 + "name" TEXT NOT NULL,
12 + "password" TEXT NOT NULL,
13 + "role" "Role" NOT NULL DEFAULT E'USER',
14 +
15 + CONSTRAINT "User_pkey" PRIMARY KEY ("id")
16 +);
17 +
18 +-- CreateTable
19 +CREATE TABLE "Post" (
20 + "id" UUID NOT NULL DEFAULT gen_random_uuid(),
21 + "title" TEXT NOT NULL,
22 + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
23 + "private" BOOLEAN NOT NULL DEFAULT true,
24 + "authorId" UUID NOT NULL,
25 + "level" "Level" NOT NULL DEFAULT E'MEDIUM',
26 + "content" TEXT NOT NULL,
27 +
28 + CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
29 +);
30 +
31 +-- CreateTable
32 +CREATE TABLE "Comment" (
33 + "id" UUID NOT NULL DEFAULT gen_random_uuid(),
34 + "content" TEXT NOT NULL,
35 + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
36 + "authorId" UUID NOT NULL,
37 + "postId" UUID NOT NULL,
38 +
39 + CONSTRAINT "Comment_pkey" PRIMARY KEY ("id")
40 +);
41 +
42 +-- CreateIndex
43 +CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
44 +
45 +-- AddForeignKey
46 +ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
47 +
48 +-- AddForeignKey
49 +ALTER TABLE "Comment" ADD CONSTRAINT "Comment_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
50 +
51 +-- AddForeignKey
52 +ALTER TABLE "Comment" ADD CONSTRAINT "Comment_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
1 +/*
2 + Warnings:
3 +
4 + - A unique constraint covering the columns `[id]` on the table `Comment` will be added. If there are existing duplicate values, this will fail.
5 + - A unique constraint covering the columns `[id]` on the table `Post` will be added. If there are existing duplicate values, this will fail.
6 + - A unique constraint covering the columns `[id]` on the table `User` will be added. If there are existing duplicate values, this will fail.
7 +
8 +*/
9 +-- CreateIndex
10 +CREATE UNIQUE INDEX "Comment_id_key" ON "Comment"("id");
11 +
12 +-- CreateIndex
13 +CREATE UNIQUE INDEX "Post_id_key" ON "Post"("id");
14 +
15 +-- CreateIndex
16 +CREATE UNIQUE INDEX "User_id_key" ON "User"("id");
1 +# Please do not edit this file manually
2 +# It should be added in your version-control system (i.e. Git)
3 +provider = "postgresql"
...\ No newline at end of file ...\ No newline at end of file
1 +// This is your Prisma schema file,
2 +// learn more about it in the docs: https://pris.ly/d/prisma-schema
3 +
4 +generator client {
5 + provider = "prisma-client-js"
6 +}
7 +
8 +datasource db {
9 + provider = "postgres"
10 + url = env("DATABASE_URL")
11 +}
12 +
13 +model User {
14 + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid @unique
15 + email String @unique
16 + name String
17 + password String
18 + role Role @default(USER)
19 +
20 + posts Post[]
21 + comments Comment[]
22 +}
23 +
24 +model Post {
25 + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid @unique
26 + title String
27 + createdAt DateTime @default(now())
28 + private Boolean @default(true)
29 + author User @relation(fields: [authorId], references: [id])
30 + authorId String @db.Uuid
31 + level Level @default(MEDIUM)
32 + content String
33 +
34 + comments Comment[]
35 +}
36 +
37 +model Comment {
38 + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid @unique
39 + content String
40 + createdAt DateTime @default(now())
41 + author User @relation(fields: [authorId], references: [id])
42 + authorId String @db.Uuid
43 + post Post @relation(fields: [postId], references: [id])
44 + postId String @db.Uuid
45 +}
46 +
47 +enum Level {
48 + LOW
49 + MEDIUM
50 + HIGH
51 +}
52 +
53 +enum Role {
54 + USER
55 + ADMIN
56 +}
1 +import { Test, TestingModule } from '@nestjs/testing';
2 +import { AppController } from './app.controller';
3 +import { AppService } from './app.service';
4 +
5 +describe('AppController', () => {
6 + let appController: AppController;
7 +
8 + beforeEach(async () => {
9 + const app: TestingModule = await Test.createTestingModule({
10 + controllers: [AppController],
11 + providers: [AppService],
12 + }).compile();
13 +
14 + appController = app.get<AppController>(AppController);
15 + });
16 +
17 + describe('root', () => {
18 + it('should return "Hello World!"', () => {
19 + expect(appController.getHello()).toBe('Hello World!');
20 + });
21 + });
22 +});
1 +import { Controller, Get } from '@nestjs/common';
2 +import { AppService } from './app.service';
3 +
4 +@Controller()
5 +export class AppController {
6 + constructor(private readonly appService: AppService) {}
7 +
8 + @Get()
9 + getHello(): string {
10 + return this.appService.getHello();
11 + }
12 +}
1 +import { Module } from '@nestjs/common';
2 +import { AppController } from './app.controller';
3 +import { AppService } from './app.service';
4 +import { PrismaModule } from 'nestjs-prisma';
5 +import { PrismaService } from './prisma.service';
6 +import { AuthModule } from './auth/auth.module';
7 +import { Auth } from './auth';
8 +
9 +@Module({
10 + imports: [PrismaModule, AuthModule],
11 + controllers: [AppController],
12 + providers: [AppService, PrismaService, Auth],
13 +})
14 +export class AppModule {}
1 +import { Injectable } from '@nestjs/common';
2 +
3 +@Injectable()
4 +export class AppService {
5 + getHello(): string {
6 + return 'Hello World!';
7 + }
8 +}
1 +import { Test, TestingModule } from '@nestjs/testing';
2 +import { Auth } from './auth';
3 +
4 +describe('Auth', () => {
5 + let provider: Auth;
6 +
7 + beforeEach(async () => {
8 + const module: TestingModule = await Test.createTestingModule({
9 + providers: [Auth],
10 + }).compile();
11 +
12 + provider = module.get<Auth>(Auth);
13 + });
14 +
15 + it('should be defined', () => {
16 + expect(provider).toBeDefined();
17 + });
18 +});
1 +import { Injectable } from '@nestjs/common';
2 +
3 +@Injectable()
4 +export class Auth {}
1 +import { Test, TestingModule } from '@nestjs/testing';
2 +import { AuthController } from './auth.controller';
3 +
4 +describe('AuthController', () => {
5 + let controller: AuthController;
6 +
7 + beforeEach(async () => {
8 + const module: TestingModule = await Test.createTestingModule({
9 + controllers: [AuthController],
10 + }).compile();
11 +
12 + controller = module.get<AuthController>(AuthController);
13 + });
14 +
15 + it('should be defined', () => {
16 + expect(controller).toBeDefined();
17 + });
18 +});
1 +import { Body, Controller, Post } from '@nestjs/common';
2 +import { AuthService } from './auth.service';
3 +
4 +@Controller('auth')
5 +export class AuthController {
6 + constructor(private readonly AuthService: AuthService) {}
7 +
8 + @Post('signup')
9 + signUp(@Body() body) {
10 + return this.AuthService.createUser(body.name, body.email, body.password);
11 + }
12 +
13 + @Post('signin')
14 + signIn(@Body() body) {
15 + return this.AuthService.login(body.email, body.password);
16 + }
17 +
18 + @Post('refresh')
19 + refresh(@Body() body) {
20 + return this.AuthService.refreshTokens(body.token);
21 + }
22 +
23 + @Post('validate')
24 + validate(@Body() body) {
25 + return this.AuthService.validateUser(body.token);
26 + }
27 +}
1 +import { Module } from '@nestjs/common';
2 +import { AuthController } from './auth.controller';
3 +import { PrismaModule } from 'nestjs-prisma';
4 +import { AuthService } from './auth.service';
5 +import { JwtModule, JwtService } from '@nestjs/jwt';
6 +
7 +@Module({
8 + imports: [PrismaModule, JwtModule.register({ secret: 'secret' })],
9 + controllers: [AuthController],
10 + providers: [AuthService],
11 +})
12 +export class AuthModule {}
1 +import { Test, TestingModule } from '@nestjs/testing';
2 +import { AuthService } from './auth.service';
3 +
4 +describe('AuthService', () => {
5 + let service: AuthService;
6 +
7 + beforeEach(async () => {
8 + const module: TestingModule = await Test.createTestingModule({
9 + providers: [AuthService],
10 + }).compile();
11 +
12 + service = module.get<AuthService>(AuthService);
13 + });
14 +
15 + it('should be defined', () => {
16 + expect(service).toBeDefined();
17 + });
18 +});
1 +import {
2 + BadRequestException,
3 + Injectable,
4 + NotFoundException,
5 +} from '@nestjs/common';
6 +import { PrismaService } from 'nestjs-prisma';
7 +import { JwtService } from '@nestjs/jwt';
8 +import { User } from '@prisma/client';
9 +import * as bcrypt from 'bcrypt';
10 +
11 +@Injectable()
12 +export class AuthService {
13 + constructor(
14 + private readonly prisma: PrismaService,
15 + private readonly jwtService: JwtService,
16 + ) {}
17 +
18 + async createUser(name: string, email: string, password: string) {
19 + const hashedPassword = await bcrypt.hash(password, 10);
20 + const user = await this.prisma.user.create({
21 + data: {
22 + name,
23 + email,
24 + password: hashedPassword,
25 + },
26 + });
27 + return this.generateTokens(user);
28 + }
29 +
30 + async login(email: string, password: string) {
31 + const user = await this.prisma.user.findUnique({ where: { email } });
32 +
33 + if (!user) {
34 + throw new NotFoundException('No user found');
35 + }
36 +
37 + const passwordMatch = await bcrypt.compare(password, user.password);
38 +
39 + if (!passwordMatch) {
40 + throw new BadRequestException('Wrong password');
41 + }
42 +
43 + return this.generateTokens(user);
44 + }
45 +
46 + validateUser(userId: string): Promise<User> {
47 + return this.prisma.user.findUnique({ where: { id: userId } });
48 + }
49 +
50 + getUserFromToken(token: string) {
51 + const id = this.jwtService.decode(token)['id'];
52 + return this.prisma.user.findUnique({ where: { id: id } });
53 + }
54 +
55 + generateTokens(user: User) {
56 + const payload = {
57 + id: user.id,
58 + name: user.name,
59 + email: user.email,
60 + };
61 + return {
62 + access_token: this.jwtService.sign(payload),
63 + };
64 + }
65 +
66 + async refreshTokens(token: string) {
67 + const _user = await this.getUserFromToken(token);
68 + const user = {
69 + id: _user.id,
70 + name: _user.name,
71 + email: _user.email,
72 + password: _user.password,
73 + role: _user.role,
74 + };
75 + return this.generateTokens(user);
76 + }
77 +
78 + async deleteUser(userId: string) {
79 + return this.prisma.user.delete({ where: { id: userId } });
80 + }
81 +
82 + async updateUser(token: string, name: string, email: string) {
83 + return this.prisma.user.update({
84 + where: { id: (await this.getUserFromToken(token)).id },
85 + data: {
86 + name,
87 + email,
88 + },
89 + });
90 + }
91 +
92 + async updatePassword(token: string, password: string) {
93 + const hashedPassword = await bcrypt.hash(password, 10);
94 + return this.prisma.user.update({
95 + where: { id: (await this.getUserFromToken(token)).id },
96 + data: {
97 + password: hashedPassword,
98 + },
99 + });
100 + }
101 +
102 + async AmIAdmin(token: string) {
103 + const user = await this.prisma.user.findUnique({
104 + where: { id: (await this.getUserFromToken(token)).id },
105 + });
106 + if (user.role === 'ADMIN') {
107 + return true;
108 + } else {
109 + return false;
110 + }
111 + }
112 +
113 + async _changeUserPassword(
114 + token: string,
115 + userId: string,
116 + name?: string,
117 + email?: string,
118 + password?: string,
119 + ) {
120 + if (this.AmIAdmin(token)) {
121 + const hashedPassword = await bcrypt.hash(password, 10);
122 + return this.prisma.user.update({
123 + where: { id: userId },
124 + data: {
125 + name: name,
126 + email: email,
127 + password: hashedPassword,
128 + },
129 + });
130 + } else {
131 + throw new BadRequestException('You are not admin');
132 + }
133 + }
134 +
135 + // return the newly saved user
136 +}
1 +import { NestFactory } from '@nestjs/core';
2 +import { AppModule } from './app.module';
3 +
4 +async function bootstrap() {
5 + const app = await NestFactory.create(AppModule);
6 + await app.listen(3000);
7 +}
8 +bootstrap();
1 +import {
2 + INestApplication,
3 + Injectable,
4 + OnModuleInit,
5 + OnModuleDestroy,
6 +} from '@nestjs/common';
7 +import { PrismaClient } from '@prisma/client';
8 +
9 +@Injectable()
10 +export class PrismaService extends PrismaClient implements OnModuleInit {
11 + async onModuleInit() {
12 + await this.$connect();
13 + }
14 +
15 + async enableShutdownHooks(app: INestApplication) {
16 + this.$on('beforeExit', async () => {
17 + await app.close();
18 + });
19 + }
20 +}
1 +import { Test, TestingModule } from '@nestjs/testing';
2 +import { INestApplication } from '@nestjs/common';
3 +import * as request from 'supertest';
4 +import { AppModule } from './../src/app.module';
5 +
6 +describe('AppController (e2e)', () => {
7 + let app: INestApplication;
8 +
9 + beforeEach(async () => {
10 + const moduleFixture: TestingModule = await Test.createTestingModule({
11 + imports: [AppModule],
12 + }).compile();
13 +
14 + app = moduleFixture.createNestApplication();
15 + await app.init();
16 + });
17 +
18 + it('/ (GET)', () => {
19 + return request(app.getHttpServer())
20 + .get('/')
21 + .expect(200)
22 + .expect('Hello World!');
23 + });
24 +});
1 +{
2 + "moduleFileExtensions": ["js", "json", "ts"],
3 + "rootDir": ".",
4 + "testEnvironment": "node",
5 + "testRegex": ".e2e-spec.ts$",
6 + "transform": {
7 + "^.+\\.(t|j)s$": "ts-jest"
8 + }
9 +}
1 +{
2 + "extends": "./tsconfig.json",
3 + "exclude": [
4 + "node_modules",
5 + "test",
6 + "dist",
7 + "**/*spec.ts",
8 + "prisma"
9 + ]
10 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "compilerOptions": {
3 + "module": "commonjs",
4 + "declaration": true,
5 + "removeComments": true,
6 + "emitDecoratorMetadata": true,
7 + "experimentalDecorators": true,
8 + "allowSyntheticDefaultImports": true,
9 + "target": "es2017",
10 + "sourceMap": true,
11 + "outDir": "./dist",
12 + "baseUrl": "./",
13 + "incremental": true,
14 + "skipLibCheck": true,
15 + "strictNullChecks": false,
16 + "noImplicitAny": false,
17 + "strictBindCallApply": false,
18 + "forceConsistentCasingInFileNames": false,
19 + "noFallthroughCasesInSwitch": false
20 + }
21 +}