clear-router 2.5.4 → 2.5.6

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 (56) hide show
  1. package/README.md +5 -0
  2. package/dist/bindings-CV1e5jho.d.mts +20 -0
  3. package/dist/bindings-DIanvIVd.mjs +211 -0
  4. package/dist/bindings-DvV2DXWi.cjs +253 -0
  5. package/dist/bindings-NV0CdqGl.d.cts +20 -0
  6. package/dist/core/index.cjs +12 -2
  7. package/dist/core/index.d.cts +2 -2
  8. package/dist/core/index.d.mts +2 -2
  9. package/dist/core/index.mjs +9 -2
  10. package/dist/decorators/index.cjs +5 -0
  11. package/dist/decorators/index.d.cts +2 -0
  12. package/dist/decorators/index.d.mts +2 -0
  13. package/dist/decorators/index.mjs +3 -0
  14. package/dist/decorators/setup.cjs +15 -0
  15. package/dist/decorators/setup.d.cts +2 -0
  16. package/dist/decorators/setup.d.mts +2 -0
  17. package/dist/decorators/setup.mjs +13 -0
  18. package/dist/express/index.cjs +26 -9
  19. package/dist/express/index.d.cts +1 -1
  20. package/dist/express/index.d.mts +1 -1
  21. package/dist/express/index.mjs +26 -9
  22. package/dist/fastify/index.cjs +24 -8
  23. package/dist/fastify/index.d.cts +4 -2
  24. package/dist/fastify/index.d.mts +4 -2
  25. package/dist/fastify/index.mjs +24 -8
  26. package/dist/h3/index.cjs +26 -9
  27. package/dist/h3/index.d.cts +1 -1
  28. package/dist/h3/index.d.mts +1 -1
  29. package/dist/h3/index.mjs +26 -9
  30. package/dist/hono/index.cjs +28 -11
  31. package/dist/hono/index.d.cts +4 -2
  32. package/dist/hono/index.d.mts +4 -2
  33. package/dist/hono/index.mjs +28 -11
  34. package/dist/index.cjs +308 -28
  35. package/dist/index.d.cts +112 -18
  36. package/dist/index.d.mts +112 -18
  37. package/dist/index.mjs +305 -28
  38. package/dist/koa/index.cjs +24 -8
  39. package/dist/koa/index.d.cts +4 -2
  40. package/dist/koa/index.d.mts +4 -2
  41. package/dist/koa/index.mjs +24 -8
  42. package/dist/{responses-B-UirWFf.cjs → responses-JzXstGU5.cjs} +18 -1
  43. package/dist/{responses-CJaD0ugv.mjs → responses-_II3dOJ5.mjs} +19 -1
  44. package/dist/{router-BReOXz-F.mjs → router-B3QjblRX.mjs} +159 -48
  45. package/dist/{router-CS_2XQ7I.d.cts → router-BYZmNzrZ.d.cts} +97 -12
  46. package/dist/{router-CHg0pZUO.cjs → router-CU4V1kX0.cjs} +159 -48
  47. package/dist/{router-_w2VzMQF.d.mts → router-DCMtQ_Xi.d.mts} +96 -11
  48. package/dist/types/basic.d.mts +7 -0
  49. package/dist/types/core/Request.d.mts +25 -0
  50. package/dist/types/core/Response.d.mts +21 -0
  51. package/dist/types/express.d.mts +5 -2
  52. package/dist/types/fastify.d.mts +5 -2
  53. package/dist/types/h3.d.mts +5 -2
  54. package/dist/types/hono.d.mts +5 -2
  55. package/dist/types/koa.d.mts +5 -2
  56. package/package.json +16 -2
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
- import { NextFunction, Request, Response as Response$1 } from "express";
3
- import { Middleware } from "h3";
2
+ import { NextFunction, Request as Request$1, Response as Response$2 } from "express";
3
+ import { Middleware as Middleware$1 } from "h3";
4
4
 
5
5
  //#region types/basic.d.ts
6
6
  /**
@@ -26,16 +26,37 @@ interface RouterConfig {
26
26
  bodyKeys?: string[] | string; /** Keys in the request headers to check for method override */
27
27
  headerKeys?: string[] | string;
28
28
  };
29
+ /**
30
+ * Optional method binding / container resolution support. Disabled by default.
31
+ */
32
+ container?: {
33
+ /** Whether decorated handler parameter binding is enabled */enabled?: boolean; /** Whether unknown constructor tokens should be instantiated automatically */
34
+ autoDiscover?: boolean;
35
+ };
29
36
  }
30
37
  //#endregion
31
- //#region types/express.d.ts
32
- /**
33
- * Middleware function type
34
- */
35
- type Middleware$1 = (req: Request, res: Response$1, next: NextFunction) => any | Promise<any>;
38
+ //#region src/core/Response.d.ts
39
+ declare class Response$1 {
40
+ body: any;
41
+ headers: Headers;
42
+ sent: boolean;
43
+ statusCode: number;
44
+ constructor(init?: Partial<Response$1>);
45
+ status(code: number): this;
46
+ code(code: number): this;
47
+ setHeader(name: string, value: string): this;
48
+ header(name: string, value: string): this;
49
+ set(name: string, value: string): this;
50
+ type(contentType: string): this;
51
+ send(body?: any): this;
52
+ json(body: any): this;
53
+ html(body: string): this;
54
+ text(body: string): this;
55
+ noContent(): this;
56
+ }
36
57
  //#endregion
37
58
  //#region src/Route.d.ts
38
- declare class Route<X = any, M = Middleware | Middleware$1, H = any> {
59
+ declare class Route<X = any, M = Middleware$1 | Middleware, H = any> {
39
60
  ctx: X;
40
61
  body: RequestData;
41
62
  query: RequestData;
@@ -52,8 +73,34 @@ declare class Route<X = any, M = Middleware | Middleware$1, H = any> {
52
73
  constructor(methods: HttpMethod[], path: string, handler: H, middlewares?: M[]);
53
74
  }
54
75
  //#endregion
76
+ //#region src/core/Request.d.ts
77
+ declare class Request<X = any, M = any> extends ClearRequest<X, M> {
78
+ original?: any;
79
+ method: string;
80
+ path: string;
81
+ url: string;
82
+ headers: Headers | Record<string, any>;
83
+ constructor(init?: Partial<Request<X, M>> & {
84
+ body?: RequestData;
85
+ query?: RequestData;
86
+ params?: RequestData;
87
+ route?: Route<X, M>;
88
+ });
89
+ getBody(): RequestData;
90
+ header(name: string): string;
91
+ param(name: string): any;
92
+ input(name: string): any;
93
+ is(method: HttpMethod | string): boolean;
94
+ }
95
+ //#endregion
96
+ //#region types/express.d.ts
97
+ /**
98
+ * Middleware function type
99
+ */
100
+ type Middleware = (req: Request$1, res: Response$2, next: NextFunction) => any | Promise<any>;
101
+ //#endregion
55
102
  //#region src/ClearRequest.d.ts
56
- declare class ClearRequest<X = any, M = Middleware | Middleware$1> {
103
+ declare class ClearRequest<X = any, M = Middleware$1 | Middleware> {
57
104
  [key: string]: any;
58
105
  /**
59
106
  * @param body - Parsed request body
@@ -81,6 +128,37 @@ declare abstract class Controller<X = any> {
81
128
  clearRequest: ClearRequest;
82
129
  }
83
130
  //#endregion
131
+ //#region src/core/bindings.d.ts
132
+ type BindToken<T = any> = abstract new (...args: any[]) => T;
133
+ type BindFactory<T = any> = (ctx: any) => T | Promise<T>;
134
+ type BindValue<T = any> = T | BindFactory<T> | BindToken<T>;
135
+ declare class Container {
136
+ private static readonly registry;
137
+ static bind<T>(token: BindToken<T>, value: BindValue<T>): void;
138
+ static unbind<T>(token: BindToken<T>): void;
139
+ static clear(): void;
140
+ static has<T>(token: BindToken<T>): boolean;
141
+ static resolve<T>(token: BindToken<T>, ctx: any, autoDiscover?: boolean): Promise<T | undefined>;
142
+ private static resolveBinding;
143
+ }
144
+ //#endregion
145
+ //#region src/core/plugins.d.ts
146
+ type PluginSetupResult = void;
147
+ type PluginBind = <T>(token: BindToken<T>, value: BindValue<T>) => void;
148
+ interface ClearRouterPluginContext<Options = any> {
149
+ container: typeof Container;
150
+ bind: PluginBind;
151
+ configure: (options: RouterConfig) => void;
152
+ configureDefaults: (options: RouterConfig) => void;
153
+ options: Options;
154
+ }
155
+ interface ClearRouterPlugin<Options = any> {
156
+ name?: string;
157
+ setup: (ctx: ClearRouterPluginContext<Options>) => PluginSetupResult;
158
+ }
159
+ type ClearRouterPluginInput<Options = any> = ClearRouterPlugin<Options> | ((ctx: ClearRouterPluginContext<Options>) => PluginSetupResult);
160
+ declare function definePlugin<Options = any>(plugin: ClearRouterPlugin<Options>): ClearRouterPlugin<Options>;
161
+ //#endregion
84
162
  //#region src/core/router.d.ts
85
163
  /**
86
164
  * @class clear-router CoreRouter
@@ -92,16 +170,16 @@ declare abstract class CoreRouter {
92
170
  protected static routerStateNamespace: string;
93
171
  private static readonly stateStoreKey;
94
172
  private static readonly stateBoundKey;
173
+ private static readonly defaultConfigKey;
174
+ private static readonly pluginStoreKey;
175
+ protected static createBaseConfig(): RouterConfig;
176
+ protected static mergeConfig(target: RouterConfig, source?: RouterConfig): RouterConfig;
177
+ protected static getDefaultConfig(): RouterConfig;
95
178
  protected static resolveStateNamespace(this: any): string;
96
179
  protected static getStateStore(): Record<string, any>;
180
+ protected static getPluginStore(): Set<string>;
97
181
  protected static createDefaultState(): {
98
- config: {
99
- methodOverride: {
100
- enabled: boolean;
101
- bodyKeys: string[];
102
- headerKeys: string[];
103
- };
104
- };
182
+ config: RouterConfig;
105
183
  groupContext: AsyncLocalStorage<{
106
184
  prefix: string;
107
185
  groupMiddlewares: any[];
@@ -116,6 +194,16 @@ declare abstract class CoreRouter {
116
194
  protected static bindStateAccessors(this: any): void;
117
195
  protected static createDefaultOptionsHandler(): any;
118
196
  static config: RouterConfig;
197
+ static configureDefaults(this: any, options?: RouterConfig): void;
198
+ /**
199
+ * Use a registered plugin
200
+ *
201
+ * @param this
202
+ * @param plugin
203
+ * @param options
204
+ * @returns
205
+ */
206
+ static use<Options = any>(this: any, plugin: ClearRouterPluginInput<Options>, options?: Options): void;
119
207
  protected static groupContext: AsyncLocalStorage<{
120
208
  prefix: string;
121
209
  groupMiddlewares: any[];
@@ -265,14 +353,20 @@ declare abstract class CoreRouter {
265
353
  */
266
354
  static allRoutes(this: any, type: 'method'): { [method in Uppercase<HttpMethod>]?: Array<Route<any, any, any>> };
267
355
  protected static resolveHandler(route: Route<any, any, any>): {
268
- handlerFunction: ((ctx: any, req: ClearRequest) => any | Promise<any>) | null;
356
+ handlerFunction: ((ctx: any, req: Request) => any | Promise<any>) | null;
269
357
  instance: Controller<any> | null;
358
+ bindingTarget?: object;
359
+ bindingMethod?: PropertyKey;
360
+ bindingHandler?: object;
361
+ bindingMetadata?: object;
270
362
  };
363
+ protected static callHandler(this: any, handlerFunction: (ctx: any, req: Request) => any | Promise<any>, ctx: any, bindingTarget?: object, bindingMethod?: PropertyKey, bindingHandler?: object, bindingMetadata?: object): Promise<any>;
271
364
  protected static bindRequestToInstance(ctx: any, instance: Controller<any> | Route<any, any, any> | null, route: Route<any, any, any>, payload: {
272
365
  body: Record<string, any>;
273
366
  query: Record<string, any>;
274
367
  params: Record<string, any>;
368
+ method?: HttpMethod | string;
275
369
  }): void;
276
370
  }
277
371
  //#endregion
278
- export { ClearRequest, Controller, CoreRouter, Route };
372
+ export { ClearRequest, ClearRouterPlugin, ClearRouterPluginContext, ClearRouterPluginInput, Controller, CoreRouter, PluginBind, PluginSetupResult, Request, Response$1 as Response, Route, definePlugin };
package/dist/index.mjs CHANGED
@@ -58,6 +58,152 @@ var Route = class {
58
58
  }
59
59
  };
60
60
 
61
+ //#endregion
62
+ //#region src/core/Request.ts
63
+ var Request = class extends ClearRequest {
64
+ original;
65
+ method = "GET";
66
+ path = "/";
67
+ url = "/";
68
+ headers = {};
69
+ constructor(init) {
70
+ super(init);
71
+ Object.assign(this, init);
72
+ }
73
+ getBody() {
74
+ return this.body ?? {};
75
+ }
76
+ header(name) {
77
+ if (typeof this.headers.get === "function") return this.headers.get(name) || "";
78
+ const headers = this.headers;
79
+ const value = headers[name] ?? headers[name.toLowerCase()];
80
+ return Array.isArray(value) ? String(value[0] ?? "") : String(value ?? "");
81
+ }
82
+ param(name) {
83
+ return this.params?.[name];
84
+ }
85
+ input(name) {
86
+ return this.body?.[name] ?? this.query?.[name] ?? this.params?.[name];
87
+ }
88
+ is(method) {
89
+ return this.method.toLowerCase() === String(method).toLowerCase();
90
+ }
91
+ };
92
+
93
+ //#endregion
94
+ //#region src/core/Response.ts
95
+ var Response = class {
96
+ body;
97
+ headers = new Headers();
98
+ sent = false;
99
+ statusCode = 200;
100
+ constructor(init) {
101
+ Object.assign(this, init);
102
+ if (init?.headers && !(init.headers instanceof Headers)) this.headers = new Headers(init.headers);
103
+ }
104
+ status(code) {
105
+ this.statusCode = code;
106
+ return this;
107
+ }
108
+ code(code) {
109
+ return this.status(code);
110
+ }
111
+ setHeader(name, value) {
112
+ this.headers.set(name, value);
113
+ return this;
114
+ }
115
+ header(name, value) {
116
+ return this.setHeader(name, value);
117
+ }
118
+ set(name, value) {
119
+ return this.setHeader(name, value);
120
+ }
121
+ type(contentType) {
122
+ return this.setHeader("Content-Type", contentType);
123
+ }
124
+ send(body) {
125
+ this.body = body;
126
+ this.sent = true;
127
+ return this;
128
+ }
129
+ json(body) {
130
+ return this.type("application/json; charset=utf-8").send(body);
131
+ }
132
+ html(body) {
133
+ return this.type("text/html; charset=utf-8").send(body);
134
+ }
135
+ text(body) {
136
+ return this.type("text/plain; charset=utf-8").send(body);
137
+ }
138
+ noContent() {
139
+ return this.status(204).send(null);
140
+ }
141
+ };
142
+
143
+ //#endregion
144
+ //#region src/core/plugins.ts
145
+ function definePlugin(plugin) {
146
+ return plugin;
147
+ }
148
+
149
+ //#endregion
150
+ //#region src/core/bindings.ts
151
+ const metadataKey = Symbol.for("clear-router:binding-metadata");
152
+ const bindings = /* @__PURE__ */ new WeakMap();
153
+ var Container = class {
154
+ static registry = /* @__PURE__ */ new Map();
155
+ static bind(token, value) {
156
+ this.registry.set(token, value);
157
+ }
158
+ static unbind(token) {
159
+ this.registry.delete(token);
160
+ }
161
+ static clear() {
162
+ this.registry.clear();
163
+ }
164
+ static has(token) {
165
+ return this.registry.has(token);
166
+ }
167
+ static async resolve(token, ctx, autoDiscover = false) {
168
+ if (token === Request) return ctx.clearRequest;
169
+ if (token === Response) return ctx.clearResponse;
170
+ if (this.registry.has(token)) return this.resolveBinding(this.registry.get(token), ctx, autoDiscover);
171
+ if (autoDiscover && typeof token === "function") return new token();
172
+ }
173
+ static async resolveBinding(binding, ctx, autoDiscover) {
174
+ if (!binding) return void 0;
175
+ if (typeof binding !== "function") return binding;
176
+ if (isClass(binding)) return new binding();
177
+ const resolved = await binding(ctx);
178
+ if (typeof resolved === "function" && autoDiscover && isClass(resolved)) return new resolved();
179
+ return resolved;
180
+ }
181
+ };
182
+ function getStandardMetadata(metadata, propertyKey) {
183
+ const store = metadata && metadata[metadataKey];
184
+ if (!store) return void 0;
185
+ return propertyKey ? store[propertyKey] : void 0;
186
+ }
187
+ function getBindingMetadataFromTargets(targets) {
188
+ for (const { target, propertyKey } of targets) {
189
+ if (!target) continue;
190
+ const metadata = getBindingMetadata(target, propertyKey);
191
+ if (metadata) return metadata;
192
+ const standardMetadata = getStandardMetadata(target[Symbol.metadata], propertyKey);
193
+ if (standardMetadata) return standardMetadata;
194
+ }
195
+ }
196
+ function getBindingMetadata(target, propertyKey) {
197
+ if (propertyKey) return bindings.get(target)?.get(propertyKey);
198
+ return bindings.get(target)?.get("__route_handler__");
199
+ }
200
+ function getDesignParamTypes(target, propertyKey) {
201
+ return Reflect.getMetadata?.("design:paramtypes", target, propertyKey) ?? [];
202
+ }
203
+ function isClass(value) {
204
+ return typeof value === "function" && /^class\s/.test(Function.prototype.toString.call(value));
205
+ }
206
+
61
207
  //#endregion
62
208
  //#region src/core/router.ts
63
209
  /**
@@ -70,6 +216,41 @@ var CoreRouter = class {
70
216
  static routerStateNamespace = "clear-router:core";
71
217
  static stateStoreKey = Symbol.for("clear-router:router-state");
72
218
  static stateBoundKey = Symbol.for("clear-router:router-state-bound");
219
+ static defaultConfigKey = Symbol.for("clear-router:default-config");
220
+ static pluginStoreKey = Symbol.for("clear-router:plugins");
221
+ static createBaseConfig() {
222
+ return {
223
+ methodOverride: {
224
+ enabled: true,
225
+ bodyKeys: ["_method"],
226
+ headerKeys: ["x-http-method"]
227
+ },
228
+ container: {
229
+ enabled: false,
230
+ autoDiscover: false
231
+ }
232
+ };
233
+ }
234
+ static mergeConfig(target, source) {
235
+ if (!source) return target;
236
+ if (source.methodOverride) target.methodOverride = {
237
+ ...target.methodOverride || {},
238
+ ...source.methodOverride
239
+ };
240
+ if (source.container) target.container = {
241
+ ...target.container || {},
242
+ ...source.container
243
+ };
244
+ return target;
245
+ }
246
+ static getDefaultConfig() {
247
+ const g = globalThis;
248
+ if (!g[this.defaultConfigKey]) g[this.defaultConfigKey] = this.createBaseConfig();
249
+ return {
250
+ methodOverride: { ...g[this.defaultConfigKey].methodOverride },
251
+ container: { ...g[this.defaultConfigKey].container }
252
+ };
253
+ }
73
254
  static resolveStateNamespace() {
74
255
  return String(this.routerStateNamespace || this.name || "clear-router:core");
75
256
  }
@@ -78,13 +259,14 @@ var CoreRouter = class {
78
259
  if (!g[this.stateStoreKey]) g[this.stateStoreKey] = Object.create(null);
79
260
  return g[this.stateStoreKey];
80
261
  }
262
+ static getPluginStore() {
263
+ const g = globalThis;
264
+ if (!g[this.pluginStoreKey]) g[this.pluginStoreKey] = /* @__PURE__ */ new Set();
265
+ return g[this.pluginStoreKey];
266
+ }
81
267
  static createDefaultState() {
82
268
  return {
83
- config: { methodOverride: {
84
- enabled: true,
85
- bodyKeys: ["_method"],
86
- headerKeys: ["x-http-method"]
87
- } },
269
+ config: this.getDefaultConfig(),
88
270
  groupContext: new AsyncLocalStorage(),
89
271
  routes: [],
90
272
  routesByPathMethod: {},
@@ -161,11 +343,47 @@ var CoreRouter = class {
161
343
  }
162
344
  };
163
345
  }
164
- static config = { methodOverride: {
165
- enabled: true,
166
- bodyKeys: ["_method"],
167
- headerKeys: ["x-http-method"]
168
- } };
346
+ static config = {
347
+ methodOverride: {
348
+ enabled: true,
349
+ bodyKeys: ["_method"],
350
+ headerKeys: ["x-http-method"]
351
+ },
352
+ container: {
353
+ enabled: false,
354
+ autoDiscover: false
355
+ }
356
+ };
357
+ static configureDefaults(options) {
358
+ const g = globalThis;
359
+ const defaults = this.mergeConfig(g[this.defaultConfigKey] || this.createBaseConfig(), options);
360
+ g[this.defaultConfigKey] = defaults;
361
+ const store = this.getStateStore();
362
+ for (const state of Object.values(store)) state.config = this.mergeConfig(state.config || this.createBaseConfig(), options);
363
+ }
364
+ /**
365
+ * Use a registered plugin
366
+ *
367
+ * @param this
368
+ * @param plugin
369
+ * @param options
370
+ * @returns
371
+ */
372
+ static use(plugin, options) {
373
+ const name = typeof plugin === "function" ? plugin.name : plugin.name;
374
+ const store = this.getPluginStore();
375
+ if (name && store.has(name)) return;
376
+ const ctx = {
377
+ container: Container,
378
+ bind: Container.bind.bind(Container),
379
+ configure: this.configure.bind(this),
380
+ configureDefaults: this.configureDefaults.bind(this),
381
+ options
382
+ };
383
+ if (typeof plugin === "function") plugin(ctx);
384
+ else plugin.setup(ctx);
385
+ if (name) store.add(name);
386
+ }
169
387
  static groupContext = new AsyncLocalStorage();
170
388
  static routes = [];
171
389
  static routesByPathMethod = {};
@@ -207,11 +425,12 @@ var CoreRouter = class {
207
425
  */
208
426
  static configure(options) {
209
427
  this.ensureState();
210
- if (!this.config.methodOverride) this.config.methodOverride = {
211
- enabled: true,
212
- bodyKeys: ["_method"],
213
- headerKeys: ["x-http-method"]
214
- };
428
+ this.config = this.mergeConfig(this.getDefaultConfig(), this.config);
429
+ const container = options?.container;
430
+ if (container) {
431
+ if (typeof container.enabled === "boolean") this.config.container.enabled = container.enabled;
432
+ if (typeof container.autoDiscover === "boolean") this.config.container.autoDiscover = container.autoDiscover;
433
+ }
215
434
  const override = options?.methodOverride;
216
435
  if (!override) return;
217
436
  if (typeof override.enabled === "boolean") this.config.methodOverride.enabled = override.enabled;
@@ -448,38 +667,96 @@ var CoreRouter = class {
448
667
  static resolveHandler(route) {
449
668
  let handlerFunction;
450
669
  let instance = null;
451
- if (typeof route.handler === "function") handlerFunction = route.handler.bind(route);
452
- else if (Array.isArray(route.handler) && route.handler.length === 2) {
670
+ let bindingTarget;
671
+ let bindingMethod;
672
+ let bindingHandler;
673
+ let bindingMetadata;
674
+ if (typeof route.handler === "function") {
675
+ handlerFunction = route.handler.bind(route);
676
+ bindingTarget = route.handler;
677
+ bindingHandler = route.handler;
678
+ } else if (Array.isArray(route.handler) && route.handler.length === 2) {
453
679
  const [ControllerType, method] = route.handler;
454
680
  if (["function", "object"].includes(typeof ControllerType) && typeof ControllerType[method] === "function") {
455
681
  instance = ControllerType;
456
682
  handlerFunction = ControllerType[method].bind(ControllerType);
683
+ bindingTarget = ControllerType;
684
+ bindingMethod = method;
685
+ bindingHandler = ControllerType[method];
686
+ bindingMetadata = ControllerType[Symbol.metadata];
457
687
  } else if (typeof ControllerType === "function") {
458
688
  instance = new ControllerType();
459
- if (typeof instance[method] === "function") handlerFunction = instance[method].bind(instance);
460
- else throw new Error(`Method "${method}" not found in controller instance "${ControllerType.name}"`);
689
+ if (typeof instance[method] === "function") {
690
+ handlerFunction = instance[method].bind(instance);
691
+ bindingTarget = ControllerType.prototype;
692
+ bindingMethod = method;
693
+ bindingHandler = instance[method];
694
+ bindingMetadata = ControllerType[Symbol.metadata];
695
+ } else throw new Error(`Method "${method}" not found in controller instance "${ControllerType.name}"`);
461
696
  } else throw new Error(`Invalid controller type for route: ${route.path}`);
462
697
  } else throw new Error(`Invalid handler format for route: ${route.path}`);
463
698
  return {
464
699
  handlerFunction,
465
- instance
700
+ instance,
701
+ bindingTarget,
702
+ bindingMethod,
703
+ bindingHandler,
704
+ bindingMetadata
466
705
  };
467
706
  }
707
+ static async callHandler(handlerFunction, ctx, bindingTarget, bindingMethod, bindingHandler, bindingMetadata) {
708
+ if (!this.config.container?.enabled) return handlerFunction(ctx, ctx.clearRequest);
709
+ const metadata = getBindingMetadataFromTargets([
710
+ {
711
+ target: bindingTarget,
712
+ propertyKey: bindingMethod
713
+ },
714
+ { target: bindingHandler },
715
+ {
716
+ target: bindingTarget,
717
+ propertyKey: "__class__"
718
+ }
719
+ ]) ?? getStandardMetadata(bindingMetadata, bindingMethod) ?? getStandardMetadata(bindingMetadata, "__class__");
720
+ if (!metadata) return handlerFunction(ctx, ctx.clearRequest);
721
+ const designTokens = [...bindingTarget ? getDesignParamTypes(bindingTarget, bindingMethod) : [], ...bindingHandler ? getDesignParamTypes(bindingHandler) : []];
722
+ const tokens = metadata.tokens?.length ? metadata.tokens : designTokens;
723
+ if (!tokens.length) return handlerFunction(ctx, ctx.clearRequest);
724
+ const args = [];
725
+ for (const token of tokens) {
726
+ const resolved = await Container.resolve(token, ctx, Boolean(this.config.container?.autoDiscover));
727
+ if (typeof resolved === "undefined") return handlerFunction(ctx, ctx.clearRequest);
728
+ args.push(resolved);
729
+ }
730
+ return handlerFunction(...args);
731
+ }
468
732
  static bindRequestToInstance(ctx, instance, route, payload) {
733
+ const clearRequest = ctx.clearRequest instanceof Request ? ctx.clearRequest : new Request({
734
+ ctx,
735
+ route,
736
+ body: payload.body,
737
+ query: payload.query,
738
+ params: payload.params,
739
+ method: String(payload.method || ctx.req?.method || ctx.method || "GET").toUpperCase(),
740
+ path: String(ctx.path || ctx.req?.path || ctx.req?.url || route.path),
741
+ url: String(ctx.url || ctx.req?.url || ctx.req?.originalUrl || route.path),
742
+ headers: ctx.req?.headers || ctx.headers || {},
743
+ original: ctx.req || ctx.request || ctx
744
+ });
745
+ clearRequest.ctx = ctx;
746
+ clearRequest.route = route;
747
+ clearRequest.body = payload.body;
748
+ clearRequest.query = payload.query;
749
+ clearRequest.params = payload.params;
750
+ ctx.clearRequest = clearRequest;
751
+ if (!(ctx.clearResponse instanceof Response)) ctx.clearResponse = new Response();
469
752
  if (!instance) return;
470
753
  instance.ctx = ctx;
471
754
  instance.body = payload.body;
472
755
  instance.query = payload.query;
473
756
  instance.params = payload.params;
474
- instance.clearRequest = new ClearRequest({
475
- ctx,
476
- route,
477
- body: instance.body,
478
- query: instance.query,
479
- params: instance.params
480
- });
757
+ instance.clearRequest = clearRequest;
481
758
  }
482
759
  };
483
760
 
484
761
  //#endregion
485
- export { ClearRequest, Controller, CoreRouter, Route };
762
+ export { ClearRequest, Controller, CoreRouter, Request, Response, Route, definePlugin };
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_router = require('../router-CHg0pZUO.cjs');
3
- const require_responses = require('../responses-B-UirWFf.cjs');
2
+ require('../bindings-DvV2DXWi.cjs');
3
+ const require_router = require('../router-CU4V1kX0.cjs');
4
+ const require_responses = require('../responses-JzXstGU5.cjs');
4
5
 
5
6
  //#region src/koa/router.ts
6
7
  /**
@@ -44,6 +45,9 @@ var Router = class Router extends require_router.CoreRouter {
44
45
  });
45
46
  if (!meta) return void 0;
46
47
  ctx.status = meta.status;
48
+ meta.headers?.forEach((headerValue, key) => {
49
+ ctx.set(key, headerValue);
50
+ });
47
51
  if (require_responses.isFetchResponse(meta.body)) {
48
52
  meta.body.headers.forEach((headerValue, key) => {
49
53
  ctx.set(key, headerValue);
@@ -180,10 +184,18 @@ var Router = class Router extends require_router.CoreRouter {
180
184
  for (const route of this.routes) {
181
185
  let handlerFunction = null;
182
186
  let instance = null;
187
+ let bindingTarget;
188
+ let bindingMethod;
189
+ let bindingHandler;
190
+ let bindingMetadata;
183
191
  try {
184
192
  const resolved = this.resolveHandler(route);
185
193
  handlerFunction = resolved.handlerFunction;
186
194
  instance = resolved.instance;
195
+ bindingTarget = resolved.bindingTarget;
196
+ bindingMethod = resolved.bindingMethod;
197
+ bindingHandler = resolved.bindingHandler;
198
+ bindingMetadata = resolved.bindingMetadata;
187
199
  } catch (error) {
188
200
  console.error(`[ROUTES] Error setting up route ${route.path}:`, error.message);
189
201
  throw error;
@@ -210,11 +222,13 @@ var Router = class Router extends require_router.CoreRouter {
210
222
  Router.bindRequestToInstance(ctx, inst, route, {
211
223
  body: reqBody,
212
224
  query: ctx.query,
213
- params: ctx.params ?? {}
225
+ params: ctx.params ?? {},
226
+ method
214
227
  });
215
- const result = handlerFunction(ctx, inst.clearRequest);
228
+ const result = await Router.callHandler(handlerFunction, ctx, bindingTarget, bindingMethod, bindingHandler, bindingMetadata);
216
229
  const resolved = await Promise.resolve(result);
217
- return Router.sendReturnValue(ctx, resolved, method, route.path);
230
+ const outgoing = typeof resolved === "undefined" && ctx.clearResponse?.sent ? ctx.clearResponse : resolved;
231
+ return Router.sendReturnValue(ctx, outgoing, method, route.path);
218
232
  });
219
233
  if ([
220
234
  "put",
@@ -228,11 +242,13 @@ var Router = class Router extends require_router.CoreRouter {
228
242
  Router.bindRequestToInstance(ctx, inst, route, {
229
243
  body: reqBody,
230
244
  query: ctx.query,
231
- params: ctx.params ?? {}
245
+ params: ctx.params ?? {},
246
+ method
232
247
  });
233
- const result = handlerFunction(ctx, inst.clearRequest);
248
+ const result = await Router.callHandler(handlerFunction, ctx, bindingTarget, bindingMethod, bindingHandler, bindingMetadata);
234
249
  const resolved = await Promise.resolve(result);
235
- return Router.sendReturnValue(ctx, resolved, method, route.path);
250
+ const outgoing = typeof resolved === "undefined" && ctx.clearResponse?.sent ? ctx.clearResponse : resolved;
251
+ return Router.sendReturnValue(ctx, outgoing, method, route.path);
236
252
  });
237
253
  }
238
254
  }
@@ -1,4 +1,4 @@
1
- import { d as ApiResourceMiddleware, f as ControllerAction, m as HttpMethod, n as ClearRequest, p as ControllerHandler, r as Route, t as CoreRouter } from "../router-CS_2XQ7I.cjs";
1
+ import { _ as ApiResourceMiddleware, b as HttpMethod, c as Request, l as Route, t as CoreRouter, v as ControllerAction, x as Response, y as ControllerHandler } from "../router-BYZmNzrZ.cjs";
2
2
  import Koa from "koa";
3
3
  import Router$1 from "@koa/router";
4
4
 
@@ -9,10 +9,12 @@ interface RequestWithGetBody extends Koa.Request {
9
9
  }
10
10
  interface HttpContext extends Koa.Context {
11
11
  request: RequestWithGetBody;
12
+ clearRequest: Request;
13
+ clearResponse: Response;
12
14
  params: Record<string, any>;
13
15
  query: Record<string, any>;
14
16
  }
15
- type RouteHandler = (ctx: HttpContext, req: ClearRequest) => any | Promise<any>;
17
+ type RouteHandler = (ctx: HttpContext, req: Request) => any | Promise<any>;
16
18
  type Handler = RouteHandler | ControllerHandler;
17
19
  type Middleware = Koa.Middleware<any, any>;
18
20
  type KoaRouterApp = Router$1<any, any>;