@velajs/vela 0.4.3 → 0.5.1
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/dist/cache/cache.module.d.ts +4 -1
- package/dist/cache/cache.module.js +51 -9
- package/dist/config/config.module.d.ts +4 -1
- package/dist/config/config.module.js +40 -3
- package/dist/config/config.types.d.ts +1 -0
- package/dist/constants.d.ts +8 -2
- package/dist/constants.js +6 -0
- package/dist/container/container.d.ts +2 -0
- package/dist/container/container.js +51 -16
- package/dist/container/decorators.d.ts +3 -1
- package/dist/container/decorators.js +27 -6
- package/dist/container/index.d.ts +4 -2
- package/dist/container/index.js +4 -2
- package/dist/container/mixin.d.ts +24 -0
- package/dist/container/mixin.js +26 -0
- package/dist/container/module-ref.d.ts +21 -0
- package/dist/container/module-ref.js +48 -0
- package/dist/container/types.d.ts +9 -3
- package/dist/container/types.js +9 -0
- package/dist/cors/cors.module.js +2 -2
- package/dist/errors/http-exception.d.ts +20 -20
- package/dist/errors/http-exception.js +47 -41
- package/dist/factory.js +11 -2
- package/dist/fetch/fetch.module.d.ts +6 -0
- package/dist/fetch/fetch.module.js +77 -0
- package/dist/fetch/fetch.service.d.ts +24 -0
- package/dist/fetch/fetch.service.js +145 -0
- package/dist/fetch/fetch.types.d.ts +24 -0
- package/dist/fetch/fetch.types.js +1 -0
- package/dist/fetch/index.d.ts +3 -0
- package/dist/fetch/index.js +2 -0
- package/dist/health/health.service.js +2 -2
- package/dist/http/decorators.d.ts +65 -0
- package/dist/http/decorators.js +91 -2
- package/dist/http/index.d.ts +3 -1
- package/dist/http/index.js +2 -1
- package/dist/http/middleware-consumer.d.ts +36 -0
- package/dist/http/middleware-consumer.js +71 -0
- package/dist/http/route.manager.d.ts +4 -0
- package/dist/http/route.manager.js +91 -6
- package/dist/http/types.d.ts +1 -0
- package/dist/index.d.ts +11 -6
- package/dist/index.js +7 -4
- package/dist/metadata.d.ts +1 -1
- package/dist/module/decorators.d.ts +1 -0
- package/dist/module/decorators.js +24 -8
- package/dist/module/index.d.ts +2 -2
- package/dist/module/index.js +1 -1
- package/dist/module/module-loader.d.ts +5 -1
- package/dist/module/module-loader.js +54 -10
- package/dist/module/types.d.ts +13 -3
- package/dist/pipeline/index.d.ts +3 -2
- package/dist/pipeline/index.js +1 -1
- package/dist/pipeline/pipes.d.ts +22 -0
- package/dist/pipeline/pipes.js +50 -0
- package/dist/pipeline/tokens.d.ts +1 -1
- package/dist/pipeline/tokens.js +1 -1
- package/dist/pipeline/types.d.ts +16 -0
- package/dist/registry/metadata.registry.d.ts +7 -6
- package/dist/registry/metadata.registry.js +13 -0
- package/dist/registry/types.d.ts +1 -0
- package/dist/schedule/schedule.module.d.ts +4 -1
- package/dist/schedule/schedule.module.js +39 -7
- package/dist/testing/testing.builder.js +5 -5
- package/dist/throttler/throttler.module.d.ts +2 -1
- package/dist/throttler/throttler.module.js +47 -9
- package/dist/validation/validation.pipe.js +1 -1
- 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 =
|
|
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
|
-
|
|
33
|
+
provide: CACHE_MANAGER,
|
|
30
34
|
useValue: store
|
|
31
35
|
},
|
|
32
36
|
{
|
|
33
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -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";
|
|
@@ -19,14 +20,19 @@ export declare enum HttpMethod {
|
|
|
19
20
|
PATCH = "patch",
|
|
20
21
|
DELETE = "delete",
|
|
21
22
|
OPTIONS = "options",
|
|
22
|
-
HEAD = "head"
|
|
23
|
+
HEAD = "head",
|
|
24
|
+
ALL = "all"
|
|
23
25
|
}
|
|
24
26
|
export declare enum ParamType {
|
|
25
27
|
BODY = "body",
|
|
26
28
|
QUERY = "query",
|
|
27
29
|
PARAM = "param",
|
|
28
30
|
HEADERS = "headers",
|
|
29
|
-
REQUEST = "request"
|
|
31
|
+
REQUEST = "request",
|
|
32
|
+
RESPONSE = "response",
|
|
33
|
+
IP = "ip",
|
|
34
|
+
COOKIE = "cookie",
|
|
35
|
+
RAW_BODY = "raw_body"
|
|
30
36
|
}
|
|
31
37
|
export declare enum Scope {
|
|
32
38
|
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',
|
|
@@ -25,6 +26,7 @@ export var HttpMethod = /*#__PURE__*/ function(HttpMethod) {
|
|
|
25
26
|
HttpMethod["DELETE"] = "delete";
|
|
26
27
|
HttpMethod["OPTIONS"] = "options";
|
|
27
28
|
HttpMethod["HEAD"] = "head";
|
|
29
|
+
HttpMethod["ALL"] = "all";
|
|
28
30
|
return HttpMethod;
|
|
29
31
|
}({});
|
|
30
32
|
export var ParamType = /*#__PURE__*/ function(ParamType) {
|
|
@@ -33,6 +35,10 @@ export var ParamType = /*#__PURE__*/ function(ParamType) {
|
|
|
33
35
|
ParamType["PARAM"] = "param";
|
|
34
36
|
ParamType["HEADERS"] = "headers";
|
|
35
37
|
ParamType["REQUEST"] = "request";
|
|
38
|
+
ParamType["RESPONSE"] = "response";
|
|
39
|
+
ParamType["IP"] = "ip";
|
|
40
|
+
ParamType["COOKIE"] = "cookie";
|
|
41
|
+
ParamType["RAW_BODY"] = "raw_body";
|
|
36
42
|
return ParamType;
|
|
37
43
|
}({});
|
|
38
44
|
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
|
-
|
|
23
|
+
provide: target,
|
|
24
24
|
scope,
|
|
25
25
|
useClass: target
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
registerOptions(options) {
|
|
29
|
-
const token = options.
|
|
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.
|
|
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.
|
|
117
|
+
if (this.resolutionStack.has(registration.provide)) {
|
|
113
118
|
const chain = [
|
|
114
119
|
...this.resolutionStack,
|
|
115
|
-
registration.
|
|
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.
|
|
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.
|
|
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.
|
|
137
|
+
this.requestInstances.set(registration.provide, instance);
|
|
133
138
|
}
|
|
134
139
|
return instance;
|
|
135
140
|
} finally{
|
|
136
|
-
this.resolutionStack.delete(registration.
|
|
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
|
|
149
|
+
m
|
|
145
150
|
]));
|
|
146
151
|
const dependencies = paramTypes.map((paramType, index)=>{
|
|
147
|
-
const
|
|
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);
|
|
@@ -156,10 +172,13 @@ export class Container {
|
|
|
156
172
|
if (!registration.useFactory) {
|
|
157
173
|
throw new Error('Factory function is missing');
|
|
158
174
|
}
|
|
159
|
-
const dependencies = (registration.inject || []).map((token)=>
|
|
175
|
+
const dependencies = (registration.inject || []).map((token)=>{
|
|
176
|
+
const resolved = token instanceof ForwardRef ? token.factory() : token;
|
|
177
|
+
return this.resolve(resolved);
|
|
178
|
+
});
|
|
160
179
|
const result = registration.useFactory(...dependencies);
|
|
161
180
|
if (result instanceof Promise) {
|
|
162
|
-
throw new Error(`Async factory for ${this.tokenToString(registration.
|
|
181
|
+
throw new Error(`Async factory for ${this.tokenToString(registration.provide)} returned a Promise. ` + `Use resolveAsync() for async providers.`);
|
|
163
182
|
}
|
|
164
183
|
return result;
|
|
165
184
|
}
|
|
@@ -185,6 +204,22 @@ export class Container {
|
|
|
185
204
|
}
|
|
186
205
|
return this.resolve(token);
|
|
187
206
|
}
|
|
207
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
208
|
+
createLazyProxy(token) {
|
|
209
|
+
const container = this;
|
|
210
|
+
return new Proxy({}, {
|
|
211
|
+
get (_target, prop) {
|
|
212
|
+
const instance = container.resolve(token);
|
|
213
|
+
const value = instance[prop];
|
|
214
|
+
return typeof value === 'function' ? value.bind(instance) : value;
|
|
215
|
+
},
|
|
216
|
+
set (_target, prop, value) {
|
|
217
|
+
const instance = container.resolve(token);
|
|
218
|
+
instance[prop] = value;
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
188
223
|
tokenToString(token) {
|
|
189
224
|
if (token instanceof InjectionToken) {
|
|
190
225
|
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
|
|
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 =
|
|
17
|
-
existing.
|
|
18
|
-
|
|
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) ??
|
|
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';
|
package/dist/container/index.js
CHANGED
|
@@ -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
|
|
23
|
+
token?: Token | ForwardRef;
|
|
24
|
+
optional?: boolean;
|
|
19
25
|
}
|
|
20
26
|
export interface ProviderOptions<T = unknown> {
|
|
21
|
-
|
|
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
|
-
|
|
36
|
+
provide: Token<T>;
|
|
31
37
|
scope: Scope;
|
|
32
38
|
instance?: T;
|
|
33
39
|
useValue?: T;
|
package/dist/container/types.js
CHANGED
|
@@ -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
|
+
}
|
package/dist/cors/cors.module.js
CHANGED