Issue
I'm migrating an existing nodejs + mongoose API to NestJS.
New to this framework, I simply followed the docs on the official website to set up my configuration services & modules, and re-define my schemas to make use of the decorators provided by @nestjs\mongoose
.
On my first API, I simply had a ConfigClass that was exported, with Nest, I have a service that is called in my controllers.
What I'm trying to do is to create a mongoose virtual field depending on the value of the configuration. Since my configuration is now stored in a service, I doubt, that I could just import it and use it as-is.
Code-wise, my current configuration module and service look like :
//app-config.config.ts
import { registerAs } from '@nestjs/config';
export const AppConfiguration = registerAs('app', () => ({
name: process.env.APP_NAME.trim(),
host: process.env.APP_HOST.trim(),
}));
//app-config.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AppConfigService {
constructor(private _config: ConfigService) {}
get name(): string {
return this._config.get<string>('app.name');
}
get host(): number {
return this._config.get<number>('app.host');
}
}
//app-config.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import * as Joi from 'joi';
import { AppConfiguration } from './app-config.config';
import { AppConfigService } from './app-config.service';
@Module({
imports: [
ConfigModule.forRoot({
load: [AppConfiguration],
validationSchema: Joi.object({
APP_NAME: Joi.string().default('nest api'),
APP_HOST: Joi.string().default('localhost.lan'),
}),
}),
],
providers: [ConfigService, AppConfigService],
exports: [AppConfigService],
})
export class AppConfigModule {}
My schema would look like :
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
@Schema({
toObject: {
virtuals: true,
},
toJSON: {
virtuals: true,
},
})
export class Category extends Document {
@Prop({
required: true,
})
name: string;
}
export const CategorySchema = SchemaFactory.createForClass(Category);
//Before my virtual would simply look like this:
CategorySchema.virtual('access').get(function (this: Category) {
// Config would be my configuration class directly imported,
//and now accessing my config property as wished.
const url: URL = new URL('/download', Config.Host);
// What I'd like to know, now is how I should proceed to get the same result
// except with AppConfigService.host ?
url.searchParams.set('name', this.name);
return url.toString();
});
So far, I thought about setting up nodejs globals in the AppConfigModule constructor, I even thought about sending the needed config property to the client, and letting the client do the concatenation.
I'm looking for what would be the cleanest way to do this, I may be unaware of a built-in method.
Thanks in advance. I'll keep this updated if I find an acceptable solution to my problem.
Solution
I finally passed my properties as nodejs globals in my config service.
@Injectable()
export class AppConfigService {
get port(): number {
return this._config.get<number>('app.port');
}
get host(): string {
return this._config.get<string>('app.host');
}
get url(): string {
const _url = new URL(`${this.host}:${this.port}`);
return _url.href;
}
constructor(private _config: ConfigService) {
global.api = this.url;
}
}
I'll probably move their declarations out of the constructor into a method or even to my app main file (since the service is called at start-up). But for now it's doing the job.
Answered By - CrazyYoshi Answer Checked By - Marie Seifert (PHPFixing Admin)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.