@di-framework/di-framework 0.0.0-prerelease-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Type Definitions and Utilities for the DI Framework
3
+ *
4
+ * Provides interfaces and utility types for building services
5
+ */
6
+ /**
7
+ * Represents a service class constructor
8
+ */
9
+ export type ServiceClass<T> = new (...args: any[]) => T;
10
+ /**
11
+ * Represents a factory function that creates a service
12
+ */
13
+ export type ServiceFactory<T> = () => T;
14
+ /**
15
+ * Service registration options
16
+ */
17
+ export interface InjectionOptions {
18
+ /**
19
+ * Whether this service should be a singleton (default: true)
20
+ * Singleton: same instance returned for each resolution
21
+ * Transient: new instance created for each resolution
22
+ */
23
+ singleton?: boolean;
24
+ }
25
+ /**
26
+ * Service with lifecycle methods
27
+ */
28
+ export interface ILifecycleService {
29
+ /**
30
+ * Called after the service is created
31
+ */
32
+ onInit?(): void;
33
+ /**
34
+ * Called before the service is destroyed
35
+ */
36
+ onDestroy?(): void;
37
+ /**
38
+ * Called to set environment variables
39
+ */
40
+ setEnv?(env: Record<string, any>): void;
41
+ /**
42
+ * Called to set execution context
43
+ */
44
+ setCtx?(context: any): void;
45
+ }
46
+ /**
47
+ * Error thrown when DI resolution fails
48
+ */
49
+ export declare class DIError extends Error {
50
+ constructor(message: string);
51
+ }
52
+ /**
53
+ * Error thrown when circular dependency is detected
54
+ */
55
+ export declare class CircularDependencyError extends DIError {
56
+ constructor(message: string);
57
+ }
58
+ /**
59
+ * Error thrown when service is not registered
60
+ */
61
+ export declare class ServiceNotFoundError extends DIError {
62
+ constructor(serviceName: string);
63
+ }
64
+ /**
65
+ * Type-safe service class identity
66
+ *
67
+ * Use this to ensure type safety when working with service classes
68
+ *
69
+ * @example
70
+ * type UserServiceId = ServiceId<UserService>;
71
+ * const serviceId: UserServiceId = UserService;
72
+ */
73
+ export type ServiceId<T> = ServiceClass<T>;
74
+ /**
75
+ * Utility type to extract the constructor parameters of a service
76
+ *
77
+ * @example
78
+ * type UserServiceDeps = ConstructorParameters<typeof UserService>;
79
+ */
80
+ export type ServiceDependencies<T> = T extends ServiceClass<infer U> ? ConstructorParameters<ServiceClass<U>> : never;
81
+ /**
82
+ * Utility type to make all properties of a service optional
83
+ *
84
+ * @example
85
+ * @Container()
86
+ * class MyService implements PartialService<MyService> {
87
+ * optionalDependency?: SomeService;
88
+ * }
89
+ */
90
+ export type PartialService<T> = Partial<T>;
91
+ /**
92
+ * Utility to create a service instance with mocked dependencies
93
+ *
94
+ * @example
95
+ * const mockUserService = new MockService<UserService>({
96
+ * database: mockDb,
97
+ * logger: mockLogger
98
+ * });
99
+ */
100
+ export type MockServiceOptions<T> = {
101
+ [K in keyof T]?: T[K];
102
+ };
103
+ /**
104
+ * Represents a resolvable service in the container
105
+ */
106
+ export type Resolvable = ServiceClass<any> | string;
107
+ /**
108
+ * Configuration for the DI container
109
+ */
110
+ export interface ContainerConfig {
111
+ /**
112
+ * Whether to throw on unregistered services (default: true)
113
+ */
114
+ throwOnUnregistered?: boolean;
115
+ /**
116
+ * Whether to detect circular dependencies (default: true)
117
+ */
118
+ detectCircularDependencies?: boolean;
119
+ /**
120
+ * Maximum recursion depth for dependency resolution (default: 100)
121
+ */
122
+ maxResolutionDepth?: number;
123
+ }
124
+ /**
125
+ * Service metadata stored in the container
126
+ */
127
+ export interface ServiceMetadata<T = any> {
128
+ type: ServiceClass<T> | ServiceFactory<T>;
129
+ singleton: boolean;
130
+ instance?: T;
131
+ dependencies?: string[];
132
+ createdAt?: Date;
133
+ }
134
+ /**
135
+ * Result of resolving a service
136
+ */
137
+ export interface ResolutionResult<T = any> {
138
+ service: T;
139
+ serviceClass: ServiceClass<T>;
140
+ isSingleton: boolean;
141
+ resolutionTimeMs: number;
142
+ }
143
+ /**
144
+ * Information about a registered service
145
+ */
146
+ export interface ServiceInfo {
147
+ name: string;
148
+ isSingleton: boolean;
149
+ dependencies: string[];
150
+ hasInstance: boolean;
151
+ }
152
+ /**
153
+ * Generic service base class with lifecycle support
154
+ *
155
+ * @example
156
+ * @Container()
157
+ * export class MyService extends BaseService {
158
+ * onInit() {
159
+ * console.log('Service initialized');
160
+ * }
161
+ * }
162
+ */
163
+ export declare abstract class BaseService implements ILifecycleService {
164
+ protected logger: ILogger;
165
+ onInit?(): void;
166
+ onDestroy?(): void;
167
+ setEnv?(env: Record<string, any>): void;
168
+ setCtx?(context: any): void;
169
+ protected log(message: string): void;
170
+ protected error(message: string): void;
171
+ }
172
+ /**
173
+ * Logger interface for services
174
+ */
175
+ export interface ILogger {
176
+ log(message: string): void;
177
+ error(message: string): void;
178
+ warn(message: string): void;
179
+ debug(message: string): void;
180
+ }
181
+ /**
182
+ * Console-based logger implementation
183
+ */
184
+ export declare class ConsoleLogger implements ILogger {
185
+ log(message: string): void;
186
+ error(message: string): void;
187
+ warn(message: string): void;
188
+ debug(message: string): void;
189
+ }
190
+ /**
191
+ * Utility functions for working with services
192
+ */
193
+ export declare namespace ServiceUtils {
194
+ /**
195
+ * Check if an object is a service class
196
+ */
197
+ function isServiceClass(obj: any): obj is ServiceClass<any>;
198
+ /**
199
+ * Check if an object is a factory function
200
+ */
201
+ function isFactory(obj: any): obj is ServiceFactory<any>;
202
+ /**
203
+ * Get the service name
204
+ */
205
+ function getServiceName(service: Resolvable): string;
206
+ /**
207
+ * Create a mock service for testing
208
+ */
209
+ function createMockService<T>(overrides?: Partial<T>): Partial<T>;
210
+ }
211
+ /**
212
+ * Decorator factory for creating custom decorators
213
+ *
214
+ * @example
215
+ * export function Cached(ttl: number = 60000) {
216
+ * return function (
217
+ * target: any,
218
+ * propertyKey: string,
219
+ * descriptor: PropertyDescriptor
220
+ * ) {
221
+ * const originalMethod = descriptor.value;
222
+ * const cache = new Map<string, { data: any; time: number }>();
223
+ *
224
+ * descriptor.value = function (...args: any[]) {
225
+ * const key = JSON.stringify(args);
226
+ * const cached = cache.get(key);
227
+ * const now = Date.now();
228
+ *
229
+ * if (cached && now - cached.time < ttl) {
230
+ * return cached.data;
231
+ * }
232
+ *
233
+ * const result = originalMethod.apply(this, args);
234
+ * cache.set(key, { data: result, time: now });
235
+ * return result;
236
+ * };
237
+ *
238
+ * return descriptor;
239
+ * };
240
+ * }
241
+ */
242
+ export declare function createDecorator<T extends (...args: any[]) => any>(decorator: T): T;
package/dist/types.js ADDED
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Type Definitions and Utilities for the DI Framework
3
+ *
4
+ * Provides interfaces and utility types for building services
5
+ */
6
+ /**
7
+ * Error thrown when DI resolution fails
8
+ */
9
+ export class DIError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = "DIError";
13
+ }
14
+ }
15
+ /**
16
+ * Error thrown when circular dependency is detected
17
+ */
18
+ export class CircularDependencyError extends DIError {
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = "CircularDependencyError";
22
+ }
23
+ }
24
+ /**
25
+ * Error thrown when service is not registered
26
+ */
27
+ export class ServiceNotFoundError extends DIError {
28
+ constructor(serviceName) {
29
+ super(`Service '${serviceName}' is not registered in the DI container`);
30
+ this.name = "ServiceNotFoundError";
31
+ }
32
+ }
33
+ /**
34
+ * Generic service base class with lifecycle support
35
+ *
36
+ * @example
37
+ * @Container()
38
+ * export class MyService extends BaseService {
39
+ * onInit() {
40
+ * console.log('Service initialized');
41
+ * }
42
+ * }
43
+ */
44
+ export class BaseService {
45
+ logger = new ConsoleLogger();
46
+ log(message) {
47
+ this.logger.log(message);
48
+ }
49
+ error(message) {
50
+ this.logger.error(message);
51
+ }
52
+ }
53
+ /**
54
+ * Console-based logger implementation
55
+ */
56
+ export class ConsoleLogger {
57
+ log(message) {
58
+ console.log(`[LOG] ${message}`);
59
+ }
60
+ error(message) {
61
+ console.error(`[ERROR] ${message}`);
62
+ }
63
+ warn(message) {
64
+ console.warn(`[WARN] ${message}`);
65
+ }
66
+ debug(message) {
67
+ console.debug(`[DEBUG] ${message}`);
68
+ }
69
+ }
70
+ /**
71
+ * Utility functions for working with services
72
+ */
73
+ export var ServiceUtils;
74
+ (function (ServiceUtils) {
75
+ /**
76
+ * Check if an object is a service class
77
+ */
78
+ function isServiceClass(obj) {
79
+ return typeof obj === "function" && obj.prototype;
80
+ }
81
+ ServiceUtils.isServiceClass = isServiceClass;
82
+ /**
83
+ * Check if an object is a factory function
84
+ */
85
+ function isFactory(obj) {
86
+ return typeof obj === "function" && !isServiceClass(obj);
87
+ }
88
+ ServiceUtils.isFactory = isFactory;
89
+ /**
90
+ * Get the service name
91
+ */
92
+ function getServiceName(service) {
93
+ if (typeof service === "string") {
94
+ return service;
95
+ }
96
+ return service.name;
97
+ }
98
+ ServiceUtils.getServiceName = getServiceName;
99
+ /**
100
+ * Create a mock service for testing
101
+ */
102
+ function createMockService(overrides = {}) {
103
+ return overrides;
104
+ }
105
+ ServiceUtils.createMockService = createMockService;
106
+ })(ServiceUtils || (ServiceUtils = {}));
107
+ /**
108
+ * Decorator factory for creating custom decorators
109
+ *
110
+ * @example
111
+ * export function Cached(ttl: number = 60000) {
112
+ * return function (
113
+ * target: any,
114
+ * propertyKey: string,
115
+ * descriptor: PropertyDescriptor
116
+ * ) {
117
+ * const originalMethod = descriptor.value;
118
+ * const cache = new Map<string, { data: any; time: number }>();
119
+ *
120
+ * descriptor.value = function (...args: any[]) {
121
+ * const key = JSON.stringify(args);
122
+ * const cached = cache.get(key);
123
+ * const now = Date.now();
124
+ *
125
+ * if (cached && now - cached.time < ttl) {
126
+ * return cached.data;
127
+ * }
128
+ *
129
+ * const result = originalMethod.apply(this, args);
130
+ * cache.set(key, { data: result, time: now });
131
+ * return result;
132
+ * };
133
+ *
134
+ * return descriptor;
135
+ * };
136
+ * }
137
+ */
138
+ export function createDecorator(decorator) {
139
+ return decorator;
140
+ }
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@di-framework/di-framework",
3
+ "version": "0.0.0-prerelease-0",
4
+ "description": "Lightweight, zero-dependency TypeScript Dependency Injection framework using decorators. Works seamlessly with SWC and TypeScript's native decorator support.",
5
+ "main": "./dist/container.js",
6
+ "types": "./dist/container.d.ts",
7
+ "module": "./dist/container.js",
8
+ "author": "github.com/geoffsee",
9
+ "type": "module",
10
+ "keywords": [
11
+ "dependency-injection",
12
+ "di",
13
+ "ioc",
14
+ "inversion-of-control",
15
+ "decorators",
16
+ "typescript",
17
+ "swc",
18
+ "framework"
19
+ ],
20
+ "exports": {
21
+ ".": {
22
+ "import": "./dist/container.js",
23
+ "types": "./dist/container.d.ts"
24
+ },
25
+ "./container": "./dist/container.js",
26
+ "./decorators": "./dist/decorators.js",
27
+ "./types": "./dist/types.js"
28
+ },
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/geoffsee/di-framework"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/geoffsee/di-framework/issues"
36
+ },
37
+ "homepage": "https://github.com/geoffsee/di-framework#readme",
38
+ "scripts": {
39
+ "test": "bun test"
40
+ },
41
+ "peerDependencies": {
42
+ "typescript": "^5"
43
+ },
44
+ "devDependencies": {},
45
+ "files": [
46
+ "dist",
47
+ "README.md",
48
+ "MIGRATION_GUIDE.md"
49
+ ]
50
+ }