clear-router 2.5.13 → 2.5.14

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.
Files changed (38) hide show
  1. package/README.md +2 -0
  2. package/dist/core/index.cjs +1 -1
  3. package/dist/core/index.d.cts +1 -1
  4. package/dist/core/index.d.mts +1 -1
  5. package/dist/core/index.mjs +1 -1
  6. package/dist/decorators/setup.cjs +1 -1
  7. package/dist/decorators/setup.d.mts +0 -1
  8. package/dist/decorators/setup.mjs +1 -1
  9. package/dist/express/index.cjs +14 -11
  10. package/dist/express/index.d.cts +11 -9
  11. package/dist/express/index.d.mts +11 -9
  12. package/dist/express/index.mjs +14 -11
  13. package/dist/fastify/index.cjs +16 -13
  14. package/dist/fastify/index.d.cts +11 -9
  15. package/dist/fastify/index.d.mts +11 -9
  16. package/dist/fastify/index.mjs +16 -13
  17. package/dist/h3/index.cjs +14 -11
  18. package/dist/h3/index.d.cts +11 -9
  19. package/dist/h3/index.d.mts +11 -9
  20. package/dist/h3/index.mjs +14 -11
  21. package/dist/hono/index.cjs +14 -11
  22. package/dist/hono/index.d.cts +11 -9
  23. package/dist/hono/index.d.mts +11 -9
  24. package/dist/hono/index.mjs +14 -11
  25. package/dist/index.cjs +101 -11
  26. package/dist/index.d.cts +37 -10
  27. package/dist/index.d.mts +37 -10
  28. package/dist/index.mjs +101 -11
  29. package/dist/koa/index.cjs +14 -11
  30. package/dist/koa/index.d.cts +11 -9
  31. package/dist/koa/index.d.mts +11 -9
  32. package/dist/koa/index.mjs +14 -11
  33. package/dist/{router-DiKqUyvk.d.mts → router-Bk8mXRu1.d.mts} +36 -9
  34. package/dist/{router-D9H9-T27.cjs → router-CAnd539U.cjs} +101 -11
  35. package/dist/{router-CPmZcbU0.mjs → router-DSq9dtuQ.mjs} +101 -11
  36. package/dist/{router-DTI0BowV.d.cts → router-jwZwD8ZT.d.cts} +36 -9
  37. package/dist/types/Route.d.mts +16 -1
  38. package/package.json +1 -1
@@ -10,21 +10,49 @@ var Route = class {
10
10
  clearRequest;
11
11
  methods;
12
12
  path;
13
+ registrationPaths;
14
+ parameters;
15
+ routeName;
13
16
  handler;
14
17
  middlewares;
15
18
  controllerName;
16
19
  actionName;
17
20
  handlerType;
18
21
  middlewareCount;
19
- constructor(methods, path, handler, middlewares = []) {
22
+ constructor(methods, path, handler, middlewares = [], options = {}) {
20
23
  this.methods = methods;
21
24
  this.path = path;
25
+ this.registrationPaths = options.registrationPaths || [path];
26
+ this.parameters = options.parameters || [];
22
27
  this.handler = handler;
23
28
  this.middlewares = middlewares;
24
29
  this.handlerType = Array.isArray(handler) ? "controller" : "function";
25
30
  this.middlewareCount = middlewares.length;
26
31
  this.controllerName = Array.isArray(handler) ? handler[0]?.name : void 0;
27
32
  this.actionName = Array.isArray(handler) ? handler[1] : typeof handler === "function" ? handler.constructor.name ?? handler.name : void 0;
33
+ this.onName = options.onName;
34
+ }
35
+ onName;
36
+ name(name) {
37
+ const previousName = this.routeName;
38
+ this.routeName = name;
39
+ this.onName?.(name, this, previousName);
40
+ return this;
41
+ }
42
+ toPath(params = {}) {
43
+ return this.path.replace(/\/?\{([^{}]+)\}/g, (segment, raw) => {
44
+ const optional = raw.endsWith("?");
45
+ const [rawName, rawField] = (optional ? raw.slice(0, -1) : raw).split(":", 2);
46
+ const name = rawName.trim();
47
+ const field = rawField?.trim();
48
+ const value = params[name];
49
+ const resolved = field && value && typeof value === "object" ? value[field] : value;
50
+ if (typeof resolved === "undefined" || resolved === null || resolved === "") {
51
+ if (optional) return "";
52
+ throw new Error(`Missing required route parameter: ${name}`);
53
+ }
54
+ return `${segment.startsWith("/") ? "/" : ""}${encodeURIComponent(String(resolved))}`;
55
+ }) || "/";
28
56
  }
29
57
  };
30
58
 
@@ -107,6 +135,7 @@ var CoreRouter = class {
107
135
  routes: [],
108
136
  routesByPathMethod: {},
109
137
  routesByMethod: {},
138
+ routesByName: {},
110
139
  prefix: "",
111
140
  groupMiddlewares: [],
112
141
  globalMiddlewares: []
@@ -123,6 +152,7 @@ var CoreRouter = class {
123
152
  "routes",
124
153
  "routesByPathMethod",
125
154
  "routesByMethod",
155
+ "routesByName",
126
156
  "prefix",
127
157
  "groupMiddlewares",
128
158
  "globalMiddlewares"
@@ -255,6 +285,7 @@ var CoreRouter = class {
255
285
  static routes = [];
256
286
  static routesByPathMethod = {};
257
287
  static routesByMethod = {};
288
+ static routesByName = {};
258
289
  static prefix = "";
259
290
  static groupMiddlewares = [];
260
291
  static globalMiddlewares = [];
@@ -306,6 +337,7 @@ var CoreRouter = class {
306
337
  if (!Array.isArray(this.routes)) this.routes = [];
307
338
  if (!this.routesByPathMethod || typeof this.routesByPathMethod !== "object") this.routesByPathMethod = {};
308
339
  if (!this.routesByMethod || typeof this.routesByMethod !== "object") this.routesByMethod = {};
340
+ if (!this.routesByName || typeof this.routesByName !== "object") this.routesByName = {};
309
341
  if (typeof this.prefix !== "string") this.prefix = "";
310
342
  if (!Array.isArray(this.groupMiddlewares)) this.groupMiddlewares = [];
311
343
  if (!Array.isArray(this.globalMiddlewares)) this.globalMiddlewares = [];
@@ -320,6 +352,47 @@ var CoreRouter = class {
320
352
  static normalizePath(path) {
321
353
  return "/" + path.split("/").filter(Boolean).join("/");
322
354
  }
355
+ static parseRouteParameters(path) {
356
+ const parameters = [];
357
+ const seen = /* @__PURE__ */ new Set();
358
+ const pattern = /\{([^{}]+)\}/g;
359
+ let match;
360
+ while ((match = pattern.exec(path)) !== null) {
361
+ const raw = match[1].trim();
362
+ const optional = raw.endsWith("?");
363
+ const [name, field] = (optional ? raw.slice(0, -1) : raw).split(":", 2).map((part) => part.trim());
364
+ if (!name || seen.has(name)) continue;
365
+ seen.add(name);
366
+ parameters.push({
367
+ name,
368
+ field: field || void 0,
369
+ optional
370
+ });
371
+ }
372
+ return parameters;
373
+ }
374
+ static expandRoutePath(path) {
375
+ let paths = [""];
376
+ const segments = this.normalizePath(path).split("/").filter(Boolean);
377
+ for (const segment of segments) {
378
+ const match = segment.match(/^\{([^{}]+)\}$/);
379
+ if (!match) {
380
+ paths = paths.map((current) => `${current}/${segment}`);
381
+ continue;
382
+ }
383
+ const raw = match[1].trim();
384
+ const optional = raw.endsWith("?");
385
+ const [rawName] = (optional ? raw.slice(0, -1) : raw).split(":", 2);
386
+ const name = rawName.trim();
387
+ if (!name) continue;
388
+ const parameterSegment = `/:${name}`;
389
+ paths = optional ? paths.flatMap((current) => [current, `${current}${parameterSegment}`]) : paths.map((current) => `${current}${parameterSegment}`);
390
+ }
391
+ return paths.map((path) => path || "/");
392
+ }
393
+ static routeRegistrationPaths(path) {
394
+ return this.expandRoutePath(path);
395
+ }
323
396
  /**
324
397
  * Configures the router with the given options, such as method override settings.
325
398
  *
@@ -393,11 +466,20 @@ var CoreRouter = class {
393
466
  methods = Array.isArray(methods) ? methods : [methods];
394
467
  middlewares = middlewares ? Array.isArray(middlewares) ? middlewares : [middlewares] : void 0;
395
468
  const fullPath = this.normalizePath(`${activePrefix}/${path}`);
469
+ const registrationPaths = this.routeRegistrationPaths(fullPath);
470
+ const parameters = this.parseRouteParameters(fullPath);
396
471
  const route = new Route(methods.includes("options") ? methods : methods.concat("options"), fullPath, handler, [
397
472
  ...this.globalMiddlewares,
398
473
  ...activeGroupMiddlewares,
399
474
  ...middlewares || []
400
- ]);
475
+ ], {
476
+ registrationPaths,
477
+ parameters,
478
+ onName: (name, route, previousName) => {
479
+ if (previousName && this.routesByName[previousName] === route) delete this.routesByName[previousName];
480
+ this.routesByName[name] = route;
481
+ }
482
+ });
401
483
  if (!methods.includes("options") && !this.routesByPathMethod[`OPTIONS ${fullPath}`]) this.options(path, this.createDefaultOptionsHandler());
402
484
  this.routes.push(route);
403
485
  for (const method of methods.map((m) => m.toUpperCase())) {
@@ -405,6 +487,7 @@ var CoreRouter = class {
405
487
  if (!this.routesByMethod[method]) this.routesByMethod[method] = [];
406
488
  this.routesByMethod[method].push(route);
407
489
  }
490
+ return route;
408
491
  }
409
492
  /**
410
493
  * Define a resourceful API controller with standard CRUD routes.
@@ -458,7 +541,7 @@ var CoreRouter = class {
458
541
  * @param middlewares Optional middlewares to apply to the GET route.
459
542
  */
460
543
  static get(path, handler, middlewares) {
461
- this.add("get", path, handler, middlewares);
544
+ return this.add("get", path, handler, middlewares);
462
545
  }
463
546
  /**
464
547
  * Adds a new POST route to the router.
@@ -469,7 +552,7 @@ var CoreRouter = class {
469
552
  * @param middlewares
470
553
  */
471
554
  static post(path, handler, middlewares) {
472
- this.add("post", path, handler, middlewares);
555
+ return this.add("post", path, handler, middlewares);
473
556
  }
474
557
  /**
475
558
  * Adds a new PUT route to the router.
@@ -480,7 +563,7 @@ var CoreRouter = class {
480
563
  * @param middlewares
481
564
  */
482
565
  static put(path, handler, middlewares) {
483
- this.add("put", path, handler, middlewares);
566
+ return this.add("put", path, handler, middlewares);
484
567
  }
485
568
  /**
486
569
  * Adds a new DELETE route to the router.
@@ -491,7 +574,7 @@ var CoreRouter = class {
491
574
  * @param middlewares
492
575
  */
493
576
  static delete(path, handler, middlewares) {
494
- this.add("delete", path, handler, middlewares);
577
+ return this.add("delete", path, handler, middlewares);
495
578
  }
496
579
  /**
497
580
  * Adds a new PATCH route to the router.
@@ -502,7 +585,7 @@ var CoreRouter = class {
502
585
  * @param middlewares
503
586
  */
504
587
  static patch(path, handler, middlewares) {
505
- this.add("patch", path, handler, middlewares);
588
+ return this.add("patch", path, handler, middlewares);
506
589
  }
507
590
  /**
508
591
  * Adds a new OPTIONS route to the router.
@@ -513,7 +596,7 @@ var CoreRouter = class {
513
596
  * @param middlewares
514
597
  */
515
598
  static options(path, handler, middlewares) {
516
- this.add("options", path, handler, middlewares);
599
+ return this.add("options", path, handler, middlewares);
517
600
  }
518
601
  /**
519
602
  * Adds a new HEAD route to the router.
@@ -524,7 +607,7 @@ var CoreRouter = class {
524
607
  * @param middlewares
525
608
  */
526
609
  static head(path, handler, middlewares) {
527
- this.add("head", path, handler, middlewares);
610
+ return this.add("head", path, handler, middlewares);
528
611
  }
529
612
  /**
530
613
  * Defines a group of routes with a common prefix.
@@ -566,8 +649,16 @@ var CoreRouter = class {
566
649
  this.ensureState();
567
650
  if (type === "method") return this.routesByMethod;
568
651
  if (type === "path") return this.routesByPathMethod;
652
+ if (type === "name") return this.routesByName;
569
653
  return this.routes.filter((e) => e.methods.length > 1 || e.methods[0] !== "options");
570
654
  }
655
+ static route(name) {
656
+ this.ensureState();
657
+ return this.routesByName[name];
658
+ }
659
+ static url(name, params) {
660
+ return this.route(name)?.toPath(params);
661
+ }
571
662
  static resolveHandler(route) {
572
663
  let handlerFunction;
573
664
  let instance = null;
@@ -634,8 +725,7 @@ var CoreRouter = class {
634
725
  designTokens
635
726
  });
636
727
  if (pluginArgs) return handlerFunction(...pluginArgs);
637
- if (!metadata) return handlerFunction(ctx, ctx.clearRequest);
638
- if (!tokens.length) return handlerFunction(ctx, ctx.clearRequest);
728
+ if (!metadata || !tokens.length) return handlerFunction(ctx, ctx.clearRequest);
639
729
  const args = [];
640
730
  for (const token of tokens) {
641
731
  const resolved = await Container.resolve(token, ctx, Boolean(this.config.container?.autoDiscover));
@@ -135,6 +135,11 @@ req: Request$1) => any | Promise<any>;
135
135
  type Handler = RouteHandler | ControllerHandler;
136
136
  //#endregion
137
137
  //#region src/Route.d.ts
138
+ interface RouteParameter {
139
+ name: string;
140
+ field?: string;
141
+ optional: boolean;
142
+ }
138
143
  declare class Route<X = any, M = Middleware | Middleware$1, H = any> {
139
144
  ctx: X;
140
145
  body: RequestData;
@@ -143,13 +148,23 @@ declare class Route<X = any, M = Middleware | Middleware$1, H = any> {
143
148
  clearRequest: ClearRequest;
144
149
  methods: HttpMethod[];
145
150
  path: string;
151
+ registrationPaths: string[];
152
+ parameters: RouteParameter[];
153
+ routeName?: string;
146
154
  handler: H;
147
155
  middlewares: M[];
148
156
  controllerName?: string;
149
157
  actionName?: string;
150
158
  handlerType: 'function' | 'controller';
151
159
  middlewareCount: number;
152
- constructor(methods: HttpMethod[], path: string, handler: H, middlewares?: M[]);
160
+ constructor(methods: HttpMethod[], path: string, handler: H, middlewares?: M[], options?: {
161
+ registrationPaths?: string[];
162
+ parameters?: RouteParameter[];
163
+ onName?: (name: string, route: Route<X, M, H>, previousName?: string) => void;
164
+ });
165
+ private onName?;
166
+ name(name: string): this;
167
+ toPath(params?: RequestData): string;
153
168
  }
154
169
  //#endregion
155
170
  //#region src/ClearRequest.d.ts
@@ -274,6 +289,7 @@ declare abstract class CoreRouter {
274
289
  routes: Array<Route<any, any, any>>;
275
290
  routesByPathMethod: Record<string, Route<any, any, any>>;
276
291
  routesByMethod: { [method in Uppercase<HttpMethod>]?: Array<Route<any, any, any>> };
292
+ routesByName: Record<string, Route<any, any, any>>;
277
293
  prefix: string;
278
294
  groupMiddlewares: any[];
279
295
  globalMiddlewares: any[];
@@ -300,6 +316,7 @@ declare abstract class CoreRouter {
300
316
  static routes: Array<Route<any, any, any>>;
301
317
  static routesByPathMethod: Record<string, Route<any, any, any>>;
302
318
  static routesByMethod: { [method in Uppercase<HttpMethod>]?: Array<Route<any, any, any>> };
319
+ static routesByName: Record<string, Route<any, any, any>>;
303
320
  static prefix: string;
304
321
  static groupMiddlewares: any[];
305
322
  static globalMiddlewares: any[];
@@ -316,6 +333,13 @@ declare abstract class CoreRouter {
316
333
  * @returns The normalized path.
317
334
  */
318
335
  static normalizePath(path: string): string;
336
+ protected static parseRouteParameters(path: string): Array<{
337
+ name: string;
338
+ field?: string;
339
+ optional: boolean;
340
+ }>;
341
+ protected static expandRoutePath(path: string): string[];
342
+ protected static routeRegistrationPaths(path: string): string[];
319
343
  /**
320
344
  * Configures the router with the given options, such as method override settings.
321
345
  *
@@ -334,7 +358,7 @@ declare abstract class CoreRouter {
334
358
  * @param handler
335
359
  * @param middlewares
336
360
  */
337
- static add(methods: HttpMethod | HttpMethod[], path: string, handler: any, middlewares?: any[] | any): void;
361
+ static add(methods: HttpMethod | HttpMethod[], path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
338
362
  /**
339
363
  * Define a resourceful API controller with standard CRUD routes.
340
364
  *
@@ -356,7 +380,7 @@ declare abstract class CoreRouter {
356
380
  * @param handler The handler function for the GET route.
357
381
  * @param middlewares Optional middlewares to apply to the GET route.
358
382
  */
359
- static get(path: string, handler: any, middlewares?: any[] | any): void;
383
+ static get(path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
360
384
  /**
361
385
  * Adds a new POST route to the router.
362
386
  *
@@ -365,7 +389,7 @@ declare abstract class CoreRouter {
365
389
  * @param handler
366
390
  * @param middlewares
367
391
  */
368
- static post(path: string, handler: any, middlewares?: any[] | any): void;
392
+ static post(path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
369
393
  /**
370
394
  * Adds a new PUT route to the router.
371
395
  *
@@ -374,7 +398,7 @@ declare abstract class CoreRouter {
374
398
  * @param handler
375
399
  * @param middlewares
376
400
  */
377
- static put(path: string, handler: any, middlewares?: any[] | any): void;
401
+ static put(path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
378
402
  /**
379
403
  * Adds a new DELETE route to the router.
380
404
  *
@@ -383,7 +407,7 @@ declare abstract class CoreRouter {
383
407
  * @param handler
384
408
  * @param middlewares
385
409
  */
386
- static delete(path: string, handler: any, middlewares?: any[] | any): void;
410
+ static delete(path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
387
411
  /**
388
412
  * Adds a new PATCH route to the router.
389
413
  *
@@ -392,7 +416,7 @@ declare abstract class CoreRouter {
392
416
  * @param handler
393
417
  * @param middlewares
394
418
  */
395
- static patch(path: string, handler: any, middlewares?: any[] | any): void;
419
+ static patch(path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
396
420
  /**
397
421
  * Adds a new OPTIONS route to the router.
398
422
  *
@@ -401,7 +425,7 @@ declare abstract class CoreRouter {
401
425
  * @param handler
402
426
  * @param middlewares
403
427
  */
404
- static options(path: string, handler: any, middlewares?: any[] | any): void;
428
+ static options(path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
405
429
  /**
406
430
  * Adds a new HEAD route to the router.
407
431
  *
@@ -410,7 +434,7 @@ declare abstract class CoreRouter {
410
434
  * @param handler
411
435
  * @param middlewares
412
436
  */
413
- static head(path: string, handler: any, middlewares?: any[] | any): void;
437
+ static head(path: string, handler: any, middlewares?: any[] | any): Route<any, any, any>;
414
438
  /**
415
439
  * Defines a group of routes with a common prefix.
416
440
  *
@@ -445,6 +469,9 @@ declare abstract class CoreRouter {
445
469
  * @param type - 'method' to get routes organized by method
446
470
  */
447
471
  static allRoutes(type: 'method'): { [method in Uppercase<HttpMethod>]?: Array<Route<any, any, any>> };
472
+ static allRoutes(type: 'name'): Record<string, Route<any, any, any>>;
473
+ static route(name: string): Route<any, any, any> | undefined;
474
+ static url(name: string, params?: Record<string, any>): string | undefined;
448
475
  protected static resolveHandler(route: Route<any, any, any>): {
449
476
  handlerFunction: ((ctx: any, req: Request$1) => any | Promise<any>) | null;
450
477
  instance: Controller<any> | null;
@@ -4,6 +4,11 @@ import { ClearRequest } from "./ClearRequest.mjs";
4
4
  import { Middleware as Middleware$1 } from "../types/express.mjs";
5
5
 
6
6
  //#region src/Route.d.ts
7
+ interface RouteParameter {
8
+ name: string;
9
+ field?: string;
10
+ optional: boolean;
11
+ }
7
12
  declare class Route<X = any, M = Middleware | Middleware$1, H = any> {
8
13
  ctx: X;
9
14
  body: RequestData;
@@ -12,13 +17,23 @@ declare class Route<X = any, M = Middleware | Middleware$1, H = any> {
12
17
  clearRequest: ClearRequest;
13
18
  methods: HttpMethod[];
14
19
  path: string;
20
+ registrationPaths: string[];
21
+ parameters: RouteParameter[];
22
+ routeName?: string;
15
23
  handler: H;
16
24
  middlewares: M[];
17
25
  controllerName?: string;
18
26
  actionName?: string;
19
27
  handlerType: 'function' | 'controller';
20
28
  middlewareCount: number;
21
- constructor(methods: HttpMethod[], path: string, handler: H, middlewares?: M[]);
29
+ constructor(methods: HttpMethod[], path: string, handler: H, middlewares?: M[], options?: {
30
+ registrationPaths?: string[];
31
+ parameters?: RouteParameter[];
32
+ onName?: (name: string, route: Route<X, M, H>, previousName?: string) => void;
33
+ });
34
+ private onName?;
35
+ name(name: string): this;
36
+ toPath(params?: RequestData): string;
22
37
  }
23
38
  //#endregion
24
39
  export { Route };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clear-router",
3
- "version": "2.5.13",
3
+ "version": "2.5.14",
4
4
  "description": "Laravel-style routing for Node.js with support for Express, H3, Fastify, Hono, and Koa, including CommonJS, ESM, and TypeScript support.",
5
5
  "keywords": [
6
6
  "h3",