@velajs/vela 0.4.3 → 0.5.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 (63) hide show
  1. package/dist/cache/cache.module.d.ts +4 -1
  2. package/dist/cache/cache.module.js +51 -9
  3. package/dist/config/config.module.d.ts +4 -1
  4. package/dist/config/config.module.js +40 -3
  5. package/dist/config/config.types.d.ts +1 -0
  6. package/dist/constants.d.ts +6 -1
  7. package/dist/constants.js +5 -0
  8. package/dist/container/container.d.ts +2 -0
  9. package/dist/container/container.js +47 -15
  10. package/dist/container/decorators.d.ts +3 -1
  11. package/dist/container/decorators.js +27 -6
  12. package/dist/container/index.d.ts +4 -2
  13. package/dist/container/index.js +4 -2
  14. package/dist/container/mixin.d.ts +24 -0
  15. package/dist/container/mixin.js +26 -0
  16. package/dist/container/module-ref.d.ts +21 -0
  17. package/dist/container/module-ref.js +48 -0
  18. package/dist/container/types.d.ts +9 -3
  19. package/dist/container/types.js +9 -0
  20. package/dist/cors/cors.module.js +2 -2
  21. package/dist/factory.js +11 -2
  22. package/dist/fetch/fetch.module.d.ts +6 -0
  23. package/dist/fetch/fetch.module.js +77 -0
  24. package/dist/fetch/fetch.service.d.ts +24 -0
  25. package/dist/fetch/fetch.service.js +145 -0
  26. package/dist/fetch/fetch.types.d.ts +24 -0
  27. package/dist/fetch/fetch.types.js +1 -0
  28. package/dist/fetch/index.d.ts +3 -0
  29. package/dist/fetch/index.js +2 -0
  30. package/dist/http/decorators.d.ts +64 -0
  31. package/dist/http/decorators.js +89 -1
  32. package/dist/http/index.d.ts +3 -1
  33. package/dist/http/index.js +2 -1
  34. package/dist/http/middleware-consumer.d.ts +36 -0
  35. package/dist/http/middleware-consumer.js +71 -0
  36. package/dist/http/route.manager.d.ts +4 -0
  37. package/dist/http/route.manager.js +75 -1
  38. package/dist/index.d.ts +11 -6
  39. package/dist/index.js +7 -4
  40. package/dist/metadata.d.ts +1 -1
  41. package/dist/module/decorators.d.ts +1 -0
  42. package/dist/module/decorators.js +24 -8
  43. package/dist/module/index.d.ts +2 -2
  44. package/dist/module/index.js +1 -1
  45. package/dist/module/module-loader.d.ts +5 -1
  46. package/dist/module/module-loader.js +54 -10
  47. package/dist/module/types.d.ts +13 -3
  48. package/dist/pipeline/index.d.ts +3 -2
  49. package/dist/pipeline/index.js +1 -1
  50. package/dist/pipeline/pipes.d.ts +22 -0
  51. package/dist/pipeline/pipes.js +50 -0
  52. package/dist/pipeline/tokens.d.ts +1 -1
  53. package/dist/pipeline/tokens.js +1 -1
  54. package/dist/pipeline/types.d.ts +16 -0
  55. package/dist/registry/metadata.registry.d.ts +7 -6
  56. package/dist/registry/metadata.registry.js +13 -0
  57. package/dist/registry/types.d.ts +1 -0
  58. package/dist/schedule/schedule.module.d.ts +4 -1
  59. package/dist/schedule/schedule.module.js +39 -7
  60. package/dist/testing/testing.builder.js +5 -5
  61. package/dist/throttler/throttler.module.d.ts +2 -1
  62. package/dist/throttler/throttler.module.js +47 -9
  63. package/package.json +1 -1
@@ -1,5 +1,8 @@
1
- import type { DynamicModule } from '../module/types';
1
+ import type { AsyncModuleOptions, DynamicModule } from '../module/types';
2
2
  import type { CacheModuleOptions } from './cache.types';
3
3
  export declare class CacheModule {
4
4
  static forRoot(options?: CacheModuleOptions): DynamicModule;
5
+ static registerAsync(options: AsyncModuleOptions<CacheModuleOptions> & {
6
+ isGlobal?: boolean;
7
+ }): DynamicModule;
5
8
  }
@@ -6,16 +6,20 @@ import { CacheInterceptor } from "./cache.interceptor.js";
6
6
  import { CacheService } from "./cache.service.js";
7
7
  import { MemoryCacheStore } from "./cache.store.js";
8
8
  import { CACHE_MANAGER, CACHE_MODULE_OPTIONS } from "./cache.tokens.js";
9
+ function makeCacheModuleClass(name) {
10
+ const moduleClass = class {
11
+ };
12
+ Object.defineProperty(moduleClass, 'name', {
13
+ value: name
14
+ });
15
+ defineMetadata(METADATA_KEYS.MODULE, true, moduleClass);
16
+ return moduleClass;
17
+ }
9
18
  export class CacheModule {
10
19
  static forRoot(options = {}) {
11
20
  const { ttl = 5, max = 100, isGlobal = false } = options;
12
21
  const store = new MemoryCacheStore(ttl, max);
13
- const moduleClass = class CacheDynamicModule {
14
- };
15
- Object.defineProperty(moduleClass, 'name', {
16
- value: 'CacheModule'
17
- });
18
- defineMetadata(METADATA_KEYS.MODULE, true, moduleClass);
22
+ const moduleClass = makeCacheModuleClass('CacheModule');
19
23
  MetadataRegistry.setModuleOptions(moduleClass, {
20
24
  exports: [
21
25
  CACHE_MANAGER,
@@ -26,11 +30,11 @@ export class CacheModule {
26
30
  });
27
31
  const providers = [
28
32
  {
29
- token: CACHE_MANAGER,
33
+ provide: CACHE_MANAGER,
30
34
  useValue: store
31
35
  },
32
36
  {
33
- token: CACHE_MODULE_OPTIONS,
37
+ provide: CACHE_MODULE_OPTIONS,
34
38
  useValue: options
35
39
  },
36
40
  CacheService,
@@ -38,7 +42,45 @@ export class CacheModule {
38
42
  ];
39
43
  if (isGlobal) {
40
44
  providers.push({
41
- token: APP_INTERCEPTOR,
45
+ provide: APP_INTERCEPTOR,
46
+ useExisting: CacheInterceptor
47
+ });
48
+ }
49
+ return {
50
+ module: moduleClass,
51
+ providers
52
+ };
53
+ }
54
+ static registerAsync(options) {
55
+ const moduleClass = makeCacheModuleClass('CacheModule');
56
+ MetadataRegistry.setModuleOptions(moduleClass, {
57
+ imports: options.imports ?? [],
58
+ exports: [
59
+ CACHE_MANAGER,
60
+ CACHE_MODULE_OPTIONS,
61
+ CacheService,
62
+ CacheInterceptor
63
+ ]
64
+ });
65
+ const providers = [
66
+ {
67
+ provide: CACHE_MODULE_OPTIONS,
68
+ useFactory: options.useFactory,
69
+ inject: options.inject ?? []
70
+ },
71
+ {
72
+ provide: CACHE_MANAGER,
73
+ useFactory: (opts)=>new MemoryCacheStore(opts.ttl ?? 5, opts.max ?? 100),
74
+ inject: [
75
+ CACHE_MODULE_OPTIONS
76
+ ]
77
+ },
78
+ CacheService,
79
+ CacheInterceptor
80
+ ];
81
+ if (options.isGlobal) {
82
+ providers.push({
83
+ provide: APP_INTERCEPTOR,
42
84
  useExisting: CacheInterceptor
43
85
  });
44
86
  }
@@ -1,5 +1,8 @@
1
- import type { DynamicModule } from '../module/types';
1
+ import type { AsyncModuleOptions, DynamicModule } from '../module/types';
2
2
  import type { ConfigModuleOptions } from './config.types';
3
3
  export declare class ConfigModule {
4
4
  static forRoot<T extends Record<string, unknown>>(options: ConfigModuleOptions<T>): DynamicModule;
5
+ static forRootAsync<T extends Record<string, unknown>>(options: AsyncModuleOptions<ConfigModuleOptions<T>> & {
6
+ isGlobal?: boolean;
7
+ }): DynamicModule;
5
8
  }
@@ -16,17 +16,54 @@ export class ConfigModule {
16
16
  exports: [
17
17
  ConfigService,
18
18
  CONFIG_OPTIONS
19
- ]
19
+ ],
20
+ isGlobal: options.isGlobal
20
21
  });
21
22
  return {
22
23
  module: moduleClass,
23
24
  providers: [
24
25
  {
25
- token: CONFIG_OPTIONS,
26
+ provide: CONFIG_OPTIONS,
26
27
  useValue: config
27
28
  },
28
29
  ConfigService
29
- ]
30
+ ],
31
+ ...options.isGlobal ? {
32
+ global: true
33
+ } : {}
34
+ };
35
+ }
36
+ static forRootAsync(options) {
37
+ const moduleClass = class ConfigAsyncDynamicModule {
38
+ };
39
+ Object.defineProperty(moduleClass, 'name', {
40
+ value: 'ConfigModule'
41
+ });
42
+ defineMetadata(METADATA_KEYS.MODULE, true, moduleClass);
43
+ MetadataRegistry.setModuleOptions(moduleClass, {
44
+ imports: options.imports ?? [],
45
+ exports: [
46
+ ConfigService,
47
+ CONFIG_OPTIONS
48
+ ],
49
+ isGlobal: options.isGlobal
50
+ });
51
+ return {
52
+ module: moduleClass,
53
+ providers: [
54
+ {
55
+ provide: CONFIG_OPTIONS,
56
+ useFactory: async (...args)=>{
57
+ const opts = await options.useFactory(...args);
58
+ return opts.validate ? opts.validate(opts.config) : opts.config;
59
+ },
60
+ inject: options.inject ?? []
61
+ },
62
+ ConfigService
63
+ ],
64
+ ...options.isGlobal ? {
65
+ global: true
66
+ } : {}
30
67
  };
31
68
  }
32
69
  }
@@ -1,4 +1,5 @@
1
1
  export interface ConfigModuleOptions<T extends Record<string, unknown> = Record<string, unknown>> {
2
2
  config: T;
3
3
  validate?: (config: T) => T;
4
+ isGlobal?: boolean;
4
5
  }
@@ -3,6 +3,7 @@ export declare const METADATA_KEYS: {
3
3
  readonly INJECT: "vela:inject";
4
4
  readonly SCOPE: "vela:scope";
5
5
  readonly MODULE: "vela:module";
6
+ readonly MODULE_OPTIONS: "vela:module-options";
6
7
  readonly CONTROLLER: "vela:controller";
7
8
  readonly ROUTES: "vela:routes";
8
9
  readonly PARAMS: "vela:params";
@@ -26,7 +27,11 @@ export declare enum ParamType {
26
27
  QUERY = "query",
27
28
  PARAM = "param",
28
29
  HEADERS = "headers",
29
- REQUEST = "request"
30
+ REQUEST = "request",
31
+ RESPONSE = "response",
32
+ IP = "ip",
33
+ COOKIE = "cookie",
34
+ RAW_BODY = "raw_body"
30
35
  }
31
36
  export declare enum Scope {
32
37
  SINGLETON = "singleton",
package/dist/constants.js CHANGED
@@ -5,6 +5,7 @@ export const METADATA_KEYS = {
5
5
  SCOPE: 'vela:scope',
6
6
  // Module
7
7
  MODULE: 'vela:module',
8
+ MODULE_OPTIONS: 'vela:module-options',
8
9
  // HTTP
9
10
  CONTROLLER: 'vela:controller',
10
11
  ROUTES: 'vela:routes',
@@ -33,6 +34,10 @@ export var ParamType = /*#__PURE__*/ function(ParamType) {
33
34
  ParamType["PARAM"] = "param";
34
35
  ParamType["HEADERS"] = "headers";
35
36
  ParamType["REQUEST"] = "request";
37
+ ParamType["RESPONSE"] = "response";
38
+ ParamType["IP"] = "ip";
39
+ ParamType["COOKIE"] = "cookie";
40
+ ParamType["RAW_BODY"] = "raw_body";
36
41
  return ParamType;
37
42
  }({});
38
43
  export var Scope = /*#__PURE__*/ function(Scope) {
@@ -18,10 +18,12 @@ export declare class Container {
18
18
  * instances separately per child (per request).
19
19
  */
20
20
  createChild(): Container;
21
+ createDetached(): Container;
21
22
  clear(): void;
22
23
  private resolveRegistration;
23
24
  private resolveClass;
24
25
  private resolveFactory;
25
26
  resolveAsync<T>(token: Token<T>): Promise<T>;
27
+ private createLazyProxy;
26
28
  private tokenToString;
27
29
  }
@@ -1,6 +1,6 @@
1
1
  import { Scope } from "../constants.js";
2
2
  import { getConstructorDependencies, getInjectMetadata, getScope, isInjectable } from "./decorators.js";
3
- import { InjectionToken } from "./types.js";
3
+ import { ForwardRef, InjectionToken } from "./types.js";
4
4
  export class Container {
5
5
  providers = new Map();
6
6
  resolutionStack = new Set();
@@ -20,18 +20,18 @@ export class Container {
20
20
  }
21
21
  const scope = getScope(target);
22
22
  this.providers.set(target, {
23
- token: target,
23
+ provide: target,
24
24
  scope,
25
25
  useClass: target
26
26
  });
27
27
  }
28
28
  registerOptions(options) {
29
- const token = options.token;
29
+ const token = options.provide;
30
30
  if (!token) {
31
31
  throw new Error('Provider registration requires a token');
32
32
  }
33
33
  const registration = {
34
- token,
34
+ provide: token,
35
35
  scope: options.scope ?? Scope.SINGLETON
36
36
  };
37
37
  if (options.useValue !== undefined) {
@@ -58,7 +58,7 @@ export class Container {
58
58
  }
59
59
  if (token instanceof InjectionToken && token.options?.factory) {
60
60
  this.register({
61
- token,
61
+ provide: token,
62
62
  useFactory: token.options.factory
63
63
  });
64
64
  return this.resolve(token);
@@ -86,6 +86,11 @@ export class Container {
86
86
  child.providers = this.providers; // share provider registrations
87
87
  return child;
88
88
  }
89
+ createDetached() {
90
+ const child = new Container();
91
+ child.providers = new Map(this.providers); // copy, not share
92
+ return child;
93
+ }
89
94
  clear() {
90
95
  this.providers.clear();
91
96
  this.resolutionStack.clear();
@@ -104,19 +109,19 @@ export class Container {
104
109
  }
105
110
  // Request: return cached from this child's requestInstances
106
111
  if (registration.scope === Scope.REQUEST) {
107
- const cached = this.requestInstances.get(registration.token);
112
+ const cached = this.requestInstances.get(registration.provide);
108
113
  if (cached !== undefined) {
109
114
  return cached;
110
115
  }
111
116
  }
112
- if (this.resolutionStack.has(registration.token)) {
117
+ if (this.resolutionStack.has(registration.provide)) {
113
118
  const chain = [
114
119
  ...this.resolutionStack,
115
- registration.token
120
+ registration.provide
116
121
  ].map((t)=>this.tokenToString(t)).join(' -> ');
117
122
  throw new Error(`Circular dependency detected: ${chain}`);
118
123
  }
119
- this.resolutionStack.add(registration.token);
124
+ this.resolutionStack.add(registration.provide);
120
125
  try {
121
126
  let instance;
122
127
  if (registration.useFactory) {
@@ -124,16 +129,16 @@ export class Container {
124
129
  } else if (registration.useClass) {
125
130
  instance = this.resolveClass(registration.useClass);
126
131
  } else {
127
- throw new Error(`Invalid provider registration for: ${this.tokenToString(registration.token)}`);
132
+ throw new Error(`Invalid provider registration for: ${this.tokenToString(registration.provide)}`);
128
133
  }
129
134
  if (registration.scope === Scope.SINGLETON) {
130
135
  registration.instance = instance;
131
136
  } else if (registration.scope === Scope.REQUEST) {
132
- this.requestInstances.set(registration.token, instance);
137
+ this.requestInstances.set(registration.provide, instance);
133
138
  }
134
139
  return instance;
135
140
  } finally{
136
- this.resolutionStack.delete(registration.token);
141
+ this.resolutionStack.delete(registration.provide);
137
142
  }
138
143
  }
139
144
  resolveClass(target) {
@@ -141,13 +146,24 @@ export class Container {
141
146
  const injectMetadata = getInjectMetadata(target);
142
147
  const injectMap = new Map(injectMetadata.map((m)=>[
143
148
  m.index,
144
- m.token
149
+ m
145
150
  ]));
146
151
  const dependencies = paramTypes.map((paramType, index)=>{
147
- const token = injectMap.get(index) ?? paramType;
152
+ const meta = injectMap.get(index);
153
+ const rawToken = meta?.token;
154
+ const isForwardRef = rawToken instanceof ForwardRef;
155
+ const token = isForwardRef ? rawToken.factory() : rawToken ?? paramType;
148
156
  if (!token || token === Object) {
157
+ if (meta?.optional) return undefined;
149
158
  throw new Error(`Cannot resolve dependency at index ${index} for ${target.name}. ` + `Parameter type is undefined or Object. ` + `Use @Inject() to specify the token explicitly.`);
150
159
  }
160
+ if (meta?.optional && !this.has(token)) {
161
+ return undefined;
162
+ }
163
+ // forwardRef with circular dep — break the cycle with a lazy Proxy
164
+ if (isForwardRef && this.resolutionStack.has(token)) {
165
+ return this.createLazyProxy(token);
166
+ }
151
167
  return this.resolve(token);
152
168
  });
153
169
  return new target(...dependencies);
@@ -159,7 +175,7 @@ export class Container {
159
175
  const dependencies = (registration.inject || []).map((token)=>this.resolve(token));
160
176
  const result = registration.useFactory(...dependencies);
161
177
  if (result instanceof Promise) {
162
- throw new Error(`Async factory for ${this.tokenToString(registration.token)} returned a Promise. ` + `Use resolveAsync() for async providers.`);
178
+ throw new Error(`Async factory for ${this.tokenToString(registration.provide)} returned a Promise. ` + `Use resolveAsync() for async providers.`);
163
179
  }
164
180
  return result;
165
181
  }
@@ -185,6 +201,22 @@ export class Container {
185
201
  }
186
202
  return this.resolve(token);
187
203
  }
204
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
205
+ createLazyProxy(token) {
206
+ const container = this;
207
+ return new Proxy({}, {
208
+ get (_target, prop) {
209
+ const instance = container.resolve(token);
210
+ const value = instance[prop];
211
+ return typeof value === 'function' ? value.bind(instance) : value;
212
+ },
213
+ set (_target, prop, value) {
214
+ const instance = container.resolve(token);
215
+ instance[prop] = value;
216
+ return true;
217
+ }
218
+ });
219
+ }
188
220
  tokenToString(token) {
189
221
  if (token instanceof InjectionToken) {
190
222
  return token.toString();
@@ -1,7 +1,9 @@
1
1
  import { Scope } from '../constants';
2
2
  import type { InjectableOptions, InjectMetadata, Token } from './types';
3
+ import { ForwardRef } from './types';
3
4
  export declare function Injectable(options?: InjectableOptions): ClassDecorator;
4
- export declare function Inject(token: Token): ParameterDecorator;
5
+ export declare function Optional(): ParameterDecorator;
6
+ export declare function Inject(token: Token | ForwardRef): ParameterDecorator;
5
7
  export declare function isInjectable(target: object): boolean;
6
8
  export declare function getScope(target: object): Scope;
7
9
  export declare function getConstructorDependencies(target: object): unknown[];
@@ -11,13 +11,34 @@ export function Injectable(options = {}) {
11
11
  defineMetadata(METADATA_KEYS.SCOPE, scope, target);
12
12
  };
13
13
  }
14
+ export function Optional() {
15
+ return (target, _propertyKey, parameterIndex)=>{
16
+ const existing = getInjectMetadata(target);
17
+ const entry = existing.find((m)=>m.index === parameterIndex);
18
+ if (entry) {
19
+ entry.optional = true;
20
+ } else {
21
+ existing.push({
22
+ index: parameterIndex,
23
+ optional: true
24
+ });
25
+ }
26
+ MetadataRegistry.setInjectTokens(target, existing);
27
+ defineMetadata(METADATA_KEYS.INJECT, existing, target);
28
+ };
29
+ }
14
30
  export function Inject(token) {
15
31
  return (target, _propertyKey, parameterIndex)=>{
16
- const existing = MetadataRegistry.getInjectTokens(target) ?? (getMetadata(METADATA_KEYS.INJECT, target) || []);
17
- existing.push({
18
- index: parameterIndex,
19
- token
20
- });
32
+ const existing = getInjectMetadata(target);
33
+ const entry = existing.find((m)=>m.index === parameterIndex);
34
+ if (entry) {
35
+ entry.token = token;
36
+ } else {
37
+ existing.push({
38
+ index: parameterIndex,
39
+ token
40
+ });
41
+ }
21
42
  MetadataRegistry.setInjectTokens(target, existing);
22
43
  defineMetadata(METADATA_KEYS.INJECT, existing, target);
23
44
  };
@@ -32,5 +53,5 @@ export function getConstructorDependencies(target) {
32
53
  return Reflect.getMetadata('design:paramtypes', target) || [];
33
54
  }
34
55
  export function getInjectMetadata(target) {
35
- return MetadataRegistry.getInjectTokens(target) ?? (getMetadata(METADATA_KEYS.INJECT, target) || []);
56
+ return MetadataRegistry.getInjectTokens(target) ?? getMetadata(METADATA_KEYS.INJECT, target) ?? [];
36
57
  }
@@ -1,4 +1,6 @@
1
1
  export { Container } from './container';
2
- export { Injectable, Inject, isInjectable, getScope } from './decorators';
3
- export { InjectionToken } from './types';
2
+ export { Injectable, Inject, Optional, isInjectable, getScope } from './decorators';
3
+ export { InjectionToken, ForwardRef, forwardRef } from './types';
4
+ export { ModuleRef } from './module-ref';
5
+ export { mixin } from './mixin';
4
6
  export type { Type, Token, InjectableOptions, InjectMetadata, ProviderOptions, ProviderRegistration, InjectionTokenOptions, } from './types';
@@ -1,3 +1,5 @@
1
1
  export { Container } from "./container.js";
2
- export { Injectable, Inject, isInjectable, getScope } from "./decorators.js";
3
- export { InjectionToken } from "./types.js";
2
+ export { Injectable, Inject, Optional, isInjectable, getScope } from "./decorators.js";
3
+ export { InjectionToken, ForwardRef, forwardRef } from "./types.js";
4
+ export { ModuleRef } from "./module-ref.js";
5
+ export { mixin } from "./mixin.js";
@@ -0,0 +1,24 @@
1
+ import type { Type } from './types';
2
+ /**
3
+ * Creates a reusable injectable mixin class from a base class.
4
+ * Applies @Injectable() so the returned class can be registered as a provider.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * function RoleGuardMixin(role: string) {
9
+ * class MixedRoleGuard implements CanActivate {
10
+ * canActivate(ctx: ExecutionContext) {
11
+ * return ctx.getRequest().headers.get('x-role') === role;
12
+ * }
13
+ * }
14
+ * return mixin(MixedRoleGuard);
15
+ * }
16
+ *
17
+ * const AdminGuard = RoleGuardMixin('admin');
18
+ *
19
+ * @UseGuards(AdminGuard)
20
+ * @Get('/admin')
21
+ * adminOnly() { ... }
22
+ * ```
23
+ */
24
+ export declare function mixin<T>(mixinClass: Type<T>): Type<T>;
@@ -0,0 +1,26 @@
1
+ import { Injectable } from "./decorators.js";
2
+ /**
3
+ * Creates a reusable injectable mixin class from a base class.
4
+ * Applies @Injectable() so the returned class can be registered as a provider.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * function RoleGuardMixin(role: string) {
9
+ * class MixedRoleGuard implements CanActivate {
10
+ * canActivate(ctx: ExecutionContext) {
11
+ * return ctx.getRequest().headers.get('x-role') === role;
12
+ * }
13
+ * }
14
+ * return mixin(MixedRoleGuard);
15
+ * }
16
+ *
17
+ * const AdminGuard = RoleGuardMixin('admin');
18
+ *
19
+ * @UseGuards(AdminGuard)
20
+ * @Get('/admin')
21
+ * adminOnly() { ... }
22
+ * ```
23
+ */ export function mixin(mixinClass) {
24
+ Injectable()(mixinClass);
25
+ return mixinClass;
26
+ }
@@ -0,0 +1,21 @@
1
+ import type { Token, Type } from './types';
2
+ import type { Container } from './container';
3
+ export declare class ModuleRef {
4
+ private readonly container;
5
+ constructor(container: Container);
6
+ /**
7
+ * Retrieve a provider instance from the DI container.
8
+ * Returns the existing singleton (or cached value) for the token.
9
+ */
10
+ get<T>(token: Token<T>): T;
11
+ /**
12
+ * Resolve a provider, creating a new instance for TRANSIENT-scoped providers.
13
+ * For SINGLETON-scoped providers this is equivalent to get().
14
+ */
15
+ resolve<T>(token: Token<T>): T;
16
+ /**
17
+ * Instantiate a class outside of the DI container's singleton cache.
18
+ * Dependencies are resolved from the container. Each call returns a new instance.
19
+ */
20
+ create<T>(type: Type<T>): T;
21
+ }
@@ -0,0 +1,48 @@
1
+ function _ts_decorate(decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ }
7
+ function _ts_metadata(k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ }
10
+ import { Scope } from "../constants.js";
11
+ import { Injectable } from "./decorators.js";
12
+ export class ModuleRef {
13
+ container;
14
+ constructor(container){
15
+ this.container = container;
16
+ }
17
+ /**
18
+ * Retrieve a provider instance from the DI container.
19
+ * Returns the existing singleton (or cached value) for the token.
20
+ */ get(token) {
21
+ return this.container.resolve(token);
22
+ }
23
+ /**
24
+ * Resolve a provider, creating a new instance for TRANSIENT-scoped providers.
25
+ * For SINGLETON-scoped providers this is equivalent to get().
26
+ */ resolve(token) {
27
+ return this.container.resolve(token);
28
+ }
29
+ /**
30
+ * Instantiate a class outside of the DI container's singleton cache.
31
+ * Dependencies are resolved from the container. Each call returns a new instance.
32
+ */ create(type) {
33
+ const sandbox = this.container.createDetached();
34
+ sandbox.register({
35
+ provide: type,
36
+ useClass: type,
37
+ scope: Scope.TRANSIENT
38
+ });
39
+ return sandbox.resolve(type);
40
+ }
41
+ }
42
+ ModuleRef = _ts_decorate([
43
+ Injectable(),
44
+ _ts_metadata("design:type", Function),
45
+ _ts_metadata("design:paramtypes", [
46
+ typeof Container === "undefined" ? Object : Container
47
+ ])
48
+ ], ModuleRef);
@@ -9,16 +9,22 @@ export declare class InjectionToken<T = unknown> {
9
9
  constructor(description: string, options?: InjectionTokenOptions<T> | undefined);
10
10
  toString(): string;
11
11
  }
12
+ export declare class ForwardRef<T = unknown> {
13
+ readonly factory: () => Token<T>;
14
+ constructor(factory: () => Token<T>);
15
+ }
16
+ export declare function forwardRef<T>(factory: () => Token<T>): ForwardRef<T>;
12
17
  export type Token<T = any> = Type<T> | InjectionToken<T> | string | symbol;
13
18
  export interface InjectableOptions {
14
19
  scope?: Scope;
15
20
  }
16
21
  export interface InjectMetadata {
17
22
  index: number;
18
- token: Token;
23
+ token?: Token | ForwardRef;
24
+ optional?: boolean;
19
25
  }
20
26
  export interface ProviderOptions<T = unknown> {
21
- token?: Token<T>;
27
+ provide?: Token<T>;
22
28
  scope?: Scope;
23
29
  useValue?: T;
24
30
  useFactory?: (...args: any[]) => T | Promise<T>;
@@ -27,7 +33,7 @@ export interface ProviderOptions<T = unknown> {
27
33
  useExisting?: Token<T>;
28
34
  }
29
35
  export interface ProviderRegistration<T = unknown> {
30
- token: Token<T>;
36
+ provide: Token<T>;
31
37
  scope: Scope;
32
38
  instance?: T;
33
39
  useValue?: T;
@@ -9,3 +9,12 @@ export class InjectionToken {
9
9
  return `InjectionToken(${this.description})`;
10
10
  }
11
11
  }
12
+ export class ForwardRef {
13
+ factory;
14
+ constructor(factory){
15
+ this.factory = factory;
16
+ }
17
+ }
18
+ export function forwardRef(factory) {
19
+ return new ForwardRef(factory);
20
+ }
@@ -32,11 +32,11 @@ export class CorsModule {
32
32
  module: moduleClass,
33
33
  providers: [
34
34
  {
35
- token: CORS_OPTIONS,
35
+ provide: CORS_OPTIONS,
36
36
  useValue: options
37
37
  },
38
38
  {
39
- token: APP_MIDDLEWARE,
39
+ provide: APP_MIDDLEWARE,
40
40
  useValue: middleware
41
41
  }
42
42
  ]