Merge pull request #10983 from nestjs/feat/graph-inspector

feat: graph inspector, preview mode
This commit is contained in:
Kamil Mysliwiec
2023-02-01 11:29:25 +01:00
committed by GitHub
174 changed files with 9662 additions and 698 deletions

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
import { ValidationPipe } from '@nestjs/common';
import { SerializedGraph } from '@nestjs/core/inspector/serialized-graph';
import { Transport } from '@nestjs/microservices';
import { Test, TestingModule } from '@nestjs/testing';
import { expect } from 'chai';
import { readFileSync } from 'fs';
import { join } from 'path';
import { AppModule } from '../src/app.module';
import { HttpExceptionFilter } from '../src/common/filters/http-exception.filter';
import { TimeoutInterceptor } from '../src/common/interceptors/timeout.interceptor';
describe('Graph inspector', () => {
let testingModule: TestingModule;
before(async () => {
testingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile({ snapshot: true });
});
it('should generate a pre-initialization graph and match snapshot', () => {
const graph = testingModule.get(SerializedGraph);
// Update snapshot:
// writeFileSync(
// join(__dirname, 'fixtures', 'pre-init-graph.json'),
// graph.toString(),
// );
const snapshot = readFileSync(
join(__dirname, 'fixtures', 'pre-init-graph.json'),
'utf-8',
);
expect(JSON.parse(graph.toString())).to.deep.equal(JSON.parse(snapshot));
});
it('should generate a post-initialization graph and match snapshot', async () => {
const app = testingModule.createNestApplication({ preview: true });
app.useGlobalPipes(new ValidationPipe());
app.useGlobalFilters(new HttpExceptionFilter());
app.useGlobalInterceptors(new TimeoutInterceptor());
app.enableVersioning();
app.connectMicroservice({ transport: Transport.TCP, options: {} });
await app.init();
const graph = testingModule.get(SerializedGraph);
// Update snapshot:
// writeFileSync(
// join(__dirname, 'fixtures', 'post-init-graph.json'),
// graph.toString(),
// );
const snapshot = readFileSync(
join(__dirname, 'fixtures', 'post-init-graph.json'),
'utf-8',
);
expect(graph.toString()).to.equal(snapshot);
});
});

View File

@@ -0,0 +1,16 @@
import { Controller, Get } from '@nestjs/common';
@Controller({
version: '1',
})
export class AppV1Controller {
@Get('/')
helloWorldV1() {
return 'Hello World V1!';
}
@Get('/:param/hello')
paramV1() {
return 'Parameter V1!';
}
}

View File

@@ -0,0 +1,17 @@
import { Controller, Get, Version } from '@nestjs/common';
@Controller({
version: '2',
})
export class AppV2Controller {
@Get('/')
helloWorldV2() {
return 'Hello World V2!';
}
@Version('3')
@Get('/:param/hello')
paramV1() {
return 'Parameter V2!';
}
}

View File

@@ -0,0 +1,46 @@
import { Module, Scope } from '@nestjs/common';
import { AppV1Controller } from './app-v1.controller';
import { AppV2Controller } from './app-v2.controller';
import { CatsModule } from './cats/cats.module';
import { ChatModule } from './chat/chat.module';
import { HelloModule as CircularHelloModule } from './circular-hello/hello.module';
import { HelloService } from './circular-hello/hello.service';
import { InputModule } from './circular-modules/input.module';
import { CoreModule } from './core/core.module';
import { DatabaseModule } from './database/database.module';
import { DogsModule } from './dogs/dogs.module';
import { DurableModule } from './durable/durable.module';
import { ExternalSvcModule } from './external-svc/external-svc.module';
import { PropertiesModule } from './properties/properties.module';
import { RequestChainModule } from './request-chain/request-chain.module';
import { UsersModule } from './users/users.module';
class Meta {
static COUNTER = 0;
constructor(private readonly helloService: HelloService) {
Meta.COUNTER++;
}
}
@Module({
imports: [
CoreModule,
CatsModule,
CircularHelloModule.forRoot({
provide: 'META',
useClass: Meta,
scope: Scope.REQUEST,
}),
DurableModule,
DogsModule,
UsersModule,
DatabaseModule,
ExternalSvcModule,
ChatModule,
RequestChainModule,
PropertiesModule,
InputModule,
],
controllers: [AppV1Controller, AppV2Controller],
})
export class AppModule {}

View File

@@ -0,0 +1,30 @@
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
import { RolesGuard } from '../common/guards/roles.guard';
import { ParseIntPipe } from '../common/pipes/parse-int.pipe';
import { CatsService } from './cats.service';
import { CreateCatDto } from './dto/create-cat.dto';
import { Cat } from './interfaces/cat.interface';
@UseGuards(RolesGuard)
@Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Post()
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
@Get(':id')
findOne(
@Param('id', new ParseIntPipe())
id: number,
) {
// get by ID logic
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}

View File

@@ -0,0 +1,15 @@
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
create(cat: Cat) {
this.cats.push(cat);
}
findAll(): Cat[] {
return this.cats;
}
}

View File

@@ -0,0 +1,12 @@
import { IsInt, IsString } from 'class-validator';
export class CreateCatDto {
@IsString()
readonly name: string;
@IsInt()
readonly age: number;
@IsString()
readonly breed: string;
}

View File

@@ -0,0 +1,5 @@
export interface Cat {
name: string;
age: number;
breed: string;
}

View File

@@ -0,0 +1,38 @@
import {
WebSocketGateway,
SubscribeMessage,
MessageBody,
} from '@nestjs/websockets';
import { ChatService } from './chat.service';
import { CreateChatDto } from './dto/create-chat.dto';
import { UpdateChatDto } from './dto/update-chat.dto';
@WebSocketGateway()
export class ChatGateway {
constructor(private readonly chatService: ChatService) {}
@SubscribeMessage('createChat')
create(@MessageBody() createChatDto: CreateChatDto) {
return this.chatService.create(createChatDto);
}
@SubscribeMessage('findAllChat')
findAll() {
return this.chatService.findAll();
}
@SubscribeMessage('findOneChat')
findOne(@MessageBody() id: number) {
return this.chatService.findOne(id);
}
@SubscribeMessage('updateChat')
update(@MessageBody() updateChatDto: UpdateChatDto) {
return this.chatService.update(updateChatDto.id, updateChatDto);
}
@SubscribeMessage('removeChat')
remove(@MessageBody() id: number) {
return this.chatService.remove(id);
}
}

View File

@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { ChatService } from './chat.service';
import { ChatGateway } from './chat.gateway';
@Module({
providers: [ChatGateway, ChatService],
})
export class ChatModule {}

View File

@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CreateChatDto } from './dto/create-chat.dto';
import { UpdateChatDto } from './dto/update-chat.dto';
@Injectable()
export class ChatService {
create(createChatDto: CreateChatDto) {
return 'This action adds a new chat';
}
findAll() {
return `This action returns all chat`;
}
findOne(id: number) {
return `This action returns a #${id} chat`;
}
update(id: number, updateChatDto: UpdateChatDto) {
return `This action updates a #${id} chat`;
}
remove(id: number) {
return `This action removes a #${id} chat`;
}
}

View File

@@ -0,0 +1 @@
export class CreateChatDto {}

View File

@@ -0,0 +1,6 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateChatDto } from './create-chat.dto';
export class UpdateChatDto extends PartialType(CreateChatDto) {
id: number;
}

View File

@@ -0,0 +1 @@
export class Chat {}

View File

@@ -0,0 +1,10 @@
import { IsString, IsNotEmpty, IsNumber } from 'class-validator';
export class TestDto {
@IsString()
@IsNotEmpty()
string: string;
@IsNumber()
number: number;
}

View File

@@ -0,0 +1,21 @@
import {
CanActivate,
ExecutionContext,
Injectable,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.REQUEST })
export class Guard implements CanActivate {
static COUNTER = 0;
constructor() {
Guard.COUNTER++;
}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return true;
}
}

View File

@@ -0,0 +1,30 @@
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { Guard } from './guards/request-scoped.guard';
import { HelloService } from './hello.service';
import { Interceptor } from './interceptors/logging.interceptor';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { UsersService } from './users/users.service';
@Controller('hello')
export class HelloController {
static COUNTER = 0;
constructor(
private readonly helloService: HelloService,
private readonly usersService: UsersService,
) {
HelloController.COUNTER++;
}
@UseGuards(Guard)
@UseInterceptors(Interceptor)
@Get()
greeting(@Param('id', UserByIdPipe) id): string {
return this.helloService.greeting();
}
}

View File

@@ -0,0 +1,19 @@
import { DynamicModule, Inject, Module, Provider } from '@nestjs/common';
import { HelloController } from './hello.controller';
import { HelloService } from './hello.service';
import { UsersService } from './users/users.service';
@Module({
controllers: [HelloController],
providers: [HelloService, UsersService],
})
export class HelloModule {
constructor(@Inject('META') private readonly meta) {}
static forRoot(meta: Provider): DynamicModule {
return {
module: HelloModule,
providers: [meta],
};
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class HelloService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
HelloService.COUNTER++;
}
greeting(): string {
return 'Hello world!';
}
}

View File

@@ -0,0 +1,19 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.REQUEST })
export class Interceptor implements NestInterceptor {
static COUNTER = 0;
constructor() {
Interceptor.COUNTER++;
}
intercept(context: ExecutionContext, call: CallHandler): Observable<any> {
return call.handle();
}
}

View File

@@ -0,0 +1,14 @@
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
import { UsersService } from './users.service';
@Injectable()
export class UserByIdPipe implements PipeTransform<string> {
static COUNTER = 0;
constructor(private readonly usersService: UsersService) {
UserByIdPipe.COUNTER++;
}
transform(value: string, metadata: ArgumentMetadata) {
return this.usersService.findById(value);
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
UsersService.COUNTER++;
}
findById(id: string) {
return { id };
}
}

View File

@@ -0,0 +1,10 @@
import { Module, forwardRef } from '@nestjs/common';
import { CircularService } from './circular.service';
import { InputModule } from './input.module';
@Module({
imports: [forwardRef(() => InputModule)],
providers: [CircularService],
exports: [CircularService],
})
export class CircularModule {}

View File

@@ -0,0 +1,10 @@
import { Injectable, forwardRef, Inject } from '@nestjs/common';
import { InputService } from './input.service';
@Injectable()
export class CircularService {
constructor(
@Inject(forwardRef(() => InputService))
public readonly service: InputService,
) {}
}

View File

@@ -0,0 +1,10 @@
import { Module, forwardRef } from '@nestjs/common';
import { CircularModule } from './circular.module';
import { InputService } from './input.service';
@Module({
imports: [forwardRef(() => CircularModule)],
providers: [InputService],
exports: [InputService],
})
export class InputModule {}

View File

@@ -0,0 +1,10 @@
import { Injectable, Inject, forwardRef } from '@nestjs/common';
import { CircularService } from './circular.service';
@Injectable()
export class InputService {
constructor(
@Inject(forwardRef(() => CircularService))
public readonly service: CircularService,
) {}
}

View File

@@ -0,0 +1,22 @@
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
} from '@nestjs/common';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter<HttpException> {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const statusCode = exception.getStatus();
response.status(statusCode).json({
statusCode,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}

View File

@@ -0,0 +1,20 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
const hasRole = () =>
user.roles.some(role => !!roles.find(item => item === role));
return user && user.roles && hasRole();
}
}

View File

@@ -0,0 +1,15 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';
@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(timeout(5000));
}
}

View File

@@ -0,0 +1,9 @@
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
console.log(`Request...`);
next();
}
}

View File

@@ -0,0 +1,17 @@
import {
BadRequestException,
PipeTransform,
Injectable,
ArgumentMetadata,
} from '@nestjs/common';
@Injectable()
export class ParseIntPipe implements PipeTransform<string> {
async transform(value: string, metadata: ArgumentMetadata) {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
return val;
}
}

View File

@@ -0,0 +1,18 @@
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { CatsController } from '../cats/cats.controller';
import { LoggerMiddleware } from '../common/middleware/logger.middleware';
import { LoggingInterceptor } from './interceptors/logging.interceptor';
import { TransformInterceptor } from './interceptors/transform.interceptor';
@Module({
providers: [
{ provide: APP_INTERCEPTOR, useClass: TransformInterceptor },
{ provide: APP_INTERCEPTOR, useClass: LoggingInterceptor },
],
})
export class CoreModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes(CatsController);
}
}

View File

@@ -0,0 +1,20 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before...');
const now = Date.now();
return next
.handle()
.pipe(tap(() => console.log(`After... ${Date.now() - now}ms`)));
}
}

View File

@@ -0,0 +1,24 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export interface Response<T> {
data: T;
}
@Injectable()
export class TransformInterceptor<T>
implements NestInterceptor<T, Response<T>>
{
intercept(
context: ExecutionContext,
next: CallHandler<T>,
): Observable<Response<T>> {
return next.handle().pipe(map(data => ({ data })));
}
}

View File

@@ -0,0 +1,45 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
} from '@nestjs/common';
import { DatabaseService } from './database.service';
import { CreateDatabaseDto } from './dto/create-database.dto';
import { UpdateDatabaseDto } from './dto/update-database.dto';
@Controller('database')
export class DatabaseController {
constructor(private readonly databaseService: DatabaseService) {}
@Post()
create(@Body() createDatabaseDto: CreateDatabaseDto) {
return this.databaseService.create(createDatabaseDto);
}
@Get()
findAll() {
return this.databaseService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.databaseService.findOne(+id);
}
@Patch(':id')
update(
@Param('id') id: string,
@Body() updateDatabaseDto: UpdateDatabaseDto,
) {
return this.databaseService.update(+id, updateDatabaseDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.databaseService.remove(+id);
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { DatabaseService } from './database.service';
import { DatabaseController } from './database.controller';
@Module({
controllers: [DatabaseController],
providers: [DatabaseService],
})
export class DatabaseModule {}

View File

@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CreateDatabaseDto } from './dto/create-database.dto';
import { UpdateDatabaseDto } from './dto/update-database.dto';
@Injectable()
export class DatabaseService {
create(createDatabaseDto: CreateDatabaseDto) {
return 'This action adds a new database';
}
findAll() {
return `This action returns all database`;
}
findOne(id: number) {
return `This action returns a #${id} database`;
}
update(id: number, updateDatabaseDto: UpdateDatabaseDto) {
return `This action updates a #${id} database`;
}
remove(id: number) {
return `This action removes a #${id} database`;
}
}

View File

@@ -0,0 +1 @@
export class CreateDatabaseDto {}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateDatabaseDto } from './create-database.dto';
export class UpdateDatabaseDto extends PartialType(CreateDatabaseDto) {}

View File

@@ -0,0 +1 @@
export class Database {}

View File

@@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class CoreService {}

View File

@@ -0,0 +1,7 @@
import { Module } from '@nestjs/common';
import { DefaultsService } from './defaults.service';
@Module({
providers: [DefaultsService],
})
export class DefaultsModule {}

View File

@@ -0,0 +1,11 @@
import { Inject, Injectable, Optional } from '@nestjs/common';
import { CoreService } from './core.service';
@Injectable()
export class DefaultsService {
constructor(
@Inject(CoreService)
@Optional()
public readonly coreService = { default: true },
) {}
}

View File

@@ -0,0 +1,42 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
} from '@nestjs/common';
import { DogsService } from './dogs.service';
import { CreateDogDto } from './dto/create-dog.dto';
import { UpdateDogDto } from './dto/update-dog.dto';
@Controller('dogs')
export class DogsController {
constructor(private readonly dogsService: DogsService) {}
@Post()
create(@Body() createDogDto: CreateDogDto) {
return this.dogsService.create(createDogDto);
}
@Get()
findAll() {
return this.dogsService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.dogsService.findOne(+id);
}
@Patch(':id')
update(@Param('id') id: string, @Body() updateDogDto: UpdateDogDto) {
return this.dogsService.update(+id, updateDogDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.dogsService.remove(+id);
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { DogsService } from './dogs.service';
import { DogsController } from './dogs.controller';
@Module({
controllers: [DogsController],
providers: [DogsService],
})
export class DogsModule {}

View File

@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CreateDogDto } from './dto/create-dog.dto';
import { UpdateDogDto } from './dto/update-dog.dto';
@Injectable()
export class DogsService {
create(createDogDto: CreateDogDto) {
return 'This action adds a new dog';
}
findAll() {
return `This action returns all dogs`;
}
findOne(id: number) {
return `This action returns a #${id} dog`;
}
update(id: number, updateDogDto: UpdateDogDto) {
return `This action updates a #${id} dog`;
}
remove(id: number) {
return `This action removes a #${id} dog`;
}
}

View File

@@ -0,0 +1 @@
export class CreateDogDto {}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateDogDto } from './create-dog.dto';
export class UpdateDogDto extends PartialType(CreateDogDto) {}

View File

@@ -0,0 +1 @@
export class Dog {}

View File

@@ -0,0 +1,23 @@
import { ContextId, ContextIdStrategy, HostComponentInfo } from '@nestjs/core';
import { Request } from 'express';
const tenants = new Map<string, ContextId>();
export class DurableContextIdStrategy implements ContextIdStrategy {
attach(contextId: ContextId, request: Request) {
const tenantId = request.headers['x-tenant-id'] as string;
let tenantSubTreeId: ContextId;
if (tenants.has(tenantId)) {
tenantSubTreeId = tenants.get(tenantId);
} else {
tenantSubTreeId = { id: +tenantId } as ContextId;
tenants.set(tenantId, tenantSubTreeId);
}
return {
resolve: (info: HostComponentInfo) =>
info.isTreeDurable ? tenantSubTreeId : contextId,
payload: { tenantId },
};
}
}

View File

@@ -0,0 +1,17 @@
import { Controller, Get } from '@nestjs/common';
import { DurableService } from './durable.service';
@Controller('durable')
export class DurableController {
constructor(private readonly durableService: DurableService) {}
@Get()
greeting(): string {
return this.durableService.greeting();
}
@Get('echo')
echo() {
return this.durableService.requestPayload;
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { DurableController } from './durable.controller';
import { DurableService } from './durable.service';
@Module({
controllers: [DurableController],
providers: [DurableService],
})
export class DurableModule {}

View File

@@ -0,0 +1,14 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
@Injectable({ scope: Scope.REQUEST, durable: true })
export class DurableService {
public instanceCounter = 0;
constructor(@Inject(REQUEST) public readonly requestPayload: unknown) {}
greeting() {
++this.instanceCounter;
return `Hello world! Counter: ${this.instanceCounter}`;
}
}

View File

@@ -0,0 +1 @@
export class CreateExternalSvcDto {}

View File

@@ -0,0 +1,6 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateExternalSvcDto } from './create-external-svc.dto';
export class UpdateExternalSvcDto extends PartialType(CreateExternalSvcDto) {
id: number;
}

View File

@@ -0,0 +1 @@
export class ExternalSvc {}

View File

@@ -0,0 +1,38 @@
import { Controller } from '@nestjs/common';
import { MessagePattern, Payload } from '@nestjs/microservices';
import { ExternalSvcService } from './external-svc.service';
import { CreateExternalSvcDto } from './dto/create-external-svc.dto';
import { UpdateExternalSvcDto } from './dto/update-external-svc.dto';
@Controller()
export class ExternalSvcController {
constructor(private readonly externalSvcService: ExternalSvcService) {}
@MessagePattern('createExternalSvc')
create(@Payload() createExternalSvcDto: CreateExternalSvcDto) {
return this.externalSvcService.create(createExternalSvcDto);
}
@MessagePattern('findAllExternalSvc')
findAll() {
return this.externalSvcService.findAll();
}
@MessagePattern('findOneExternalSvc')
findOne(@Payload() id: number) {
return this.externalSvcService.findOne(id);
}
@MessagePattern('updateExternalSvc')
update(@Payload() updateExternalSvcDto: UpdateExternalSvcDto) {
return this.externalSvcService.update(
updateExternalSvcDto.id,
updateExternalSvcDto,
);
}
@MessagePattern('removeExternalSvc')
remove(@Payload() id: number) {
return this.externalSvcService.remove(id);
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { ExternalSvcService } from './external-svc.service';
import { ExternalSvcController } from './external-svc.controller';
@Module({
controllers: [ExternalSvcController],
providers: [ExternalSvcService],
})
export class ExternalSvcModule {}

View File

@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CreateExternalSvcDto } from './dto/create-external-svc.dto';
import { UpdateExternalSvcDto } from './dto/update-external-svc.dto';
@Injectable()
export class ExternalSvcService {
create(createExternalSvcDto: CreateExternalSvcDto) {
return 'This action adds a new externalSvc';
}
findAll() {
return `This action returns all externalSvc`;
}
findOne(id: number) {
return `This action returns a #${id} externalSvc`;
}
update(id: number, updateExternalSvcDto: UpdateExternalSvcDto) {
return `This action updates a #${id} externalSvc`;
}
remove(id: number) {
return `This action removes a #${id} externalSvc`;
}
}

View File

@@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class DependencyService {}

View File

@@ -0,0 +1,19 @@
import { Module } from '@nestjs/common';
import { DependencyService } from './dependency.service';
import { PropertiesService, SYMBOL_TOKEN } from './properties.service';
@Module({
providers: [
DependencyService,
PropertiesService,
{
provide: 'token',
useValue: true,
},
{
provide: SYMBOL_TOKEN,
useValue: true,
},
],
})
export class PropertiesModule {}

View File

@@ -0,0 +1,11 @@
import { Inject, Injectable } from '@nestjs/common';
import { DependencyService } from './dependency.service';
export const SYMBOL_TOKEN = Symbol('token');
@Injectable()
export class PropertiesService {
@Inject() service: DependencyService;
@Inject('token') token: boolean;
@Inject(SYMBOL_TOKEN) symbolToken: boolean;
}

View File

@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { HelperService } from './helper.service';
@Module({
providers: [HelperService],
exports: [HelperService],
})
export class HelperModule {}

View File

@@ -0,0 +1,9 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
@Injectable({ scope: Scope.REQUEST })
export class HelperService {
constructor(@Inject(REQUEST) public readonly request) {}
public noop() {}
}

View File

@@ -0,0 +1,21 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { HelperService } from '../helper/helper.service';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
constructor(private readonly helperSvc: HelperService) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
this.helperSvc.noop();
if (!this.helperSvc.request) {
throw new Error('error');
}
return next.handle();
}
}

View File

@@ -0,0 +1,14 @@
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { LoggingInterceptor } from './interceptors/logging.interceptor';
import { RequestChainService } from './request-chain.service';
@Controller('hello')
export class RequestChainController {
constructor(private readonly chainService: RequestChainService) {}
@UseInterceptors(LoggingInterceptor)
@Get()
greeting(): void {
this.chainService.call();
}
}

View File

@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { HelperModule } from './helper/helper.module';
import { RequestChainController } from './request-chain.controller';
import { RequestChainService } from './request-chain.service';
@Module({
imports: [HelperModule],
providers: [RequestChainService],
controllers: [RequestChainController],
})
export class RequestChainModule {}

View File

@@ -0,0 +1,15 @@
import { Injectable } from '@nestjs/common';
import { HelperService } from './helper/helper.service';
@Injectable()
export class RequestChainService {
static COUNTER = 0;
constructor(private readonly helperService: HelperService) {
helperService.noop();
RequestChainService.COUNTER += 1;
}
call() {
this.helperService.noop();
}
}

View File

@@ -0,0 +1 @@
export class CreateUserDto {}

View File

@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto';
export class UpdateUserDto extends PartialType(CreateUserDto) {}

View File

@@ -0,0 +1 @@
export class User {}

View File

@@ -0,0 +1,42 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(+id);
}
@Patch(':id')
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return this.usersService.update(+id, updateUserDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.usersService.remove(+id);
}
}

View File

@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}

View File

@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
@Injectable()
export class UsersService {
create(createUserDto: CreateUserDto) {
return 'This action adds a new user';
}
findAll() {
return `This action returns all users`;
}
findOne(id: number) {
return `This action returns a #${id} user`;
}
update(id: number, updateUserDto: UpdateUserDto) {
return `This action updates a #${id} user`;
}
remove(id: number) {
return `This action removes a #${id} user`;
}
}

View File

@@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"allowJs": true,
"outDir": "./dist",
"paths": {
"@nestjs/common": ["../../packages/common"],
"@nestjs/common/*": ["../../packages/common/*"],
"@nestjs/core": ["../../packages/core"],
"@nestjs/core/*": ["../../packages/core/*"],
"@nestjs/microservices": ["../../packages/microservices"],
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],
"@nestjs/platform-socket.io/*": ["../../packages/platform-socket.io/*"],
"@nestjs/platform-ws": ["../../packages/platform-ws"],
"@nestjs/platform-ws/*": ["../../packages/platform-ws/*"]
}
},
"include": [
"src/**/*",
"e2e/**/*"
],
"exclude": [
"node_modules",
]
}

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -20,8 +20,8 @@
"@nestjs/microservices/*": ["../../packages/microservices/*"],
"@nestjs/websockets": ["../../packages/websockets"],
"@nestjs/websockets/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/websockets"],
"@nestjs/testing/*": ["../../packages/websockets/*"],
"@nestjs/testing": ["../../packages/testing"],
"@nestjs/testing/*": ["../../packages/testing/*"],
"@nestjs/platform-express": ["../../packages/platform-express"],
"@nestjs/platform-express/*": ["../../packages/platform-express/*"],
"@nestjs/platform-socket.io": ["../../packages/platform-socket.io"],

View File

@@ -3,5 +3,5 @@
"packages": [
"packages/*"
],
"version": "9.2.1"
"version": "9.3.0-beta.3"
}

View File

@@ -204,17 +204,16 @@
"**/*.js",
"**/*.d.ts",
"**/*.spec.ts",
"packages/**/*.spec.ts",
"packages/**/adapters/*.ts",
"packages/**/nest-*.ts",
"packages/**/test/**/*.ts",
"packages/core/errors/**/*",
"packages/common/exceptions/*.ts",
"packages/common/http/*.ts",
"packages/common/utils/load-package.util.ts",
"packages/microservices/exceptions/",
"packages/microservices/microservices-module.ts",
"packages/core/middleware/middleware-module.ts",
"packages/core/discovery/discovery-service.ts",
"packages/core/injector/module-ref.ts",
"packages/core/injector/instance-links-host.ts",
"packages/core/helpers/context-id-factory.ts",

View File

@@ -78,7 +78,10 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
<td>
<a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/jetbrains-logo.svg" width="110" valign="middle" /></a></td><td>
<a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td><td>
<a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/fuse-logo.svg" width="105" valign="middle" /></a></td></</tr></table>
<a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/fuse-logo.svg" width="105" valign="middle" /></a></td>
<td>
<a href="https://ridicorp.com/career/" target="_blank"><img src="https://nestjs.com/img/ridi-logo.svg" width="105" valign="middle" /></a></td><td>
<a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://nestjs.com/img/movavi-logo.svg" width="105" valign="middle" /></a></td></</tr></table>
#### Silver Sponsors
@@ -91,7 +94,8 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
<td><a href="https://www.tinystacks.com" target="_blank"><img src="https://nestjs.com/img/tinystacks-logo.png#1" width="140" valign="middle" /></td>
<td><a href="https://n.inc" target="_blank"><img src="https://nestjs.com/img/n-inc-logo.svg" width="120" valign="middle" /></td></tr><tr>
<td><a href="https://bilberrry.com/" target="_blank"><img src="https://nestjs.com/img/bilberrry-logo.svg" width="180" valign="middle" /></td>
<td><a href="https://ipinfo.ai/" target="_blank"><img src="https://nestjs.com/img/ipinfo-logo.png" width="130" valign="middle" /></td></tr>
<td><a href="https://ipinfo.ai/" target="_blank"><img src="https://nestjs.com/img/ipinfo-logo.png" width="130" valign="middle" /></td>
<td><a href="https://chax.at" target="_blank"><img src="https://nestjs.com/img/chaxat-logo.png" width="100" valign="middle" /></td></tr>
</table>
#### Sponsors
@@ -132,7 +136,8 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
<td align="center" valign="middle"><a href="https://mobilereality.pl/" target="_blank"><img src="https://nestjs.com/img/mobile-reality-logo.png" width="45" valign="middle" /></a></td>
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
<td align="center" valign="middle"><a href="https://db.nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nord-logo.png" width="50" valign="middle" /></a></td>
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
</tr></table>
## Backers

Some files were not shown because too many files have changed in this diff Show More