@noxfly/noxus 2.1.1 → 2.2.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/README.md CHANGED
@@ -311,6 +311,50 @@ import { MyClass } from 'src/myclass';
311
311
  const instance: MyClass = inject(MyClass);
312
312
  ```
313
313
 
314
+ ### Circular Dependencies
315
+
316
+ Noxus solves circular dependencies using a forward reference pattern. When two classes depend on each other, you can use `forwardRef()` combined with either the `@Inject()` decorator or the `inject()` helper to lazily resolve the dependency.
317
+
318
+ **Using Constructor Injection (`@Inject`)**
319
+
320
+ ```ts
321
+ import { Injectable, Inject, forwardRef } from '@noxfly/noxus/main';
322
+
323
+ @Injectable()
324
+ class ServiceA {
325
+ constructor(
326
+ @Inject(forwardRef(() => ServiceB))
327
+ private readonly serviceB: ServiceB
328
+ ) {}
329
+ }
330
+
331
+ @Injectable()
332
+ class ServiceB {
333
+ constructor(
334
+ private readonly serviceA: ServiceA
335
+ ) {}
336
+ }
337
+ ```
338
+
339
+ **Using Property Injection (`inject`)**
340
+
341
+ ```ts
342
+ import { Injectable, inject, forwardRef } from '@noxfly/noxus/main';
343
+
344
+ @Injectable()
345
+ class ServiceA {
346
+ // Lazily resolves ServiceB, avoiding infinite recursion during instantiation
347
+ private readonly serviceB = inject(forwardRef(() => ServiceB));
348
+ }
349
+
350
+ @Injectable()
351
+ class ServiceB {
352
+ private readonly serviceA = inject(ServiceA);
353
+ }
354
+ ```
355
+
356
+ In both cases, a `Proxy` is returned, meaning the actual instance is only resolved when you access a property or method on it.
357
+
314
358
  ### Middlewares
315
359
 
316
360
  Declare middlewares as follow :
@@ -110,6 +110,28 @@ declare const Delete: (path: string) => MethodDecorator;
110
110
  declare const ROUTE_METADATA_KEY: unique symbol;
111
111
 
112
112
 
113
+ /**
114
+ * A function that returns a type.
115
+ * Used for forward references to types that are not yet defined.
116
+ */
117
+ interface ForwardRefFn<T = any> {
118
+ (): Type<T>;
119
+ }
120
+ /**
121
+ * A wrapper class for forward referenced types.
122
+ */
123
+ declare class ForwardReference<T = any> {
124
+ readonly forwardRefFn: ForwardRefFn<T>;
125
+ constructor(forwardRefFn: ForwardRefFn<T>);
126
+ }
127
+ /**
128
+ * Creates a forward reference to a type.
129
+ * @param fn A function that returns the type.
130
+ * @returns A ForwardReference instance.
131
+ */
132
+ declare function forwardRef<T = any>(fn: ForwardRefFn<T>): ForwardReference<T>;
133
+
134
+
113
135
  /**
114
136
  * Represents a lifetime of a binding in the dependency injection system.
115
137
  * It can be one of the following:
@@ -151,9 +173,9 @@ declare class AppInjector {
151
173
  * Called when resolving a dependency,
152
174
  * i.e., retrieving the instance of a given class.
153
175
  */
154
- resolve<T extends Type<unknown>>(target: T): InstanceType<T>;
176
+ resolve<T>(target: Type<T> | ForwardReference<T>): T;
155
177
  /**
156
- *
178
+ * Instantiates a class, resolving its dependencies.
157
179
  */
158
180
  private instantiate;
159
181
  }
@@ -165,7 +187,7 @@ declare class AppInjector {
165
187
  * @returns An instance of the type.
166
188
  * @throws If the type is not registered in the dependency injection system.
167
189
  */
168
- declare function inject<T>(t: Type<T>): T;
190
+ declare function inject<T>(t: Type<T> | ForwardReference<T>): T;
169
191
  declare const RootInjector: AppInjector;
170
192
 
171
193
 
@@ -315,4 +337,4 @@ declare class NoxRendererClient {
315
337
  isElectronEnvironment(): boolean;
316
338
  }
317
339
 
318
- export { AppInjector as A, Delete as D, Get as G, type HttpMethod as H, type IResponse as I, type Lifetime as L, type MaybeAsync as M, NoxRendererClient as N, Post as P, Request as R, type Type as T, type IGuard as a, type IPortRequester as b, type IBinding as c, RootInjector as d, Authorize as e, getGuardForControllerAction as f, getGuardForController as g, type IRouteMetadata as h, inject as i, type AtomicHttpMethod as j, getRouteMetadata as k, Put as l, Patch as m, ROUTE_METADATA_KEY as n, type IRequest as o, type IBatchRequestItem as p, type IBatchRequestPayload as q, type IBatchResponsePayload as r, RENDERER_EVENT_TYPE as s, type IRendererEventMessage as t, createRendererEventMessage as u, isRendererEventMessage as v, type RendererEventHandler as w, type RendererEventSubscription as x, RendererEventRegistry as y, type RendererClientOptions as z };
340
+ export { AppInjector as A, RendererEventRegistry as B, type RendererClientOptions as C, Delete as D, type ForwardRefFn as F, Get as G, type HttpMethod as H, type IResponse as I, type Lifetime as L, type MaybeAsync as M, NoxRendererClient as N, Post as P, Request as R, type Type as T, type IGuard as a, type IPortRequester as b, type IBinding as c, RootInjector as d, Authorize as e, getGuardForControllerAction as f, getGuardForController as g, type IRouteMetadata as h, inject as i, type AtomicHttpMethod as j, getRouteMetadata as k, Put as l, Patch as m, ROUTE_METADATA_KEY as n, ForwardReference as o, forwardRef as p, type IRequest as q, type IBatchRequestItem as r, type IBatchRequestPayload as s, type IBatchResponsePayload as t, RENDERER_EVENT_TYPE as u, type IRendererEventMessage as v, createRendererEventMessage as w, isRendererEventMessage as x, type RendererEventHandler as y, type RendererEventSubscription as z };
@@ -110,6 +110,28 @@ declare const Delete: (path: string) => MethodDecorator;
110
110
  declare const ROUTE_METADATA_KEY: unique symbol;
111
111
 
112
112
 
113
+ /**
114
+ * A function that returns a type.
115
+ * Used for forward references to types that are not yet defined.
116
+ */
117
+ interface ForwardRefFn<T = any> {
118
+ (): Type<T>;
119
+ }
120
+ /**
121
+ * A wrapper class for forward referenced types.
122
+ */
123
+ declare class ForwardReference<T = any> {
124
+ readonly forwardRefFn: ForwardRefFn<T>;
125
+ constructor(forwardRefFn: ForwardRefFn<T>);
126
+ }
127
+ /**
128
+ * Creates a forward reference to a type.
129
+ * @param fn A function that returns the type.
130
+ * @returns A ForwardReference instance.
131
+ */
132
+ declare function forwardRef<T = any>(fn: ForwardRefFn<T>): ForwardReference<T>;
133
+
134
+
113
135
  /**
114
136
  * Represents a lifetime of a binding in the dependency injection system.
115
137
  * It can be one of the following:
@@ -151,9 +173,9 @@ declare class AppInjector {
151
173
  * Called when resolving a dependency,
152
174
  * i.e., retrieving the instance of a given class.
153
175
  */
154
- resolve<T extends Type<unknown>>(target: T): InstanceType<T>;
176
+ resolve<T>(target: Type<T> | ForwardReference<T>): T;
155
177
  /**
156
- *
178
+ * Instantiates a class, resolving its dependencies.
157
179
  */
158
180
  private instantiate;
159
181
  }
@@ -165,7 +187,7 @@ declare class AppInjector {
165
187
  * @returns An instance of the type.
166
188
  * @throws If the type is not registered in the dependency injection system.
167
189
  */
168
- declare function inject<T>(t: Type<T>): T;
190
+ declare function inject<T>(t: Type<T> | ForwardReference<T>): T;
169
191
  declare const RootInjector: AppInjector;
170
192
 
171
193
 
@@ -315,4 +337,4 @@ declare class NoxRendererClient {
315
337
  isElectronEnvironment(): boolean;
316
338
  }
317
339
 
318
- export { AppInjector as A, Delete as D, Get as G, type HttpMethod as H, type IResponse as I, type Lifetime as L, type MaybeAsync as M, NoxRendererClient as N, Post as P, Request as R, type Type as T, type IGuard as a, type IPortRequester as b, type IBinding as c, RootInjector as d, Authorize as e, getGuardForControllerAction as f, getGuardForController as g, type IRouteMetadata as h, inject as i, type AtomicHttpMethod as j, getRouteMetadata as k, Put as l, Patch as m, ROUTE_METADATA_KEY as n, type IRequest as o, type IBatchRequestItem as p, type IBatchRequestPayload as q, type IBatchResponsePayload as r, RENDERER_EVENT_TYPE as s, type IRendererEventMessage as t, createRendererEventMessage as u, isRendererEventMessage as v, type RendererEventHandler as w, type RendererEventSubscription as x, RendererEventRegistry as y, type RendererClientOptions as z };
340
+ export { AppInjector as A, RendererEventRegistry as B, type RendererClientOptions as C, Delete as D, type ForwardRefFn as F, Get as G, type HttpMethod as H, type IResponse as I, type Lifetime as L, type MaybeAsync as M, NoxRendererClient as N, Post as P, Request as R, type Type as T, type IGuard as a, type IPortRequester as b, type IBinding as c, RootInjector as d, Authorize as e, getGuardForControllerAction as f, getGuardForController as g, type IRouteMetadata as h, inject as i, type AtomicHttpMethod as j, getRouteMetadata as k, Put as l, Patch as m, ROUTE_METADATA_KEY as n, ForwardReference as o, forwardRef as p, type IRequest as q, type IBatchRequestItem as r, type IBatchRequestPayload as s, type IBatchResponsePayload as t, RENDERER_EVENT_TYPE as u, type IRendererEventMessage as v, createRendererEventMessage as w, isRendererEventMessage as x, type RendererEventHandler as y, type RendererEventSubscription as z };
package/dist/main.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Request, I as IResponse, M as MaybeAsync, T as Type, a as IGuard, L as Lifetime, b as IPortRequester } from './index-CI3OMzNR.mjs';
2
- export { A as AppInjector, j as AtomicHttpMethod, e as Authorize, D as Delete, G as Get, H as HttpMethod, p as IBatchRequestItem, q as IBatchRequestPayload, r as IBatchResponsePayload, c as IBinding, t as IRendererEventMessage, o as IRequest, h as IRouteMetadata, N as NoxRendererClient, m as Patch, P as Post, l as Put, s as RENDERER_EVENT_TYPE, n as ROUTE_METADATA_KEY, z as RendererClientOptions, w as RendererEventHandler, y as RendererEventRegistry, x as RendererEventSubscription, d as RootInjector, u as createRendererEventMessage, g as getGuardForController, f as getGuardForControllerAction, k as getRouteMetadata, i as inject, v as isRendererEventMessage } from './index-CI3OMzNR.mjs';
1
+ import { R as Request, I as IResponse, M as MaybeAsync, T as Type, a as IGuard, L as Lifetime, b as IPortRequester } from './index-Dr-ifUJj.mjs';
2
+ export { A as AppInjector, j as AtomicHttpMethod, e as Authorize, D as Delete, F as ForwardRefFn, o as ForwardReference, G as Get, H as HttpMethod, r as IBatchRequestItem, s as IBatchRequestPayload, t as IBatchResponsePayload, c as IBinding, v as IRendererEventMessage, q as IRequest, h as IRouteMetadata, N as NoxRendererClient, m as Patch, P as Post, l as Put, u as RENDERER_EVENT_TYPE, n as ROUTE_METADATA_KEY, C as RendererClientOptions, y as RendererEventHandler, B as RendererEventRegistry, z as RendererEventSubscription, d as RootInjector, w as createRendererEventMessage, p as forwardRef, g as getGuardForController, f as getGuardForControllerAction, k as getRouteMetadata, i as inject, x as isRendererEventMessage } from './index-Dr-ifUJj.mjs';
3
3
 
4
4
  /**
5
5
  * @copyright 2025 NoxFly
@@ -374,6 +374,16 @@ declare function hasInjectableMetadata(target: Function): boolean;
374
374
  declare function Injectable(lifetime?: Lifetime): ClassDecorator;
375
375
 
376
376
 
377
+ declare const INJECT_METADATA_KEY = "custom:inject";
378
+ /**
379
+ * Decorator to manually inject a dependency.
380
+ * Useful for handling circular dependencies with `forwardRef` or injecting specific tokens.
381
+ *
382
+ * @param token The token or forward reference to inject.
383
+ */
384
+ declare function Inject(token: any): ParameterDecorator;
385
+
386
+
377
387
  interface IModuleMetadata {
378
388
  imports?: Type<unknown>[];
379
389
  exports?: Type<unknown>[];
@@ -508,4 +518,4 @@ declare namespace Logger {
508
518
  };
509
519
  }
510
520
 
511
- export { BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, ForbiddenException, GatewayTimeoutException, HttpVersionNotSupportedException, type IApp, type IControllerMetadata, IGuard, type IMiddleware, type IModuleMetadata, INJECTABLE_METADATA_KEY, IPortRequester, IResponse, type IRouteDefinition, Injectable, InsufficientStorageException, InternalServerException, Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, type NextFunction, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, NoxSocket, type NoxusPreloadAPI, type NoxusPreloadOptions, PaymentRequiredException, Request, RequestTimeoutException, ResponseException, Router, ServiceUnavailableException, TooManyRequestsException, Type, UnauthorizedException, UpgradeRequiredException, UseMiddlewares, VariantAlsoNegotiatesException, bootstrapApplication, exposeNoxusBridge, getControllerMetadata, getInjectableMetadata, getMiddlewaresForController, getMiddlewaresForControllerAction, getModuleMetadata, hasInjectableMetadata };
521
+ export { BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, ForbiddenException, GatewayTimeoutException, HttpVersionNotSupportedException, type IApp, type IControllerMetadata, IGuard, type IMiddleware, type IModuleMetadata, INJECTABLE_METADATA_KEY, INJECT_METADATA_KEY, IPortRequester, IResponse, type IRouteDefinition, Inject, Injectable, InsufficientStorageException, InternalServerException, Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, type NextFunction, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, NoxSocket, type NoxusPreloadAPI, type NoxusPreloadOptions, PaymentRequiredException, Request, RequestTimeoutException, ResponseException, Router, ServiceUnavailableException, TooManyRequestsException, Type, UnauthorizedException, UpgradeRequiredException, UseMiddlewares, VariantAlsoNegotiatesException, bootstrapApplication, exposeNoxusBridge, getControllerMetadata, getInjectableMetadata, getMiddlewaresForController, getMiddlewaresForControllerAction, getModuleMetadata, hasInjectableMetadata };
package/dist/main.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as Request, I as IResponse, M as MaybeAsync, T as Type, a as IGuard, L as Lifetime, b as IPortRequester } from './index-CI3OMzNR.js';
2
- export { A as AppInjector, j as AtomicHttpMethod, e as Authorize, D as Delete, G as Get, H as HttpMethod, p as IBatchRequestItem, q as IBatchRequestPayload, r as IBatchResponsePayload, c as IBinding, t as IRendererEventMessage, o as IRequest, h as IRouteMetadata, N as NoxRendererClient, m as Patch, P as Post, l as Put, s as RENDERER_EVENT_TYPE, n as ROUTE_METADATA_KEY, z as RendererClientOptions, w as RendererEventHandler, y as RendererEventRegistry, x as RendererEventSubscription, d as RootInjector, u as createRendererEventMessage, g as getGuardForController, f as getGuardForControllerAction, k as getRouteMetadata, i as inject, v as isRendererEventMessage } from './index-CI3OMzNR.js';
1
+ import { R as Request, I as IResponse, M as MaybeAsync, T as Type, a as IGuard, L as Lifetime, b as IPortRequester } from './index-Dr-ifUJj.js';
2
+ export { A as AppInjector, j as AtomicHttpMethod, e as Authorize, D as Delete, F as ForwardRefFn, o as ForwardReference, G as Get, H as HttpMethod, r as IBatchRequestItem, s as IBatchRequestPayload, t as IBatchResponsePayload, c as IBinding, v as IRendererEventMessage, q as IRequest, h as IRouteMetadata, N as NoxRendererClient, m as Patch, P as Post, l as Put, u as RENDERER_EVENT_TYPE, n as ROUTE_METADATA_KEY, C as RendererClientOptions, y as RendererEventHandler, B as RendererEventRegistry, z as RendererEventSubscription, d as RootInjector, w as createRendererEventMessage, p as forwardRef, g as getGuardForController, f as getGuardForControllerAction, k as getRouteMetadata, i as inject, x as isRendererEventMessage } from './index-Dr-ifUJj.js';
3
3
 
4
4
  /**
5
5
  * @copyright 2025 NoxFly
@@ -374,6 +374,16 @@ declare function hasInjectableMetadata(target: Function): boolean;
374
374
  declare function Injectable(lifetime?: Lifetime): ClassDecorator;
375
375
 
376
376
 
377
+ declare const INJECT_METADATA_KEY = "custom:inject";
378
+ /**
379
+ * Decorator to manually inject a dependency.
380
+ * Useful for handling circular dependencies with `forwardRef` or injecting specific tokens.
381
+ *
382
+ * @param token The token or forward reference to inject.
383
+ */
384
+ declare function Inject(token: any): ParameterDecorator;
385
+
386
+
377
387
  interface IModuleMetadata {
378
388
  imports?: Type<unknown>[];
379
389
  exports?: Type<unknown>[];
@@ -508,4 +518,4 @@ declare namespace Logger {
508
518
  };
509
519
  }
510
520
 
511
- export { BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, ForbiddenException, GatewayTimeoutException, HttpVersionNotSupportedException, type IApp, type IControllerMetadata, IGuard, type IMiddleware, type IModuleMetadata, INJECTABLE_METADATA_KEY, IPortRequester, IResponse, type IRouteDefinition, Injectable, InsufficientStorageException, InternalServerException, Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, type NextFunction, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, NoxSocket, type NoxusPreloadAPI, type NoxusPreloadOptions, PaymentRequiredException, Request, RequestTimeoutException, ResponseException, Router, ServiceUnavailableException, TooManyRequestsException, Type, UnauthorizedException, UpgradeRequiredException, UseMiddlewares, VariantAlsoNegotiatesException, bootstrapApplication, exposeNoxusBridge, getControllerMetadata, getInjectableMetadata, getMiddlewaresForController, getMiddlewaresForControllerAction, getModuleMetadata, hasInjectableMetadata };
521
+ export { BadGatewayException, BadRequestException, CONTROLLER_METADATA_KEY, ConflictException, Controller, type ControllerAction, ForbiddenException, GatewayTimeoutException, HttpVersionNotSupportedException, type IApp, type IControllerMetadata, IGuard, type IMiddleware, type IModuleMetadata, INJECTABLE_METADATA_KEY, INJECT_METADATA_KEY, IPortRequester, IResponse, type IRouteDefinition, Inject, Injectable, InsufficientStorageException, InternalServerException, Lifetime, type LogLevel, Logger, LoopDetectedException, MODULE_METADATA_KEY, MaybeAsync, MethodNotAllowedException, Module, NetworkAuthenticationRequiredException, NetworkConnectTimeoutException, type NextFunction, NotAcceptableException, NotExtendedException, NotFoundException, NotImplementedException, NoxApp, NoxSocket, type NoxusPreloadAPI, type NoxusPreloadOptions, PaymentRequiredException, Request, RequestTimeoutException, ResponseException, Router, ServiceUnavailableException, TooManyRequestsException, Type, UnauthorizedException, UpgradeRequiredException, UseMiddlewares, VariantAlsoNegotiatesException, bootstrapApplication, exposeNoxusBridge, getControllerMetadata, getInjectableMetadata, getMiddlewaresForController, getMiddlewaresForControllerAction, getModuleMetadata, hasInjectableMetadata };
package/dist/main.js CHANGED
@@ -47,10 +47,13 @@ __export(main_exports, {
47
47
  Controller: () => Controller,
48
48
  Delete: () => Delete,
49
49
  ForbiddenException: () => ForbiddenException,
50
+ ForwardReference: () => ForwardReference,
50
51
  GatewayTimeoutException: () => GatewayTimeoutException,
51
52
  Get: () => Get,
52
53
  HttpVersionNotSupportedException: () => HttpVersionNotSupportedException,
53
54
  INJECTABLE_METADATA_KEY: () => INJECTABLE_METADATA_KEY,
55
+ INJECT_METADATA_KEY: () => INJECT_METADATA_KEY,
56
+ Inject: () => Inject,
54
57
  Injectable: () => Injectable,
55
58
  InsufficientStorageException: () => InsufficientStorageException,
56
59
  InternalServerException: () => InternalServerException,
@@ -89,6 +92,7 @@ __export(main_exports, {
89
92
  bootstrapApplication: () => bootstrapApplication,
90
93
  createRendererEventMessage: () => createRendererEventMessage,
91
94
  exposeNoxusBridge: () => exposeNoxusBridge,
95
+ forwardRef: () => forwardRef,
92
96
  getControllerMetadata: () => getControllerMetadata,
93
97
  getGuardForController: () => getGuardForController,
94
98
  getGuardForControllerAction: () => getGuardForControllerAction,
@@ -104,7 +108,19 @@ __export(main_exports, {
104
108
  module.exports = __toCommonJS(main_exports);
105
109
 
106
110
  // src/DI/app-injector.ts
111
+ var import_reflect_metadata2 = require("reflect-metadata");
112
+
113
+ // src/decorators/inject.decorator.ts
107
114
  var import_reflect_metadata = require("reflect-metadata");
115
+ var INJECT_METADATA_KEY = "custom:inject";
116
+ function Inject(token) {
117
+ return (target, propertyKey, parameterIndex) => {
118
+ const existingParameters = Reflect.getOwnMetadata(INJECT_METADATA_KEY, target) || [];
119
+ existingParameters[parameterIndex] = token;
120
+ Reflect.defineMetadata(INJECT_METADATA_KEY, existingParameters, target);
121
+ };
122
+ }
123
+ __name(Inject, "Inject");
108
124
 
109
125
  // src/exceptions.ts
110
126
  var _ResponseException = class _ResponseException extends Error {
@@ -310,6 +326,20 @@ var _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException exte
310
326
  __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
311
327
  var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
312
328
 
329
+ // src/utils/forward-ref.ts
330
+ var _ForwardReference = class _ForwardReference {
331
+ constructor(forwardRefFn) {
332
+ __publicField(this, "forwardRefFn");
333
+ this.forwardRefFn = forwardRefFn;
334
+ }
335
+ };
336
+ __name(_ForwardReference, "ForwardReference");
337
+ var ForwardReference = _ForwardReference;
338
+ function forwardRef(fn) {
339
+ return new ForwardReference(fn);
340
+ }
341
+ __name(forwardRef, "forwardRef");
342
+
313
343
  // src/DI/app-injector.ts
314
344
  var _AppInjector = class _AppInjector {
315
345
  constructor(name = null) {
@@ -336,9 +366,34 @@ var _AppInjector = class _AppInjector {
336
366
  * i.e., retrieving the instance of a given class.
337
367
  */
338
368
  resolve(target) {
369
+ if (target instanceof ForwardReference) {
370
+ return new Proxy({}, {
371
+ get: /* @__PURE__ */ __name((obj, prop, receiver) => {
372
+ const realType = target.forwardRefFn();
373
+ const instance = this.resolve(realType);
374
+ const value = Reflect.get(instance, prop, receiver);
375
+ return typeof value === "function" ? value.bind(instance) : value;
376
+ }, "get"),
377
+ set: /* @__PURE__ */ __name((obj, prop, value, receiver) => {
378
+ const realType = target.forwardRefFn();
379
+ const instance = this.resolve(realType);
380
+ return Reflect.set(instance, prop, value, receiver);
381
+ }, "set"),
382
+ getPrototypeOf: /* @__PURE__ */ __name(() => {
383
+ const realType = target.forwardRefFn();
384
+ return realType.prototype;
385
+ }, "getPrototypeOf")
386
+ });
387
+ }
339
388
  const binding = this.bindings.get(target);
340
- if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}.
389
+ if (!binding) {
390
+ if (target === void 0) {
391
+ throw new InternalServerException("Failed to resolve a dependency injection : Undefined target type.\nThis might be caused by a circular dependency.");
392
+ }
393
+ const name = target.name || "unknown";
394
+ throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${name}.
341
395
  Did you forget to use @Injectable() decorator ?`);
396
+ }
342
397
  switch (binding.lifetime) {
343
398
  case "transient":
344
399
  return this.instantiate(binding.implementation);
@@ -360,11 +415,16 @@ Did you forget to use @Injectable() decorator ?`);
360
415
  }
361
416
  }
362
417
  /**
363
- *
418
+ * Instantiates a class, resolving its dependencies.
364
419
  */
365
420
  instantiate(target) {
366
421
  const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
367
- const params = paramTypes.map((p) => this.resolve(p));
422
+ const injectParams = Reflect.getMetadata(INJECT_METADATA_KEY, target) || [];
423
+ const params = paramTypes.map((paramType, index) => {
424
+ const overrideToken = injectParams[index];
425
+ const actualToken = overrideToken !== void 0 ? overrideToken : paramType;
426
+ return this.resolve(actualToken);
427
+ });
368
428
  return new target(...params);
369
429
  }
370
430
  };
@@ -377,7 +437,7 @@ __name(inject, "inject");
377
437
  var RootInjector = new AppInjector("root");
378
438
 
379
439
  // src/router.ts
380
- var import_reflect_metadata3 = require("reflect-metadata");
440
+ var import_reflect_metadata4 = require("reflect-metadata");
381
441
 
382
442
  // src/decorators/guards.decorator.ts
383
443
  function Authorize(...guardClasses) {
@@ -864,7 +924,7 @@ __name(getMiddlewaresForControllerAction, "getMiddlewaresForControllerAction");
864
924
  var middlewares = /* @__PURE__ */ new Map();
865
925
 
866
926
  // src/request.ts
867
- var import_reflect_metadata2 = require("reflect-metadata");
927
+ var import_reflect_metadata3 = require("reflect-metadata");
868
928
  var _Request = class _Request {
869
929
  constructor(event, senderId, id, method, path2, body) {
870
930
  __publicField(this, "event");
@@ -2063,10 +2123,13 @@ var NoxRendererClient = _NoxRendererClient;
2063
2123
  Controller,
2064
2124
  Delete,
2065
2125
  ForbiddenException,
2126
+ ForwardReference,
2066
2127
  GatewayTimeoutException,
2067
2128
  Get,
2068
2129
  HttpVersionNotSupportedException,
2069
2130
  INJECTABLE_METADATA_KEY,
2131
+ INJECT_METADATA_KEY,
2132
+ Inject,
2070
2133
  Injectable,
2071
2134
  InsufficientStorageException,
2072
2135
  InternalServerException,
@@ -2105,6 +2168,7 @@ var NoxRendererClient = _NoxRendererClient;
2105
2168
  bootstrapApplication,
2106
2169
  createRendererEventMessage,
2107
2170
  exposeNoxusBridge,
2171
+ forwardRef,
2108
2172
  getControllerMetadata,
2109
2173
  getGuardForController,
2110
2174
  getGuardForControllerAction,
package/dist/main.mjs CHANGED
@@ -11,6 +11,18 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
11
11
  // src/DI/app-injector.ts
12
12
  import "reflect-metadata";
13
13
 
14
+ // src/decorators/inject.decorator.ts
15
+ import "reflect-metadata";
16
+ var INJECT_METADATA_KEY = "custom:inject";
17
+ function Inject(token) {
18
+ return (target, propertyKey, parameterIndex) => {
19
+ const existingParameters = Reflect.getOwnMetadata(INJECT_METADATA_KEY, target) || [];
20
+ existingParameters[parameterIndex] = token;
21
+ Reflect.defineMetadata(INJECT_METADATA_KEY, existingParameters, target);
22
+ };
23
+ }
24
+ __name(Inject, "Inject");
25
+
14
26
  // src/exceptions.ts
15
27
  var _ResponseException = class _ResponseException extends Error {
16
28
  constructor(statusOrMessage, message) {
@@ -215,6 +227,20 @@ var _NetworkConnectTimeoutException = class _NetworkConnectTimeoutException exte
215
227
  __name(_NetworkConnectTimeoutException, "NetworkConnectTimeoutException");
216
228
  var NetworkConnectTimeoutException = _NetworkConnectTimeoutException;
217
229
 
230
+ // src/utils/forward-ref.ts
231
+ var _ForwardReference = class _ForwardReference {
232
+ constructor(forwardRefFn) {
233
+ __publicField(this, "forwardRefFn");
234
+ this.forwardRefFn = forwardRefFn;
235
+ }
236
+ };
237
+ __name(_ForwardReference, "ForwardReference");
238
+ var ForwardReference = _ForwardReference;
239
+ function forwardRef(fn) {
240
+ return new ForwardReference(fn);
241
+ }
242
+ __name(forwardRef, "forwardRef");
243
+
218
244
  // src/DI/app-injector.ts
219
245
  var _AppInjector = class _AppInjector {
220
246
  constructor(name = null) {
@@ -241,9 +267,34 @@ var _AppInjector = class _AppInjector {
241
267
  * i.e., retrieving the instance of a given class.
242
268
  */
243
269
  resolve(target) {
270
+ if (target instanceof ForwardReference) {
271
+ return new Proxy({}, {
272
+ get: /* @__PURE__ */ __name((obj, prop, receiver) => {
273
+ const realType = target.forwardRefFn();
274
+ const instance = this.resolve(realType);
275
+ const value = Reflect.get(instance, prop, receiver);
276
+ return typeof value === "function" ? value.bind(instance) : value;
277
+ }, "get"),
278
+ set: /* @__PURE__ */ __name((obj, prop, value, receiver) => {
279
+ const realType = target.forwardRefFn();
280
+ const instance = this.resolve(realType);
281
+ return Reflect.set(instance, prop, value, receiver);
282
+ }, "set"),
283
+ getPrototypeOf: /* @__PURE__ */ __name(() => {
284
+ const realType = target.forwardRefFn();
285
+ return realType.prototype;
286
+ }, "getPrototypeOf")
287
+ });
288
+ }
244
289
  const binding = this.bindings.get(target);
245
- if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}.
290
+ if (!binding) {
291
+ if (target === void 0) {
292
+ throw new InternalServerException("Failed to resolve a dependency injection : Undefined target type.\nThis might be caused by a circular dependency.");
293
+ }
294
+ const name = target.name || "unknown";
295
+ throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${name}.
246
296
  Did you forget to use @Injectable() decorator ?`);
297
+ }
247
298
  switch (binding.lifetime) {
248
299
  case "transient":
249
300
  return this.instantiate(binding.implementation);
@@ -265,11 +316,16 @@ Did you forget to use @Injectable() decorator ?`);
265
316
  }
266
317
  }
267
318
  /**
268
- *
319
+ * Instantiates a class, resolving its dependencies.
269
320
  */
270
321
  instantiate(target) {
271
322
  const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
272
- const params = paramTypes.map((p) => this.resolve(p));
323
+ const injectParams = Reflect.getMetadata(INJECT_METADATA_KEY, target) || [];
324
+ const params = paramTypes.map((paramType, index) => {
325
+ const overrideToken = injectParams[index];
326
+ const actualToken = overrideToken !== void 0 ? overrideToken : paramType;
327
+ return this.resolve(actualToken);
328
+ });
273
329
  return new target(...params);
274
330
  }
275
331
  };
@@ -1967,10 +2023,13 @@ export {
1967
2023
  Controller,
1968
2024
  Delete,
1969
2025
  ForbiddenException,
2026
+ ForwardReference,
1970
2027
  GatewayTimeoutException,
1971
2028
  Get,
1972
2029
  HttpVersionNotSupportedException,
1973
2030
  INJECTABLE_METADATA_KEY,
2031
+ INJECT_METADATA_KEY,
2032
+ Inject,
1974
2033
  Injectable,
1975
2034
  InsufficientStorageException,
1976
2035
  InternalServerException,
@@ -2009,6 +2068,7 @@ export {
2009
2068
  bootstrapApplication,
2010
2069
  createRendererEventMessage,
2011
2070
  exposeNoxusBridge,
2071
+ forwardRef,
2012
2072
  getControllerMetadata,
2013
2073
  getGuardForController,
2014
2074
  getGuardForControllerAction,
@@ -1 +1 @@
1
- export { p as IBatchRequestItem, q as IBatchRequestPayload, r as IBatchResponsePayload, b as IPortRequester, t as IRendererEventMessage, o as IRequest, I as IResponse, N as NoxRendererClient, s as RENDERER_EVENT_TYPE, z as RendererClientOptions, w as RendererEventHandler, y as RendererEventRegistry, x as RendererEventSubscription, R as Request, u as createRendererEventMessage, v as isRendererEventMessage } from './index-CI3OMzNR.mjs';
1
+ export { r as IBatchRequestItem, s as IBatchRequestPayload, t as IBatchResponsePayload, b as IPortRequester, v as IRendererEventMessage, q as IRequest, I as IResponse, N as NoxRendererClient, u as RENDERER_EVENT_TYPE, C as RendererClientOptions, y as RendererEventHandler, B as RendererEventRegistry, z as RendererEventSubscription, R as Request, w as createRendererEventMessage, x as isRendererEventMessage } from './index-Dr-ifUJj.mjs';
@@ -1 +1 @@
1
- export { p as IBatchRequestItem, q as IBatchRequestPayload, r as IBatchResponsePayload, b as IPortRequester, t as IRendererEventMessage, o as IRequest, I as IResponse, N as NoxRendererClient, s as RENDERER_EVENT_TYPE, z as RendererClientOptions, w as RendererEventHandler, y as RendererEventRegistry, x as RendererEventSubscription, R as Request, u as createRendererEventMessage, v as isRendererEventMessage } from './index-CI3OMzNR.js';
1
+ export { r as IBatchRequestItem, s as IBatchRequestPayload, t as IBatchResponsePayload, b as IPortRequester, v as IRendererEventMessage, q as IRequest, I as IResponse, N as NoxRendererClient, u as RENDERER_EVENT_TYPE, C as RendererClientOptions, y as RendererEventHandler, B as RendererEventRegistry, z as RendererEventSubscription, R as Request, w as createRendererEventMessage, x as isRendererEventMessage } from './index-Dr-ifUJj.js';
package/dist/renderer.js CHANGED
@@ -38,10 +38,14 @@ __export(src_exports, {
38
38
  module.exports = __toCommonJS(src_exports);
39
39
 
40
40
  // src/request.ts
41
- var import_reflect_metadata2 = require("reflect-metadata");
41
+ var import_reflect_metadata3 = require("reflect-metadata");
42
42
 
43
43
  // src/DI/app-injector.ts
44
+ var import_reflect_metadata2 = require("reflect-metadata");
45
+
46
+ // src/decorators/inject.decorator.ts
44
47
  var import_reflect_metadata = require("reflect-metadata");
48
+ var INJECT_METADATA_KEY = "custom:inject";
45
49
 
46
50
  // src/exceptions.ts
47
51
  var _ResponseException = class _ResponseException extends Error {
@@ -71,6 +75,16 @@ var _InternalServerException = class _InternalServerException extends ResponseEx
71
75
  __name(_InternalServerException, "InternalServerException");
72
76
  var InternalServerException = _InternalServerException;
73
77
 
78
+ // src/utils/forward-ref.ts
79
+ var _ForwardReference = class _ForwardReference {
80
+ constructor(forwardRefFn) {
81
+ __publicField(this, "forwardRefFn");
82
+ this.forwardRefFn = forwardRefFn;
83
+ }
84
+ };
85
+ __name(_ForwardReference, "ForwardReference");
86
+ var ForwardReference = _ForwardReference;
87
+
74
88
  // src/DI/app-injector.ts
75
89
  var _AppInjector = class _AppInjector {
76
90
  constructor(name = null) {
@@ -97,9 +111,34 @@ var _AppInjector = class _AppInjector {
97
111
  * i.e., retrieving the instance of a given class.
98
112
  */
99
113
  resolve(target) {
114
+ if (target instanceof ForwardReference) {
115
+ return new Proxy({}, {
116
+ get: /* @__PURE__ */ __name((obj, prop, receiver) => {
117
+ const realType = target.forwardRefFn();
118
+ const instance = this.resolve(realType);
119
+ const value = Reflect.get(instance, prop, receiver);
120
+ return typeof value === "function" ? value.bind(instance) : value;
121
+ }, "get"),
122
+ set: /* @__PURE__ */ __name((obj, prop, value, receiver) => {
123
+ const realType = target.forwardRefFn();
124
+ const instance = this.resolve(realType);
125
+ return Reflect.set(instance, prop, value, receiver);
126
+ }, "set"),
127
+ getPrototypeOf: /* @__PURE__ */ __name(() => {
128
+ const realType = target.forwardRefFn();
129
+ return realType.prototype;
130
+ }, "getPrototypeOf")
131
+ });
132
+ }
100
133
  const binding = this.bindings.get(target);
101
- if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}.
134
+ if (!binding) {
135
+ if (target === void 0) {
136
+ throw new InternalServerException("Failed to resolve a dependency injection : Undefined target type.\nThis might be caused by a circular dependency.");
137
+ }
138
+ const name = target.name || "unknown";
139
+ throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${name}.
102
140
  Did you forget to use @Injectable() decorator ?`);
141
+ }
103
142
  switch (binding.lifetime) {
104
143
  case "transient":
105
144
  return this.instantiate(binding.implementation);
@@ -121,11 +160,16 @@ Did you forget to use @Injectable() decorator ?`);
121
160
  }
122
161
  }
123
162
  /**
124
- *
163
+ * Instantiates a class, resolving its dependencies.
125
164
  */
126
165
  instantiate(target) {
127
166
  const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
128
- const params = paramTypes.map((p) => this.resolve(p));
167
+ const injectParams = Reflect.getMetadata(INJECT_METADATA_KEY, target) || [];
168
+ const params = paramTypes.map((paramType, index) => {
169
+ const overrideToken = injectParams[index];
170
+ const actualToken = overrideToken !== void 0 ? overrideToken : paramType;
171
+ return this.resolve(actualToken);
172
+ });
129
173
  return new target(...params);
130
174
  }
131
175
  };
package/dist/renderer.mjs CHANGED
@@ -14,6 +14,10 @@ import "reflect-metadata";
14
14
  // src/DI/app-injector.ts
15
15
  import "reflect-metadata";
16
16
 
17
+ // src/decorators/inject.decorator.ts
18
+ import "reflect-metadata";
19
+ var INJECT_METADATA_KEY = "custom:inject";
20
+
17
21
  // src/exceptions.ts
18
22
  var _ResponseException = class _ResponseException extends Error {
19
23
  constructor(statusOrMessage, message) {
@@ -42,6 +46,16 @@ var _InternalServerException = class _InternalServerException extends ResponseEx
42
46
  __name(_InternalServerException, "InternalServerException");
43
47
  var InternalServerException = _InternalServerException;
44
48
 
49
+ // src/utils/forward-ref.ts
50
+ var _ForwardReference = class _ForwardReference {
51
+ constructor(forwardRefFn) {
52
+ __publicField(this, "forwardRefFn");
53
+ this.forwardRefFn = forwardRefFn;
54
+ }
55
+ };
56
+ __name(_ForwardReference, "ForwardReference");
57
+ var ForwardReference = _ForwardReference;
58
+
45
59
  // src/DI/app-injector.ts
46
60
  var _AppInjector = class _AppInjector {
47
61
  constructor(name = null) {
@@ -68,9 +82,34 @@ var _AppInjector = class _AppInjector {
68
82
  * i.e., retrieving the instance of a given class.
69
83
  */
70
84
  resolve(target) {
85
+ if (target instanceof ForwardReference) {
86
+ return new Proxy({}, {
87
+ get: /* @__PURE__ */ __name((obj, prop, receiver) => {
88
+ const realType = target.forwardRefFn();
89
+ const instance = this.resolve(realType);
90
+ const value = Reflect.get(instance, prop, receiver);
91
+ return typeof value === "function" ? value.bind(instance) : value;
92
+ }, "get"),
93
+ set: /* @__PURE__ */ __name((obj, prop, value, receiver) => {
94
+ const realType = target.forwardRefFn();
95
+ const instance = this.resolve(realType);
96
+ return Reflect.set(instance, prop, value, receiver);
97
+ }, "set"),
98
+ getPrototypeOf: /* @__PURE__ */ __name(() => {
99
+ const realType = target.forwardRefFn();
100
+ return realType.prototype;
101
+ }, "getPrototypeOf")
102
+ });
103
+ }
71
104
  const binding = this.bindings.get(target);
72
- if (!binding) throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${target.name}.
105
+ if (!binding) {
106
+ if (target === void 0) {
107
+ throw new InternalServerException("Failed to resolve a dependency injection : Undefined target type.\nThis might be caused by a circular dependency.");
108
+ }
109
+ const name = target.name || "unknown";
110
+ throw new InternalServerException(`Failed to resolve a dependency injection : No binding for type ${name}.
73
111
  Did you forget to use @Injectable() decorator ?`);
112
+ }
74
113
  switch (binding.lifetime) {
75
114
  case "transient":
76
115
  return this.instantiate(binding.implementation);
@@ -92,11 +131,16 @@ Did you forget to use @Injectable() decorator ?`);
92
131
  }
93
132
  }
94
133
  /**
95
- *
134
+ * Instantiates a class, resolving its dependencies.
96
135
  */
97
136
  instantiate(target) {
98
137
  const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
99
- const params = paramTypes.map((p) => this.resolve(p));
138
+ const injectParams = Reflect.getMetadata(INJECT_METADATA_KEY, target) || [];
139
+ const params = paramTypes.map((paramType, index) => {
140
+ const overrideToken = injectParams[index];
141
+ const actualToken = overrideToken !== void 0 ? overrideToken : paramType;
142
+ return this.resolve(actualToken);
143
+ });
100
144
  return new target(...params);
101
145
  }
102
146
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noxfly/noxus",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "main": "dist/main.js",
5
5
  "module": "dist/main.mjs",
6
6
  "types": "dist/main.d.ts",
@@ -5,7 +5,9 @@
5
5
  */
6
6
 
7
7
  import 'reflect-metadata';
8
+ import { INJECT_METADATA_KEY } from 'src/decorators/inject.decorator';
8
9
  import { InternalServerException } from 'src/exceptions';
10
+ import { ForwardReference } from 'src/utils/forward-ref';
9
11
  import { Type } from 'src/utils/types';
10
12
 
11
13
  /**
@@ -61,28 +63,59 @@ export class AppInjector {
61
63
  * Called when resolving a dependency,
62
64
  * i.e., retrieving the instance of a given class.
63
65
  */
64
- public resolve<T extends Type<unknown>>(target: T): InstanceType<T> {
66
+ public resolve<T>(target: Type<T> | ForwardReference<T>): T {
67
+ if (target instanceof ForwardReference) {
68
+ return new Proxy({}, {
69
+ get: (obj, prop, receiver) => {
70
+ const realType = target.forwardRefFn();
71
+ const instance = this.resolve(realType) as any;
72
+ const value = Reflect.get(instance, prop, receiver);
73
+
74
+ return typeof value === 'function' ? value.bind(instance) : value;
75
+ },
76
+ set: (obj, prop, value, receiver) => {
77
+ const realType = target.forwardRefFn();
78
+ const instance = this.resolve(realType) as any;
79
+ return Reflect.set(instance, prop, value, receiver);
80
+ },
81
+ getPrototypeOf: () => {
82
+ const realType = target.forwardRefFn();
83
+ return (realType as any).prototype;
84
+ }
85
+ }) as T;
86
+ }
87
+
65
88
  const binding = this.bindings.get(target);
66
89
 
67
- if(!binding)
90
+ if(!binding) {
91
+ if(target === undefined) {
92
+ throw new InternalServerException(
93
+ "Failed to resolve a dependency injection : Undefined target type.\n"
94
+ + "This might be caused by a circular dependency."
95
+ );
96
+ }
97
+
98
+ const name = target.name || "unknown";
99
+
68
100
  throw new InternalServerException(
69
- `Failed to resolve a dependency injection : No binding for type ${target.name}.\n`
101
+ `Failed to resolve a dependency injection : No binding for type ${name}.\n`
70
102
  + `Did you forget to use @Injectable() decorator ?`
71
103
  );
104
+ }
72
105
 
73
106
  switch(binding.lifetime) {
74
107
  case 'transient':
75
- return this.instantiate(binding.implementation) as InstanceType<T>;
108
+ return this.instantiate(binding.implementation) as T;
76
109
 
77
110
  case 'scope': {
78
111
  if(this.scoped.has(target)) {
79
- return this.scoped.get(target) as InstanceType<T>;
112
+ return this.scoped.get(target) as T;
80
113
  }
81
114
 
82
115
  const instance = this.instantiate(binding.implementation);
83
116
  this.scoped.set(target, instance);
84
117
 
85
- return instance as InstanceType<T>;
118
+ return instance as T;
86
119
  }
87
120
 
88
121
  case 'singleton': {
@@ -91,17 +124,25 @@ export class AppInjector {
91
124
  this.singletons.set(target, binding.instance);
92
125
  }
93
126
 
94
- return binding.instance as InstanceType<T>;
127
+ return binding.instance as T;
95
128
  }
96
129
  }
97
130
  }
98
131
 
99
132
  /**
100
- *
133
+ * Instantiates a class, resolving its dependencies.
101
134
  */
102
135
  private instantiate<T extends Type<unknown>>(target: T): InstanceType<T> {
103
136
  const paramTypes = Reflect.getMetadata('design:paramtypes', target) || [];
104
- const params = paramTypes.map((p: any) => this.resolve(p));
137
+ const injectParams = Reflect.getMetadata(INJECT_METADATA_KEY, target) || [];
138
+
139
+ const params = paramTypes.map((paramType: any, index: number) => {
140
+ const overrideToken = injectParams[index];
141
+ const actualToken = overrideToken !== undefined ? overrideToken : paramType;
142
+
143
+ return this.resolve(actualToken);
144
+ });
145
+
105
146
  return new target(...params) as InstanceType<T>;
106
147
  }
107
148
  }
@@ -114,7 +155,7 @@ export class AppInjector {
114
155
  * @returns An instance of the type.
115
156
  * @throws If the type is not registered in the dependency injection system.
116
157
  */
117
- export function inject<T>(t: Type<T>): T {
158
+ export function inject<T>(t: Type<T> | ForwardReference<T>): T {
118
159
  return RootInjector.resolve(t);
119
160
  }
120
161
 
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @copyright 2025 NoxFly
3
+ * @license MIT
4
+ * @author NoxFly
5
+ */
6
+
7
+ import 'reflect-metadata';
8
+
9
+ export const INJECT_METADATA_KEY = 'custom:inject';
10
+
11
+ /**
12
+ * Decorator to manually inject a dependency.
13
+ * Useful for handling circular dependencies with `forwardRef` or injecting specific tokens.
14
+ *
15
+ * @param token The token or forward reference to inject.
16
+ */
17
+ export function Inject(token: any): ParameterDecorator {
18
+ return (target, propertyKey, parameterIndex) => {
19
+ // target is the constructor for constructor parameters
20
+ const existingParameters = Reflect.getOwnMetadata(INJECT_METADATA_KEY, target) || [];
21
+ existingParameters[parameterIndex] = token;
22
+ Reflect.defineMetadata(INJECT_METADATA_KEY, existingParameters, target);
23
+ };
24
+ }
package/src/main.ts CHANGED
@@ -19,11 +19,13 @@ export * from './decorators/middleware.decorator';
19
19
  export * from './decorators/guards.decorator';
20
20
  export * from './decorators/controller.decorator';
21
21
  export * from './decorators/injectable.decorator';
22
+ export * from './decorators/inject.decorator';
22
23
  export * from './decorators/method.decorator';
23
24
  export * from './decorators/module.decorator';
24
25
  export * from './preload-bridge';
25
26
  export * from './utils/logger';
26
27
  export * from './utils/types';
28
+ export * from './utils/forward-ref';
27
29
  export * from './request';
28
30
  export * from './renderer-events';
29
31
  export * from './renderer-client';
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @copyright 2025 NoxFly
3
+ * @license MIT
4
+ * @author NoxFly
5
+ */
6
+
7
+ import { Type } from "./types";
8
+
9
+ /**
10
+ * A function that returns a type.
11
+ * Used for forward references to types that are not yet defined.
12
+ */
13
+ export interface ForwardRefFn<T = any> {
14
+ (): Type<T>;
15
+ }
16
+
17
+ /**
18
+ * A wrapper class for forward referenced types.
19
+ */
20
+ export class ForwardReference<T = any> {
21
+ constructor(public readonly forwardRefFn: ForwardRefFn<T>) {}
22
+ }
23
+
24
+ /**
25
+ * Creates a forward reference to a type.
26
+ * @param fn A function that returns the type.
27
+ * @returns A ForwardReference instance.
28
+ */
29
+ export function forwardRef<T = any>(fn: ForwardRefFn<T>): ForwardReference<T> {
30
+ return new ForwardReference(fn);
31
+ }