@stacksjs/bun-router 0.0.5 → 0.0.7
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/dist/auth.d.ts +134 -0
- package/dist/cache/lru-cache.d.ts +139 -0
- package/dist/cache/middleware-memoization.d.ts +151 -0
- package/dist/cache/route-cache-warmer.d.ts +161 -0
- package/dist/cache/sqlite-cache.d.ts +209 -0
- package/dist/cache/streaming-cache.d.ts +132 -0
- package/dist/cli/colors.d.ts +15 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/middleware.d.ts +31 -0
- package/dist/cli/openapi.d.ts +17 -0
- package/dist/cli/router.d.ts +15 -0
- package/dist/cli/routes.d.ts +29 -0
- package/dist/cli/utils.d.ts +74 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/container/container.d.ts +273 -0
- package/dist/container/contextual-binding.d.ts +240 -0
- package/dist/container/decorators.d.ts +141 -0
- package/dist/container/service-provider.d.ts +285 -0
- package/dist/development/hot-reload.d.ts +187 -0
- package/dist/development/index.d.ts +167 -0
- package/dist/development/performance-profiler.d.ts +217 -0
- package/dist/development/route-debugger.d.ts +154 -0
- package/dist/development/route-inspector.d.ts +211 -0
- package/dist/development/typescript-utilities.d.ts +209 -0
- package/dist/docs.d.ts +11 -0
- package/dist/errors/circuit-breaker.d.ts +195 -0
- package/dist/errors/error-handler.d.ts +88 -0
- package/dist/errors/error-reporting.d.ts +144 -0
- package/dist/errors/exceptions.d.ts +184 -0
- package/dist/errors/graceful-degradation.d.ts +154 -0
- package/dist/errors/index.d.ts +9 -0
- package/dist/errors/router-errors.d.ts +110 -0
- package/dist/file-serving/static-files.d.ts +143 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +375 -227
- package/dist/middleware/auth.d.ts +63 -0
- package/dist/middleware/content_security_policy.d.ts +53 -0
- package/dist/middleware/cors.d.ts +5 -0
- package/dist/middleware/csrf.d.ts +7 -0
- package/dist/middleware/ddos_protection.d.ts +39 -0
- package/dist/middleware/file_security.d.ts +26 -0
- package/dist/middleware/file_upload.d.ts +38 -0
- package/dist/middleware/helmet.d.ts +54 -0
- package/dist/middleware/index.d.ts +44 -0
- package/dist/middleware/input_validation.d.ts +45 -0
- package/dist/middleware/json_body.d.ts +4 -0
- package/dist/middleware/performance_alerting.d.ts +87 -0
- package/dist/middleware/performance_dashboard.d.ts +87 -0
- package/dist/middleware/performance_monitor.d.ts +209 -0
- package/dist/middleware/pipeline.d.ts +131 -0
- package/dist/middleware/rate_limit.d.ts +36 -0
- package/dist/middleware/request_id.d.ts +4 -0
- package/dist/middleware/request_signing.d.ts +153 -0
- package/dist/middleware/request_tracer.d.ts +72 -0
- package/dist/middleware/response_cache.d.ts +97 -0
- package/dist/middleware/security.d.ts +69 -0
- package/dist/middleware/security_suite.d.ts +46 -0
- package/dist/middleware/session.d.ts +23 -0
- package/dist/model-binding/index.d.ts +2 -0
- package/dist/model-binding/model-middleware.d.ts +118 -0
- package/dist/model-binding/model-registry.d.ts +164 -0
- package/dist/model-binding.d.ts +185 -0
- package/dist/model-resolver-factory.d.ts +31 -0
- package/dist/observability/correlation.d.ts +187 -0
- package/dist/observability/health-checks.d.ts +186 -0
- package/dist/observability/index.d.ts +60 -0
- package/dist/observability/integration.d.ts +147 -0
- package/dist/observability/metrics.d.ts +184 -0
- package/dist/observability/tracing.d.ts +187 -0
- package/dist/optimization/bun-utilities.d.ts +224 -0
- package/dist/query-builder-integration.d.ts +36 -0
- package/dist/request/context.d.ts +34 -0
- package/dist/request/enhanced-request.d.ts +213 -0
- package/dist/request/macros.d.ts +300 -0
- package/dist/response/macros.d.ts +245 -0
- package/dist/response/response-factory.d.ts +133 -0
- package/dist/router/api-routes.d.ts +5 -0
- package/dist/router/file-based-routing.d.ts +118 -0
- package/dist/router/file-streaming.d.ts +5 -0
- package/dist/router/fluent-router.d.ts +315 -0
- package/dist/router/fluent-routing.d.ts +271 -0
- package/dist/router/group-organization.d.ts +5 -0
- package/dist/router/handler-resolver.d.ts +24 -0
- package/dist/router/http-methods.d.ts +10 -0
- package/dist/router/index.d.ts +113 -0
- package/dist/router/middleware-groups.d.ts +94 -0
- package/dist/router/middleware-integration.d.ts +112 -0
- package/dist/router/middleware.d.ts +5 -0
- package/dist/router/model-binding.d.ts +5 -0
- package/dist/router/optimized-route-matching.d.ts +6 -0
- package/dist/router/route-building.d.ts +5 -0
- package/dist/router/route-compiler.d.ts +153 -0
- package/dist/router/route-matching.d.ts +5 -0
- package/dist/router/route-trie.d.ts +114 -0
- package/dist/router/router.d.ts +276 -0
- package/dist/router/server.d.ts +5 -0
- package/dist/router/validation-integration.d.ts +170 -0
- package/dist/router/view-rendering.d.ts +5 -0
- package/dist/router/websocket.d.ts +5 -0
- package/dist/routing/route-caching.d.ts +129 -0
- package/dist/routing/route-throttling.d.ts +150 -0
- package/dist/routing/subdomain-routing.d.ts +206 -0
- package/dist/session/database-store.d.ts +51 -0
- package/dist/session/file-store.d.ts +22 -0
- package/dist/session/index.d.ts +106 -0
- package/dist/session/memory-store.d.ts +21 -0
- package/dist/session/redis-store.d.ts +31 -0
- package/dist/streaming/index.d.ts +3 -0
- package/dist/streaming/sse-handler.d.ts +138 -0
- package/dist/streaming/stream-handler.d.ts +114 -0
- package/dist/testing/auth-testing.d.ts +156 -0
- package/dist/testing/file-upload-testing.d.ts +190 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/middleware-testing.d.ts +138 -0
- package/dist/testing/model-binding-testing.d.ts +186 -0
- package/dist/testing/performance-testing.d.ts +235 -0
- package/dist/testing/test-client.d.ts +117 -0
- package/dist/testing/test-request.d.ts +85 -0
- package/dist/testing/test-response.d.ts +90 -0
- package/dist/testing/types.d.ts +207 -0
- package/dist/testing/websocket-testing.d.ts +227 -0
- package/dist/types/controller-types.d.ts +208 -0
- package/dist/types/core.d.ts +543 -0
- package/dist/types/middleware-types.d.ts +227 -0
- package/dist/types/request-response-augmentation.d.ts +261 -0
- package/dist/types/route-inference.d.ts +168 -0
- package/dist/types.d.ts +1776 -0
- package/dist/url.d.ts +56 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/query-preservation.d.ts +48 -0
- package/dist/utils.d.ts +69 -0
- package/dist/validation/validator.d.ts +140 -0
- package/dist/websocket/clustering.d.ts +185 -0
- package/package.json +3 -2
- package/src/auth.ts +469 -0
- package/src/cache/lru-cache.ts +457 -0
- package/src/cache/middleware-memoization.ts +531 -0
- package/src/cache/route-cache-warmer.ts +486 -0
- package/src/cache/sqlite-cache.ts +783 -0
- package/src/cache/streaming-cache.ts +572 -0
- package/src/cli/colors.ts +29 -0
- package/src/cli/index.ts +287 -0
- package/src/cli/middleware.ts +291 -0
- package/src/cli/openapi.ts +407 -0
- package/src/cli/router.ts +188 -0
- package/src/cli/routes.ts +265 -0
- package/src/cli/utils.ts +531 -0
- package/src/cli.ts +5 -0
- package/src/config.ts +322 -0
- package/src/container/container.ts +740 -0
- package/src/container/contextual-binding.ts +603 -0
- package/src/container/decorators.ts +359 -0
- package/src/container/service-provider.ts +596 -0
- package/src/development/hot-reload.ts +673 -0
- package/src/development/index.ts +499 -0
- package/src/development/performance-profiler.ts +717 -0
- package/src/development/route-debugger.ts +527 -0
- package/src/development/route-inspector.ts +749 -0
- package/src/development/typescript-utilities.ts +678 -0
- package/src/docs.ts +397 -0
- package/src/errors/circuit-breaker.ts +732 -0
- package/src/errors/error-handler.ts +569 -0
- package/src/errors/error-reporting.ts +672 -0
- package/src/errors/exceptions.ts +536 -0
- package/src/errors/graceful-degradation.ts +621 -0
- package/src/errors/index.ts +21 -0
- package/src/errors/router-errors.ts +632 -0
- package/src/file-serving/static-files.ts +581 -0
- package/src/index.ts +14 -0
- package/src/middleware/auth.ts +219 -0
- package/src/middleware/content_security_policy.ts +215 -0
- package/src/middleware/cors.ts +74 -0
- package/src/middleware/csrf.ts +108 -0
- package/src/middleware/ddos_protection.ts +255 -0
- package/src/middleware/file_security.ts +191 -0
- package/src/middleware/file_upload.ts +264 -0
- package/src/middleware/helmet.ts +268 -0
- package/src/middleware/index.ts +117 -0
- package/src/middleware/input_validation.ts +449 -0
- package/src/middleware/json_body.ts +37 -0
- package/src/middleware/performance_alerting.ts +538 -0
- package/src/middleware/performance_dashboard.ts +661 -0
- package/src/middleware/performance_monitor.ts +943 -0
- package/src/middleware/pipeline.ts +489 -0
- package/src/middleware/rate_limit.ts +245 -0
- package/src/middleware/request_id.ts +36 -0
- package/src/middleware/request_signing.ts +636 -0
- package/src/middleware/request_tracer.ts +636 -0
- package/src/middleware/response_cache.ts +743 -0
- package/src/middleware/security.ts +482 -0
- package/src/middleware/security_suite.ts +257 -0
- package/src/middleware/session.ts +91 -0
- package/src/model-binding/index.ts +18 -0
- package/src/model-binding/model-middleware.ts +425 -0
- package/src/model-binding/model-registry.ts +550 -0
- package/src/model-binding.ts +370 -0
- package/src/model-resolver-factory.ts +106 -0
- package/src/observability/correlation.ts +691 -0
- package/src/observability/health-checks.ts +729 -0
- package/src/observability/index.ts +184 -0
- package/src/observability/integration.ts +548 -0
- package/src/observability/metrics.ts +753 -0
- package/src/observability/tracing.ts +638 -0
- package/src/optimization/bun-utilities.ts +778 -0
- package/src/query-builder-integration.ts +137 -0
- package/src/request/context.ts +62 -0
- package/src/request/enhanced-request.ts +857 -0
- package/src/request/macros.ts +688 -0
- package/src/response/macros.ts +612 -0
- package/src/response/response-factory.ts +588 -0
- package/src/router/api-routes.ts +243 -0
- package/src/router/file-based-routing.ts +670 -0
- package/src/router/file-streaming.ts +372 -0
- package/src/router/fluent-router.ts +927 -0
- package/src/router/fluent-routing.ts +797 -0
- package/src/router/group-organization.ts +213 -0
- package/src/router/handler-resolver.ts +291 -0
- package/src/router/http-methods.ts +377 -0
- package/src/router/index.ts +185 -0
- package/src/router/middleware-groups.ts +222 -0
- package/src/router/middleware-integration.ts +399 -0
- package/src/router/middleware.ts +231 -0
- package/src/router/model-binding.ts +215 -0
- package/src/router/optimized-route-matching.ts +253 -0
- package/src/router/route-building.ts +212 -0
- package/src/router/route-compiler.ts +702 -0
- package/src/router/route-matching.ts +349 -0
- package/src/router/route-trie.ts +464 -0
- package/src/router/router.ts +1524 -0
- package/src/router/server.ts +429 -0
- package/src/router/validation-integration.ts +443 -0
- package/src/router/view-rendering.ts +233 -0
- package/src/router/websocket.ts +100 -0
- package/src/routing/route-caching.ts +402 -0
- package/src/routing/route-throttling.ts +469 -0
- package/src/routing/subdomain-routing.ts +492 -0
- package/src/session/database-store.ts +109 -0
- package/src/session/file-store.ts +148 -0
- package/src/session/index.ts +244 -0
- package/src/session/memory-store.ts +88 -0
- package/src/session/redis-store.ts +93 -0
- package/src/streaming/index.ts +17 -0
- package/src/streaming/sse-handler.ts +482 -0
- package/src/streaming/stream-handler.ts +552 -0
- package/src/testing/auth-testing.ts +446 -0
- package/src/testing/file-upload-testing.ts +543 -0
- package/src/testing/index.ts +10 -0
- package/src/testing/middleware-testing.ts +322 -0
- package/src/testing/model-binding-testing.ts +645 -0
- package/src/testing/performance-testing.ts +738 -0
- package/src/testing/test-client.ts +310 -0
- package/src/testing/test-request.ts +315 -0
- package/src/testing/test-response.ts +332 -0
- package/src/testing/types.ts +224 -0
- package/src/testing/websocket-testing.ts +590 -0
- package/src/types/controller-types.ts +385 -0
- package/src/types/core.ts +683 -0
- package/src/types/middleware-types.ts +419 -0
- package/src/types/request-response-augmentation.ts +489 -0
- package/src/types/route-inference.ts +357 -0
- package/src/types.ts +2049 -0
- package/src/url.ts +126 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/query-preservation.ts +201 -0
- package/src/utils.ts +327 -0
- package/src/validation/validator.ts +685 -0
- package/src/websocket/clustering.ts +762 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contextual Binding for Different Environments
|
|
3
|
+
*
|
|
4
|
+
* Advanced contextual binding system supporting environment-specific configurations,
|
|
5
|
+
* conditional service resolution, and dynamic binding based on runtime context
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Binding, ResolutionContext, Token } from './container'
|
|
9
|
+
import { Container } from './container'
|
|
10
|
+
|
|
11
|
+
// Contextual binding interfaces
|
|
12
|
+
export interface ContextualBinding<T = any> extends Binding<T> {
|
|
13
|
+
conditions: BindingCondition[]
|
|
14
|
+
priority: number
|
|
15
|
+
fallback?: Binding<T>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface BindingCondition {
|
|
19
|
+
type: 'environment' | 'custom' | 'tag' | 'parent' | 'request'
|
|
20
|
+
predicate: (context: ResolutionContext) => boolean
|
|
21
|
+
description?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface EnvironmentConfig {
|
|
25
|
+
name: string
|
|
26
|
+
variables: Record<string, any>
|
|
27
|
+
services: Record<string, any>
|
|
28
|
+
features: string[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ContextualBindingBuilder<T> {
|
|
32
|
+
to: (implementation: new (...args: any[]) => T) => ContextualBindingBuilder<T>
|
|
33
|
+
toValue: (value: T) => ContextualBindingBuilder<T>
|
|
34
|
+
toFactory: (factory: (...args: any[]) => T) => ContextualBindingBuilder<T>
|
|
35
|
+
when: (condition: BindingCondition) => ContextualBindingBuilder<T>
|
|
36
|
+
whenEnvironment: (...environments: string[]) => ContextualBindingBuilder<T>
|
|
37
|
+
whenTag: (tag: string) => ContextualBindingBuilder<T>
|
|
38
|
+
whenParent: (parentToken: string | symbol | ((..._args: any[]) => any)) => ContextualBindingBuilder<T>
|
|
39
|
+
whenRequest: (predicate: (context: ResolutionContext) => boolean) => ContextualBindingBuilder<T>
|
|
40
|
+
withPriority: (priority: number) => ContextualBindingBuilder<T>
|
|
41
|
+
withFallback: (fallback: Binding<T>) => ContextualBindingBuilder<T>
|
|
42
|
+
build: () => Container
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Environment manager for handling different deployment contexts
|
|
47
|
+
*/
|
|
48
|
+
export class EnvironmentManager {
|
|
49
|
+
private environments = new Map<string, EnvironmentConfig>()
|
|
50
|
+
private currentEnvironment: string
|
|
51
|
+
private variables = new Map<string, any>()
|
|
52
|
+
|
|
53
|
+
constructor(defaultEnvironment: string = 'development') {
|
|
54
|
+
this.currentEnvironment = defaultEnvironment
|
|
55
|
+
this.loadEnvironmentVariables()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Register an environment configuration
|
|
60
|
+
*/
|
|
61
|
+
register(config: EnvironmentConfig): this {
|
|
62
|
+
this.environments.set(config.name, config)
|
|
63
|
+
return this
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Set current environment
|
|
68
|
+
*/
|
|
69
|
+
setEnvironment(name: string): this {
|
|
70
|
+
if (!this.environments.has(name)) {
|
|
71
|
+
throw new Error(`Environment ${name} is not registered`)
|
|
72
|
+
}
|
|
73
|
+
this.currentEnvironment = name
|
|
74
|
+
this.loadEnvironmentVariables()
|
|
75
|
+
return this
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get current environment
|
|
80
|
+
*/
|
|
81
|
+
getCurrentEnvironment(): string {
|
|
82
|
+
return this.currentEnvironment
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get environment configuration
|
|
87
|
+
*/
|
|
88
|
+
getEnvironment(name?: string): EnvironmentConfig | undefined {
|
|
89
|
+
return this.environments.get(name || this.currentEnvironment)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Check if environment is active
|
|
94
|
+
*/
|
|
95
|
+
is(...environments: string[]): boolean {
|
|
96
|
+
return environments.includes(this.currentEnvironment)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get environment variable
|
|
101
|
+
*/
|
|
102
|
+
get(key: string, defaultValue?: any): any {
|
|
103
|
+
return this.variables.get(key) ?? defaultValue
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Set environment variable
|
|
108
|
+
*/
|
|
109
|
+
set(key: string, value: any): this {
|
|
110
|
+
this.variables.set(key, value)
|
|
111
|
+
return this
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Check if feature is enabled
|
|
116
|
+
*/
|
|
117
|
+
hasFeature(feature: string): boolean {
|
|
118
|
+
const env = this.getEnvironment()
|
|
119
|
+
return env?.features.includes(feature) ?? false
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Load environment variables
|
|
124
|
+
*/
|
|
125
|
+
private loadEnvironmentVariables(): void {
|
|
126
|
+
const env = this.getEnvironment()
|
|
127
|
+
if (env) {
|
|
128
|
+
for (const [key, value] of Object.entries(env.variables)) {
|
|
129
|
+
this.variables.set(key, value)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Load from environment variables (if available)
|
|
134
|
+
// Note: Environment variables can be loaded from external configuration
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Contextual binding builder implementation
|
|
140
|
+
*/
|
|
141
|
+
export class DefaultContextualBindingBuilder<T> implements ContextualBindingBuilder<T> {
|
|
142
|
+
private binding: Partial<ContextualBinding<T>>
|
|
143
|
+
|
|
144
|
+
constructor(
|
|
145
|
+
private container: ContextualContainer,
|
|
146
|
+
token: Token,
|
|
147
|
+
) {
|
|
148
|
+
this.binding = {
|
|
149
|
+
token,
|
|
150
|
+
conditions: [],
|
|
151
|
+
priority: 0,
|
|
152
|
+
metadata: {
|
|
153
|
+
scope: 'transient',
|
|
154
|
+
},
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Add custom condition
|
|
160
|
+
*/
|
|
161
|
+
when(condition: BindingCondition): ContextualBindingBuilder<T> {
|
|
162
|
+
this.binding.conditions!.push(condition)
|
|
163
|
+
return this
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Add environment condition
|
|
168
|
+
*/
|
|
169
|
+
whenEnvironment(...environments: string[]): ContextualBindingBuilder<T> {
|
|
170
|
+
const condition: BindingCondition = {
|
|
171
|
+
type: 'environment',
|
|
172
|
+
predicate: context => environments.includes(context.environment || 'development'),
|
|
173
|
+
description: `Environment is one of: ${environments.join(', ')}`,
|
|
174
|
+
}
|
|
175
|
+
return this.when(condition)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Add tag condition
|
|
180
|
+
*/
|
|
181
|
+
whenTag(tag: string): ContextualBindingBuilder<T> {
|
|
182
|
+
const condition: BindingCondition = {
|
|
183
|
+
type: 'tag',
|
|
184
|
+
predicate: (context) => {
|
|
185
|
+
// Check if the requesting context has the specified tag
|
|
186
|
+
return context.parent?.token?.toString().includes(tag) ?? false
|
|
187
|
+
},
|
|
188
|
+
description: `Parent has tag: ${tag}`,
|
|
189
|
+
}
|
|
190
|
+
return this.when(condition)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Add parent condition
|
|
195
|
+
*/
|
|
196
|
+
whenParent(parentToken: string | symbol | ((..._args: any[]) => any)): ContextualBindingBuilder<T> {
|
|
197
|
+
const condition: BindingCondition = {
|
|
198
|
+
type: 'parent',
|
|
199
|
+
predicate: context => context.parent?.token === parentToken,
|
|
200
|
+
description: `Parent token is: ${parentToken.toString()}`,
|
|
201
|
+
}
|
|
202
|
+
return this.when(condition)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Add request condition
|
|
207
|
+
*/
|
|
208
|
+
whenRequest(predicate: (context: ResolutionContext) => boolean): ContextualBindingBuilder<T> {
|
|
209
|
+
const condition: BindingCondition = {
|
|
210
|
+
type: 'request',
|
|
211
|
+
predicate,
|
|
212
|
+
description: 'Custom request condition',
|
|
213
|
+
}
|
|
214
|
+
return this.when(condition)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Set priority
|
|
219
|
+
*/
|
|
220
|
+
withPriority(priority: number): ContextualBindingBuilder<T> {
|
|
221
|
+
this.binding.priority = priority
|
|
222
|
+
return this
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Set fallback binding
|
|
227
|
+
*/
|
|
228
|
+
withFallback(fallback: Binding<T>): ContextualBindingBuilder<T> {
|
|
229
|
+
this.binding.fallback = fallback
|
|
230
|
+
return this
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Set implementation
|
|
235
|
+
*/
|
|
236
|
+
to(implementation: new (...args: any[]) => T): this {
|
|
237
|
+
this.binding.implementation = implementation
|
|
238
|
+
return this
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Set value
|
|
243
|
+
*/
|
|
244
|
+
toValue(value: T): this {
|
|
245
|
+
this.binding.value = value
|
|
246
|
+
this.binding.metadata!.scope = 'singleton'
|
|
247
|
+
return this
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Set factory
|
|
252
|
+
*/
|
|
253
|
+
toFactory(factory: (...args: any[]) => T): this {
|
|
254
|
+
this.binding.factory = factory
|
|
255
|
+
return this
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Set singleton scope
|
|
260
|
+
*/
|
|
261
|
+
inSingletonScope(): this {
|
|
262
|
+
this.binding.metadata!.scope = 'singleton'
|
|
263
|
+
return this
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Set transient scope
|
|
268
|
+
*/
|
|
269
|
+
inTransientScope(): this {
|
|
270
|
+
this.binding.metadata!.scope = 'transient'
|
|
271
|
+
return this
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Build and register binding
|
|
276
|
+
*/
|
|
277
|
+
build(): Container {
|
|
278
|
+
this.container.registerContextualBinding(this.binding as ContextualBinding<T>)
|
|
279
|
+
return this.container as unknown as Container
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Enhanced container with contextual binding support
|
|
285
|
+
*/
|
|
286
|
+
export class ContextualContainer extends Container {
|
|
287
|
+
private contextualBindings = new Map<Token, ContextualBinding[]>()
|
|
288
|
+
private environmentManager: EnvironmentManager
|
|
289
|
+
|
|
290
|
+
constructor(options?: any) {
|
|
291
|
+
super(options)
|
|
292
|
+
this.environmentManager = new EnvironmentManager()
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Create contextual binding
|
|
297
|
+
*/
|
|
298
|
+
bindContextual<T>(token: Token): ContextualBindingBuilder<T> {
|
|
299
|
+
return new DefaultContextualBindingBuilder<T>(this, token)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Register contextual binding
|
|
304
|
+
*/
|
|
305
|
+
registerContextualBinding<T>(binding: ContextualBinding<T>): this {
|
|
306
|
+
if (!this.contextualBindings.has(binding.token)) {
|
|
307
|
+
this.contextualBindings.set(binding.token, [])
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const bindings = this.contextualBindings.get(binding.token)!
|
|
311
|
+
bindings.push(binding)
|
|
312
|
+
|
|
313
|
+
// Sort by priority (higher first)
|
|
314
|
+
bindings.sort((a, b) => b.priority - a.priority)
|
|
315
|
+
|
|
316
|
+
return this
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Get environment manager
|
|
321
|
+
*/
|
|
322
|
+
getEnvironmentManager(): EnvironmentManager {
|
|
323
|
+
return this.environmentManager
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Environment-specific binding helpers
|
|
328
|
+
*/
|
|
329
|
+
forDevelopment<T>(token: Token): ContextualBindingBuilder<T> {
|
|
330
|
+
return this.bindContextual<T>(token).whenEnvironment('development')
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
forProduction<T>(token: Token): ContextualBindingBuilder<T> {
|
|
334
|
+
return this.bindContextual<T>(token).whenEnvironment('production')
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
forTesting<T>(token: Token): ContextualBindingBuilder<T> {
|
|
338
|
+
return this.bindContextual<T>(token).whenEnvironment('test', 'testing')
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
forStaging<T>(token: Token): ContextualBindingBuilder<T> {
|
|
342
|
+
return this.bindContextual<T>(token).whenEnvironment('staging')
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Override resolve to handle contextual bindings
|
|
347
|
+
*/
|
|
348
|
+
resolve<T>(token: Token, context?: Partial<ResolutionContext>): T {
|
|
349
|
+
const resolutionContext: ResolutionContext = {
|
|
350
|
+
container: this as Container,
|
|
351
|
+
token,
|
|
352
|
+
environment: context?.environment || this.environmentManager.getCurrentEnvironment(),
|
|
353
|
+
requestId: context?.requestId || this.generateContextualRequestId(),
|
|
354
|
+
depth: context?.depth || 0,
|
|
355
|
+
resolving: context?.resolving || new Set(),
|
|
356
|
+
parent: context?.parent,
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Try contextual bindings first
|
|
360
|
+
const contextualBinding = this.findContextualBinding(token, resolutionContext)
|
|
361
|
+
if (contextualBinding) {
|
|
362
|
+
return this.createInstanceFromContextualBinding<T>(contextualBinding, resolutionContext)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Fall back to regular resolution
|
|
366
|
+
return super.resolve<T>(token, resolutionContext)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Find matching contextual binding
|
|
371
|
+
*/
|
|
372
|
+
private findContextualBinding(
|
|
373
|
+
token: Token,
|
|
374
|
+
context: ResolutionContext,
|
|
375
|
+
): ContextualBinding | undefined {
|
|
376
|
+
const bindings = this.contextualBindings.get(token)
|
|
377
|
+
if (!bindings)
|
|
378
|
+
return undefined
|
|
379
|
+
|
|
380
|
+
for (const binding of bindings) {
|
|
381
|
+
if (this.evaluateConditions(binding.conditions, context)) {
|
|
382
|
+
return binding
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return undefined
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Evaluate binding conditions
|
|
391
|
+
*/
|
|
392
|
+
private evaluateConditions(conditions: BindingCondition[], context: ResolutionContext): boolean {
|
|
393
|
+
return conditions.every((condition) => {
|
|
394
|
+
try {
|
|
395
|
+
return condition.predicate(context)
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
console.warn(`Error evaluating binding condition: ${condition.description}`, error)
|
|
399
|
+
return false
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Create instance from contextual binding
|
|
406
|
+
*/
|
|
407
|
+
private createInstanceFromContextualBinding<T>(
|
|
408
|
+
binding: ContextualBinding<T>,
|
|
409
|
+
context: ResolutionContext,
|
|
410
|
+
): T {
|
|
411
|
+
try {
|
|
412
|
+
return this.createInstance<T>(binding, context)
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
if (binding.fallback) {
|
|
416
|
+
console.warn(`Contextual binding failed, using fallback for ${binding.token.toString()}`)
|
|
417
|
+
return this.createInstance<T>(binding.fallback, context)
|
|
418
|
+
}
|
|
419
|
+
throw error
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Generate unique request ID
|
|
425
|
+
*/
|
|
426
|
+
private generateContextualRequestId(): string {
|
|
427
|
+
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Pre-configured environment setups
|
|
433
|
+
*/
|
|
434
|
+
export class EnvironmentPresets {
|
|
435
|
+
/**
|
|
436
|
+
* Development environment
|
|
437
|
+
*/
|
|
438
|
+
static development(): EnvironmentConfig {
|
|
439
|
+
return {
|
|
440
|
+
name: 'development',
|
|
441
|
+
variables: {
|
|
442
|
+
DEBUG: true,
|
|
443
|
+
LOG_LEVEL: 'debug',
|
|
444
|
+
CACHE_TTL: 60,
|
|
445
|
+
DB_POOL_SIZE: 5,
|
|
446
|
+
},
|
|
447
|
+
services: {
|
|
448
|
+
logger: 'ConsoleLogger',
|
|
449
|
+
cache: 'MemoryCache',
|
|
450
|
+
database: 'SQLiteDatabase',
|
|
451
|
+
},
|
|
452
|
+
features: ['hot-reload', 'debug-toolbar', 'detailed-errors'],
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Production environment
|
|
458
|
+
*/
|
|
459
|
+
static production(): EnvironmentConfig {
|
|
460
|
+
return {
|
|
461
|
+
name: 'production',
|
|
462
|
+
variables: {
|
|
463
|
+
DEBUG: false,
|
|
464
|
+
LOG_LEVEL: 'error',
|
|
465
|
+
CACHE_TTL: 3600,
|
|
466
|
+
DB_POOL_SIZE: 20,
|
|
467
|
+
},
|
|
468
|
+
services: {
|
|
469
|
+
logger: 'FileLogger',
|
|
470
|
+
cache: 'RedisCache',
|
|
471
|
+
database: 'PostgreSQLDatabase',
|
|
472
|
+
},
|
|
473
|
+
features: ['performance-monitoring', 'error-tracking'],
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Testing environment
|
|
479
|
+
*/
|
|
480
|
+
static testing(): EnvironmentConfig {
|
|
481
|
+
return {
|
|
482
|
+
name: 'test',
|
|
483
|
+
variables: {
|
|
484
|
+
DEBUG: false,
|
|
485
|
+
LOG_LEVEL: 'warn',
|
|
486
|
+
CACHE_TTL: 1,
|
|
487
|
+
DB_POOL_SIZE: 1,
|
|
488
|
+
},
|
|
489
|
+
services: {
|
|
490
|
+
logger: 'NullLogger',
|
|
491
|
+
cache: 'MemoryCache',
|
|
492
|
+
database: 'InMemoryDatabase',
|
|
493
|
+
},
|
|
494
|
+
features: ['test-doubles', 'fast-teardown'],
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Staging environment
|
|
500
|
+
*/
|
|
501
|
+
static staging(): EnvironmentConfig {
|
|
502
|
+
return {
|
|
503
|
+
name: 'staging',
|
|
504
|
+
variables: {
|
|
505
|
+
DEBUG: true,
|
|
506
|
+
LOG_LEVEL: 'info',
|
|
507
|
+
CACHE_TTL: 1800,
|
|
508
|
+
DB_POOL_SIZE: 10,
|
|
509
|
+
},
|
|
510
|
+
services: {
|
|
511
|
+
logger: 'FileLogger',
|
|
512
|
+
cache: 'RedisCache',
|
|
513
|
+
database: 'PostgreSQLDatabase',
|
|
514
|
+
},
|
|
515
|
+
features: ['performance-monitoring', 'debug-toolbar'],
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Contextual binding conditions factory
|
|
522
|
+
*/
|
|
523
|
+
export class BindingConditions {
|
|
524
|
+
/**
|
|
525
|
+
* Environment condition
|
|
526
|
+
*/
|
|
527
|
+
static environment(...environments: string[]): BindingCondition {
|
|
528
|
+
return {
|
|
529
|
+
type: 'environment',
|
|
530
|
+
predicate: context => environments.includes(context.environment || 'development'),
|
|
531
|
+
description: `Environment is one of: ${environments.join(', ')}`,
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Feature flag condition
|
|
537
|
+
*/
|
|
538
|
+
static feature(featureName: string): BindingCondition {
|
|
539
|
+
return {
|
|
540
|
+
type: 'custom',
|
|
541
|
+
predicate: (context) => {
|
|
542
|
+
const container = context.container as ContextualContainer
|
|
543
|
+
return container.getEnvironmentManager().hasFeature(featureName)
|
|
544
|
+
},
|
|
545
|
+
description: `Feature ${featureName} is enabled`,
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Environment variable condition
|
|
551
|
+
*/
|
|
552
|
+
static envVar(key: string, value: any): BindingCondition {
|
|
553
|
+
return {
|
|
554
|
+
type: 'custom',
|
|
555
|
+
predicate: (context) => {
|
|
556
|
+
const container = context.container as ContextualContainer
|
|
557
|
+
return container.getEnvironmentManager().get(key) === value
|
|
558
|
+
},
|
|
559
|
+
description: `Environment variable ${key} equals ${value}`,
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Request ID pattern condition
|
|
565
|
+
*/
|
|
566
|
+
static requestPattern(pattern: RegExp): BindingCondition {
|
|
567
|
+
return {
|
|
568
|
+
type: 'request',
|
|
569
|
+
predicate: context => pattern.test(context.requestId || ''),
|
|
570
|
+
description: `Request ID matches pattern: ${pattern.toString()}`,
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Time-based condition
|
|
576
|
+
*/
|
|
577
|
+
static timeRange(startHour: number, endHour: number): BindingCondition {
|
|
578
|
+
return {
|
|
579
|
+
type: 'custom',
|
|
580
|
+
predicate: () => {
|
|
581
|
+
const hour = new Date().getHours()
|
|
582
|
+
return hour >= startHour && hour <= endHour
|
|
583
|
+
},
|
|
584
|
+
description: `Time is between ${startHour}:00 and ${endHour}:00`,
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Custom predicate condition
|
|
590
|
+
*/
|
|
591
|
+
static custom(
|
|
592
|
+
predicate: (context: ResolutionContext) => boolean,
|
|
593
|
+
description?: string,
|
|
594
|
+
): BindingCondition {
|
|
595
|
+
return {
|
|
596
|
+
type: 'custom',
|
|
597
|
+
predicate,
|
|
598
|
+
description: description || 'Custom condition',
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export { ContextualContainer as DIContainer }
|