So I am working in a project, which uses Nest.js
I have a custom package, which exports the configured redis object.
What I need to do, is initialize the custom redis class in a function, but all cases in our code, show how to do it in a class. Like so:
import { RedisService } from 'custom-redis-package';
//...
export class Gateway implements /*...*/ {
constructor(
private readonly redisService: RedisService,
) {
//...
}
public foo() {
this.redisService.bar()//... Use the redisService freely here.
}
}
The problem is now I need to initialize this redis package in a function in main.ts to use redis as session memory.
import { AppModule } from './app.module';
import { RedisService } from 'custom-redis-package';
import * as session from 'express-session';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const redis = new RedisService(); // This would work, but it want's the entire config object. So password, user, all the urls and so on, and it seems like a DRY violation
app.use(
session({
secret: 'secret',
resave: false,
saveUninitialized: false,
store: redis.getSessionStorage(session),//Unable to, RedisService is not initialized
}),
);
await app.listen(3000);
}
bootstrap();
So, how can I initialize RedisService without the whole config mess in a function?
Turns out there is smth like:
app.get(serviceAsImportedModule).
More info here:
https://docs.nestjs.com/standalone-applications#getting-started
Related
I am exporting this function:
import { MongoClient } from 'mongodb';
import nextConnect from 'next-connect';
const client = new MongoClient('mongodb://localhost:27017/nextauth', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log('hello why is this printing');
async function database(req, res, next) {
if (!client.isConnected()) await client.connect();
console.log('connected');
req.dbClient = client;
req.db = client.db('nextauth');
return next();
}
export default database;
And i am importing it here:
import database from '../../middlewares/database'
handler.use(database)
For context - This is a next js application and what you are seeing is next-connect code (basically just node js).
As you can see im only exporting the single function, So why does every line in the file execute?
The file has to be executed in order for the function declaration to create the function and the export statement to create the export.
I have a made a NestJS microservice package and separate NestJS client application for contacting the microservice. Below given is the code used in the client application. In microservice the method used is #messagePattern and it is functional. My question is how a front-end app can contact directly to the microservice without going through the client also how to setup swagger in microservice or test it directly from a postman ?
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');
}
}
You cannot call the service directly. You need to create a controller (to bind to an endpoint) which then can call the service.
Examples can be found in the NestJS Documentation (https://docs.nestjs.com/microservices/basics).
I am very new to typescript/javascript, I am trying to build backend rest apis with session
following is app.ts file
import express from "express";
import { applyMiddleware, applyRoutes } from "./utils";
import routes from "./services";
const app = express();
var ses= {
secret: "secret_session",
resave: true,
saveUninitialized: true,
cookie: { maxAge: 3600000,secure: false, httpOnly: true
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1)
ses.cookie.secure = true
}
app.use(session(ses));
applyRoutes(routes, app);
I have started the server and applied the middlewares for error handling but those are not related to question in my opinion so I'm not adding code for it. Following is my routes.ts code where I'm trying to set the session.
import { Request, Response } from "express";
import { getAll, getByKeyword, addNewProduct } from "./productControllers";
{
path: "/api/v1/getAllProducts",
method: "get",
handler: [
(req: Request, res: Response) => {
getAll()
.then((row: any) => {
var sess = req.session;
sess.views = 1;
res.status(200).json({ data: row });
})
.catch(err => {
res.json({
message: err
});
});
}
]
}
I'm getting error at sess.views = 1;
I have tried the suggested questions before asking it, none of them were of any help to me.
EDIT:
I have created an index.ts
import searchRoutes from "./products/routes";
export default [...searchRoutes];
I have another util class
export const applyRoutes = (routes: Route[], router: Router) => {
for (const route of routes) {
const { method, path, handler } = route;
(router as any)[method](path, handler);
}
}
You are using an interface which is Request for express.js. But it doesn't have type definition for session. So typescript throws a compile error. To solve it you need to define session type under Request interface.
You could define a session.d.ts file under your project. And create required types & interfaces. Like:
declare global {
namespace Express {
interface Request {
session?: Session;
sessionID?: string;
}
}
}
interface Session{
mySessionVarible:string
}
But the good thing is we have DefinitilyTyped project which you can find many type definitions. This needs to solve your compile problem.
npm install --save-dev #types/express-session
And don't forget to change your import for Request.
import { Request, Response } from "#types/express-session";
Im trying to apply middleware based on config like so:
export class UsersModule implements NestModule{
configure(consumer: MiddlewaresConsumer): void {
const authRoutes = UsersController.getAuthRoutes();
consumer
.apply(AuthMiddleware)
.forRoutes(...authRoutes);
}
}
method getAuthRoutes is static:
public static getAuthRoutes(){
return [
{ path: `/api/users`, method: RequestMethod.ALL},
];
}
My AuthMIddleware is pretty basic:
#Middleware()
export class AuthMiddleware implements NestMiddleware {
constructor(
#Inject(constants.logger) private logger: Winston,
){}
resolve(...args: any[]): ExpressMiddleware {
// return passport.authenticate('jwt', { session: false });
return (req, res, next) => {
this.logger.debug('AuthMiddleware');
next();
};
}
}
It just logs line in console. Im trying to access via get request /api/users, im getting list of users, but no AuthMiddleware message in console. Any advices?
See my issue here. Its just misunderstanding of documentation.
I am having a file, where I create exports dynamically like:
import fs from 'fs';
import path from 'path';
import Sequelize from 'sequelize';
import config from '../config';
const sequelize = new Sequelize(config.database.name, config.database.user, config.database.password, {
dialect: 'postgres',
host: config.database.host,
logging: false,
define: {
underscored: true
}
});
const db = {
sequelize,
Sequelize
};
fs
.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js');
})
.forEach(function(file) {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ('associate' in db[modelName]) {
db[modelName].associate(db);
}
});
export default db;
With babel 5 register hook this kind of code was working just fine. Now I was about to upgrade to babel 6 and so I used require('babel-register'). It is working fine, except that if I want to call the dynamic added attributes like
import { sequelize } from './the_above_file';
then the variable sequelize is always undefined.
But if I call
import db from './the_above_file';
then db.sequelize has a value.
Is there a way to fix it or do I have to avoid dynamic values in the export;
import { sequelize } from './the_above_file'; should have never worked since you don't have a named export with that name. You only have a default export which is an object. Properties of the default export are not the same as having named export.
That was considered a bug in Babel 5 and Babel 6 fixed it.
You can do
import db from './the_above_file';
const { sequelize } = db;
to extract the property sequelize of your default export.