@the-teacher/the-router v0.9.6
The Router
Простое и мощное решение для маршрутизации в приложениях на Express.js
, которое предоставляет чистый и интуитивно понятный способ организации маршрутов и действий.
Возможности
- Простой синтаксис определения маршрутов (похож на фреймворк Rails)
- Подход, основанный на действиях (похож на фреймворк Hanami)
- Каждое действие в отдельном файле для лучшей поддерживаемости
- Группировка маршрутов для улучшенной организации
- Автоматическая загрузка действий
Установка
npm install @the-teacher/the-router
yarn add @the-teacher/the-router
pnpm add @the-teacher/the-router
Использование
Базовые маршруты
routes/index.ts
import {
root,
get,
post,
getRouter,
routeScope as scope,
} from "@the-teacher/the-router";
// Определение корневого маршрута
root("index/index"); // Использует src/actions/index/indexAction.ts
// Определение GET и POST маршрутов
get("/users", "users/show"); // Использует src/actions/users/showAction.ts
post("/users", "users/create"); // Использует src/actions/users/createAction.ts
// Определение сгруппированных маршрутов
scope("admin", () => {
get("/users", "admin/users/create"); // Использует src/actions/admin/users/createAction.ts
post("/users", "admin/users/update"); // Использует src/actions/admin/users/updateAction.ts
});
Структура файлов действий
Каждое действие определяется в своём собственном файле и должно экспортировать функцию perform
:
src/
actions/
index/
indexAction.ts # обработчик для root("index/index")
users/
showAction.ts # обработчик для get("/users", "users/show")
createAction.ts # обработчик для post("/users", "users/create")
admin/
users/
listAction.ts # обработчик для get("/users", "admin/users/list") в scope admin
Пример файла действия:
// src/actions/users/showAction.ts
import { Request, Response } from "express";
// perform - обязательный метод для каждого действия
export const perform = (req: Request, res: Response) => {
res.json({ message: "Список пользователей" });
};
Группировка маршрутов
Группируйте связанные маршруты под общим префиксом:
scope("admin", () => {
get("/users", "admin/users/list"); // Использует src/actions/admin/users/listAction.ts
post("/users", "admin/users/create"); // Использует src/actions/admin/users/createAction.ts
});
Маршруты с Middleware
Вы можете добавлять middleware к любому маршруту:
import { authenticate } from "./middlewares/auth";
import { validateUser } from "./middlewares/validation";
// Один middleware
get("/users/:id", [authenticate], "users/show");
// Несколько middleware в порядке выполнения
post("/users", [authenticate, validateUser], "users/create");
// Корневой маршрут с middleware
root([authenticate], "index/index");
// Простые маршруты без middleware
get("/about", "pages/about");
post("/contact", "pages/contact");
// Middleware в сгруппированных маршрутах
scope("admin", [authenticate], () => {
// Эти маршруты наследуют аутентификацию из scope
get("/users", "users/show");
post("/users", "users/create");
// Дополнительный middleware для конкретного маршрута
post("/users/:id", [validateUser], "users/update");
});
Группировка маршрутов с Middleware
Вы можете добавлять middleware как к отдельным маршрутам, так и ко всей группе маршрутов:
import { authenticate } from "./middlewares/auth";
import { validateUser } from "./middlewares/validation";
import { logRequest } from "./middlewares/logging";
// Применить middleware ко всем маршрутам в группе
scope("admin", [authenticate], () => {
// Эти маршруты будут требовать аутентификации
get("/users", "users/index");
post("/users", "users/create");
// Этот маршрут будет требовать и аутентификации, и валидации
post("/users/:id", [validateUser], "users/update");
});
// Комбинирование нескольких middleware для группы
scope("api", [authenticate, logRequest], () => {
get("/stats", "stats/index");
get("/health", "health/check");
});
// Простая группа без middleware
scope("public", () => {
get("/about", "pages/about");
get("/contact", "pages/contact");
});
Middleware, указанные вторым параметром, будут применяться ко всем маршрутам внутри этой группы.
При этом вы можете добавлять дополнительные middleware к конкретным маршрутам, которые будут выполняться после middleware группы.
Структура файлов приложения:
src/
index.ts
routes/
index.ts
actions/
index/
indexAction.ts
users/
showAction.ts
createAction.ts
updateAction.ts
posts/
showAction.ts
createAction.ts
admin/
users/
listAction.ts
createAction.ts
posts/
listAction.ts
updateAction.ts
Пример маршрутов, соответствующих этой структуре:
import { root, get, post, routeScope as scope } from "@the-teacher/the-router";
// Корневой и базовые маршруты
root("index/index"); // -> src/actions/index/indexAction.ts
get("/users", "users/show"); // -> src/actions/users/showAction.ts
post("/users", "users/create"); // -> src/actions/users/createAction.ts
get("/posts", "posts/show"); // -> src/actions/posts/showAction.ts
post("/posts", "posts/create"); // -> src/actions/posts/createAction.ts
// Административная часть
scope("admin", () => {
get("/users", "users/list"); // -> src/actions/admin/users/listAction.ts
post("/users", "users/create"); // -> src/actions/admin/users/createAction.ts
get("/posts", "posts/list"); // -> src/actions/admin/posts/listAction.ts
post("/posts", "posts/update"); // -> src/actions/admin/posts/updateAction.ts
});
Это создаст маршруты:
- GET
/
->src/actions/index/indexAction.ts
- GET
/users
->src/actions/users/showAction.ts
- POST
/users
->src/actions/users/createAction.ts
- GET
/posts
->src/actions/posts/showAction.ts
- POST
/posts
->src/actions/posts/createAction.ts
- GET
/admin/users
->src/actions/admin/users/listAction.ts
- POST
/admin/users
->src/actions/admin/users/createAction.ts
- GET
/admin/posts
->src/actions/admin/posts/listAction.ts
- POST
/admin/posts
->src/actions/admin/posts/updateAction.ts
Группировка маршрутов
Группируйте связанные маршруты под общим префиксом:
scope("admin", () => {
get("/users", "users/list"); // -> src/actions/admin/users/listAction.ts
post("/users", "users/create"); // -> src/actions/admin/users/createAction.ts
});
Маршруты с параметрами
Маршруты могут включать динамические параметры:
// Базовые маршруты с параметрами
get("/users/:id", "users/show"); // -> /users/123
get("/posts/:id/comments", "posts/comments"); // -> /posts/456/comments
// Параметры с middleware
get("/users/:id", [authenticate], "users/show");
// Несколько параметров
get("/posts/:postId/comments/:commentId", "comments#show");
Порядок маршрутов
Порядок определения маршрутов имеет значение. Более специфичные маршруты должны быть определены перед более общими:
// ✅ Правильный порядок
get("/posts/featured", "posts/featured"); // Сначала специфичный маршрут
get("/posts/:id", "posts/show"); // Затем общий маршрут
// ❌ Неправильный порядок - "/posts/featured" никогда не будет достигнут
get("/posts/:id", "posts/show"); // Общий маршрут перехватывает все
get("/posts/featured", "posts/featured"); // Никогда не сработает
Организация Middleware
При использовании нескольких middleware рекомендуется группировать их в переменные для лучшей поддерживаемости:
// Группировка связанных middleware
const authMiddlewares = [authenticate, checkRole];
const validationMiddlewares = [validateUser, sanitizeInput];
// Использование групп middleware в маршрутах
get("/users", authMiddlewares, "users/index");
post("/users", [...authMiddlewares, ...validationMiddlewares], "users/create");
// В сгруппированных маршрутах
const adminMiddlewares = [authenticate, requireAdmin, logAccess];
scope("admin", adminMiddlewares, () => {
get("/users", "users/list");
// Дополнительные middleware для конкретных маршрутов
const userUpdateMiddlewares = [validateUser];
post("/users/:id", userUpdateMiddlewares, "users/update");
});
API Reference
Базовое использование:
root(scopeAction)
: Определяет корневой маршрут (/
)get(path, scopeAction)
: Определяет GET маршрутpost(path, scopeAction)
: Определяет POST маршрутput(path, scopeAction)
: Определяет PUT маршрутpatch(path, scopeAction)
: Определяет PATCH маршрутdestroy(path, scopeAction)
: Определяет DELETE маршрутoptions(path, scopeAction)
: Определяет OPTIONS маршрутhead(path, scopeAction)
: Определяет HEAD маршрутall(path, scopeAction)
: Определяет маршрут для всех HTTP методовscope(prefix, callback)
: Группирует маршруты под общим префиксом
С middleware:
root(middlewares[], scopeAction)
: Определяет корневой маршрут с middlewareget(path, middlewares[], scopeAction)
: Определяет GET маршрут с middlewarepost(path, middlewares[], scopeAction)
: Определяет POST маршрут с middlewareput(path, middlewares[], scopeAction)
: Определяет PUT маршрут с middlewarepatch(path, middlewares[], scopeAction)
: Определяет PATCH маршрут с middlewaredestroy(path, middlewares[], scopeAction)
: Определяет DELETE маршрут с middlewareoptions(path, middlewares[], scopeAction)
: Определяет OPTIONS маршрут с middlewarehead(path, middlewares[], scopeAction)
: Определяет HEAD маршрут с middlewareall(path, middlewares[], scopeAction)
: Определяет маршрут для всех HTTP методов с middlewarescope(prefix, middlewares[], callback)
: Группирует маршруты с middleware
Примеры:
// Базовое использование
root("index/index");
get("/users", "users/show");
post("/users", "users/create");
put("/users/:id", "users/update");
patch("/users/:id", "users/patch");
destroy("/users/:id", "users/delete");
options("/users", "users/options");
head("/users", "users/head");
all("/api", "api/handle");
scope("admin", () => {
/* маршруты */
});
// С middleware
const authMiddlewares = [authenticate, logRequest];
root([authenticate], "index/index");
get("/users", authMiddlewares, "users/show");
put("/users/:id", authMiddlewares, "users/update");
scope("admin", authMiddlewares, () => {
/* маршруты */
});
Маршруты с регулярными выражениями
Вы можете использовать регулярные выражения для путей маршрутов:
// Сопоставление путей, заканчивающихся на 'fly'
get(/.*fly$/, "insects#list"); // Совпадает с: /butterfly, /dragonfly
get(/^\/api\/v\d+\/.*$/, "api#handle"); // Совпадает с: /api/v1/users, /api/v2/posts
// Маршруты с регулярными выражениями и middleware
get(/^\/secure\/.*$/, [authenticate], "secure#handle");
// Порядок важен и для маршрутов с регулярными выражениями
get(/^\/api\/v1\/users$/, "users/list"); // Сначала специфичный маршрут
get(/^\/api\/v1\/.*$/, "api/handle"); // Затем общий маршрут
Примечание: При использовании регулярных выражений путь передается в Express.js
как есть, без какой-либо нормализации.
Ресурсные маршруты
Подобно Ruby on Rails, вы можете определить набор RESTful маршрутов для ресурса:
resources("posts");
Это создаст следующие маршруты:
GET /posts
->src/actions/posts/indexAction.ts
GET /posts/new
->src/actions/posts/newAction.ts
POST /posts
->src/actions/posts/createAction.ts
GET /posts/:id
->src/actions/posts/showAction.ts
GET /posts/:id/edit
->src/actions/posts/editAction.ts
PUT /posts/:id
->src/actions/posts/updateAction.ts
PATCH /posts/:id
->src/actions/posts/updateAction.ts
DELETE /posts/:id
->src/actions/posts/destroyAction.ts
Вы можете добавить middleware для всех маршрутов ресурса:
const postMiddlewares = [authenticate, logRequest];
resources("posts", postMiddlewares);
Ресурсы также можно группировать:
scope("admin", [authenticate], () => {
resources("posts"); // Маршруты будут начинаться с /admin
resources("users"); // Маршруты будут начинаться с /admin
});
Это создаст маршруты вида /admin/posts
, /admin/posts/:id
и т.д.
License
MIT.
Author
Ilya N. Zykin | the-teacher