@veloxts/core 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +697 -16
- package/dist/app.d.ts +67 -10
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +79 -12
- package/dist/app.js.map +1 -1
- package/dist/context.d.ts +26 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +29 -0
- package/dist/context.js.map +1 -1
- package/dist/di/container.d.ts +406 -0
- package/dist/di/container.d.ts.map +1 -0
- package/dist/di/container.js +699 -0
- package/dist/di/container.js.map +1 -0
- package/dist/di/decorators.d.ts +235 -0
- package/dist/di/decorators.d.ts.map +1 -0
- package/dist/di/decorators.js +297 -0
- package/dist/di/decorators.js.map +1 -0
- package/dist/di/index.d.ts +65 -0
- package/dist/di/index.d.ts.map +1 -0
- package/dist/di/index.js +73 -0
- package/dist/di/index.js.map +1 -0
- package/dist/di/providers.d.ts +397 -0
- package/dist/di/providers.d.ts.map +1 -0
- package/dist/di/providers.js +380 -0
- package/dist/di/providers.js.map +1 -0
- package/dist/di/scope.d.ts +230 -0
- package/dist/di/scope.d.ts.map +1 -0
- package/dist/di/scope.js +294 -0
- package/dist/di/scope.js.map +1 -0
- package/dist/di/tokens.d.ts +227 -0
- package/dist/di/tokens.d.ts.map +1 -0
- package/dist/di/tokens.js +192 -0
- package/dist/di/tokens.js.map +1 -0
- package/dist/errors/catalog.d.ts +79 -0
- package/dist/errors/catalog.d.ts.map +1 -0
- package/dist/errors/catalog.js +492 -0
- package/dist/errors/catalog.js.map +1 -0
- package/dist/errors/formatter.d.ts +101 -0
- package/dist/errors/formatter.d.ts.map +1 -0
- package/dist/errors/formatter.js +330 -0
- package/dist/errors/formatter.js.map +1 -0
- package/dist/errors/index.d.ts +14 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +16 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors.d.ts +35 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +57 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/package.json +14 -2
package/dist/di/scope.js
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle scope management for dependency injection
|
|
3
|
+
*
|
|
4
|
+
* Defines how service instances are created and shared:
|
|
5
|
+
* - Singleton: One instance for the entire application
|
|
6
|
+
* - Transient: New instance on every resolution
|
|
7
|
+
* - Request: One instance per HTTP request
|
|
8
|
+
*
|
|
9
|
+
* @module di/scope
|
|
10
|
+
*/
|
|
11
|
+
import { VeloxError } from '../errors.js';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Scope Enum
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Service lifecycle scope
|
|
17
|
+
*
|
|
18
|
+
* Determines how instances are created and shared across the application.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // Singleton - shared across all requests
|
|
23
|
+
* container.register({
|
|
24
|
+
* provide: ConfigService,
|
|
25
|
+
* useClass: ConfigService,
|
|
26
|
+
* scope: Scope.SINGLETON
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Transient - new instance every time
|
|
30
|
+
* container.register({
|
|
31
|
+
* provide: RequestIdGenerator,
|
|
32
|
+
* useClass: RequestIdGenerator,
|
|
33
|
+
* scope: Scope.TRANSIENT
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Request - shared within a single HTTP request
|
|
37
|
+
* container.register({
|
|
38
|
+
* provide: UserContext,
|
|
39
|
+
* useClass: UserContext,
|
|
40
|
+
* scope: Scope.REQUEST
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export var Scope;
|
|
45
|
+
(function (Scope) {
|
|
46
|
+
/**
|
|
47
|
+
* Singleton scope
|
|
48
|
+
*
|
|
49
|
+
* A single instance is created and shared across the entire application.
|
|
50
|
+
* The instance is created on first resolution and reused for all subsequent
|
|
51
|
+
* resolutions.
|
|
52
|
+
*
|
|
53
|
+
* Best for:
|
|
54
|
+
* - Configuration services
|
|
55
|
+
* - Database connection pools
|
|
56
|
+
* - Cache clients
|
|
57
|
+
* - Stateless utility services
|
|
58
|
+
*/
|
|
59
|
+
Scope["SINGLETON"] = "singleton";
|
|
60
|
+
/**
|
|
61
|
+
* Transient scope
|
|
62
|
+
*
|
|
63
|
+
* A new instance is created every time the service is resolved.
|
|
64
|
+
* No caching or sharing occurs.
|
|
65
|
+
*
|
|
66
|
+
* Best for:
|
|
67
|
+
* - Services that maintain mutable state
|
|
68
|
+
* - Factories that produce unique objects
|
|
69
|
+
* - Services where isolation is critical
|
|
70
|
+
*/
|
|
71
|
+
Scope["TRANSIENT"] = "transient";
|
|
72
|
+
/**
|
|
73
|
+
* Request scope
|
|
74
|
+
*
|
|
75
|
+
* A single instance is created and shared within the lifetime of an HTTP request.
|
|
76
|
+
* Different requests get different instances.
|
|
77
|
+
*
|
|
78
|
+
* Best for:
|
|
79
|
+
* - User context/session data
|
|
80
|
+
* - Request-specific caching
|
|
81
|
+
* - Transaction management
|
|
82
|
+
* - Audit logging with request context
|
|
83
|
+
*
|
|
84
|
+
* Note: Resolving request-scoped services outside of a request context
|
|
85
|
+
* will throw an error.
|
|
86
|
+
*/
|
|
87
|
+
Scope["REQUEST"] = "request";
|
|
88
|
+
})(Scope || (Scope = {}));
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// Scope Manager
|
|
91
|
+
// ============================================================================
|
|
92
|
+
/**
|
|
93
|
+
* Request-scoped instance store key
|
|
94
|
+
* Using a symbol prevents collision with user-defined properties
|
|
95
|
+
*/
|
|
96
|
+
const REQUEST_SCOPE_KEY = Symbol('velox:di:request-scope');
|
|
97
|
+
/**
|
|
98
|
+
* Manages service instance lifecycles
|
|
99
|
+
*
|
|
100
|
+
* Handles creation, caching, and cleanup of service instances
|
|
101
|
+
* based on their configured scope.
|
|
102
|
+
*
|
|
103
|
+
* @internal
|
|
104
|
+
*/
|
|
105
|
+
export class ScopeManager {
|
|
106
|
+
/**
|
|
107
|
+
* Singleton instance cache
|
|
108
|
+
* Maps tokens to their singleton instances
|
|
109
|
+
*/
|
|
110
|
+
singletonCache = new Map();
|
|
111
|
+
/**
|
|
112
|
+
* Whether request scope hooks have been set up
|
|
113
|
+
*/
|
|
114
|
+
requestScopeInitialized = false;
|
|
115
|
+
/**
|
|
116
|
+
* Attaches the scope manager to a Fastify server
|
|
117
|
+
*
|
|
118
|
+
* This sets up the request lifecycle hooks needed for request-scoped services.
|
|
119
|
+
* Must be called before resolving request-scoped services.
|
|
120
|
+
*
|
|
121
|
+
* @param server - Fastify server instance
|
|
122
|
+
*/
|
|
123
|
+
attachToFastify(server) {
|
|
124
|
+
if (this.requestScopeInitialized) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Initialize request scope cache on each request
|
|
128
|
+
server.addHook('onRequest', async (request) => {
|
|
129
|
+
request[REQUEST_SCOPE_KEY] = new Map();
|
|
130
|
+
});
|
|
131
|
+
// Clean up request scope cache after response
|
|
132
|
+
server.addHook('onResponse', async (request) => {
|
|
133
|
+
const cache = request[REQUEST_SCOPE_KEY];
|
|
134
|
+
if (cache) {
|
|
135
|
+
cache.clear();
|
|
136
|
+
delete request[REQUEST_SCOPE_KEY];
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
this.requestScopeInitialized = true;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Gets a singleton instance from cache
|
|
143
|
+
*
|
|
144
|
+
* @param token - The service token
|
|
145
|
+
* @returns The cached instance or undefined
|
|
146
|
+
*/
|
|
147
|
+
getSingleton(token) {
|
|
148
|
+
return this.singletonCache.get(token);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Stores a singleton instance in cache
|
|
152
|
+
*
|
|
153
|
+
* @param token - The service token
|
|
154
|
+
* @param instance - The instance to cache
|
|
155
|
+
*/
|
|
156
|
+
setSingleton(token, instance) {
|
|
157
|
+
this.singletonCache.set(token, instance);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Checks if a singleton instance exists
|
|
161
|
+
*
|
|
162
|
+
* @param token - The service token
|
|
163
|
+
* @returns true if a singleton instance is cached
|
|
164
|
+
*/
|
|
165
|
+
hasSingleton(token) {
|
|
166
|
+
return this.singletonCache.has(token);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Gets a singleton instance from cache, throwing if not found
|
|
170
|
+
*
|
|
171
|
+
* Use this when you've already verified with hasSingleton()
|
|
172
|
+
*
|
|
173
|
+
* @param token - The service token
|
|
174
|
+
* @returns The cached instance
|
|
175
|
+
* @throws {VeloxError} If no singleton is cached for this token
|
|
176
|
+
*/
|
|
177
|
+
getSingletonOrThrow(token) {
|
|
178
|
+
if (!this.singletonCache.has(token)) {
|
|
179
|
+
throw new VeloxError('Singleton not found for token', 500, 'SINGLETON_NOT_FOUND');
|
|
180
|
+
}
|
|
181
|
+
return this.singletonCache.get(token);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Gets a request-scoped instance from the current request's cache
|
|
185
|
+
*
|
|
186
|
+
* @param token - The service token
|
|
187
|
+
* @param request - The current Fastify request
|
|
188
|
+
* @returns The cached instance or undefined
|
|
189
|
+
*/
|
|
190
|
+
getRequestScoped(token, request) {
|
|
191
|
+
const cache = request[REQUEST_SCOPE_KEY];
|
|
192
|
+
if (!cache) {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
return cache.get(token);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Stores a request-scoped instance in the current request's cache
|
|
199
|
+
*
|
|
200
|
+
* @param token - The service token
|
|
201
|
+
* @param instance - The instance to cache
|
|
202
|
+
* @param request - The current Fastify request
|
|
203
|
+
*/
|
|
204
|
+
setRequestScoped(token, instance, request) {
|
|
205
|
+
const cache = request[REQUEST_SCOPE_KEY];
|
|
206
|
+
if (!cache) {
|
|
207
|
+
throw new VeloxError('Request scope cache not initialized. Ensure ScopeManager is attached to Fastify.', 500, 'REQUEST_SCOPE_UNAVAILABLE');
|
|
208
|
+
}
|
|
209
|
+
cache.set(token, instance);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Checks if a request-scoped instance exists
|
|
213
|
+
*
|
|
214
|
+
* @param token - The service token
|
|
215
|
+
* @param request - The current Fastify request
|
|
216
|
+
* @returns true if a request-scoped instance is cached
|
|
217
|
+
*/
|
|
218
|
+
hasRequestScoped(token, request) {
|
|
219
|
+
const cache = request[REQUEST_SCOPE_KEY];
|
|
220
|
+
return cache?.has(token) ?? false;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Gets a request-scoped instance from cache, throwing if not found
|
|
224
|
+
*
|
|
225
|
+
* Use this when you've already verified with hasRequestScoped()
|
|
226
|
+
*
|
|
227
|
+
* @param token - The service token
|
|
228
|
+
* @param request - The current Fastify request
|
|
229
|
+
* @returns The cached instance
|
|
230
|
+
* @throws {VeloxError} If no request-scoped instance is cached for this token
|
|
231
|
+
*/
|
|
232
|
+
getRequestScopedOrThrow(token, request) {
|
|
233
|
+
const cache = request[REQUEST_SCOPE_KEY];
|
|
234
|
+
if (!cache || !cache.has(token)) {
|
|
235
|
+
throw new VeloxError('Request-scoped instance not found for token', 500, 'REQUEST_SCOPED_NOT_FOUND');
|
|
236
|
+
}
|
|
237
|
+
return cache.get(token);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Validates that request scope is available and returns the request
|
|
241
|
+
*
|
|
242
|
+
* @param request - The current request (may be undefined outside request context)
|
|
243
|
+
* @returns The validated FastifyRequest
|
|
244
|
+
* @throws {VeloxError} If request scope is not available
|
|
245
|
+
*/
|
|
246
|
+
ensureRequestScope(request) {
|
|
247
|
+
if (!request) {
|
|
248
|
+
throw new VeloxError('Cannot resolve request-scoped service outside of request context. ' +
|
|
249
|
+
'Ensure you are resolving within a request handler or middleware.', 500, 'REQUEST_SCOPE_UNAVAILABLE');
|
|
250
|
+
}
|
|
251
|
+
if (!request[REQUEST_SCOPE_KEY]) {
|
|
252
|
+
throw new VeloxError('Request scope cache not initialized. Ensure ScopeManager is attached to Fastify.', 500, 'REQUEST_SCOPE_UNAVAILABLE');
|
|
253
|
+
}
|
|
254
|
+
return request;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Clears all singleton instances
|
|
258
|
+
*
|
|
259
|
+
* Useful for testing or application shutdown.
|
|
260
|
+
*/
|
|
261
|
+
clearSingletons() {
|
|
262
|
+
this.singletonCache.clear();
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Clears all cached instances and resets state
|
|
266
|
+
*
|
|
267
|
+
* @internal
|
|
268
|
+
*/
|
|
269
|
+
reset() {
|
|
270
|
+
this.singletonCache.clear();
|
|
271
|
+
this.requestScopeInitialized = false;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// ============================================================================
|
|
275
|
+
// Scope Utilities
|
|
276
|
+
// ============================================================================
|
|
277
|
+
/**
|
|
278
|
+
* Validates a scope value
|
|
279
|
+
*
|
|
280
|
+
* @param scope - The scope to validate
|
|
281
|
+
* @returns true if the scope is valid
|
|
282
|
+
*/
|
|
283
|
+
export function isValidScope(scope) {
|
|
284
|
+
return scope === Scope.SINGLETON || scope === Scope.TRANSIENT || scope === Scope.REQUEST;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Gets the default scope for a provider
|
|
288
|
+
*
|
|
289
|
+
* @returns The default scope (SINGLETON)
|
|
290
|
+
*/
|
|
291
|
+
export function getDefaultScope() {
|
|
292
|
+
return Scope.SINGLETON;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/di/scope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service tokens for dependency injection
|
|
3
|
+
*
|
|
4
|
+
* Tokens are unique identifiers used to register and resolve services.
|
|
5
|
+
* VeloxTS supports three token types:
|
|
6
|
+
* - Class tokens: The class constructor itself
|
|
7
|
+
* - String tokens: String literals for named services
|
|
8
|
+
* - Symbol tokens: Unique symbols for collision-free tokens
|
|
9
|
+
*
|
|
10
|
+
* @module di/tokens
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Abstract class token type
|
|
14
|
+
*
|
|
15
|
+
* Represents a class constructor that can be used as a service token.
|
|
16
|
+
* Supports both concrete classes and abstract classes.
|
|
17
|
+
*
|
|
18
|
+
* @template T - The type that the class constructs
|
|
19
|
+
*/
|
|
20
|
+
export interface AbstractClass<T = unknown> {
|
|
21
|
+
prototype: T;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Concrete class constructor type
|
|
25
|
+
*
|
|
26
|
+
* Represents a class that can be instantiated with `new`.
|
|
27
|
+
* The constructor accepts any arguments and returns an instance of T.
|
|
28
|
+
*
|
|
29
|
+
* @template T - The type that the class constructs
|
|
30
|
+
*/
|
|
31
|
+
export interface ClassConstructor<T = unknown> extends AbstractClass<T> {
|
|
32
|
+
new (...args: never[]): T;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Unique brand symbol for string tokens (compile-time only)
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
declare const StringTokenBrand: unique symbol;
|
|
39
|
+
/**
|
|
40
|
+
* Unique brand symbol for symbol tokens (compile-time only)
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
declare const SymbolTokenBrand: unique symbol;
|
|
44
|
+
/**
|
|
45
|
+
* String token type for named services
|
|
46
|
+
*
|
|
47
|
+
* Branded type to distinguish service tokens from regular strings at compile time.
|
|
48
|
+
* The brand is purely a compile-time construct for type safety.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const DATABASE = createStringToken<DatabaseClient>('DATABASE');
|
|
53
|
+
* container.register({ provide: DATABASE, useFactory: () => createDb() });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export type StringToken<T = unknown> = string & {
|
|
57
|
+
readonly [StringTokenBrand]: T;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Symbol token type for unique service identifiers
|
|
61
|
+
*
|
|
62
|
+
* Branded type that carries the service type information.
|
|
63
|
+
* The brand is purely a compile-time construct for type safety.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const LOGGER = createSymbolToken<Logger>('LOGGER');
|
|
68
|
+
* container.register({ provide: LOGGER, useClass: ConsoleLogger });
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export type SymbolToken<T = unknown> = symbol & {
|
|
72
|
+
readonly [SymbolTokenBrand]: T;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Union of all valid injection token types
|
|
76
|
+
*
|
|
77
|
+
* A token can be:
|
|
78
|
+
* - A class constructor (for automatic injection)
|
|
79
|
+
* - A string token (for named services)
|
|
80
|
+
* - A symbol token (for unique identifiers)
|
|
81
|
+
*
|
|
82
|
+
* @template T - The type of service the token represents
|
|
83
|
+
*/
|
|
84
|
+
export type InjectionToken<T = unknown> = ClassConstructor<T> | AbstractClass<T> | StringToken<T> | SymbolToken<T>;
|
|
85
|
+
/**
|
|
86
|
+
* Extract the type from an injection token
|
|
87
|
+
*
|
|
88
|
+
* @template T - The injection token type
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* type UserServiceType = TokenType<typeof UserService>; // UserService
|
|
93
|
+
* type DbType = TokenType<typeof DATABASE>; // DatabaseClient
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export type TokenType<T> = T extends InjectionToken<infer U> ? U : never;
|
|
97
|
+
/**
|
|
98
|
+
* Creates a typed string token for service registration
|
|
99
|
+
*
|
|
100
|
+
* String tokens are useful when you want human-readable identifiers.
|
|
101
|
+
* The type parameter ensures type safety when resolving the service.
|
|
102
|
+
*
|
|
103
|
+
* @template T - The type of service this token represents
|
|
104
|
+
* @param name - The string identifier for this token
|
|
105
|
+
* @returns A typed string token
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* interface DatabaseClient {
|
|
110
|
+
* query(sql: string): Promise<unknown>;
|
|
111
|
+
* }
|
|
112
|
+
*
|
|
113
|
+
* const DATABASE = createStringToken<DatabaseClient>('DATABASE');
|
|
114
|
+
*
|
|
115
|
+
* // Registration
|
|
116
|
+
* container.register({
|
|
117
|
+
* provide: DATABASE,
|
|
118
|
+
* useFactory: () => createDatabaseClient()
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* // Resolution - type is inferred as DatabaseClient
|
|
122
|
+
* const db = container.resolve(DATABASE);
|
|
123
|
+
* await db.query('SELECT * FROM users');
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
export declare function createStringToken<T>(name: string): StringToken<T>;
|
|
127
|
+
/**
|
|
128
|
+
* Creates a typed symbol token for service registration
|
|
129
|
+
*
|
|
130
|
+
* Symbol tokens guarantee uniqueness across the application,
|
|
131
|
+
* preventing name collisions between different modules.
|
|
132
|
+
*
|
|
133
|
+
* @template T - The type of service this token represents
|
|
134
|
+
* @param description - Optional description for debugging
|
|
135
|
+
* @returns A typed symbol token
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* interface Logger {
|
|
140
|
+
* log(message: string): void;
|
|
141
|
+
* }
|
|
142
|
+
*
|
|
143
|
+
* const LOGGER = createSymbolToken<Logger>('Logger');
|
|
144
|
+
*
|
|
145
|
+
* // Registration
|
|
146
|
+
* container.register({
|
|
147
|
+
* provide: LOGGER,
|
|
148
|
+
* useClass: ConsoleLogger
|
|
149
|
+
* });
|
|
150
|
+
*
|
|
151
|
+
* // Resolution - type is inferred as Logger
|
|
152
|
+
* const logger = container.resolve(LOGGER);
|
|
153
|
+
* logger.log('Hello, world!');
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export declare function createSymbolToken<T>(description?: string): SymbolToken<T>;
|
|
157
|
+
/**
|
|
158
|
+
* Creates a typed string token for service registration
|
|
159
|
+
*
|
|
160
|
+
* This is the preferred API for creating tokens. String tokens are
|
|
161
|
+
* useful when you want human-readable identifiers.
|
|
162
|
+
*
|
|
163
|
+
* @template T - The type of service this token represents
|
|
164
|
+
* @param name - The string identifier for this token
|
|
165
|
+
* @returns A typed string token
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const DATABASE = token<DatabaseClient>('DATABASE');
|
|
170
|
+
* const CONFIG = token<AppConfig>('CONFIG');
|
|
171
|
+
*
|
|
172
|
+
* container.register({ provide: DATABASE, useFactory: createDb });
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export declare function token<T>(name: string): StringToken<T>;
|
|
176
|
+
export declare namespace token {
|
|
177
|
+
var symbol: <T>(description?: string) => SymbolToken<T>;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Gets a human-readable name for a token
|
|
181
|
+
*
|
|
182
|
+
* @param token - The token to get the name for
|
|
183
|
+
* @returns A string representation of the token
|
|
184
|
+
*
|
|
185
|
+
* @internal
|
|
186
|
+
*/
|
|
187
|
+
export declare function getTokenName(token: InjectionToken): string;
|
|
188
|
+
/**
|
|
189
|
+
* Type guard for class constructor tokens
|
|
190
|
+
*
|
|
191
|
+
* @param token - The token to check
|
|
192
|
+
* @returns true if the token is a class constructor
|
|
193
|
+
*/
|
|
194
|
+
export declare function isClassToken(token: InjectionToken): token is ClassConstructor;
|
|
195
|
+
/**
|
|
196
|
+
* Type guard for string tokens
|
|
197
|
+
*
|
|
198
|
+
* @param token - The token to check
|
|
199
|
+
* @returns true if the token is a string token
|
|
200
|
+
*/
|
|
201
|
+
export declare function isStringToken(token: InjectionToken): token is StringToken;
|
|
202
|
+
/**
|
|
203
|
+
* Type guard for symbol tokens
|
|
204
|
+
*
|
|
205
|
+
* @param token - The token to check
|
|
206
|
+
* @returns true if the token is a symbol token
|
|
207
|
+
*/
|
|
208
|
+
export declare function isSymbolToken(token: InjectionToken): token is SymbolToken;
|
|
209
|
+
/**
|
|
210
|
+
* Validates that a token is a valid injection token
|
|
211
|
+
*
|
|
212
|
+
* @param token - The value to validate
|
|
213
|
+
* @throws {VeloxError} If the token is not valid
|
|
214
|
+
*
|
|
215
|
+
* @internal
|
|
216
|
+
*/
|
|
217
|
+
export declare function validateToken(token: unknown): asserts token is InjectionToken;
|
|
218
|
+
/**
|
|
219
|
+
* Extend the error code registry for DI-related errors
|
|
220
|
+
*/
|
|
221
|
+
declare module '../errors.js' {
|
|
222
|
+
interface VeloxErrorCodeRegistry {
|
|
223
|
+
di: 'INVALID_INJECTION_TOKEN' | 'SERVICE_NOT_FOUND' | 'CIRCULAR_DEPENDENCY' | 'MISSING_INJECTABLE_DECORATOR' | 'INVALID_PROVIDER' | 'SCOPE_MISMATCH' | 'REQUEST_SCOPE_UNAVAILABLE';
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
export {};
|
|
227
|
+
//# sourceMappingURL=tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/di/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,SAAS,EAAE,CAAC,CAAC;CACd;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IACrE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;CAC3B;AAED;;;GAGG;AACH,OAAO,CAAC,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC;AAE9C;;;GAGG;AACH,OAAO,CAAC,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEnF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEnF;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAClC,gBAAgB,CAAC,CAAC,CAAC,GACnB,aAAa,CAAC,CAAC,CAAC,GAChB,WAAW,CAAC,CAAC,CAAC,GACd,WAAW,CAAC,CAAC,CAAC,CAAC;AAEnB;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAMzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAEjE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAEzE;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAErD;yBAFe,KAAK;iBAkBe,CAAC,gBAAgB,MAAM,KAAG,WAAW,CAAC,CAAC,CAAC;;AAQ5E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAkB1D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,gBAAgB,CAE7E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,WAAW,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,WAAW,CAGzE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,cAAc,CAkB7E;AAMD;;GAEG;AACH,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,sBAAsB;QAC9B,EAAE,EACE,yBAAyB,GACzB,mBAAmB,GACnB,qBAAqB,GACrB,8BAA8B,GAC9B,kBAAkB,GAClB,gBAAgB,GAChB,2BAA2B,CAAC;KACjC;CACF"}
|