@carno.js/core 0.2.11 → 1.0.2
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/LICENSE +673 -673
- package/README.md +188 -0
- package/dist/Carno.js +272 -333
- package/dist/Carno.mjs +268 -0
- package/dist/DefaultRoutes.js +51 -0
- package/dist/DefaultRoutes.mjs +34 -0
- package/dist/bun/index.js +183 -0
- package/dist/bun/index.js.map +86 -0
- package/dist/cache/CacheDriver.js +13 -0
- package/dist/cache/CacheDriver.mjs +0 -0
- package/dist/cache/CacheService.js +113 -0
- package/dist/cache/CacheService.mjs +93 -0
- package/dist/cache/MemoryDriver.js +66 -0
- package/dist/cache/MemoryDriver.mjs +46 -0
- package/dist/cache/RedisDriver.js +81 -0
- package/dist/cache/RedisDriver.mjs +61 -0
- package/dist/compiler/JITCompiler.js +111 -0
- package/dist/compiler/JITCompiler.mjs +89 -0
- package/dist/container/Container.js +99 -0
- package/dist/container/Container.mjs +78 -0
- package/dist/context/Context.js +97 -0
- package/dist/context/Context.mjs +77 -0
- package/dist/cors/CorsHandler.js +90 -0
- package/dist/cors/CorsHandler.mjs +68 -0
- package/dist/decorators/Controller.js +42 -0
- package/dist/decorators/Controller.mjs +22 -0
- package/dist/decorators/Inject.js +30 -0
- package/dist/decorators/Inject.mjs +10 -0
- package/dist/decorators/Middleware.js +35 -0
- package/dist/decorators/Middleware.mjs +15 -0
- package/dist/decorators/Service.js +31 -0
- package/dist/decorators/Service.mjs +12 -0
- package/dist/decorators/methods.js +60 -0
- package/dist/decorators/methods.mjs +34 -0
- package/dist/decorators/params.js +63 -0
- package/dist/decorators/params.mjs +37 -0
- package/dist/events/Lifecycle.js +69 -0
- package/dist/events/Lifecycle.mjs +41 -0
- package/dist/exceptions/HttpException.js +112 -26
- package/dist/exceptions/HttpException.mjs +82 -0
- package/dist/index.js +129 -31
- package/dist/index.mjs +94 -0
- package/dist/metadata.js +34 -0
- package/dist/metadata.mjs +9 -0
- package/dist/middleware/CarnoMiddleware.js +13 -0
- package/dist/middleware/CarnoMiddleware.mjs +0 -0
- package/dist/router/RadixRouter.js +121 -0
- package/dist/router/RadixRouter.mjs +101 -0
- package/dist/testing/TestHarness.js +81 -0
- package/dist/testing/TestHarness.mjs +60 -0
- package/dist/utils/Metadata.js +53 -0
- package/dist/utils/Metadata.mjs +31 -0
- package/dist/validation/ValibotAdapter.js +67 -0
- package/dist/validation/ValibotAdapter.mjs +48 -0
- package/dist/validation/ValidatorAdapter.js +35 -19
- package/dist/validation/ValidatorAdapter.mjs +14 -0
- package/dist/validation/ZodAdapter.js +80 -0
- package/dist/validation/ZodAdapter.mjs +59 -0
- package/package.json +21 -63
- package/src/Carno.ts +605 -0
- package/src/DefaultRoutes.ts +34 -0
- package/src/cache/CacheDriver.ts +50 -0
- package/src/cache/CacheService.ts +139 -0
- package/src/cache/MemoryDriver.ts +104 -0
- package/src/cache/RedisDriver.ts +116 -0
- package/src/compiler/JITCompiler.ts +167 -0
- package/src/container/Container.ts +168 -0
- package/src/context/Context.ts +128 -0
- package/src/cors/CorsHandler.ts +145 -0
- package/src/decorators/Controller.ts +63 -0
- package/src/decorators/Inject.ts +16 -0
- package/src/decorators/Middleware.ts +22 -0
- package/src/decorators/Service.ts +18 -0
- package/src/decorators/methods.ts +58 -0
- package/src/decorators/params.ts +47 -0
- package/src/events/Lifecycle.ts +97 -0
- package/src/exceptions/HttpException.ts +99 -0
- package/src/index.ts +92 -0
- package/src/metadata.ts +46 -0
- package/src/middleware/CarnoMiddleware.ts +14 -0
- package/src/router/RadixRouter.ts +225 -0
- package/src/testing/TestHarness.ts +177 -0
- package/src/utils/Metadata.ts +43 -0
- package/src/validation/ValibotAdapter.ts +95 -0
- package/src/validation/ValidatorAdapter.ts +69 -0
- package/src/validation/ZodAdapter.ts +102 -0
- package/dist/Carno.d.ts +0 -75
- package/dist/cache/bento-cache.driver.d.ts +0 -13
- package/dist/cache/bento-cache.driver.js +0 -55
- package/dist/cache/cache.service.d.ts +0 -8
- package/dist/cache/cache.service.js +0 -6
- package/dist/commons/decorators/Injectable.decorator.d.ts +0 -20
- package/dist/commons/decorators/Injectable.decorator.js +0 -33
- package/dist/commons/decorators/controller.decorator.d.ts +0 -8
- package/dist/commons/decorators/controller.decorator.js +0 -22
- package/dist/commons/decorators/http.decorators.d.ts +0 -13
- package/dist/commons/decorators/http.decorators.js +0 -63
- package/dist/commons/decorators/index.d.ts +0 -6
- package/dist/commons/decorators/index.js +0 -22
- package/dist/commons/decorators/inject.decorator.d.ts +0 -1
- package/dist/commons/decorators/inject.decorator.js +0 -5
- package/dist/commons/decorators/middleware.decorator.d.ts +0 -2
- package/dist/commons/decorators/middleware.decorator.js +0 -30
- package/dist/commons/decorators/service.decorator.d.ts +0 -2
- package/dist/commons/decorators/service.decorator.js +0 -7
- package/dist/commons/decorators/validation.decorator.d.ts +0 -32
- package/dist/commons/decorators/validation.decorator.js +0 -40
- package/dist/commons/http-code.enum.d.ts +0 -50
- package/dist/commons/http-code.enum.js +0 -54
- package/dist/commons/index.d.ts +0 -3
- package/dist/commons/index.js +0 -19
- package/dist/commons/registries/ProviderControl.d.ts +0 -77
- package/dist/commons/registries/ProviderControl.js +0 -112
- package/dist/commons/registries/ProviderRegistry.d.ts +0 -7
- package/dist/commons/registries/ProviderRegistry.js +0 -20
- package/dist/constants.d.ts +0 -8
- package/dist/constants.js +0 -11
- package/dist/container/ContainerConfiguration.d.ts +0 -45
- package/dist/container/ContainerConfiguration.js +0 -121
- package/dist/container/DependencyResolver.d.ts +0 -20
- package/dist/container/DependencyResolver.js +0 -85
- package/dist/container/InjectorService.d.ts +0 -58
- package/dist/container/InjectorService.js +0 -286
- package/dist/container/MethodInvoker.d.ts +0 -21
- package/dist/container/MethodInvoker.js +0 -83
- package/dist/container/RouteResolver.d.ts +0 -27
- package/dist/container/RouteResolver.js +0 -173
- package/dist/container/container.d.ts +0 -41
- package/dist/container/container.js +0 -71
- package/dist/container/createContainer.d.ts +0 -3
- package/dist/container/createContainer.js +0 -12
- package/dist/container/createInjector.d.ts +0 -2
- package/dist/container/createInjector.js +0 -7
- package/dist/container/index.d.ts +0 -6
- package/dist/container/index.js +0 -22
- package/dist/container/middleware.resolver.d.ts +0 -9
- package/dist/container/middleware.resolver.js +0 -35
- package/dist/default-routes-carno.d.ts +0 -3
- package/dist/default-routes-carno.js +0 -29
- package/dist/domain/BaseContext.d.ts +0 -15
- package/dist/domain/BaseContext.js +0 -2
- package/dist/domain/CarnoClosure.d.ts +0 -1
- package/dist/domain/CarnoClosure.js +0 -2
- package/dist/domain/CarnoMiddleware.d.ts +0 -5
- package/dist/domain/CarnoMiddleware.js +0 -2
- package/dist/domain/Context.d.ts +0 -58
- package/dist/domain/Context.js +0 -188
- package/dist/domain/FastContext.d.ts +0 -34
- package/dist/domain/FastContext.js +0 -59
- package/dist/domain/LocalsContainer.d.ts +0 -4
- package/dist/domain/LocalsContainer.js +0 -10
- package/dist/domain/Metadata.d.ts +0 -449
- package/dist/domain/Metadata.js +0 -511
- package/dist/domain/cors-config.d.ts +0 -12
- package/dist/domain/cors-config.js +0 -18
- package/dist/domain/cors-headers-cache.d.ts +0 -17
- package/dist/domain/cors-headers-cache.js +0 -101
- package/dist/domain/http-method.d.ts +0 -7
- package/dist/domain/http-method.js +0 -11
- package/dist/domain/index.d.ts +0 -10
- package/dist/domain/index.js +0 -26
- package/dist/domain/provider-scope.d.ts +0 -5
- package/dist/domain/provider-scope.js +0 -9
- package/dist/domain/provider-type.d.ts +0 -6
- package/dist/domain/provider-type.js +0 -10
- package/dist/domain/provider.d.ts +0 -37
- package/dist/domain/provider.js +0 -70
- package/dist/events/hooks.decorator.d.ts +0 -3
- package/dist/events/hooks.decorator.js +0 -29
- package/dist/events/index.d.ts +0 -2
- package/dist/events/index.js +0 -18
- package/dist/events/on-event.d.ts +0 -13
- package/dist/events/on-event.js +0 -11
- package/dist/exceptions/HttpException.d.ts +0 -9
- package/dist/exceptions/index.d.ts +0 -1
- package/dist/exceptions/index.js +0 -17
- package/dist/index.d.ts +0 -16
- package/dist/route/CompiledRoute.d.ts +0 -23
- package/dist/route/CompiledRoute.js +0 -9
- package/dist/route/FastPathExecutor.d.ts +0 -12
- package/dist/route/FastPathExecutor.js +0 -50
- package/dist/route/JITCompiler.d.ts +0 -28
- package/dist/route/JITCompiler.js +0 -245
- package/dist/route/Matcher.d.ts +0 -11
- package/dist/route/Matcher.js +0 -48
- package/dist/route/ParamResolverFactory.d.ts +0 -14
- package/dist/route/ParamResolverFactory.js +0 -49
- package/dist/route/RouteCompiler.d.ts +0 -28
- package/dist/route/RouteCompiler.js +0 -157
- package/dist/route/RouteExecutor.d.ts +0 -12
- package/dist/route/RouteExecutor.js +0 -84
- package/dist/route/memoirist.d.ts +0 -31
- package/dist/route/memoirist.js +0 -373
- package/dist/services/logger.service.d.ts +0 -23
- package/dist/services/logger.service.js +0 -47
- package/dist/testing/core-testing.d.ts +0 -24
- package/dist/testing/core-testing.js +0 -102
- package/dist/testing/index.d.ts +0 -1
- package/dist/testing/index.js +0 -17
- package/dist/utils/ValidationCache.d.ts +0 -5
- package/dist/utils/ValidationCache.js +0 -35
- package/dist/utils/ancestorOf.d.ts +0 -2
- package/dist/utils/ancestorOf.js +0 -10
- package/dist/utils/ancestorsOf.d.ts +0 -6
- package/dist/utils/ancestorsOf.js +0 -20
- package/dist/utils/classOf.d.ts +0 -13
- package/dist/utils/classOf.js +0 -21
- package/dist/utils/cleanObject.d.ts +0 -6
- package/dist/utils/cleanObject.js +0 -22
- package/dist/utils/constructorOf.d.ts +0 -11
- package/dist/utils/constructorOf.js +0 -18
- package/dist/utils/createInstance.d.ts +0 -1
- package/dist/utils/createInstance.js +0 -7
- package/dist/utils/decoratorTypeOf.d.ts +0 -11
- package/dist/utils/decoratorTypeOf.js +0 -32
- package/dist/utils/deepClone.d.ts +0 -6
- package/dist/utils/deepClone.js +0 -63
- package/dist/utils/deepMerge.d.ts +0 -9
- package/dist/utils/deepMerge.js +0 -62
- package/dist/utils/descriptorOf.d.ts +0 -8
- package/dist/utils/descriptorOf.js +0 -16
- package/dist/utils/formatValidationErrors.d.ts +0 -5
- package/dist/utils/formatValidationErrors.js +0 -80
- package/dist/utils/getClassOrSymbol.d.ts +0 -1
- package/dist/utils/getClassOrSymbol.js +0 -8
- package/dist/utils/getConstructorArgNames.d.ts +0 -1
- package/dist/utils/getConstructorArgNames.js +0 -12
- package/dist/utils/getMethodArgTypes.d.ts +0 -1
- package/dist/utils/getMethodArgTypes.js +0 -9
- package/dist/utils/getValue.d.ts +0 -32
- package/dist/utils/getValue.js +0 -47
- package/dist/utils/hasJsonMethod.d.ts +0 -1
- package/dist/utils/hasJsonMethod.js +0 -6
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/index.js +0 -31
- package/dist/utils/isArray.d.ts +0 -13
- package/dist/utils/isArray.js +0 -21
- package/dist/utils/isArrowFn.d.ts +0 -1
- package/dist/utils/isArrowFn.js +0 -7
- package/dist/utils/isBoolean.d.ts +0 -7
- package/dist/utils/isBoolean.js +0 -15
- package/dist/utils/isBuffer.d.ts +0 -7
- package/dist/utils/isBuffer.js +0 -19
- package/dist/utils/isClass.d.ts +0 -1
- package/dist/utils/isClass.js +0 -26
- package/dist/utils/isCollection.d.ts +0 -6
- package/dist/utils/isCollection.js +0 -20
- package/dist/utils/isDate.d.ts +0 -6
- package/dist/utils/isDate.js +0 -11
- package/dist/utils/isEmpty.d.ts +0 -6
- package/dist/utils/isEmpty.js +0 -12
- package/dist/utils/isFunction.d.ts +0 -1
- package/dist/utils/isFunction.js +0 -6
- package/dist/utils/isInheritedFrom.d.ts +0 -1
- package/dist/utils/isInheritedFrom.js +0 -24
- package/dist/utils/isMomentObject.d.ts +0 -1
- package/dist/utils/isMomentObject.js +0 -6
- package/dist/utils/isMongooseObject.d.ts +0 -2
- package/dist/utils/isMongooseObject.js +0 -11
- package/dist/utils/isNil.d.ts +0 -1
- package/dist/utils/isNil.js +0 -6
- package/dist/utils/isNumber.d.ts +0 -7
- package/dist/utils/isNumber.js +0 -15
- package/dist/utils/isObject.d.ts +0 -1
- package/dist/utils/isObject.js +0 -6
- package/dist/utils/isObservable.d.ts +0 -1
- package/dist/utils/isObservable.js +0 -6
- package/dist/utils/isPlainObject.d.ts +0 -7
- package/dist/utils/isPlainObject.js +0 -16
- package/dist/utils/isPrimitive.d.ts +0 -14
- package/dist/utils/isPrimitive.js +0 -28
- package/dist/utils/isPrimitiveType.d.ts +0 -1
- package/dist/utils/isPrimitiveType.js +0 -11
- package/dist/utils/isPromise.d.ts +0 -7
- package/dist/utils/isPromise.js +0 -14
- package/dist/utils/isProtectedKey.d.ts +0 -5
- package/dist/utils/isProtectedKey.js +0 -10
- package/dist/utils/isRegExp.d.ts +0 -1
- package/dist/utils/isRegExp.js +0 -6
- package/dist/utils/isRequestScope.d.ts +0 -11
- package/dist/utils/isRequestScope.js +0 -23
- package/dist/utils/isSerializable.d.ts +0 -1
- package/dist/utils/isSerializable.js +0 -11
- package/dist/utils/isStream.d.ts +0 -1
- package/dist/utils/isStream.js +0 -6
- package/dist/utils/isString.d.ts +0 -6
- package/dist/utils/isString.js +0 -14
- package/dist/utils/isSymbol.d.ts +0 -6
- package/dist/utils/isSymbol.js +0 -14
- package/dist/utils/methodsOf.d.ts +0 -9
- package/dist/utils/methodsOf.js +0 -24
- package/dist/utils/nameOf.d.ts +0 -14
- package/dist/utils/nameOf.js +0 -31
- package/dist/utils/objectKeys.d.ts +0 -1
- package/dist/utils/objectKeys.js +0 -7
- package/dist/utils/primitiveOf.d.ts +0 -1
- package/dist/utils/primitiveOf.js +0 -18
- package/dist/utils/prototypeOf.d.ts +0 -6
- package/dist/utils/prototypeOf.js +0 -12
- package/dist/utils/setValue.d.ts +0 -1
- package/dist/utils/setValue.js +0 -32
- package/dist/utils/toMap.d.ts +0 -3
- package/dist/utils/toMap.js +0 -34
- package/dist/utils/toStringConstructor.d.ts +0 -1
- package/dist/utils/toStringConstructor.js +0 -10
- package/dist/validation/ValidatorAdapter.d.ts +0 -66
- package/dist/validation/adapters/ClassValidatorAdapter.d.ts +0 -23
- package/dist/validation/adapters/ClassValidatorAdapter.js +0 -47
- package/dist/validation/adapters/ZodAdapter.d.ts +0 -14
- package/dist/validation/adapters/ZodAdapter.js +0 -56
- package/dist/validation/adapters/index.d.ts +0 -4
- package/dist/validation/adapters/index.js +0 -7
- package/dist/validation/index.d.ts +0 -3
- package/dist/validation/index.js +0 -20
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { CacheDriver, CacheConfig } from './CacheDriver';
|
|
2
|
+
import { MemoryDriver } from './MemoryDriver';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CacheService - High-performance caching with driver pattern.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - In-memory (default) or Redis backend
|
|
9
|
+
* - getOrSet for cache-aside pattern
|
|
10
|
+
* - Key prefixing for namespacing
|
|
11
|
+
* - Configurable default TTL
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const cache = new CacheService();
|
|
16
|
+
*
|
|
17
|
+
* // Basic operations
|
|
18
|
+
* await cache.set('user:123', { name: 'John' }, 3600);
|
|
19
|
+
* const user = await cache.get<User>('user:123');
|
|
20
|
+
*
|
|
21
|
+
* // Cache-aside pattern
|
|
22
|
+
* const user = await cache.getOrSet('user:123',
|
|
23
|
+
* async () => db.findUser(123),
|
|
24
|
+
* 3600
|
|
25
|
+
* );
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class CacheService {
|
|
29
|
+
private driver: CacheDriver;
|
|
30
|
+
private prefix: string;
|
|
31
|
+
private defaultTtl: number | undefined;
|
|
32
|
+
|
|
33
|
+
constructor(config: CacheConfig = {}) {
|
|
34
|
+
this.driver = config.driver || new MemoryDriver();
|
|
35
|
+
this.prefix = config.prefix || '';
|
|
36
|
+
this.defaultTtl = config.defaultTtl;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get the full key with prefix.
|
|
41
|
+
*/
|
|
42
|
+
private key(key: string): string {
|
|
43
|
+
return this.prefix ? `${this.prefix}:${key}` : key;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get a value from cache.
|
|
48
|
+
*/
|
|
49
|
+
async get<T>(key: string): Promise<T | null> {
|
|
50
|
+
return this.driver.get<T>(this.key(key));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Set a value in cache.
|
|
55
|
+
* @param ttl Time to live in seconds
|
|
56
|
+
*/
|
|
57
|
+
async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
|
|
58
|
+
return this.driver.set(this.key(key), value, ttl ?? this.defaultTtl);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Delete a value from cache.
|
|
63
|
+
*/
|
|
64
|
+
async del(key: string): Promise<boolean> {
|
|
65
|
+
return this.driver.del(this.key(key));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check if key exists.
|
|
70
|
+
*/
|
|
71
|
+
async has(key: string): Promise<boolean> {
|
|
72
|
+
return this.driver.has(this.key(key));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Clear all cached values.
|
|
77
|
+
*/
|
|
78
|
+
async clear(): Promise<void> {
|
|
79
|
+
return this.driver.clear();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get value from cache or compute and store it.
|
|
84
|
+
* This is the cache-aside pattern - most commonly used method.
|
|
85
|
+
*
|
|
86
|
+
* @param key Cache key
|
|
87
|
+
* @param cb Callback to compute value if not cached
|
|
88
|
+
* @param ttl Time to live in seconds
|
|
89
|
+
*/
|
|
90
|
+
async getOrSet<T>(key: string, cb: () => Promise<T>, ttl?: number): Promise<T> {
|
|
91
|
+
const cached = await this.get<T>(key);
|
|
92
|
+
|
|
93
|
+
if (cached !== null) {
|
|
94
|
+
return cached;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const value = await cb();
|
|
98
|
+
await this.set(key, value, ttl);
|
|
99
|
+
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get multiple values at once.
|
|
105
|
+
*/
|
|
106
|
+
async getMany<T>(keys: string[]): Promise<(T | null)[]> {
|
|
107
|
+
return Promise.all(keys.map(key => this.get<T>(key)));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Set multiple values at once.
|
|
112
|
+
*/
|
|
113
|
+
async setMany<T>(entries: Array<{ key: string; value: T; ttl?: number }>): Promise<boolean[]> {
|
|
114
|
+
return Promise.all(
|
|
115
|
+
entries.map(entry => this.set(entry.key, entry.value, entry.ttl))
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Delete multiple values at once.
|
|
121
|
+
*/
|
|
122
|
+
async delMany(keys: string[]): Promise<boolean[]> {
|
|
123
|
+
return Promise.all(keys.map(key => this.del(key)));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Close the cache driver connection.
|
|
128
|
+
*/
|
|
129
|
+
async close(): Promise<void> {
|
|
130
|
+
await this.driver.close?.();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get the underlying driver (for advanced use).
|
|
135
|
+
*/
|
|
136
|
+
getDriver(): CacheDriver {
|
|
137
|
+
return this.driver;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { CacheDriver } from './CacheDriver';
|
|
2
|
+
|
|
3
|
+
interface CacheEntry<T> {
|
|
4
|
+
value: T;
|
|
5
|
+
expiresAt: number | null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* In-Memory Cache Driver.
|
|
10
|
+
* Ultra-fast, perfect for single-instance applications.
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - O(1) get/set/del operations
|
|
14
|
+
* - Lazy expiration (checked on access)
|
|
15
|
+
* - Periodic cleanup of expired entries
|
|
16
|
+
*/
|
|
17
|
+
export class MemoryDriver implements CacheDriver {
|
|
18
|
+
readonly name = 'MemoryDriver';
|
|
19
|
+
|
|
20
|
+
private cache = new Map<string, CacheEntry<any>>();
|
|
21
|
+
private cleanupInterval: Timer | null = null;
|
|
22
|
+
|
|
23
|
+
constructor(cleanupIntervalMs: number = 0) {
|
|
24
|
+
// Periodic cleanup of expired entries (disabled by default for performance)
|
|
25
|
+
if (cleanupIntervalMs > 0) {
|
|
26
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), cleanupIntervalMs);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async get<T>(key: string): Promise<T | null> {
|
|
31
|
+
const entry = this.cache.get(key);
|
|
32
|
+
|
|
33
|
+
if (!entry) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Check expiration
|
|
38
|
+
if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
|
|
39
|
+
this.cache.delete(key);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return entry.value;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
|
|
47
|
+
const expiresAt = ttl ? Date.now() + ttl : null;
|
|
48
|
+
|
|
49
|
+
this.cache.set(key, { value, expiresAt });
|
|
50
|
+
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async del(key: string): Promise<boolean> {
|
|
55
|
+
return this.cache.delete(key);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async has(key: string): Promise<boolean> {
|
|
59
|
+
const entry = this.cache.get(key);
|
|
60
|
+
|
|
61
|
+
if (!entry) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
|
|
66
|
+
this.cache.delete(key);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async clear(): Promise<void> {
|
|
74
|
+
this.cache.clear();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async close(): Promise<void> {
|
|
78
|
+
if (this.cleanupInterval) {
|
|
79
|
+
clearInterval(this.cleanupInterval);
|
|
80
|
+
this.cleanupInterval = null;
|
|
81
|
+
}
|
|
82
|
+
this.cache.clear();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Remove expired entries.
|
|
87
|
+
*/
|
|
88
|
+
private cleanup(): void {
|
|
89
|
+
const now = Date.now();
|
|
90
|
+
|
|
91
|
+
for (const [key, entry] of this.cache) {
|
|
92
|
+
if (entry.expiresAt !== null && now > entry.expiresAt) {
|
|
93
|
+
this.cache.delete(key);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get cache stats (for debugging).
|
|
100
|
+
*/
|
|
101
|
+
stats(): { size: number } {
|
|
102
|
+
return { size: this.cache.size };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { CacheDriver } from './CacheDriver';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Redis Cache Driver Configuration.
|
|
5
|
+
*/
|
|
6
|
+
export interface RedisConfig {
|
|
7
|
+
host?: string;
|
|
8
|
+
port?: number;
|
|
9
|
+
password?: string;
|
|
10
|
+
db?: number;
|
|
11
|
+
url?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Redis Cache Driver.
|
|
16
|
+
* For distributed caching in multi-instance deployments.
|
|
17
|
+
*
|
|
18
|
+
* Uses Bun's native Redis client for maximum performance.
|
|
19
|
+
*/
|
|
20
|
+
export class RedisDriver implements CacheDriver {
|
|
21
|
+
readonly name = 'RedisDriver';
|
|
22
|
+
|
|
23
|
+
private client: any = null;
|
|
24
|
+
private connected = false;
|
|
25
|
+
|
|
26
|
+
constructor(private config: RedisConfig = {}) { }
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Connect to Redis (lazy - connects on first use).
|
|
30
|
+
*/
|
|
31
|
+
private async ensureConnected(): Promise<void> {
|
|
32
|
+
if (this.connected) return;
|
|
33
|
+
|
|
34
|
+
const url = this.config.url ||
|
|
35
|
+
`redis://${this.config.host || 'localhost'}:${this.config.port || 6379}`;
|
|
36
|
+
|
|
37
|
+
// Use Bun's native Redis client if available
|
|
38
|
+
if (typeof Bun !== 'undefined' && (Bun as any).redis) {
|
|
39
|
+
this.client = new (Bun as any).redis(url);
|
|
40
|
+
} else {
|
|
41
|
+
// Fallback to ioredis
|
|
42
|
+
try {
|
|
43
|
+
const Redis = require('ioredis');
|
|
44
|
+
this.client = new Redis({
|
|
45
|
+
host: this.config.host || 'localhost',
|
|
46
|
+
port: this.config.port || 6379,
|
|
47
|
+
password: this.config.password,
|
|
48
|
+
db: this.config.db || 0
|
|
49
|
+
});
|
|
50
|
+
} catch {
|
|
51
|
+
throw new Error('Redis client not available. Install ioredis or use Bun with Redis support.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.connected = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async get<T>(key: string): Promise<T | null> {
|
|
59
|
+
await this.ensureConnected();
|
|
60
|
+
|
|
61
|
+
const value = await this.client.get(key);
|
|
62
|
+
|
|
63
|
+
if (value === null) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(value);
|
|
69
|
+
} catch {
|
|
70
|
+
return value as T;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async set<T>(key: string, value: T, ttl?: number): Promise<boolean> {
|
|
75
|
+
await this.ensureConnected();
|
|
76
|
+
|
|
77
|
+
const serialized = typeof value === 'string' ? value : JSON.stringify(value);
|
|
78
|
+
|
|
79
|
+
if (ttl) {
|
|
80
|
+
await this.client.setex(key, ttl, serialized);
|
|
81
|
+
} else {
|
|
82
|
+
await this.client.set(key, serialized);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async del(key: string): Promise<boolean> {
|
|
89
|
+
await this.ensureConnected();
|
|
90
|
+
|
|
91
|
+
const result = await this.client.del(key);
|
|
92
|
+
|
|
93
|
+
return result > 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async has(key: string): Promise<boolean> {
|
|
97
|
+
await this.ensureConnected();
|
|
98
|
+
|
|
99
|
+
const result = await this.client.exists(key);
|
|
100
|
+
|
|
101
|
+
return result > 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async clear(): Promise<void> {
|
|
105
|
+
await this.ensureConnected();
|
|
106
|
+
|
|
107
|
+
await this.client.flushdb();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async close(): Promise<void> {
|
|
111
|
+
if (this.client && this.connected) {
|
|
112
|
+
await this.client.quit?.();
|
|
113
|
+
this.connected = false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JIT Compiler for Turbo.
|
|
3
|
+
*
|
|
4
|
+
* Aggressive AOT optimizations:
|
|
5
|
+
* - Detects async at compile time (not runtime)
|
|
6
|
+
* - Generates specialized handlers via new Function()
|
|
7
|
+
* - Inlines parameter access
|
|
8
|
+
* - Zero overhead for simple handlers
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ParamType } from '../decorators/params';
|
|
12
|
+
|
|
13
|
+
export interface ParamInfo {
|
|
14
|
+
type: ParamType;
|
|
15
|
+
key?: string;
|
|
16
|
+
index: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CompiledHandler {
|
|
20
|
+
fn: Function;
|
|
21
|
+
isAsync: boolean;
|
|
22
|
+
isStatic: boolean;
|
|
23
|
+
staticValue?: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const ASYNC_REGEX = /^async\s|^\([^)]*\)\s*=>\s*\{[\s\S]*await\s|^function\s*\*|\.then\s*\(/;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Detects if function is async at compile time.
|
|
30
|
+
* Checks: async keyword, await usage, generators, .then()
|
|
31
|
+
*/
|
|
32
|
+
export function isAsyncFunction(fn: Function): boolean {
|
|
33
|
+
if (fn.constructor.name === 'AsyncFunction') {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const source = fn.toString();
|
|
38
|
+
|
|
39
|
+
return ASYNC_REGEX.test(source);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Detects if handler returns a static value.
|
|
44
|
+
* Static handlers can be pre-computed at startup.
|
|
45
|
+
*/
|
|
46
|
+
export function isStaticHandler(fn: Function): boolean {
|
|
47
|
+
const source = fn.toString();
|
|
48
|
+
|
|
49
|
+
if (source.includes('this.') || source.includes('await')) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const returnMatch = source.match(/=>\s*["'`]|return\s+["'`]|=>\s*\{|=>\s*\d/);
|
|
54
|
+
|
|
55
|
+
return !!returnMatch;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Compiles handler with inlined parameter access.
|
|
60
|
+
* Uses new Function() for maximum V8 optimization.
|
|
61
|
+
*/
|
|
62
|
+
export function compileHandler(
|
|
63
|
+
instance: any,
|
|
64
|
+
methodName: string,
|
|
65
|
+
params: ParamInfo[]
|
|
66
|
+
): CompiledHandler {
|
|
67
|
+
const method = instance[methodName];
|
|
68
|
+
const bound = method.bind(instance);
|
|
69
|
+
const async = isAsyncFunction(method);
|
|
70
|
+
|
|
71
|
+
if (params.length === 0) {
|
|
72
|
+
const isStatic = isStaticHandler(method);
|
|
73
|
+
|
|
74
|
+
if (isStatic && !async) {
|
|
75
|
+
const staticValue = bound();
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
fn: bound,
|
|
79
|
+
isAsync: false,
|
|
80
|
+
isStatic: true,
|
|
81
|
+
staticValue
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
fn: bound,
|
|
87
|
+
isAsync: async,
|
|
88
|
+
isStatic: false
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const argExprs = params
|
|
93
|
+
.sort((a, b) => a.index - b.index)
|
|
94
|
+
.map(p => buildArgExpression(p));
|
|
95
|
+
|
|
96
|
+
const argsCode = argExprs.join(',');
|
|
97
|
+
const hasBody = params.some(p => p.type === 'body');
|
|
98
|
+
|
|
99
|
+
if (hasBody) {
|
|
100
|
+
const code = `return async function(c){
|
|
101
|
+
await c.parseBody();
|
|
102
|
+
return h(${argsCode});
|
|
103
|
+
}`;
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
fn: new Function('h', code)(bound),
|
|
107
|
+
isAsync: true,
|
|
108
|
+
isStatic: false
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (async) {
|
|
113
|
+
const code = `return async function(c){
|
|
114
|
+
return await h(${argsCode});
|
|
115
|
+
}`;
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
fn: new Function('h', code)(bound),
|
|
119
|
+
isAsync: true,
|
|
120
|
+
isStatic: false
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const code = `return function(c){
|
|
125
|
+
return h(${argsCode});
|
|
126
|
+
}`;
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
fn: new Function('h', code)(bound),
|
|
130
|
+
isAsync: false,
|
|
131
|
+
isStatic: false
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function escapeKey(key: string): string {
|
|
136
|
+
return key.replace(/['\"\\]/g, '\\$&');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function buildArgExpression(param: ParamInfo): string {
|
|
140
|
+
const key = param.key ? escapeKey(param.key) : undefined;
|
|
141
|
+
|
|
142
|
+
switch (param.type) {
|
|
143
|
+
case 'param':
|
|
144
|
+
return key ? `c.params['${key}']` : 'c.params';
|
|
145
|
+
|
|
146
|
+
case 'query':
|
|
147
|
+
return key ? `c.query['${key}']` : 'c.query';
|
|
148
|
+
|
|
149
|
+
case 'body':
|
|
150
|
+
return key ? `c.body['${key}']` : 'c.body';
|
|
151
|
+
|
|
152
|
+
case 'header':
|
|
153
|
+
return key ? `c.req.headers.get('${key}')` : 'c.req.headers';
|
|
154
|
+
|
|
155
|
+
case 'req':
|
|
156
|
+
return 'c.req';
|
|
157
|
+
|
|
158
|
+
case 'ctx':
|
|
159
|
+
return 'c';
|
|
160
|
+
|
|
161
|
+
case 'locals':
|
|
162
|
+
return key ? `c.locals['${key}']` : 'c.locals';
|
|
163
|
+
|
|
164
|
+
default:
|
|
165
|
+
return 'undefined';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight DI Container for Turbo.
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Constructor injection via reflect-metadata
|
|
6
|
+
* - Singleton scope by default
|
|
7
|
+
* - Request scope support
|
|
8
|
+
* - Lazy instantiation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export type Token<T = any> = new (...args: any[]) => T;
|
|
12
|
+
|
|
13
|
+
export enum Scope {
|
|
14
|
+
SINGLETON = 'singleton', // Always the same instance
|
|
15
|
+
REQUEST = 'request', // New instance per request
|
|
16
|
+
INSTANCE = 'instance' // New instance per dependency injection
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ProviderConfig<T = any> {
|
|
20
|
+
token: Token<T>;
|
|
21
|
+
useClass?: Token<T>;
|
|
22
|
+
useValue?: T;
|
|
23
|
+
scope?: Scope;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ProviderEntry {
|
|
27
|
+
config: ProviderConfig;
|
|
28
|
+
instance: any | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class Container {
|
|
32
|
+
private configs = new Map<Token, ProviderConfig>();
|
|
33
|
+
private instances = new Map<Token, any>();
|
|
34
|
+
private resolving = new Set<Token>();
|
|
35
|
+
|
|
36
|
+
register<T>(config: ProviderConfig<T> | Token<T>): this {
|
|
37
|
+
const normalized = this.normalizeConfig(config);
|
|
38
|
+
|
|
39
|
+
this.configs.set(normalized.token, normalized);
|
|
40
|
+
|
|
41
|
+
if (normalized.useValue !== undefined) {
|
|
42
|
+
this.instances.set(normalized.token, normalized.useValue);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get<T>(token: Token<T>): T {
|
|
49
|
+
const cached = this.instances.get(token);
|
|
50
|
+
|
|
51
|
+
if (cached !== undefined) {
|
|
52
|
+
return cached;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const res = this.resolveInternal(token);
|
|
56
|
+
return res.instance;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
has(token: Token): boolean {
|
|
60
|
+
return this.configs.has(token);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolves a token to return instance and its effective scope.
|
|
65
|
+
*/
|
|
66
|
+
private resolveInternal<T>(token: Token<T>, requestLocals?: Map<Token, any>): { instance: T, scope: Scope } {
|
|
67
|
+
// 1. Check Request Cache
|
|
68
|
+
if (requestLocals?.has(token)) {
|
|
69
|
+
return { instance: requestLocals.get(token), scope: Scope.REQUEST };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 2. Check Singleton Cache
|
|
73
|
+
const cached = this.instances.get(token);
|
|
74
|
+
if (cached !== undefined) {
|
|
75
|
+
return { instance: cached, scope: Scope.SINGLETON };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const config = this.configs.get(token);
|
|
79
|
+
|
|
80
|
+
if (!config) {
|
|
81
|
+
throw new Error(`Provider not found: ${token.name}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 3. Create Instance with Scope Bubbling
|
|
85
|
+
const creation = this.createInstance(config, requestLocals);
|
|
86
|
+
|
|
87
|
+
// 4. Cache based on Effective Scope
|
|
88
|
+
if (creation.scope === Scope.SINGLETON) {
|
|
89
|
+
this.instances.set(token, creation.instance);
|
|
90
|
+
} else if (creation.scope === Scope.REQUEST && requestLocals) {
|
|
91
|
+
requestLocals.set(token, creation.instance);
|
|
92
|
+
}
|
|
93
|
+
// INSTANCE scope is never cached
|
|
94
|
+
|
|
95
|
+
return creation;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private createInstance(config: ProviderConfig, requestLocals?: Map<Token, any>): { instance: any, scope: Scope } {
|
|
99
|
+
const target = config.useClass ?? config.token;
|
|
100
|
+
|
|
101
|
+
if (this.resolving.has(target)) {
|
|
102
|
+
throw new Error(`Circular dependency detected: ${target.name}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
this.resolving.add(target);
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const depsToken = this.getDependencies(target);
|
|
109
|
+
|
|
110
|
+
if (depsToken.length === 0) {
|
|
111
|
+
// No deps: Scope is as configured
|
|
112
|
+
return { instance: new target(), scope: config.scope || Scope.SINGLETON };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const args: any[] = [];
|
|
116
|
+
let effectiveScope = config.scope || Scope.SINGLETON;
|
|
117
|
+
|
|
118
|
+
for (const depToken of depsToken) {
|
|
119
|
+
const depResult = this.resolveInternal(depToken, requestLocals);
|
|
120
|
+
args.push(depResult.instance);
|
|
121
|
+
|
|
122
|
+
// Scope Bubbling Logic:
|
|
123
|
+
// If a dependency is REQUEST scoped, the parent MUST become REQUEST scoped (if it was Singleton)
|
|
124
|
+
// to avoid holding a stale reference to a request-bound instance.
|
|
125
|
+
if (depResult.scope === Scope.REQUEST && effectiveScope === Scope.SINGLETON) {
|
|
126
|
+
effectiveScope = Scope.REQUEST;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Note: INSTANCE scope dependencies do not force bubbling because they are transient and safe to hold (usually),
|
|
130
|
+
// unless semantic logic dictates otherwise. For now, strictly bubbling REQUEST scope.
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return { instance: new target(...args), scope: effectiveScope };
|
|
134
|
+
} finally {
|
|
135
|
+
this.resolving.delete(target);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private getDependencies(target: Token): Token[] {
|
|
140
|
+
const types = Reflect.getMetadata('design:paramtypes', target) || [];
|
|
141
|
+
return types.filter((t: any) => t && typeof t === 'function' && !this.isPrimitive(t));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private isPrimitive(type: any): boolean {
|
|
145
|
+
return type === String || type === Number || type === Boolean || type === Object || type === Array || type === Symbol;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private normalizeConfig<T>(config: ProviderConfig<T> | Token<T>): ProviderConfig<T> {
|
|
149
|
+
if (typeof config === 'function') {
|
|
150
|
+
return {
|
|
151
|
+
token: config,
|
|
152
|
+
useClass: config,
|
|
153
|
+
scope: Scope.SINGLETON
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
...config,
|
|
159
|
+
useClass: config.useClass ?? config.token,
|
|
160
|
+
scope: config.scope ?? Scope.SINGLETON
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
clear(): void {
|
|
165
|
+
this.configs.clear();
|
|
166
|
+
this.instances.clear();
|
|
167
|
+
}
|
|
168
|
+
}
|