create-rebe 1.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/.env.example +4 -0
- package/template/README.md +63 -8
- package/template/SECURITY.md +39 -0
- package/template/app/routes/api.route.js +1 -1
- package/template/app/routes/register.route.js +1 -1
- package/template/app/routes/web.route.js +1 -1
- package/template/app/socket/register.socket.js +0 -2
- package/template/config/express.config.js +8 -0
- package/template/core/common/string.js +1 -1
- package/template/core/cron.core.js +1 -0
- package/template/core/database.core.js +30 -17
- package/template/core/error.core.js +8 -4
- package/template/core/express.core.js +16 -4
- package/template/core/hooks.core.js +10 -7
- package/template/core/migrator.core.js +201 -0
- package/template/core/modules.core.js +167 -0
- package/template/core/queue.core.js +1 -0
- package/template/core/routing.core.d.ts +273 -0
- package/template/core/routing.core.js +666 -0
- package/template/core/seeder.core.js +105 -0
- package/template/core/socket.core.js +1 -0
- package/template/database/migrations/.gitkeep +0 -0
- package/template/database/seeders/.gitkeep +0 -0
- package/template/docs/Database.md +14 -8
- package/template/docs/Express.md +5 -2
- package/template/docs/Make.md +46 -0
- package/template/docs/Migration.md +56 -0
- package/template/docs/Modules.md +96 -0
- package/template/docs/README.md +5 -0
- package/template/docs/Routing.md +116 -0
- package/template/docs/Seeder.md +54 -0
- package/template/eslint.config.js +52 -0
- package/template/package-lock.json +1068 -70
- package/template/package.json +15 -8
- package/template/scripts/cli/args.js +39 -0
- package/template/scripts/cli/bootstrap.js +16 -0
- package/template/scripts/cli/db.js +79 -0
- package/template/scripts/cli/help.js +58 -0
- package/template/scripts/cli/keys.js +100 -0
- package/template/scripts/cli/log.js +58 -0
- package/template/scripts/cli/make.js +249 -0
- package/template/scripts/cli/names.js +51 -0
- package/template/scripts/cli/templates.js +358 -0
- package/template/scripts/cli.js +75 -234
- package/template/tests/http.test.js +99 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
|
|
6
|
+
const logger = require('@core/logger.core')
|
|
7
|
+
|
|
8
|
+
const MODULES_DIR = path.resolve(process.cwd(), 'modules')
|
|
9
|
+
|
|
10
|
+
// Optional modular layer. A "module" groups one feature's pieces (models, routes,
|
|
11
|
+
// migrations, seeders, jobs, queue, socket) under modules/<name>/ behind a single
|
|
12
|
+
// entry file. Discovery is additive: the flat layout (database/models, app/routes…)
|
|
13
|
+
// keeps working untouched, and a project with no modules/ directory pays nothing.
|
|
14
|
+
//
|
|
15
|
+
// Entry file — modules/<name>/<name>.module.js (also accepts index.js / module.js):
|
|
16
|
+
//
|
|
17
|
+
// module.exports = {
|
|
18
|
+
// name: 'blog', // optional, defaults to the folder name
|
|
19
|
+
// models: './models', // dir of (sequelize, DataTypes) factories
|
|
20
|
+
// migrations: './migrations', // dir of up/down migration files
|
|
21
|
+
// seeders: './seeders', // dir of seeder files
|
|
22
|
+
// routes: './routes', // file or dir required for its routing side-effect
|
|
23
|
+
// middlewares: (app) => {}, // global Express middleware
|
|
24
|
+
// jobs: (Cron) => {}, // cron definitions
|
|
25
|
+
// queue: (Queue) => {}, // queue workers
|
|
26
|
+
// socket: (io, Socket) => {}, // socket handlers
|
|
27
|
+
// }
|
|
28
|
+
//
|
|
29
|
+
// The core layer never imports module code statically; modules are app-land and are
|
|
30
|
+
// discovered here at runtime, keeping the arrow app -> core one-directional.
|
|
31
|
+
class Modules {
|
|
32
|
+
static _modules = null
|
|
33
|
+
|
|
34
|
+
// Entry-file candidates, tried in order, for a folder named <name>.
|
|
35
|
+
static _entryCandidates(name) {
|
|
36
|
+
return [`${name}.module.js`, 'module.js', 'index.js']
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Discover and cache every module once. Safe to call repeatedly.
|
|
40
|
+
static discover() {
|
|
41
|
+
if (Modules._modules) return Modules._modules
|
|
42
|
+
Modules._modules = []
|
|
43
|
+
|
|
44
|
+
if (!fs.existsSync(MODULES_DIR)) return Modules._modules
|
|
45
|
+
|
|
46
|
+
for (const entry of fs.readdirSync(MODULES_DIR, { withFileTypes: true })) {
|
|
47
|
+
if (!entry.isDirectory() || entry.name.startsWith('_')) continue
|
|
48
|
+
|
|
49
|
+
const dir = path.join(MODULES_DIR, entry.name)
|
|
50
|
+
const entryFile = Modules._entryCandidates(entry.name)
|
|
51
|
+
.map((f) => path.join(dir, f))
|
|
52
|
+
.find((f) => fs.existsSync(f))
|
|
53
|
+
|
|
54
|
+
if (!entryFile) {
|
|
55
|
+
logger.warn(`Module "${entry.name}" has no entry file (expected one of: ${Modules._entryCandidates(entry.name).join(', ')}); skipping`)
|
|
56
|
+
continue
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const raw = require(entryFile)
|
|
61
|
+
const def = raw && raw.default !== undefined ? raw.default : raw
|
|
62
|
+
if (!def || typeof def !== 'object') {
|
|
63
|
+
logger.warn(`Module "${entry.name}" entry must export an object; skipping`)
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
Modules._modules.push({ name: def.name || entry.name, dir, def })
|
|
67
|
+
} catch (err) {
|
|
68
|
+
logger.error(`Failed to load module "${entry.name}"`, err)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const names = Modules._modules.map((m) => m.name)
|
|
73
|
+
if (names.length) logger.info(`Loaded ${names.length} module(s): ${names.join(', ')}`)
|
|
74
|
+
return Modules._modules
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Absolute, existing directories declared by modules for a given kind
|
|
78
|
+
// ('models' | 'migrations' | 'seeders'). Relative paths resolve against the
|
|
79
|
+
// module folder; missing directories are silently dropped.
|
|
80
|
+
static dirs(kind) {
|
|
81
|
+
const out = []
|
|
82
|
+
for (const mod of Modules.discover()) {
|
|
83
|
+
const rel = mod.def[kind]
|
|
84
|
+
if (!rel) continue
|
|
85
|
+
const abs = path.resolve(mod.dir, rel)
|
|
86
|
+
if (fs.existsSync(abs)) out.push(abs)
|
|
87
|
+
else logger.warn(`Module "${mod.name}" ${kind} directory not found: ${abs}`)
|
|
88
|
+
}
|
|
89
|
+
return out
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Require each module's routes for their routing side-effect. When `routes` points
|
|
93
|
+
// to a directory, every *.js file in it is loaded (sorted; "_"-prefixed skipped) so
|
|
94
|
+
// dropping in a new <name>.route.js is enough — no central wiring needed. When it
|
|
95
|
+
// points to a single file, just that file is required.
|
|
96
|
+
static requireRoutes() {
|
|
97
|
+
for (const mod of Modules.discover()) {
|
|
98
|
+
const rel = mod.def.routes
|
|
99
|
+
if (!rel) continue
|
|
100
|
+
const abs = path.resolve(mod.dir, rel)
|
|
101
|
+
if (!fs.existsSync(abs)) {
|
|
102
|
+
logger.warn(`Module "${mod.name}" routes not found: ${abs}`)
|
|
103
|
+
continue
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const files = fs.statSync(abs).isDirectory()
|
|
107
|
+
? fs
|
|
108
|
+
.readdirSync(abs)
|
|
109
|
+
.filter((f) => f.endsWith('.js') && !f.startsWith('_'))
|
|
110
|
+
.sort()
|
|
111
|
+
.map((f) => path.join(abs, f))
|
|
112
|
+
: [abs]
|
|
113
|
+
|
|
114
|
+
for (const file of files) {
|
|
115
|
+
try {
|
|
116
|
+
require(file)
|
|
117
|
+
} catch (err) {
|
|
118
|
+
logger.error(`Failed to load routes for module "${mod.name}" (${path.basename(file)})`, err)
|
|
119
|
+
throw err
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Invoke each module's callable for a given kind ('middlewares' | 'jobs' |
|
|
126
|
+
// 'queue' | 'socket'), forwarding args (the core facade). Failures are isolated
|
|
127
|
+
// per module so one bad module cannot abort boot of the rest.
|
|
128
|
+
static async invoke(kind, args = []) {
|
|
129
|
+
for (const mod of Modules.discover()) {
|
|
130
|
+
const fn = mod.def[kind]
|
|
131
|
+
if (typeof fn !== 'function') continue
|
|
132
|
+
try {
|
|
133
|
+
await fn(...args)
|
|
134
|
+
} catch (err) {
|
|
135
|
+
logger.error(`Module "${mod.name}" ${kind} register failed`, err)
|
|
136
|
+
throw err
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Run each module's lifecycle hook for a stage ('before' | 'after' | 'shutdown'),
|
|
142
|
+
// from its `hooks: { before, after, shutdown }` export. Errors propagate so a
|
|
143
|
+
// failing before-hook aborts boot, matching the flat hook contract.
|
|
144
|
+
static async runHooks(stage, ctx = {}) {
|
|
145
|
+
for (const mod of Modules.discover()) {
|
|
146
|
+
const fn = mod.def.hooks && mod.def.hooks[stage]
|
|
147
|
+
if (typeof fn !== 'function') continue
|
|
148
|
+
try {
|
|
149
|
+
await fn(ctx)
|
|
150
|
+
} catch (err) {
|
|
151
|
+
logger.error(`Module "${mod.name}" hook "${stage}" failed`, err)
|
|
152
|
+
throw err
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static list() {
|
|
158
|
+
return Modules.discover().map((m) => m.name)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Reset the discovery cache (used by tooling/tests that mutate modules/).
|
|
162
|
+
static reset() {
|
|
163
|
+
Modules._modules = null
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
module.exports = Modules
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { Application, Router, Request, Response, NextFunction } from 'express'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HTTP context passed to ALL handlers and handle() middleware — always { req, res, next, error }
|
|
5
|
+
*/
|
|
6
|
+
export interface HttpContext {
|
|
7
|
+
req: Request
|
|
8
|
+
res: Response
|
|
9
|
+
next: NextFunction
|
|
10
|
+
/** Populated in errorHandler, null in normal route/middleware handlers */
|
|
11
|
+
error: Error | null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Route handler function — receives the full HttpContext.
|
|
16
|
+
* The return value is ignored, so handlers may freely `return res.json(...)`
|
|
17
|
+
* or be `async`. (Typed as `any` to allow the common `({ res }) => res.json(...)` form.)
|
|
18
|
+
*/
|
|
19
|
+
export type RouteHandler = (ctx: HttpContext) => any
|
|
20
|
+
|
|
21
|
+
/** Controller method reference tuple */
|
|
22
|
+
export type ControllerHandler = [any, string]
|
|
23
|
+
|
|
24
|
+
/** Handler can be an inline function or a controller binding */
|
|
25
|
+
export type Handler = RouteHandler | ControllerHandler
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Middleware — plain Express function, object/class with handle(), OR a registered
|
|
29
|
+
* alias/group name (string, see Routes.registerMiddleware / Routes.middlewareGroup).
|
|
30
|
+
*
|
|
31
|
+
* PLAIN FUNCTION — allowed in scoped Routes.middleware([fn], () => { ... }) and per-route:
|
|
32
|
+
* (req, res, next) => void
|
|
33
|
+
*
|
|
34
|
+
* HANDLE CLASS — required in chaining Routes.middleware([Mw]).get(...):
|
|
35
|
+
* class Mw { static handle({ req, res, next, error }: HttpContext): void }
|
|
36
|
+
* class Mw { handle({ req, res, next, error }: HttpContext): void }
|
|
37
|
+
* const obj = { handle({ req, res, next, error }: HttpContext): void }
|
|
38
|
+
*
|
|
39
|
+
* STRING — a registered middleware alias or group: 'auth', 'web', ...
|
|
40
|
+
*/
|
|
41
|
+
export type MiddlewareFn = (req: Request, res: Response, next: NextFunction) => void | Promise<void>
|
|
42
|
+
|
|
43
|
+
export interface MiddlewareClass {
|
|
44
|
+
handle(ctx: HttpContext): void | Promise<void>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type Middleware = MiddlewareFn | MiddlewareClass | (new () => MiddlewareClass) | string
|
|
48
|
+
|
|
49
|
+
/** HTTP methods supported by the router */
|
|
50
|
+
export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head'
|
|
51
|
+
|
|
52
|
+
/** Parameter constraint — a regex source string or a RegExp. */
|
|
53
|
+
export type RouteConstraint = string | RegExp
|
|
54
|
+
|
|
55
|
+
/** Route information object returned by allRoutes() */
|
|
56
|
+
export interface RouteInfo {
|
|
57
|
+
methods: HttpMethod[]
|
|
58
|
+
path: string
|
|
59
|
+
/** Route name (Routes...name()), or null if unnamed */
|
|
60
|
+
name: string | null
|
|
61
|
+
middlewareCount: number
|
|
62
|
+
handlerType: 'function' | 'controller'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The seven RESTful resource actions. */
|
|
66
|
+
export type ResourceAction = 'index' | 'create' | 'store' | 'show' | 'edit' | 'update' | 'destroy'
|
|
67
|
+
|
|
68
|
+
/** Options for Routes.resource() / Routes.apiResource(). */
|
|
69
|
+
export interface ResourceOptions {
|
|
70
|
+
/** Only register these actions. */
|
|
71
|
+
only?: ResourceAction[]
|
|
72
|
+
/** Register all actions except these. */
|
|
73
|
+
except?: ResourceAction[]
|
|
74
|
+
/** Path parameter name for show/update/destroy/edit (default: 'id'). */
|
|
75
|
+
parameter?: string
|
|
76
|
+
/** When true, omit the HTML-form `create` and `edit` routes. */
|
|
77
|
+
api?: boolean
|
|
78
|
+
/** Middleware applied to every generated resource route. */
|
|
79
|
+
middleware?: Middleware | Middleware[]
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Chainable handle returned by route-definition methods, enabling Laravel-style
|
|
84
|
+
* fluent configuration:
|
|
85
|
+
* Routes.get('/users/:id', h).name('users.show').whereNumber('id')
|
|
86
|
+
*/
|
|
87
|
+
export interface RouteRegistration {
|
|
88
|
+
/** Assign a route name for URL generation via Routes.url() / Routes.route(). */
|
|
89
|
+
name(name: string): RouteRegistration
|
|
90
|
+
/** Constrain a path parameter to a pattern (regex string or RegExp). */
|
|
91
|
+
where(param: string, pattern: RouteConstraint): RouteRegistration
|
|
92
|
+
/** Constrain several path parameters at once. */
|
|
93
|
+
where(constraints: Record<string, RouteConstraint>): RouteRegistration
|
|
94
|
+
whereNumber(param: string): RouteRegistration
|
|
95
|
+
whereAlpha(param: string): RouteRegistration
|
|
96
|
+
whereAlphaNumeric(param: string): RouteRegistration
|
|
97
|
+
whereUuid(param: string): RouteRegistration
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Per-method middleware map for Routes.controller().
|
|
102
|
+
* Keys are controller method names; values are a single middleware or array.
|
|
103
|
+
* Only handle()-based middleware classes/objects are recommended here.
|
|
104
|
+
*/
|
|
105
|
+
export type MethodMiddlewareMap = Record<string, Middleware | Middleware[]>
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Proxy returned by Routes.middleware() when called WITHOUT a callback (chaining mode).
|
|
109
|
+
*
|
|
110
|
+
* STRICT: only handle()-based middleware classes/objects (or aliases that resolve to one)
|
|
111
|
+
* are allowed. Each method call is terminal — globalMiddlewares are restored after.
|
|
112
|
+
*
|
|
113
|
+
* Usage:
|
|
114
|
+
* Routes.middleware([Mw]).get(path, handler).name('...')
|
|
115
|
+
* Routes.middleware([Mw]).group(prefix, callback)
|
|
116
|
+
*/
|
|
117
|
+
export interface MiddlewareChain {
|
|
118
|
+
group(prefix: string, callback: () => void, middlewares?: Middleware[]): void
|
|
119
|
+
add(methods: HttpMethod | HttpMethod[], path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
120
|
+
get(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
121
|
+
post(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
122
|
+
put(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
123
|
+
delete(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
124
|
+
patch(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
125
|
+
options(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
126
|
+
head(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export default class Routes {
|
|
130
|
+
static routes: Array<{
|
|
131
|
+
methods: HttpMethod[]
|
|
132
|
+
path: string
|
|
133
|
+
handler: Handler
|
|
134
|
+
middlewares: Middleware[]
|
|
135
|
+
name?: string | null
|
|
136
|
+
constraints?: Record<string, RouteConstraint>
|
|
137
|
+
_resolved?: boolean
|
|
138
|
+
}>
|
|
139
|
+
static prefix: string
|
|
140
|
+
static groupMiddlewares: Middleware[]
|
|
141
|
+
static globalMiddlewares: Middleware[]
|
|
142
|
+
static middlewareAliases: Record<string, Middleware>
|
|
143
|
+
static middlewareGroups: Record<string, Middleware[]>
|
|
144
|
+
static _errorHandler: RouteHandler | null
|
|
145
|
+
static _maintenanceMode: boolean
|
|
146
|
+
static _maintenanceHandler: RouteHandler | null
|
|
147
|
+
static _fallbackHandler: RouteHandler | null
|
|
148
|
+
|
|
149
|
+
static normalizePath(path: string): string
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Convert method/function name to kebab-case URL segment.
|
|
153
|
+
* samplePath → sample-path
|
|
154
|
+
* SamplePath → sample-path
|
|
155
|
+
* sample_path → sample-path
|
|
156
|
+
* Samplepath → samplepath
|
|
157
|
+
*/
|
|
158
|
+
static nameToPath(name: string): string
|
|
159
|
+
|
|
160
|
+
static resolveHandler(Controller: any, method: string): RouteHandler
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Normalize middleware — accepts plain function OR handle() class/object.
|
|
164
|
+
* Used for scoped middleware and per-route middleware.
|
|
165
|
+
*/
|
|
166
|
+
static normalizeMiddleware(mw: Middleware): MiddlewareFn
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Strict normalization — ONLY handle() classes/objects allowed.
|
|
170
|
+
* Used internally by chaining syntax. Throws if a plain function is passed.
|
|
171
|
+
*/
|
|
172
|
+
static normalizeMiddlewareStrict(mw: Middleware): MiddlewareFn
|
|
173
|
+
|
|
174
|
+
/** Register named middleware aliases (Laravel-style). */
|
|
175
|
+
static registerMiddleware(name: string, mw: Middleware): typeof Routes
|
|
176
|
+
static registerMiddleware(map: Record<string, Middleware>): typeof Routes
|
|
177
|
+
|
|
178
|
+
/** Register a named middleware group — a string that expands to several middlewares. */
|
|
179
|
+
static middlewareGroup(name: string, list: Middleware[]): typeof Routes
|
|
180
|
+
|
|
181
|
+
/** Expand a middleware list, resolving string aliases/groups to actual middleware. */
|
|
182
|
+
static expandMiddleware(list: Middleware[]): Middleware[]
|
|
183
|
+
|
|
184
|
+
static add(methods: HttpMethod | HttpMethod[], path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
185
|
+
static get(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
186
|
+
static post(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
187
|
+
static put(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
188
|
+
static delete(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
189
|
+
static patch(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
190
|
+
static options(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
191
|
+
static head(path: string, handler: Handler, middlewares?: Middleware[]): RouteRegistration
|
|
192
|
+
static group(prefix: string, callback: () => void, middlewares?: Middleware[]): void
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Apply global middlewares.
|
|
196
|
+
*
|
|
197
|
+
* SCOPED (with callback) — accepts plain functions OR handle() classes:
|
|
198
|
+
* Routes.middleware([Mw, fn], () => { Routes.get(...) })
|
|
199
|
+
* Returns `typeof Routes` for fluency.
|
|
200
|
+
*
|
|
201
|
+
* CHAINING (without callback) — STRICT: only handle() classes/objects:
|
|
202
|
+
* Routes.middleware([Mw]).get(path, handler)
|
|
203
|
+
* Routes.middleware([Mw]).group(prefix, callback)
|
|
204
|
+
* Returns MiddlewareChain — each call is terminal.
|
|
205
|
+
*/
|
|
206
|
+
static middleware(middlewares: Middleware[], callback: () => void): typeof Routes
|
|
207
|
+
static middleware(middlewares: Middleware[]): MiddlewareChain
|
|
208
|
+
|
|
209
|
+
static errorHandler(handler: Handler): void
|
|
210
|
+
static maintenance(enabled: boolean, handler?: Handler): void
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Auto-register all methods of a controller as routes.
|
|
214
|
+
*
|
|
215
|
+
* Methods whose name starts with `_` (e.g. `_helper`) are treated as private
|
|
216
|
+
* helpers and are NEVER registered as routes.
|
|
217
|
+
*
|
|
218
|
+
* @param basePath Base URL for the controller
|
|
219
|
+
* @param Controller Class (static or instance) or plain object
|
|
220
|
+
* @param methodMiddlewares Optional per-method middleware map:
|
|
221
|
+
* {
|
|
222
|
+
* 'index': AuthMiddleware,
|
|
223
|
+
* 'myProfile': [AuthMiddleware, LogMiddleware],
|
|
224
|
+
* }
|
|
225
|
+
*/
|
|
226
|
+
static controller(basePath: string, Controller: any, methodMiddlewares?: MethodMiddlewareMap): void
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Register the seven RESTful resource routes for a controller (Laravel-style):
|
|
230
|
+
* GET index · GET create · POST store · GET show · GET edit · PUT|PATCH update · DELETE destroy
|
|
231
|
+
* Each is named `<name>.<action>`. Only actions the controller implements are registered.
|
|
232
|
+
*/
|
|
233
|
+
static resource(name: string, Controller: any, options?: ResourceOptions): typeof Routes
|
|
234
|
+
|
|
235
|
+
/** API resource — resource() without the HTML-form create/edit routes. */
|
|
236
|
+
static apiResource(name: string, Controller: any, options?: ResourceOptions): typeof Routes
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Build a resolver binding a controller method to the class, a single shared
|
|
240
|
+
* instance, or the object — returning null when the method does not exist.
|
|
241
|
+
*/
|
|
242
|
+
static makeMethodResolver(Controller: any): (method: string) => RouteHandler | null
|
|
243
|
+
|
|
244
|
+
/** Register a redirect route (default status 302). */
|
|
245
|
+
static redirect(from: string, to: string, status?: number): RouteRegistration
|
|
246
|
+
|
|
247
|
+
/** Register a route that renders a view via the Express view engine (res.render). */
|
|
248
|
+
static view(path: string, view: string, data?: Record<string, any>): RouteRegistration
|
|
249
|
+
|
|
250
|
+
/** Register a fallback handler invoked when no other route matches. */
|
|
251
|
+
static fallback(handler: Handler): typeof Routes
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Generate a URL for a named route, substituting `:param` segments and appending
|
|
255
|
+
* any extra keys as a query string.
|
|
256
|
+
* Routes.url('users.show', { id: 5 }) // → /users/5
|
|
257
|
+
*/
|
|
258
|
+
static url(name: string, params?: Record<string, any>): string
|
|
259
|
+
|
|
260
|
+
/** Alias of Routes.url() — matches Laravel's `route()` helper. */
|
|
261
|
+
static route(name: string, params?: Record<string, any>): string
|
|
262
|
+
|
|
263
|
+
static allRoutes(): RouteInfo[]
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Apply routes to Express.
|
|
267
|
+
* Routes.apply(app) — direct mount
|
|
268
|
+
* Routes.apply(app, router) — auto app.use(router)
|
|
269
|
+
*/
|
|
270
|
+
static apply(appOrRouter: Application | Router, router?: Router): Promise<void>
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export { Routes }
|