PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, October 20, 2022

[FIXED] How would you pass a property from a nest service to a Schema's virtual property declaration?

 October 20, 2022     mongodb, mongoose, mongoose-schema, nestjs, node.js     No comments   

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)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing