clear-router 2.1.11 → 2.2.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/README.md +4 -4
- package/dist/core/index.cjs +4 -0
- package/dist/core/index.d.cts +2 -0
- package/dist/core/index.d.mts +2 -0
- package/dist/core/index.mjs +3 -0
- package/dist/express/index.cjs +91 -244
- package/dist/express/index.d.cts +68 -96
- package/dist/express/index.d.mts +68 -96
- package/dist/express/index.mjs +91 -244
- package/dist/h3/index.cjs +99 -244
- package/dist/h3/index.d.cts +72 -93
- package/dist/h3/index.d.mts +72 -93
- package/dist/h3/index.mjs +99 -244
- package/dist/index.cjs +342 -0
- package/dist/index.d.cts +184 -31
- package/dist/index.d.mts +184 -31
- package/dist/index.mjs +343 -1
- package/dist/router-BNVIrTi3.cjs +397 -0
- package/dist/router-BiCuy5TZ.mjs +392 -0
- package/dist/router-C1jVRytA.d.mts +311 -0
- package/dist/router-CZIh1ZPJ.d.cts +311 -0
- package/dist/types/Route.d.mts +4 -4
- package/dist/types/express.d.mts +5 -2
- package/dist/types/h3.d.mts +7 -2
- package/package.json +10 -2
- package/dist/Route-BbPXcDGX.mjs +0 -50
- package/dist/Route-DhC4kNPX.cjs +0 -62
- package/dist/basic-DXbqD6cP.d.cts +0 -130
- package/dist/basic-vvrFwa_Y.d.mts +0 -130
package/dist/express/index.mjs
CHANGED
|
@@ -1,291 +1,140 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
1
|
+
import { t as CoreRouter } from "../router-BiCuy5TZ.mjs";
|
|
3
2
|
|
|
4
3
|
//#region src/express/router.ts
|
|
5
4
|
/**
|
|
6
|
-
* @class clear-router
|
|
5
|
+
* @class clear-router Express Router
|
|
7
6
|
* @description Laravel-style routing system for Express.js and H3 with support for CommonJS, ESM, and TypeScript
|
|
8
7
|
* @author Refkinscallv
|
|
9
8
|
* @author 3m1n3nc3
|
|
10
9
|
* @repository https://github.com/toneflix/clear-router
|
|
11
10
|
*/
|
|
12
|
-
var Router = class Router {
|
|
13
|
-
static
|
|
14
|
-
|
|
15
|
-
bodyKeys: ["_method"],
|
|
16
|
-
headerKeys: ["x-http-method"]
|
|
17
|
-
} };
|
|
18
|
-
static groupContext = new AsyncLocalStorage();
|
|
19
|
-
/**
|
|
20
|
-
* All registered routes
|
|
21
|
-
*/
|
|
22
|
-
static routes = [];
|
|
23
|
-
/**
|
|
24
|
-
* Mapping of routes by path and method for quick lookup.
|
|
25
|
-
*/
|
|
26
|
-
static routesByPathMethod = {};
|
|
27
|
-
/**
|
|
28
|
-
* Mapping of routes by method for quick lookup.
|
|
29
|
-
*/
|
|
30
|
-
static routesByMethod = {};
|
|
31
|
-
/**
|
|
32
|
-
* Current route prefix
|
|
33
|
-
*/
|
|
34
|
-
static prefix = "";
|
|
35
|
-
/**
|
|
36
|
-
* Group-level middlewares
|
|
37
|
-
*/
|
|
38
|
-
static groupMiddlewares = [];
|
|
39
|
-
/**
|
|
40
|
-
* Global-level middlewares
|
|
41
|
-
*/
|
|
42
|
-
static globalMiddlewares = [];
|
|
43
|
-
/**
|
|
44
|
-
* Normalize path by removing duplicate slashes and ensuring leading slash
|
|
45
|
-
* @param path - Path to normalize
|
|
46
|
-
* @returns Normalized path
|
|
47
|
-
*/
|
|
48
|
-
static normalizePath(path) {
|
|
49
|
-
return "/" + path.split("/").filter(Boolean).join("/");
|
|
11
|
+
var Router = class Router extends CoreRouter {
|
|
12
|
+
static ensureRequestBodyAccessor(req) {
|
|
13
|
+
if (typeof req.getBody !== "function") req.getBody = () => req.body ?? {};
|
|
50
14
|
}
|
|
51
15
|
/**
|
|
52
|
-
*
|
|
16
|
+
* Adds a new route to the router with the specified HTTP methods, path, handler, and optional middlewares.
|
|
53
17
|
*
|
|
54
|
-
* @param
|
|
55
|
-
* @
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (!this.config.methodOverride) this.config.methodOverride = {
|
|
59
|
-
enabled: true,
|
|
60
|
-
bodyKeys: ["_method"],
|
|
61
|
-
headerKeys: ["x-http-method"]
|
|
62
|
-
};
|
|
63
|
-
const override = options?.methodOverride;
|
|
64
|
-
if (!override) return;
|
|
65
|
-
if (typeof override.enabled === "boolean") this.config.methodOverride.enabled = override.enabled;
|
|
66
|
-
const bodyKeys = override.bodyKeys;
|
|
67
|
-
if (typeof bodyKeys !== "undefined") this.config.methodOverride.bodyKeys = (Array.isArray(bodyKeys) ? bodyKeys : [bodyKeys]).map((e) => String(e).trim()).filter(Boolean);
|
|
68
|
-
const headerKeys = override.headerKeys;
|
|
69
|
-
if (typeof headerKeys !== "undefined") this.config.methodOverride.headerKeys = (Array.isArray(headerKeys) ? headerKeys : [headerKeys]).map((e) => String(e).trim().toLowerCase()).filter(Boolean);
|
|
70
|
-
}
|
|
71
|
-
static resolveMethodOverride(method, headers, body) {
|
|
72
|
-
if (!this.config.methodOverride?.enabled || method.toLowerCase() !== "post") return null;
|
|
73
|
-
let override;
|
|
74
|
-
for (const key of this.config.methodOverride?.headerKeys || []) {
|
|
75
|
-
const value = headers?.[key];
|
|
76
|
-
if (Array.isArray(value) ? value[0] : value) {
|
|
77
|
-
override = Array.isArray(value) ? value[0] : value;
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (!override && body && typeof body === "object") for (const key of this.config.methodOverride?.bodyKeys || []) {
|
|
82
|
-
const value = body[key];
|
|
83
|
-
if (typeof value !== "undefined" && value !== null && value !== "") {
|
|
84
|
-
override = value;
|
|
85
|
-
break;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const normalized = String(override || "").trim().toLowerCase();
|
|
89
|
-
if (!normalized) return null;
|
|
90
|
-
if ([
|
|
91
|
-
"put",
|
|
92
|
-
"patch",
|
|
93
|
-
"delete",
|
|
94
|
-
"post"
|
|
95
|
-
].includes(normalized)) return normalized;
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Add a route with specified HTTP methods, path, handler, and middlewares
|
|
100
|
-
* @param methods - HTTP method(s) for the route
|
|
101
|
-
* @param path - Route path
|
|
102
|
-
* @param handler - Route handler function or controller reference
|
|
103
|
-
* @param middlewares - Array of middleware functions
|
|
18
|
+
* @param methods
|
|
19
|
+
* @param path
|
|
20
|
+
* @param handler
|
|
21
|
+
* @param middlewares
|
|
104
22
|
*/
|
|
105
23
|
static add(methods, path, handler, middlewares) {
|
|
106
|
-
|
|
107
|
-
const activePrefix = context?.prefix ?? this.prefix;
|
|
108
|
-
const activeGroupMiddlewares = context?.groupMiddlewares ?? this.groupMiddlewares;
|
|
109
|
-
methods = Array.isArray(methods) ? methods : [methods];
|
|
110
|
-
middlewares = middlewares ? Array.isArray(middlewares) ? middlewares : [middlewares] : void 0;
|
|
111
|
-
const fullPath = this.normalizePath(`${activePrefix}/${path}`);
|
|
112
|
-
const route = new Route(methods.includes("options") ? methods : methods.concat("options"), fullPath, handler, [
|
|
113
|
-
...this.globalMiddlewares,
|
|
114
|
-
...activeGroupMiddlewares,
|
|
115
|
-
...middlewares || []
|
|
116
|
-
]);
|
|
117
|
-
if (!methods.includes("options") && !this.routesByPathMethod[`OPTIONS ${fullPath}`]) this.options(path, ({ res }) => {
|
|
118
|
-
res.set("Allow", "GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD");
|
|
119
|
-
res.sendStatus(204);
|
|
120
|
-
});
|
|
121
|
-
this.routes.push(route);
|
|
122
|
-
for (const method of methods.map((m) => m.toUpperCase())) {
|
|
123
|
-
this.routesByPathMethod[`${method.toUpperCase()} ${fullPath}`] = route;
|
|
124
|
-
if (!this.routesByMethod[method]) this.routesByMethod[method] = [];
|
|
125
|
-
this.routesByMethod[method].push(route);
|
|
126
|
-
}
|
|
24
|
+
super.add(methods, path, handler, middlewares);
|
|
127
25
|
}
|
|
128
26
|
/**
|
|
129
|
-
*
|
|
27
|
+
* Adds a new API resource route to the router for the specified base path and controller, with
|
|
28
|
+
* optional configuration for included/excluded actions and middlewares.
|
|
130
29
|
*
|
|
131
|
-
* @param basePath
|
|
132
|
-
* @param controller
|
|
133
|
-
* @param options
|
|
30
|
+
* @param basePath
|
|
31
|
+
* @param controller
|
|
32
|
+
* @param options
|
|
134
33
|
*/
|
|
135
34
|
static apiResource(basePath, controller, options) {
|
|
136
|
-
|
|
137
|
-
index: {
|
|
138
|
-
method: "get",
|
|
139
|
-
path: "/"
|
|
140
|
-
},
|
|
141
|
-
show: {
|
|
142
|
-
method: "get",
|
|
143
|
-
path: "/:id"
|
|
144
|
-
},
|
|
145
|
-
create: {
|
|
146
|
-
method: "post",
|
|
147
|
-
path: "/"
|
|
148
|
-
},
|
|
149
|
-
update: {
|
|
150
|
-
method: "put",
|
|
151
|
-
path: "/:id"
|
|
152
|
-
},
|
|
153
|
-
destroy: {
|
|
154
|
-
method: "delete",
|
|
155
|
-
path: "/:id"
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
const only = options?.only || Object.keys(actions);
|
|
159
|
-
const except = options?.except || [];
|
|
160
|
-
const preController = typeof controller === "function" ? new controller() : controller;
|
|
161
|
-
for (const action of only) {
|
|
162
|
-
if (except.includes(action)) continue;
|
|
163
|
-
if (typeof preController[action] === "function") {
|
|
164
|
-
const { method, path } = actions[action];
|
|
165
|
-
const actionMiddlewares = typeof options?.middlewares === "object" && !Array.isArray(options.middlewares) ? options.middlewares[action] : options?.middlewares;
|
|
166
|
-
this.add(method, `${basePath}${path}`, [controller, action], Array.isArray(actionMiddlewares) ? actionMiddlewares : actionMiddlewares ? [actionMiddlewares] : void 0);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
35
|
+
super.apiResource(basePath, controller, options);
|
|
169
36
|
}
|
|
170
37
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* @param
|
|
174
|
-
* @param
|
|
38
|
+
* Adds a new GET route to the router with the specified path, handler, and optional middlewares.
|
|
39
|
+
*
|
|
40
|
+
* @param path
|
|
41
|
+
* @param handler
|
|
42
|
+
* @param middlewares
|
|
175
43
|
*/
|
|
176
44
|
static get(path, handler, middlewares) {
|
|
177
|
-
|
|
45
|
+
super.get(path, handler, middlewares);
|
|
178
46
|
}
|
|
179
47
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* @param
|
|
183
|
-
* @param
|
|
48
|
+
* Adds a new POST route to the router with the specified path, handler, and optional middlewares.
|
|
49
|
+
*
|
|
50
|
+
* @param path
|
|
51
|
+
* @param handler
|
|
52
|
+
* @param middlewares
|
|
184
53
|
*/
|
|
185
54
|
static post(path, handler, middlewares) {
|
|
186
|
-
|
|
55
|
+
super.post(path, handler, middlewares);
|
|
187
56
|
}
|
|
188
57
|
/**
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
* @param
|
|
192
|
-
* @param
|
|
58
|
+
* Adds a new PUT route to the router with the specified path, handler, and optional middlewares.
|
|
59
|
+
*
|
|
60
|
+
* @param path
|
|
61
|
+
* @param handler
|
|
62
|
+
* @param middlewares
|
|
193
63
|
*/
|
|
194
64
|
static put(path, handler, middlewares) {
|
|
195
|
-
|
|
65
|
+
super.put(path, handler, middlewares);
|
|
196
66
|
}
|
|
197
67
|
/**
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* @param
|
|
201
|
-
* @param
|
|
68
|
+
* Adds a new DELETE route to the router with the specified path, handler, and optional middlewares.
|
|
69
|
+
*
|
|
70
|
+
* @param path
|
|
71
|
+
* @param handler
|
|
72
|
+
* @param middlewares
|
|
202
73
|
*/
|
|
203
74
|
static delete(path, handler, middlewares) {
|
|
204
|
-
|
|
75
|
+
super.delete(path, handler, middlewares);
|
|
205
76
|
}
|
|
206
77
|
/**
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* @param
|
|
210
|
-
* @param
|
|
78
|
+
* Adds a new PATCH route to the router with the specified path, handler, and optional middlewares.
|
|
79
|
+
*
|
|
80
|
+
* @param path
|
|
81
|
+
* @param handler
|
|
82
|
+
* @param middlewares
|
|
211
83
|
*/
|
|
212
84
|
static patch(path, handler, middlewares) {
|
|
213
|
-
|
|
85
|
+
super.patch(path, handler, middlewares);
|
|
214
86
|
}
|
|
215
87
|
/**
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* @param
|
|
219
|
-
* @param
|
|
88
|
+
* Adds a new OPTIONS route to the router with the specified path, handler, and optional middlewares.
|
|
89
|
+
*
|
|
90
|
+
* @param path
|
|
91
|
+
* @param handler
|
|
92
|
+
* @param middlewares
|
|
220
93
|
*/
|
|
221
94
|
static options(path, handler, middlewares) {
|
|
222
|
-
|
|
95
|
+
super.options(path, handler, middlewares);
|
|
223
96
|
}
|
|
224
97
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* @param
|
|
228
|
-
* @param
|
|
98
|
+
* Adds a new HEAD route to the router with the specified path, handler, and optional middlewares.
|
|
99
|
+
*
|
|
100
|
+
* @param path
|
|
101
|
+
* @param handler
|
|
102
|
+
* @param middlewares
|
|
229
103
|
*/
|
|
230
104
|
static head(path, handler, middlewares) {
|
|
231
|
-
|
|
105
|
+
super.head(path, handler, middlewares);
|
|
232
106
|
}
|
|
233
107
|
/**
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* @param
|
|
108
|
+
* Defines a group of routes with a common prefix and optional middlewares, allowing for better
|
|
109
|
+
* organization and reuse of route configurations.
|
|
110
|
+
*
|
|
111
|
+
* @param prefix
|
|
112
|
+
* @param callback
|
|
113
|
+
* @param middlewares
|
|
238
114
|
*/
|
|
239
115
|
static async group(prefix, callback, middlewares) {
|
|
240
|
-
|
|
241
|
-
const previousPrefix = context?.prefix ?? this.prefix;
|
|
242
|
-
const previousMiddlewares = context?.groupMiddlewares ?? this.groupMiddlewares;
|
|
243
|
-
const fullPrefix = [previousPrefix, prefix].filter(Boolean).join("/");
|
|
244
|
-
const nextContext = {
|
|
245
|
-
prefix: this.normalizePath(fullPrefix),
|
|
246
|
-
groupMiddlewares: [...previousMiddlewares, ...middlewares || []]
|
|
247
|
-
};
|
|
248
|
-
await this.groupContext.run(nextContext, async () => {
|
|
249
|
-
await Promise.resolve(callback());
|
|
250
|
-
});
|
|
116
|
+
await super.group(prefix, callback, middlewares);
|
|
251
117
|
}
|
|
252
118
|
/**
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
* @param
|
|
119
|
+
* Adds global middlewares to the router, which will be applied to all routes.
|
|
120
|
+
*
|
|
121
|
+
* @param middlewares
|
|
122
|
+
* @param callback
|
|
256
123
|
*/
|
|
257
124
|
static middleware(middlewares, callback) {
|
|
258
|
-
|
|
259
|
-
this.globalMiddlewares = [...prevMiddlewares, ...middlewares || []];
|
|
260
|
-
callback();
|
|
261
|
-
this.globalMiddlewares = prevMiddlewares;
|
|
125
|
+
super.middleware(middlewares, callback);
|
|
262
126
|
}
|
|
263
127
|
static allRoutes(type) {
|
|
264
|
-
|
|
265
|
-
if (type === "path") return this.routesByPathMethod;
|
|
266
|
-
return this.routes.filter((e) => e.methods.length > 1 || e.methods[0] !== "options");
|
|
128
|
+
return super.allRoutes(type);
|
|
267
129
|
}
|
|
268
130
|
static async apply(router) {
|
|
269
131
|
for (const route of this.routes) {
|
|
270
132
|
let handlerFunction = null;
|
|
271
133
|
let instance = null;
|
|
272
134
|
try {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
*/
|
|
277
|
-
handlerFunction = route.handler.bind(route);
|
|
278
|
-
else if (Array.isArray(route.handler) && route.handler.length === 2) {
|
|
279
|
-
const [Controller, method] = route.handler;
|
|
280
|
-
if (["function", "object"].includes(typeof Controller) && typeof Controller[method] === "function") {
|
|
281
|
-
instance = Controller;
|
|
282
|
-
handlerFunction = Controller[method].bind(Controller);
|
|
283
|
-
} else if (typeof Controller === "function") {
|
|
284
|
-
instance = new Controller();
|
|
285
|
-
if (typeof instance[method] === "function") handlerFunction = instance[method].bind(instance);
|
|
286
|
-
else throw new Error(`Method "${method}" not found in controller instance "${Controller.name}"`);
|
|
287
|
-
} else throw new Error(`Invalid controller type for route: ${route.path}`);
|
|
288
|
-
} else throw new Error(`Invalid handler format for route: ${route.path}`);
|
|
135
|
+
const resolved = this.resolveHandler(route);
|
|
136
|
+
handlerFunction = resolved.handlerFunction;
|
|
137
|
+
instance = resolved.instance;
|
|
289
138
|
} catch (error) {
|
|
290
139
|
console.error(`[ROUTES] Error setting up route ${route.path}:`, error.message);
|
|
291
140
|
throw error;
|
|
@@ -307,19 +156,25 @@ var Router = class Router {
|
|
|
307
156
|
console.error("[ROUTES]", error.message);
|
|
308
157
|
throw error;
|
|
309
158
|
}
|
|
310
|
-
router[method](route.path, (req,
|
|
159
|
+
router[method](route.path, (req, _res, next) => {
|
|
160
|
+
Router.ensureRequestBodyAccessor(req);
|
|
311
161
|
const override = Router.resolveMethodOverride(req.method, req.headers, req.body);
|
|
312
162
|
if (method === "post" && override && override !== "post") return next("route");
|
|
313
163
|
return next();
|
|
314
164
|
}, ...route.middlewares || [], async (req, res, next) => {
|
|
315
165
|
try {
|
|
166
|
+
Router.ensureRequestBodyAccessor(req);
|
|
316
167
|
const ctx = {
|
|
317
168
|
req,
|
|
318
169
|
res,
|
|
319
170
|
next
|
|
320
171
|
};
|
|
321
172
|
const inst = instance ?? route;
|
|
322
|
-
|
|
173
|
+
Router.bindRequestToInstance(ctx, inst, route, {
|
|
174
|
+
body: ctx.req.getBody(),
|
|
175
|
+
query: ctx.req.query,
|
|
176
|
+
params: ctx.req.params
|
|
177
|
+
});
|
|
323
178
|
const result = handlerFunction(ctx, inst.clearRequest);
|
|
324
179
|
await Promise.resolve(result);
|
|
325
180
|
} catch (error) {
|
|
@@ -330,19 +185,25 @@ var Router = class Router {
|
|
|
330
185
|
"put",
|
|
331
186
|
"patch",
|
|
332
187
|
"delete"
|
|
333
|
-
].includes(method)) router.post(route.path, (req,
|
|
188
|
+
].includes(method)) router.post(route.path, (req, _res, next) => {
|
|
189
|
+
Router.ensureRequestBodyAccessor(req);
|
|
334
190
|
if (Router.resolveMethodOverride(req.method, req.headers, req.body) !== method) return next("route");
|
|
335
191
|
req.method = method.toUpperCase();
|
|
336
192
|
return next();
|
|
337
193
|
}, ...route.middlewares || [], async (req, res, next) => {
|
|
338
194
|
try {
|
|
195
|
+
Router.ensureRequestBodyAccessor(req);
|
|
339
196
|
const ctx = {
|
|
340
197
|
req,
|
|
341
198
|
res,
|
|
342
199
|
next
|
|
343
200
|
};
|
|
344
201
|
const inst = instance ?? route;
|
|
345
|
-
|
|
202
|
+
Router.bindRequestToInstance(ctx, inst, route, {
|
|
203
|
+
body: ctx.req.getBody(),
|
|
204
|
+
query: ctx.req.query,
|
|
205
|
+
params: ctx.req.params
|
|
206
|
+
});
|
|
346
207
|
const result = handlerFunction(ctx, inst.clearRequest);
|
|
347
208
|
await Promise.resolve(result);
|
|
348
209
|
} catch (error) {
|
|
@@ -352,20 +213,6 @@ var Router = class Router {
|
|
|
352
213
|
}
|
|
353
214
|
}
|
|
354
215
|
}
|
|
355
|
-
static async bindRequestToInstance(ctx, instance, route) {
|
|
356
|
-
if (!instance) return;
|
|
357
|
-
instance.ctx = ctx;
|
|
358
|
-
instance.body = ctx.req.body;
|
|
359
|
-
instance.query = ctx.req.query;
|
|
360
|
-
instance.params = ctx.req.params;
|
|
361
|
-
instance.clearRequest = new ClearRequest({
|
|
362
|
-
ctx,
|
|
363
|
-
route,
|
|
364
|
-
body: instance.body,
|
|
365
|
-
query: instance.query,
|
|
366
|
-
params: instance.params
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
216
|
};
|
|
370
217
|
|
|
371
218
|
//#endregion
|