@adonisjs/http-server 8.0.0-next.7 → 8.0.0-next.9

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.
@@ -0,0 +1,1222 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // src/helpers.ts
8
+ import cookie from "cookie";
9
+ import matchit from "@poppinss/matchit";
10
+ import string3 from "@poppinss/utils/string";
11
+ import { parseBindingReference } from "@adonisjs/fold";
12
+
13
+ // src/utils.ts
14
+ import Cache from "tmp-cache";
15
+ import { InvalidArgumentsException } from "@poppinss/utils/exception";
16
+
17
+ // src/router/group.ts
18
+ import Macroable4 from "@poppinss/macroable";
19
+
20
+ // src/router/brisk.ts
21
+ import Macroable2 from "@poppinss/macroable";
22
+
23
+ // src/router/route.ts
24
+ import is from "@sindresorhus/is";
25
+ import Macroable from "@poppinss/macroable";
26
+ import Middleware from "@poppinss/middleware";
27
+ import { RuntimeException } from "@poppinss/utils/exception";
28
+ import { moduleCaller, moduleImporter } from "@adonisjs/fold";
29
+
30
+ // src/debug.ts
31
+ import { debuglog } from "util";
32
+ var debug_default = debuglog("adonisjs:http");
33
+
34
+ // src/router/factories/use_return_value.ts
35
+ function canWriteResponseBody(value, ctx) {
36
+ return value !== void 0 && // Return value is explicitly defined
37
+ !ctx.response.hasLazyBody && // Lazy body is not set
38
+ value !== ctx.response;
39
+ }
40
+ function useReturnValue(ctx) {
41
+ return function(value) {
42
+ if (canWriteResponseBody(value, ctx)) {
43
+ ctx.response.send(value);
44
+ }
45
+ };
46
+ }
47
+
48
+ // src/tracing_channels.ts
49
+ var tracing_channels_exports = {};
50
+ __export(tracing_channels_exports, {
51
+ httpExceptionHandler: () => httpExceptionHandler,
52
+ httpMiddleware: () => httpMiddleware,
53
+ httpRequest: () => httpRequest,
54
+ httpResponseSerializer: () => httpResponseSerializer,
55
+ httpRouteHandler: () => httpRouteHandler
56
+ });
57
+ import diagnostics_channel from "diagnostics_channel";
58
+ var httpRequest = diagnostics_channel.tracingChannel("adonisjs.http.request");
59
+ var httpMiddleware = diagnostics_channel.tracingChannel("adonisjs.http.middleware");
60
+ var httpExceptionHandler = diagnostics_channel.tracingChannel(
61
+ "adonisjs.http.exception.handler"
62
+ );
63
+ var httpRouteHandler = diagnostics_channel.tracingChannel("adonisjs.http.route.handler");
64
+ var httpResponseSerializer = diagnostics_channel.tracingChannel(
65
+ "adonisjs.http.response.serializer"
66
+ );
67
+
68
+ // src/router/executor.ts
69
+ function execute(route, resolver, ctx, errorResponder) {
70
+ return route.middleware.runner().errorHandler((error) => errorResponder(error, ctx)).finalHandler(() => {
71
+ if (typeof route.handler === "function") {
72
+ return httpRouteHandler.tracePromise(
73
+ ($ctx) => Promise.resolve(route.handler($ctx)),
74
+ httpRouteHandler.hasSubscribers ? { route } : void 0,
75
+ void 0,
76
+ ctx
77
+ ).then(useReturnValue(ctx));
78
+ }
79
+ return httpRouteHandler.tracePromise(
80
+ route.handler.handle,
81
+ httpRouteHandler.hasSubscribers ? { route } : void 0,
82
+ void 0,
83
+ resolver,
84
+ ctx
85
+ ).then(useReturnValue(ctx));
86
+ }).run(async (middleware, next) => {
87
+ if (typeof middleware === "function") {
88
+ return httpMiddleware.tracePromise(
89
+ middleware,
90
+ httpMiddleware.hasSubscribers ? { middleware } : void 0,
91
+ void 0,
92
+ ctx,
93
+ next
94
+ );
95
+ }
96
+ return httpMiddleware.tracePromise(
97
+ middleware.handle,
98
+ httpMiddleware.hasSubscribers ? { middleware } : void 0,
99
+ void 0,
100
+ resolver,
101
+ ctx,
102
+ next,
103
+ middleware.args
104
+ );
105
+ });
106
+ }
107
+
108
+ // src/router/route.ts
109
+ import StringBuilder from "@poppinss/utils/string_builder";
110
+ import string from "@poppinss/utils/string";
111
+ var Route = class extends Macroable {
112
+ /**
113
+ * Route pattern
114
+ */
115
+ #pattern;
116
+ /**
117
+ * HTTP Methods for the route
118
+ */
119
+ #methods;
120
+ /**
121
+ * A unique name for the route
122
+ */
123
+ #name;
124
+ /**
125
+ * A boolean to prevent route from getting registered within
126
+ * the store.
127
+ *
128
+ * This flag must be set before "Router.commit" method
129
+ */
130
+ #isDeleted = false;
131
+ /**
132
+ * Route handler
133
+ */
134
+ #handler;
135
+ /**
136
+ * Matchers inherited from the router
137
+ */
138
+ #globalMatchers;
139
+ /**
140
+ * Reference to the AdonisJS application
141
+ */
142
+ #app;
143
+ /**
144
+ * Middleware registered on the router
145
+ */
146
+ #routerMiddleware;
147
+ /**
148
+ * By default the route is part of the `root` domain. Root domain is used
149
+ * when no domain is defined
150
+ */
151
+ #routeDomain = "root";
152
+ /**
153
+ * An object of matchers to be forwarded to the store. The matchers
154
+ * list is populated by calling `where` method
155
+ */
156
+ #matchers = {};
157
+ /**
158
+ * Custom prefixes defined on the route or the route parent
159
+ * groups
160
+ */
161
+ #prefixes = [];
162
+ /**
163
+ * Middleware defined directly on the route or the route parent
164
+ * routes. We mantain an array for each layer of the stack
165
+ */
166
+ #middleware = [];
167
+ /**
168
+ * Creates a new Route instance
169
+ * @param app - The AdonisJS application instance
170
+ * @param routerMiddleware - Array of global middleware registered on the router
171
+ * @param options - Configuration options for the route
172
+ */
173
+ constructor(app, routerMiddleware, options) {
174
+ super();
175
+ this.#app = app;
176
+ this.#routerMiddleware = routerMiddleware;
177
+ this.#pattern = options.pattern;
178
+ this.#methods = options.methods;
179
+ this.#globalMatchers = options.globalMatchers;
180
+ const { handler, routeName } = this.#resolveRouteHandle(options.handler);
181
+ this.#handler = handler;
182
+ this.#name = routeName;
183
+ }
184
+ /**
185
+ * Resolves the route handler string expression to a
186
+ * handler method object
187
+ */
188
+ #resolveRouteHandle(handler) {
189
+ if (typeof handler === "string") {
190
+ const parts = handler.split(".");
191
+ const method = parts.length === 1 ? "handle" : parts.pop();
192
+ const moduleRefId = parts.join(".");
193
+ return {
194
+ handler: {
195
+ method,
196
+ reference: handler,
197
+ importExpression: moduleRefId,
198
+ ...moduleImporter(() => this.#app.import(moduleRefId), method).toHandleMethod(),
199
+ name: handler
200
+ },
201
+ routeName: `${new StringBuilder(moduleRefId.split("/").pop()).removeSuffix("controller").snakeCase()}.${string.snakeCase(method)}`
202
+ };
203
+ }
204
+ if (Array.isArray(handler)) {
205
+ const controller = handler[0];
206
+ const method = handler[1] ?? "handle";
207
+ if (is.class(controller)) {
208
+ return {
209
+ handler: {
210
+ method,
211
+ reference: handler,
212
+ importExpression: null,
213
+ ...moduleCaller(controller, method).toHandleMethod()
214
+ },
215
+ routeName: `${new StringBuilder(controller.name).removeSuffix("controller").snakeCase()}.${string.snakeCase(method)}`
216
+ };
217
+ }
218
+ return {
219
+ handler: {
220
+ method,
221
+ reference: handler,
222
+ importExpression: String(controller),
223
+ ...moduleImporter(controller, method).toHandleMethod()
224
+ },
225
+ routeName: controller.name ? `${new StringBuilder(controller.name).removeSuffix("controller").snakeCase()}.${string.snakeCase(method)}` : void 0
226
+ };
227
+ }
228
+ return { handler };
229
+ }
230
+ /**
231
+ * Returns an object of param matchers by merging global and local
232
+ * matchers. The local copy is given preference over the global
233
+ * one's
234
+ */
235
+ #getMatchers() {
236
+ return { ...this.#globalMatchers, ...this.#matchers };
237
+ }
238
+ /**
239
+ * Returns a normalized pattern string by prefixing the `prefix` (if defined).
240
+ */
241
+ #computePattern() {
242
+ const pattern = dropSlash(this.#pattern);
243
+ const prefix = this.#prefixes.slice().reverse().map((one) => dropSlash(one)).join("");
244
+ return prefix ? `${prefix}${pattern === "/" ? "" : pattern}` : pattern;
245
+ }
246
+ /**
247
+ * Define matcher for a given param. If a matcher exists, then we do not
248
+ * override that, since the routes inside a group will set matchers
249
+ * before the group, so they should have priority over the group
250
+ * matchers.
251
+ *
252
+ * ```ts
253
+ * Route.group(() => {
254
+ * Route.get('/:id', 'handler').where('id', /^[0-9]$/)
255
+ * }).where('id', /[^a-z$]/)
256
+ * ```
257
+ *
258
+ * The `/^[0-9]$/` will win over the matcher defined by the group
259
+ */
260
+ where(param, matcher) {
261
+ if (this.#matchers[param]) {
262
+ return this;
263
+ }
264
+ if (typeof matcher === "string") {
265
+ this.#matchers[param] = { match: new RegExp(matcher) };
266
+ } else if (is.regExp(matcher)) {
267
+ this.#matchers[param] = { match: matcher };
268
+ } else {
269
+ this.#matchers[param] = matcher;
270
+ }
271
+ return this;
272
+ }
273
+ /**
274
+ * Define prefix for the route. Calling this method multiple times
275
+ * applies multiple prefixes in the reverse order.
276
+ * @param prefix - The prefix to add to the route
277
+ * @returns Current Route instance for method chaining
278
+ */
279
+ prefix(prefix) {
280
+ this.#prefixes.push(prefix);
281
+ return this;
282
+ }
283
+ /**
284
+ * Define a custom domain for the route. We do not overwrite the domain
285
+ * unless `overwrite` flag is set to true.
286
+ */
287
+ domain(domain, overwrite = false) {
288
+ if (this.#routeDomain === "root" || overwrite) {
289
+ this.#routeDomain = domain;
290
+ }
291
+ return this;
292
+ }
293
+ /**
294
+ * Define one or more middleware to be executed before the route
295
+ * handler.
296
+ *
297
+ * Named middleware can be referenced using the name registered with
298
+ * the router middleware store.
299
+ */
300
+ use(middleware) {
301
+ this.#middleware.push(Array.isArray(middleware) ? middleware : [middleware]);
302
+ return this;
303
+ }
304
+ /**
305
+ * Alias for {@link Route.use}
306
+ */
307
+ middleware(middleware) {
308
+ return this.use(middleware);
309
+ }
310
+ /**
311
+ * Give a unique name to the route. Assinging a new unique removes the
312
+ * existing name of the route.
313
+ *
314
+ * Setting prepends to true prefixes the name to the existing name.
315
+ */
316
+ as(name, prepend = false) {
317
+ if (prepend) {
318
+ if (!this.#name) {
319
+ throw new RuntimeException(
320
+ `Routes inside a group must have names before calling "router.group.as"`
321
+ );
322
+ }
323
+ this.#name = `${name}.${this.#name}`;
324
+ return this;
325
+ }
326
+ this.#name = name;
327
+ return this;
328
+ }
329
+ /**
330
+ * Check if the route was marked to be deleted
331
+ */
332
+ isDeleted() {
333
+ return this.#isDeleted;
334
+ }
335
+ /**
336
+ * Mark route as deleted. Deleted routes are not registered
337
+ * with the route store
338
+ */
339
+ markAsDeleted() {
340
+ this.#isDeleted = true;
341
+ }
342
+ /**
343
+ * Get the route name
344
+ */
345
+ getName() {
346
+ return this.#name;
347
+ }
348
+ /**
349
+ * Get the route pattern
350
+ */
351
+ getPattern() {
352
+ return this.#pattern;
353
+ }
354
+ /**
355
+ * Set the route pattern
356
+ */
357
+ setPattern(pattern) {
358
+ this.#pattern = pattern;
359
+ return this;
360
+ }
361
+ /**
362
+ * Returns the stack of middleware registered on the route.
363
+ * The value is shared by reference.
364
+ */
365
+ getMiddleware() {
366
+ return this.#middleware;
367
+ }
368
+ /**
369
+ * Returns the middleware instance for persistence inside the
370
+ * store
371
+ */
372
+ #getMiddlewareForStore() {
373
+ const middleware = new Middleware();
374
+ this.#routerMiddleware.forEach((one) => {
375
+ debug_default("adding global middleware to route %s, %O", this.#pattern, one);
376
+ middleware.add(one);
377
+ });
378
+ this.#middleware.flat().forEach((one) => {
379
+ debug_default("adding named middleware to route %s, %O", this.#pattern, one);
380
+ middleware.add(one);
381
+ });
382
+ middleware.freeze();
383
+ return middleware;
384
+ }
385
+ /**
386
+ * Returns JSON representation of the route
387
+ */
388
+ toJSON() {
389
+ const pattern = this.#computePattern();
390
+ const matchers = this.#getMatchers();
391
+ return {
392
+ domain: this.#routeDomain,
393
+ pattern,
394
+ matchers,
395
+ tokens: parseRoute(pattern, matchers),
396
+ meta: {},
397
+ name: this.#name,
398
+ handler: this.#handler,
399
+ methods: this.#methods,
400
+ middleware: this.#getMiddlewareForStore(),
401
+ execute
402
+ };
403
+ }
404
+ };
405
+
406
+ // src/router/brisk.ts
407
+ var BriskRoute = class extends Macroable2 {
408
+ /**
409
+ * Route pattern
410
+ */
411
+ #pattern;
412
+ /**
413
+ * Matchers inherited from the router
414
+ */
415
+ #globalMatchers;
416
+ /**
417
+ * Reference to the AdonisJS application
418
+ */
419
+ #app;
420
+ /**
421
+ * Middleware registered on the router
422
+ */
423
+ #routerMiddleware;
424
+ /**
425
+ * Reference to route instance. Set after `setHandler` is called
426
+ */
427
+ route = null;
428
+ /**
429
+ * Creates a new BriskRoute instance
430
+ * @param app - The AdonisJS application instance
431
+ * @param routerMiddleware - Array of global middleware registered on the router
432
+ * @param options - Configuration options for the brisk route
433
+ */
434
+ constructor(app, routerMiddleware, options) {
435
+ super();
436
+ this.#app = app;
437
+ this.#routerMiddleware = routerMiddleware;
438
+ this.#pattern = options.pattern;
439
+ this.#globalMatchers = options.globalMatchers;
440
+ }
441
+ /**
442
+ * Set handler for the brisk route
443
+ * @param handler - The route handler function
444
+ * @returns The created route instance
445
+ */
446
+ setHandler(handler) {
447
+ this.route = new Route(this.#app, this.#routerMiddleware, {
448
+ pattern: this.#pattern,
449
+ globalMatchers: this.#globalMatchers,
450
+ methods: ["GET", "HEAD"],
451
+ handler
452
+ });
453
+ return this.route;
454
+ }
455
+ /**
456
+ * Redirects to a given route. Params from the original request will
457
+ * be used when no custom params are defined.
458
+ * @param args - Route identifier, parameters, and options for building the redirect URL
459
+ * @returns The created route instance
460
+ */
461
+ redirect(...args) {
462
+ const [identifier, params, options] = args;
463
+ function redirectsToRoute(ctx) {
464
+ const redirector = ctx.response.redirect();
465
+ if (options?.status) {
466
+ redirector.status(options.status);
467
+ }
468
+ return redirector.toRoute(identifier, params || ctx.params, options);
469
+ }
470
+ Object.defineProperty(redirectsToRoute, "listArgs", { value: identifier, writable: false });
471
+ return this.setHandler(redirectsToRoute);
472
+ }
473
+ /**
474
+ * Redirect request to a fixed URL
475
+ * @param url - The URL to redirect to
476
+ * @param options - Optional redirect options including HTTP status code
477
+ * @returns The created route instance
478
+ */
479
+ redirectToPath(url, options) {
480
+ function redirectsToPath(ctx) {
481
+ const redirector = ctx.response.redirect();
482
+ if (options?.status) {
483
+ redirector.status(options.status);
484
+ }
485
+ return redirector.toPath(url);
486
+ }
487
+ Object.defineProperty(redirectsToPath, "listArgs", { value: url, writable: false });
488
+ return this.setHandler(redirectsToPath);
489
+ }
490
+ };
491
+
492
+ // src/router/resource.ts
493
+ import string2 from "@poppinss/utils/string";
494
+ import Macroable3 from "@poppinss/macroable";
495
+ import { RuntimeException as RuntimeException2 } from "@poppinss/utils/exception";
496
+ var RouteResource = class extends Macroable3 {
497
+ /**
498
+ * Resource identifier. Nested resources are separated
499
+ * with a dot notation
500
+ */
501
+ #resource;
502
+ /**
503
+ * The controller to handle resource routing requests
504
+ */
505
+ #controller;
506
+ /**
507
+ * Is it a shallow resource? Shallow resources URLs do not have parent
508
+ * resource name and id once they can be identified with the id.
509
+ */
510
+ #shallow = false;
511
+ /**
512
+ * Matchers inherited from the router
513
+ */
514
+ #globalMatchers;
515
+ /**
516
+ * Reference to the AdonisJS application
517
+ */
518
+ #app;
519
+ /**
520
+ * Middleware registered on the router
521
+ */
522
+ #routerMiddleware;
523
+ /**
524
+ * Parameter names for the resources. Defaults to `id` for
525
+ * a singular resource and `resource_id` for nested
526
+ * resources.
527
+ */
528
+ #params = {};
529
+ /**
530
+ * Base name for the routes. We suffix action names
531
+ * on top of the base name
532
+ */
533
+ #routesBaseName;
534
+ /**
535
+ * A collection of routes instances that belongs to this resource
536
+ */
537
+ routes = [];
538
+ /**
539
+ * Creates a new RouteResource instance
540
+ * @param app - The AdonisJS application instance
541
+ * @param routerMiddleware - Array of global middleware registered on the router
542
+ * @param options - Configuration options for the route resource
543
+ */
544
+ constructor(app, routerMiddleware, options) {
545
+ super();
546
+ this.#validateResourceName(options.resource);
547
+ this.#app = app;
548
+ this.#shallow = options.shallow;
549
+ this.#routerMiddleware = routerMiddleware;
550
+ this.#controller = options.controller;
551
+ this.#globalMatchers = options.globalMatchers;
552
+ this.#resource = this.#normalizeResourceName(options.resource);
553
+ this.#routesBaseName = this.#getRoutesBaseName();
554
+ this.#buildRoutes();
555
+ }
556
+ /**
557
+ * Normalizes the resource name to dropping leading and trailing
558
+ * slashes.
559
+ */
560
+ #normalizeResourceName(resource) {
561
+ return resource.replace(/^\//, "").replace(/\/$/, "");
562
+ }
563
+ /**
564
+ * Ensure resource name is not an empty string
565
+ */
566
+ #validateResourceName(resource) {
567
+ if (!resource || resource === "/") {
568
+ throw new RuntimeException2(`Invalid resource name "${resource}"`);
569
+ }
570
+ }
571
+ /**
572
+ * Converting segments of a resource to snake case to
573
+ * make the route name.
574
+ */
575
+ #getRoutesBaseName() {
576
+ return this.#resource.split(".").map((token) => string2.snakeCase(token)).join(".");
577
+ }
578
+ /**
579
+ * Create a new route for the given pattern, methods and controller action
580
+ */
581
+ #createRoute(pattern, methods, action) {
582
+ const route = new Route(this.#app, this.#routerMiddleware, {
583
+ pattern,
584
+ methods,
585
+ handler: typeof this.#controller === "string" ? `${this.#controller}.${action}` : [this.#controller, action],
586
+ globalMatchers: this.#globalMatchers
587
+ });
588
+ route.as(`${this.#routesBaseName}.${action}`);
589
+ this.routes.push(route);
590
+ }
591
+ /**
592
+ * Returns the `resource_id` name for a given resource. The
593
+ * resource name is converted to singular form and
594
+ * transformed to snake case.
595
+ *
596
+ * photos becomes photo_id
597
+ * users becomes user_id
598
+ */
599
+ #getResourceId(resource) {
600
+ return `${string2.snakeCase(string2.singular(resource))}_id`;
601
+ }
602
+ /**
603
+ * Build routes for the given resource
604
+ */
605
+ #buildRoutes() {
606
+ const resources = this.#resource.split(".");
607
+ const mainResource = resources.pop();
608
+ this.#params[mainResource] = ":id";
609
+ const baseURI = `${resources.map((resource) => {
610
+ const paramName = `:${this.#getResourceId(resource)}`;
611
+ this.#params[resource] = paramName;
612
+ return `${resource}/${paramName}`;
613
+ }).join("/")}/${mainResource}`;
614
+ this.#createRoute(baseURI, ["GET", "HEAD"], "index");
615
+ this.#createRoute(`${baseURI}/create`, ["GET", "HEAD"], "create");
616
+ this.#createRoute(baseURI, ["POST"], "store");
617
+ this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ["GET", "HEAD"], "show");
618
+ this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id/edit`, ["GET", "HEAD"], "edit");
619
+ this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ["PUT", "PATCH"], "update");
620
+ this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ["DELETE"], "destroy");
621
+ }
622
+ /**
623
+ * Filter the routes based on their partial names
624
+ */
625
+ #filter(names, inverse) {
626
+ const actions = Array.isArray(names) ? names : [names];
627
+ return this.routes.filter((route) => {
628
+ const match = actions.find((name) => route.getName().endsWith(name));
629
+ return inverse ? !match : match;
630
+ });
631
+ }
632
+ /**
633
+ * Register only given routes and remove others
634
+ * @param names - Array of action names to keep
635
+ * @returns Current RouteResource instance with filtered actions
636
+ */
637
+ only(names) {
638
+ this.#filter(names, true).forEach((route) => route.markAsDeleted());
639
+ return this;
640
+ }
641
+ /**
642
+ * Register all routes, except the one's defined
643
+ * @param names - Array of action names to exclude
644
+ * @returns Current RouteResource instance with filtered actions
645
+ */
646
+ except(names) {
647
+ this.#filter(names, false).forEach((route) => route.markAsDeleted());
648
+ return this;
649
+ }
650
+ /**
651
+ * Register api only routes. The `create` and `edit` routes, which
652
+ * are meant to show forms will not be registered
653
+ * @returns Current RouteResource instance without create and edit actions
654
+ */
655
+ apiOnly() {
656
+ return this.except(["create", "edit"]);
657
+ }
658
+ /**
659
+ * Define matcher for params inside the resource
660
+ * @param key - The parameter name to match
661
+ * @param matcher - The matcher pattern (RegExp, string, or RouteMatcher)
662
+ * @returns Current RouteResource instance for method chaining
663
+ */
664
+ where(key, matcher) {
665
+ this.routes.forEach((route) => {
666
+ route.where(key, matcher);
667
+ });
668
+ return this;
669
+ }
670
+ tap(actions, callback) {
671
+ if (typeof actions === "function") {
672
+ this.routes.forEach((route) => {
673
+ if (!route.isDeleted()) {
674
+ actions(route);
675
+ }
676
+ });
677
+ return this;
678
+ }
679
+ this.#filter(actions, false).forEach((route) => {
680
+ if (!route.isDeleted()) {
681
+ callback(route);
682
+ }
683
+ });
684
+ return this;
685
+ }
686
+ /**
687
+ * Set the param name for a given resource
688
+ * @param resources - Object mapping resource names to parameter names
689
+ * @returns Current RouteResource instance for method chaining
690
+ */
691
+ params(resources) {
692
+ Object.keys(resources).forEach((resource) => {
693
+ const param = resources[resource];
694
+ const existingParam = this.#params[resource];
695
+ this.#params[resource] = `:${param}`;
696
+ this.routes.forEach((route) => {
697
+ route.setPattern(
698
+ route.getPattern().replace(`${resource}/${existingParam}`, `${resource}/:${param}`)
699
+ );
700
+ });
701
+ });
702
+ return this;
703
+ }
704
+ /**
705
+ * Define one or more middleware on the routes created by
706
+ * the resource.
707
+ *
708
+ * Calling this method multiple times will append middleware
709
+ * to existing list.
710
+ * @param actions - Action name(s) or '*' for all actions
711
+ * @param middleware - Middleware function(s) to apply
712
+ * @returns Current RouteResource instance for method chaining
713
+ */
714
+ use(actions, middleware) {
715
+ if (actions === "*") {
716
+ this.tap((route) => route.use(middleware));
717
+ } else {
718
+ this.tap(actions, (route) => route.use(middleware));
719
+ }
720
+ return this;
721
+ }
722
+ /**
723
+ * Alias for {@link RouteResource.use}
724
+ * @param actions - Action name(s) or '*' for all actions
725
+ * @param middleware - Middleware function(s) to apply
726
+ * @returns Current RouteResource instance for method chaining
727
+ */
728
+ middleware(actions, middleware) {
729
+ return this.use(actions, middleware);
730
+ }
731
+ /**
732
+ * Prepend name to all the routes
733
+ * @param name - The name to prepend to all route names
734
+ * @param normalizeName - Whether to normalize the name to snake_case
735
+ * @returns Current RouteResource instance for method chaining
736
+ */
737
+ as(name, normalizeName = true) {
738
+ name = normalizeName ? string2.snakeCase(name) : name;
739
+ this.routes.forEach((route) => {
740
+ route.as(route.getName().replace(this.#routesBaseName, name), false);
741
+ });
742
+ this.#routesBaseName = name;
743
+ return this;
744
+ }
745
+ };
746
+
747
+ // src/router/group.ts
748
+ var RouteGroup = class _RouteGroup extends Macroable4 {
749
+ /**
750
+ * Creates a new RouteGroup instance
751
+ * @param routes - Array of routes that belong to this group
752
+ */
753
+ constructor(routes) {
754
+ super();
755
+ this.routes = routes;
756
+ }
757
+ /**
758
+ * Array of middleware registered on the group.
759
+ */
760
+ #middleware = [];
761
+ /**
762
+ * Shares midldeware stack with the routes. The method is invoked recursively
763
+ * to only register middleware with the route class and not with the
764
+ * resource or the child group
765
+ */
766
+ #shareMiddlewareStackWithRoutes(route) {
767
+ if (route instanceof _RouteGroup) {
768
+ route.routes.forEach((child) => this.#shareMiddlewareStackWithRoutes(child));
769
+ return;
770
+ }
771
+ if (route instanceof RouteResource) {
772
+ route.routes.forEach((child) => child.getMiddleware().unshift(this.#middleware));
773
+ return;
774
+ }
775
+ if (route instanceof BriskRoute) {
776
+ route.route.getMiddleware().unshift(this.#middleware);
777
+ return;
778
+ }
779
+ route.getMiddleware().unshift(this.#middleware);
780
+ }
781
+ /**
782
+ * Updates the route name. The method is invoked recursively to only update
783
+ * the name with the route class and not with the resource or the child
784
+ * group.
785
+ */
786
+ #updateRouteName(route, name) {
787
+ if (route instanceof _RouteGroup) {
788
+ route.routes.forEach((child) => this.#updateRouteName(child, name));
789
+ return;
790
+ }
791
+ if (route instanceof RouteResource) {
792
+ route.routes.forEach((child) => child.as(name, true));
793
+ return;
794
+ }
795
+ if (route instanceof BriskRoute) {
796
+ route.route.as(name, true);
797
+ return;
798
+ }
799
+ route.as(name, true);
800
+ }
801
+ /**
802
+ * Sets prefix on the route. The method is invoked recursively to only set
803
+ * the prefix with the route class and not with the resource or the
804
+ * child group.
805
+ */
806
+ #setRoutePrefix(route, prefix) {
807
+ if (route instanceof _RouteGroup) {
808
+ route.routes.forEach((child) => this.#setRoutePrefix(child, prefix));
809
+ return;
810
+ }
811
+ if (route instanceof RouteResource) {
812
+ route.routes.forEach((child) => child.prefix(prefix));
813
+ return;
814
+ }
815
+ if (route instanceof BriskRoute) {
816
+ route.route.prefix(prefix);
817
+ return;
818
+ }
819
+ route.prefix(prefix);
820
+ }
821
+ /**
822
+ * Updates domain on the route. The method is invoked recursively to only update
823
+ * the domain with the route class and not with the resource or the child
824
+ * group.
825
+ */
826
+ #updateRouteDomain(route, domain) {
827
+ if (route instanceof _RouteGroup) {
828
+ route.routes.forEach((child) => this.#updateRouteDomain(child, domain));
829
+ return;
830
+ }
831
+ if (route instanceof RouteResource) {
832
+ route.routes.forEach((child) => child.domain(domain));
833
+ return;
834
+ }
835
+ if (route instanceof BriskRoute) {
836
+ route.route.domain(domain, false);
837
+ return;
838
+ }
839
+ route.domain(domain, false);
840
+ }
841
+ /**
842
+ * Updates matchers on the route. The method is invoked recursively to only update
843
+ * the matchers with the route class and not with the resource or the child
844
+ * group.
845
+ */
846
+ #updateRouteMatchers(route, param, matcher) {
847
+ if (route instanceof _RouteGroup) {
848
+ route.routes.forEach((child) => this.#updateRouteMatchers(child, param, matcher));
849
+ return;
850
+ }
851
+ if (route instanceof RouteResource) {
852
+ route.routes.forEach((child) => child.where(param, matcher));
853
+ return;
854
+ }
855
+ if (route instanceof BriskRoute) {
856
+ route.route.where(param, matcher);
857
+ return;
858
+ }
859
+ route.where(param, matcher);
860
+ }
861
+ /**
862
+ * Define route param matcher
863
+ *
864
+ * ```ts
865
+ * Route.group(() => {
866
+ * }).where('id', /^[0-9]+/)
867
+ * ```
868
+ * @param param - The parameter name to match
869
+ * @param matcher - The matcher pattern (RegExp, string, or RouteMatcher)
870
+ * @returns Current RouteGroup instance for method chaining
871
+ */
872
+ where(param, matcher) {
873
+ this.routes.forEach((route) => this.#updateRouteMatchers(route, param, matcher));
874
+ return this;
875
+ }
876
+ /**
877
+ * Define prefix all the routes in the group.
878
+ *
879
+ * ```ts
880
+ * Route.group(() => {
881
+ * }).prefix('v1')
882
+ * ```
883
+ * @param prefix - The prefix to add to all routes in the group
884
+ * @returns Current RouteGroup instance for method chaining
885
+ */
886
+ prefix(prefix) {
887
+ this.routes.forEach((route) => this.#setRoutePrefix(route, prefix));
888
+ return this;
889
+ }
890
+ /**
891
+ * Define domain for all the routes.
892
+ *
893
+ * ```ts
894
+ * Route.group(() => {
895
+ * }).domain(':name.adonisjs.com')
896
+ * ```
897
+ * @param domain - The domain pattern for all routes in the group
898
+ * @returns Current RouteGroup instance for method chaining
899
+ */
900
+ domain(domain) {
901
+ this.routes.forEach((route) => this.#updateRouteDomain(route, domain));
902
+ return this;
903
+ }
904
+ /**
905
+ * Prepend name to the routes name.
906
+ *
907
+ * ```ts
908
+ * Route.group(() => {
909
+ * }).as('version1')
910
+ * ```
911
+ * @param name - The name to prepend to all route names in the group
912
+ * @returns Current RouteGroup instance for method chaining
913
+ */
914
+ as(name) {
915
+ this.routes.forEach((route) => this.#updateRouteName(route, name));
916
+ return this;
917
+ }
918
+ /**
919
+ * Prepend an array of middleware to all routes middleware.
920
+ *
921
+ * ```ts
922
+ * Route.group(() => {
923
+ * }).use(middleware.auth())
924
+ * ```
925
+ * @param middleware - Middleware function(s) to apply to all routes in the group
926
+ * @returns Current RouteGroup instance for method chaining
927
+ */
928
+ use(middleware) {
929
+ if (!this.#middleware.length) {
930
+ this.routes.forEach((route) => this.#shareMiddlewareStackWithRoutes(route));
931
+ }
932
+ if (Array.isArray(middleware)) {
933
+ for (let one of middleware) {
934
+ this.#middleware.push(one);
935
+ }
936
+ } else {
937
+ this.#middleware.push(middleware);
938
+ }
939
+ return this;
940
+ }
941
+ /**
942
+ * Alias for {@link RouteGroup.use}
943
+ * @param middleware - Middleware function(s) to apply to all routes in the group
944
+ * @returns Current RouteGroup instance for method chaining
945
+ */
946
+ middleware(middleware) {
947
+ return this.use(middleware);
948
+ }
949
+ };
950
+
951
+ // src/utils.ts
952
+ var proxyCache = new Cache({ max: 200 });
953
+ function dropSlash(input) {
954
+ if (input === "/") {
955
+ return "/";
956
+ }
957
+ return `/${input.replace(/^\//, "").replace(/\/$/, "")}`;
958
+ }
959
+ function toRoutesJSON(routes) {
960
+ return routes.reduce((list, route) => {
961
+ if (route instanceof RouteGroup) {
962
+ list = list.concat(toRoutesJSON(route.routes));
963
+ return list;
964
+ }
965
+ if (route instanceof RouteResource) {
966
+ list = list.concat(toRoutesJSON(route.routes));
967
+ return list;
968
+ }
969
+ if (route instanceof BriskRoute) {
970
+ if (route.route && !route.route.isDeleted()) {
971
+ list.push(route.route.toJSON());
972
+ }
973
+ return list;
974
+ }
975
+ if (!route.isDeleted()) {
976
+ list.push(route.toJSON());
977
+ }
978
+ return list;
979
+ }, []);
980
+ }
981
+ function trustProxy(remoteAddress, proxyFn) {
982
+ if (proxyCache.has(remoteAddress)) {
983
+ return proxyCache.get(remoteAddress);
984
+ }
985
+ const result = proxyFn(remoteAddress, 0);
986
+ proxyCache.set(remoteAddress, result);
987
+ return result;
988
+ }
989
+ function parseRange(range, value) {
990
+ const parts = range.split("..");
991
+ const min = Number(parts[0]);
992
+ const max = Number(parts[1]);
993
+ if (parts.length === 1 && !Number.isNaN(min)) {
994
+ return {
995
+ [min]: value
996
+ };
997
+ }
998
+ if (Number.isNaN(min) || Number.isNaN(max)) {
999
+ return {};
1000
+ }
1001
+ if (min === max) {
1002
+ return {
1003
+ [min]: value
1004
+ };
1005
+ }
1006
+ if (max < min) {
1007
+ throw new InvalidArgumentsException(`Invalid range "${range}"`);
1008
+ }
1009
+ return [...Array(max - min + 1).keys()].reduce(
1010
+ (result, step) => {
1011
+ result[min + step] = value;
1012
+ return result;
1013
+ },
1014
+ {}
1015
+ );
1016
+ }
1017
+ function decodeComponentChar(highCharCode, lowCharCode) {
1018
+ if (highCharCode === 50) {
1019
+ if (lowCharCode === 53) return "%";
1020
+ if (lowCharCode === 51) return "#";
1021
+ if (lowCharCode === 52) return "$";
1022
+ if (lowCharCode === 54) return "&";
1023
+ if (lowCharCode === 66) return "+";
1024
+ if (lowCharCode === 98) return "+";
1025
+ if (lowCharCode === 67) return ",";
1026
+ if (lowCharCode === 99) return ",";
1027
+ if (lowCharCode === 70) return "/";
1028
+ if (lowCharCode === 102) return "/";
1029
+ return null;
1030
+ }
1031
+ if (highCharCode === 51) {
1032
+ if (lowCharCode === 65) return ":";
1033
+ if (lowCharCode === 97) return ":";
1034
+ if (lowCharCode === 66) return ";";
1035
+ if (lowCharCode === 98) return ";";
1036
+ if (lowCharCode === 68) return "=";
1037
+ if (lowCharCode === 100) return "=";
1038
+ if (lowCharCode === 70) return "?";
1039
+ if (lowCharCode === 102) return "?";
1040
+ return null;
1041
+ }
1042
+ if (highCharCode === 52 && lowCharCode === 48) {
1043
+ return "@";
1044
+ }
1045
+ return null;
1046
+ }
1047
+ function safeDecodeURI(path, useSemicolonDelimiter) {
1048
+ let shouldDecode = false;
1049
+ let shouldDecodeParam = false;
1050
+ let querystring = "";
1051
+ for (let i = 1; i < path.length; i++) {
1052
+ const charCode = path.charCodeAt(i);
1053
+ if (charCode === 37) {
1054
+ const highCharCode = path.charCodeAt(i + 1);
1055
+ const lowCharCode = path.charCodeAt(i + 2);
1056
+ if (decodeComponentChar(highCharCode, lowCharCode) === null) {
1057
+ shouldDecode = true;
1058
+ } else {
1059
+ shouldDecodeParam = true;
1060
+ if (highCharCode === 50 && lowCharCode === 53) {
1061
+ shouldDecode = true;
1062
+ path = path.slice(0, i + 1) + "25" + path.slice(i + 1);
1063
+ i += 2;
1064
+ }
1065
+ i += 2;
1066
+ }
1067
+ } else if (charCode === 63 || charCode === 35 || charCode === 59 && useSemicolonDelimiter) {
1068
+ querystring = path.slice(i + 1);
1069
+ path = path.slice(0, i);
1070
+ break;
1071
+ }
1072
+ }
1073
+ const decodedPath = shouldDecode ? decodeURI(path) : path;
1074
+ return { pathname: decodedPath, query: querystring, shouldDecodeParam };
1075
+ }
1076
+
1077
+ // src/helpers.ts
1078
+ import { default as default2 } from "encodeurl";
1079
+ import { default as default3 } from "mime-types";
1080
+ function parseRoute(pattern, matchers) {
1081
+ const tokens = matchit.parse(pattern, matchers);
1082
+ return tokens;
1083
+ }
1084
+ function createURL(pattern, tokens, searchParamsStringifier, params, options) {
1085
+ const uriSegments = [];
1086
+ const paramsArray = Array.isArray(params) ? params : null;
1087
+ const paramsObject = !Array.isArray(params) ? params ?? {} : {};
1088
+ let paramsIndex = 0;
1089
+ for (const token of tokens) {
1090
+ if (token.type === 0) {
1091
+ uriSegments.push(token.val === "/" ? "" : `${token.val}${token.end}`);
1092
+ continue;
1093
+ }
1094
+ if (token.type === 2) {
1095
+ const values = paramsArray ? paramsArray.slice(paramsIndex) : paramsObject["*"];
1096
+ if (!Array.isArray(values) || !values.length) {
1097
+ throw new Error(
1098
+ `Cannot make URL for "${pattern}". Invalid value provided for the wildcard param`
1099
+ );
1100
+ }
1101
+ uriSegments.push(`${values.join("/")}${token.end}`);
1102
+ break;
1103
+ }
1104
+ const paramName = token.val;
1105
+ const value = paramsArray ? paramsArray[paramsIndex] : paramsObject[paramName];
1106
+ const isDefined = value !== void 0 && value !== null;
1107
+ if (token.type === 1 && !isDefined) {
1108
+ throw new Error(
1109
+ `Cannot make URL for "${pattern}". Missing value for the "${paramName}" param`
1110
+ );
1111
+ }
1112
+ if (isDefined) {
1113
+ uriSegments.push(`${value}${token.end}`);
1114
+ }
1115
+ paramsIndex++;
1116
+ }
1117
+ let URI = `/${uriSegments.join("/")}`;
1118
+ if (options?.prefixUrl) {
1119
+ URI = `${options?.prefixUrl.replace(/\/$/, "")}${URI}`;
1120
+ }
1121
+ if (options?.qs) {
1122
+ const queryString = searchParamsStringifier(options?.qs);
1123
+ URI = queryString ? `${URI}?${queryString}` : URI;
1124
+ }
1125
+ return URI;
1126
+ }
1127
+ function createSignedURL(identifier, tokens, searchParamsStringifier, encryption, params, options) {
1128
+ const signature = encryption.verifier.sign(
1129
+ createURL(identifier, tokens, searchParamsStringifier, params, {
1130
+ ...options,
1131
+ prefixUrl: void 0
1132
+ }),
1133
+ options?.expiresIn,
1134
+ options?.purpose
1135
+ );
1136
+ return createURL(identifier, tokens, searchParamsStringifier, params, {
1137
+ ...options,
1138
+ qs: { ...options?.qs, signature }
1139
+ });
1140
+ }
1141
+ function matchRoute(url, patterns) {
1142
+ const tokensBucket = patterns.map((pattern) => parseRoute(pattern));
1143
+ const match = matchit.match(url, tokensBucket);
1144
+ if (!match.length) {
1145
+ return null;
1146
+ }
1147
+ return matchit.exec(url, match);
1148
+ }
1149
+ function serializeCookie(key, value, options) {
1150
+ let expires;
1151
+ let maxAge;
1152
+ if (options) {
1153
+ expires = typeof options.expires === "function" ? options.expires() : options.expires;
1154
+ maxAge = options.maxAge ? string3.seconds.parse(options.maxAge) : void 0;
1155
+ }
1156
+ return cookie.serialize(key, value, { ...options, maxAge, expires });
1157
+ }
1158
+ async function middlewareInfo(middleware) {
1159
+ if (typeof middleware === "function") {
1160
+ return {
1161
+ type: "closure",
1162
+ name: middleware.name || "closure"
1163
+ };
1164
+ }
1165
+ if ("args" in middleware) {
1166
+ return {
1167
+ type: "named",
1168
+ name: middleware.name,
1169
+ args: middleware.args,
1170
+ ...await parseBindingReference([middleware.reference])
1171
+ };
1172
+ }
1173
+ return {
1174
+ type: "global",
1175
+ name: middleware.name,
1176
+ ...await parseBindingReference([middleware.reference])
1177
+ };
1178
+ }
1179
+ async function routeInfo(route) {
1180
+ return "reference" in route.handler ? {
1181
+ type: "controller",
1182
+ ...await parseBindingReference(route.handler.reference)
1183
+ } : {
1184
+ type: "closure",
1185
+ name: route.handler.name || "closure",
1186
+ args: "listArgs" in route.handler ? String(route.handler.listArgs) : void 0
1187
+ };
1188
+ }
1189
+ function appendQueryString(uri, queryString, qsParser) {
1190
+ const { query, pathname } = safeDecodeURI(uri, false);
1191
+ const mergedQueryString = qsParser.stringify(Object.assign(qsParser.parse(query), queryString));
1192
+ return mergedQueryString ? `${pathname}?${mergedQueryString}` : pathname;
1193
+ }
1194
+
1195
+ export {
1196
+ __export,
1197
+ debug_default,
1198
+ canWriteResponseBody,
1199
+ httpRequest,
1200
+ httpMiddleware,
1201
+ httpExceptionHandler,
1202
+ httpResponseSerializer,
1203
+ tracing_channels_exports,
1204
+ parseRoute,
1205
+ createURL,
1206
+ createSignedURL,
1207
+ matchRoute,
1208
+ serializeCookie,
1209
+ middlewareInfo,
1210
+ routeInfo,
1211
+ appendQueryString,
1212
+ default2 as default,
1213
+ default3 as default2,
1214
+ Route,
1215
+ BriskRoute,
1216
+ RouteResource,
1217
+ RouteGroup,
1218
+ toRoutesJSON,
1219
+ trustProxy,
1220
+ parseRange,
1221
+ safeDecodeURI
1222
+ };