@veloxts/core 0.3.3 → 0.3.4

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.
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Provider types and registration interfaces for dependency injection
3
+ *
4
+ * Providers define how services are created and configured.
5
+ * VeloxTS supports four provider types:
6
+ * - Class providers: Instantiate a class
7
+ * - Factory providers: Use a factory function
8
+ * - Value providers: Use an existing value
9
+ * - Existing providers: Alias another token
10
+ *
11
+ * @module di/providers
12
+ */
13
+ import { VeloxError } from '../errors.js';
14
+ import { getDefaultScope, isValidScope, Scope } from './scope.js';
15
+ import { getTokenName, validateToken } from './tokens.js';
16
+ // ============================================================================
17
+ // Provider Type Guards
18
+ // ============================================================================
19
+ /**
20
+ * Type guard for class providers
21
+ */
22
+ export function isClassProvider(provider) {
23
+ return 'useClass' in provider && typeof provider.useClass === 'function';
24
+ }
25
+ /**
26
+ * Type guard for factory providers
27
+ */
28
+ export function isFactoryProvider(provider) {
29
+ return 'useFactory' in provider && typeof provider.useFactory === 'function';
30
+ }
31
+ /**
32
+ * Type guard for value providers
33
+ */
34
+ export function isValueProvider(provider) {
35
+ return 'useValue' in provider;
36
+ }
37
+ /**
38
+ * Type guard for existing/alias providers
39
+ */
40
+ export function isExistingProvider(provider) {
41
+ return 'useExisting' in provider;
42
+ }
43
+ // ============================================================================
44
+ // Provider Validation
45
+ // ============================================================================
46
+ /**
47
+ * Validates a provider configuration
48
+ *
49
+ * @param provider - The provider to validate
50
+ * @throws {VeloxError} If the provider is invalid
51
+ */
52
+ export function validateProvider(provider) {
53
+ // Check provider is an object
54
+ if (typeof provider !== 'object' || provider === null) {
55
+ throw new VeloxError('Provider must be an object', 500, 'INVALID_PROVIDER');
56
+ }
57
+ // Check 'provide' token exists
58
+ if (!('provide' in provider)) {
59
+ throw new VeloxError('Provider must have a "provide" token', 500, 'INVALID_PROVIDER');
60
+ }
61
+ // Validate the token
62
+ validateToken(provider.provide);
63
+ const typedProvider = provider;
64
+ // Check that exactly one of the provider type properties exists
65
+ const providerTypes = ['useClass', 'useFactory', 'useValue', 'useExisting'];
66
+ const definedTypes = providerTypes.filter((type) => type in typedProvider);
67
+ if (definedTypes.length === 0) {
68
+ throw new VeloxError('Provider must specify one of: useClass, useFactory, useValue, or useExisting', 500, 'INVALID_PROVIDER');
69
+ }
70
+ if (definedTypes.length > 1) {
71
+ throw new VeloxError(`Provider cannot have multiple types. Found: ${definedTypes.join(', ')}`, 500, 'INVALID_PROVIDER');
72
+ }
73
+ // Validate scope if provided
74
+ if ('scope' in typedProvider && typedProvider.scope !== undefined) {
75
+ if (!isValidScope(typedProvider.scope)) {
76
+ throw new VeloxError(`Invalid scope: ${String(typedProvider.scope)}. Must be one of: singleton, transient, request`, 500, 'INVALID_PROVIDER');
77
+ }
78
+ }
79
+ // Validate specific provider types
80
+ if ('useClass' in typedProvider) {
81
+ if (typeof typedProvider.useClass !== 'function') {
82
+ throw new VeloxError('useClass must be a class constructor', 500, 'INVALID_PROVIDER');
83
+ }
84
+ }
85
+ if ('useFactory' in typedProvider) {
86
+ if (typeof typedProvider.useFactory !== 'function') {
87
+ throw new VeloxError('useFactory must be a function', 500, 'INVALID_PROVIDER');
88
+ }
89
+ if ('inject' in typedProvider && typedProvider.inject !== undefined) {
90
+ if (!Array.isArray(typedProvider.inject)) {
91
+ throw new VeloxError('Factory inject must be an array of injection tokens', 500, 'INVALID_PROVIDER');
92
+ }
93
+ // Validate each inject token
94
+ for (const token of typedProvider.inject) {
95
+ validateToken(token);
96
+ }
97
+ }
98
+ }
99
+ if ('useExisting' in typedProvider) {
100
+ validateToken(typedProvider.useExisting);
101
+ }
102
+ }
103
+ /**
104
+ * Normalizes a provider to a consistent internal format
105
+ *
106
+ * @param provider - The provider to normalize
107
+ * @returns The normalized provider
108
+ *
109
+ * @internal
110
+ */
111
+ export function normalizeProvider(provider) {
112
+ const scope = provider.scope ?? getDefaultScope();
113
+ if (isClassProvider(provider)) {
114
+ return {
115
+ provide: provider.provide,
116
+ scope,
117
+ type: 'class',
118
+ implementation: {
119
+ class: provider.useClass,
120
+ },
121
+ };
122
+ }
123
+ if (isFactoryProvider(provider)) {
124
+ return {
125
+ provide: provider.provide,
126
+ scope,
127
+ type: 'factory',
128
+ implementation: {
129
+ factory: provider.useFactory,
130
+ inject: provider.inject,
131
+ },
132
+ };
133
+ }
134
+ if (isValueProvider(provider)) {
135
+ // Value providers are always effectively singleton since they use the same value
136
+ return {
137
+ provide: provider.provide,
138
+ scope: Scope.SINGLETON,
139
+ type: 'value',
140
+ implementation: {
141
+ value: provider.useValue,
142
+ },
143
+ };
144
+ }
145
+ if (isExistingProvider(provider)) {
146
+ return {
147
+ provide: provider.provide,
148
+ scope, // Inherit scope from the aliased provider at resolution time
149
+ type: 'existing',
150
+ implementation: {
151
+ existing: provider.useExisting,
152
+ },
153
+ };
154
+ }
155
+ // This should never happen due to validation, but TypeScript needs it
156
+ throw new VeloxError('Unknown provider type', 500, 'INVALID_PROVIDER');
157
+ }
158
+ // ============================================================================
159
+ // Convenience Provider Builders
160
+ // ============================================================================
161
+ /**
162
+ * Creates a class provider with type inference
163
+ *
164
+ * @param cls - The class to provide
165
+ * @param scope - The lifecycle scope
166
+ * @returns A class provider configuration
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * container.register(asClass(UserService, Scope.REQUEST));
171
+ * ```
172
+ */
173
+ export function asClass(cls, scope = Scope.SINGLETON) {
174
+ return {
175
+ provide: cls,
176
+ useClass: cls,
177
+ scope,
178
+ };
179
+ }
180
+ /**
181
+ * Creates a factory provider with type inference
182
+ *
183
+ * @param token - The token to provide
184
+ * @param factory - The factory function
185
+ * @param options - Factory options (inject, scope)
186
+ * @returns A factory provider configuration
187
+ *
188
+ * @example
189
+ * ```typescript
190
+ * container.register(asFactory(
191
+ * DATABASE,
192
+ * (config: ConfigService) => createDb(config.dbUrl),
193
+ * { inject: [ConfigService] }
194
+ * ));
195
+ * ```
196
+ */
197
+ export function asFactory(token, factory, options = {}) {
198
+ return {
199
+ provide: token,
200
+ useFactory: factory,
201
+ inject: options.inject,
202
+ scope: options.scope ?? Scope.SINGLETON,
203
+ };
204
+ }
205
+ /**
206
+ * Creates a value provider with type inference
207
+ *
208
+ * @param token - The token to provide
209
+ * @param value - The value to use
210
+ * @returns A value provider configuration
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * container.register(asValue(CONFIG, { port: 3210 }));
215
+ * ```
216
+ */
217
+ export function asValue(token, value) {
218
+ return {
219
+ provide: token,
220
+ useValue: value,
221
+ };
222
+ }
223
+ /**
224
+ * Creates an existing/alias provider with type inference
225
+ *
226
+ * @param token - The token to provide (alias)
227
+ * @param existing - The token to alias to
228
+ * @returns An existing provider configuration
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * container.register(asExisting(LOGGER, ConsoleLogger));
233
+ * ```
234
+ */
235
+ export function asExisting(token, existing) {
236
+ return {
237
+ provide: token,
238
+ useExisting: existing,
239
+ };
240
+ }
241
+ // ============================================================================
242
+ // Succinct Scope Helpers
243
+ // ============================================================================
244
+ /**
245
+ * Creates a singleton class provider
246
+ *
247
+ * Singleton services are instantiated once and shared across all requests.
248
+ * This is the default scope and the most common pattern.
249
+ *
250
+ * @param cls - The class to provide as a singleton
251
+ * @returns A class provider configured as singleton
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * container.register(singleton(ConfigService));
256
+ * container.register(singleton(DatabasePool));
257
+ * ```
258
+ */
259
+ export function singleton(cls) {
260
+ return {
261
+ provide: cls,
262
+ useClass: cls,
263
+ scope: Scope.SINGLETON,
264
+ };
265
+ }
266
+ /**
267
+ * Creates a request-scoped class provider
268
+ *
269
+ * Request-scoped services are instantiated once per HTTP request.
270
+ * Ideal for services that need request-specific state.
271
+ *
272
+ * @param cls - The class to provide with request scope
273
+ * @returns A class provider configured as request-scoped
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * container.register(scoped(RequestContext));
278
+ * container.register(scoped(UserSession));
279
+ * ```
280
+ */
281
+ export function scoped(cls) {
282
+ return {
283
+ provide: cls,
284
+ useClass: cls,
285
+ scope: Scope.REQUEST,
286
+ };
287
+ }
288
+ /**
289
+ * Creates a transient class provider
290
+ *
291
+ * Transient services are instantiated every time they are resolved.
292
+ * Useful for stateful objects that should not be shared.
293
+ *
294
+ * @param cls - The class to provide as transient
295
+ * @returns A class provider configured as transient
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * container.register(transient(EmailBuilder));
300
+ * container.register(transient(RequestId));
301
+ * ```
302
+ */
303
+ export function transient(cls) {
304
+ return {
305
+ provide: cls,
306
+ useClass: cls,
307
+ scope: Scope.TRANSIENT,
308
+ };
309
+ }
310
+ /**
311
+ * Creates a value provider (convenience alias)
312
+ *
313
+ * @param token - The token to provide
314
+ * @param val - The value to use
315
+ * @returns A value provider configuration
316
+ *
317
+ * @example
318
+ * ```typescript
319
+ * container.register(value(CONFIG, { port: 3210 }));
320
+ * ```
321
+ */
322
+ export function value(token, val) {
323
+ return {
324
+ provide: token,
325
+ useValue: val,
326
+ };
327
+ }
328
+ /**
329
+ * Creates a factory provider (convenience alias)
330
+ *
331
+ * @param token - The token to provide
332
+ * @param factoryFn - The factory function
333
+ * @param deps - Dependencies to inject into the factory
334
+ * @returns A factory provider configuration
335
+ *
336
+ * @example
337
+ * ```typescript
338
+ * container.register(factory(DATABASE, createDb, [ConfigService]));
339
+ * ```
340
+ */
341
+ export function factory(token, factoryFn, deps) {
342
+ return {
343
+ provide: token,
344
+ useFactory: factoryFn,
345
+ inject: deps,
346
+ scope: Scope.SINGLETON,
347
+ };
348
+ }
349
+ // ============================================================================
350
+ // Provider Description (for debugging)
351
+ // ============================================================================
352
+ /**
353
+ * Gets a human-readable description of a provider
354
+ *
355
+ * @param provider - The provider to describe
356
+ * @returns A string description
357
+ *
358
+ * @internal
359
+ */
360
+ export function describeProvider(provider) {
361
+ const tokenName = getTokenName(provider.provide);
362
+ const scope = provider.scope ?? 'singleton';
363
+ if (isClassProvider(provider)) {
364
+ const className = provider.useClass.name || 'AnonymousClass';
365
+ return `ClassProvider(${tokenName} => ${className}, ${scope})`;
366
+ }
367
+ if (isFactoryProvider(provider)) {
368
+ const deps = provider.inject?.map(getTokenName).join(', ') ?? 'none';
369
+ return `FactoryProvider(${tokenName}, deps=[${deps}], ${scope})`;
370
+ }
371
+ if (isValueProvider(provider)) {
372
+ return `ValueProvider(${tokenName})`;
373
+ }
374
+ if (isExistingProvider(provider)) {
375
+ const existing = getTokenName(provider.useExisting);
376
+ return `ExistingProvider(${tokenName} => ${existing})`;
377
+ }
378
+ return `Provider(${tokenName})`;
379
+ }
380
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/di/providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,209 @@
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 type { FastifyInstance, FastifyRequest } from 'fastify';
12
+ /**
13
+ * Service lifecycle scope
14
+ *
15
+ * Determines how instances are created and shared across the application.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // Singleton - shared across all requests
20
+ * container.register({
21
+ * provide: ConfigService,
22
+ * useClass: ConfigService,
23
+ * scope: Scope.SINGLETON
24
+ * });
25
+ *
26
+ * // Transient - new instance every time
27
+ * container.register({
28
+ * provide: RequestIdGenerator,
29
+ * useClass: RequestIdGenerator,
30
+ * scope: Scope.TRANSIENT
31
+ * });
32
+ *
33
+ * // Request - shared within a single HTTP request
34
+ * container.register({
35
+ * provide: UserContext,
36
+ * useClass: UserContext,
37
+ * scope: Scope.REQUEST
38
+ * });
39
+ * ```
40
+ */
41
+ export declare enum Scope {
42
+ /**
43
+ * Singleton scope
44
+ *
45
+ * A single instance is created and shared across the entire application.
46
+ * The instance is created on first resolution and reused for all subsequent
47
+ * resolutions.
48
+ *
49
+ * Best for:
50
+ * - Configuration services
51
+ * - Database connection pools
52
+ * - Cache clients
53
+ * - Stateless utility services
54
+ */
55
+ SINGLETON = "singleton",
56
+ /**
57
+ * Transient scope
58
+ *
59
+ * A new instance is created every time the service is resolved.
60
+ * No caching or sharing occurs.
61
+ *
62
+ * Best for:
63
+ * - Services that maintain mutable state
64
+ * - Factories that produce unique objects
65
+ * - Services where isolation is critical
66
+ */
67
+ TRANSIENT = "transient",
68
+ /**
69
+ * Request scope
70
+ *
71
+ * A single instance is created and shared within the lifetime of an HTTP request.
72
+ * Different requests get different instances.
73
+ *
74
+ * Best for:
75
+ * - User context/session data
76
+ * - Request-specific caching
77
+ * - Transaction management
78
+ * - Audit logging with request context
79
+ *
80
+ * Note: Resolving request-scoped services outside of a request context
81
+ * will throw an error.
82
+ */
83
+ REQUEST = "request"
84
+ }
85
+ /**
86
+ * Request-scoped instance store key
87
+ * Using a symbol prevents collision with user-defined properties
88
+ */
89
+ declare const REQUEST_SCOPE_KEY: unique symbol;
90
+ /**
91
+ * Type augmentation for Fastify request to store scoped instances
92
+ */
93
+ declare module 'fastify' {
94
+ interface FastifyRequest {
95
+ /**
96
+ * Request-scoped service instance cache
97
+ * @internal
98
+ */
99
+ [REQUEST_SCOPE_KEY]?: Map<unknown, unknown>;
100
+ }
101
+ }
102
+ /**
103
+ * Manages service instance lifecycles
104
+ *
105
+ * Handles creation, caching, and cleanup of service instances
106
+ * based on their configured scope.
107
+ *
108
+ * @internal
109
+ */
110
+ export declare class ScopeManager {
111
+ /**
112
+ * Singleton instance cache
113
+ * Maps tokens to their singleton instances
114
+ */
115
+ private readonly singletonCache;
116
+ /**
117
+ * Whether request scope hooks have been set up
118
+ */
119
+ private requestScopeInitialized;
120
+ /**
121
+ * Attaches the scope manager to a Fastify server
122
+ *
123
+ * This sets up the request lifecycle hooks needed for request-scoped services.
124
+ * Must be called before resolving request-scoped services.
125
+ *
126
+ * @param server - Fastify server instance
127
+ */
128
+ attachToFastify(server: FastifyInstance): void;
129
+ /**
130
+ * Gets a singleton instance from cache
131
+ *
132
+ * @param token - The service token
133
+ * @returns The cached instance or undefined
134
+ */
135
+ getSingleton<T>(token: unknown): T | undefined;
136
+ /**
137
+ * Stores a singleton instance in cache
138
+ *
139
+ * @param token - The service token
140
+ * @param instance - The instance to cache
141
+ */
142
+ setSingleton<T>(token: unknown, instance: T): void;
143
+ /**
144
+ * Checks if a singleton instance exists
145
+ *
146
+ * @param token - The service token
147
+ * @returns true if a singleton instance is cached
148
+ */
149
+ hasSingleton(token: unknown): boolean;
150
+ /**
151
+ * Gets a request-scoped instance from the current request's cache
152
+ *
153
+ * @param token - The service token
154
+ * @param request - The current Fastify request
155
+ * @returns The cached instance or undefined
156
+ */
157
+ getRequestScoped<T>(token: unknown, request: FastifyRequest): T | undefined;
158
+ /**
159
+ * Stores a request-scoped instance in the current request's cache
160
+ *
161
+ * @param token - The service token
162
+ * @param instance - The instance to cache
163
+ * @param request - The current Fastify request
164
+ */
165
+ setRequestScoped<T>(token: unknown, instance: T, request: FastifyRequest): void;
166
+ /**
167
+ * Checks if a request-scoped instance exists
168
+ *
169
+ * @param token - The service token
170
+ * @param request - The current Fastify request
171
+ * @returns true if a request-scoped instance is cached
172
+ */
173
+ hasRequestScoped(token: unknown, request: FastifyRequest): boolean;
174
+ /**
175
+ * Validates that request scope is available and returns the request
176
+ *
177
+ * @param request - The current request (may be undefined outside request context)
178
+ * @returns The validated FastifyRequest
179
+ * @throws {VeloxError} If request scope is not available
180
+ */
181
+ ensureRequestScope(request: FastifyRequest | undefined): FastifyRequest;
182
+ /**
183
+ * Clears all singleton instances
184
+ *
185
+ * Useful for testing or application shutdown.
186
+ */
187
+ clearSingletons(): void;
188
+ /**
189
+ * Clears all cached instances and resets state
190
+ *
191
+ * @internal
192
+ */
193
+ reset(): void;
194
+ }
195
+ /**
196
+ * Validates a scope value
197
+ *
198
+ * @param scope - The scope to validate
199
+ * @returns true if the scope is valid
200
+ */
201
+ export declare function isValidScope(scope: unknown): scope is Scope;
202
+ /**
203
+ * Gets the default scope for a provider
204
+ *
205
+ * @returns The default scope (SINGLETON)
206
+ */
207
+ export declare function getDefaultScope(): Scope;
208
+ export {};
209
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/di/scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAQ/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,oBAAY,KAAK;IACf;;;;;;;;;;;;OAYG;IACH,SAAS,cAAc;IAEvB;;;;;;;;;;OAUG;IACH,SAAS,cAAc;IAEvB;;;;;;;;;;;;;;OAcG;IACH,OAAO,YAAY;CACpB;AAMD;;;GAGG;AACH,QAAA,MAAM,iBAAiB,eAAmC,CAAC;AAE3D;;GAEG;AACH,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB;;;WAGG;QACH,CAAC,iBAAiB,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;KAC7C;CACF;AAED;;;;;;;GAOG;AACH,qBAAa,YAAY;IACvB;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+B;IAE9D;;OAEG;IACH,OAAO,CAAC,uBAAuB,CAAS;IAExC;;;;;;;OAOG;IACH,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAsB9C;;;;;OAKG;IACH,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,SAAS;IAI9C;;;;;OAKG;IACH,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI;IAIlD;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAIrC;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,CAAC,GAAG,SAAS;IAQ3E;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI;IAY/E;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO;IAKlE;;;;;;OAMG;IACH,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,cAAc;IAqBvE;;;;OAIG;IACH,eAAe,IAAI,IAAI;IAIvB;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAId;AAMD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,KAAK,CAEvC"}