@navios/di 0.2.1 ā 0.3.1
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 +299 -38
- package/docs/README.md +121 -48
- package/docs/api-reference.md +763 -0
- package/docs/container.md +274 -0
- package/docs/examples/basic-usage.mts +97 -0
- package/docs/examples/factory-pattern.mts +318 -0
- package/docs/examples/injection-tokens.mts +225 -0
- package/docs/examples/request-scope-example.mts +254 -0
- package/docs/examples/service-lifecycle.mts +359 -0
- package/docs/factory.md +584 -0
- package/docs/getting-started.md +308 -0
- package/docs/injectable.md +496 -0
- package/docs/injection-tokens.md +400 -0
- package/docs/lifecycle.md +539 -0
- package/docs/scopes.md +749 -0
- package/lib/_tsup-dts-rollup.d.mts +494 -145
- package/lib/_tsup-dts-rollup.d.ts +494 -145
- package/lib/index.d.mts +26 -12
- package/lib/index.d.ts +26 -12
- package/lib/index.js +1021 -470
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1011 -461
- package/lib/index.mjs.map +1 -1
- package/package.json +2 -2
- package/project.json +10 -2
- package/src/__tests__/container.spec.mts +1301 -0
- package/src/__tests__/factory.spec.mts +137 -0
- package/src/__tests__/injectable.spec.mts +32 -88
- package/src/__tests__/injection-token.spec.mts +333 -17
- package/src/__tests__/request-scope.spec.mts +427 -0
- package/src/__type-tests__/factory.spec-d.mts +65 -0
- package/src/__type-tests__/inject.spec-d.mts +27 -28
- package/src/__type-tests__/injectable.spec-d.mts +42 -206
- package/src/container.mts +167 -0
- package/src/decorators/factory.decorator.mts +79 -0
- package/src/decorators/index.mts +1 -0
- package/src/decorators/injectable.decorator.mts +6 -56
- package/src/enums/injectable-scope.enum.mts +5 -1
- package/src/event-emitter.mts +18 -20
- package/src/factory-context.mts +2 -10
- package/src/index.mts +3 -2
- package/src/injection-token.mts +19 -4
- package/src/injector.mts +8 -20
- package/src/interfaces/factory.interface.mts +3 -3
- package/src/interfaces/index.mts +2 -0
- package/src/interfaces/on-service-destroy.interface.mts +3 -0
- package/src/interfaces/on-service-init.interface.mts +3 -0
- package/src/registry.mts +7 -16
- package/src/request-context-holder.mts +174 -0
- package/src/service-instantiator.mts +158 -0
- package/src/service-locator-event-bus.mts +0 -28
- package/src/service-locator-instance-holder.mts +27 -16
- package/src/service-locator-manager.mts +84 -0
- package/src/service-locator.mts +548 -393
- package/src/utils/defer.mts +73 -0
- package/src/utils/get-injectors.mts +91 -78
- package/src/utils/index.mts +2 -0
- package/src/utils/types.mts +52 -0
- package/docs/concepts/injectable.md +0 -182
- package/docs/concepts/injection-token.md +0 -145
- package/src/proxy-service-locator.mts +0 -83
- package/src/resolve-service.mts +0 -41
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injection Tokens Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates:
|
|
5
|
+
* - Creating injection tokens with schemas
|
|
6
|
+
* - Using bound injection tokens
|
|
7
|
+
* - Using factory injection tokens
|
|
8
|
+
* - Token-based dependency resolution
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { Container, Injectable, InjectionToken } from '@navios/di'
|
|
12
|
+
|
|
13
|
+
import { z } from 'zod'
|
|
14
|
+
|
|
15
|
+
const container = new Container()
|
|
16
|
+
|
|
17
|
+
// 1. Define schemas for configuration
|
|
18
|
+
const databaseConfigSchema = z.object({
|
|
19
|
+
host: z.string(),
|
|
20
|
+
port: z.number(),
|
|
21
|
+
database: z.string(),
|
|
22
|
+
username: z.string(),
|
|
23
|
+
password: z.string(),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const emailConfigSchema = z.object({
|
|
27
|
+
provider: z.enum(['smtp', 'sendgrid', 'ses']),
|
|
28
|
+
apiKey: z.string(),
|
|
29
|
+
fromEmail: z.string().email(),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// 2. Create injection tokens
|
|
33
|
+
const DB_CONFIG_TOKEN = InjectionToken.create<
|
|
34
|
+
DatabaseConfigService,
|
|
35
|
+
typeof databaseConfigSchema
|
|
36
|
+
>('DB_CONFIG', databaseConfigSchema)
|
|
37
|
+
|
|
38
|
+
const EMAIL_CONFIG_TOKEN = InjectionToken.create<
|
|
39
|
+
EmailConfigService,
|
|
40
|
+
typeof emailConfigSchema
|
|
41
|
+
>('EMAIL_CONFIG', emailConfigSchema)
|
|
42
|
+
|
|
43
|
+
// 3. Create services that use injection tokens
|
|
44
|
+
@Injectable({ token: DB_CONFIG_TOKEN })
|
|
45
|
+
class DatabaseConfigService {
|
|
46
|
+
constructor(private config: z.infer<typeof databaseConfigSchema>) {}
|
|
47
|
+
|
|
48
|
+
getConnectionString() {
|
|
49
|
+
return `postgresql://${this.config.username}:${this.config.password}@${this.config.host}:${this.config.port}/${this.config.database}`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getHost() {
|
|
53
|
+
return this.config.host
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getPort() {
|
|
57
|
+
return this.config.port
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Injectable({ token: EMAIL_CONFIG_TOKEN })
|
|
62
|
+
class EmailConfigService {
|
|
63
|
+
constructor(private config: z.infer<typeof emailConfigSchema>) {}
|
|
64
|
+
|
|
65
|
+
getProvider() {
|
|
66
|
+
return this.config.provider
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getApiKey() {
|
|
70
|
+
return this.config.apiKey
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getFromEmail() {
|
|
74
|
+
return this.config.fromEmail
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 4. Create bound tokens for different environments
|
|
79
|
+
const PRODUCTION_DB_CONFIG = InjectionToken.bound(DB_CONFIG_TOKEN, {
|
|
80
|
+
host: 'prod-db.example.com',
|
|
81
|
+
port: 5432,
|
|
82
|
+
database: 'production',
|
|
83
|
+
username: 'prod_user',
|
|
84
|
+
password: 'prod_password',
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
const DEVELOPMENT_DB_CONFIG = InjectionToken.bound(DB_CONFIG_TOKEN, {
|
|
88
|
+
host: 'localhost',
|
|
89
|
+
port: 5432,
|
|
90
|
+
database: 'development',
|
|
91
|
+
username: 'dev_user',
|
|
92
|
+
password: 'dev_password',
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const PRODUCTION_EMAIL_CONFIG = InjectionToken.bound(EMAIL_CONFIG_TOKEN, {
|
|
96
|
+
provider: 'sendgrid',
|
|
97
|
+
apiKey: 'sg.prod_key',
|
|
98
|
+
fromEmail: 'noreply@example.com',
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const DEVELOPMENT_EMAIL_CONFIG = InjectionToken.bound(EMAIL_CONFIG_TOKEN, {
|
|
102
|
+
provider: 'smtp',
|
|
103
|
+
apiKey: 'smtp_dev_key',
|
|
104
|
+
fromEmail: 'dev@example.com',
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
// 5. Create factory tokens for dynamic configuration
|
|
108
|
+
const DYNAMIC_DB_CONFIG = InjectionToken.factory(DB_CONFIG_TOKEN, async () => {
|
|
109
|
+
const env = process.env.NODE_ENV || 'development'
|
|
110
|
+
|
|
111
|
+
if (env === 'production') {
|
|
112
|
+
return {
|
|
113
|
+
host: 'prod-db.example.com',
|
|
114
|
+
port: 5432,
|
|
115
|
+
database: 'production',
|
|
116
|
+
username: 'prod_user',
|
|
117
|
+
password: 'prod_password',
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
return {
|
|
121
|
+
host: 'localhost',
|
|
122
|
+
port: 5432,
|
|
123
|
+
database: 'development',
|
|
124
|
+
username: 'dev_user',
|
|
125
|
+
password: 'dev_password',
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
const DYNAMIC_EMAIL_CONFIG = InjectionToken.factory(
|
|
131
|
+
EMAIL_CONFIG_TOKEN,
|
|
132
|
+
async () => {
|
|
133
|
+
const env = process.env.NODE_ENV || 'development'
|
|
134
|
+
|
|
135
|
+
if (env === 'production') {
|
|
136
|
+
return {
|
|
137
|
+
provider: 'sendgrid' as const,
|
|
138
|
+
apiKey: 'sg.prod_key',
|
|
139
|
+
fromEmail: 'noreply@example.com',
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
return {
|
|
143
|
+
provider: 'smtp' as const,
|
|
144
|
+
apiKey: 'smtp_dev_key',
|
|
145
|
+
fromEmail: 'dev@example.com',
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
// 6. Usage examples
|
|
152
|
+
async function demonstrateBoundTokens() {
|
|
153
|
+
console.log('=== Bound Tokens Example ===\n')
|
|
154
|
+
|
|
155
|
+
// Use production configuration
|
|
156
|
+
const prodDbConfig = await container.get(PRODUCTION_DB_CONFIG)
|
|
157
|
+
console.log('Production DB:', prodDbConfig.getConnectionString())
|
|
158
|
+
|
|
159
|
+
const prodEmailConfig = await container.get(PRODUCTION_EMAIL_CONFIG)
|
|
160
|
+
console.log('Production Email:', prodEmailConfig.getProvider())
|
|
161
|
+
|
|
162
|
+
// Use development configuration
|
|
163
|
+
const devDbConfig = await container.get(DEVELOPMENT_DB_CONFIG)
|
|
164
|
+
console.log('Development DB:', devDbConfig.getConnectionString())
|
|
165
|
+
|
|
166
|
+
const devEmailConfig = await container.get(DEVELOPMENT_EMAIL_CONFIG)
|
|
167
|
+
console.log('Development Email:', devEmailConfig.getProvider())
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function demonstrateFactoryTokens() {
|
|
171
|
+
console.log('\n=== Factory Tokens Example ===\n')
|
|
172
|
+
|
|
173
|
+
// Use dynamic configuration based on environment
|
|
174
|
+
const dbConfig = await container.get(DYNAMIC_DB_CONFIG)
|
|
175
|
+
console.log('Dynamic DB:', dbConfig.getConnectionString())
|
|
176
|
+
|
|
177
|
+
const emailConfig = await container.get(DYNAMIC_EMAIL_CONFIG)
|
|
178
|
+
console.log('Dynamic Email:', emailConfig.getProvider())
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function demonstrateDirectTokens() {
|
|
182
|
+
console.log('\n=== Direct Tokens Example ===\n')
|
|
183
|
+
|
|
184
|
+
// Use tokens directly with configuration
|
|
185
|
+
const dbConfig = await container.get(DB_CONFIG_TOKEN, {
|
|
186
|
+
host: 'custom-db.example.com',
|
|
187
|
+
port: 5432,
|
|
188
|
+
database: 'custom',
|
|
189
|
+
username: 'custom_user',
|
|
190
|
+
password: 'custom_password',
|
|
191
|
+
})
|
|
192
|
+
console.log('Custom DB:', dbConfig.getConnectionString())
|
|
193
|
+
|
|
194
|
+
const emailConfig = await container.get(EMAIL_CONFIG_TOKEN, {
|
|
195
|
+
provider: 'ses',
|
|
196
|
+
apiKey: 'aws_ses_key',
|
|
197
|
+
fromEmail: 'custom@example.com',
|
|
198
|
+
})
|
|
199
|
+
console.log('Custom Email:', emailConfig.getProvider())
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Main function
|
|
203
|
+
async function main() {
|
|
204
|
+
await demonstrateBoundTokens()
|
|
205
|
+
await demonstrateFactoryTokens()
|
|
206
|
+
await demonstrateDirectTokens()
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Run the example
|
|
210
|
+
if (require.main === module) {
|
|
211
|
+
main().catch(console.error)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export {
|
|
215
|
+
DB_CONFIG_TOKEN,
|
|
216
|
+
EMAIL_CONFIG_TOKEN,
|
|
217
|
+
PRODUCTION_DB_CONFIG,
|
|
218
|
+
DEVELOPMENT_DB_CONFIG,
|
|
219
|
+
PRODUCTION_EMAIL_CONFIG,
|
|
220
|
+
DEVELOPMENT_EMAIL_CONFIG,
|
|
221
|
+
DYNAMIC_DB_CONFIG,
|
|
222
|
+
DYNAMIC_EMAIL_CONFIG,
|
|
223
|
+
DatabaseConfigService,
|
|
224
|
+
EmailConfigService,
|
|
225
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example demonstrating the Request scope functionality in Navios DI.
|
|
3
|
+
*
|
|
4
|
+
* This example shows how to use request-scoped services for web applications
|
|
5
|
+
* where you need services that are shared within a request but isolated between requests.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Container } from '../../src/container.mjs'
|
|
9
|
+
import { Injectable } from '../../src/decorators/injectable.decorator.mjs'
|
|
10
|
+
import { InjectableScope } from '../../src/enums/index.mjs'
|
|
11
|
+
import { inject } from '../../src/injector.mjs'
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// EXAMPLE SERVICES
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Singleton service - shared across the entire application
|
|
19
|
+
*/
|
|
20
|
+
@Injectable({ scope: InjectableScope.Singleton })
|
|
21
|
+
class DatabaseService {
|
|
22
|
+
private connectionCount = 0
|
|
23
|
+
|
|
24
|
+
async getConnection() {
|
|
25
|
+
this.connectionCount++
|
|
26
|
+
console.log(`[DatabaseService] Created connection #${this.connectionCount}`)
|
|
27
|
+
return {
|
|
28
|
+
id: this.connectionCount,
|
|
29
|
+
connected: true,
|
|
30
|
+
createdAt: new Date(),
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getConnectionCount() {
|
|
35
|
+
return this.connectionCount
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Request-scoped service - shared within a request, isolated between requests
|
|
41
|
+
*/
|
|
42
|
+
@Injectable({ scope: InjectableScope.Request })
|
|
43
|
+
class UserContext {
|
|
44
|
+
public readonly requestId: string
|
|
45
|
+
public readonly userId: string
|
|
46
|
+
public readonly sessionId: string
|
|
47
|
+
public readonly startTime: number
|
|
48
|
+
private readonly database = inject(DatabaseService)
|
|
49
|
+
|
|
50
|
+
constructor({ userId, sessionId }: { userId: string; sessionId: string }) {
|
|
51
|
+
this.requestId = Math.random().toString(36).substring(2, 15)
|
|
52
|
+
this.userId = userId
|
|
53
|
+
this.sessionId = sessionId
|
|
54
|
+
this.startTime = Date.now()
|
|
55
|
+
|
|
56
|
+
console.log(
|
|
57
|
+
`[UserContext] Created for user ${userId} in request ${this.requestId}`,
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getDatabaseConnection() {
|
|
62
|
+
const db = await this.database
|
|
63
|
+
return await db.getConnection()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getRequestDuration() {
|
|
67
|
+
return Date.now() - this.startTime
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async onServiceDestroy() {
|
|
71
|
+
console.log(
|
|
72
|
+
`[UserContext] Destroying context for user ${this.userId} (request ${this.requestId})`,
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Request-scoped service that depends on UserContext
|
|
79
|
+
*/
|
|
80
|
+
@Injectable({ scope: InjectableScope.Request })
|
|
81
|
+
class OrderService {
|
|
82
|
+
private readonly userContext = inject(UserContext)
|
|
83
|
+
private orders: string[] = []
|
|
84
|
+
|
|
85
|
+
async createOrder(productName: string) {
|
|
86
|
+
const userCtx = await this.userContext
|
|
87
|
+
const orderId = `order_${Math.random().toString(36).substring(2, 15)}`
|
|
88
|
+
|
|
89
|
+
this.orders.push(orderId)
|
|
90
|
+
console.log(
|
|
91
|
+
`[OrderService] Created order ${orderId} for user ${userCtx.userId}`,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
orderId,
|
|
96
|
+
userId: userCtx.userId,
|
|
97
|
+
productName,
|
|
98
|
+
requestId: userCtx.requestId,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getOrders() {
|
|
103
|
+
return [...this.orders]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Transient service - new instance for each injection
|
|
109
|
+
*/
|
|
110
|
+
@Injectable({ scope: InjectableScope.Transient })
|
|
111
|
+
class LoggerService {
|
|
112
|
+
private readonly logId = Math.random().toString(36).substring(2, 15)
|
|
113
|
+
|
|
114
|
+
log(message: string) {
|
|
115
|
+
console.log(`[LoggerService:${this.logId}] ${message}`)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Service that uses all scopes
|
|
121
|
+
*/
|
|
122
|
+
@Injectable({ scope: InjectableScope.Singleton })
|
|
123
|
+
class RequestHandler {
|
|
124
|
+
private readonly logger = inject(LoggerService)
|
|
125
|
+
private readonly userContext = inject(UserContext)
|
|
126
|
+
private readonly orderService = inject(OrderService)
|
|
127
|
+
|
|
128
|
+
async handleRequest(userId: string, sessionId: string) {
|
|
129
|
+
const logger = await this.logger
|
|
130
|
+
logger.log(`Handling request for user ${userId}`)
|
|
131
|
+
|
|
132
|
+
const userCtx = await this.userContext
|
|
133
|
+
logger.log(`User context request ID: ${userCtx.requestId}`)
|
|
134
|
+
|
|
135
|
+
const orderSvc = await this.orderService
|
|
136
|
+
const order = await orderSvc.createOrder('Sample Product')
|
|
137
|
+
|
|
138
|
+
logger.log(`Created order: ${order.orderId}`)
|
|
139
|
+
logger.log(`Request duration: ${userCtx.getRequestDuration()}ms`)
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
userId: userCtx.userId,
|
|
143
|
+
requestId: userCtx.requestId,
|
|
144
|
+
orderId: order.orderId,
|
|
145
|
+
duration: userCtx.getRequestDuration(),
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ============================================================================
|
|
151
|
+
// EXAMPLE USAGE
|
|
152
|
+
// ============================================================================
|
|
153
|
+
|
|
154
|
+
async function demonstrateRequestScope() {
|
|
155
|
+
console.log('š Request Scope Example\n')
|
|
156
|
+
|
|
157
|
+
const container = new Container()
|
|
158
|
+
|
|
159
|
+
// Simulate multiple requests
|
|
160
|
+
const requests = [
|
|
161
|
+
{ userId: 'user1', sessionId: 'session1' },
|
|
162
|
+
{ userId: 'user2', sessionId: 'session2' },
|
|
163
|
+
{ userId: 'user1', sessionId: 'session3' }, // Same user, different session
|
|
164
|
+
]
|
|
165
|
+
|
|
166
|
+
for (let i = 0; i < requests.length; i++) {
|
|
167
|
+
const { userId, sessionId } = requests[i]
|
|
168
|
+
|
|
169
|
+
console.log(
|
|
170
|
+
`\nš Processing Request ${i + 1}: User ${userId}, Session ${sessionId}`,
|
|
171
|
+
)
|
|
172
|
+
console.log('ā'.repeat(50))
|
|
173
|
+
|
|
174
|
+
// Begin request context
|
|
175
|
+
const requestId = `req_${i + 1}`
|
|
176
|
+
container.beginRequest(requestId, { userId, sessionId })
|
|
177
|
+
|
|
178
|
+
// Handle the request
|
|
179
|
+
const handler = await container.get(RequestHandler)
|
|
180
|
+
const result = await handler.handleRequest(userId, sessionId)
|
|
181
|
+
|
|
182
|
+
console.log(`ā
Request completed:`, result)
|
|
183
|
+
|
|
184
|
+
// End request context (cleans up request-scoped instances)
|
|
185
|
+
await container.endRequest(requestId)
|
|
186
|
+
|
|
187
|
+
console.log('ā'.repeat(50))
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Show that singleton services persist across requests
|
|
191
|
+
const dbService = await container.get(DatabaseService)
|
|
192
|
+
console.log(
|
|
193
|
+
`\nš Total database connections created: ${dbService.getConnectionCount()}`,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
console.log('\n⨠Example completed!')
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// PERFORMANCE COMPARISON
|
|
201
|
+
// ============================================================================
|
|
202
|
+
|
|
203
|
+
async function demonstratePerformanceBenefits() {
|
|
204
|
+
console.log('\nā” Performance Comparison\n')
|
|
205
|
+
|
|
206
|
+
const container = new Container()
|
|
207
|
+
|
|
208
|
+
// Without pre-preparation
|
|
209
|
+
console.log('š Without pre-preparation:')
|
|
210
|
+
const start1 = Date.now()
|
|
211
|
+
|
|
212
|
+
container.beginRequest('perf-test-1')
|
|
213
|
+
const handler1 = await container.get(RequestHandler)
|
|
214
|
+
await handler1.handleRequest('user1', 'session1')
|
|
215
|
+
await container.endRequest('perf-test-1')
|
|
216
|
+
|
|
217
|
+
const time1 = Date.now() - start1
|
|
218
|
+
console.log(` Time: ${time1}ms`)
|
|
219
|
+
|
|
220
|
+
// With pre-preparation
|
|
221
|
+
console.log('š With pre-preparation:')
|
|
222
|
+
const start2 = Date.now()
|
|
223
|
+
|
|
224
|
+
container.beginRequest('perf-test-2')
|
|
225
|
+
const handler2 = await container.get(RequestHandler)
|
|
226
|
+
await handler2.handleRequest('user1', 'session1')
|
|
227
|
+
await container.endRequest('perf-test-2')
|
|
228
|
+
|
|
229
|
+
const time2 = Date.now() - start2
|
|
230
|
+
console.log(` Time: ${time2}ms`)
|
|
231
|
+
console.log(
|
|
232
|
+
` Improvement: ${(((time1 - time2) / time1) * 100).toFixed(1)}% faster`,
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ============================================================================
|
|
237
|
+
// MAIN EXECUTION
|
|
238
|
+
// ============================================================================
|
|
239
|
+
|
|
240
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
241
|
+
demonstrateRequestScope()
|
|
242
|
+
.then(() => demonstratePerformanceBenefits())
|
|
243
|
+
.catch(console.error)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export {
|
|
247
|
+
DatabaseService,
|
|
248
|
+
UserContext,
|
|
249
|
+
OrderService,
|
|
250
|
+
LoggerService,
|
|
251
|
+
RequestHandler,
|
|
252
|
+
demonstrateRequestScope,
|
|
253
|
+
demonstratePerformanceBenefits,
|
|
254
|
+
}
|