-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasic-usage.ts
More file actions
146 lines (117 loc) · 3.9 KB
/
Copy pathbasic-usage.ts
File metadata and controls
146 lines (117 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import 'reflect-metadata';
import { Container, createToken, singleton, transient, get, setContainer } from '../index.js';
// ============================================
// 1. Define interfaces and create tokens
// ============================================
interface Logger {
log(message: string): void;
error(message: string): void;
}
interface Database {
connect(): void;
query(sql: string): any[];
}
interface UserService {
getUser(id: number): void;
createUser(name: string): void;
}
// Create type-safe tokens
const Logger = createToken<Logger>('Logger');
const Database = createToken<Database>('Database');
const UserService = createToken<UserService>('UserService');
// ============================================
// 2. Implement classes with decorators
// ============================================
@singleton()
class ConsoleLogger implements Logger {
constructor() {
console.log('[ConsoleLogger] Instance created');
}
log(message: string): void {
console.log(`[LOG] ${message}`);
}
error(message: string): void {
console.error(`[ERROR] ${message}`);
}
}
@singleton()
class PostgresDatabase implements Database {
// Property injection using get()
private logger = get(Logger);
constructor() {
this.logger.log('PostgresDatabase instance created');
}
connect(): void {
this.logger.log('Connecting to PostgreSQL...');
}
query(sql: string): any[] {
this.logger.log(`Executing query: ${sql}`);
return [];
}
}
@transient()
class UserServiceImpl implements UserService {
// Multiple dependencies using get()
private logger = get(Logger);
private database = get(Database);
constructor() {
this.logger.log('UserService instance created');
}
getUser(id: number): void {
this.logger.log(`Getting user with ID: ${id}`);
this.database.query(`SELECT * FROM users WHERE id = ${id}`);
}
createUser(name: string): void {
this.logger.log(`Creating user: ${name}`);
this.database.query(`INSERT INTO users (name) VALUES ('${name}')`);
}
}
// ============================================
// 3. Setup and use the container
// ============================================
function main() {
console.log('=== Dependency Injection Framework Demo (Koin-Style) ===\n');
// Create container
const container = new Container();
// Set as global container for get() calls
setContainer(container);
// Register dependencies
console.log('--- Registering dependencies ---');
container.register(Logger, ConsoleLogger);
container.register(Database, PostgresDatabase);
container.register(UserService, UserServiceImpl);
console.log('All dependencies registered!\n');
// Resolve and use UserService
console.log('--- Resolving UserService (1st time) ---');
const userService1 = container.resolve(UserService);
userService1.getUser(1);
userService1.createUser('Alice');
console.log('');
// Resolve UserService again (Transient - new instance)
console.log('--- Resolving UserService (2nd time) ---');
const userService2 = container.resolve(UserService);
userService2.getUser(2);
console.log('');
// Check if instances are different (Transient)
console.log('--- Lifecycle Demo ---');
console.log(`UserService1 === UserService2? ${userService1 === userService2}`);
console.log('(false because UserService is @transient)\n');
// Logger is singleton - same instance
const logger1 = container.resolve(Logger);
const logger2 = container.resolve(Logger);
console.log(`Logger1 === Logger2? ${logger1 === logger2}`);
console.log('(true because Logger is @singleton)\n');
// Test error handling
console.log('--- Error Handling Demo ---');
try {
const unknownToken = createToken<any>('UnknownService');
container.resolve(unknownToken);
} catch (error) {
if (error instanceof Error) {
console.log(`Caught error: ${error.message}`);
}
}
console.log('\n=== Demo Complete ===');
}
// Run the example
main();