MasterController
Controllers
Plain ESM classes that turn requests into responses.
Controllers live in app/controllers/. Each request constructs a fresh instance and calls the action method named in the route. Actions receive the request object and reply with one of the response helpers.
Anatomy of a controller#
postsController.js
import db from '../models/db.js';
export default class PostsController {
constructor(requestObject) {
this.requestObject = requestObject;
}
// GET /posts
async index() {
const data = await db.Post.toList();
this.returnJson({ data });
}
// POST /posts
async create(obj) {
const post = db.Post.new();
Object.assign(post, obj.params.formData || {});
await post.save();
this.returnJson({ data: post });
}
// GET /posts/:id
async show(obj) {
const post = await db.Post.where((p) => p.id == $$, Number(obj.params.id)).single();
if (!post) return this.returnError(404, 'Not found');
this.returnJson({ data: post });
}
}Response helpers#
| Method | Effect |
|---|---|
this.returnJson(data) | Send JSON (200, or data.status if 4xx/5xx). |
this.returnError(code, msg, details?) | Send a structured JSON error. |
this.returnView(data) | Render the action’s view (needs a view engine). |
this.returnPartialView(view, data) | Render a partial without a layout. |
this.redirectTo(path) | Redirect (same-origin validated). |
this.redirectBack(fallback?) | Redirect to the referer, or a fallback. |
It's returnJson, not json
The response methods are
returnJson, returnError, returnView, and redirectTo — there is no this.json() or this.render().Accessing request data#
request-data.js
async show(obj) {
const id = obj.params.id; // route parameter (casing preserved)
const q = obj.params.query.search; // ?search=...
const body = obj.params.formData; // parsed JSON / form body
const method = obj.type; // 'get' | 'post' | ...
const req = obj.request; // raw Node request
const res = obj.response; // raw Node response
} Note
For
application/json requests, the parsed body is available as obj.params.formData. Multipart uploads expose obj.params.formData.files.Per-request state#
Each instance gets this.state (shared with middleware) plus this.__request, this.__response, and the route context — set on the instance, never the prototype, for concurrency safety.