Rules Of Architecture
Overview
Storona does not provide any functionality for validating exports per se, however it enforces certain file structure rules to ensure that the codebase is maintainable and readable.
Rules of architecture are a set of guidelines that should be followed when creating a new file. These rules are enforced by the parsing engine and will result in a warn or error if not followed.
Rules
Handler Definition
You can define only 1 handler in a single file.
This rule is enforced to ensure that the file is not cluttered with multiple handlers. This makes it easier to maintain and read the codebase.
ERROR
import { define } from "@storona/express";
const validateAuth = define((_req, res) => {
// ...
});
const getBody = define((req, res) => {
return req.body;
});
export default define((req, res) => {
validateAuth(req, res);
const body = getBody(req, res);
res.send(`Hello ${body.name}!`);
});
OK
import { define } from "@storona/express";
import { getBody } from "../utils/getBody";
export default define((req, res) => {
const body = getBody(req);
res.send(`Hello ${body.name}!`);
});
import type { Request } from "express";
export function getBody(req: Request) {
return req.body;
}
import { app } from "..";
app.use((_req, res, next) => {
// ...
next();
});
Default Export
The handler must be an unnamed default export of the file.
This rule is enforced to ensure that the handler is easily accessible when reading the code. This makes it easier to work with the contents of a route.
ERROR
import { define } from "@storona/express";
const handler = define((req, res) => {
res.send("Hello world!");
});
export default handler;
OK
import { define } from "@storona/express";
export default define((req, res) => {
res.send("Hello world!");
});
Function Signature
There must be used an appropriate function signature for the handler.
NOTE
Function signatures are wrappers around the handler function that provide strict type checking. This ensures that the handler is correctly defined and that the codebase is maintainable.
This rule is enforced to ensure better DX and less boilerplate. It also helps to avoid any confusion when working with the routes.
ERROR
import type { Request, Response } from "express";
export default (req: Request, res: Response) => {
res.send("Hello world!");
};
OK
import { define } from "@storona/express";
export default define((req, res) => {
res.send("Hello world!");
});
Route Overriding
Files with overridden route or method must start with !
.
For example, apples/!someroute.get.ts
.
This rule is enforced to ensure that the route is overriden in a file structure. This makes it easier to understand the route structure of the application.
ERROR
import { define } from "@storona/express";
export const route = /foo|bar/;
export default define((req, res) => {
res.send("Caught foobar!");
});
OK
// Note the `!` in the file name
import { define } from "@storona/express";
export const route = /foo|bar/;
export default define((req, res) => {
res.send("Caught foobar!");
});