Nodejs | Exhange Data Between Controllers - node.js

I have my PlantsController where I get the Plants like this:
function getAll() {
const plants= HttpRequestPromise.get(config.ApiURL+'allPlants', config.head);
return plants;
}
export class PlantsController {
...
public getPlants() {
return async (req: Request, res: Response, next?: NextFunction): Promise<Response> => {
try {
const plants = await getAll();
return res
.status(OK)
.send(plants);
} catch (e) {
next(e);
}
};
}
...
}
export default new PlantsController();
I have PlantedActivitiesController where I get the PlantedActivities
like this:
import plantsController from '../plants/plants.controller';
export class PlantedActivitiesController {
...
public getPlantedActivities(){
return async (req: Request, res: Response, next?: NextFunction): Promise<Response> => {
try {
var plants = ? // How can i get the plants from PlantsController?
// plantsController.get...?
...
} catch (e) {
next(e);
}
};
}
...
}
So, how can I get the plants to my PlantedActivitiesController?

Found it:
I created a getPlantsHelper like this:
function getAll() {
const plants= HttpRequestPromise.get(config.ApiURL+'allPlants', config.head);
return plants;
}
export class PlantsController {
...
//-----------
public getPlantsHelper(){
return getAll()
}
//-----------
public getPlants() {
return async (req: Request, res: Response, next?: NextFunction): Promise<Response> => {
try {
const plants = await getAll();
return res
.status(OK)
.send(plants);
} catch (e) {
next(e);
}
};
}
...
}
and then in PlantedActivities I did:
activeSeeds = await plantsController.getPlantsHelper();

Related

Cannot GET /api/posts

post.controller.ts
class PostController implements Controller {
public path = '/posts';
public router = Router();
private PostService = new PostService();
constructor() {
this.initialiseRoutes();
}
private initialiseRoutes(): void {
this.router.get(
`${this.path}`, this.get);
}
private get = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const posts = await this.PostService.get();
res.status(200).json({ posts });
} catch (error:any) {
next(new HttpException(400, error.message));
}
};
}
export default PostController;
post.service.ts
class PostService {
private post = PostModel;
public async get(): Promise<Post[]> {
try {
const posts = await this.post.find();
return posts;
} catch (error) {
throw new Error('Unable to get posts');
}
}
}
export default PostService;
Trying out a Get request for a Blog Post Model in Nodejs+Express API with Mongodb. But getting "Cannot GET /api/posts" error. Other requests such as create posts and User CRUD actions are working fine.

Using Fastify preHandler middleware

Passing a middleware to authenticate user before accessing this route.
When I'm passing tokenController.authUser as a middleware tokenService inside tokenController is undefined. However when I run this method as a function inside the route instead of a middleware it works fine.
server.post('/api/admin/test', { preHandler: [tokenController.authUser] }, async (request: any, reply: any) => {
return null
});
Token Controller :-
import { Users } from "#prisma/client";
import ITokenService from "../../services/tokenService/ITokenService";
import ITokenController from "./ITokenController";
export default class TokenController implements ITokenController {
private readonly tokenService: ITokenService;
constructor(_tokenService: ITokenService) {
this.tokenService = _tokenService;
}
async authUser(request: any, reply: any): Promise<Users | Error> {
const authHeader = request.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (token === null)
return reply.code(401);
try {
const result = await this.tokenService.verifyToken(token);
console.log(result);
return result;
}
catch (e) {
reply.code(401);
return new Error("Error");
}
}
}
Token Service :-
import { Users } from "#prisma/client";
import ITokenService from "./ITokenService";
export default class TokenService implements ITokenService {
private readonly sign: Function;
private readonly verify: Function;
private readonly secretKey: string;
constructor(sign: Function, verify: Function, _secretKey: string) {
this.sign = sign;
this.verify = verify;
this.secretKey = _secretKey;
}
public async generateToken(user: Users): Promise<string> {
return await this.sign({ user }, this.secretKey);
}
public async verifyToken(token: string): Promise<Users | Error> {
const result = await this.verify(token, this.secretKey);
return result;
}
}
For some reason making a separate middleware function and calling tokenController.authUser inside that method works fine.
const middleware = (_req, _res, next) => {
console.log('middleware');
next()
}
server.post('/api/admin/test', { preHandler: [middleware] }, async (request: any, reply: any) => {
return null
});

Apply an interface in Typescript

I am creating a project with Node JS and Typescript, I have a class and an interface where I type all the data. What I need to know is how to apply it to the classroom.
This is my interface:
export interface IController {
url: string,
api: string
}
This is my class where I want to apply it:
import { Request, Response } from 'express';
import { constUtils } from '../utils/const.utils';
import { IController } from '../utils/model.utils';
import { utilsController } from '../utils/index.utils';
class IndexController {
public async index(req: Request, res: Response): Promise<IController> {
try {
let api = req.query.api;
let constUt = new constUtils();
let url = constUt.conf.API_MOCS[`${api}`].url;
await utilsController.utilsCsvConverter(api, url);
} catch (error) {
console.log(error);
}
}
}
export const indexController = new IndexController();
This assumes that the local variables url and api should be returned in a Promise resolving to an object specified the by IController interface:
import { Request, Response } from 'express';
import { constUtils } from '../utils/const.utils';
import { IController } from '../utils/model.utils';
import { utilsController } from '../utils/index.utils';
class IndexController {
public async index(req: Request, res: Response): Promise<IController> {
try {
let api = req.query.api;
let constUt = new constUtils();
let url = constUt.conf.API_MOCS[`${api}`].url;
await utilsController.utilsCsvConverter(api, url);
return {url, api};
} catch (error) {
console.log(error);
}
}
}
export const indexController = new IndexController();
If you want use or apply interface to the class you should have to implement it within the applied class. Below code might give you clear idea.
class IndexController implements csvModel {
url: string;
api: string;
public async index(req: Request, res: Response): Promise<IController> {
try {
this.api = req.query.api;
let constUt = new constUtils();
this.url = constUt.conf.API_MOCS[`${api}`].url;
} catch (error) {
console.log(error);
}
}
}
export const indexController = new IndexController();

How to return exception from common error handler in nodejs

My API is in nodejs with a layered architecture. Im facing problem in returning an error from anywhere in the application. My express error handler is capturing the error but then my controller logic is also getting executed. Below is my sample code.
//accountcontroller.ts
updateAccountStatus = async (req: Request, res: Response, next: any): Promise<any> => {
let responseFromService = await AccountService.updateAccountStatus(
parseInt(req.params.accountId),
next
);
// even after the exception it comes here, after visiting the express default error code
if (responseFromService !== undefined) {
responseHandler(res, 200, responseFromService);
}
if (responseFromService.err) {
return next(responseFromService);
}
//accountService.ts
public updateAccountStatus = async (accountId: number, next: any): Promise<any> => {
let accountStatusReponse = await accountRepository.updateAccountStatus(accountId, next);
return accountStatusReponse;
};
//accountRepository.ts
public updateAccountStatus = async (accountId: any, next: any): Promise<any> => {
try {
const updateAccountStatus = await Accounts.updateOne(
{ id: accountId },
{ accountStatus: true }
);
if (updateAccountStatus) {
return updateAccountStatus;
} else {
throw new Error("Error while saving the data");
}
} catch (error) {
error.err = error.message;
error.status = 500;
return next(error);
}
};
//responseHandler is my commons file to return the responses.
responseHandler.ts
class responseHandler {
constructor() {}
statusCodeResponse = (
response: any,
message: string,
statusCode: number,
): void => {
response.statusMessage = statusMessage;
response
.status(statusCode)
.json(
response: response,
message: message
)
);
};
}
//app.js
import accountRouter from "./routes/accountroute";
var app = express();
app.use("/accounts", accountRouter);
Any suggestions on how do I make returns so that in case of an exception the control don't move back to the previous file.

I can see node-express server response but i cannot use it in my angular2 promise service

I have my object returned from the server response, which i can see in the networks tab response on google chrome dev tools.
module.exports = (req, res) => {
var obj = {
name: "Thabo",
age: 23
};
res.json({obj})
};
And I have the angular2-typescript service that uses a promise to get the response observable from the server
export class MyService {
constructor(private http: Http) { }
getMessage(): Promise<any> {
return this.http.get('/map-moving-agents')
.toPromise()
.then((res)=> {
console.log(res.json().data);
res.json().data;
})
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
I even logged the response on the 'then' of the promise and it logs undefined.
And this is the component that uses the service
export class MapMovingAgents implements OnInit{
msg: {};
constructor(private myService: MyService){}
getMessage(): void {
this.myService.getMessage().then((res) => { this.msg = res;})
console.log(this.msg);
}
ngOnInit(): void {
this.getMessage();
}
}
getMessage(): void {
this.myService.getMessage().then((res) => { this.msg = res;})
console.log(this.msg);
}
will log undefined because getMessage() function is an async function.
Change it to
getMessage(): void {
this.myService.getMessage().then((res) => {
this.msg = res;
console.log(this.msg);
});
}
And your response doesn't have a data field so res.json().data; wil be undefined return only res.json() or res.json().obj
You need to return the final value for the rest of your code to use
return this.http.get('/map-moving-agents')
.toPromise()
.then((res)=> {
console.log(res.json().data);
return res.json().data; <--------------
})
.catch(this.handleError);
}

Resources