mvc-middleware
Mvc middleware for express like .Net Mvc
How to use
index.js
import express, { Router } from 'express';
import { MvcMiddleware } from 'mvc-middleware';
const app = express();
MvcMiddleware.connect(app, Router);
app.listen(3000, 'localhost');
By default, place for controllers is my-project/controllers
.
You can specify your controller location:
index.js
import express, { Router } from 'express';
import { MvcMiddleware } from 'mvc-middleware';
const app = express();
const directoryPath = path.join(__dirname, 'src', 'some-folder', 'controllers');
new MvcMiddleware(app, Router)
.registerControllers(directoryPath)
.run();
app.listen(3000, 'localhost');
Controller sample:
my-project/controllers/users-controller.js
import { UserService } from '../domain/users';
import { ControllerBase } from './base/controller-base';
export class UsersController extends MvcController {
static area = '/users';
static get = {
'/api/users/list': 'list',
'/api/users/:userId': 'getById',
'/users': 'userListPage',
':userId': 'userPage',
}
static post = {
'/api/users/add': 'add',
}
constructor(request, response) {
super(request, response);
this.users = [{
id: 1,
name: 'user 1',
}];
}
userListPage() {
return this.view('list');
}
userPage(userId) {
return this.view('user');
}
list() {
return this.ok(this.users);
}
getById(userId) {
const user = this.users.find(user => user.id === userId);
return this.ok(user);
}
add({ name }) {
this.users.push({
id: this.users.length + 1,
name,
});
return this.ok('user is added');
}
}
export default UsersController;
Default paths for views is my-project/public/views/*.html
and my-project/public/views/<controller area>/*.html
.
You change it by overriding getViewPath(viewName, area)
method of MvcController
.
If you want to get query params and body content you should use connect another middleware, that will handle requests before MvcMiddleware like bellow.
index.js
import path from 'path';
import express, { Router } from 'express';
import bodyParser from 'body-parser';
import { MvcMiddleware } from 'mvc-middleware';
const app = express();
const rootPath = path.join(__dirname, 'public');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(publicPath));
MvcMiddleware.connect(app, Router, container);
app.listen(3000, 'localhost');
Dependency injection
You can connect any container to resolve your dependencies, that provide follow contract:
export interface IDependencyResolver {
resolve: (type: InstanceType<any>, ...args: any[]) => InstanceType<any>;
}
for example how it looks with cheap-di
index.js
import path from 'path';
import express, { Router } from 'express';
import { MvcMiddleware } from 'mvc-middleware';
import { container } from 'cheap-di';
import { Logger } from './logger';
import { ConsoleLogger } from './console-logger';
container.registerType(ConsoleLogger).as(Logger);
const app = express();
MvcMiddleware.connect(app, Router, container);
app.listen(3000, 'localhost');
users-controller.js
import { UserService } from '../domain/users';
import { ControllerBase } from './base/controller-base';
export class UsersController extends MvcController {
static get = {
'/users': 'userListPage',
}
static __constructorParams = [ Logger ];
constructor(logger, request, response) {
super(request, response);
this.logger = logger;
}
userListPage() {
this.logger.log('request to user list');
return this.view('list');
}
}
export default UsersController;
logger.js
class Logger {
constructor() {
if (new.target === Logger) {
throw new TypeError('Cannot construct Logger instances directly');
}
}
log(message) {
throw new Error("Not implemented");
}
}
export { Logger };
console-logger.js
import { Logger } from './logger';
class ConsoleLogger extends Logger {
log(message) {
console.log(message);
}
}
export { ConsoleLogger };
Controller API
Method name | Response status code | Response type | Arguments | Description |
---|
view | 200 | html | viewName: string | returns html view by name (using of getViewPath method) |
ok | 200 | text or json | model?: any | returns 200 status code with data |
created | 201 | text or json | model?: any | returns 201 status code with data |
accepted | 202 | text or json | model?: any | returns 202 status code with data |
noContent | 204 | - | - | returns 204 status code |
| | | | |
found | 302 | text | url: string | returns 302 status code |
permanentRedirect | 308 | text | url: string | returns 308 status code |
redirect | 300 - 308 | text | statusCode: number, url: string | returns redirection status code |
| | | | |
badRequest | 400 | text or json | model?: any | returns 400 status code with data |
unauthorized | 401 | text or json | model?: any | returns 401 status code with data |
forbid | 403 | - | model?: any | returns 403 status code |
notFound | 404 | text or json | model?: any | returns 404 status code with data |
conflict | 409 | text or json | model?: any | returns 409 status code with data |
| | | | |
serverError | 500 | text | message?: any | returns 500 status code with error message |
sendResponse | any http status code | text | model: any, statusCode?: number | returns status code with data. Default status code is 200 |