clear-router 2.8.8 → 2.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.
Files changed (42) hide show
  1. package/dist/Route.cjs +200 -12
  2. package/dist/Route.d.cts +125 -1
  3. package/dist/Route.d.mts +125 -1
  4. package/dist/Route.mjs +199 -12
  5. package/dist/RouteGroup.cjs +2 -1
  6. package/dist/RouteGroup.mjs +2 -1
  7. package/dist/RouteRegistrar.cjs +68 -0
  8. package/dist/RouteRegistrar.d.cts +62 -0
  9. package/dist/RouteRegistrar.d.mts +62 -0
  10. package/dist/RouteRegistrar.mjs +67 -0
  11. package/dist/core/CoreRouter.cjs +307 -0
  12. package/dist/core/CoreRouter.d.cts +168 -0
  13. package/dist/core/CoreRouter.d.mts +168 -0
  14. package/dist/core/CoreRouter.mjs +307 -0
  15. package/dist/decorators/setup.d.mts +0 -1
  16. package/dist/express/router.cjs +13 -4
  17. package/dist/express/router.d.cts +1 -0
  18. package/dist/express/router.d.mts +1 -0
  19. package/dist/express/router.mjs +13 -4
  20. package/dist/fastify/router.cjs +13 -4
  21. package/dist/fastify/router.d.cts +1 -0
  22. package/dist/fastify/router.d.mts +1 -0
  23. package/dist/fastify/router.mjs +13 -4
  24. package/dist/h3/router.cjs +13 -4
  25. package/dist/h3/router.d.cts +1 -0
  26. package/dist/h3/router.d.mts +1 -0
  27. package/dist/h3/router.mjs +13 -4
  28. package/dist/hono/router.cjs +11 -4
  29. package/dist/hono/router.d.cts +1 -0
  30. package/dist/hono/router.d.mts +1 -0
  31. package/dist/hono/router.mjs +11 -4
  32. package/dist/index.cjs +3 -0
  33. package/dist/index.d.cts +3 -2
  34. package/dist/index.d.mts +3 -2
  35. package/dist/index.mjs +3 -2
  36. package/dist/koa/router.cjs +13 -4
  37. package/dist/koa/router.d.cts +1 -0
  38. package/dist/koa/router.d.mts +1 -0
  39. package/dist/koa/router.mjs +13 -4
  40. package/dist/types/basic.d.cts +2 -0
  41. package/dist/types/basic.d.mts +2 -0
  42. package/package.json +2 -2
package/dist/Route.mjs CHANGED
@@ -1,11 +1,39 @@
1
1
  //#region src/Route.ts
2
2
  /**
3
+ * Parse the placeholder parameters declared in a domain/host pattern such as
4
+ * `{account}.example.com`. Mirrors the path parameter syntax (supporting the
5
+ * optional `{name?}` form) so domain parameters feel consistent with path ones.
6
+ *
7
+ * @param pattern
8
+ * @returns
9
+ */
10
+ const parseDomainParameters = (pattern) => {
11
+ if (!pattern) return [];
12
+ const parameters = [];
13
+ const seen = /* @__PURE__ */ new Set();
14
+ const matcher = /\{([^{}]+)\}/g;
15
+ let match;
16
+ while ((match = matcher.exec(pattern)) !== null) {
17
+ const raw = match[1].trim();
18
+ const optional = raw.endsWith("?");
19
+ const [name, field] = (optional ? raw.slice(0, -1) : raw).split(":", 2).map((part) => part.trim());
20
+ if (!name || seen.has(name)) continue;
21
+ seen.add(name);
22
+ parameters.push({
23
+ name,
24
+ field: field || void 0,
25
+ optional
26
+ });
27
+ }
28
+ return parameters;
29
+ };
30
+ /**
3
31
  * @class clear-router Route
4
32
  * @description A route describes a single enpoint on clear-router
5
33
  * @author 3m1n3nc3
6
34
  * @repository https://github.com/arkstack-hq/clear-router
7
35
  */
8
- var Route = class {
36
+ var Route = class Route {
9
37
  ctx;
10
38
  body = {};
11
39
  query = {};
@@ -22,6 +50,9 @@ var Route = class {
22
50
  actionName;
23
51
  handlerType;
24
52
  middlewareCount;
53
+ domainPattern;
54
+ domainParameters;
55
+ constraints = {};
25
56
  constructor(methods, path, handler, middlewares = [], options = {}) {
26
57
  this.methods = methods;
27
58
  this.path = path;
@@ -33,16 +64,65 @@ var Route = class {
33
64
  this.middlewareCount = middlewares.length;
34
65
  this.controllerName = Array.isArray(handler) ? handler[0]?.name : void 0;
35
66
  this.actionName = Array.isArray(handler) ? handler[1] : typeof handler === "function" ? handler.constructor.name ?? handler.name : void 0;
67
+ this.domainPattern = options.domain;
68
+ this.domainParameters = parseDomainParameters(options.domain);
36
69
  this.onName = options.onName;
37
70
  this.normalizeMiddleware = options.normalizeMiddleware;
38
71
  }
39
72
  onName;
40
73
  normalizeMiddleware;
74
+ static currentResolvers;
75
+ /**
76
+ * Wire the resolvers used by the static `current*` accessors. Called once by
77
+ * `CoreRouter` so `Route.current()` reflects the active request.
78
+ *
79
+ * @internal
80
+ * @param resolvers
81
+ */
82
+ static bindCurrentResolvers(resolvers) {
83
+ Route.currentResolvers = resolvers;
84
+ }
85
+ /**
86
+ * Get the route currently being dispatched, if any.
87
+ *
88
+ * @returns
89
+ */
90
+ static current() {
91
+ return Route.currentResolvers?.current();
92
+ }
93
+ /**
94
+ * Get the name of the route currently being dispatched.
95
+ *
96
+ * @returns
97
+ */
98
+ static currentRouteName() {
99
+ return Route.currentResolvers?.currentRouteName() ?? "";
100
+ }
101
+ /**
102
+ * Get the action (controller@method or `Closure`) of the route currently
103
+ * being dispatched.
104
+ *
105
+ * @returns
106
+ */
107
+ static currentRouteAction() {
108
+ return Route.currentResolvers?.currentRouteAction() ?? "";
109
+ }
110
+ /**
111
+ * The route action expressed as `Controller@method` for controller routes or
112
+ * `Closure` for callback routes.
113
+ */
114
+ get action() {
115
+ if (this.handlerType === "controller") {
116
+ const method = String(this.actionName ?? "");
117
+ return this.controllerName ? `${this.controllerName}@${method}` : method;
118
+ }
119
+ return "Closure";
120
+ }
41
121
  /**
42
122
  * Set the route name
43
- *
44
- * @param name
45
- * @returns
123
+ *
124
+ * @param name
125
+ * @returns
46
126
  */
47
127
  name(name) {
48
128
  const previousName = this.routeName;
@@ -51,10 +131,96 @@ var Route = class {
51
131
  return this;
52
132
  }
53
133
  /**
134
+ * Constrain the route to a host pattern such as `{account}.example.com`.
135
+ * Any `{placeholder}` segments are exposed as route parameters once matched.
136
+ *
137
+ * @param pattern
138
+ * @returns
139
+ */
140
+ domain(pattern) {
141
+ this.domainPattern = pattern;
142
+ this.domainParameters = parseDomainParameters(pattern);
143
+ return this;
144
+ }
145
+ /**
146
+ * Constrain one or more route parameters with a regular expression. Accepts
147
+ * either `where(name, pattern)` or `where({ name: pattern, ... })`.
148
+ *
149
+ * @param name
150
+ * @param pattern
151
+ * @returns
152
+ */
153
+ where(name, pattern) {
154
+ if (typeof name === "object") Object.assign(this.constraints, name);
155
+ else if (typeof pattern !== "undefined") this.constraints[name] = pattern;
156
+ return this;
157
+ }
158
+ /**
159
+ * Constrain the given parameters to numeric values.
160
+ *
161
+ * @param names
162
+ * @returns
163
+ */
164
+ whereNumber(...names) {
165
+ return this.applyConstraint(names, "[0-9]+");
166
+ }
167
+ /**
168
+ * Constrain the given parameters to alphabetic values.
169
+ *
170
+ * @param names
171
+ * @returns
172
+ */
173
+ whereAlpha(...names) {
174
+ return this.applyConstraint(names, "[a-zA-Z]+");
175
+ }
176
+ /**
177
+ * Constrain the given parameters to alphanumeric values.
178
+ *
179
+ * @param names
180
+ * @returns
181
+ */
182
+ whereAlphaNumeric(...names) {
183
+ return this.applyConstraint(names, "[a-zA-Z0-9]+");
184
+ }
185
+ /**
186
+ * Constrain the given parameters to UUID values.
187
+ *
188
+ * @param names
189
+ * @returns
190
+ */
191
+ whereUuid(...names) {
192
+ return this.applyConstraint(names, "[\\da-fA-F]{8}-[\\da-fA-F]{4}-[\\da-fA-F]{4}-[\\da-fA-F]{4}-[\\da-fA-F]{12}");
193
+ }
194
+ /**
195
+ * Constrain the given parameters to ULID values.
196
+ *
197
+ * @param names
198
+ * @returns
199
+ */
200
+ whereUlid(...names) {
201
+ return this.applyConstraint(names, "[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}");
202
+ }
203
+ /**
204
+ * Constrain a parameter to one of the given values.
205
+ *
206
+ * @param name
207
+ * @param values
208
+ * @returns
209
+ */
210
+ whereIn(name, values) {
211
+ const escaped = values.map((value) => String(value).replace(/[.*+?^${}()|[\]\\]/g, (match) => `\\${match}`));
212
+ this.constraints[name] = escaped.join("|");
213
+ return this;
214
+ }
215
+ applyConstraint(names, pattern) {
216
+ for (const name of names) this.constraints[name] = pattern;
217
+ return this;
218
+ }
219
+ /**
54
220
  * Register one or more middleware that will be executed before the route.
55
- *
56
- * @param middlewares
57
- * @returns
221
+ *
222
+ * @param middlewares
223
+ * @returns
58
224
  */
59
225
  middleware(middlewares) {
60
226
  const normalized = (Array.isArray(middlewares) ? middlewares : [middlewares]).map((middleware) => this.normalizeMiddleware?.(middleware) ?? middleware);
@@ -63,13 +229,32 @@ var Route = class {
63
229
  return this;
64
230
  }
65
231
  /**
232
+ * Resolve the route's domain pattern into a concrete host using the given
233
+ * parameters.
234
+ *
235
+ * @param params
236
+ * @returns
237
+ */
238
+ resolveDomainHost(params) {
239
+ return this.domainPattern.replace(/\{([^{}]+)\}/g, (_, raw) => {
240
+ const optional = raw.endsWith("?");
241
+ const name = (optional ? raw.slice(0, -1) : raw).split(":", 2)[0].trim();
242
+ const value = params[name];
243
+ if (typeof value === "undefined" || value === null || value === "") {
244
+ if (optional) return "";
245
+ throw new Error(`Missing required route domain parameter: ${name}`);
246
+ }
247
+ return encodeURIComponent(String(value));
248
+ });
249
+ }
250
+ /**
66
251
  * Get the path generated and accessible by this route
67
- *
68
- * @param params
69
- * @returns
252
+ *
253
+ * @param params
254
+ * @returns
70
255
  */
71
256
  toPath(params = {}) {
72
- return this.path.replace(/\/?\{([^{}]+)\}/g, (segment, raw) => {
257
+ const resolved = this.path.replace(/\/?\{([^{}]+)\}/g, (segment, raw) => {
73
258
  const optional = raw.endsWith("?");
74
259
  const [rawName, rawField] = (optional ? raw.slice(0, -1) : raw).split(":", 2);
75
260
  const name = rawName.trim();
@@ -82,8 +267,10 @@ var Route = class {
82
267
  }
83
268
  return `${segment.startsWith("/") ? "/" : ""}${encodeURIComponent(String(resolved))}`;
84
269
  }) || "/";
270
+ if (!this.domainPattern) return resolved;
271
+ return `//${this.resolveDomainHost(params)}${resolved}`;
85
272
  }
86
273
  };
87
274
 
88
275
  //#endregion
89
- export { Route };
276
+ export { Route, parseDomainParameters };
@@ -69,6 +69,7 @@ var RouteGroup = class {
69
69
  const nextContext = {
70
70
  prefix: this.options.normalizePath(fullPrefix),
71
71
  groupMiddlewares: [...previousMiddlewares, ...this.options.middlewares || []],
72
+ domain: this.options.domain ?? current?.domain,
72
73
  routeCollectors: [...current?.routeCollectors ?? [], this.routes]
73
74
  };
74
75
  await this.options.context.run(nextContext, async () => {
@@ -140,7 +141,7 @@ var RouteGroup = class {
140
141
  for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
141
142
  const path = (0, node_path.join)(directory, entry.name);
142
143
  if (entry.isDirectory()) files.push(...await this.readDirectory(path));
143
- else if (entry.isFile() && /\.(?:[cm]?ts)$/.test(entry.name) && !entry.name.endsWith(".d.ts")) files.push(path);
144
+ else if (entry.isFile() && /\.(?:[cm]?[jt]s)$/.test(entry.name) && !entry.name.endsWith(".d.ts")) files.push(path);
144
145
  }
145
146
  return files;
146
147
  }
@@ -69,6 +69,7 @@ var RouteGroup = class {
69
69
  const nextContext = {
70
70
  prefix: this.options.normalizePath(fullPrefix),
71
71
  groupMiddlewares: [...previousMiddlewares, ...this.options.middlewares || []],
72
+ domain: this.options.domain ?? current?.domain,
72
73
  routeCollectors: [...current?.routeCollectors ?? [], this.routes]
73
74
  };
74
75
  await this.options.context.run(nextContext, async () => {
@@ -140,7 +141,7 @@ var RouteGroup = class {
140
141
  for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
141
142
  const path = join(directory, entry.name);
142
143
  if (entry.isDirectory()) files.push(...await this.readDirectory(path));
143
- else if (entry.isFile() && /\.(?:[cm]?ts)$/.test(entry.name) && !entry.name.endsWith(".d.ts")) files.push(path);
144
+ else if (entry.isFile() && /\.(?:[cm]?[jt]s)$/.test(entry.name) && !entry.name.endsWith(".d.ts")) files.push(path);
144
145
  }
145
146
  return files;
146
147
  }
@@ -0,0 +1,68 @@
1
+
2
+ //#region src/RouteRegistrar.ts
3
+ /**
4
+ * @class clear-router RouteRegistrar
5
+ * @description Fluent builder returned by `Router.domain()` that lets routes be
6
+ * grouped under a shared host pattern (and optionally a prefix/middlewares),
7
+ * mirroring Laravel's route attribute registrar.
8
+ * @author 3m1n3nc3
9
+ * @repository https://github.com/arkstack-hq/clear-router
10
+ */
11
+ var RouteRegistrar = class {
12
+ attributes;
13
+ constructor(makeGroup, attributes = {}) {
14
+ this.makeGroup = makeGroup;
15
+ this.attributes = {
16
+ domain: attributes.domain,
17
+ prefix: attributes.prefix ?? "",
18
+ middlewares: attributes.middlewares ?? []
19
+ };
20
+ }
21
+ /**
22
+ * Constrain the grouped routes to a host pattern such as `{account}.example.com`.
23
+ *
24
+ * @param pattern
25
+ * @returns
26
+ */
27
+ domain(pattern) {
28
+ this.attributes.domain = pattern;
29
+ return this;
30
+ }
31
+ /**
32
+ * Prepend a path prefix to the grouped routes.
33
+ *
34
+ * @param prefix
35
+ * @returns
36
+ */
37
+ prefix(prefix) {
38
+ this.attributes.prefix = prefix;
39
+ return this;
40
+ }
41
+ /**
42
+ * Register one or more middleware shared by the grouped routes.
43
+ *
44
+ * @param middlewares
45
+ * @returns
46
+ */
47
+ middleware(middlewares) {
48
+ this.attributes.middlewares = [...this.attributes.middlewares, ...Array.isArray(middlewares) ? middlewares : [middlewares]];
49
+ return this;
50
+ }
51
+ group(prefixOrSource, sourceOrMiddlewares, middlewares) {
52
+ let prefix = this.attributes.prefix;
53
+ let source;
54
+ let extraMiddlewares;
55
+ if (typeof prefixOrSource === "string") {
56
+ prefix = prefixOrSource;
57
+ source = sourceOrMiddlewares;
58
+ extraMiddlewares = middlewares;
59
+ } else {
60
+ source = prefixOrSource;
61
+ extraMiddlewares = sourceOrMiddlewares;
62
+ }
63
+ return this.makeGroup(prefix, source, [...this.attributes.middlewares, ...extraMiddlewares ?? []], { domain: this.attributes.domain });
64
+ }
65
+ };
66
+
67
+ //#endregion
68
+ exports.RouteRegistrar = RouteRegistrar;
@@ -0,0 +1,62 @@
1
+ import { RouteGroupSource } from "./types/basic.cjs";
2
+ import { RouteGroup } from "./RouteGroup.cjs";
3
+
4
+ //#region src/RouteRegistrar.d.ts
5
+ /**
6
+ * Factory used by the registrar to build a route group while carrying the
7
+ * accumulated attributes (domain, prefix, middlewares).
8
+ */
9
+ type RouteRegistrarGroupFactory = (prefix: string, source: RouteGroupSource, middlewares: any[] | undefined, extra: {
10
+ domain?: string;
11
+ }) => RouteGroup<any, any, any, any>;
12
+ /**
13
+ * @class clear-router RouteRegistrar
14
+ * @description Fluent builder returned by `Router.domain()` that lets routes be
15
+ * grouped under a shared host pattern (and optionally a prefix/middlewares),
16
+ * mirroring Laravel's route attribute registrar.
17
+ * @author 3m1n3nc3
18
+ * @repository https://github.com/arkstack-hq/clear-router
19
+ */
20
+ declare class RouteRegistrar {
21
+ private readonly makeGroup;
22
+ private attributes;
23
+ constructor(makeGroup: RouteRegistrarGroupFactory, attributes?: {
24
+ domain?: string;
25
+ prefix?: string;
26
+ middlewares?: any[];
27
+ });
28
+ /**
29
+ * Constrain the grouped routes to a host pattern such as `{account}.example.com`.
30
+ *
31
+ * @param pattern
32
+ * @returns
33
+ */
34
+ domain(pattern: string): this;
35
+ /**
36
+ * Prepend a path prefix to the grouped routes.
37
+ *
38
+ * @param prefix
39
+ * @returns
40
+ */
41
+ prefix(prefix: string): this;
42
+ /**
43
+ * Register one or more middleware shared by the grouped routes.
44
+ *
45
+ * @param middlewares
46
+ * @returns
47
+ */
48
+ middleware(middlewares: any[] | any): this;
49
+ /**
50
+ * Register the grouped routes. A leading string is treated as a path prefix
51
+ * (matching `Router.group(prefix, source, middlewares?)`); otherwise the first
52
+ * argument is the source and the registrar's own prefix is used.
53
+ *
54
+ * @param source
55
+ * @param middlewares
56
+ * @returns
57
+ */
58
+ group<S extends RouteGroupSource = RouteGroupSource>(source: S, middlewares?: any[]): RouteGroup<any, any, any, S>;
59
+ group<S extends RouteGroupSource = RouteGroupSource>(prefix: string, source: S, middlewares?: any[]): RouteGroup<any, any, any, S>;
60
+ }
61
+ //#endregion
62
+ export { RouteRegistrar, RouteRegistrarGroupFactory };
@@ -0,0 +1,62 @@
1
+ import { RouteGroupSource } from "./types/basic.mjs";
2
+ import { RouteGroup } from "./RouteGroup.mjs";
3
+
4
+ //#region src/RouteRegistrar.d.ts
5
+ /**
6
+ * Factory used by the registrar to build a route group while carrying the
7
+ * accumulated attributes (domain, prefix, middlewares).
8
+ */
9
+ type RouteRegistrarGroupFactory = (prefix: string, source: RouteGroupSource, middlewares: any[] | undefined, extra: {
10
+ domain?: string;
11
+ }) => RouteGroup<any, any, any, any>;
12
+ /**
13
+ * @class clear-router RouteRegistrar
14
+ * @description Fluent builder returned by `Router.domain()` that lets routes be
15
+ * grouped under a shared host pattern (and optionally a prefix/middlewares),
16
+ * mirroring Laravel's route attribute registrar.
17
+ * @author 3m1n3nc3
18
+ * @repository https://github.com/arkstack-hq/clear-router
19
+ */
20
+ declare class RouteRegistrar {
21
+ private readonly makeGroup;
22
+ private attributes;
23
+ constructor(makeGroup: RouteRegistrarGroupFactory, attributes?: {
24
+ domain?: string;
25
+ prefix?: string;
26
+ middlewares?: any[];
27
+ });
28
+ /**
29
+ * Constrain the grouped routes to a host pattern such as `{account}.example.com`.
30
+ *
31
+ * @param pattern
32
+ * @returns
33
+ */
34
+ domain(pattern: string): this;
35
+ /**
36
+ * Prepend a path prefix to the grouped routes.
37
+ *
38
+ * @param prefix
39
+ * @returns
40
+ */
41
+ prefix(prefix: string): this;
42
+ /**
43
+ * Register one or more middleware shared by the grouped routes.
44
+ *
45
+ * @param middlewares
46
+ * @returns
47
+ */
48
+ middleware(middlewares: any[] | any): this;
49
+ /**
50
+ * Register the grouped routes. A leading string is treated as a path prefix
51
+ * (matching `Router.group(prefix, source, middlewares?)`); otherwise the first
52
+ * argument is the source and the registrar's own prefix is used.
53
+ *
54
+ * @param source
55
+ * @param middlewares
56
+ * @returns
57
+ */
58
+ group<S extends RouteGroupSource = RouteGroupSource>(source: S, middlewares?: any[]): RouteGroup<any, any, any, S>;
59
+ group<S extends RouteGroupSource = RouteGroupSource>(prefix: string, source: S, middlewares?: any[]): RouteGroup<any, any, any, S>;
60
+ }
61
+ //#endregion
62
+ export { RouteRegistrar, RouteRegistrarGroupFactory };
@@ -0,0 +1,67 @@
1
+ //#region src/RouteRegistrar.ts
2
+ /**
3
+ * @class clear-router RouteRegistrar
4
+ * @description Fluent builder returned by `Router.domain()` that lets routes be
5
+ * grouped under a shared host pattern (and optionally a prefix/middlewares),
6
+ * mirroring Laravel's route attribute registrar.
7
+ * @author 3m1n3nc3
8
+ * @repository https://github.com/arkstack-hq/clear-router
9
+ */
10
+ var RouteRegistrar = class {
11
+ attributes;
12
+ constructor(makeGroup, attributes = {}) {
13
+ this.makeGroup = makeGroup;
14
+ this.attributes = {
15
+ domain: attributes.domain,
16
+ prefix: attributes.prefix ?? "",
17
+ middlewares: attributes.middlewares ?? []
18
+ };
19
+ }
20
+ /**
21
+ * Constrain the grouped routes to a host pattern such as `{account}.example.com`.
22
+ *
23
+ * @param pattern
24
+ * @returns
25
+ */
26
+ domain(pattern) {
27
+ this.attributes.domain = pattern;
28
+ return this;
29
+ }
30
+ /**
31
+ * Prepend a path prefix to the grouped routes.
32
+ *
33
+ * @param prefix
34
+ * @returns
35
+ */
36
+ prefix(prefix) {
37
+ this.attributes.prefix = prefix;
38
+ return this;
39
+ }
40
+ /**
41
+ * Register one or more middleware shared by the grouped routes.
42
+ *
43
+ * @param middlewares
44
+ * @returns
45
+ */
46
+ middleware(middlewares) {
47
+ this.attributes.middlewares = [...this.attributes.middlewares, ...Array.isArray(middlewares) ? middlewares : [middlewares]];
48
+ return this;
49
+ }
50
+ group(prefixOrSource, sourceOrMiddlewares, middlewares) {
51
+ let prefix = this.attributes.prefix;
52
+ let source;
53
+ let extraMiddlewares;
54
+ if (typeof prefixOrSource === "string") {
55
+ prefix = prefixOrSource;
56
+ source = sourceOrMiddlewares;
57
+ extraMiddlewares = middlewares;
58
+ } else {
59
+ source = prefixOrSource;
60
+ extraMiddlewares = sourceOrMiddlewares;
61
+ }
62
+ return this.makeGroup(prefix, source, [...this.attributes.middlewares, ...extraMiddlewares ?? []], { domain: this.attributes.domain });
63
+ }
64
+ };
65
+
66
+ //#endregion
67
+ export { RouteRegistrar };