migrate NestJS boilerplate

This commit is contained in:
Rhuan 2024-06-10 10:21:25 -03:00
parent 05cf6313db
commit 07baec4577
40 changed files with 15812 additions and 0 deletions

View File

@ -0,0 +1,73 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
</p>
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
[circleci-url]: https://circleci.com/gh/nestjs/nest
<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>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
<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>
<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>
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
<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>
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
</p>
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
## Description
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
## Installation
```bash
$ yarn install
```
## Running the app
```bash
# development
$ yarn run start
# watch mode
$ yarn run start:dev
# production mode
$ yarn run start:prod
```
## Test
```bash
# unit tests
$ yarn run test
# e2e tests
$ yarn run test:e2e
# test coverage
$ yarn run test:cov
```
## Support
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).
## Stay in touch
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
- Website - [https://nestjs.com](https://nestjs.com/)
- Twitter - [@nestframework](https://twitter.com/nestframework)
## License
Nest is [MIT licensed](LICENSE).

View File

@ -0,0 +1,14 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class Migrations1690475833727 implements MigrationInterface {
name = 'Migrations1690475833727'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "users" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "username" character varying NOT NULL, "password_hash" character varying, "deleted_at" TIMESTAMP, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_fe0bb3f6520ee0469504521e710" UNIQUE ("username"), CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "users"`);
}
}

View File

@ -0,0 +1,14 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class Migrations1691602467422 implements MigrationInterface {
name = 'Migrations1691602467422'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "companies" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying NOT NULL, "deleted_at" TIMESTAMP, "created_at" TIMESTAMP NOT NULL DEFAULT now(), "updated_at" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_3dacbb3eb4f095e29372ff8e131" UNIQUE ("name"), CONSTRAINT "PK_d4bc3e82a314fa9e29f652c2c22" PRIMARY KEY ("id"))`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "companies"`);
}
}

8
nest-cli.json Normal file
View File

@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}

18
orm.config.ts Normal file
View File

@ -0,0 +1,18 @@
import { DataSource } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { config } from 'dotenv';
config();
const configService = new ConfigService();
export default new DataSource({
type: 'postgres',
host: configService.get('DATABASE_HOST') || 'localhost',
port: configService.get('DATABASE_PORT') || 5432,
username: configService.get('DATABASE_USERNAME') || 'postgres',
password: configService.get('DATABASE_PASSWORD') || '1234',
database: configService.get('DATABASE_NAME') || 'boilerplatenestjs',
entities: ['./src/**/*.entity.ts'],
migrations: ['migrations/*-migrations.ts'],
});

9554
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

87
package.json Normal file
View File

@ -0,0 +1,87 @@
{
"name": "nestjs_typeorm",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"typeorm": "node -r ts-node/register ./node_modules/typeorm/cli",
"typeorm:run": "npm run typeorm migration:run -- -d ./orm.config.ts",
"typeorm:generate": "npm run typeorm -- -d ./orm.config.ts migration:generate ./migrations/migrations",
"typeorm:create": "npm run typeorm -- migration:create ./migrations/migrations",
"typeorm:revert": "npm run typeorm -- -d ./orm.config.ts migration:revert"
},
"dependencies": {
"@nestjs/common": "^9.0.0",
"@nestjs/config": "^3.0.0",
"@nestjs/core": "^9.0.0",
"@nestjs/jwt": "^10.1.0",
"@nestjs/passport": "^10.0.0",
"@nestjs/platform-express": "^9.0.0",
"@nestjs/typeorm": "^10.0.0",
"bcrypt": "^5.1.0",
"class-validator": "^0.14.0",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"pg": "^8.11.1",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.2.0",
"typeorm": "^0.3.17"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@types/bcrypt": "^5.0.0",
"@types/express": "^4.17.13",
"@types/jest": "29.2.4",
"@types/node": "18.11.18",
"@types/passport-jwt": "^3.0.9",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "29.3.1",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "29.0.3",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "4.1.1",
"typescript": "^4.7.4"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}

View File

@ -0,0 +1,22 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
describe('AppController', () => {
let appController: AppController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();
appController = app.get<AppController>(AppController);
});
describe('root', () => {
it('should return "Hello World!"', () => {
expect(appController.getHello()).toBe('Hello World!');
});
});
});

12
src/app.controller.ts Normal file
View File

@ -0,0 +1,12 @@
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}

54
src/app.module.ts Normal file
View File

@ -0,0 +1,54 @@
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { JwtModule, JwtModuleOptions } from '@nestjs/jwt';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { AppService } from './app.service';
import { AppController } from './app.controller';
import databaseConfig from './config/database.config';
import jwtConfig from './config/jwt.config';
import { UsersDatabaseModule } from './database/user/users.module';
import { JwtAuthGuard } from './libs/jwt/jwtAuth.guard';
import { AuthorizationModule } from './application/authorization/authorization.module';
import { UsersModule } from './application/users/users.module';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true,
load: [databaseConfig, jwtConfig],
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
const databaseConfig = configService.get<TypeOrmModuleOptions>('database');
return databaseConfig;
},
}), JwtModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
const jwtConfig = configService.get<JwtModuleOptions>('jwt')
return jwtConfig
}
}),
UsersModule,
AuthorizationModule
],
controllers: [AppController],
providers: [
{
provide: APP_GUARD,
useClass: JwtAuthGuard,
},
AppService
],
})
export class AppModule {}

8
src/app.service.ts Normal file
View File

@ -0,0 +1,8 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}

View File

@ -0,0 +1,17 @@
import { Controller, Post, Request, UseGuards } from '@nestjs/common';
import { Public } from 'src/libs/jwt/jwtAuth.guard';
import { AuthorizationService } from './authorization.service';
import { LocalAuthGuard } from './localAuth.guard';
@Controller('authorization')
export class AuthorizationController {
constructor(private authorizationService: AuthorizationService) { }
@Public()
@UseGuards(LocalAuthGuard)
@Post('login')
async login(@Request() req) {
return this.authorizationService.login(req.user);
}
}

View File

@ -0,0 +1,30 @@
import { Module } from '@nestjs/common';
import { AuthorizationService } from './authorization.service';
import { AuthorizationController } from './authorization.controller';
import { UsersDatabaseModule } from 'src/database/user/users.module';
import { LocalStrategy } from './local.strategy';
import { PassportModule } from '@nestjs/passport';
import { JwtModule, JwtModuleOptions } from '@nestjs/jwt';
import { JwtAuthModule } from 'src/libs/jwt/jwtAuth.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
UsersDatabaseModule,
PassportModule,
JwtAuthModule,
JwtModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
const jwtConfig = configService.get<JwtModuleOptions>('jwt')
return jwtConfig
}
})],
providers: [AuthorizationService, LocalStrategy],
controllers: [AuthorizationController]
})
export class AuthorizationModule { }

View File

@ -0,0 +1,36 @@
import { Injectable } from '@nestjs/common';
import { UsersRepository } from 'src/database/user/users.repository';
import { AuthorizationDto } from './dto/authorization.dto';
import * as bcrypt from 'bcrypt';
import { UserEntity } from 'src/database/user/user.entity';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthorizationService {
constructor(
private usersRepository: UsersRepository,
private jwtService: JwtService
) { }
async validateUser(authorizationDto: AuthorizationDto): Promise<UserEntity> {
const userEntity = await this.usersRepository.getUserByUsername(authorizationDto.username)
const isMatch = await bcrypt.compare(authorizationDto.password, userEntity.passwordHash)
if (isMatch) {
return await this.usersRepository.getUser(userEntity.id)
}
return null
}
async login(user: UserEntity) {
if (!user) {
return null
}
const payload = { id: user.id }
return {
access_token: this.jwtService.sign(payload),
}
}
}

View File

@ -0,0 +1,10 @@
import { IsNotEmpty } from "class-validator";
export class AuthorizationDto {
@IsNotEmpty()
username: string;
@IsNotEmpty()
password: string;
}

View File

@ -0,0 +1,21 @@
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthorizationService } from './authorization.service';
import { UserEntity } from 'src/database/user/user.entity';
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy, 'local') {
constructor(private authorizationService: AuthorizationService) {
super();
}
async validate(username: string, password: string): Promise<UserEntity> {
const user = await this.authorizationService.validateUser({ username: username, password: password });
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}

View File

@ -0,0 +1,5 @@
import { Injectable, SetMetadata } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') { }

View File

@ -0,0 +1,19 @@
import { Optional } from "@nestjs/common";
import { IsEmail, IsUUID, IsString } from "class-validator";
import { IUser } from "src/database/user/interfaces/user.interface";
export class UserDto implements IUser {
@Optional()
@IsUUID()
id: string;
@IsString()
passwordHash: string;
@IsEmail()
username: string;
}

View File

@ -0,0 +1,20 @@
import { Controller, Post, Body,} from '@nestjs/common';
import { Public } from 'src/libs/jwt/jwtAuth.guard';
import { UsersService } from './users.service';
import { UserDto } from './dto/user.dto';
@Controller('users')
export class UsersController {
constructor(
private usersService: UsersService
) { }
@Public()
@Post()
async create(@Body() createUserDto: UserDto) {
await this.usersService.createUser(createUserDto)
}
}

View File

@ -0,0 +1,29 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { JwtModule, JwtModuleOptions } from '@nestjs/jwt';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { UsersDatabaseModule } from 'src/database/user/users.module';
@Module({
imports: [
UsersDatabaseModule,
ConfigModule,
JwtModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
const jwtConfig = configService.get<JwtModuleOptions>('jwt')
return jwtConfig
}
}),
],
providers: [
UsersService
],
controllers: [UsersController]
})
export class UsersModule { }

View File

@ -0,0 +1,27 @@
import { Injectable } from '@nestjs/common';
import { UsersRepository } from 'src/database/user/users.repository';
import { randomUUID } from 'crypto'
import * as bcrypt from 'bcrypt';
import { JwtService } from '@nestjs/jwt';
import { UserDto } from './dto/user.dto';
@Injectable()
export class UsersService {
constructor(
private usersRepository: UsersRepository,
) { }
async createUser(createUserDto: UserDto) {
const userEntity = await this.usersRepository.create(createUserDto)
return
}
}

View File

@ -0,0 +1,25 @@
import { registerAs } from '@nestjs/config';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
export default registerAs<TypeOrmModuleOptions>('database', () => {
return {
type: 'postgres',
host: process.env.DATABASE_HOST || 'localhost',
port:
Number(process.env.DATABASE_PORT) || 5432,
username:
process.env.DATABASE_USERNAME ||
'postgres',
password:
process.env.DATABASE_PASSWORD ||
'1234',
database:
process.env.DATABASE_NAME ||
'boilerplatenestjs',
logging: process.env.DATABASE_LOGGING === 'true',
autoLoadEntities: true,
synchronize: false,
migrations: ['dist/migrations/*-migrations.js'],
migrationsRun: true,
};
});

9
src/config/jwt.config.ts Normal file
View File

@ -0,0 +1,9 @@
import { registerAs } from '@nestjs/config';
import {JwtModuleOptions} from '@nestjs/jwt';
export default registerAs<JwtModuleOptions>('jwt', ()=>{
return{
secret: process.env.JWT_SECRET_KEY,
signOptions: { expiresIn: process.env.JWT_EXPIRATION_TIME}
}
});

View File

@ -0,0 +1,21 @@
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, DeleteDateColumn } from 'typeorm';
@Entity({ name: "companies" })
export class CompanyEntity {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({unique:true})
name: string;
@DeleteDateColumn({ name: "deleted_at", nullable: true })
deletedAt: Date;
@CreateDateColumn({ name: "created_at" })
createdAt: Date;
@UpdateDateColumn({ name: "updated_at" })
updatedAt: Date;
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CompanyEntity } from './company.entity';
import { CompaniesRepository } from './company.repository';
@Module({
imports: [TypeOrmModule.forFeature([CompanyEntity])],
providers: [CompaniesRepository],
exports: [CompaniesRepository]
})
export class UsersDatabaseModule { }

View File

@ -0,0 +1,40 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Equal, Repository } from 'typeorm';
import { ICompany } from './interfaces/company.interface';
import { CompanyEntity } from './company.entity';
@Injectable()
export class CompaniesRepository {
constructor(
@InjectRepository(CompanyEntity)
private repository: Repository<CompanyEntity>,
) { }
async create(company: ICompany) {
const userEntity = this.repository.create(company)
return this.repository.save(userEntity)
}
async getUser(id:string){
const user = await this.repository.findOne({
select:['id','name'],
where:{
id:Equal(id)
}
})
return user
}
async getCompanyByName(name:string){
const user = await this.repository.findOne({
select:['id','name'],
where:{
name:Equal(name)
}
})
return user
}
}

View File

@ -0,0 +1,5 @@
export interface ICompany {
id: string
name: string;
}

View File

@ -0,0 +1,6 @@
export interface IUser {
id: string
username: string;
passwordHash: string;
}

View File

@ -0,0 +1,24 @@
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, DeleteDateColumn } from 'typeorm';
@Entity({ name: "users" })
export class UserEntity {
@PrimaryGeneratedColumn("uuid")
id: string;
@Column({unique:true})
username: string;
@Column({ name: "password_hash", nullable: true, select: false })
passwordHash: string;
@DeleteDateColumn({ name: "deleted_at", nullable: true })
deletedAt: Date;
@CreateDateColumn({ name: "created_at" })
createdAt: Date;
@UpdateDateColumn({ name: "updated_at" })
updatedAt: Date;
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserEntity } from './user.entity';
import { UsersRepository } from './users.repository';
@Module({
imports: [TypeOrmModule.forFeature([UserEntity])],
providers: [UsersRepository],
exports: [UsersRepository]
})
export class UsersDatabaseModule { }

View File

@ -0,0 +1,40 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Equal, Repository } from 'typeorm';
import { IUser } from './interfaces/user.interface';
import { UserEntity } from './user.entity';
@Injectable()
export class UsersRepository {
constructor(
@InjectRepository(UserEntity)
private repository: Repository<UserEntity>,
) { }
async create(user: IUser) {
const userEntity = this.repository.create(user)
return this.repository.save(userEntity)
}
async getUser(id:string){
const user = await this.repository.findOne({
select:['id','username'],
where:{
id:Equal(id)
}
})
return user
}
async getUserByUsername(username:string){
const user = await this.repository.findOne({
select:['id','username','passwordHash'],
where:{
username:Equal(username)
}
})
return user
}
}

View File

@ -0,0 +1,36 @@
import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { SetMetadata } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
constructor(private reflector: Reflector) {
super();
}
canActivate(context: ExecutionContext) {
// Add your custom authentication logic here
// for example, call super.logIn(request) to establish a session.
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic) {
return true;
}
return super.canActivate(context);
}
handleRequest(err, user, info) {
// You can throw an exception based on either "info" or "err" arguments
if (err || !user) {
throw err || new UnauthorizedException();
}
return user;
}
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { JwtAuthGuard } from './jwtAuth.guard';
import { JwtStrategy } from './jwtAuth.strategy';
@Module({
providers: [JwtAuthGuard, JwtStrategy],
exports: [JwtAuthGuard, JwtStrategy]
})
export class JwtAuthModule { }

View File

@ -0,0 +1,22 @@
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtModuleOptions } from '@nestjs/jwt';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(private configService: ConfigService) {
const jtwconfig = configService.get<JwtModuleOptions>('jwt')
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: jtwconfig.secret,
});
}
async validate(payload: any) {
return { userId: payload.id};
}
}

8
src/main.ts Normal file
View File

@ -0,0 +1,8 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();

24
test/app.e2e-spec.ts Normal file
View File

@ -0,0 +1,24 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!');
});
});

9
test/jest-e2e.json Normal file
View File

@ -0,0 +1,9 @@
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e-spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}

4
tsconfig.build.json Normal file
View File

@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}

22
tsconfig.json Normal file
View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false
}
}

5403
yarn.lock Normal file

File diff suppressed because it is too large Load Diff