@h3ravel/router 1.9.3 → 1.10.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/dist/index.cjs CHANGED
@@ -21,10 +21,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  }) : target, mod));
22
22
 
23
23
  //#endregion
24
- let node_fs_promises = require("node:fs/promises");
25
- node_fs_promises = __toESM(node_fs_promises);
26
24
  let __h3ravel_core = require("@h3ravel/core");
27
25
  __h3ravel_core = __toESM(__h3ravel_core);
26
+ let __h3ravel_shared = require("@h3ravel/shared");
27
+ __h3ravel_shared = __toESM(__h3ravel_shared);
28
+ let node_fs_promises = require("node:fs/promises");
29
+ node_fs_promises = __toESM(node_fs_promises);
28
30
  let __h3ravel_support = require("@h3ravel/support");
29
31
  __h3ravel_support = __toESM(__h3ravel_support);
30
32
  let node_path = require("node:path");
@@ -36,11 +38,86 @@ node_fs = __toESM(node_fs);
36
38
  require("reflect-metadata");
37
39
  let __h3ravel_http = require("@h3ravel/http");
38
40
  __h3ravel_http = __toESM(__h3ravel_http);
39
- let __h3ravel_shared = require("@h3ravel/shared");
40
- __h3ravel_shared = __toESM(__h3ravel_shared);
41
41
  let __h3ravel_database = require("@h3ravel/database");
42
42
  __h3ravel_database = __toESM(__h3ravel_database);
43
43
 
44
+ //#region src/Commands/RouteListCommand.ts
45
+ var RouteListCommand = class extends __h3ravel_core.ConsoleCommand {
46
+ /**
47
+ * The name and signature of the console command.
48
+ *
49
+ * @var string
50
+ */
51
+ signature = `#route:
52
+ {list : List all registered routes.
53
+ | {--json : Output the route list as JSON}
54
+ | {--r|reverse : Reverse the ordering of the routes}
55
+ }
56
+ `;
57
+ /**
58
+ * The console command description.
59
+ *
60
+ * @var string
61
+ */
62
+ description = "List all registered routes.";
63
+ /**
64
+ * Execute the console command.
65
+ */
66
+ async handle() {
67
+ console.log("");
68
+ const command = this.dictionary.baseCommand ?? this.dictionary.name;
69
+ await this[command]();
70
+ }
71
+ /**
72
+ * List all registered routes.
73
+ */
74
+ async list() {
75
+ [...this.app.make("routes")].sort((a, b) => {
76
+ if (a.path === "/" && b.path !== "/") return -1;
77
+ if (b.path === "/" && a.path !== "/") return 1;
78
+ return a.path.localeCompare(b.path);
79
+ }).forEach((route) => {
80
+ const path$1 = route.path === "/" ? route.path : __h3ravel_shared.Logger.log(route.path.slice(1).split("/").map((e) => [(e.includes(":") ? __h3ravel_shared.Logger.log("/", "white", false) : "") + e, e.startsWith(":") ? "yellow" : "white"]), "", false);
81
+ const method = (route.method.startsWith("/") ? route.method.slice(1) : route.method).toUpperCase();
82
+ const name = route.signature[1] ? [
83
+ route.name ?? "",
84
+ route.name ? "›" : "",
85
+ route.signature.join("@")
86
+ ].join(" ") : "";
87
+ const desc = __h3ravel_shared.Logger.describe(__h3ravel_shared.Logger.log(__h3ravel_shared.Logger.log(method + this.pair(method), this.color(method), false), "green", false), path$1, 15, false);
88
+ return __h3ravel_shared.Logger.twoColumnLog(desc.join(""), name);
89
+ });
90
+ }
91
+ /**
92
+ * Get the color
93
+ *
94
+ * @param method
95
+ * @returns
96
+ */
97
+ color(method) {
98
+ switch (method.toLowerCase()) {
99
+ case "get": return "blue";
100
+ case "head": return "gray";
101
+ case "delete": return "red";
102
+ default: return "yellow";
103
+ }
104
+ }
105
+ /**
106
+ * Get the alternate method
107
+ *
108
+ * @param method
109
+ * @returns
110
+ */
111
+ pair(method) {
112
+ switch (method.toLowerCase()) {
113
+ case "get": return "|HEAD";
114
+ case "put": return "|PATCH";
115
+ default: return "";
116
+ }
117
+ }
118
+ };
119
+
120
+ //#endregion
44
121
  //#region src/Helpers.ts
45
122
  var Helpers = class Helpers {
46
123
  /**
@@ -103,7 +180,6 @@ var AssetsServiceProvider = class extends __h3ravel_core.ServiceProvider {
103
180
  static priority = 996;
104
181
  register() {
105
182
  const app = this.app.make("router");
106
- this.app.make("config").get("filesystem");
107
183
  const publicPath = this.app.getPath("public");
108
184
  /**
109
185
  * Use a middleware to check if this request for for a file
@@ -183,7 +259,7 @@ var Router = class {
183
259
  * @param name
184
260
  * @param middleware
185
261
  */
186
- addRoute(method, path$1, handler, name, middleware = []) {
262
+ addRoute(method, path$1, handler, name, middleware = [], signature = ["", ""]) {
187
263
  /**
188
264
  * Join all defined route names to make a single route name
189
265
  */
@@ -197,9 +273,11 @@ var Router = class {
197
273
  method,
198
274
  path: fullPath,
199
275
  name,
200
- handler
276
+ handler,
277
+ signature
201
278
  });
202
279
  this.h3App[method](fullPath, this.resolveHandler(handler, middleware));
280
+ this.app.singleton("routes", () => this.routes);
203
281
  }
204
282
  /**
205
283
  * Resolves a route handler definition into an executable EventHandler.
@@ -284,7 +362,7 @@ var Router = class {
284
362
  get(path$1, definition, name, middleware = []) {
285
363
  const handler = Array.isArray(definition) ? definition[0] : definition;
286
364
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
287
- this.addRoute("get", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
365
+ this.addRoute("get", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
288
366
  return this;
289
367
  }
290
368
  /**
@@ -300,7 +378,7 @@ var Router = class {
300
378
  post(path$1, definition, name, middleware = []) {
301
379
  const handler = Array.isArray(definition) ? definition[0] : definition;
302
380
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
303
- this.addRoute("post", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
381
+ this.addRoute("post", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
304
382
  return this;
305
383
  }
306
384
  /**
@@ -316,7 +394,7 @@ var Router = class {
316
394
  put(path$1, definition, name, middleware = []) {
317
395
  const handler = Array.isArray(definition) ? definition[0] : definition;
318
396
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
319
- this.addRoute("put", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
397
+ this.addRoute("put", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
320
398
  return this;
321
399
  }
322
400
  /**
@@ -332,7 +410,7 @@ var Router = class {
332
410
  patch(path$1, definition, name, middleware = []) {
333
411
  const handler = Array.isArray(definition) ? definition[0] : definition;
334
412
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
335
- this.addRoute("patch", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
413
+ this.addRoute("patch", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
336
414
  return this;
337
415
  }
338
416
  /**
@@ -348,7 +426,7 @@ var Router = class {
348
426
  delete(path$1, definition, name, middleware = []) {
349
427
  const handler = Array.isArray(definition) ? definition[0] : definition;
350
428
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
351
- this.addRoute("delete", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
429
+ this.addRoute("delete", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
352
430
  return this;
353
431
  }
354
432
  /**
@@ -446,6 +524,7 @@ var RouteServiceProvider = class extends __h3ravel_core.ServiceProvider {
446
524
  const h3App = this.app.make("http.app");
447
525
  return new Router(h3App, this.app);
448
526
  });
527
+ this.commands([RouteListCommand]);
449
528
  }
450
529
  /**
451
530
  * Load routes from src/routes
@@ -472,6 +551,7 @@ var RouteServiceProvider = class extends __h3ravel_core.ServiceProvider {
472
551
  //#endregion
473
552
  exports.AssetsServiceProvider = AssetsServiceProvider;
474
553
  exports.Helpers = Helpers;
554
+ exports.RouteListCommand = RouteListCommand;
475
555
  exports.RouteServiceProvider = RouteServiceProvider;
476
556
  exports.Router = Router;
477
557
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["params: string[]","match: RegExpExecArray | null","path","ServiceProvider","h3App: H3","app: Application","Kernel","HttpContext","Request","Response","path","controller: IController","Container","paramTypes: []","Model","ServiceProvider","path"],"sources":["../src/Helpers.ts","../src/Providers/AssetsServiceProvider.ts","../src/Route.ts","../src/Providers/RouteServiceProvider.ts"],"sourcesContent":["import { HttpContext } from '@h3ravel/shared'\nimport { Model } from '@h3ravel/database'\n\nexport class Helpers {\n /**\n * Extracts parameter names from a route path string.\n *\n * - Looks for segments prefixed with \":\" (e.g. \"/users/:id\")\n * - Captures only the param name (without the \":\")\n * - Returns all matches in order of appearance\n *\n * @param path - The route path string (e.g. \"/groups/:group/users/:user\")\n * @returns An array of parameter names (e.g. [\"group\", \"user\"])\n */\n static extractParams (path: string): string[] {\n const regex = /:([^/]+)/g\n const params: string[] = []\n let match: RegExpExecArray | null\n\n while ((match = regex.exec(path)) !== null) {\n params.push(match[1])\n }\n\n return params\n }\n\n /**\n * Resolves route model binding for a given path, HTTP context, and model.\n * \n * - Extracts all route parameters from the given path\n * - If a parameter matches the model name, it attempts to resolve the model binding\n * using the provided value and binding field (defaults to \"id\" unless specified).\n * - For non-matching parameters, it simply returns the key-value pair as is.\n * - If no parameters are found, returns an empty object.\n *\n * @param path - The route path (e.g. \"/groups/:group/users/:user\")\n * @param ctx - The HTTP context containing the request\n * @param model - The model instance to resolve bindings against\n * @returns A resolved model instance or an object containing param values\n */\n static async resolveRouteModelBinding (path: string, ctx: HttpContext, model: Model): Promise<any> {\n const name = model.constructor.name.toLowerCase()\n /**\n * Extract field (defaults to 'id' if not specified after '|')\n */\n const field = name.split('|').at(1) ?? 'id'\n\n /**\n * Iterate through extracted parameters from the path\n */\n for await (const e of Helpers.extractParams(path)) {\n const value = ctx.request.params[e] ?? null\n if (e === name) return await model.resolveRouteBinding(value, field)\n else return { [e]: ctx.request.params[e] ?? {} }\n }\n\n return {}\n }\n}\n","import { readFile, stat } from 'node:fs/promises'\n\nimport { ServiceProvider } from '@h3ravel/core'\nimport { before } from '@h3ravel/support'\nimport { join } from 'node:path'\nimport { serveStatic } from 'h3'\nimport { statSync } from 'node:fs'\n\n/**\n * Handles public assets loading\n * \n * Auto-Registered\n */\nexport class AssetsServiceProvider extends ServiceProvider {\n public static priority = 996\n\n register () {\n const app = this.app.make('router')\n const config = this.app.make('config')\n const fsconfig = config.get('filesystem')\n const publicPath = this.app.getPath('public')\n\n /**\n * Use a middleware to check if this request for for a file\n */\n app.middleware((event) => {\n const { pathname } = new URL(event.req.url)\n\n /**\n * Only serve if it looks like a static asset (has an extension)\n * but skip dotfiles or sensitive files\n */\n if (!/\\.[a-zA-Z0-9]+$/.test(pathname)) return\n if (pathname.startsWith('/.') || pathname.includes('..')) return\n\n /**\n * Serve the asset\n */\n return serveStatic(event, {\n indexNames: ['/index.html'],\n getContents: (id) => {\n return <never>readFile(join(before(publicPath, id), id))\n },\n getMeta: async (id) => {\n const stats = await stat(join(before(publicPath, id), id)).catch(() => { })\n if (stats?.isFile()) {\n return {\n size: stats.size,\n mtime: stats.mtimeMs,\n }\n }\n },\n })\n })\n\n this.app.singleton('asset', () => {\n return (key: string, def?: string) => {\n if (def) {\n try {\n statSync(join(before(publicPath, key), key))\n } catch {\n key = def\n }\n }\n\n return key\n }\n })\n }\n}\n","import 'reflect-metadata'\nimport { H3Event, Middleware, MiddlewareOptions, type H3 } from 'h3'\nimport { Application, Container, Kernel } from '@h3ravel/core'\nimport { Request, Response } from '@h3ravel/http'\nimport { singularize } from '@h3ravel/support'\nimport { HttpContext, RouteEventHandler } from '@h3ravel/shared'\nimport type { EventHandler, IController, IMiddleware, IRouter, RouterEnd } from '@h3ravel/shared'\nimport { Helpers } from './Helpers'\nimport { Model } from '@h3ravel/database'\n\ninterface RouteDefinition {\n method: string\n path: string\n name?: string\n handler: EventHandler\n}\n\nexport class Router implements IRouter {\n private routes: RouteDefinition[] = []\n private nameMap: string[] = []\n private groupPrefix = ''\n private middlewareMap: IMiddleware[] = []\n private groupMiddleware: EventHandler[] = []\n\n constructor(protected h3App: H3, private app: Application) { }\n\n /**\n * Route Resolver\n * \n * @param handler \n * @param middleware \n * @returns \n */\n private resolveHandler (handler: EventHandler, middleware: IMiddleware[] = []) {\n return async (event: H3Event) => {\n const kernel = new Kernel(() => HttpContext.init({\n app: this.app,\n request: new Request(event, this.app),\n response: new Response(event, this.app)\n }), middleware)\n\n return kernel.handle(event, (ctx) => Promise.resolve(handler(ctx)))\n }\n }\n\n /**\n * Add a route to the stack\n * \n * @param method \n * @param path \n * @param handler \n * @param name \n * @param middleware \n */\n private addRoute (\n method: string,\n path: string,\n handler: EventHandler,\n name?: string,\n middleware: IMiddleware[] = []\n ) {\n /**\n * Join all defined route names to make a single route name\n */\n if (this.nameMap.length > 0) {\n name = this.nameMap.join('.')\n }\n\n /**\n * Join all defined middlewares\n */\n if (this.middlewareMap.length > 0) {\n middleware = this.middlewareMap\n }\n\n const fullPath = `${this.groupPrefix}${path}`.replace(/\\/+/g, '/')\n this.routes.push({ method, path: fullPath, name, handler })\n this.h3App[method as 'get'](fullPath, this.resolveHandler(handler, middleware))\n }\n\n /**\n * Resolves a route handler definition into an executable EventHandler.\n *\n * A handler can be:\n * - A function matching the EventHandler signature\n * - A controller class (optionally decorated for IoC resolution)\n *\n * If it’s a controller class, this method will:\n * - Instantiate it (via IoC or manually)\n * - Call the specified method (defaults to `index`)\n *\n * @param handler Event handler function OR controller class\n * @param methodName Method to invoke on the controller (defaults to 'index')\n */\n private resolveControllerOrHandler (\n handler: EventHandler | (new (...args: any[]) => Record<string, any>),\n methodName?: string,\n path?: string,\n ): EventHandler {\n /**\n * Checks if the handler is a function (either a plain function or a class constructor)\n */\n if (typeof handler === 'function' && typeof (handler as any).prototype !== 'undefined') {\n return async (ctx) => {\n let controller: IController\n if (Container.hasAnyDecorator(handler as any)) {\n /**\n * If the controller is decorated use the IoC container\n */\n controller = this.app.make<any, IController>(handler as any)\n } else {\n /**\n * Otherwise instantiate manually so that we can at least\n * pass the app instance\n */\n controller = new (handler as new (...args: any[]) => IController)(this.app)\n }\n\n /**\n * The method to execute (defaults to 'index')\n */\n const action = (methodName || 'index') as keyof IController\n\n /**\n * Ensure the method exists on the controller\n */\n if (typeof controller[action] !== 'function') {\n throw new Error(`Method \"${String(action)}\" not found on controller ${handler.name}`)\n }\n\n /**\n * Get param types for the controller method\n */\n const paramTypes: [] = Reflect.getMetadata('design:paramtypes', controller, action) || []\n\n /**\n * Resolve the bound dependencies\n */\n let args = await Promise.all(\n paramTypes.map(async (paramType: any) => {\n switch (paramType?.name) {\n case 'Application':\n return this.app\n case 'Request':\n return ctx.request\n case 'Response':\n return ctx.response\n case 'HttpContext':\n return ctx\n default: {\n const inst = this.app.make(paramType)\n if (inst instanceof Model) {\n // Route model binding returns a Promise\n return await Helpers.resolveRouteModelBinding(path ?? '', ctx, inst)\n }\n return inst\n }\n }\n })\n )\n\n /**\n * Ensure that the HttpContext is always available\n */\n if (args.length < 1) {\n args = [ctx]\n }\n\n /**\n * Call the controller method, passing all resolved dependencies\n */\n return await controller[action](...args)\n }\n }\n\n return handler as EventHandler\n }\n\n /**\n * Registers a route that responds to HTTP GET requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n get (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n\n this.addRoute('get', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP POST requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n post (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('post', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PUT requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n put (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('put', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PATCH requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n patch (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('patch', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP DELETE requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n delete (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('delete', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * API Resource support \n * \n * @param path \n * @param controller \n */\n apiResource (\n path: string,\n Controller: new (app: Application) => IController,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd | 'name'> {\n path = path.replace(/\\//g, '/')\n\n const basePath = `/${path}`.replace(/\\/+$/, '').replace(/(\\/)+/g, '$1')\n const name = basePath.substring(basePath.lastIndexOf('/') + 1).replaceAll(/\\/|:/g, '') || ''\n const param = singularize(name)\n\n this.get(basePath, [Controller, 'index'], `${name}.index`, middleware)\n this.post(basePath, [Controller, 'store'], `${name}.store`, middleware)\n this.get(`${basePath}/:${param}`, [Controller, 'show'], `${name}.show`, middleware)\n this.put(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.patch(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.delete(`${basePath}/:${param}`, [Controller, 'destroy'], `${name}.destroy`, middleware)\n\n return this\n }\n\n /**\n * Named route URL generator\n * \n * @param name \n * @param params \n * @returns \n */\n route (name: string, params: Record<string, string> = {}): string | undefined {\n const found = this.routes.find(r => r.name === name)\n if (!found) return undefined\n\n let url = found.path\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`:${key}`, value)\n }\n return url\n }\n\n /**\n * Grouping\n * \n * @param options \n * @param callback \n */\n group (options: { prefix?: string; middleware?: EventHandler[] }, callback: (_e: this) => void) {\n const prevPrefix = this.groupPrefix\n const prevMiddleware = [...this.groupMiddleware]\n\n this.groupPrefix += options.prefix || ''\n this.groupMiddleware.push(...(options.middleware || []))\n\n callback(this)\n\n /**\n * Restore state after group\n */\n this.groupPrefix = prevPrefix\n this.groupMiddleware = prevMiddleware\n return this\n }\n\n /**\n * Set the name of the current route\n * \n * @param name \n */\n name (name: string) {\n this.nameMap.push(name)\n return this\n }\n\n /**\n * Registers middleware for a specific path.\n * @param path - The path to apply the middleware.\n * @param handler - The middleware handler.\n * @param opts - Optional middleware options.\n */\n middleware (path: string | IMiddleware[] | Middleware, handler: Middleware | MiddlewareOptions, opts?: MiddlewareOptions) {\n opts = typeof handler === 'object' ? handler : (typeof opts === 'function' ? opts : {})\n handler = typeof path === 'function' ? path : (typeof handler === 'function' ? handler : () => { })\n\n if (Array.isArray(path)) {\n this.middlewareMap.concat(path)\n } else if (typeof path === 'function') {\n this.h3App.use('/', () => { }).use(path)\n } else {\n this.h3App.use(path, handler, opts)\n }\n\n return this\n }\n}\n","import { Router } from '../Route'\nimport { ServiceProvider } from '@h3ravel/core'\nimport path from 'node:path'\nimport { readdir } from 'node:fs/promises'\n\n/**\n * Handles routing registration\n * \n * Load route files (web.ts, api.ts).\n * Map controllers to routes.\n * Register route-related middleware.\n * \n * Auto-Registered\n */\nexport class RouteServiceProvider extends ServiceProvider {\n public static priority = 997\n\n register () {\n this.app.singleton('router', () => {\n const h3App = this.app.make('http.app')\n return new Router(h3App, this.app)\n })\n }\n\n /**\n * Load routes from src/routes\n */\n async boot () {\n try {\n const routePath = this.app.getPath('routes')\n\n const files = (await readdir(routePath)).filter((e) => {\n return !e.includes('.d.ts') && !e.includes('.d.cts') && !e.includes('.map')\n })\n\n for (let i = 0; i < files.length; i++) {\n const routesModule = await import(path.join(routePath, files[i]))\n\n if (typeof routesModule.default === 'function') {\n const router = this.app.make('router')\n routesModule.default(router)\n }\n }\n } catch (e) {\n console.warn('No web routes found or failed to load:', e)\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,IAAa,UAAb,MAAa,QAAQ;;;;;;;;;;;CAWjB,OAAO,cAAe,QAAwB;EAC1C,MAAM,QAAQ;EACd,MAAMA,SAAmB,EAAE;EAC3B,IAAIC;AAEJ,UAAQ,QAAQ,MAAM,KAAKC,OAAK,MAAM,KAClC,QAAO,KAAK,MAAM,GAAG;AAGzB,SAAO;;;;;;;;;;;;;;;;CAiBX,aAAa,yBAA0B,QAAc,KAAkB,OAA4B;EAC/F,MAAM,OAAO,MAAM,YAAY,KAAK,aAAa;;;;EAIjD,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI;;;;AAKvC,aAAW,MAAM,KAAK,QAAQ,cAAcA,OAAK,EAAE;GAC/C,MAAM,QAAQ,IAAI,QAAQ,OAAO,MAAM;AACvC,OAAI,MAAM,KAAM,QAAO,MAAM,MAAM,oBAAoB,OAAO,MAAM;OAC/D,QAAO,GAAG,IAAI,IAAI,QAAQ,OAAO,MAAM,EAAE,EAAE;;AAGpD,SAAO,EAAE;;;;;;;;;;;AC3CjB,IAAa,wBAAb,cAA2CC,+BAAgB;CACvD,OAAc,WAAW;CAEzB,WAAY;EACR,MAAM,MAAM,KAAK,IAAI,KAAK,SAAS;AAElB,EADF,KAAK,IAAI,KAAK,SAAS,CACd,IAAI,aAAa;EACzC,MAAM,aAAa,KAAK,IAAI,QAAQ,SAAS;;;;AAK7C,MAAI,YAAY,UAAU;GACtB,MAAM,EAAE,aAAa,IAAI,IAAI,MAAM,IAAI,IAAI;;;;;AAM3C,OAAI,CAAC,kBAAkB,KAAK,SAAS,CAAE;AACvC,OAAI,SAAS,WAAW,KAAK,IAAI,SAAS,SAAS,KAAK,CAAE;;;;AAK1D,8BAAmB,OAAO;IACtB,YAAY,CAAC,cAAc;IAC3B,cAAc,OAAO;AACjB,6FAAmC,YAAY,GAAG,EAAE,GAAG,CAAC;;IAE5D,SAAS,OAAO,OAAO;KACnB,MAAM,QAAQ,mFAAuB,YAAY,GAAG,EAAE,GAAG,CAAC,CAAC,YAAY,GAAI;AAC3E,SAAI,OAAO,QAAQ,CACf,QAAO;MACH,MAAM,MAAM;MACZ,OAAO,MAAM;MAChB;;IAGZ,CAAC;IACJ;AAEF,OAAK,IAAI,UAAU,eAAe;AAC9B,WAAQ,KAAa,QAAiB;AAClC,QAAI,IACA,KAAI;AACA,6EAAqB,YAAY,IAAI,EAAE,IAAI,CAAC;YACxC;AACJ,WAAM;;AAId,WAAO;;IAEb;;;;;;AClDV,IAAa,SAAb,MAAuC;CACnC,AAAQ,SAA4B,EAAE;CACtC,AAAQ,UAAoB,EAAE;CAC9B,AAAQ,cAAc;CACtB,AAAQ,gBAA+B,EAAE;CACzC,AAAQ,kBAAkC,EAAE;CAE5C,YAAY,AAAUC,OAAW,AAAQC,KAAkB;EAArC;EAAmB;;;;;;;;;CASzC,AAAQ,eAAgB,SAAuB,aAA4B,EAAE,EAAE;AAC3E,SAAO,OAAO,UAAmB;AAO7B,UANe,IAAIC,4BAAaC,6BAAY,KAAK;IAC7C,KAAK,KAAK;IACV,SAAS,IAAIC,uBAAQ,OAAO,KAAK,IAAI;IACrC,UAAU,IAAIC,wBAAS,OAAO,KAAK,IAAI;IAC1C,CAAC,EAAE,WAAW,CAED,OAAO,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,IAAI,CAAC,CAAC;;;;;;;;;;;;CAa3E,AAAQ,SACJ,QACA,QACA,SACA,MACA,aAA4B,EAAE,EAChC;;;;AAIE,MAAI,KAAK,QAAQ,SAAS,EACtB,QAAO,KAAK,QAAQ,KAAK,IAAI;;;;AAMjC,MAAI,KAAK,cAAc,SAAS,EAC5B,cAAa,KAAK;EAGtB,MAAM,WAAW,GAAG,KAAK,cAAcC,SAAO,QAAQ,QAAQ,IAAI;AAClE,OAAK,OAAO,KAAK;GAAE;GAAQ,MAAM;GAAU;GAAM;GAAS,CAAC;AAC3D,OAAK,MAAM,QAAiB,UAAU,KAAK,eAAe,SAAS,WAAW,CAAC;;;;;;;;;;;;;;;;CAiBnF,AAAQ,2BACJ,SACA,YACA,QACY;;;;AAIZ,MAAI,OAAO,YAAY,cAAc,OAAQ,QAAgB,cAAc,YACvE,QAAO,OAAO,QAAQ;GAClB,IAAIC;AACJ,OAAIC,yBAAU,gBAAgB,QAAe;;;;AAIzC,gBAAa,KAAK,IAAI,KAAuB,QAAe;;;;;;AAM5D,gBAAa,IAAK,QAAgD,KAAK,IAAI;;;;GAM/E,MAAM,SAAU,cAAc;;;;AAK9B,OAAI,OAAO,WAAW,YAAY,WAC9B,OAAM,IAAI,MAAM,WAAW,OAAO,OAAO,CAAC,4BAA4B,QAAQ,OAAO;;;;GAMzF,MAAMC,aAAiB,QAAQ,YAAY,qBAAqB,YAAY,OAAO,IAAI,EAAE;;;;GAKzF,IAAI,OAAO,MAAM,QAAQ,IACrB,WAAW,IAAI,OAAO,cAAmB;AACrC,YAAQ,WAAW,MAAnB;KACI,KAAK,cACD,QAAO,KAAK;KAChB,KAAK,UACD,QAAO,IAAI;KACf,KAAK,WACD,QAAO,IAAI;KACf,KAAK,cACD,QAAO;KACX,SAAS;MACL,MAAM,OAAO,KAAK,IAAI,KAAK,UAAU;AACrC,UAAI,gBAAgBC,yBAEhB,QAAO,MAAM,QAAQ,yBAAyBJ,UAAQ,IAAI,KAAK,KAAK;AAExE,aAAO;;;KAGjB,CACL;;;;AAKD,OAAI,KAAK,SAAS,EACd,QAAO,CAAC,IAAI;;;;AAMhB,UAAO,MAAM,WAAW,QAAQ,GAAG,KAAK;;AAIhD,SAAO;;;;;;;;;;;;CAaX,IACI,QACA,YACA,MACA,aAA4B,EAAE,EACT;EACrB,MAAM,UAAU,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;EAC5D,MAAM,aAAa,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;AAE/D,OAAK,SAAS,OAAOA,QAAM,KAAK,2BAA2B,SAAS,YAAYA,OAAK,EAAE,MAAM,WAAW;AACxG,SAAO;;;;;;;;;;;;CAaX,KACI,QACA,YACA,MACA,aAA4B,EAAE,EACT;EACrB,MAAM,UAAU,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;EAC5D,MAAM,aAAa,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;AAC/D,OAAK,SAAS,QAAQA,QAAM,KAAK,2BAA2B,SAAS,YAAYA,OAAK,EAAE,MAAM,WAAW;AACzG,SAAO;;;;;;;;;;;;CAaX,IACI,QACA,YACA,MACA,aAA4B,EAAE,EACT;EACrB,MAAM,UAAU,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;EAC5D,MAAM,aAAa,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;AAC/D,OAAK,SAAS,OAAOA,QAAM,KAAK,2BAA2B,SAAS,YAAYA,OAAK,EAAE,MAAM,WAAW;AACxG,SAAO;;;;;;;;;;;;CAaX,MACI,QACA,YACA,MACA,aAA4B,EAAE,EACT;EACrB,MAAM,UAAU,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;EAC5D,MAAM,aAAa,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;AAC/D,OAAK,SAAS,SAASA,QAAM,KAAK,2BAA2B,SAAS,YAAYA,OAAK,EAAE,MAAM,WAAW;AAC1G,SAAO;;;;;;;;;;;;CAaX,OACI,QACA,YACA,MACA,aAA4B,EAAE,EACT;EACrB,MAAM,UAAU,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;EAC5D,MAAM,aAAa,MAAM,QAAQ,WAAW,GAAG,WAAW,KAAK;AAC/D,OAAK,SAAS,UAAUA,QAAM,KAAK,2BAA2B,SAAS,YAAYA,OAAK,EAAE,MAAM,WAAW;AAC3G,SAAO;;;;;;;;CASX,YACI,QACA,YACA,aAA4B,EAAE,EACA;AAC9B,WAAOA,OAAK,QAAQ,OAAO,IAAI;EAE/B,MAAM,WAAW,IAAIA,SAAO,QAAQ,QAAQ,GAAG,CAAC,QAAQ,UAAU,KAAK;EACvE,MAAM,OAAO,SAAS,UAAU,SAAS,YAAY,IAAI,GAAG,EAAE,CAAC,WAAW,SAAS,GAAG,IAAI;EAC1F,MAAM,2CAAoB,KAAK;AAE/B,OAAK,IAAI,UAAU,CAAC,YAAY,QAAQ,EAAE,GAAG,KAAK,SAAS,WAAW;AACtE,OAAK,KAAK,UAAU,CAAC,YAAY,QAAQ,EAAE,GAAG,KAAK,SAAS,WAAW;AACvE,OAAK,IAAI,GAAG,SAAS,IAAI,SAAS,CAAC,YAAY,OAAO,EAAE,GAAG,KAAK,QAAQ,WAAW;AACnF,OAAK,IAAI,GAAG,SAAS,IAAI,SAAS,CAAC,YAAY,SAAS,EAAE,GAAG,KAAK,UAAU,WAAW;AACvF,OAAK,MAAM,GAAG,SAAS,IAAI,SAAS,CAAC,YAAY,SAAS,EAAE,GAAG,KAAK,UAAU,WAAW;AACzF,OAAK,OAAO,GAAG,SAAS,IAAI,SAAS,CAAC,YAAY,UAAU,EAAE,GAAG,KAAK,WAAW,WAAW;AAE5F,SAAO;;;;;;;;;CAUX,MAAO,MAAc,SAAiC,EAAE,EAAsB;EAC1E,MAAM,QAAQ,KAAK,OAAO,MAAK,MAAK,EAAE,SAAS,KAAK;AACpD,MAAI,CAAC,MAAO,QAAO;EAEnB,IAAI,MAAM,MAAM;AAChB,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC7C,OAAM,IAAI,QAAQ,IAAI,OAAO,MAAM;AAEvC,SAAO;;;;;;;;CASX,MAAO,SAA2D,UAA8B;EAC5F,MAAM,aAAa,KAAK;EACxB,MAAM,iBAAiB,CAAC,GAAG,KAAK,gBAAgB;AAEhD,OAAK,eAAe,QAAQ,UAAU;AACtC,OAAK,gBAAgB,KAAK,GAAI,QAAQ,cAAc,EAAE,CAAE;AAExD,WAAS,KAAK;;;;AAKd,OAAK,cAAc;AACnB,OAAK,kBAAkB;AACvB,SAAO;;;;;;;CAQX,KAAM,MAAc;AAChB,OAAK,QAAQ,KAAK,KAAK;AACvB,SAAO;;;;;;;;CASX,WAAY,QAA2C,SAAyC,MAA0B;AACtH,SAAO,OAAO,YAAY,WAAW,UAAW,OAAO,SAAS,aAAa,OAAO,EAAE;AACtF,YAAU,OAAOA,WAAS,aAAaA,SAAQ,OAAO,YAAY,aAAa,gBAAgB;AAE/F,MAAI,MAAM,QAAQA,OAAK,CACnB,MAAK,cAAc,OAAOA,OAAK;WACxB,OAAOA,WAAS,WACvB,MAAK,MAAM,IAAI,WAAW,GAAI,CAAC,IAAIA,OAAK;MAExC,MAAK,MAAM,IAAIA,QAAM,SAAS,KAAK;AAGvC,SAAO;;;;;;;;;;;;;;;ACnXf,IAAa,uBAAb,cAA0CK,+BAAgB;CACtD,OAAc,WAAW;CAEzB,WAAY;AACR,OAAK,IAAI,UAAU,gBAAgB;GAC/B,MAAM,QAAQ,KAAK,IAAI,KAAK,WAAW;AACvC,UAAO,IAAI,OAAO,OAAO,KAAK,IAAI;IACpC;;;;;CAMN,MAAM,OAAQ;AACV,MAAI;GACA,MAAM,YAAY,KAAK,IAAI,QAAQ,SAAS;GAE5C,MAAM,SAAS,oCAAc,UAAU,EAAE,QAAQ,MAAM;AACnD,WAAO,CAAC,EAAE,SAAS,QAAQ,IAAI,CAAC,EAAE,SAAS,SAAS,IAAI,CAAC,EAAE,SAAS,OAAO;KAC7E;AAEF,QAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACnC,MAAM,eAAe,MAAM,OAAOC,kBAAK,KAAK,WAAW,MAAM,GAAG;AAEhE,QAAI,OAAO,aAAa,YAAY,YAAY;KAC5C,MAAM,SAAS,KAAK,IAAI,KAAK,SAAS;AACtC,kBAAa,QAAQ,OAAO;;;WAG/B,GAAG;AACR,WAAQ,KAAK,0CAA0C,EAAE"}
1
+ {"version":3,"file":"index.cjs","names":["ConsoleCommand","path","Logger","params: string[]","match: RegExpExecArray | null","path","ServiceProvider","h3App: H3","app: Application","Kernel","HttpContext","Request","Response","path","controller: IController","Container","paramTypes: []","Model","ServiceProvider","path"],"sources":["../src/Commands/RouteListCommand.ts","../src/Helpers.ts","../src/Providers/AssetsServiceProvider.ts","../src/Route.ts","../src/Providers/RouteServiceProvider.ts"],"sourcesContent":["import { RouteDefinition, RouteMethod } from '../Contracts/Router'\n\nimport { ConsoleCommand } from '@h3ravel/core'\nimport { Logger } from '@h3ravel/shared'\nimport { LoggerChalk } from '@/packages/shared/dist'\n\nexport class RouteListCommand extends ConsoleCommand {\n\n /**\n * The name and signature of the console command.\n *\n * @var string\n */\n protected signature: string = `#route:\n {list : List all registered routes. \n | {--json : Output the route list as JSON}\n | {--r|reverse : Reverse the ordering of the routes}\n }\n `\n\n /**\n * The console command description.\n *\n * @var string\n */\n protected description: string = 'List all registered routes.'\n\n /**\n * Execute the console command.\n */\n public async handle (this: any) {\n console.log('')\n const command = (this.dictionary.baseCommand ?? this.dictionary.name)\n\n await this[command]()\n }\n\n /**\n * List all registered routes.\n */\n protected async list () {\n const list = [...(this.app.make<any>('routes') as RouteDefinition[])].sort((a, b) => {\n if (a.path === '/' && b.path !== '/') return -1\n if (b.path === '/' && a.path !== '/') return 1\n return a.path.localeCompare(b.path)\n })\n\n\n list.forEach(route => {\n const path = route.path === '/'\n ? route.path\n : Logger.log((route.path.slice(1)).split('/').map(e => [\n (e.includes(':') ? Logger.log('/', 'white', false) : '') + e,\n e.startsWith(':') ? 'yellow' : 'white'\n ] as [string, LoggerChalk]), '', false)\n\n const method = (route.method.startsWith('/') ? route.method.slice(1) : route.method).toUpperCase() as RouteMethod\n const name = route.signature[1] ? [route.name ?? '', route.name ? '›' : '', route.signature.join('@')].join(' ') : ''\n\n const desc = Logger.describe(\n Logger.log(Logger.log(method + this.pair(method), this.color(method), false), 'green', false), path, 15, false\n )\n return Logger.twoColumnLog(desc.join(''), name)\n })\n }\n\n /**\n * Get the color\n * \n * @param method \n * @returns \n */\n private color (method: RouteMethod): LoggerChalk {\n switch (method.toLowerCase()) {\n case 'get':\n return 'blue'\n case 'head':\n return 'gray'\n case 'delete':\n return 'red'\n default:\n return 'yellow'\n }\n }\n\n /**\n * Get the alternate method\n * \n * @param method \n * @returns \n */\n private pair (method: RouteMethod) {\n switch (method.toLowerCase()) {\n case 'get':\n return '|HEAD'\n case 'put':\n return '|PATCH'\n default:\n return ''\n }\n }\n}\n","import { HttpContext } from '@h3ravel/shared'\nimport { Model } from '@h3ravel/database'\n\nexport class Helpers {\n /**\n * Extracts parameter names from a route path string.\n *\n * - Looks for segments prefixed with \":\" (e.g. \"/users/:id\")\n * - Captures only the param name (without the \":\")\n * - Returns all matches in order of appearance\n *\n * @param path - The route path string (e.g. \"/groups/:group/users/:user\")\n * @returns An array of parameter names (e.g. [\"group\", \"user\"])\n */\n static extractParams (path: string): string[] {\n const regex = /:([^/]+)/g\n const params: string[] = []\n let match: RegExpExecArray | null\n\n while ((match = regex.exec(path)) !== null) {\n params.push(match[1])\n }\n\n return params\n }\n\n /**\n * Resolves route model binding for a given path, HTTP context, and model.\n * \n * - Extracts all route parameters from the given path\n * - If a parameter matches the model name, it attempts to resolve the model binding\n * using the provided value and binding field (defaults to \"id\" unless specified).\n * - For non-matching parameters, it simply returns the key-value pair as is.\n * - If no parameters are found, returns an empty object.\n *\n * @param path - The route path (e.g. \"/groups/:group/users/:user\")\n * @param ctx - The HTTP context containing the request\n * @param model - The model instance to resolve bindings against\n * @returns A resolved model instance or an object containing param values\n */\n static async resolveRouteModelBinding (path: string, ctx: HttpContext, model: Model): Promise<any> {\n const name = model.constructor.name.toLowerCase()\n /**\n * Extract field (defaults to 'id' if not specified after '|')\n */\n const field = name.split('|').at(1) ?? 'id'\n\n /**\n * Iterate through extracted parameters from the path\n */\n for await (const e of Helpers.extractParams(path)) {\n const value = ctx.request.params[e] ?? null\n if (e === name) return await model.resolveRouteBinding(value, field)\n else return { [e]: ctx.request.params[e] ?? {} }\n }\n\n return {}\n }\n}\n","import { readFile, stat } from 'node:fs/promises'\n\nimport { ServiceProvider } from '@h3ravel/core'\nimport { before } from '@h3ravel/support'\nimport { join } from 'node:path'\nimport { serveStatic } from 'h3'\nimport { statSync } from 'node:fs'\n\n/**\n * Handles public assets loading\n * \n * Auto-Registered\n */\nexport class AssetsServiceProvider extends ServiceProvider {\n public static priority = 996\n\n register () {\n const app = this.app.make('router')\n const publicPath = this.app.getPath('public')\n\n /**\n * Use a middleware to check if this request for for a file\n */\n app.middleware((event) => {\n const { pathname } = new URL(event.req.url)\n\n /**\n * Only serve if it looks like a static asset (has an extension)\n * but skip dotfiles or sensitive files\n */\n if (!/\\.[a-zA-Z0-9]+$/.test(pathname)) return\n if (pathname.startsWith('/.') || pathname.includes('..')) return\n\n /**\n * Serve the asset\n */\n return serveStatic(event, {\n indexNames: ['/index.html'],\n getContents: (id) => {\n return <never>readFile(join(before(publicPath, id), id))\n },\n getMeta: async (id) => {\n const stats = await stat(join(before(publicPath, id), id)).catch(() => { })\n if (stats?.isFile()) {\n return {\n size: stats.size,\n mtime: stats.mtimeMs,\n }\n }\n },\n })\n })\n\n this.app.singleton('asset', () => {\n return (key: string, def?: string) => {\n if (def) {\n try {\n statSync(join(before(publicPath, key), key))\n } catch {\n key = def\n }\n }\n\n return key\n }\n })\n }\n}\n","import 'reflect-metadata'\nimport { H3Event, Middleware, MiddlewareOptions, type H3 } from 'h3'\nimport { Application, Container, Kernel } from '@h3ravel/core'\nimport { Request, Response } from '@h3ravel/http'\nimport { singularize } from '@h3ravel/support'\nimport { HttpContext, RouteEventHandler } from '@h3ravel/shared'\nimport type { EventHandler, IController, IMiddleware, IRouter, RouterEnd } from '@h3ravel/shared'\nimport { Helpers } from './Helpers'\nimport { Model } from '@h3ravel/database'\nimport { RouteDefinition, RouteMethod } from './Contracts/Router'\n\nexport class Router implements IRouter {\n private routes: RouteDefinition[] = []\n private nameMap: string[] = []\n private groupPrefix = ''\n private middlewareMap: IMiddleware[] = []\n private groupMiddleware: EventHandler[] = []\n\n constructor(protected h3App: H3, private app: Application) { }\n\n /**\n * Route Resolver\n * \n * @param handler \n * @param middleware \n * @returns \n */\n private resolveHandler (handler: EventHandler, middleware: IMiddleware[] = []) {\n return async (event: H3Event) => {\n const kernel = new Kernel(() => HttpContext.init({\n app: this.app,\n request: new Request(event, this.app),\n response: new Response(event, this.app)\n }), middleware)\n\n return kernel.handle(event, (ctx) => Promise.resolve(handler(ctx)))\n }\n }\n\n /**\n * Add a route to the stack\n * \n * @param method \n * @param path \n * @param handler \n * @param name \n * @param middleware \n */\n private addRoute (\n method: RouteMethod,\n path: string,\n handler: EventHandler,\n name?: string,\n middleware: IMiddleware[] = [],\n signature: RouteDefinition['signature'] = ['', '']\n ) {\n /**\n * Join all defined route names to make a single route name\n */\n if (this.nameMap.length > 0) {\n name = this.nameMap.join('.')\n }\n\n /**\n * Join all defined middlewares\n */\n if (this.middlewareMap.length > 0) {\n middleware = this.middlewareMap\n }\n\n const fullPath = `${this.groupPrefix}${path}`.replace(/\\/+/g, '/')\n this.routes.push({ method, path: fullPath, name, handler, signature })\n this.h3App[method as 'get'](fullPath, this.resolveHandler(handler, middleware))\n this.app.singleton<any>('routes', () => this.routes)\n }\n\n /**\n * Resolves a route handler definition into an executable EventHandler.\n *\n * A handler can be:\n * - A function matching the EventHandler signature\n * - A controller class (optionally decorated for IoC resolution)\n *\n * If it’s a controller class, this method will:\n * - Instantiate it (via IoC or manually)\n * - Call the specified method (defaults to `index`)\n *\n * @param handler Event handler function OR controller class\n * @param methodName Method to invoke on the controller (defaults to 'index')\n */\n private resolveControllerOrHandler (\n handler: EventHandler | (new (...args: any[]) => Record<string, any>),\n methodName?: string,\n path?: string,\n ): EventHandler {\n /**\n * Checks if the handler is a function (either a plain function or a class constructor)\n */\n if (typeof handler === 'function' && typeof (handler as any).prototype !== 'undefined') {\n return async (ctx) => {\n let controller: IController\n if (Container.hasAnyDecorator(handler as any)) {\n /**\n * If the controller is decorated use the IoC container\n */\n controller = this.app.make<any, IController>(handler as any)\n } else {\n /**\n * Otherwise instantiate manually so that we can at least\n * pass the app instance\n */\n controller = new (handler as new (...args: any[]) => IController)(this.app)\n }\n\n /**\n * The method to execute (defaults to 'index')\n */\n const action = (methodName || 'index') as keyof IController\n\n /**\n * Ensure the method exists on the controller\n */\n if (typeof controller[action] !== 'function') {\n throw new Error(`Method \"${String(action)}\" not found on controller ${handler.name}`)\n }\n\n /**\n * Get param types for the controller method\n */\n const paramTypes: [] = Reflect.getMetadata('design:paramtypes', controller, action) || []\n\n /**\n * Resolve the bound dependencies\n */\n let args = await Promise.all(\n paramTypes.map(async (paramType: any) => {\n switch (paramType?.name) {\n case 'Application':\n return this.app\n case 'Request':\n return ctx.request\n case 'Response':\n return ctx.response\n case 'HttpContext':\n return ctx\n default: {\n const inst = this.app.make(paramType)\n if (inst instanceof Model) {\n // Route model binding returns a Promise\n return await Helpers.resolveRouteModelBinding(path ?? '', ctx, inst)\n }\n return inst\n }\n }\n })\n )\n\n /**\n * Ensure that the HttpContext is always available\n */\n if (args.length < 1) {\n args = [ctx]\n }\n\n /**\n * Call the controller method, passing all resolved dependencies\n */\n return await controller[action](...args)\n }\n }\n\n return handler as EventHandler\n }\n\n /**\n * Registers a route that responds to HTTP GET requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n get (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n\n this.addRoute('get', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP POST requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n post (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n\n this.addRoute('post', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PUT requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n put (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('put', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PATCH requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n patch (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('patch', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP DELETE requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n delete (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('delete', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * API Resource support \n * \n * @param path \n * @param controller \n */\n apiResource (\n path: string,\n Controller: new (app: Application) => IController,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd | 'name'> {\n path = path.replace(/\\//g, '/')\n\n const basePath = `/${path}`.replace(/\\/+$/, '').replace(/(\\/)+/g, '$1')\n const name = basePath.substring(basePath.lastIndexOf('/') + 1).replaceAll(/\\/|:/g, '') || ''\n const param = singularize(name)\n\n this.get(basePath, [Controller, 'index'], `${name}.index`, middleware)\n this.post(basePath, [Controller, 'store'], `${name}.store`, middleware)\n this.get(`${basePath}/:${param}`, [Controller, 'show'], `${name}.show`, middleware)\n this.put(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.patch(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.delete(`${basePath}/:${param}`, [Controller, 'destroy'], `${name}.destroy`, middleware)\n\n return this\n }\n\n /**\n * Named route URL generator\n * \n * @param name \n * @param params \n * @returns \n */\n route (name: string, params: Record<string, string> = {}): string | undefined {\n const found = this.routes.find(r => r.name === name)\n if (!found) return undefined\n\n let url = found.path\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`:${key}`, value)\n }\n return url\n }\n\n /**\n * Grouping\n * \n * @param options \n * @param callback \n */\n group (options: { prefix?: string; middleware?: EventHandler[] }, callback: (_e: this) => void) {\n const prevPrefix = this.groupPrefix\n const prevMiddleware = [...this.groupMiddleware]\n\n this.groupPrefix += options.prefix || ''\n this.groupMiddleware.push(...(options.middleware || []))\n\n callback(this)\n\n /**\n * Restore state after group\n */\n this.groupPrefix = prevPrefix\n this.groupMiddleware = prevMiddleware\n return this\n }\n\n /**\n * Set the name of the current route\n * \n * @param name \n */\n name (name: string) {\n this.nameMap.push(name)\n return this\n }\n\n /**\n * Registers middleware for a specific path.\n * @param path - The path to apply the middleware.\n * @param handler - The middleware handler.\n * @param opts - Optional middleware options.\n */\n middleware (path: string | IMiddleware[] | Middleware, handler: Middleware | MiddlewareOptions, opts?: MiddlewareOptions) {\n opts = typeof handler === 'object' ? handler : (typeof opts === 'function' ? opts : {})\n handler = typeof path === 'function' ? path : (typeof handler === 'function' ? handler : () => { })\n\n if (Array.isArray(path)) {\n this.middlewareMap.concat(path)\n } else if (typeof path === 'function') {\n this.h3App.use('/', () => { }).use(path)\n } else {\n this.h3App.use(path, handler, opts)\n }\n\n return this\n }\n}\n","import { RouteListCommand } from '../Commands/RouteListCommand'\nimport { Router } from '../Route'\nimport { ServiceProvider } from '@h3ravel/core'\nimport path from 'node:path'\nimport { readdir } from 'node:fs/promises'\n\n/**\n * Handles routing registration\n * \n * Load route files (web.ts, api.ts).\n * Map controllers to routes.\n * Register route-related middleware.\n * \n * Auto-Registered\n */\nexport class RouteServiceProvider extends ServiceProvider {\n public static priority = 997\n\n register () {\n this.app.singleton('router', () => {\n const h3App = this.app.make('http.app')\n return new Router(h3App, this.app)\n })\n this.commands([RouteListCommand])\n }\n\n /**\n * Load routes from src/routes\n */\n async boot () {\n try {\n const routePath = this.app.getPath('routes')\n\n const files = (await readdir(routePath)).filter((e) => {\n return !e.includes('.d.ts') && !e.includes('.d.cts') && !e.includes('.map')\n })\n\n for (let i = 0; i < files.length; i++) {\n const routesModule = await import(path.join(routePath, files[i]))\n\n if (typeof routesModule.default === 'function') {\n const router = this.app.make('router')\n routesModule.default(router)\n }\n }\n } catch (e) {\n console.warn('No web routes found or failed to load:', e)\n }\n }\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,9 +1,57 @@
1
1
  /// <reference path="./app.globals.d.ts" />
2
+ import { Application, ConsoleCommand, ServiceProvider } from "@h3ravel/core";
2
3
  import { EventHandler, HttpContext, IController, IMiddleware, IRouter, RouteEventHandler, RouterEnd } from "@h3ravel/shared";
3
4
  import { Model } from "@h3ravel/database";
4
- import { Application, ServiceProvider } from "@h3ravel/core";
5
5
  import { H3, Middleware, MiddlewareOptions } from "h3";
6
6
 
7
+ //#region src/Commands/RouteListCommand.d.ts
8
+ declare class RouteListCommand extends ConsoleCommand {
9
+ /**
10
+ * The name and signature of the console command.
11
+ *
12
+ * @var string
13
+ */
14
+ protected signature: string;
15
+ /**
16
+ * The console command description.
17
+ *
18
+ * @var string
19
+ */
20
+ protected description: string;
21
+ /**
22
+ * Execute the console command.
23
+ */
24
+ handle(this: any): Promise<void>;
25
+ /**
26
+ * List all registered routes.
27
+ */
28
+ protected list(): Promise<void>;
29
+ /**
30
+ * Get the color
31
+ *
32
+ * @param method
33
+ * @returns
34
+ */
35
+ private color;
36
+ /**
37
+ * Get the alternate method
38
+ *
39
+ * @param method
40
+ * @returns
41
+ */
42
+ private pair;
43
+ }
44
+ //#endregion
45
+ //#region src/Contracts/Router.d.ts
46
+ type RouteMethod = 'get' | 'head' | 'put' | 'patch' | 'post' | 'delete';
47
+ interface RouteDefinition {
48
+ method: RouteMethod;
49
+ path: string;
50
+ name?: string | undefined;
51
+ handler: EventHandler;
52
+ signature: [string, string | undefined];
53
+ }
54
+ //#endregion
7
55
  //#region src/Helpers.d.ts
8
56
  declare class Helpers {
9
57
  /**
@@ -202,5 +250,5 @@ declare class Router implements IRouter {
202
250
  middleware(path: string | IMiddleware[] | Middleware, handler: Middleware | MiddlewareOptions, opts?: MiddlewareOptions): this;
203
251
  }
204
252
  //#endregion
205
- export { AssetsServiceProvider, Helpers, RouteServiceProvider, Router };
253
+ export { AssetsServiceProvider, Helpers, RouteDefinition, RouteListCommand, RouteMethod, RouteServiceProvider, Router };
206
254
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,10 +1,58 @@
1
1
  /// <reference path="./app.globals.d.ts" />
2
- import { Application, ServiceProvider } from "@h3ravel/core";
2
+ import { Application, ConsoleCommand, ServiceProvider } from "@h3ravel/core";
3
+ import { EventHandler, HttpContext, IController, IMiddleware, IRouter, RouteEventHandler, RouterEnd } from "@h3ravel/shared";
3
4
  import { H3, Middleware, MiddlewareOptions } from "h3";
4
5
  import "reflect-metadata";
5
- import { EventHandler, HttpContext, IController, IMiddleware, IRouter, RouteEventHandler, RouterEnd } from "@h3ravel/shared";
6
6
  import { Model } from "@h3ravel/database";
7
7
 
8
+ //#region src/Commands/RouteListCommand.d.ts
9
+ declare class RouteListCommand extends ConsoleCommand {
10
+ /**
11
+ * The name and signature of the console command.
12
+ *
13
+ * @var string
14
+ */
15
+ protected signature: string;
16
+ /**
17
+ * The console command description.
18
+ *
19
+ * @var string
20
+ */
21
+ protected description: string;
22
+ /**
23
+ * Execute the console command.
24
+ */
25
+ handle(this: any): Promise<void>;
26
+ /**
27
+ * List all registered routes.
28
+ */
29
+ protected list(): Promise<void>;
30
+ /**
31
+ * Get the color
32
+ *
33
+ * @param method
34
+ * @returns
35
+ */
36
+ private color;
37
+ /**
38
+ * Get the alternate method
39
+ *
40
+ * @param method
41
+ * @returns
42
+ */
43
+ private pair;
44
+ }
45
+ //#endregion
46
+ //#region src/Contracts/Router.d.ts
47
+ type RouteMethod = 'get' | 'head' | 'put' | 'patch' | 'post' | 'delete';
48
+ interface RouteDefinition {
49
+ method: RouteMethod;
50
+ path: string;
51
+ name?: string | undefined;
52
+ handler: EventHandler;
53
+ signature: [string, string | undefined];
54
+ }
55
+ //#endregion
8
56
  //#region src/Helpers.d.ts
9
57
  declare class Helpers {
10
58
  /**
@@ -203,5 +251,5 @@ declare class Router implements IRouter {
203
251
  middleware(path: string | IMiddleware[] | Middleware, handler: Middleware | MiddlewareOptions, opts?: MiddlewareOptions): this;
204
252
  }
205
253
  //#endregion
206
- export { AssetsServiceProvider, Helpers, RouteServiceProvider, Router };
254
+ export { AssetsServiceProvider, Helpers, RouteDefinition, RouteListCommand, RouteMethod, RouteServiceProvider, Router };
207
255
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,14 +1,91 @@
1
+ import { ConsoleCommand, Container, Kernel, ServiceProvider } from "@h3ravel/core";
2
+ import { HttpContext, Logger } from "@h3ravel/shared";
1
3
  import { readFile, readdir, stat } from "node:fs/promises";
2
- import { Container, Kernel, ServiceProvider } from "@h3ravel/core";
3
4
  import { before, singularize } from "@h3ravel/support";
4
5
  import path, { join } from "node:path";
5
6
  import { serveStatic } from "h3";
6
7
  import { statSync } from "node:fs";
7
8
  import "reflect-metadata";
8
9
  import { Request, Response } from "@h3ravel/http";
9
- import { HttpContext } from "@h3ravel/shared";
10
10
  import { Model } from "@h3ravel/database";
11
11
 
12
+ //#region src/Commands/RouteListCommand.ts
13
+ var RouteListCommand = class extends ConsoleCommand {
14
+ /**
15
+ * The name and signature of the console command.
16
+ *
17
+ * @var string
18
+ */
19
+ signature = `#route:
20
+ {list : List all registered routes.
21
+ | {--json : Output the route list as JSON}
22
+ | {--r|reverse : Reverse the ordering of the routes}
23
+ }
24
+ `;
25
+ /**
26
+ * The console command description.
27
+ *
28
+ * @var string
29
+ */
30
+ description = "List all registered routes.";
31
+ /**
32
+ * Execute the console command.
33
+ */
34
+ async handle() {
35
+ console.log("");
36
+ const command = this.dictionary.baseCommand ?? this.dictionary.name;
37
+ await this[command]();
38
+ }
39
+ /**
40
+ * List all registered routes.
41
+ */
42
+ async list() {
43
+ [...this.app.make("routes")].sort((a, b) => {
44
+ if (a.path === "/" && b.path !== "/") return -1;
45
+ if (b.path === "/" && a.path !== "/") return 1;
46
+ return a.path.localeCompare(b.path);
47
+ }).forEach((route) => {
48
+ const path$1 = route.path === "/" ? route.path : Logger.log(route.path.slice(1).split("/").map((e) => [(e.includes(":") ? Logger.log("/", "white", false) : "") + e, e.startsWith(":") ? "yellow" : "white"]), "", false);
49
+ const method = (route.method.startsWith("/") ? route.method.slice(1) : route.method).toUpperCase();
50
+ const name = route.signature[1] ? [
51
+ route.name ?? "",
52
+ route.name ? "›" : "",
53
+ route.signature.join("@")
54
+ ].join(" ") : "";
55
+ const desc = Logger.describe(Logger.log(Logger.log(method + this.pair(method), this.color(method), false), "green", false), path$1, 15, false);
56
+ return Logger.twoColumnLog(desc.join(""), name);
57
+ });
58
+ }
59
+ /**
60
+ * Get the color
61
+ *
62
+ * @param method
63
+ * @returns
64
+ */
65
+ color(method) {
66
+ switch (method.toLowerCase()) {
67
+ case "get": return "blue";
68
+ case "head": return "gray";
69
+ case "delete": return "red";
70
+ default: return "yellow";
71
+ }
72
+ }
73
+ /**
74
+ * Get the alternate method
75
+ *
76
+ * @param method
77
+ * @returns
78
+ */
79
+ pair(method) {
80
+ switch (method.toLowerCase()) {
81
+ case "get": return "|HEAD";
82
+ case "put": return "|PATCH";
83
+ default: return "";
84
+ }
85
+ }
86
+ };
87
+
88
+ //#endregion
12
89
  //#region src/Helpers.ts
13
90
  var Helpers = class Helpers {
14
91
  /**
@@ -71,7 +148,6 @@ var AssetsServiceProvider = class extends ServiceProvider {
71
148
  static priority = 996;
72
149
  register() {
73
150
  const app = this.app.make("router");
74
- this.app.make("config").get("filesystem");
75
151
  const publicPath = this.app.getPath("public");
76
152
  /**
77
153
  * Use a middleware to check if this request for for a file
@@ -151,7 +227,7 @@ var Router = class {
151
227
  * @param name
152
228
  * @param middleware
153
229
  */
154
- addRoute(method, path$1, handler, name, middleware = []) {
230
+ addRoute(method, path$1, handler, name, middleware = [], signature = ["", ""]) {
155
231
  /**
156
232
  * Join all defined route names to make a single route name
157
233
  */
@@ -165,9 +241,11 @@ var Router = class {
165
241
  method,
166
242
  path: fullPath,
167
243
  name,
168
- handler
244
+ handler,
245
+ signature
169
246
  });
170
247
  this.h3App[method](fullPath, this.resolveHandler(handler, middleware));
248
+ this.app.singleton("routes", () => this.routes);
171
249
  }
172
250
  /**
173
251
  * Resolves a route handler definition into an executable EventHandler.
@@ -252,7 +330,7 @@ var Router = class {
252
330
  get(path$1, definition, name, middleware = []) {
253
331
  const handler = Array.isArray(definition) ? definition[0] : definition;
254
332
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
255
- this.addRoute("get", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
333
+ this.addRoute("get", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
256
334
  return this;
257
335
  }
258
336
  /**
@@ -268,7 +346,7 @@ var Router = class {
268
346
  post(path$1, definition, name, middleware = []) {
269
347
  const handler = Array.isArray(definition) ? definition[0] : definition;
270
348
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
271
- this.addRoute("post", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
349
+ this.addRoute("post", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
272
350
  return this;
273
351
  }
274
352
  /**
@@ -284,7 +362,7 @@ var Router = class {
284
362
  put(path$1, definition, name, middleware = []) {
285
363
  const handler = Array.isArray(definition) ? definition[0] : definition;
286
364
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
287
- this.addRoute("put", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
365
+ this.addRoute("put", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
288
366
  return this;
289
367
  }
290
368
  /**
@@ -300,7 +378,7 @@ var Router = class {
300
378
  patch(path$1, definition, name, middleware = []) {
301
379
  const handler = Array.isArray(definition) ? definition[0] : definition;
302
380
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
303
- this.addRoute("patch", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
381
+ this.addRoute("patch", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
304
382
  return this;
305
383
  }
306
384
  /**
@@ -316,7 +394,7 @@ var Router = class {
316
394
  delete(path$1, definition, name, middleware = []) {
317
395
  const handler = Array.isArray(definition) ? definition[0] : definition;
318
396
  const methodName = Array.isArray(definition) ? definition[1] : void 0;
319
- this.addRoute("delete", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
397
+ this.addRoute("delete", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware, [handler.name, methodName]);
320
398
  return this;
321
399
  }
322
400
  /**
@@ -414,6 +492,7 @@ var RouteServiceProvider = class extends ServiceProvider {
414
492
  const h3App = this.app.make("http.app");
415
493
  return new Router(h3App, this.app);
416
494
  });
495
+ this.commands([RouteListCommand]);
417
496
  }
418
497
  /**
419
498
  * Load routes from src/routes
@@ -438,5 +517,5 @@ var RouteServiceProvider = class extends ServiceProvider {
438
517
  };
439
518
 
440
519
  //#endregion
441
- export { AssetsServiceProvider, Helpers, RouteServiceProvider, Router };
520
+ export { AssetsServiceProvider, Helpers, RouteListCommand, RouteServiceProvider, Router };
442
521
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["params: string[]","match: RegExpExecArray | null","path","h3App: H3","app: Application","path","controller: IController","paramTypes: []"],"sources":["../src/Helpers.ts","../src/Providers/AssetsServiceProvider.ts","../src/Route.ts","../src/Providers/RouteServiceProvider.ts"],"sourcesContent":["import { HttpContext } from '@h3ravel/shared'\nimport { Model } from '@h3ravel/database'\n\nexport class Helpers {\n /**\n * Extracts parameter names from a route path string.\n *\n * - Looks for segments prefixed with \":\" (e.g. \"/users/:id\")\n * - Captures only the param name (without the \":\")\n * - Returns all matches in order of appearance\n *\n * @param path - The route path string (e.g. \"/groups/:group/users/:user\")\n * @returns An array of parameter names (e.g. [\"group\", \"user\"])\n */\n static extractParams (path: string): string[] {\n const regex = /:([^/]+)/g\n const params: string[] = []\n let match: RegExpExecArray | null\n\n while ((match = regex.exec(path)) !== null) {\n params.push(match[1])\n }\n\n return params\n }\n\n /**\n * Resolves route model binding for a given path, HTTP context, and model.\n * \n * - Extracts all route parameters from the given path\n * - If a parameter matches the model name, it attempts to resolve the model binding\n * using the provided value and binding field (defaults to \"id\" unless specified).\n * - For non-matching parameters, it simply returns the key-value pair as is.\n * - If no parameters are found, returns an empty object.\n *\n * @param path - The route path (e.g. \"/groups/:group/users/:user\")\n * @param ctx - The HTTP context containing the request\n * @param model - The model instance to resolve bindings against\n * @returns A resolved model instance or an object containing param values\n */\n static async resolveRouteModelBinding (path: string, ctx: HttpContext, model: Model): Promise<any> {\n const name = model.constructor.name.toLowerCase()\n /**\n * Extract field (defaults to 'id' if not specified after '|')\n */\n const field = name.split('|').at(1) ?? 'id'\n\n /**\n * Iterate through extracted parameters from the path\n */\n for await (const e of Helpers.extractParams(path)) {\n const value = ctx.request.params[e] ?? null\n if (e === name) return await model.resolveRouteBinding(value, field)\n else return { [e]: ctx.request.params[e] ?? {} }\n }\n\n return {}\n }\n}\n","import { readFile, stat } from 'node:fs/promises'\n\nimport { ServiceProvider } from '@h3ravel/core'\nimport { before } from '@h3ravel/support'\nimport { join } from 'node:path'\nimport { serveStatic } from 'h3'\nimport { statSync } from 'node:fs'\n\n/**\n * Handles public assets loading\n * \n * Auto-Registered\n */\nexport class AssetsServiceProvider extends ServiceProvider {\n public static priority = 996\n\n register () {\n const app = this.app.make('router')\n const config = this.app.make('config')\n const fsconfig = config.get('filesystem')\n const publicPath = this.app.getPath('public')\n\n /**\n * Use a middleware to check if this request for for a file\n */\n app.middleware((event) => {\n const { pathname } = new URL(event.req.url)\n\n /**\n * Only serve if it looks like a static asset (has an extension)\n * but skip dotfiles or sensitive files\n */\n if (!/\\.[a-zA-Z0-9]+$/.test(pathname)) return\n if (pathname.startsWith('/.') || pathname.includes('..')) return\n\n /**\n * Serve the asset\n */\n return serveStatic(event, {\n indexNames: ['/index.html'],\n getContents: (id) => {\n return <never>readFile(join(before(publicPath, id), id))\n },\n getMeta: async (id) => {\n const stats = await stat(join(before(publicPath, id), id)).catch(() => { })\n if (stats?.isFile()) {\n return {\n size: stats.size,\n mtime: stats.mtimeMs,\n }\n }\n },\n })\n })\n\n this.app.singleton('asset', () => {\n return (key: string, def?: string) => {\n if (def) {\n try {\n statSync(join(before(publicPath, key), key))\n } catch {\n key = def\n }\n }\n\n return key\n }\n })\n }\n}\n","import 'reflect-metadata'\nimport { H3Event, Middleware, MiddlewareOptions, type H3 } from 'h3'\nimport { Application, Container, Kernel } from '@h3ravel/core'\nimport { Request, Response } from '@h3ravel/http'\nimport { singularize } from '@h3ravel/support'\nimport { HttpContext, RouteEventHandler } from '@h3ravel/shared'\nimport type { EventHandler, IController, IMiddleware, IRouter, RouterEnd } from '@h3ravel/shared'\nimport { Helpers } from './Helpers'\nimport { Model } from '@h3ravel/database'\n\ninterface RouteDefinition {\n method: string\n path: string\n name?: string\n handler: EventHandler\n}\n\nexport class Router implements IRouter {\n private routes: RouteDefinition[] = []\n private nameMap: string[] = []\n private groupPrefix = ''\n private middlewareMap: IMiddleware[] = []\n private groupMiddleware: EventHandler[] = []\n\n constructor(protected h3App: H3, private app: Application) { }\n\n /**\n * Route Resolver\n * \n * @param handler \n * @param middleware \n * @returns \n */\n private resolveHandler (handler: EventHandler, middleware: IMiddleware[] = []) {\n return async (event: H3Event) => {\n const kernel = new Kernel(() => HttpContext.init({\n app: this.app,\n request: new Request(event, this.app),\n response: new Response(event, this.app)\n }), middleware)\n\n return kernel.handle(event, (ctx) => Promise.resolve(handler(ctx)))\n }\n }\n\n /**\n * Add a route to the stack\n * \n * @param method \n * @param path \n * @param handler \n * @param name \n * @param middleware \n */\n private addRoute (\n method: string,\n path: string,\n handler: EventHandler,\n name?: string,\n middleware: IMiddleware[] = []\n ) {\n /**\n * Join all defined route names to make a single route name\n */\n if (this.nameMap.length > 0) {\n name = this.nameMap.join('.')\n }\n\n /**\n * Join all defined middlewares\n */\n if (this.middlewareMap.length > 0) {\n middleware = this.middlewareMap\n }\n\n const fullPath = `${this.groupPrefix}${path}`.replace(/\\/+/g, '/')\n this.routes.push({ method, path: fullPath, name, handler })\n this.h3App[method as 'get'](fullPath, this.resolveHandler(handler, middleware))\n }\n\n /**\n * Resolves a route handler definition into an executable EventHandler.\n *\n * A handler can be:\n * - A function matching the EventHandler signature\n * - A controller class (optionally decorated for IoC resolution)\n *\n * If it’s a controller class, this method will:\n * - Instantiate it (via IoC or manually)\n * - Call the specified method (defaults to `index`)\n *\n * @param handler Event handler function OR controller class\n * @param methodName Method to invoke on the controller (defaults to 'index')\n */\n private resolveControllerOrHandler (\n handler: EventHandler | (new (...args: any[]) => Record<string, any>),\n methodName?: string,\n path?: string,\n ): EventHandler {\n /**\n * Checks if the handler is a function (either a plain function or a class constructor)\n */\n if (typeof handler === 'function' && typeof (handler as any).prototype !== 'undefined') {\n return async (ctx) => {\n let controller: IController\n if (Container.hasAnyDecorator(handler as any)) {\n /**\n * If the controller is decorated use the IoC container\n */\n controller = this.app.make<any, IController>(handler as any)\n } else {\n /**\n * Otherwise instantiate manually so that we can at least\n * pass the app instance\n */\n controller = new (handler as new (...args: any[]) => IController)(this.app)\n }\n\n /**\n * The method to execute (defaults to 'index')\n */\n const action = (methodName || 'index') as keyof IController\n\n /**\n * Ensure the method exists on the controller\n */\n if (typeof controller[action] !== 'function') {\n throw new Error(`Method \"${String(action)}\" not found on controller ${handler.name}`)\n }\n\n /**\n * Get param types for the controller method\n */\n const paramTypes: [] = Reflect.getMetadata('design:paramtypes', controller, action) || []\n\n /**\n * Resolve the bound dependencies\n */\n let args = await Promise.all(\n paramTypes.map(async (paramType: any) => {\n switch (paramType?.name) {\n case 'Application':\n return this.app\n case 'Request':\n return ctx.request\n case 'Response':\n return ctx.response\n case 'HttpContext':\n return ctx\n default: {\n const inst = this.app.make(paramType)\n if (inst instanceof Model) {\n // Route model binding returns a Promise\n return await Helpers.resolveRouteModelBinding(path ?? '', ctx, inst)\n }\n return inst\n }\n }\n })\n )\n\n /**\n * Ensure that the HttpContext is always available\n */\n if (args.length < 1) {\n args = [ctx]\n }\n\n /**\n * Call the controller method, passing all resolved dependencies\n */\n return await controller[action](...args)\n }\n }\n\n return handler as EventHandler\n }\n\n /**\n * Registers a route that responds to HTTP GET requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n get (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n\n this.addRoute('get', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP POST requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n post (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('post', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PUT requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n put (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('put', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PATCH requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n patch (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('patch', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * Registers a route that responds to HTTP DELETE requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n delete (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('delete', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware)\n return this\n }\n\n /**\n * API Resource support \n * \n * @param path \n * @param controller \n */\n apiResource (\n path: string,\n Controller: new (app: Application) => IController,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd | 'name'> {\n path = path.replace(/\\//g, '/')\n\n const basePath = `/${path}`.replace(/\\/+$/, '').replace(/(\\/)+/g, '$1')\n const name = basePath.substring(basePath.lastIndexOf('/') + 1).replaceAll(/\\/|:/g, '') || ''\n const param = singularize(name)\n\n this.get(basePath, [Controller, 'index'], `${name}.index`, middleware)\n this.post(basePath, [Controller, 'store'], `${name}.store`, middleware)\n this.get(`${basePath}/:${param}`, [Controller, 'show'], `${name}.show`, middleware)\n this.put(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.patch(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.delete(`${basePath}/:${param}`, [Controller, 'destroy'], `${name}.destroy`, middleware)\n\n return this\n }\n\n /**\n * Named route URL generator\n * \n * @param name \n * @param params \n * @returns \n */\n route (name: string, params: Record<string, string> = {}): string | undefined {\n const found = this.routes.find(r => r.name === name)\n if (!found) return undefined\n\n let url = found.path\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`:${key}`, value)\n }\n return url\n }\n\n /**\n * Grouping\n * \n * @param options \n * @param callback \n */\n group (options: { prefix?: string; middleware?: EventHandler[] }, callback: (_e: this) => void) {\n const prevPrefix = this.groupPrefix\n const prevMiddleware = [...this.groupMiddleware]\n\n this.groupPrefix += options.prefix || ''\n this.groupMiddleware.push(...(options.middleware || []))\n\n callback(this)\n\n /**\n * Restore state after group\n */\n this.groupPrefix = prevPrefix\n this.groupMiddleware = prevMiddleware\n return this\n }\n\n /**\n * Set the name of the current route\n * \n * @param name \n */\n name (name: string) {\n this.nameMap.push(name)\n return this\n }\n\n /**\n * Registers middleware for a specific path.\n * @param path - The path to apply the middleware.\n * @param handler - The middleware handler.\n * @param opts - Optional middleware options.\n */\n middleware (path: string | IMiddleware[] | Middleware, handler: Middleware | MiddlewareOptions, opts?: MiddlewareOptions) {\n opts = typeof handler === 'object' ? handler : (typeof opts === 'function' ? opts : {})\n handler = typeof path === 'function' ? path : (typeof handler === 'function' ? handler : () => { })\n\n if (Array.isArray(path)) {\n this.middlewareMap.concat(path)\n } else if (typeof path === 'function') {\n this.h3App.use('/', () => { }).use(path)\n } else {\n this.h3App.use(path, handler, opts)\n }\n\n return this\n }\n}\n","import { Router } from '../Route'\nimport { ServiceProvider } from '@h3ravel/core'\nimport path from 'node:path'\nimport { readdir } from 'node:fs/promises'\n\n/**\n * Handles routing registration\n * \n * Load route files (web.ts, api.ts).\n * Map controllers to routes.\n * Register route-related middleware.\n * \n * Auto-Registered\n */\nexport class RouteServiceProvider extends ServiceProvider {\n public static priority = 997\n\n register () {\n this.app.singleton('router', () => {\n const h3App = this.app.make('http.app')\n return new Router(h3App, this.app)\n })\n }\n\n /**\n * Load routes from src/routes\n */\n async boot () {\n try {\n const routePath = this.app.getPath('routes')\n\n const files = (await readdir(routePath)).filter((e) => {\n return !e.includes('.d.ts') && !e.includes('.d.cts') && !e.includes('.map')\n })\n\n for (let i = 0; i < files.length; i++) {\n const routesModule = await import(path.join(routePath, files[i]))\n\n if (typeof routesModule.default === 'function') {\n const router = this.app.make('router')\n routesModule.default(router)\n }\n }\n } catch (e) {\n console.warn('No web routes found or failed to load:', e)\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["path","params: string[]","match: RegExpExecArray | null","path","h3App: H3","app: Application","path","controller: IController","paramTypes: []"],"sources":["../src/Commands/RouteListCommand.ts","../src/Helpers.ts","../src/Providers/AssetsServiceProvider.ts","../src/Route.ts","../src/Providers/RouteServiceProvider.ts"],"sourcesContent":["import { RouteDefinition, RouteMethod } from '../Contracts/Router'\n\nimport { ConsoleCommand } from '@h3ravel/core'\nimport { Logger } from '@h3ravel/shared'\nimport { LoggerChalk } from '@/packages/shared/dist'\n\nexport class RouteListCommand extends ConsoleCommand {\n\n /**\n * The name and signature of the console command.\n *\n * @var string\n */\n protected signature: string = `#route:\n {list : List all registered routes. \n | {--json : Output the route list as JSON}\n | {--r|reverse : Reverse the ordering of the routes}\n }\n `\n\n /**\n * The console command description.\n *\n * @var string\n */\n protected description: string = 'List all registered routes.'\n\n /**\n * Execute the console command.\n */\n public async handle (this: any) {\n console.log('')\n const command = (this.dictionary.baseCommand ?? this.dictionary.name)\n\n await this[command]()\n }\n\n /**\n * List all registered routes.\n */\n protected async list () {\n const list = [...(this.app.make<any>('routes') as RouteDefinition[])].sort((a, b) => {\n if (a.path === '/' && b.path !== '/') return -1\n if (b.path === '/' && a.path !== '/') return 1\n return a.path.localeCompare(b.path)\n })\n\n\n list.forEach(route => {\n const path = route.path === '/'\n ? route.path\n : Logger.log((route.path.slice(1)).split('/').map(e => [\n (e.includes(':') ? Logger.log('/', 'white', false) : '') + e,\n e.startsWith(':') ? 'yellow' : 'white'\n ] as [string, LoggerChalk]), '', false)\n\n const method = (route.method.startsWith('/') ? route.method.slice(1) : route.method).toUpperCase() as RouteMethod\n const name = route.signature[1] ? [route.name ?? '', route.name ? '›' : '', route.signature.join('@')].join(' ') : ''\n\n const desc = Logger.describe(\n Logger.log(Logger.log(method + this.pair(method), this.color(method), false), 'green', false), path, 15, false\n )\n return Logger.twoColumnLog(desc.join(''), name)\n })\n }\n\n /**\n * Get the color\n * \n * @param method \n * @returns \n */\n private color (method: RouteMethod): LoggerChalk {\n switch (method.toLowerCase()) {\n case 'get':\n return 'blue'\n case 'head':\n return 'gray'\n case 'delete':\n return 'red'\n default:\n return 'yellow'\n }\n }\n\n /**\n * Get the alternate method\n * \n * @param method \n * @returns \n */\n private pair (method: RouteMethod) {\n switch (method.toLowerCase()) {\n case 'get':\n return '|HEAD'\n case 'put':\n return '|PATCH'\n default:\n return ''\n }\n }\n}\n","import { HttpContext } from '@h3ravel/shared'\nimport { Model } from '@h3ravel/database'\n\nexport class Helpers {\n /**\n * Extracts parameter names from a route path string.\n *\n * - Looks for segments prefixed with \":\" (e.g. \"/users/:id\")\n * - Captures only the param name (without the \":\")\n * - Returns all matches in order of appearance\n *\n * @param path - The route path string (e.g. \"/groups/:group/users/:user\")\n * @returns An array of parameter names (e.g. [\"group\", \"user\"])\n */\n static extractParams (path: string): string[] {\n const regex = /:([^/]+)/g\n const params: string[] = []\n let match: RegExpExecArray | null\n\n while ((match = regex.exec(path)) !== null) {\n params.push(match[1])\n }\n\n return params\n }\n\n /**\n * Resolves route model binding for a given path, HTTP context, and model.\n * \n * - Extracts all route parameters from the given path\n * - If a parameter matches the model name, it attempts to resolve the model binding\n * using the provided value and binding field (defaults to \"id\" unless specified).\n * - For non-matching parameters, it simply returns the key-value pair as is.\n * - If no parameters are found, returns an empty object.\n *\n * @param path - The route path (e.g. \"/groups/:group/users/:user\")\n * @param ctx - The HTTP context containing the request\n * @param model - The model instance to resolve bindings against\n * @returns A resolved model instance or an object containing param values\n */\n static async resolveRouteModelBinding (path: string, ctx: HttpContext, model: Model): Promise<any> {\n const name = model.constructor.name.toLowerCase()\n /**\n * Extract field (defaults to 'id' if not specified after '|')\n */\n const field = name.split('|').at(1) ?? 'id'\n\n /**\n * Iterate through extracted parameters from the path\n */\n for await (const e of Helpers.extractParams(path)) {\n const value = ctx.request.params[e] ?? null\n if (e === name) return await model.resolveRouteBinding(value, field)\n else return { [e]: ctx.request.params[e] ?? {} }\n }\n\n return {}\n }\n}\n","import { readFile, stat } from 'node:fs/promises'\n\nimport { ServiceProvider } from '@h3ravel/core'\nimport { before } from '@h3ravel/support'\nimport { join } from 'node:path'\nimport { serveStatic } from 'h3'\nimport { statSync } from 'node:fs'\n\n/**\n * Handles public assets loading\n * \n * Auto-Registered\n */\nexport class AssetsServiceProvider extends ServiceProvider {\n public static priority = 996\n\n register () {\n const app = this.app.make('router')\n const publicPath = this.app.getPath('public')\n\n /**\n * Use a middleware to check if this request for for a file\n */\n app.middleware((event) => {\n const { pathname } = new URL(event.req.url)\n\n /**\n * Only serve if it looks like a static asset (has an extension)\n * but skip dotfiles or sensitive files\n */\n if (!/\\.[a-zA-Z0-9]+$/.test(pathname)) return\n if (pathname.startsWith('/.') || pathname.includes('..')) return\n\n /**\n * Serve the asset\n */\n return serveStatic(event, {\n indexNames: ['/index.html'],\n getContents: (id) => {\n return <never>readFile(join(before(publicPath, id), id))\n },\n getMeta: async (id) => {\n const stats = await stat(join(before(publicPath, id), id)).catch(() => { })\n if (stats?.isFile()) {\n return {\n size: stats.size,\n mtime: stats.mtimeMs,\n }\n }\n },\n })\n })\n\n this.app.singleton('asset', () => {\n return (key: string, def?: string) => {\n if (def) {\n try {\n statSync(join(before(publicPath, key), key))\n } catch {\n key = def\n }\n }\n\n return key\n }\n })\n }\n}\n","import 'reflect-metadata'\nimport { H3Event, Middleware, MiddlewareOptions, type H3 } from 'h3'\nimport { Application, Container, Kernel } from '@h3ravel/core'\nimport { Request, Response } from '@h3ravel/http'\nimport { singularize } from '@h3ravel/support'\nimport { HttpContext, RouteEventHandler } from '@h3ravel/shared'\nimport type { EventHandler, IController, IMiddleware, IRouter, RouterEnd } from '@h3ravel/shared'\nimport { Helpers } from './Helpers'\nimport { Model } from '@h3ravel/database'\nimport { RouteDefinition, RouteMethod } from './Contracts/Router'\n\nexport class Router implements IRouter {\n private routes: RouteDefinition[] = []\n private nameMap: string[] = []\n private groupPrefix = ''\n private middlewareMap: IMiddleware[] = []\n private groupMiddleware: EventHandler[] = []\n\n constructor(protected h3App: H3, private app: Application) { }\n\n /**\n * Route Resolver\n * \n * @param handler \n * @param middleware \n * @returns \n */\n private resolveHandler (handler: EventHandler, middleware: IMiddleware[] = []) {\n return async (event: H3Event) => {\n const kernel = new Kernel(() => HttpContext.init({\n app: this.app,\n request: new Request(event, this.app),\n response: new Response(event, this.app)\n }), middleware)\n\n return kernel.handle(event, (ctx) => Promise.resolve(handler(ctx)))\n }\n }\n\n /**\n * Add a route to the stack\n * \n * @param method \n * @param path \n * @param handler \n * @param name \n * @param middleware \n */\n private addRoute (\n method: RouteMethod,\n path: string,\n handler: EventHandler,\n name?: string,\n middleware: IMiddleware[] = [],\n signature: RouteDefinition['signature'] = ['', '']\n ) {\n /**\n * Join all defined route names to make a single route name\n */\n if (this.nameMap.length > 0) {\n name = this.nameMap.join('.')\n }\n\n /**\n * Join all defined middlewares\n */\n if (this.middlewareMap.length > 0) {\n middleware = this.middlewareMap\n }\n\n const fullPath = `${this.groupPrefix}${path}`.replace(/\\/+/g, '/')\n this.routes.push({ method, path: fullPath, name, handler, signature })\n this.h3App[method as 'get'](fullPath, this.resolveHandler(handler, middleware))\n this.app.singleton<any>('routes', () => this.routes)\n }\n\n /**\n * Resolves a route handler definition into an executable EventHandler.\n *\n * A handler can be:\n * - A function matching the EventHandler signature\n * - A controller class (optionally decorated for IoC resolution)\n *\n * If it’s a controller class, this method will:\n * - Instantiate it (via IoC or manually)\n * - Call the specified method (defaults to `index`)\n *\n * @param handler Event handler function OR controller class\n * @param methodName Method to invoke on the controller (defaults to 'index')\n */\n private resolveControllerOrHandler (\n handler: EventHandler | (new (...args: any[]) => Record<string, any>),\n methodName?: string,\n path?: string,\n ): EventHandler {\n /**\n * Checks if the handler is a function (either a plain function or a class constructor)\n */\n if (typeof handler === 'function' && typeof (handler as any).prototype !== 'undefined') {\n return async (ctx) => {\n let controller: IController\n if (Container.hasAnyDecorator(handler as any)) {\n /**\n * If the controller is decorated use the IoC container\n */\n controller = this.app.make<any, IController>(handler as any)\n } else {\n /**\n * Otherwise instantiate manually so that we can at least\n * pass the app instance\n */\n controller = new (handler as new (...args: any[]) => IController)(this.app)\n }\n\n /**\n * The method to execute (defaults to 'index')\n */\n const action = (methodName || 'index') as keyof IController\n\n /**\n * Ensure the method exists on the controller\n */\n if (typeof controller[action] !== 'function') {\n throw new Error(`Method \"${String(action)}\" not found on controller ${handler.name}`)\n }\n\n /**\n * Get param types for the controller method\n */\n const paramTypes: [] = Reflect.getMetadata('design:paramtypes', controller, action) || []\n\n /**\n * Resolve the bound dependencies\n */\n let args = await Promise.all(\n paramTypes.map(async (paramType: any) => {\n switch (paramType?.name) {\n case 'Application':\n return this.app\n case 'Request':\n return ctx.request\n case 'Response':\n return ctx.response\n case 'HttpContext':\n return ctx\n default: {\n const inst = this.app.make(paramType)\n if (inst instanceof Model) {\n // Route model binding returns a Promise\n return await Helpers.resolveRouteModelBinding(path ?? '', ctx, inst)\n }\n return inst\n }\n }\n })\n )\n\n /**\n * Ensure that the HttpContext is always available\n */\n if (args.length < 1) {\n args = [ctx]\n }\n\n /**\n * Call the controller method, passing all resolved dependencies\n */\n return await controller[action](...args)\n }\n }\n\n return handler as EventHandler\n }\n\n /**\n * Registers a route that responds to HTTP GET requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n get (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n\n this.addRoute('get', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP POST requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n post (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n\n this.addRoute('post', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PUT requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n put (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('put', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP PATCH requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n patch (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('patch', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * Registers a route that responds to HTTP DELETE requests.\n *\n * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').\n * @param definition Either:\n * - An EventHandler function\n * - A tuple: [ControllerClass, methodName]\n * @param name Optional route name (for URL generation or referencing).\n * @param middleware Optional array of middleware functions to execute before the handler.\n */\n delete (\n path: string,\n definition: RouteEventHandler | [(new (...args: any[]) => Record<string, any>), methodName: string],\n name?: string,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd> {\n const handler = Array.isArray(definition) ? definition[0] : definition\n const methodName = Array.isArray(definition) ? definition[1] : undefined\n this.addRoute('delete', path, this.resolveControllerOrHandler(handler, methodName, path), name, middleware, [handler.name, methodName])\n return this\n }\n\n /**\n * API Resource support \n * \n * @param path \n * @param controller \n */\n apiResource (\n path: string,\n Controller: new (app: Application) => IController,\n middleware: IMiddleware[] = []\n ): Omit<this, RouterEnd | 'name'> {\n path = path.replace(/\\//g, '/')\n\n const basePath = `/${path}`.replace(/\\/+$/, '').replace(/(\\/)+/g, '$1')\n const name = basePath.substring(basePath.lastIndexOf('/') + 1).replaceAll(/\\/|:/g, '') || ''\n const param = singularize(name)\n\n this.get(basePath, [Controller, 'index'], `${name}.index`, middleware)\n this.post(basePath, [Controller, 'store'], `${name}.store`, middleware)\n this.get(`${basePath}/:${param}`, [Controller, 'show'], `${name}.show`, middleware)\n this.put(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.patch(`${basePath}/:${param}`, [Controller, 'update'], `${name}.update`, middleware)\n this.delete(`${basePath}/:${param}`, [Controller, 'destroy'], `${name}.destroy`, middleware)\n\n return this\n }\n\n /**\n * Named route URL generator\n * \n * @param name \n * @param params \n * @returns \n */\n route (name: string, params: Record<string, string> = {}): string | undefined {\n const found = this.routes.find(r => r.name === name)\n if (!found) return undefined\n\n let url = found.path\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`:${key}`, value)\n }\n return url\n }\n\n /**\n * Grouping\n * \n * @param options \n * @param callback \n */\n group (options: { prefix?: string; middleware?: EventHandler[] }, callback: (_e: this) => void) {\n const prevPrefix = this.groupPrefix\n const prevMiddleware = [...this.groupMiddleware]\n\n this.groupPrefix += options.prefix || ''\n this.groupMiddleware.push(...(options.middleware || []))\n\n callback(this)\n\n /**\n * Restore state after group\n */\n this.groupPrefix = prevPrefix\n this.groupMiddleware = prevMiddleware\n return this\n }\n\n /**\n * Set the name of the current route\n * \n * @param name \n */\n name (name: string) {\n this.nameMap.push(name)\n return this\n }\n\n /**\n * Registers middleware for a specific path.\n * @param path - The path to apply the middleware.\n * @param handler - The middleware handler.\n * @param opts - Optional middleware options.\n */\n middleware (path: string | IMiddleware[] | Middleware, handler: Middleware | MiddlewareOptions, opts?: MiddlewareOptions) {\n opts = typeof handler === 'object' ? handler : (typeof opts === 'function' ? opts : {})\n handler = typeof path === 'function' ? path : (typeof handler === 'function' ? handler : () => { })\n\n if (Array.isArray(path)) {\n this.middlewareMap.concat(path)\n } else if (typeof path === 'function') {\n this.h3App.use('/', () => { }).use(path)\n } else {\n this.h3App.use(path, handler, opts)\n }\n\n return this\n }\n}\n","import { RouteListCommand } from '../Commands/RouteListCommand'\nimport { Router } from '../Route'\nimport { ServiceProvider } from '@h3ravel/core'\nimport path from 'node:path'\nimport { readdir } from 'node:fs/promises'\n\n/**\n * Handles routing registration\n * \n * Load route files (web.ts, api.ts).\n * Map controllers to routes.\n * Register route-related middleware.\n * \n * Auto-Registered\n */\nexport class RouteServiceProvider extends ServiceProvider {\n public static priority = 997\n\n register () {\n this.app.singleton('router', () => {\n const h3App = this.app.make('http.app')\n return new Router(h3App, this.app)\n })\n this.commands([RouteListCommand])\n }\n\n /**\n * Load routes from src/routes\n */\n async boot () {\n try {\n const routePath = this.app.getPath('routes')\n\n const files = (await readdir(routePath)).filter((e) => {\n return !e.includes('.d.ts') && !e.includes('.d.cts') && !e.includes('.map')\n })\n\n for (let i = 0; i < files.length; i++) {\n const routesModule = await import(path.join(routePath, files[i]))\n\n if (typeof routesModule.default === 'function') {\n const router = this.app.make('router')\n routesModule.default(router)\n }\n }\n } catch (e) {\n console.warn('No web routes found or failed to load:', e)\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h3ravel/router",
3
- "version": "1.9.3",
3
+ "version": "1.10.0",
4
4
  "description": "Route facade, decorators and controller system for H3ravel.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,10 +38,10 @@
38
38
  "dependencies": {
39
39
  "h3": "2.0.0-beta.4",
40
40
  "reflect-metadata": "^0.2.2",
41
- "@h3ravel/database": "^11.2.6",
42
- "@h3ravel/core": "^1.11.0",
43
- "@h3ravel/shared": "^0.20.8",
41
+ "@h3ravel/shared": "^0.20.9",
44
42
  "@h3ravel/http": "^11.3.1",
43
+ "@h3ravel/database": "^11.2.7",
44
+ "@h3ravel/core": "^1.11.0",
45
45
  "@h3ravel/support": "^0.10.3"
46
46
  },
47
47
  "scripts": {