clear-router 2.1.12 → 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 +86 -247
- package/dist/express/index.d.cts +68 -97
- package/dist/express/index.d.mts +68 -97
- package/dist/express/index.mjs +86 -247
- package/dist/h3/index.cjs +88 -242
- package/dist/h3/index.d.cts +72 -93
- package/dist/h3/index.d.mts +72 -93
- package/dist/h3/index.mjs +88 -242
- package/dist/index.cjs +342 -0
- package/dist/index.d.cts +184 -38
- package/dist/index.d.mts +184 -38
- 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/package.json +6 -2
- package/dist/Route-BbPXcDGX.mjs +0 -50
- package/dist/Route-DhC4kNPX.cjs +0 -62
- package/dist/basic-C_1O6RVq.d.cts +0 -138
- package/dist/basic-cLeny2Zk.d.mts +0 -138
package/dist/express/index.mjs
CHANGED
|
@@ -1,294 +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 config = { methodOverride: {
|
|
14
|
-
enabled: true,
|
|
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("/");
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Configure router settings to modify behavior.
|
|
53
|
-
*
|
|
54
|
-
* @param options - Configuration options for the router
|
|
55
|
-
* @returns
|
|
56
|
-
*/
|
|
57
|
-
static configure(options) {
|
|
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
|
-
}
|
|
11
|
+
var Router = class Router extends CoreRouter {
|
|
71
12
|
static ensureRequestBodyAccessor(req) {
|
|
72
13
|
if (typeof req.getBody !== "function") req.getBody = () => req.body ?? {};
|
|
73
14
|
}
|
|
74
|
-
static resolveMethodOverride(method, headers, body) {
|
|
75
|
-
if (!this.config.methodOverride?.enabled || method.toLowerCase() !== "post") return null;
|
|
76
|
-
let override;
|
|
77
|
-
for (const key of this.config.methodOverride?.headerKeys || []) {
|
|
78
|
-
const value = headers?.[key];
|
|
79
|
-
if (Array.isArray(value) ? value[0] : value) {
|
|
80
|
-
override = Array.isArray(value) ? value[0] : value;
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (!override && body && typeof body === "object") for (const key of this.config.methodOverride?.bodyKeys || []) {
|
|
85
|
-
const value = body[key];
|
|
86
|
-
if (typeof value !== "undefined" && value !== null && value !== "") {
|
|
87
|
-
override = value;
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const normalized = String(override || "").trim().toLowerCase();
|
|
92
|
-
if (!normalized) return null;
|
|
93
|
-
if ([
|
|
94
|
-
"put",
|
|
95
|
-
"patch",
|
|
96
|
-
"delete",
|
|
97
|
-
"post"
|
|
98
|
-
].includes(normalized)) return normalized;
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
15
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* @param
|
|
105
|
-
* @param
|
|
106
|
-
* @param
|
|
16
|
+
* Adds a new route to the router with the specified HTTP methods, path, handler, and optional middlewares.
|
|
17
|
+
*
|
|
18
|
+
* @param methods
|
|
19
|
+
* @param path
|
|
20
|
+
* @param handler
|
|
21
|
+
* @param middlewares
|
|
107
22
|
*/
|
|
108
23
|
static add(methods, path, handler, middlewares) {
|
|
109
|
-
|
|
110
|
-
const activePrefix = context?.prefix ?? this.prefix;
|
|
111
|
-
const activeGroupMiddlewares = context?.groupMiddlewares ?? this.groupMiddlewares;
|
|
112
|
-
methods = Array.isArray(methods) ? methods : [methods];
|
|
113
|
-
middlewares = middlewares ? Array.isArray(middlewares) ? middlewares : [middlewares] : void 0;
|
|
114
|
-
const fullPath = this.normalizePath(`${activePrefix}/${path}`);
|
|
115
|
-
const route = new Route(methods.includes("options") ? methods : methods.concat("options"), fullPath, handler, [
|
|
116
|
-
...this.globalMiddlewares,
|
|
117
|
-
...activeGroupMiddlewares,
|
|
118
|
-
...middlewares || []
|
|
119
|
-
]);
|
|
120
|
-
if (!methods.includes("options") && !this.routesByPathMethod[`OPTIONS ${fullPath}`]) this.options(path, ({ res }) => {
|
|
121
|
-
res.set("Allow", "GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD");
|
|
122
|
-
res.sendStatus(204);
|
|
123
|
-
});
|
|
124
|
-
this.routes.push(route);
|
|
125
|
-
for (const method of methods.map((m) => m.toUpperCase())) {
|
|
126
|
-
this.routesByPathMethod[`${method.toUpperCase()} ${fullPath}`] = route;
|
|
127
|
-
if (!this.routesByMethod[method]) this.routesByMethod[method] = [];
|
|
128
|
-
this.routesByMethod[method].push(route);
|
|
129
|
-
}
|
|
24
|
+
super.add(methods, path, handler, middlewares);
|
|
130
25
|
}
|
|
131
26
|
/**
|
|
132
|
-
*
|
|
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.
|
|
133
29
|
*
|
|
134
|
-
* @param basePath
|
|
135
|
-
* @param controller
|
|
136
|
-
* @param options
|
|
30
|
+
* @param basePath
|
|
31
|
+
* @param controller
|
|
32
|
+
* @param options
|
|
137
33
|
*/
|
|
138
34
|
static apiResource(basePath, controller, options) {
|
|
139
|
-
|
|
140
|
-
index: {
|
|
141
|
-
method: "get",
|
|
142
|
-
path: "/"
|
|
143
|
-
},
|
|
144
|
-
show: {
|
|
145
|
-
method: "get",
|
|
146
|
-
path: "/:id"
|
|
147
|
-
},
|
|
148
|
-
create: {
|
|
149
|
-
method: "post",
|
|
150
|
-
path: "/"
|
|
151
|
-
},
|
|
152
|
-
update: {
|
|
153
|
-
method: "put",
|
|
154
|
-
path: "/:id"
|
|
155
|
-
},
|
|
156
|
-
destroy: {
|
|
157
|
-
method: "delete",
|
|
158
|
-
path: "/:id"
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
const only = options?.only || Object.keys(actions);
|
|
162
|
-
const except = options?.except || [];
|
|
163
|
-
const preController = typeof controller === "function" ? new controller() : controller;
|
|
164
|
-
for (const action of only) {
|
|
165
|
-
if (except.includes(action)) continue;
|
|
166
|
-
if (typeof preController[action] === "function") {
|
|
167
|
-
const { method, path } = actions[action];
|
|
168
|
-
const actionMiddlewares = typeof options?.middlewares === "object" && !Array.isArray(options.middlewares) ? options.middlewares[action] : options?.middlewares;
|
|
169
|
-
this.add(method, `${basePath}${path}`, [controller, action], Array.isArray(actionMiddlewares) ? actionMiddlewares : actionMiddlewares ? [actionMiddlewares] : void 0);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
35
|
+
super.apiResource(basePath, controller, options);
|
|
172
36
|
}
|
|
173
37
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* @param
|
|
177
|
-
* @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
|
|
178
43
|
*/
|
|
179
44
|
static get(path, handler, middlewares) {
|
|
180
|
-
|
|
45
|
+
super.get(path, handler, middlewares);
|
|
181
46
|
}
|
|
182
47
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* @param
|
|
186
|
-
* @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
|
|
187
53
|
*/
|
|
188
54
|
static post(path, handler, middlewares) {
|
|
189
|
-
|
|
55
|
+
super.post(path, handler, middlewares);
|
|
190
56
|
}
|
|
191
57
|
/**
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* @param
|
|
195
|
-
* @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
|
|
196
63
|
*/
|
|
197
64
|
static put(path, handler, middlewares) {
|
|
198
|
-
|
|
65
|
+
super.put(path, handler, middlewares);
|
|
199
66
|
}
|
|
200
67
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
* @param
|
|
204
|
-
* @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
|
|
205
73
|
*/
|
|
206
74
|
static delete(path, handler, middlewares) {
|
|
207
|
-
|
|
75
|
+
super.delete(path, handler, middlewares);
|
|
208
76
|
}
|
|
209
77
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* @param
|
|
213
|
-
* @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
|
|
214
83
|
*/
|
|
215
84
|
static patch(path, handler, middlewares) {
|
|
216
|
-
|
|
85
|
+
super.patch(path, handler, middlewares);
|
|
217
86
|
}
|
|
218
87
|
/**
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
* @param
|
|
222
|
-
* @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
|
|
223
93
|
*/
|
|
224
94
|
static options(path, handler, middlewares) {
|
|
225
|
-
|
|
95
|
+
super.options(path, handler, middlewares);
|
|
226
96
|
}
|
|
227
97
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* @param
|
|
231
|
-
* @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
|
|
232
103
|
*/
|
|
233
104
|
static head(path, handler, middlewares) {
|
|
234
|
-
|
|
105
|
+
super.head(path, handler, middlewares);
|
|
235
106
|
}
|
|
236
107
|
/**
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
* @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
|
|
241
114
|
*/
|
|
242
115
|
static async group(prefix, callback, middlewares) {
|
|
243
|
-
|
|
244
|
-
const previousPrefix = context?.prefix ?? this.prefix;
|
|
245
|
-
const previousMiddlewares = context?.groupMiddlewares ?? this.groupMiddlewares;
|
|
246
|
-
const fullPrefix = [previousPrefix, prefix].filter(Boolean).join("/");
|
|
247
|
-
const nextContext = {
|
|
248
|
-
prefix: this.normalizePath(fullPrefix),
|
|
249
|
-
groupMiddlewares: [...previousMiddlewares, ...middlewares || []]
|
|
250
|
-
};
|
|
251
|
-
await this.groupContext.run(nextContext, async () => {
|
|
252
|
-
await Promise.resolve(callback());
|
|
253
|
-
});
|
|
116
|
+
await super.group(prefix, callback, middlewares);
|
|
254
117
|
}
|
|
255
118
|
/**
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
* @param
|
|
119
|
+
* Adds global middlewares to the router, which will be applied to all routes.
|
|
120
|
+
*
|
|
121
|
+
* @param middlewares
|
|
122
|
+
* @param callback
|
|
259
123
|
*/
|
|
260
124
|
static middleware(middlewares, callback) {
|
|
261
|
-
|
|
262
|
-
this.globalMiddlewares = [...prevMiddlewares, ...middlewares || []];
|
|
263
|
-
callback();
|
|
264
|
-
this.globalMiddlewares = prevMiddlewares;
|
|
125
|
+
super.middleware(middlewares, callback);
|
|
265
126
|
}
|
|
266
127
|
static allRoutes(type) {
|
|
267
|
-
|
|
268
|
-
if (type === "path") return this.routesByPathMethod;
|
|
269
|
-
return this.routes.filter((e) => e.methods.length > 1 || e.methods[0] !== "options");
|
|
128
|
+
return super.allRoutes(type);
|
|
270
129
|
}
|
|
271
130
|
static async apply(router) {
|
|
272
131
|
for (const route of this.routes) {
|
|
273
132
|
let handlerFunction = null;
|
|
274
133
|
let instance = null;
|
|
275
134
|
try {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
*/
|
|
280
|
-
handlerFunction = route.handler.bind(route);
|
|
281
|
-
else if (Array.isArray(route.handler) && route.handler.length === 2) {
|
|
282
|
-
const [Controller, method] = route.handler;
|
|
283
|
-
if (["function", "object"].includes(typeof Controller) && typeof Controller[method] === "function") {
|
|
284
|
-
instance = Controller;
|
|
285
|
-
handlerFunction = Controller[method].bind(Controller);
|
|
286
|
-
} else if (typeof Controller === "function") {
|
|
287
|
-
instance = new Controller();
|
|
288
|
-
if (typeof instance[method] === "function") handlerFunction = instance[method].bind(instance);
|
|
289
|
-
else throw new Error(`Method "${method}" not found in controller instance "${Controller.name}"`);
|
|
290
|
-
} else throw new Error(`Invalid controller type for route: ${route.path}`);
|
|
291
|
-
} 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;
|
|
292
138
|
} catch (error) {
|
|
293
139
|
console.error(`[ROUTES] Error setting up route ${route.path}:`, error.message);
|
|
294
140
|
throw error;
|
|
@@ -310,7 +156,7 @@ var Router = class Router {
|
|
|
310
156
|
console.error("[ROUTES]", error.message);
|
|
311
157
|
throw error;
|
|
312
158
|
}
|
|
313
|
-
router[method](route.path, (req,
|
|
159
|
+
router[method](route.path, (req, _res, next) => {
|
|
314
160
|
Router.ensureRequestBodyAccessor(req);
|
|
315
161
|
const override = Router.resolveMethodOverride(req.method, req.headers, req.body);
|
|
316
162
|
if (method === "post" && override && override !== "post") return next("route");
|
|
@@ -324,7 +170,11 @@ var Router = class Router {
|
|
|
324
170
|
next
|
|
325
171
|
};
|
|
326
172
|
const inst = instance ?? route;
|
|
327
|
-
|
|
173
|
+
Router.bindRequestToInstance(ctx, inst, route, {
|
|
174
|
+
body: ctx.req.getBody(),
|
|
175
|
+
query: ctx.req.query,
|
|
176
|
+
params: ctx.req.params
|
|
177
|
+
});
|
|
328
178
|
const result = handlerFunction(ctx, inst.clearRequest);
|
|
329
179
|
await Promise.resolve(result);
|
|
330
180
|
} catch (error) {
|
|
@@ -335,7 +185,7 @@ var Router = class Router {
|
|
|
335
185
|
"put",
|
|
336
186
|
"patch",
|
|
337
187
|
"delete"
|
|
338
|
-
].includes(method)) router.post(route.path, (req,
|
|
188
|
+
].includes(method)) router.post(route.path, (req, _res, next) => {
|
|
339
189
|
Router.ensureRequestBodyAccessor(req);
|
|
340
190
|
if (Router.resolveMethodOverride(req.method, req.headers, req.body) !== method) return next("route");
|
|
341
191
|
req.method = method.toUpperCase();
|
|
@@ -349,7 +199,11 @@ var Router = class Router {
|
|
|
349
199
|
next
|
|
350
200
|
};
|
|
351
201
|
const inst = instance ?? route;
|
|
352
|
-
|
|
202
|
+
Router.bindRequestToInstance(ctx, inst, route, {
|
|
203
|
+
body: ctx.req.getBody(),
|
|
204
|
+
query: ctx.req.query,
|
|
205
|
+
params: ctx.req.params
|
|
206
|
+
});
|
|
353
207
|
const result = handlerFunction(ctx, inst.clearRequest);
|
|
354
208
|
await Promise.resolve(result);
|
|
355
209
|
} catch (error) {
|
|
@@ -359,21 +213,6 @@ var Router = class Router {
|
|
|
359
213
|
}
|
|
360
214
|
}
|
|
361
215
|
}
|
|
362
|
-
static async bindRequestToInstance(ctx, instance, route) {
|
|
363
|
-
if (!instance) return;
|
|
364
|
-
Router.ensureRequestBodyAccessor(ctx.req);
|
|
365
|
-
instance.ctx = ctx;
|
|
366
|
-
instance.body = ctx.req.getBody();
|
|
367
|
-
instance.query = ctx.req.query;
|
|
368
|
-
instance.params = ctx.req.params;
|
|
369
|
-
instance.clearRequest = new ClearRequest({
|
|
370
|
-
ctx,
|
|
371
|
-
route,
|
|
372
|
-
body: instance.body,
|
|
373
|
-
query: instance.query,
|
|
374
|
-
params: instance.params
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
216
|
};
|
|
378
217
|
|
|
379
218
|
//#endregion
|