Introduction
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.

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.
// 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.
// 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);
}
}returnView) if you want classic server-rendered HTML — see Views & Templates.What’s in the box#
| Area | MasterController | ASP.NET Core |
|---|---|---|
| Routing | routes, resources, typed constraints, route options, groups, urlFor | endpoint routing, MapGroup, LinkGenerator |
| Controllers | actions, typed results, filters, static declarations | ControllerBase, attributes |
| Minimal APIs | master.map.get(path, handler, options) | MapGet |
| Dependency injection | singleton / scoped / transient, services on this, scope per request, createScope() | IServiceCollection, CreateScope() |
| Authentication | JWT bearer, signed cookie, custom schemes, policies, authorize, this.user | AddJwtBearer, [Authorize], ClaimsPrincipal |
| Model binding | static schemas, this.model, automatic 400, ProblemDetails, typed results | [ApiController], DataAnnotations |
| Configuration | layered sources, user secrets, Options pattern validated at start, master.environment | IConfiguration, IOptions<T> |
| Hosted services | BackgroundService, periodic services, task queue, lifetime, graceful shutdown | generic host |
| Logging | category loggers, levels from config, scopes, X-Request-Id, providers | ILogger<T> |
| Caching | response compression, output cache, distributed cache (memory/Redis) | UseResponseCompression, [OutputCache], IDistributedCache |
| OpenAPI | generated document + Swagger UI | AddOpenApi |
| API versioning | readers, apiVersion, report headers | Asp.Versioning |
| Localization | request culture, this.localizer, Intl | IStringLocalizer |
| Health checks | /health/live, /health/ready, tagged checks | MapHealthChecks |
| Testing | createTestClient() — in-process, cookie jar, bearer | WebApplicationFactory |
| Middleware · WebSockets · Security · Monitoring | pipeline stages, Socket.IO controllers, CSRF/rate limiting/headers, Prometheus + Redis scaling | — |