all, how to use DynamicModule in config case?
https://github.com/nestjs/nest/blob/master/sample/25-dynamic-modules/src/config/config.service.ts#L12 for official example.
After config like official Example:
import { Inject, Injectable } from '#nestjs/common';
import * as dotenv from 'dotenv';
import * as fs from 'fs';
import * as path from 'path';
import { CONFIG_OPTIONS } from './constants';
import { ConfigOptions, EnvConfig } from './interfaces';
#Injectable()
export class ConfigService {
private readonly envConfig: EnvConfig;
constructor(#Inject(CONFIG_OPTIONS) options: ConfigOptions) {
const filePath = `${process.env.NODE_ENV || 'development'}.env`;
const envFile = path.resolve(__dirname, '../../', options.folder, filePath);
this.envConfig = dotenv.parse(fs.readFileSync(envFile));
}
get(key: string): string {
return this.envConfig[key];
}
}
Really don't understand "Dynamic modules give us the ability to pass parameters into the module being imported so we can change its behavior. "(from official docs) Any difference to common ways? Like:https://docs.nestjs.com/techniques/configuration
For example, If I have two of three config file in config folder. How to use? And difference between the common ways.
Thanks.
Thanks to the nestjs official group.
Just add #Global() to my ConfigService is work fine.
Related
I am trying to import a typescript module that loads my environment variables. since the order of import and executions for my variables is important for my app, I want to refactor them from my index.ts file into another module. However, I don't want to call a function to run my script, but rather I want to execute them upon importing the module which I am doing right now with the loadEnvVars() function.
// index.ts
import loadEnvVars from './settings';
**loadEnvVars();**
import app from './server';
app.run();
Instead of above I want:
// index.ts
import loadEnvVars from './settings';
import app from './server';
app.run();
// ./settings.ts
import dotenv from 'dotenv';
import path from 'path';
const envVars = (): void => {
dotenv.config({
path: path.join(__dirname, '../.env.' + process.env.NODE_ENV),
debug: process.env.NODE_ENV === 'development' ? true : false,
});
};
export default envVars
I myself have come up with the following solution but I am not sure if this is a proper way of doing such imports:
// index.ts
import './settings';
...
// settings.ts
import dotenv from 'dotenv';
import path from 'path';
const envVars = (): void => {
dotenv.config({
path: path.join(__dirname, '../.env.' + process.env.NODE_ENV),
debug: process.env.NODE_ENV === 'development' ? true : false,
});
};
envVars();
export default envVars;
You can make it a bit cleaner by removing the function entirely, since it's no longer used, but called automatically:
// settings.ts
import dotenv from 'dotenv';
import path from 'path';
dotenv.config({
path: path.join(__dirname, '../.env.' + process.env.NODE_ENV),
debug: process.env.NODE_ENV === 'development' ? true : false,
});
// remove this next line
// export default envVars;
That said - depending on import order leads to fragile code. It would be easy to mess up something by accidentally importing something else before importing settings that depends on the config already being set. If I were you, consider continuing to use the original code. Explicit execution dependency timelines are good.
Also note that imports are hoisted. Your code of
import loadEnvVars from './settings';
loadEnvVars();
import app from './server';
is equivalent to
import loadEnvVars from './settings';
import app from './server';
loadEnvVars();
I am trying to add Objection.js to my project (using ES6 "type": "module"), and getting this error which points to ./models/user.js:
import { Model } from "objection";
^^^^^
SyntaxError: The requested module 'objection' does not provide an export named 'Model'
Using the following code:
./methods.js
import User from "./models/user.js";
async function getInfo(idnum) {
const someUser = await User.query().findById(idnum);
return someUser;
}
./models/user.js
import db from "../connection.js";
import { Model } from "objection";
Model.knex(db);
class User extends Model {
static get tableName() {
return "users";
}
}
export default User;
./connection.js
const environment = process.env.NODE_ENV || "development";
import knexfile from "../knexfile.js";
const connection = knexfile[environment];
import knex from "knex";
const db = knex(connection);
export default db;
UPDATE
The creator of Objection.js said import { Model } from "objection" should work.
What am I doing wrong?
The only current workaround appears to be importing the Model like this:
import objection from "objection";
const { Model } = objection;
since Objection.js does exports like this:
export default { Model }
and not like this:
export { Model }
I hope that you are using a .mjs extension for the file if you are using import in a Node app.
But if you are using a .js as extension then you have to call that module using require.
const { Model } = require('objection');
This was the problem I once had... I don't know if this is the solution to your problem.
I've defined a class that uses ProcessHelper.hostName and I want to know how to import ProcessHelper in the class
Exporting/Importing is described in detail here: https://www.typescriptlang.org/docs/handbook/modules.html
In your case, you could export your class as:
export class ProcessHelper { ... }
and import it somewhere else as:
import { ProcessHelper } from './path/to/process-helper';
There is an export-import syntax for legacy modules and a standard export format for modern ES6 modules
// export the default export of a legacy (`export =`) module
export import MessageBase = require('./message-base');
// export the default export of a modern (`export default`) module
export { default as MessageBase } from './message-base';
// export an interface from a legacy module
import Types = require('./message-types');
export type IMessage = Types.IMessage;
// export an interface from a modern module
export { IMessage } from './message-types';
more details
import 'jquery'; // import a module without any import bindings
import $ from 'jquery'; // import the default export of a module
import { $ } from 'jquery'; // import a named export of a module
import { $ as jQuery } from 'jquery'; // import a named export to a different name
import * as crypto from 'crypto'; // import an entire module instance object
export var x = 42; // export a named variable
export function foo() {}; // export a named function
export default 42; // export the default export
export default function foo() {}; // export the default export as a function
export { encrypt }; // export an existing variable
export { decrypt as dec }; // export a variable as a new name
export { encrypt as en } from 'crypto'; // export an export from another module
export * from 'crypto'; // export all exports from another module
// (except the default export)
I have migrated my project to ESM and thus using .mjs in all my files in nodejs.
Previously in CommonJs, I could require a file right in the middle of a ES6 class function in order to load it only when needed.
module.exports = class Core{
constructor() {
this.init = this._init.bind(this)
return this.init()
}
async _init(){
const module = require('module')
//use required file/module here
}
}
But now when using Michael Jackson Scripts a.k.a .mjs, I cannot import a file on demand:
import Koa from 'koa'
export default = class Core{
constructor() {
this.init = this._init.bind(this)
return this.init()
}
async _init(){
import module from 'module'
//use imported file/module here
}
}
My app has many files/modules that are not consumed immediately, and can more can always be added in future, thus hardcoding the imports at the begining of the file is not an option.
Is there a way to import the files dynamically on demand when needed?
With a little modification from this answer, I managed to get it working via:
import Koa from 'koa'
export default = class Core{
constructor() {
this.init = this._init.bind(this)
return this.init()
}
async _init(){
const router = await import('./Router')
//use imported file/module here
}
}
Or you can use a promise if you are into that:
import('./router')
.then(something => {
//use imported module here
});
This suits me for now until the spec if finalised and shipped
I am trying to integrate graphql with my vue project.
I am following these instructions: https://github.com/Akryum/vue-apollo
I have npm installed 'apollo-client' as required, but for some reason i can't import 'createBatchingNetworkInterface'.
this is my main.js file:
import Vue from 'vue'
import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client'
import VueApollo from 'vue-apollo'
import App from './App'
import router from './router'
and this is the index.d.ts file of my apollo-client:
export { print as printAST } from 'graphql/language/printer';
export { ObservableQuery, FetchMoreOptions, UpdateQueryOptions, ApolloCurrentResult } from './core/ObservableQuery';
export { WatchQueryOptions, MutationOptions, SubscriptionOptions, FetchPolicy, FetchMoreQueryOptions, SubscribeToMoreOptions, MutationUpdaterFn } from './core/watchQueryOptions';
export { NetworkStatus } from './core/networkStatus';
export * from './core/types';
export { ApolloError } from './errors/ApolloError';
import ApolloClient, { ApolloClientOptions } from './ApolloClient';
export { ApolloClientOptions };
export { ApolloClient };
export default ApolloClient;
I don't see here the 'createBatchingNetworkInterface' desired object.
I don't know what am i doing wrong here.
It sounds like you're using Apollo Client 2.0.You should downgrade to an older version (1.9.3) to continue using network interfaces, including the batching one.
The newest version of the client uses Links instead. You can check out the upgrade guide here if you are interested. you can still batch requests in 2.0 using apollo-link-batch-http.