tezx 2.0.6 → 2.0.8
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 +3 -1
- package/cjs/core/context.js +38 -5
- package/cjs/core/request.js +2 -0
- package/cjs/core/router.js +124 -13
- package/cjs/core/server.js +9 -13
- package/cjs/index.js +6 -5
- package/cjs/middleware/cacheControl.js +34 -1
- package/cjs/node/adapter.js +34 -1
- package/cjs/utils/regexRouter.js +58 -0
- package/cjs/utils/staticFile.js +35 -2
- package/cjs/ws/node.js +34 -1
- package/core/request.d.ts +6 -1
- package/core/request.js +2 -0
- package/core/router.d.ts +34 -30
- package/core/router.js +90 -12
- package/core/server.d.ts +1 -1
- package/core/server.js +9 -13
- package/helper/index.d.ts +4 -2
- package/index.d.ts +5 -4
- package/index.js +4 -4
- package/package.json +1 -1
- package/utils/regexRouter.d.ts +66 -0
- package/utils/regexRouter.js +53 -0
- package/cjs/utils/params.js +0 -94
- package/utils/params.d.ts +0 -7
- package/utils/params.js +0 -91
package/core/router.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type NextCallback = () => Promise<any>;
|
|
|
6
6
|
export type CallbackReturn = Promise<Response> | Response;
|
|
7
7
|
export type Callback<T extends Record<string, any> = {}> = (ctx: ctx<T>) => CallbackReturn;
|
|
8
8
|
export type Middleware<T extends Record<string, any> = {}> = (ctx: ctx<T>, next: NextCallback) => Promise<Response | void> | Response | NextCallback;
|
|
9
|
+
export type PathType = string | RegExp;
|
|
9
10
|
export type RouterConfig = {
|
|
10
11
|
/**
|
|
11
12
|
* `env` allows you to define environment variables for the router.
|
|
@@ -36,6 +37,8 @@ export type StaticServeOption = {
|
|
|
36
37
|
};
|
|
37
38
|
export type RouterHandler<T extends Record<string, any>> = {
|
|
38
39
|
callback: Callback<T>;
|
|
40
|
+
paramNames: string[];
|
|
41
|
+
regex: RegExp;
|
|
39
42
|
middlewares: UniqueMiddlewares | DuplicateMiddlewares;
|
|
40
43
|
};
|
|
41
44
|
export declare class Router<T extends Record<string, any> = {}> extends MiddlewareConfigure<T> {
|
|
@@ -72,13 +75,14 @@ export declare class Router<T extends Record<string, any> = {}> extends Middlewa
|
|
|
72
75
|
*
|
|
73
76
|
* // With middleware
|
|
74
77
|
* app.get('/secure', authMiddleware, (ctx) => { ... });
|
|
78
|
+
* app.get(/^\/item\/(\d+)\/(edit|view)?\/?$/, (ctx) => { ... });
|
|
75
79
|
*
|
|
76
80
|
* // With multiple middlewares
|
|
77
81
|
* app.get('/admin', [authMiddleware, adminMiddleware], (ctx) => { ... });
|
|
78
82
|
*/
|
|
79
|
-
get(path:
|
|
80
|
-
get(path:
|
|
81
|
-
get(path:
|
|
83
|
+
get(path: PathType, callback: Callback<T>): this;
|
|
84
|
+
get(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
85
|
+
get(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
82
86
|
/**
|
|
83
87
|
* Registers a Server-Sent Events (SSE) route handler for the given path.
|
|
84
88
|
*
|
|
@@ -108,66 +112,66 @@ export declare class Router<T extends Record<string, any> = {}> extends Middlewa
|
|
|
108
112
|
* });
|
|
109
113
|
* ```
|
|
110
114
|
*
|
|
111
|
-
* @param {
|
|
115
|
+
* @param {PathType} path - The route path for SSE (e.g. `/events`).
|
|
112
116
|
* @param {(ctx: Context) => any} handler - A handler function that returns a streamed response.
|
|
113
117
|
*/
|
|
114
|
-
sse(path:
|
|
118
|
+
sse(path: PathType, handler: (ctx: Context) => any): void;
|
|
115
119
|
/**
|
|
116
120
|
* Registers a POST route with optional middleware(s)
|
|
117
121
|
* @param path - URL path pattern
|
|
118
122
|
* @param args - Handler callback or middleware(s) + handler
|
|
119
123
|
*/
|
|
120
|
-
post(path:
|
|
121
|
-
post(path:
|
|
122
|
-
post(path:
|
|
124
|
+
post(path: PathType, callback: Callback<T>): this;
|
|
125
|
+
post(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
126
|
+
post(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
123
127
|
/**
|
|
124
128
|
* Registers a PUT route with optional middleware(s)
|
|
125
129
|
* @param path - URL path pattern
|
|
126
130
|
* @param args - Handler callback or middleware(s) + handler
|
|
127
131
|
*/
|
|
128
|
-
put(path:
|
|
129
|
-
put(path:
|
|
130
|
-
put(path:
|
|
132
|
+
put(path: PathType, callback: Callback<T>): this;
|
|
133
|
+
put(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
134
|
+
put(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
131
135
|
/**
|
|
132
136
|
* Registers a PATCH route with optional middleware(s)
|
|
133
137
|
* @param path - URL path pattern
|
|
134
138
|
* @param args - Handler callback or middleware(s) + handler
|
|
135
139
|
*/
|
|
136
|
-
patch(path:
|
|
137
|
-
patch(path:
|
|
138
|
-
patch(path:
|
|
140
|
+
patch(path: PathType, callback: Callback<T>): this;
|
|
141
|
+
patch(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
142
|
+
patch(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
139
143
|
/**
|
|
140
144
|
* Registers a DELETE route with optional middleware(s)
|
|
141
145
|
* @param path - URL path pattern
|
|
142
146
|
* @param args - Handler callback or middleware(s) + handler
|
|
143
147
|
*/
|
|
144
|
-
delete(path:
|
|
145
|
-
delete(path:
|
|
146
|
-
delete(path:
|
|
148
|
+
delete(path: PathType, callback: Callback<T>): this;
|
|
149
|
+
delete(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
150
|
+
delete(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
147
151
|
/**
|
|
148
152
|
* Registers an OPTIONS route (primarily for CORS preflight requests)
|
|
149
153
|
* @param path - URL path pattern
|
|
150
154
|
* @param args - Handler callback or middleware(s) + handler
|
|
151
155
|
*/
|
|
152
|
-
options(path:
|
|
153
|
-
options(path:
|
|
154
|
-
options(path:
|
|
156
|
+
options(path: PathType, callback: Callback<T>): this;
|
|
157
|
+
options(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
158
|
+
options(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
155
159
|
/**
|
|
156
160
|
* Registers a HEAD route (returns headers only)
|
|
157
161
|
* @param path - URL path pattern
|
|
158
162
|
* @param args - Handler callback or middleware(s) + handler
|
|
159
163
|
*/
|
|
160
|
-
head(path:
|
|
161
|
-
head(path:
|
|
162
|
-
head(path:
|
|
164
|
+
head(path: PathType, callback: Callback<T>): this;
|
|
165
|
+
head(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
166
|
+
head(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
163
167
|
/**
|
|
164
168
|
* Registers a route that responds to all HTTP methods
|
|
165
169
|
* @param path - URL path pattern
|
|
166
170
|
* @param args - Handler callback or middleware(s) + handler
|
|
167
171
|
*/
|
|
168
|
-
all(path:
|
|
169
|
-
all(path:
|
|
170
|
-
all(path:
|
|
172
|
+
all(path: PathType, callback: Callback<T>): this;
|
|
173
|
+
all(path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
174
|
+
all(path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
171
175
|
/**
|
|
172
176
|
* Generic method registration for custom HTTP methods
|
|
173
177
|
* @param method - HTTP method name (e.g., 'PURGE')
|
|
@@ -178,10 +182,10 @@ export declare class Router<T extends Record<string, any> = {}> extends Middlewa
|
|
|
178
182
|
* // Register custom method
|
|
179
183
|
* server.addRoute('PURGE', '/cache', purgeHandler);
|
|
180
184
|
*/
|
|
181
|
-
addRoute(method: HTTPMethod, path:
|
|
182
|
-
addRoute(method: HTTPMethod, path:
|
|
183
|
-
addRoute(method: HTTPMethod, path:
|
|
184
|
-
addRoute(method: HTTPMethod, path:
|
|
185
|
+
addRoute(method: HTTPMethod, path: PathType, callback: Callback<T>): this;
|
|
186
|
+
addRoute(method: HTTPMethod, path: PathType, middleware: Middleware<T>): this;
|
|
187
|
+
addRoute(method: HTTPMethod, path: PathType, middleware: Middleware<T>, callback: Callback<T>): this;
|
|
188
|
+
addRoute(method: HTTPMethod, path: PathType, middlewares: Middleware<T>[], callback: Callback<T>): this;
|
|
185
189
|
/**
|
|
186
190
|
* Mount a sub-router at specific path prefix
|
|
187
191
|
* @param path - Base path for the sub-router
|
package/core/router.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addBaseToRegex, compileRegexRoute } from "../utils/regexRouter.js";
|
|
1
2
|
import { getFiles } from "../utils/staticFile.js";
|
|
2
3
|
import { sanitizePathSplit, wildcardOrOptionalParamRegex, } from "../utils/url.js";
|
|
3
4
|
import { GlobalConfig } from "./config.js";
|
|
@@ -191,25 +192,57 @@ export class Router extends MiddlewareConfigure {
|
|
|
191
192
|
this.#addRoute(method, path, callback, middlewares);
|
|
192
193
|
}
|
|
193
194
|
#addRoute(method, path, callback, middlewares) {
|
|
194
|
-
const parts = sanitizePathSplit(this.basePath, path);
|
|
195
195
|
let finalMiddleware = middlewares;
|
|
196
196
|
if (!GlobalConfig.allowDuplicateMw) {
|
|
197
197
|
finalMiddleware = new Set(middlewares);
|
|
198
198
|
}
|
|
199
|
+
if (path instanceof RegExp) {
|
|
200
|
+
let regex = addBaseToRegex(this.basePath, path);
|
|
201
|
+
let regexPath = `regex://${regex?.source}`;
|
|
202
|
+
let handler = this.routers.get(regexPath);
|
|
203
|
+
if (!handler) {
|
|
204
|
+
handler = new Map();
|
|
205
|
+
handler.set(method, {
|
|
206
|
+
callback: callback,
|
|
207
|
+
paramNames: [],
|
|
208
|
+
regex: regex,
|
|
209
|
+
middlewares: finalMiddleware,
|
|
210
|
+
});
|
|
211
|
+
return this.routers.set(regexPath, handler);
|
|
212
|
+
}
|
|
213
|
+
if (!GlobalConfig.overwriteMethod && handler.has(method))
|
|
214
|
+
return;
|
|
215
|
+
return handler.set(method, {
|
|
216
|
+
callback,
|
|
217
|
+
paramNames: [],
|
|
218
|
+
regex: regex,
|
|
219
|
+
middlewares: finalMiddleware
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
const parts = sanitizePathSplit(this.basePath, path);
|
|
199
223
|
let p = parts.join("/");
|
|
200
224
|
if (wildcardOrOptionalParamRegex.test(`/${p}`)) {
|
|
201
|
-
let
|
|
225
|
+
let strPath = `string://${p}`;
|
|
226
|
+
let { paramNames, regex } = compileRegexRoute(parts);
|
|
227
|
+
let handler = this.routers.get(strPath);
|
|
202
228
|
if (!handler) {
|
|
203
229
|
handler = new Map();
|
|
204
230
|
handler.set(method, {
|
|
205
231
|
callback: callback,
|
|
232
|
+
regex: regex,
|
|
233
|
+
paramNames: paramNames,
|
|
206
234
|
middlewares: finalMiddleware,
|
|
207
235
|
});
|
|
208
|
-
return this.routers.set(
|
|
236
|
+
return this.routers.set(strPath, handler);
|
|
209
237
|
}
|
|
210
238
|
if (!GlobalConfig.overwriteMethod && handler.has(method))
|
|
211
239
|
return;
|
|
212
|
-
return handler.set(method, {
|
|
240
|
+
return handler.set(method, {
|
|
241
|
+
callback,
|
|
242
|
+
regex: regex,
|
|
243
|
+
paramNames: paramNames,
|
|
244
|
+
middlewares: finalMiddleware
|
|
245
|
+
});
|
|
213
246
|
}
|
|
214
247
|
let node = this.triRouter;
|
|
215
248
|
for (const part of parts) {
|
|
@@ -249,17 +282,62 @@ export class Router extends MiddlewareConfigure {
|
|
|
249
282
|
const parts = sanitizePathSplit(this.basePath, path);
|
|
250
283
|
if (router.routers.size) {
|
|
251
284
|
for (const [segment, handlers] of router.routers) {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
285
|
+
if (segment.indexOf("string://") == 0) {
|
|
286
|
+
let pattern = segment.replace(/^string:\/\//, "");
|
|
287
|
+
let joined = [...parts, pattern].join("/");
|
|
288
|
+
let strPath = `string://${joined}`;
|
|
289
|
+
if (this.routers.has(strPath)) {
|
|
290
|
+
const baseRouter = this.routers.get(strPath);
|
|
291
|
+
for (const [method, handler] of handlers) {
|
|
292
|
+
let { regex, paramNames } = baseRouter?.get(method);
|
|
293
|
+
handler.regex = regex;
|
|
294
|
+
handler.paramNames = paramNames;
|
|
295
|
+
if (!GlobalConfig.overwriteMethod && baseRouter.has(method))
|
|
296
|
+
continue;
|
|
297
|
+
baseRouter.set(method, handler);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
let h = new Map();
|
|
302
|
+
for (const [method, { callback, middlewares }] of handlers) {
|
|
303
|
+
let { paramNames, regex } = compileRegexRoute(joined);
|
|
304
|
+
h.set(method, {
|
|
305
|
+
callback: callback,
|
|
306
|
+
middlewares: middlewares,
|
|
307
|
+
paramNames,
|
|
308
|
+
regex
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
this.routers.set(strPath, h);
|
|
259
312
|
}
|
|
260
313
|
}
|
|
261
314
|
else {
|
|
262
|
-
|
|
315
|
+
let pattern = segment.replace("regex://", "");
|
|
316
|
+
let base = parts?.join("/");
|
|
317
|
+
let regex = addBaseToRegex(base, new RegExp(pattern));
|
|
318
|
+
let regexPath = `regex://${regex.source}`;
|
|
319
|
+
if (this.routers.has(regexPath)) {
|
|
320
|
+
const baseRouter = this.routers.get(regexPath);
|
|
321
|
+
for (const [method, handler] of handlers) {
|
|
322
|
+
handler.regex = regex;
|
|
323
|
+
handler.paramNames = [];
|
|
324
|
+
if (!GlobalConfig.overwriteMethod && baseRouter.has(method))
|
|
325
|
+
continue;
|
|
326
|
+
baseRouter.set(method, handler);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
let h = new Map();
|
|
331
|
+
for (const [method, { callback, middlewares }] of handlers) {
|
|
332
|
+
h.set(method, {
|
|
333
|
+
callback: callback,
|
|
334
|
+
middlewares: middlewares,
|
|
335
|
+
paramNames: [],
|
|
336
|
+
regex
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
this.routers.set(regexPath, h);
|
|
340
|
+
}
|
|
263
341
|
}
|
|
264
342
|
}
|
|
265
343
|
}
|
package/core/server.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export declare class TezX<T extends Record<string, any> = {}> extends Router<T>
|
|
|
62
62
|
protected findRoute(method: HTTPMethod, pathname: string): {
|
|
63
63
|
callback: any;
|
|
64
64
|
middlewares: Middleware<T>[];
|
|
65
|
-
params: Record<string, string>;
|
|
65
|
+
params: Record<string, null | string>;
|
|
66
66
|
} | null;
|
|
67
67
|
serve(req: Request, options: TezXServeOptions): Promise<Response | {
|
|
68
68
|
websocket: (props: any) => any;
|
package/core/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { colorText } from "../utils/colors.js";
|
|
2
2
|
import { httpStatusMap } from "../utils/httpStatusMap.js";
|
|
3
|
-
import {
|
|
3
|
+
import { regexMatchRoute } from "../utils/regexRouter.js";
|
|
4
4
|
import { GlobalConfig } from "./config.js";
|
|
5
5
|
import { Context } from "./context.js";
|
|
6
6
|
import { Router } from "./router.js";
|
|
@@ -16,18 +16,14 @@ export class TezX extends Router {
|
|
|
16
16
|
this.#onPathResolve = onPathResolve;
|
|
17
17
|
this.serve = this.serve.bind(this);
|
|
18
18
|
}
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const { success, params } =
|
|
23
|
-
|
|
24
|
-
urlPattern: pattern,
|
|
25
|
-
});
|
|
26
|
-
const handlers = routers.get(pattern)?.get(method) || routers.get(pattern)?.get("ALL");
|
|
27
|
-
if (success && handlers) {
|
|
19
|
+
#regexRouter(method, pathname) {
|
|
20
|
+
for (let pattern of this.routers.values()) {
|
|
21
|
+
const handler = pattern?.get(method) || pattern?.get("ALL");
|
|
22
|
+
const { success, params } = regexMatchRoute(handler?.regex, pathname, handler?.paramNames || []);
|
|
23
|
+
if (success && handler) {
|
|
28
24
|
return {
|
|
29
|
-
callback:
|
|
30
|
-
middlewares:
|
|
25
|
+
callback: handler.callback,
|
|
26
|
+
middlewares: handler.middlewares,
|
|
31
27
|
params: params,
|
|
32
28
|
};
|
|
33
29
|
}
|
|
@@ -83,7 +79,7 @@ export class TezX extends Router {
|
|
|
83
79
|
}
|
|
84
80
|
findRoute(method, pathname) {
|
|
85
81
|
const route = this.#triRouter(method, pathname) ||
|
|
86
|
-
this.#
|
|
82
|
+
this.#regexRouter(method, pathname) ||
|
|
87
83
|
this.#triRouter(method, pathname, "param");
|
|
88
84
|
if (route) {
|
|
89
85
|
return {
|
package/helper/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Environment } from "../core/environment.js";
|
|
2
2
|
import { sanitizePathSplit } from "../utils/url.js";
|
|
3
3
|
import { generateID } from "./common.js";
|
|
4
|
-
export {
|
|
4
|
+
export { GlobalConfig } from "../core/config.js";
|
|
5
|
+
export type { AdapterType } from "../core/config.js";
|
|
5
6
|
export { Environment } from "../core/environment.js";
|
|
6
|
-
export { sanitizePathSplit
|
|
7
|
+
export { sanitizePathSplit } from "../utils/url.js";
|
|
8
|
+
export type { UrlRef } from "../utils/url.js";
|
|
7
9
|
export { generateID } from "./common.js";
|
|
8
10
|
declare const _default: {
|
|
9
11
|
Environment: typeof Environment;
|
package/index.d.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { Router } from "./core/router.js";
|
|
2
2
|
import { TezX } from "./core/server.js";
|
|
3
|
-
import {
|
|
3
|
+
import { regexMatchRoute, compileRegexRoute } from "./utils/regexRouter.js";
|
|
4
4
|
export { Router } from "./core/router.js";
|
|
5
|
-
export type { Callback, ctx as Context, Middleware, NextCallback, RouterConfig, StaticServeOption } from "./core/router.js";
|
|
5
|
+
export type { Callback, ctx as Context, Middleware, NextCallback, RouterConfig, PathType, StaticServeOption } from "./core/router.js";
|
|
6
6
|
export type { AdapterType } from "./core/config.js";
|
|
7
7
|
export type { CookieOptions, ResponseHeaders } from "./core/context.js";
|
|
8
8
|
export type { NetAddr as AddressType, ConnAddress, FormDataOptions, HTTPMethod } from "./core/request.js";
|
|
9
9
|
export { TezX } from "./core/server.js";
|
|
10
10
|
export type { TezXConfig, TezXServeOptions } from "./core/server.js";
|
|
11
11
|
export type { UrlRef } from "./utils/url.js";
|
|
12
|
-
export {
|
|
12
|
+
export { regexMatchRoute, compileRegexRoute };
|
|
13
13
|
export declare let version: string;
|
|
14
14
|
declare const _default: {
|
|
15
15
|
Router: typeof Router;
|
|
16
|
+
regexMatchRoute: typeof regexMatchRoute;
|
|
17
|
+
compileRegexRoute: typeof compileRegexRoute;
|
|
16
18
|
TezX: typeof TezX;
|
|
17
|
-
useParams: typeof useParams;
|
|
18
19
|
version: string;
|
|
19
20
|
};
|
|
20
21
|
export default _default;
|
package/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Router } from "./core/router.js";
|
|
2
2
|
import { TezX } from "./core/server.js";
|
|
3
|
-
import {
|
|
3
|
+
import { regexMatchRoute, compileRegexRoute } from "./utils/regexRouter.js";
|
|
4
4
|
export { Router } from "./core/router.js";
|
|
5
5
|
export { TezX } from "./core/server.js";
|
|
6
|
-
export {
|
|
7
|
-
export let version = "2.0.
|
|
6
|
+
export { regexMatchRoute, compileRegexRoute };
|
|
7
|
+
export let version = "2.0.8";
|
|
8
8
|
export default {
|
|
9
9
|
Router,
|
|
10
|
+
regexMatchRoute, compileRegexRoute,
|
|
10
11
|
TezX,
|
|
11
|
-
useParams,
|
|
12
12
|
version,
|
|
13
13
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tezx",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "TezX is a high-performance, lightweight JavaScript framework designed for speed, scalability, and flexibility. It enables efficient routing, middleware management, and static file serving with minimal configuration. Fully compatible with Node.js, Deno, and Bun.",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "index.js",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiles a route string or segment array into a regular expression for matching URL paths.
|
|
3
|
+
* Supports dynamic `:param`, optional `:param?`, and wildcard `*param` segments.
|
|
4
|
+
*
|
|
5
|
+
* @param {string | string[]} seg - The route pattern, either as a string (`'/user/:id'`)
|
|
6
|
+
* or an array of segments (`['user', ':id']`).
|
|
7
|
+
*
|
|
8
|
+
* @returns {{
|
|
9
|
+
* regex: RegExp,
|
|
10
|
+
* paramNames: string[]
|
|
11
|
+
* }}
|
|
12
|
+
* @example
|
|
13
|
+
* const { regex, paramNames } = compileRegexRoute('/user/:id/post/:slug?');
|
|
14
|
+
* // regex: /^\/user\/([^\/]+)\/(?:([^\/]+))?\/?$/
|
|
15
|
+
* // paramNames: ['id', 'slug']
|
|
16
|
+
*
|
|
17
|
+
* regex.test('/user/123/post/hello'); // ✅ true
|
|
18
|
+
* regex.test('/user/123/post'); // ✅ true (because :slug? is optional)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const { regex, paramNames } = compileRegexRoute('/files/*path');
|
|
22
|
+
* // regex: /^\/files\/(.+)\/?$/
|
|
23
|
+
* // paramNames: ['path']
|
|
24
|
+
*
|
|
25
|
+
* regex.test('/files/images/cat.jpg'); // ✅ true
|
|
26
|
+
*/
|
|
27
|
+
export declare function compileRegexRoute(seg: string | string[]): {
|
|
28
|
+
regex: RegExp;
|
|
29
|
+
paramNames: string[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Combines a base path with a route regex pattern.
|
|
33
|
+
*
|
|
34
|
+
* @param basePath - The base path to prepend (e.g., '/api/v1')
|
|
35
|
+
* @param routeRegex - The original route regex (e.g., /^\/users\/([^/]+?)$/)
|
|
36
|
+
* @returns A new regex that includes the base path
|
|
37
|
+
*/
|
|
38
|
+
export declare function addBaseToRegex(basePath: string, routeRegex: RegExp): RegExp;
|
|
39
|
+
/**
|
|
40
|
+
* Matches a given URL against a provided regular expression and extracts named parameters.
|
|
41
|
+
*
|
|
42
|
+
* @param {RegExp} regex - The regular expression to match against the URL.
|
|
43
|
+
* It should include capturing groups for each parameter.
|
|
44
|
+
* Example: /^\/user\/(\d+)\/post\/(\w+)$/
|
|
45
|
+
*
|
|
46
|
+
* @param {string} url - The URL string to match.
|
|
47
|
+
* Example: "/user/123/post/abc"
|
|
48
|
+
*
|
|
49
|
+
* @param {string[]} paramNames - An array of parameter names corresponding to the capturing groups in the regex.
|
|
50
|
+
* Example: ["userId", "postId"]
|
|
51
|
+
*
|
|
52
|
+
* @returns {{ success: boolean, params: Record<string, string | null> }} An object indicating:
|
|
53
|
+
* - `success`: whether the URL matched the regex.
|
|
54
|
+
* - `params`: an object mapping parameter names to their matched values, or `null` if not found.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* const regex = /^\/user\/(\d+)\/post\/(\w+)$/;
|
|
58
|
+
* const url = "/user/123/post/abc";
|
|
59
|
+
* const paramNames = ["userId", "postId"];
|
|
60
|
+
* const result = regexMatchRoute(regex, url, paramNames);
|
|
61
|
+
* // result = { success: true, params: { userId: "123", postId: "abc" } }
|
|
62
|
+
*/
|
|
63
|
+
export declare function regexMatchRoute(regex: RegExp, url: string, paramNames: string[]): {
|
|
64
|
+
params: Record<string, string | null>;
|
|
65
|
+
success: boolean;
|
|
66
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { sanitizePathSplit } from "./url.js";
|
|
2
|
+
export function compileRegexRoute(seg) {
|
|
3
|
+
const segments = typeof seg == 'string' ? seg.split("/").filter(Boolean) : seg;
|
|
4
|
+
let regexStr = "^";
|
|
5
|
+
const paramNames = [];
|
|
6
|
+
for (let seg of segments) {
|
|
7
|
+
if (seg.startsWith(":")) {
|
|
8
|
+
const isOptional = seg.endsWith("?");
|
|
9
|
+
const name = seg.replace(":", "").replace("?", "");
|
|
10
|
+
paramNames.push(name);
|
|
11
|
+
regexStr += isOptional
|
|
12
|
+
? `(?:\\/([^\\/]+))?`
|
|
13
|
+
: `\\/([^\\/]+)`;
|
|
14
|
+
}
|
|
15
|
+
else if (seg.startsWith("*")) {
|
|
16
|
+
const name = seg.slice(1) || "*";
|
|
17
|
+
paramNames.push(name);
|
|
18
|
+
regexStr += `\\/(.+)`;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
regexStr += `\\/${seg}`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
regexStr += "\\/?$";
|
|
25
|
+
return {
|
|
26
|
+
regex: new RegExp(regexStr),
|
|
27
|
+
paramNames,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function addBaseToRegex(basePath, routeRegex) {
|
|
31
|
+
basePath = "/" + sanitizePathSplit("/", basePath)?.join("/");
|
|
32
|
+
if (basePath === "/")
|
|
33
|
+
basePath = "";
|
|
34
|
+
let body = routeRegex.source.replace(/^(\^)/, '').replace(/(\$)$/, '');
|
|
35
|
+
body = body.replace(/\\\//g, "/");
|
|
36
|
+
if (body.startsWith("/")) {
|
|
37
|
+
body = body.slice(1);
|
|
38
|
+
}
|
|
39
|
+
const cleaned = body.replace(/^\/+|\/+$/g, "").replace(/\/?\?$/, "");
|
|
40
|
+
const combined = basePath + "/" + cleaned + "/?";
|
|
41
|
+
const finalRegex = new RegExp(`^${combined}$`);
|
|
42
|
+
return finalRegex;
|
|
43
|
+
}
|
|
44
|
+
export function regexMatchRoute(regex, url, paramNames) {
|
|
45
|
+
const match = url.match(regex);
|
|
46
|
+
if (!match)
|
|
47
|
+
return { success: false, params: {} };
|
|
48
|
+
const params = {};
|
|
49
|
+
paramNames.forEach((name, idx) => {
|
|
50
|
+
params[name] = match[idx + 1] ?? null;
|
|
51
|
+
});
|
|
52
|
+
return { params, success: true };
|
|
53
|
+
}
|
package/cjs/utils/params.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useParams = useParams;
|
|
4
|
-
function useParams({ path, urlPattern, }) {
|
|
5
|
-
let params = {};
|
|
6
|
-
path = path.replace(/^\/+|\/+$/g, "");
|
|
7
|
-
urlPattern = urlPattern.replace(/^\/+|\/+$/g, "");
|
|
8
|
-
const pathSegments = path ? path.split("/") : [];
|
|
9
|
-
const patternSegments = urlPattern ? urlPattern.split("/") : [];
|
|
10
|
-
const pathLength = pathSegments.length;
|
|
11
|
-
const patternLength = patternSegments.length;
|
|
12
|
-
if (pathLength > patternLength && !urlPattern.includes("*")) {
|
|
13
|
-
return { success: false, params: {} };
|
|
14
|
-
}
|
|
15
|
-
let pathIndex = 0;
|
|
16
|
-
for (let i = 0; i < patternLength; i++) {
|
|
17
|
-
const patternSegment = patternSegments[i];
|
|
18
|
-
if (patternSegment?.startsWith("*")) {
|
|
19
|
-
const trailingPatterns = patternSegments.slice(i + 1);
|
|
20
|
-
let paramName = patternSegment.length == 1 ? "*" : patternSegment?.slice(1);
|
|
21
|
-
if (trailingPatterns.length > 0) {
|
|
22
|
-
const expectedTrailing = trailingPatterns.join("/");
|
|
23
|
-
const actualTrailing = pathSegments
|
|
24
|
-
.slice(pathLength - trailingPatterns.length)
|
|
25
|
-
.join("/");
|
|
26
|
-
const wildcardPath = pathSegments
|
|
27
|
-
.slice(pathIndex, pathLength - trailingPatterns.length)
|
|
28
|
-
.join("/");
|
|
29
|
-
if (expectedTrailing !== actualTrailing || !wildcardPath) {
|
|
30
|
-
return { success: false, params: {} };
|
|
31
|
-
}
|
|
32
|
-
params[paramName] = wildcardPath;
|
|
33
|
-
return { success: true, params };
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
const wildcardPath = pathSegments.slice(pathIndex).join("/");
|
|
37
|
-
if (!wildcardPath) {
|
|
38
|
-
return { success: false, params: {} };
|
|
39
|
-
}
|
|
40
|
-
params[paramName] = wildcardPath;
|
|
41
|
-
return { success: true, params };
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (patternSegment.startsWith(":") && patternSegment.endsWith("?")) {
|
|
45
|
-
const paramName = patternSegment.slice(1, -1);
|
|
46
|
-
const nextPattern = patternSegments[i + 1];
|
|
47
|
-
if (nextPattern &&
|
|
48
|
-
!nextPattern.startsWith(":") &&
|
|
49
|
-
nextPattern !== "*" &&
|
|
50
|
-
pathIndex < pathLength &&
|
|
51
|
-
pathSegments[pathIndex] === nextPattern) {
|
|
52
|
-
params[paramName] = null;
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
const remainingPatterns = patternSegments.slice(i + 1);
|
|
56
|
-
const requiredCount = remainingPatterns.filter((seg) => !(seg.startsWith(":") && seg.endsWith("?"))).length;
|
|
57
|
-
const remainingPath = pathLength - pathIndex;
|
|
58
|
-
if (remainingPath === requiredCount) {
|
|
59
|
-
params[paramName] = null;
|
|
60
|
-
}
|
|
61
|
-
else if (pathIndex < pathLength) {
|
|
62
|
-
params[paramName] = pathSegments[pathIndex];
|
|
63
|
-
pathIndex++;
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
params[paramName] = null;
|
|
67
|
-
}
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
if (patternSegment.startsWith(":")) {
|
|
71
|
-
const paramName = patternSegment.slice(1);
|
|
72
|
-
if (!/^[a-zA-Z0-9_]+$/.test(paramName)) {
|
|
73
|
-
return { success: false, params: {} };
|
|
74
|
-
}
|
|
75
|
-
if (pathIndex < pathLength) {
|
|
76
|
-
params[paramName] = pathSegments[pathIndex];
|
|
77
|
-
pathIndex++;
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
return { success: false, params: {} };
|
|
81
|
-
}
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
const pathSegment = pathSegments[pathIndex];
|
|
85
|
-
if (patternSegment !== pathSegment) {
|
|
86
|
-
return { success: false, params: {} };
|
|
87
|
-
}
|
|
88
|
-
pathIndex++;
|
|
89
|
-
}
|
|
90
|
-
if (pathIndex < pathLength) {
|
|
91
|
-
return { success: false, params: {} };
|
|
92
|
-
}
|
|
93
|
-
return { success: true, params };
|
|
94
|
-
}
|