我制作了一个 NestJS 微服务包和单独的 NestJS 客户端应用程序来联系微服务。下面给出的是客户端应用程序中使用的代码。在微服务中使用的方法是@messagePattern,并且它是函数式的。我的问题是前端应用程序如何直接联系微服务而不通过客户端以及如何在微服务中设置 swagger 或直接从邮递员测试它?
import { BadRequestException, Injectable, UnauthorizedException } from '@nestjs/common';
import { ClientProxy, ClientProxyFactory, Transport } from '@nestjs/microservices';
import { errorResponse, goodResponse } from 'src/helpers/response.helper';
import { AddContractDTO } from './contract.dto';
@Injectable()
export class ContractService {
private client: ClientProxy;
constructor() {
this.client = ClientProxyFactory.create({
transport: Transport.TCP,
options: {
host: '127.0.0.1',
port: 3011,
},
});
}
public async addContract(data: AddContractDTO) {
const res = await this.client.send<any,any>('contract/addContract', data).toPromise();
console.log(res);
if(!res.success){
throw new BadRequestException(res)
}
return goodResponse(res.data.data,'Contract created'); …Run Code Online (Sandbox Code Playgroud) 目前,在我的打字稿代码(nestjs)中,我使用控制器中的 DTO 来验证进入 API 的数据,模式用作其余文件中的类型,并且除特殊情况外我不会创建接口。
我试图弄清楚我正在做的事情是否好,或者我是否应该在任何地方使用 DTO 作为类型,或者其他什么?目标是提高代码的质量。
用户集合示例:
user.schema.ts
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
@Schema({ collection: 'users' })
export class User extends Document {
@Prop()
name: string;
}
export const UserSchema = SchemaFactory.createForClass(User);
UserSchema.set('timestamps', true);
Run Code Online (Sandbox Code Playgroud)
user.dto.ts
import { IsNotEmpty, IsString, Length } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class UserDto {
@IsNotEmpty()
@IsString()
@Length(3)
@ApiProperty({ required: true })
readonly name: string;
}
Run Code Online (Sandbox Code Playgroud)
使用示例:
async …Run Code Online (Sandbox Code Playgroud) 我在验证嵌套对象时遇到困难。使用类验证器运行nestJs。顶级字段(名字、姓氏等)验证正常。Profile 对象在顶层验证正常,即如果我作为数组提交,我会得到正确的错误,它应该是一个对象。
然而,Profile 的内容尚未得到验证。我已遵循文档上的建议,但也许我只是错过了一些东西。
有谁知道如何验证嵌套对象字段?
export enum GenderType {
Male,
Female,
}
export class Profile {
@IsEnum(GenderType) gender: string;
}
export class CreateClientDto {
@Length(1) first_name: string;
@Length(1) last_name: string;
@IsEmail() email: string;
@IsObject()
@ValidateNested({each: true})
@Type(() => Profile)
profile: Profile;
}
Run Code Online (Sandbox Code Playgroud)
当我发送此有效负载时,我预计它会失败,因为性别不在枚举或字符串中。但它并没有失败
{
"first_name":"A",
"last_name":"B",
"profile":{
"gender":1
}
}
Run Code Online (Sandbox Code Playgroud) 我觉得Model-View-Controller @ docs.nestjs.com没有涵盖这个用例 - 有“动态模板渲染”部分 + Fastify,但两者组合在一起似乎效果不佳。
我尝试过以下片段:
import { Get, Res } from '@nestjs/common'
@Get()
index(@Res() res) {
if (isFoo()) {
return res.render('template1.html', {var1: 'foo'})
} else {
return res.render('template2.html', {var2: 'bar'})
}
}
Run Code Online (Sandbox Code Playgroud)
它失败了
类型错误:res.render 不是函数
有什么办法可以解决吗?
需要明确的是,我不使用的原因@Render是因为我需要该操作中的条件逻辑。
我正在使用 Nest.js 和 TypeORM。我需要进行一个查询,返回表中的所有行,其中facility_id 等于某个值,并且date 小于或等于(<=) 某个日期值。
我阅读了有关Nest.js的文档,但找不到正确的方法。
另外,我阅读了typeORM的官方 GitHub 文档。
这是我的代码。如果可以使用 EntityRepository 中的 find 方法来完成,那就太好了
import { DeleteResult, EntityRepository, Repository, UpdateResult } from "typeorm";
import { Reservations} from "src/Entities/reservations.entity";
import { Facility} from "src/Entities/facility.entity";
import { PaginationParams } from "src/pagination.model";
import { LessThanOrEqual } from "typeorm";
@EntityRepository(Reservation)
export class ReservationRepository extends Repository<Reservation> {
async findByFacility(ustanovaId, paginationParams, dateParams): Promise<Reservation[]> {
return await this.find({where: { termin: LessThanOrEqual(new Date(2021, 0, 1))},
relations: ["users", "facility"],
take: paginationParams.limit,
skip: paginationParams.offset,
order: { …Run Code Online (Sandbox Code Playgroud) 我按照https://www.stewright.me/2021/03/add-header-api-key-to-nestjs-rest-api/制定了 api-key 策略
它有效,我在标头中传递 api-key 并对其进行授权。
现在,对于某些情况,我需要将 api-key 作为查询参数传递给 url 而不是 header。我无法弄清楚。
示例 mysite.com/api/book/5?api-key=myapikey
我当前的代码是
api-密钥策略.ts
@Injectable()
export class ApiKeyStrategy extends PassportStrategy(Strategy, 'api-key') {
constructor(private configService: ConfigService) {
super({ header: 'api-key', prefix: '' }, true, async (apiKey, done) =>
this.validate(apiKey, done)
);
}
private validate(apiKey: string, done: (error: Error, data) => any) {
if (
this.configService.get(AuthEnvironmentVariables.API_KEY) === apiKey
) {
done(null, true);
}
done(new UnauthorizedException(), null);
}
}
Run Code Online (Sandbox Code Playgroud)
api-key-auth-gurad.ts
import { Injectable } from '@nestjs/common';
import { AuthGuard } …Run Code Online (Sandbox Code Playgroud) 我有一个监听事件的监听器,但我也希望该监听器调用其他服务来执行事件中的操作。即创建数据库通知,发送短信等。
当我创建一个构造函数来注入依赖的服务时,侦听器停止拾取事件,当我使用服务删除构造函数时,它会再次开始工作。
我需要如何构造这个监听器才能调用其他服务,例如下面示例中的NotificationsService?
客户端更新.listener.ts
@Injectable()
export class ClientUpdatedListener {
constructor(
@Inject(NotificationsService) private notificationService) {
}
private readonly logger = new Logger(ClientUpdatedListener.name);
@OnEvent(eventType.CLIENT_UPDATED)
handleClientUpdatedEvent(event: ClientUpdatedEvent) {
this.logger.log('Processing event: ' + eventType.CLIENT_UPDATED );
console.log(event);
this.notificationService.emailClient(event.id);
}
Run Code Online (Sandbox Code Playgroud)
通知服务。目前它是一个 shell,但我希望在其中执行逻辑并可能执行数据库调用。
@Injectable()
export class NotificationsService {
constructor(
@Inject(TENANT_CONNECTION) private tenantDb,
) {}
emailClient(id: string) {
console.log(id);
}
}
Run Code Online (Sandbox Code Playgroud)
调用服务代码
const clientUpdatedEvent = new ClientUpdatedEvent();
clientUpdatedEvent.id = id;
this.eventEmitter.emit(eventType.CLIENT_UPDATED, clientUpdatedEvent);
Run Code Online (Sandbox Code Playgroud) 我正在使用 NestJS 应用程序来使用 RabbitMQ 队列。无论顺序如何,每条消息都可以处理,所以我想知道为同一队列声明新消费者的最佳实践是什么。
预期行为:队列由该服务处理,该服务使用多个消费者
队列:[1,2,3,4,5,6,...N];
在nestJS中,您可以使用@RabbitSubscribe装饰器来分配一个函数来处理数据。我想要做的可以通过简单地使用装饰器复制(并重命名)该函数来实现,因此该函数也将被调用来处理来自队列的数据
@RabbitSubscribe({
...
queue: 'my-queue',
})
async firstSubscriber(data){
// 1, 3, 5...
}
@RabbitSubscribe({
...
queue: 'my-queue',
})
async secondSubscriber(data){
// 2, 4, 6...
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以复制项目并水平扩展,但我更喜欢在同一流程中执行此操作。
我如何声明订阅者以编程方式获得相同的行为,以便我可以通过更多并发处理来处理数据?
我有 Swagger,效果很好。但我找不到将路由导出为 JSON 的方法。我记得这样做过,只需在浏览器中访问一个 URL,但现在我不记得了。
我的招摇设置是这样的:
const swaggerOptions = new DocumentBuilder()
.setTitle('Some API Docs')
.setDescription('Some API description')
.setVersion('1.0')
.build();
const swaggerDocument = SwaggerModule.createDocument(app, swaggerOptions);
SwaggerModule.setup('docs', app, swaggerDocument);
Run Code Online (Sandbox Code Playgroud)
我可以使用以下命令访问 Swagger UI: localhost:3000/docs
我已阅读官方文档,他们提到使用:
另外,我看了SO,有这个线程
不幸的是,这些都不适用于我的情况。
获取 JSON 格式文档的 URL 是什么?
我在尝试为 MacBook 安装 NestJS 时遇到问题,当我使用 $ npm install -g @nestjs/cli 时,此错误不断在我的终端中弹出。我是否做错了什么或者我没有将此命令行放在正确的位置?请帮忙 :)
nestjs ×10
node.js ×3
swagger ×2
amqp ×1
fastify ×1
installation ×1
javascript ×1
passport.js ×1
rabbitmq ×1
swagger-ui ×1
terminal ×1
typeorm ×1
typescript ×1