MasterController

Introduction

The backend fortress — a fast, modern MVC framework for Node.js.

MasterController is the backend half of Master: a pure-ESM, Node 22.12+ MVC framework that deliberately mirrors ASP.NET Core — routing and controllers, a composable middleware pipeline, dependency injection with per-request scopes, authentication and authorization, model binding and validation, layered configuration, hosted services, structured logging, caching, OpenAPI, minimal APIs, API versioning, localization, health checks, and an in-process test client — with no extra dependencies.

MasterController fortress

Boot in one file#

A MasterController app starts with a tiny server.js. setupServer() wires the framework pipeline and builds configuration, you register services and features, startMVC('app') loads your routes and pre-registers every controller, and start() validates options, starts hosted services, and finalizes the request pipeline.

server.js
// backend/server.js
import master from 'mastercontroller';
import AppContext from './app/models/AppContext.js';

master.root = import.meta.dirname;
master.environmentType = process.env.NODE_ENV || 'development';

const server = master.setupServer('http');   // wire the pipeline + build configuration
master.cors.init({ origin: ['http://localhost:3000'] });

master.addScoped('db', AppContext);          // one MasterRecord context per request → this.db
master.auth.addJwtBearer('bearer', { secret: process.env.JWT_SECRET, issuer: 'my-api' });
master.useResponseCompression();
master.useHealthChecks({ checks: { db: { check: () => true, tags: ['ready'] } } });
master.useOpenApi({ title: 'My API', version: '1.0.0', ui: '/docs' });

await master.startMVC('app');   // load routes.js + discover controllers
await master.start(server);     // validate options, start hosted services, register terminal routing

server.listen(3001, () => console.log('⚡ API on :3001'));

Controllers reply with data#

Controllers are plain ESM classes. Each request gets a fresh instance and its own DI scope; actions receive the request object and reply with typed results (this.ok, this.created, this.notFound…) or the classic this.returnJson(...). Pair them with MasterRecord queries for a complete API.

postsController.js
// app/controllers/postsController.js
export default class PostsController {
  static authorize = { '*': true, index: false, show: false };          // [Authorize] per action
  static schemas = { create: { body: { title: 'string!', body: 'string' } } };   // bind + validate → this.model

  // GET /posts
  async index() {
    const posts = await this.db.Post.toList();   // this.db: request-scoped context
    this.ok({ posts });
  }

  // GET /posts/:id(int)
  async show(obj) {
    const post = await this.db.Post.find(obj.params.id);
    if (!post) return this.notFound('No such post');
    this.ok(post);
  }

  // POST /posts — invalid input already answered 400 ValidationProblemDetails
  async create() {
    const post = await this.db.Post.add({ ...this.model, authorId: this.user.id });
    await this.db.saveChanges();
    this.logger.info('post {id} created', { id: post.id });
    this.created(`/posts/${post.id}`, post);
  }
}
API-first, view-optional
In a Master app the UI lives in Next.js, so controllers return JSON by default. MasterController also ships a pluggable view layer (returnView) if you want classic server-rendered HTML — see Views & Templates.

What’s in the box#

AreaMasterControllerASP.NET Core
Routingroutes, resources, typed constraints, route options, groups, urlForendpoint routing, MapGroup, LinkGenerator
Controllersactions, typed results, filters, static declarationsControllerBase, attributes
Minimal APIsmaster.map.get(path, handler, options)MapGet
Dependency injectionsingleton / scoped / transient, services on this, scope per request, createScope()IServiceCollection, CreateScope()
AuthenticationJWT bearer, signed cookie, custom schemes, policies, authorize, this.userAddJwtBearer, [Authorize], ClaimsPrincipal
Model bindingstatic schemas, this.model, automatic 400, ProblemDetails, typed results[ApiController], DataAnnotations
Configurationlayered sources, user secrets, Options pattern validated at start, master.environmentIConfiguration, IOptions<T>
Hosted servicesBackgroundService, periodic services, task queue, lifetime, graceful shutdowngeneric host
Loggingcategory loggers, levels from config, scopes, X-Request-Id, providersILogger<T>
Cachingresponse compression, output cache, distributed cache (memory/Redis)UseResponseCompression, [OutputCache], IDistributedCache
OpenAPIgenerated document + Swagger UIAddOpenApi
API versioningreaders, apiVersion, report headersAsp.Versioning
Localizationrequest culture, this.localizer, IntlIStringLocalizer
Health checks/health/live, /health/ready, tagged checksMapHealthChecks
TestingcreateTestClient() — in-process, cookie jar, bearerWebApplicationFactory
Middleware · WebSockets · Security · Monitoringpipeline stages, Socket.IO controllers, CSRF/rate limiting/headers, Prometheus + Redis scaling