@h3ravel/router 1.8.3 → 1.9.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
@@ -1,425 +1,463 @@
1
- "use strict";
1
+ //#region rolldown:runtime
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
- var __export = (target, all) => {
10
- for (var name in all)
11
- __defProp(target, name, { get: all[name], enumerable: true });
12
- };
13
8
  var __copyProps = (to, from, except, desc) => {
14
- if (from && typeof from === "object" || typeof from === "function") {
15
- for (let key of __getOwnPropNames(from))
16
- if (!__hasOwnProp.call(to, key) && key !== except)
17
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
- }
19
- return to;
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
20
17
  };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+ let node_fs_promises = require("node:fs/promises");
25
+ node_fs_promises = __toESM(node_fs_promises);
26
+ let __h3ravel_core = require("@h3ravel/core");
27
+ __h3ravel_core = __toESM(__h3ravel_core);
28
+ let __h3ravel_support = require("@h3ravel/support");
29
+ __h3ravel_support = __toESM(__h3ravel_support);
30
+ let node_path = require("node:path");
31
+ node_path = __toESM(node_path);
32
+ let h3 = require("h3");
33
+ h3 = __toESM(h3);
34
+ let node_fs = require("node:fs");
35
+ node_fs = __toESM(node_fs);
36
+ require("reflect-metadata");
37
+ let __h3ravel_http = require("@h3ravel/http");
38
+ __h3ravel_http = __toESM(__h3ravel_http);
39
+ let __h3ravel_shared = require("@h3ravel/shared");
40
+ __h3ravel_shared = __toESM(__h3ravel_shared);
41
+ let __h3ravel_database = require("@h3ravel/database");
42
+ __h3ravel_database = __toESM(__h3ravel_database);
30
43
 
31
- // src/index.ts
32
- var index_exports = {};
33
- __export(index_exports, {
34
- AssetsServiceProvider: () => AssetsServiceProvider,
35
- RouteServiceProvider: () => RouteServiceProvider,
36
- Router: () => Router
37
- });
38
- module.exports = __toCommonJS(index_exports);
44
+ //#region src/Helpers.ts
45
+ var Helpers = class Helpers {
46
+ /**
47
+ * Extracts parameter names from a route path string.
48
+ *
49
+ * - Looks for segments prefixed with ":" (e.g. "/users/:id")
50
+ * - Captures only the param name (without the ":")
51
+ * - Returns all matches in order of appearance
52
+ *
53
+ * @param path - The route path string (e.g. "/groups/:group/users/:user")
54
+ * @returns An array of parameter names (e.g. ["group", "user"])
55
+ */
56
+ static extractParams(path$1) {
57
+ const regex = /:([^/]+)/g;
58
+ const params = [];
59
+ let match;
60
+ while ((match = regex.exec(path$1)) !== null) params.push(match[1]);
61
+ return params;
62
+ }
63
+ /**
64
+ * Resolves route model binding for a given path, HTTP context, and model.
65
+ *
66
+ * - Extracts all route parameters from the given path
67
+ * - If a parameter matches the model name, it attempts to resolve the model binding
68
+ * using the provided value and binding field (defaults to "id" unless specified).
69
+ * - For non-matching parameters, it simply returns the key-value pair as is.
70
+ * - If no parameters are found, returns an empty object.
71
+ *
72
+ * @param path - The route path (e.g. "/groups/:group/users/:user")
73
+ * @param ctx - The HTTP context containing the request
74
+ * @param model - The model instance to resolve bindings against
75
+ * @returns A resolved model instance or an object containing param values
76
+ */
77
+ static async resolveRouteModelBinding(path$1, ctx, model) {
78
+ const name = model.constructor.name.toLowerCase();
79
+ /**
80
+ * Extract field (defaults to 'id' if not specified after '|')
81
+ */
82
+ const field = name.split("|").at(1) ?? "id";
83
+ /**
84
+ * Iterate through extracted parameters from the path
85
+ */
86
+ for await (const e of Helpers.extractParams(path$1)) {
87
+ const value = ctx.request.params[e] ?? null;
88
+ if (e === name) return await model.resolveRouteBinding(value, field);
89
+ else return { [e]: ctx.request.params[e] ?? {} };
90
+ }
91
+ return {};
92
+ }
93
+ };
39
94
 
40
- // src/Providers/AssetsServiceProvider.ts
41
- var import_promises = require("fs/promises");
42
- var import_core = require("@h3ravel/core");
43
- var import_support = require("@h3ravel/support");
44
- var import_node_path = require("path");
45
- var import_h3 = require("h3");
46
- var import_node_fs = require("fs");
47
- var AssetsServiceProvider = class extends import_core.ServiceProvider {
48
- static {
49
- __name(this, "AssetsServiceProvider");
50
- }
51
- static priority = 996;
52
- register() {
53
- const app = this.app.make("router");
54
- const config = this.app.make("config");
55
- const fsconfig = config.get("filesystem");
56
- const publicPath = this.app.getPath("public");
57
- app.middleware(`/${fsconfig.public_mask}/**`, (event) => {
58
- return (0, import_h3.serveStatic)(event, {
59
- indexNames: [
60
- "/index.html"
61
- ],
62
- getContents: /* @__PURE__ */ __name((id) => {
63
- const newId = id.replace(`/${fsconfig.public_mask}/`, "");
64
- return (0, import_promises.readFile)((0, import_node_path.join)((0, import_support.before)(publicPath, newId), newId));
65
- }, "getContents"),
66
- getMeta: /* @__PURE__ */ __name(async (id) => {
67
- const newId = id.replace(`/${fsconfig.public_mask}/`, "");
68
- const stats = await (0, import_promises.stat)((0, import_node_path.join)((0, import_support.before)(publicPath, newId), newId)).catch(() => {
69
- });
70
- if (stats?.isFile()) {
71
- return {
72
- size: stats.size,
73
- mtime: stats.mtimeMs
74
- };
75
- }
76
- }, "getMeta")
77
- });
78
- });
79
- this.app.singleton("asset", () => {
80
- return (key, def = "") => {
81
- try {
82
- (0, import_node_fs.statSync)((0, import_node_path.join)((0, import_support.before)(publicPath, key), key));
83
- } catch {
84
- key = def;
85
- }
86
- return (0, import_node_path.join)(fsconfig.public_mask, key);
87
- };
88
- });
89
- }
95
+ //#endregion
96
+ //#region src/Providers/AssetsServiceProvider.ts
97
+ /**
98
+ * Handles public assets loading
99
+ *
100
+ * Auto-Registered
101
+ */
102
+ var AssetsServiceProvider = class extends __h3ravel_core.ServiceProvider {
103
+ static priority = 996;
104
+ register() {
105
+ const app = this.app.make("router");
106
+ const fsconfig = this.app.make("config").get("filesystem");
107
+ const publicPath = this.app.getPath("public");
108
+ app.middleware(`/${fsconfig.public_mask}/**`, (event) => {
109
+ return (0, h3.serveStatic)(event, {
110
+ indexNames: ["/index.html"],
111
+ getContents: (id) => {
112
+ const newId = id.replace(`/${fsconfig.public_mask}/`, "");
113
+ return (0, node_fs_promises.readFile)((0, node_path.join)((0, __h3ravel_support.before)(publicPath, newId), newId));
114
+ },
115
+ getMeta: async (id) => {
116
+ const newId = id.replace(`/${fsconfig.public_mask}/`, "");
117
+ const stats = await (0, node_fs_promises.stat)((0, node_path.join)((0, __h3ravel_support.before)(publicPath, newId), newId)).catch(() => {});
118
+ if (stats?.isFile()) return {
119
+ size: stats.size,
120
+ mtime: stats.mtimeMs
121
+ };
122
+ }
123
+ });
124
+ });
125
+ this.app.singleton("asset", () => {
126
+ return (key, def = "") => {
127
+ try {
128
+ (0, node_fs.statSync)((0, node_path.join)((0, __h3ravel_support.before)(publicPath, key), key));
129
+ } catch {
130
+ key = def;
131
+ }
132
+ return (0, node_path.join)(fsconfig.public_mask, key);
133
+ };
134
+ });
135
+ }
90
136
  };
91
137
 
92
- // src/Route.ts
93
- var import_reflect_metadata = require("reflect-metadata");
94
- var import_core2 = require("@h3ravel/core");
95
- var import_http = require("@h3ravel/http");
96
- var import_support2 = require("@h3ravel/support");
97
- var import_shared = require("@h3ravel/shared");
138
+ //#endregion
139
+ //#region src/Route.ts
98
140
  var Router = class {
99
- static {
100
- __name(this, "Router");
101
- }
102
- h3App;
103
- app;
104
- routes = [];
105
- nameMap = [];
106
- groupPrefix = "";
107
- middlewareMap = [];
108
- groupMiddleware = [];
109
- constructor(h3App, app) {
110
- this.h3App = h3App;
111
- this.app = app;
112
- }
113
- /**
114
- * Route Resolver
115
- *
116
- * @param handler
117
- * @param middleware
118
- * @returns
119
- */
120
- resolveHandler(handler, middleware = []) {
121
- return async (event) => {
122
- const kernel = new import_core2.Kernel(() => import_shared.HttpContext.init({
123
- app: this.app,
124
- request: new import_http.Request(event, this.app),
125
- response: new import_http.Response(event, this.app)
126
- }), middleware);
127
- return kernel.handle(event, (ctx) => Promise.resolve(handler(ctx)));
128
- };
129
- }
130
- /**
131
- * Add a route to the stack
132
- *
133
- * @param method
134
- * @param path
135
- * @param handler
136
- * @param name
137
- * @param middleware
138
- */
139
- addRoute(method, path2, handler, name, middleware = []) {
140
- if (this.nameMap.length > 0) {
141
- name = this.nameMap.join(".");
142
- }
143
- if (this.middlewareMap.length > 0) {
144
- middleware = this.middlewareMap;
145
- }
146
- const fullPath = `${this.groupPrefix}${path2}`.replace(/\/+/g, "/");
147
- this.routes.push({
148
- method,
149
- path: fullPath,
150
- name,
151
- handler
152
- });
153
- this.h3App[method](fullPath, this.resolveHandler(handler, middleware));
154
- }
155
- /**
156
- * Resolves a route handler definition into an executable EventHandler.
157
- *
158
- * A handler can be:
159
- * - A function matching the EventHandler signature
160
- * - A controller class (optionally decorated for IoC resolution)
161
- *
162
- * If it’s a controller class, this method will:
163
- * - Instantiate it (via IoC or manually)
164
- * - Call the specified method (defaults to `index`)
165
- *
166
- * @param handler Event handler function OR controller class
167
- * @param methodName Method to invoke on the controller (defaults to 'index')
168
- */
169
- resolveControllerOrHandler(handler, methodName) {
170
- if (typeof handler === "function" && typeof handler.prototype !== "undefined") {
171
- return (_ctx) => {
172
- let controller;
173
- if (import_core2.Container.hasAnyDecorator(handler)) {
174
- controller = this.app.make(handler);
175
- } else {
176
- controller = new handler(this.app);
177
- }
178
- const action = methodName || "index";
179
- if (typeof controller[action] !== "function") {
180
- throw new Error(`Method "${String(action)}" not found on controller ${handler.name}`);
181
- }
182
- const paramTypes = Reflect.getMetadata("design:paramtypes", controller, action) || [];
183
- let args = paramTypes.map((paramType) => {
184
- switch (paramType?.name) {
185
- case "Application":
186
- return this.app;
187
- case "Request":
188
- return _ctx.request;
189
- case "Response":
190
- return _ctx.response;
191
- case "HttpContext":
192
- return _ctx;
193
- default:
194
- return this.app.make(paramType);
195
- }
196
- });
197
- if (args.length < 1) {
198
- args = [
199
- _ctx
200
- ];
201
- }
202
- return controller[action](...args);
203
- };
204
- }
205
- return handler;
206
- }
207
- /**
208
- * Registers a route that responds to HTTP GET requests.
209
- *
210
- * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
211
- * @param definition Either:
212
- * - An EventHandler function
213
- * - A tuple: [ControllerClass, methodName]
214
- * @param name Optional route name (for URL generation or referencing).
215
- * @param middleware Optional array of middleware functions to execute before the handler.
216
- */
217
- get(path2, definition, name, middleware = []) {
218
- const handler = Array.isArray(definition) ? definition[0] : definition;
219
- const methodName = Array.isArray(definition) ? definition[1] : void 0;
220
- this.addRoute("get", path2, this.resolveControllerOrHandler(handler, methodName), name, middleware);
221
- return this;
222
- }
223
- /**
224
- * Registers a route that responds to HTTP POST requests.
225
- *
226
- * @param path The URL pattern to match (can include parameters, e.g., '/users').
227
- * @param definition Either:
228
- * - An EventHandler function
229
- * - A tuple: [ControllerClass, methodName]
230
- * @param name Optional route name (for URL generation or referencing).
231
- * @param middleware Optional array of middleware functions to execute before the handler.
232
- */
233
- post(path2, definition, name, middleware = []) {
234
- const handler = Array.isArray(definition) ? definition[0] : definition;
235
- const methodName = Array.isArray(definition) ? definition[1] : void 0;
236
- this.addRoute("post", path2, this.resolveControllerOrHandler(handler, methodName), name, middleware);
237
- return this;
238
- }
239
- /**
240
- * Registers a route that responds to HTTP PUT requests.
241
- *
242
- * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
243
- * @param definition Either:
244
- * - An EventHandler function
245
- * - A tuple: [ControllerClass, methodName]
246
- * @param name Optional route name (for URL generation or referencing).
247
- * @param middleware Optional array of middleware functions to execute before the handler.
248
- */
249
- put(path2, definition, name, middleware = []) {
250
- const handler = Array.isArray(definition) ? definition[0] : definition;
251
- const methodName = Array.isArray(definition) ? definition[1] : void 0;
252
- this.addRoute("put", path2, this.resolveControllerOrHandler(handler, methodName), name, middleware);
253
- return this;
254
- }
255
- /**
256
- * Registers a route that responds to HTTP PATCH requests.
257
- *
258
- * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
259
- * @param definition Either:
260
- * - An EventHandler function
261
- * - A tuple: [ControllerClass, methodName]
262
- * @param name Optional route name (for URL generation or referencing).
263
- * @param middleware Optional array of middleware functions to execute before the handler.
264
- */
265
- patch(path2, definition, name, middleware = []) {
266
- const handler = Array.isArray(definition) ? definition[0] : definition;
267
- const methodName = Array.isArray(definition) ? definition[1] : void 0;
268
- this.addRoute("patch", path2, this.resolveControllerOrHandler(handler, methodName), name, middleware);
269
- return this;
270
- }
271
- /**
272
- * Registers a route that responds to HTTP DELETE requests.
273
- *
274
- * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
275
- * @param definition Either:
276
- * - An EventHandler function
277
- * - A tuple: [ControllerClass, methodName]
278
- * @param name Optional route name (for URL generation or referencing).
279
- * @param middleware Optional array of middleware functions to execute before the handler.
280
- */
281
- delete(path2, definition, name, middleware = []) {
282
- const handler = Array.isArray(definition) ? definition[0] : definition;
283
- const methodName = Array.isArray(definition) ? definition[1] : void 0;
284
- this.addRoute("delete", path2, this.resolveControllerOrHandler(handler, methodName), name, middleware);
285
- return this;
286
- }
287
- /**
288
- * API Resource support
289
- *
290
- * @param path
291
- * @param controller
292
- */
293
- apiResource(path2, Controller, middleware = []) {
294
- path2 = path2.replace(/\//g, "/");
295
- const basePath = `/${path2}`.replace(/\/+$/, "").replace(/(\/)+/g, "$1");
296
- const name = basePath.substring(basePath.lastIndexOf("/") + 1).replaceAll(/\/|:/g, "") || "";
297
- const param = (0, import_support2.singularize)(name);
298
- this.get(basePath, [
299
- Controller,
300
- "index"
301
- ], `${name}.index`, middleware);
302
- this.post(basePath, [
303
- Controller,
304
- "store"
305
- ], `${name}.store`, middleware);
306
- this.get(`${basePath}/:${param}`, [
307
- Controller,
308
- "show"
309
- ], `${name}.show`, middleware);
310
- this.put(`${basePath}/:${param}`, [
311
- Controller,
312
- "update"
313
- ], `${name}.update`, middleware);
314
- this.patch(`${basePath}/:${param}`, [
315
- Controller,
316
- "update"
317
- ], `${name}.update`, middleware);
318
- this.delete(`${basePath}/:${param}`, [
319
- Controller,
320
- "destroy"
321
- ], `${name}.destroy`, middleware);
322
- return this;
323
- }
324
- /**
325
- * Named route URL generator
326
- *
327
- * @param name
328
- * @param params
329
- * @returns
330
- */
331
- route(name, params = {}) {
332
- const found = this.routes.find((r) => r.name === name);
333
- if (!found) return void 0;
334
- let url = found.path;
335
- for (const [key, value] of Object.entries(params)) {
336
- url = url.replace(`:${key}`, value);
337
- }
338
- return url;
339
- }
340
- /**
341
- * Grouping
342
- *
343
- * @param options
344
- * @param callback
345
- */
346
- group(options, callback) {
347
- const prevPrefix = this.groupPrefix;
348
- const prevMiddleware = [
349
- ...this.groupMiddleware
350
- ];
351
- this.groupPrefix += options.prefix || "";
352
- this.groupMiddleware.push(...options.middleware || []);
353
- callback(this);
354
- this.groupPrefix = prevPrefix;
355
- this.groupMiddleware = prevMiddleware;
356
- return this;
357
- }
358
- /**
359
- * Set the name of the current route
360
- *
361
- * @param name
362
- */
363
- name(name) {
364
- this.nameMap.push(name);
365
- return this;
366
- }
367
- /**
368
- * Registers middleware for a specific path.
369
- * @param path - The path to apply the middleware.
370
- * @param handler - The middleware handler.
371
- * @param opts - Optional middleware options.
372
- */
373
- middleware(path2, handler, opts) {
374
- if (typeof path2 === "string") {
375
- this.h3App.use(path2, handler, opts);
376
- } else {
377
- this.middlewareMap.concat(path2);
378
- }
379
- return this;
380
- }
141
+ routes = [];
142
+ nameMap = [];
143
+ groupPrefix = "";
144
+ middlewareMap = [];
145
+ groupMiddleware = [];
146
+ constructor(h3App, app) {
147
+ this.h3App = h3App;
148
+ this.app = app;
149
+ }
150
+ /**
151
+ * Route Resolver
152
+ *
153
+ * @param handler
154
+ * @param middleware
155
+ * @returns
156
+ */
157
+ resolveHandler(handler, middleware = []) {
158
+ return async (event) => {
159
+ return new __h3ravel_core.Kernel(() => __h3ravel_shared.HttpContext.init({
160
+ app: this.app,
161
+ request: new __h3ravel_http.Request(event, this.app),
162
+ response: new __h3ravel_http.Response(event, this.app)
163
+ }), middleware).handle(event, (ctx) => Promise.resolve(handler(ctx)));
164
+ };
165
+ }
166
+ /**
167
+ * Add a route to the stack
168
+ *
169
+ * @param method
170
+ * @param path
171
+ * @param handler
172
+ * @param name
173
+ * @param middleware
174
+ */
175
+ addRoute(method, path$1, handler, name, middleware = []) {
176
+ /**
177
+ * Join all defined route names to make a single route name
178
+ */
179
+ if (this.nameMap.length > 0) name = this.nameMap.join(".");
180
+ /**
181
+ * Join all defined middlewares
182
+ */
183
+ if (this.middlewareMap.length > 0) middleware = this.middlewareMap;
184
+ const fullPath = `${this.groupPrefix}${path$1}`.replace(/\/+/g, "/");
185
+ this.routes.push({
186
+ method,
187
+ path: fullPath,
188
+ name,
189
+ handler
190
+ });
191
+ this.h3App[method](fullPath, this.resolveHandler(handler, middleware));
192
+ }
193
+ /**
194
+ * Resolves a route handler definition into an executable EventHandler.
195
+ *
196
+ * A handler can be:
197
+ * - A function matching the EventHandler signature
198
+ * - A controller class (optionally decorated for IoC resolution)
199
+ *
200
+ * If it’s a controller class, this method will:
201
+ * - Instantiate it (via IoC or manually)
202
+ * - Call the specified method (defaults to `index`)
203
+ *
204
+ * @param handler Event handler function OR controller class
205
+ * @param methodName Method to invoke on the controller (defaults to 'index')
206
+ */
207
+ resolveControllerOrHandler(handler, methodName, path$1) {
208
+ /**
209
+ * Checks if the handler is a function (either a plain function or a class constructor)
210
+ */
211
+ if (typeof handler === "function" && typeof handler.prototype !== "undefined") return async (ctx) => {
212
+ let controller;
213
+ if (__h3ravel_core.Container.hasAnyDecorator(handler))
214
+ /**
215
+ * If the controller is decorated use the IoC container
216
+ */
217
+ controller = this.app.make(handler);
218
+ else
219
+ /**
220
+ * Otherwise instantiate manually so that we can at least
221
+ * pass the app instance
222
+ */
223
+ controller = new handler(this.app);
224
+ /**
225
+ * The method to execute (defaults to 'index')
226
+ */
227
+ const action = methodName || "index";
228
+ /**
229
+ * Ensure the method exists on the controller
230
+ */
231
+ if (typeof controller[action] !== "function") throw new Error(`Method "${String(action)}" not found on controller ${handler.name}`);
232
+ /**
233
+ * Get param types for the controller method
234
+ */
235
+ const paramTypes = Reflect.getMetadata("design:paramtypes", controller, action) || [];
236
+ /**
237
+ * Resolve the bound dependencies
238
+ */
239
+ let args = await Promise.all(paramTypes.map(async (paramType) => {
240
+ switch (paramType?.name) {
241
+ case "Application": return this.app;
242
+ case "Request": return ctx.request;
243
+ case "Response": return ctx.response;
244
+ case "HttpContext": return ctx;
245
+ default: {
246
+ const inst = this.app.make(paramType);
247
+ if (inst instanceof __h3ravel_database.Model) return await Helpers.resolveRouteModelBinding(path$1 ?? "", ctx, inst);
248
+ return inst;
249
+ }
250
+ }
251
+ }));
252
+ /**
253
+ * Ensure that the HttpContext is always available
254
+ */
255
+ if (args.length < 1) args = [ctx];
256
+ /**
257
+ * Call the controller method, passing all resolved dependencies
258
+ */
259
+ return await controller[action](...args);
260
+ };
261
+ return handler;
262
+ }
263
+ /**
264
+ * Registers a route that responds to HTTP GET requests.
265
+ *
266
+ * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
267
+ * @param definition Either:
268
+ * - An EventHandler function
269
+ * - A tuple: [ControllerClass, methodName]
270
+ * @param name Optional route name (for URL generation or referencing).
271
+ * @param middleware Optional array of middleware functions to execute before the handler.
272
+ */
273
+ get(path$1, definition, name, middleware = []) {
274
+ const handler = Array.isArray(definition) ? definition[0] : definition;
275
+ const methodName = Array.isArray(definition) ? definition[1] : void 0;
276
+ this.addRoute("get", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
277
+ return this;
278
+ }
279
+ /**
280
+ * Registers a route that responds to HTTP POST requests.
281
+ *
282
+ * @param path The URL pattern to match (can include parameters, e.g., '/users').
283
+ * @param definition Either:
284
+ * - An EventHandler function
285
+ * - A tuple: [ControllerClass, methodName]
286
+ * @param name Optional route name (for URL generation or referencing).
287
+ * @param middleware Optional array of middleware functions to execute before the handler.
288
+ */
289
+ post(path$1, definition, name, middleware = []) {
290
+ const handler = Array.isArray(definition) ? definition[0] : definition;
291
+ const methodName = Array.isArray(definition) ? definition[1] : void 0;
292
+ this.addRoute("post", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
293
+ return this;
294
+ }
295
+ /**
296
+ * Registers a route that responds to HTTP PUT requests.
297
+ *
298
+ * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
299
+ * @param definition Either:
300
+ * - An EventHandler function
301
+ * - A tuple: [ControllerClass, methodName]
302
+ * @param name Optional route name (for URL generation or referencing).
303
+ * @param middleware Optional array of middleware functions to execute before the handler.
304
+ */
305
+ put(path$1, definition, name, middleware = []) {
306
+ const handler = Array.isArray(definition) ? definition[0] : definition;
307
+ const methodName = Array.isArray(definition) ? definition[1] : void 0;
308
+ this.addRoute("put", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
309
+ return this;
310
+ }
311
+ /**
312
+ * Registers a route that responds to HTTP PATCH requests.
313
+ *
314
+ * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
315
+ * @param definition Either:
316
+ * - An EventHandler function
317
+ * - A tuple: [ControllerClass, methodName]
318
+ * @param name Optional route name (for URL generation or referencing).
319
+ * @param middleware Optional array of middleware functions to execute before the handler.
320
+ */
321
+ patch(path$1, definition, name, middleware = []) {
322
+ const handler = Array.isArray(definition) ? definition[0] : definition;
323
+ const methodName = Array.isArray(definition) ? definition[1] : void 0;
324
+ this.addRoute("patch", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
325
+ return this;
326
+ }
327
+ /**
328
+ * Registers a route that responds to HTTP DELETE requests.
329
+ *
330
+ * @param path The URL pattern to match (can include parameters, e.g., '/users/:id').
331
+ * @param definition Either:
332
+ * - An EventHandler function
333
+ * - A tuple: [ControllerClass, methodName]
334
+ * @param name Optional route name (for URL generation or referencing).
335
+ * @param middleware Optional array of middleware functions to execute before the handler.
336
+ */
337
+ delete(path$1, definition, name, middleware = []) {
338
+ const handler = Array.isArray(definition) ? definition[0] : definition;
339
+ const methodName = Array.isArray(definition) ? definition[1] : void 0;
340
+ this.addRoute("delete", path$1, this.resolveControllerOrHandler(handler, methodName, path$1), name, middleware);
341
+ return this;
342
+ }
343
+ /**
344
+ * API Resource support
345
+ *
346
+ * @param path
347
+ * @param controller
348
+ */
349
+ apiResource(path$1, Controller, middleware = []) {
350
+ path$1 = path$1.replace(/\//g, "/");
351
+ const basePath = `/${path$1}`.replace(/\/+$/, "").replace(/(\/)+/g, "$1");
352
+ const name = basePath.substring(basePath.lastIndexOf("/") + 1).replaceAll(/\/|:/g, "") || "";
353
+ const param = (0, __h3ravel_support.singularize)(name);
354
+ this.get(basePath, [Controller, "index"], `${name}.index`, middleware);
355
+ this.post(basePath, [Controller, "store"], `${name}.store`, middleware);
356
+ this.get(`${basePath}/:${param}`, [Controller, "show"], `${name}.show`, middleware);
357
+ this.put(`${basePath}/:${param}`, [Controller, "update"], `${name}.update`, middleware);
358
+ this.patch(`${basePath}/:${param}`, [Controller, "update"], `${name}.update`, middleware);
359
+ this.delete(`${basePath}/:${param}`, [Controller, "destroy"], `${name}.destroy`, middleware);
360
+ return this;
361
+ }
362
+ /**
363
+ * Named route URL generator
364
+ *
365
+ * @param name
366
+ * @param params
367
+ * @returns
368
+ */
369
+ route(name, params = {}) {
370
+ const found = this.routes.find((r) => r.name === name);
371
+ if (!found) return void 0;
372
+ let url = found.path;
373
+ for (const [key, value] of Object.entries(params)) url = url.replace(`:${key}`, value);
374
+ return url;
375
+ }
376
+ /**
377
+ * Grouping
378
+ *
379
+ * @param options
380
+ * @param callback
381
+ */
382
+ group(options, callback) {
383
+ const prevPrefix = this.groupPrefix;
384
+ const prevMiddleware = [...this.groupMiddleware];
385
+ this.groupPrefix += options.prefix || "";
386
+ this.groupMiddleware.push(...options.middleware || []);
387
+ callback(this);
388
+ /**
389
+ * Restore state after group
390
+ */
391
+ this.groupPrefix = prevPrefix;
392
+ this.groupMiddleware = prevMiddleware;
393
+ return this;
394
+ }
395
+ /**
396
+ * Set the name of the current route
397
+ *
398
+ * @param name
399
+ */
400
+ name(name) {
401
+ this.nameMap.push(name);
402
+ return this;
403
+ }
404
+ /**
405
+ * Registers middleware for a specific path.
406
+ * @param path - The path to apply the middleware.
407
+ * @param handler - The middleware handler.
408
+ * @param opts - Optional middleware options.
409
+ */
410
+ middleware(path$1, handler, opts) {
411
+ if (typeof path$1 === "string") this.h3App.use(path$1, handler, opts);
412
+ else this.middlewareMap.concat(path$1);
413
+ return this;
414
+ }
381
415
  };
382
416
 
383
- // src/Providers/RouteServiceProvider.ts
384
- var import_core3 = require("@h3ravel/core");
385
- var import_node_path2 = __toESM(require("path"), 1);
386
- var import_promises2 = require("fs/promises");
387
- var RouteServiceProvider = class extends import_core3.ServiceProvider {
388
- static {
389
- __name(this, "RouteServiceProvider");
390
- }
391
- static priority = 997;
392
- register() {
393
- this.app.singleton("router", () => {
394
- const h3App = this.app.make("http.app");
395
- return new Router(h3App, this.app);
396
- });
397
- }
398
- /**
399
- * Load routes from src/routes
400
- */
401
- async boot() {
402
- try {
403
- const routePath = this.app.getPath("routes");
404
- const files = (await (0, import_promises2.readdir)(routePath)).filter((e) => {
405
- return !e.includes(".d.ts") && !e.includes(".map");
406
- });
407
- for (let i = 0; i < files.length; i++) {
408
- const routesModule = await import(import_node_path2.default.join(routePath, files[i]));
409
- if (typeof routesModule.default === "function") {
410
- const router = this.app.make("router");
411
- routesModule.default(router);
412
- }
413
- }
414
- } catch (e) {
415
- console.warn("No web routes found or failed to load:", e);
416
- }
417
- }
417
+ //#endregion
418
+ //#region src/Providers/RouteServiceProvider.ts
419
+ /**
420
+ * Handles routing registration
421
+ *
422
+ * Load route files (web.ts, api.ts).
423
+ * Map controllers to routes.
424
+ * Register route-related middleware.
425
+ *
426
+ * Auto-Registered
427
+ */
428
+ var RouteServiceProvider = class extends __h3ravel_core.ServiceProvider {
429
+ static priority = 997;
430
+ register() {
431
+ this.app.singleton("router", () => {
432
+ const h3App = this.app.make("http.app");
433
+ return new Router(h3App, this.app);
434
+ });
435
+ }
436
+ /**
437
+ * Load routes from src/routes
438
+ */
439
+ async boot() {
440
+ try {
441
+ const routePath = this.app.getPath("routes");
442
+ const files = (await (0, node_fs_promises.readdir)(routePath)).filter((e) => {
443
+ return !e.includes(".d.ts") && !e.includes(".d.cts") && !e.includes(".map");
444
+ });
445
+ for (let i = 0; i < files.length; i++) {
446
+ const routesModule = await import(node_path.default.join(routePath, files[i]));
447
+ if (typeof routesModule.default === "function") {
448
+ const router = this.app.make("router");
449
+ routesModule.default(router);
450
+ }
451
+ }
452
+ } catch (e) {
453
+ console.warn("No web routes found or failed to load:", e);
454
+ }
455
+ }
418
456
  };
419
- // Annotate the CommonJS export names for ESM import in node:
420
- 0 && (module.exports = {
421
- AssetsServiceProvider,
422
- RouteServiceProvider,
423
- Router
424
- });
457
+
458
+ //#endregion
459
+ exports.AssetsServiceProvider = AssetsServiceProvider;
460
+ exports.Helpers = Helpers;
461
+ exports.RouteServiceProvider = RouteServiceProvider;
462
+ exports.Router = Router;
425
463
  //# sourceMappingURL=index.cjs.map