I have controller homeController where i do export let index
import { Request, Response } from "express";
export let index = (req: Request, res: Response) => {
console.log("home");
};
In app.ts
import * as homeController from "../src/modules/home/controllers/home.controller";
const app = express();
...
app.get("/", homeController.index);
tslint passed it but whe i do npm start (npm run serve), i getting the error
internal/modules/cjs/loader.js:589
throw err;
^
Error: Cannot find module '../src/modules/home/controllers/home.controller'
path to /home.controller is right
The problem is that in your HomeController you are exporting a function, the index function. So, when you import that file you are already importing the function so
import * as homeController from "../src/modules/home/controllers/home.controller";
const app = express();
...
app.get("/", homeController);
might work
If you want to do homeController.index
In you homeController module you should do
import { Request, Response } from "express";
let index = (req: Request, res: Response) => {
console.log("home");
};
module.exports = {
index
}
Related
I'm having a problem during the initialization of a system. In order to initialize this system, I'm calling the index.ts file. This file imports an initializer class called StartServer. This class has an async method called start that initialize all the system database connections and express server. The problem is, somehow Node initialize express files, index.routes.ts, where the routes are defined, and all it dependencies, before starting the index file with the initializer class, generating an error of undefined due to no connections exits at this point.
index.ts file :
import { StartServer } from './services';
StartServer.start();
StarterServer.ts file :
export class StartServer {
public static async start(): Promise<void> {
try {
const configPort: IConfig = config.get('App.port');
await Connections.startDatabaseConnections();
const server = ServerFactory.create();
await server.init();
console.log(`Server is listening at port ${configPort}...`);
} catch (error) {
console.error((error as Error)?.stack);
}
}
}
ExpressServer.ts file :
import routes from '../routes/index.routes';
export class ExpressApp {
private app = express();
private port = config.get('App.port');
routes() {
this.app.use(routes);
}
async init() {
this.routes();
this.app.listen(this.port);
}
}
index.routes.ts file :
import express from 'express';
const router = express.Router();
router.get('/', (_, res) => {
res.status(200).json({ message: 'App listening...' });
});
export default router;
ServerFactory.ts file :
import { ExpressApp } from '#src/services';
export class ServerFactory {
public static create() {
return new ExpressApp();
}
}
In Node, import (and require) are synchronous. As soon as you require a file it is executed.
// a.js
import b from './b';
console.log('a.js');
//b.js
import c from './c';
console.log('b.js');
// c.js
console.log('c.js');
That will output:
c.js
b.js
a.js
In your case, the index.routes.ts will be executed as soon as it's required by ExpressServer.ts. One pattern to avoid initialisation is to export a factory function to perform the setup. You're doing this for your server already!
import express from 'express';
export default function createRouter() {
const router = express.Router();
router.get('/', (_, res) => {
res.status(200).json({ message: 'App listening...' });
});
}
Im trying to send a connect call to my api from my vue (i use vue.js),
but when i get the object req.body in my back, the object is empty
I've read this : Axios post request.body is empty object
but it didn't help me
(it works from Postman with the body filled and the option x-www-form-encoded)
i got this got from my Vue :
My vue service.js
import Axios from 'axios';
class APIClient {
constructor () {
this.client = Axios.create({
baseURL: 'http://localhost:8080'
});
}
async connect () {
const params = new URLSearchParams();
params.append('mail', 'test');
params.append('pwd', 'mypwd');
return await this.client.get('/api/user/auth', params);
}
and i got this in my back :
index.ts :
import express from "express";
var cors = require('cors');
import "reflect-metadata";
var bodyParser = require('body-parser')
const http = require('http');
const MainRouter = require('./routes/main_router');
let port = 8080;
const server = express();
server.use(cors({origin: true}))
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended: true}))
let mainRouter = new MainRouter(server);
const httpServer = http.createServer(server);
httpServer.listen(port);
console.log('Server is listening');
and the main_router.ts
import express from 'express';
import mysql from "promise-mysql";
export default class MainRouter {
public server: express.Express;
constructor (server: express.Express) {
super();
this.server = server;
this.server.get("/api/user/auth", async (req: any, res: any) => {
if (req.body) //the req.body is equal to {} instead of {mail: 'test', ...
return res.json(await this.userManager.getUserByCredidentials(req.body));
else return res.json([])
});
}
}
module.exports = MainRouter;
I don't know if i have something to add in my express server or in my vue with axios ?
You are passing the mail and pwd as GET parameters and not at the request body. You can access the using req.query, but ....
You should avoid sending creds as parameters of the url with GET, use the body and POST instead. For more information see this post.
Here is an example:
return await this.client.post('/api/user/auth', {
mail: "test",
pwd: "mypwd"
});
and of course do not forget to change this.server.get("/api/user/auth",... to this.server.post("/api/user/auth",...
I have a Nodejs with express application. I register my routes using tsoa.
When i add swagger-ui-express to my nodejs application I get the following error Error: TypeError: Router.use() requires a middleware function but got a undefined
I initialize the app as follows:
app.ts
import config from './api/build/config';
import express from 'express';
function startServer() {
const app = express();
require('./api/loaders').default(app);
app.listen(config.port, () => {
console.log(`
################################################
🛡️ Server listening on port: ${config.port} 🛡️
################################################
`);
});
}
startServer();
loaders\index.ts
import {Express} from 'express';
export default (app: Express) => {
require('./express').default(app);
console.log('✌️ Express loaded');
require('./swagger').default(app);
console.log('✌️ Swagger loaded');
};
express.ts
import bodyParser from 'body-parser';
import {Express, Request, Response, NextFunction} from 'express';
import logger from 'morgan';
import { RegisterRoutes } from '../routes';
import cors from 'cors';
export default function startExpress(app: Express) {
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(cors());
//register all routes from the routes generated by tsoa
RegisterRoutes(app);
// catch 404 and forward to error handler
app.use((request: Request, response: Response, next: NextFunction) => {
const error = new Error('404 Not Found');
error['status'] = 404;
next(error);
});
// error handlers
// error handler will print stacktrace only in development
app.use((error: any, request: Request, response: Response) => {
response.locals.message = error.message;
response.locals.error = request.app.get('env') === 'development' ? error : {};
response.status(error.status || 500);
response.send(error.message);
});
}
swagger.ts
import { Express } from 'express';
import swaggerUi from 'swagger-ui-express';
export default function startSwagger(app: Express) {
try{
const swaggerDocument = require('../build/swagger.json');
var options = {
explorer: true
};
app.use('/swagger', swaggerUi.server, swaggerUi.setup(swaggerDocument, options));
}
catch(error){
throw new Error(error);
}
}
I also tried to use import statements instead of require, but it doesn't make a difference. Why does my compiler suddenly say my app Express object is a Router object and how do I set up nodejs with express and registering routes in different files?
To answer your question...
Why does my compiler suddenly say my app Express object is a Router object...
It doesn't. You can see a reference to the Router.use() function because it is just eventually called inside the app.use() function.
The actual issue here as mentioned in the error message is the middleware function being undefined. This is because inside your swagger.ts file, you specified swaggerUi.server as the middleware function but it needs to be changed to swaggerUi.serve.
import { Express } from 'express';
import swaggerUi from 'swagger-ui-express';
export default function startSwagger(app: Express) {
try{
const swaggerDocument = require('../build/swagger.json');
var options = {
explorer: true
};
// The problem was here... change server to serve
app.use('/swagger', swaggerUi.serve, swaggerUi.setup(swaggerDocument, options));
}
catch(error){
throw new Error(error);
}
}
I'm experimenting with organizing my routes with Express router and classes in Typescript. This is what I've tried so far. The index.ts file is supposed to reference the Notes class in the notes.ts file which exposes an endpoint via a private method.
So, for example, I have a file index.ts
import * as express from "express";
import rootRoutes from "./root";
import { Notes } from "./notes";
import accountRoutes from "./account";
const router: express.Router = express.Router();
router.use("/", rootRoutes);
router.use("/account", accountRoutes);
router.use("/notes", Notes.routes);
export = router;
and another file notes.ts:
import express, { Router, Request, Response, NextFunction } from "express";
const router: express.Router = express.Router();
export class Notes {
constructor() {
this.routes();
}
private routes(): void {
//Get notes
router
.route("/")
.get((req: Request, res: Response, next: NextFunction) => {
res.send("notes");
});
}
}
What am I missing here?
You are calling a private method router.use("/notes", Notes.routes);
To use it like you did, first you have to instantiate the class or make the method static.
Mixing class instance state with router state can be tricky, try to keep it free of any instance state.
Also I would suggest you to simplify that implementation, to something like this:
export class Notes {
static handler(req: Request, res: Response): void {
res.send('Hello from A!')
}
}
app.get('/', Notes.handler);
I'm trying to load ExpressJS routes from a Typescript class. The idea is that this should eventually be dynamic routes. But I'm already stuck at defininghard coded routes in a class.
My index.ts js looks like this:
import generic = require('./generic');
import Generic = generic.Generic;
class Test {
private app:any;
private port:number = 3000;
constructor() {
this.app = express();
new Generic();
this.app.listen(this.port, () => {
console.log('Listening on port ' + this.port);
});
}
}
export = Test;
new Test();
Then my generic.ts looks like this. I'm trying to define another route from this class:
module Generic {
export class Generic {
constructor() {
console.log('In generic');
var router:any = express.Router();
router.get('/', function (req, res) {
res.setHeader('Content-Type', 'application/json');
res.status(200).send("AAA");
});
}
}
}
export = Generic;
When I run my application then I see the message In generic appear in console. But when I load my browser it says:
Cannot GET /
So for some reason it's not really registering the route from the Generic class. What am I doing wrong?
Take a look at the sample on Microsoft's github page. Rather than using express.Router, they simply use get and import the function from an external module. It has worked pretty well for me.
app.ts
import * as express from "express";
import * as routes from "./routes/index";
var app = express();
app.get('/', routes.index);
routes/index.ts
import express = require("express")
export function index(req: express.Request, res: express.Response) {
res.render('index', { title: 'ImageBoard'});
};