@hazeljs/core 0.2.0-alpha.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/LICENSE +192 -0
- package/README.md +560 -0
- package/dist/__tests__/container.test.d.ts +2 -0
- package/dist/__tests__/container.test.d.ts.map +1 -0
- package/dist/__tests__/container.test.js +454 -0
- package/dist/__tests__/decorators.test.d.ts +2 -0
- package/dist/__tests__/decorators.test.d.ts.map +1 -0
- package/dist/__tests__/decorators.test.js +1237 -0
- package/dist/__tests__/errors/http.error.test.d.ts +2 -0
- package/dist/__tests__/errors/http.error.test.d.ts.map +1 -0
- package/dist/__tests__/errors/http.error.test.js +117 -0
- package/dist/__tests__/filters/exception-filter.test.d.ts +2 -0
- package/dist/__tests__/filters/exception-filter.test.d.ts.map +1 -0
- package/dist/__tests__/filters/exception-filter.test.js +135 -0
- package/dist/__tests__/filters/http-exception.filter.test.d.ts +2 -0
- package/dist/__tests__/filters/http-exception.filter.test.d.ts.map +1 -0
- package/dist/__tests__/filters/http-exception.filter.test.js +119 -0
- package/dist/__tests__/hazel-app.test.d.ts +2 -0
- package/dist/__tests__/hazel-app.test.d.ts.map +1 -0
- package/dist/__tests__/hazel-app.test.js +810 -0
- package/dist/__tests__/hazel-module.test.d.ts +2 -0
- package/dist/__tests__/hazel-module.test.d.ts.map +1 -0
- package/dist/__tests__/hazel-module.test.js +408 -0
- package/dist/__tests__/hazel-response.test.d.ts +2 -0
- package/dist/__tests__/hazel-response.test.d.ts.map +1 -0
- package/dist/__tests__/hazel-response.test.js +138 -0
- package/dist/__tests__/health.test.d.ts +2 -0
- package/dist/__tests__/health.test.d.ts.map +1 -0
- package/dist/__tests__/health.test.js +147 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/index.test.js +239 -0
- package/dist/__tests__/interceptors/interceptor.test.d.ts +2 -0
- package/dist/__tests__/interceptors/interceptor.test.d.ts.map +1 -0
- package/dist/__tests__/interceptors/interceptor.test.js +166 -0
- package/dist/__tests__/logger.test.d.ts +2 -0
- package/dist/__tests__/logger.test.d.ts.map +1 -0
- package/dist/__tests__/logger.test.js +141 -0
- package/dist/__tests__/middleware/cors.test.d.ts +2 -0
- package/dist/__tests__/middleware/cors.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/cors.test.js +129 -0
- package/dist/__tests__/middleware/csrf.test.d.ts +2 -0
- package/dist/__tests__/middleware/csrf.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/csrf.test.js +247 -0
- package/dist/__tests__/middleware/global-middleware.test.d.ts +2 -0
- package/dist/__tests__/middleware/global-middleware.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/global-middleware.test.js +259 -0
- package/dist/__tests__/middleware/rate-limit.test.d.ts +2 -0
- package/dist/__tests__/middleware/rate-limit.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/rate-limit.test.js +264 -0
- package/dist/__tests__/middleware/security-headers.test.d.ts +2 -0
- package/dist/__tests__/middleware/security-headers.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/security-headers.test.js +229 -0
- package/dist/__tests__/middleware/timeout.test.d.ts +2 -0
- package/dist/__tests__/middleware/timeout.test.d.ts.map +1 -0
- package/dist/__tests__/middleware/timeout.test.js +132 -0
- package/dist/__tests__/middleware.test.d.ts +2 -0
- package/dist/__tests__/middleware.test.d.ts.map +1 -0
- package/dist/__tests__/middleware.test.js +180 -0
- package/dist/__tests__/pipes/pipe.test.d.ts +2 -0
- package/dist/__tests__/pipes/pipe.test.d.ts.map +1 -0
- package/dist/__tests__/pipes/pipe.test.js +245 -0
- package/dist/__tests__/pipes/validation.pipe.test.d.ts +2 -0
- package/dist/__tests__/pipes/validation.pipe.test.d.ts.map +1 -0
- package/dist/__tests__/pipes/validation.pipe.test.js +297 -0
- package/dist/__tests__/request-parser.test.d.ts +2 -0
- package/dist/__tests__/request-parser.test.d.ts.map +1 -0
- package/dist/__tests__/request-parser.test.js +182 -0
- package/dist/__tests__/router.test.d.ts +2 -0
- package/dist/__tests__/router.test.d.ts.map +1 -0
- package/dist/__tests__/router.test.js +1183 -0
- package/dist/__tests__/routing/route-matcher.test.d.ts +2 -0
- package/dist/__tests__/routing/route-matcher.test.d.ts.map +1 -0
- package/dist/__tests__/routing/route-matcher.test.js +219 -0
- package/dist/__tests__/routing/version.decorator.test.d.ts +2 -0
- package/dist/__tests__/routing/version.decorator.test.d.ts.map +1 -0
- package/dist/__tests__/routing/version.decorator.test.js +298 -0
- package/dist/__tests__/service.test.d.ts +2 -0
- package/dist/__tests__/service.test.d.ts.map +1 -0
- package/dist/__tests__/service.test.js +121 -0
- package/dist/__tests__/shutdown.test.d.ts +2 -0
- package/dist/__tests__/shutdown.test.d.ts.map +1 -0
- package/dist/__tests__/shutdown.test.js +250 -0
- package/dist/__tests__/testing/testing.module.test.d.ts +2 -0
- package/dist/__tests__/testing/testing.module.test.d.ts.map +1 -0
- package/dist/__tests__/testing/testing.module.test.js +370 -0
- package/dist/__tests__/upload/file-upload.test.d.ts +2 -0
- package/dist/__tests__/upload/file-upload.test.d.ts.map +1 -0
- package/dist/__tests__/upload/file-upload.test.js +498 -0
- package/dist/__tests__/utils/sanitize.test.d.ts +2 -0
- package/dist/__tests__/utils/sanitize.test.d.ts.map +1 -0
- package/dist/__tests__/utils/sanitize.test.js +291 -0
- package/dist/__tests__/validator.test.d.ts +2 -0
- package/dist/__tests__/validator.test.d.ts.map +1 -0
- package/dist/__tests__/validator.test.js +300 -0
- package/dist/container.d.ts +80 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/container.js +271 -0
- package/dist/decorators.d.ts +166 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +538 -0
- package/dist/errors/http.error.d.ts +34 -0
- package/dist/errors/http.error.d.ts.map +1 -0
- package/dist/errors/http.error.js +69 -0
- package/dist/filters/exception-filter.d.ts +39 -0
- package/dist/filters/exception-filter.d.ts.map +1 -0
- package/dist/filters/exception-filter.js +38 -0
- package/dist/filters/http-exception.filter.d.ts +9 -0
- package/dist/filters/http-exception.filter.d.ts.map +1 -0
- package/dist/filters/http-exception.filter.js +42 -0
- package/dist/hazel-app.d.ts +94 -0
- package/dist/hazel-app.d.ts.map +1 -0
- package/dist/hazel-app.js +516 -0
- package/dist/hazel-module.d.ts +29 -0
- package/dist/hazel-module.d.ts.map +1 -0
- package/dist/hazel-module.js +137 -0
- package/dist/hazel-response.d.ts +25 -0
- package/dist/hazel-response.d.ts.map +1 -0
- package/dist/hazel-response.js +89 -0
- package/dist/health.d.ts +73 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +174 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +159 -0
- package/dist/interceptors/interceptor.d.ts +30 -0
- package/dist/interceptors/interceptor.d.ts.map +1 -0
- package/dist/interceptors/interceptor.js +71 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +261 -0
- package/dist/middleware/cors.middleware.d.ts +44 -0
- package/dist/middleware/cors.middleware.d.ts.map +1 -0
- package/dist/middleware/cors.middleware.js +118 -0
- package/dist/middleware/csrf.middleware.d.ts +82 -0
- package/dist/middleware/csrf.middleware.d.ts.map +1 -0
- package/dist/middleware/csrf.middleware.js +183 -0
- package/dist/middleware/global-middleware.d.ts +111 -0
- package/dist/middleware/global-middleware.d.ts.map +1 -0
- package/dist/middleware/global-middleware.js +179 -0
- package/dist/middleware/rate-limit.middleware.d.ts +73 -0
- package/dist/middleware/rate-limit.middleware.d.ts.map +1 -0
- package/dist/middleware/rate-limit.middleware.js +124 -0
- package/dist/middleware/security-headers.middleware.d.ts +76 -0
- package/dist/middleware/security-headers.middleware.d.ts.map +1 -0
- package/dist/middleware/security-headers.middleware.js +123 -0
- package/dist/middleware/timeout.middleware.d.ts +25 -0
- package/dist/middleware/timeout.middleware.d.ts.map +1 -0
- package/dist/middleware/timeout.middleware.js +74 -0
- package/dist/middleware.d.ts +13 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +47 -0
- package/dist/pipes/pipe.d.ts +50 -0
- package/dist/pipes/pipe.d.ts.map +1 -0
- package/dist/pipes/pipe.js +96 -0
- package/dist/pipes/validation.pipe.d.ts +6 -0
- package/dist/pipes/validation.pipe.d.ts.map +1 -0
- package/dist/pipes/validation.pipe.js +61 -0
- package/dist/request-context.d.ts +22 -0
- package/dist/request-context.d.ts.map +1 -0
- package/dist/request-context.js +2 -0
- package/dist/request-parser.d.ts +7 -0
- package/dist/request-parser.d.ts.map +1 -0
- package/dist/request-parser.js +60 -0
- package/dist/router.d.ts +33 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +506 -0
- package/dist/routing/route-matcher.d.ts +39 -0
- package/dist/routing/route-matcher.d.ts.map +1 -0
- package/dist/routing/route-matcher.js +93 -0
- package/dist/routing/version.decorator.d.ts +36 -0
- package/dist/routing/version.decorator.d.ts.map +1 -0
- package/dist/routing/version.decorator.js +89 -0
- package/dist/service.d.ts +9 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +39 -0
- package/dist/shutdown.d.ts +32 -0
- package/dist/shutdown.d.ts.map +1 -0
- package/dist/shutdown.js +109 -0
- package/dist/testing/testing.module.d.ts +83 -0
- package/dist/testing/testing.module.d.ts.map +1 -0
- package/dist/testing/testing.module.js +164 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/upload/file-upload.d.ts +75 -0
- package/dist/upload/file-upload.d.ts.map +1 -0
- package/dist/upload/file-upload.js +261 -0
- package/dist/utils/sanitize.d.ts +45 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +165 -0
- package/dist/validator.d.ts +7 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +119 -0
- package/package.json +67 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Container = exports.Scope = void 0;
|
|
7
|
+
require("reflect-metadata");
|
|
8
|
+
const logger_1 = __importDefault(require("./logger"));
|
|
9
|
+
var Scope;
|
|
10
|
+
(function (Scope) {
|
|
11
|
+
Scope["SINGLETON"] = "singleton";
|
|
12
|
+
Scope["TRANSIENT"] = "transient";
|
|
13
|
+
Scope["REQUEST"] = "request";
|
|
14
|
+
})(Scope || (exports.Scope = Scope = {}));
|
|
15
|
+
class Container {
|
|
16
|
+
// Note: resolutionStack is used per-resolve chain via parameter threading, not shared state
|
|
17
|
+
constructor() {
|
|
18
|
+
this.providers = new Map();
|
|
19
|
+
this.requestScopedProviders = new Map();
|
|
20
|
+
logger_1.default.debug('Container initialized');
|
|
21
|
+
}
|
|
22
|
+
static getInstance() {
|
|
23
|
+
if (!Container.instance) {
|
|
24
|
+
Container.instance = new Container();
|
|
25
|
+
}
|
|
26
|
+
return Container.instance;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a new container instance (for testing)
|
|
30
|
+
*/
|
|
31
|
+
static createTestInstance() {
|
|
32
|
+
return new Container();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Register a provider with the container
|
|
36
|
+
*/
|
|
37
|
+
register(token, provider, scope = Scope.SINGLETON) {
|
|
38
|
+
const tokenName = this.getTokenName(token);
|
|
39
|
+
logger_1.default.debug(`Registering provider: ${tokenName} with scope: ${scope}`);
|
|
40
|
+
if (this.isProvider(provider)) {
|
|
41
|
+
this.registerProvider(provider);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.providers.set(token, {
|
|
45
|
+
instance: provider,
|
|
46
|
+
scope,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Register a provider configuration
|
|
52
|
+
*/
|
|
53
|
+
registerProvider(provider) {
|
|
54
|
+
const tokenName = this.getTokenName(provider.token);
|
|
55
|
+
logger_1.default.debug(`Registering provider configuration: ${tokenName}`);
|
|
56
|
+
const scope = provider.scope || Scope.SINGLETON;
|
|
57
|
+
const metadata = { scope };
|
|
58
|
+
if (provider.useValue !== undefined) {
|
|
59
|
+
metadata.instance = provider.useValue;
|
|
60
|
+
}
|
|
61
|
+
else if (provider.useFactory) {
|
|
62
|
+
metadata.factory = (requestId) => {
|
|
63
|
+
const deps = (provider.inject || []).map((dep) => this.resolve(dep, requestId));
|
|
64
|
+
return provider.useFactory(...deps);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
else if (provider.useClass) {
|
|
68
|
+
metadata.factory = (requestId) => this.createInstance(provider.useClass, requestId);
|
|
69
|
+
}
|
|
70
|
+
this.providers.set(provider.token, metadata);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve a dependency from the container
|
|
74
|
+
*/
|
|
75
|
+
resolve(token, requestId, resolutionStack) {
|
|
76
|
+
if (!token) {
|
|
77
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
78
|
+
logger_1.default.debug('No token provided for resolution');
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
83
|
+
const tokenName = this.getTokenName(token);
|
|
84
|
+
logger_1.default.debug(`Resolving dependency: ${tokenName}`);
|
|
85
|
+
}
|
|
86
|
+
// Check if provider is registered
|
|
87
|
+
const metadata = this.providers.get(token);
|
|
88
|
+
if (metadata) {
|
|
89
|
+
return this.resolveFromMetadata(token, metadata, requestId, resolutionStack);
|
|
90
|
+
}
|
|
91
|
+
// If token is a class, try to auto-resolve
|
|
92
|
+
if (typeof token === 'function' && token.prototype) {
|
|
93
|
+
return this.autoResolve(token, requestId, resolutionStack);
|
|
94
|
+
}
|
|
95
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
96
|
+
logger_1.default.warn(`No provider found for token: ${this.getTokenName(token)}`);
|
|
97
|
+
}
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolve from provider metadata
|
|
102
|
+
*/
|
|
103
|
+
resolveFromMetadata(token, metadata, requestId, resolutionStack) {
|
|
104
|
+
const tokenName = this.getTokenName(token);
|
|
105
|
+
// Use per-chain resolution stack to detect circular deps (thread-safe)
|
|
106
|
+
const stack = resolutionStack || new Set();
|
|
107
|
+
if (stack.has(token)) {
|
|
108
|
+
const chain = Array.from(stack).map(t => this.getTokenName(t));
|
|
109
|
+
chain.push(tokenName);
|
|
110
|
+
throw new Error(`Circular dependency detected: ${chain.join(' → ')}`);
|
|
111
|
+
}
|
|
112
|
+
stack.add(token);
|
|
113
|
+
try {
|
|
114
|
+
// Handle different scopes
|
|
115
|
+
switch (metadata.scope) {
|
|
116
|
+
case Scope.SINGLETON:
|
|
117
|
+
if (metadata.instance !== undefined) {
|
|
118
|
+
return metadata.instance;
|
|
119
|
+
}
|
|
120
|
+
if (metadata.isResolving) {
|
|
121
|
+
// Another resolve is already creating this singleton — wait would deadlock in sync, so error
|
|
122
|
+
throw new Error(`Singleton ${tokenName} is already being resolved (possible async race)`);
|
|
123
|
+
}
|
|
124
|
+
if (metadata.factory) {
|
|
125
|
+
metadata.isResolving = true;
|
|
126
|
+
try {
|
|
127
|
+
const result = metadata.factory(requestId);
|
|
128
|
+
metadata.instance = result;
|
|
129
|
+
return metadata.instance;
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
metadata.isResolving = false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
case Scope.TRANSIENT:
|
|
137
|
+
if (metadata.factory) {
|
|
138
|
+
return metadata.factory(requestId);
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
case Scope.REQUEST:
|
|
142
|
+
if (!requestId) {
|
|
143
|
+
throw new Error(`Request scope requires requestId for: ${tokenName}`);
|
|
144
|
+
}
|
|
145
|
+
return this.resolveRequestScoped(token, metadata, requestId);
|
|
146
|
+
}
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
stack.delete(token);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Resolve request-scoped provider
|
|
155
|
+
*/
|
|
156
|
+
resolveRequestScoped(token, metadata, requestId) {
|
|
157
|
+
let requestProviders = this.requestScopedProviders.get(requestId);
|
|
158
|
+
if (!requestProviders) {
|
|
159
|
+
requestProviders = new Map();
|
|
160
|
+
this.requestScopedProviders.set(requestId, requestProviders);
|
|
161
|
+
}
|
|
162
|
+
if (requestProviders.has(token)) {
|
|
163
|
+
return requestProviders.get(token);
|
|
164
|
+
}
|
|
165
|
+
if (metadata.factory) {
|
|
166
|
+
const instance = metadata.factory(requestId);
|
|
167
|
+
requestProviders.set(token, instance);
|
|
168
|
+
return instance;
|
|
169
|
+
}
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Auto-resolve a class without explicit registration
|
|
174
|
+
*/
|
|
175
|
+
autoResolve(token, requestId, resolutionStack) {
|
|
176
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
177
|
+
logger_1.default.debug(`Auto-resolving: ${token.name}`);
|
|
178
|
+
}
|
|
179
|
+
// Check if already registered
|
|
180
|
+
if (this.providers.has(token)) {
|
|
181
|
+
return this.resolve(token, requestId, resolutionStack);
|
|
182
|
+
}
|
|
183
|
+
// Get scope from metadata
|
|
184
|
+
const scope = Reflect.getMetadata('hazel:scope', token) || Scope.SINGLETON;
|
|
185
|
+
// Create factory for the class
|
|
186
|
+
const factory = (reqId) => this.createInstance(token, reqId, resolutionStack);
|
|
187
|
+
this.providers.set(token, { scope, factory });
|
|
188
|
+
return this.resolve(token, requestId, resolutionStack);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Create instance of a class with dependency injection
|
|
192
|
+
*/
|
|
193
|
+
createInstance(token, requestId, resolutionStack) {
|
|
194
|
+
// Get constructor parameters
|
|
195
|
+
const params = Reflect.getMetadata('design:paramtypes', token) || [];
|
|
196
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
197
|
+
logger_1.default.debug(`Constructor parameters: ${params.map((p) => p?.name || 'undefined').join(', ')}`);
|
|
198
|
+
}
|
|
199
|
+
// Get injection tokens if specified
|
|
200
|
+
const injectionTokens = Reflect.getMetadata('hazel:inject', token) || [];
|
|
201
|
+
// Resolve dependencies
|
|
202
|
+
const dependencies = params.map((param, index) => {
|
|
203
|
+
const injectionToken = injectionTokens[index];
|
|
204
|
+
const tokenToResolve = injectionToken || param;
|
|
205
|
+
if (!tokenToResolve) {
|
|
206
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
207
|
+
logger_1.default.debug('Undefined parameter type found');
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
212
|
+
logger_1.default.debug(`Resolving dependency for: ${this.getTokenName(tokenToResolve)}`);
|
|
213
|
+
}
|
|
214
|
+
return this.resolve(tokenToResolve, requestId, resolutionStack);
|
|
215
|
+
});
|
|
216
|
+
// Create instance with dependencies
|
|
217
|
+
const instance = new token(...dependencies);
|
|
218
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
219
|
+
logger_1.default.debug(`Created instance of: ${this.getTokenName(token)}`);
|
|
220
|
+
}
|
|
221
|
+
return instance;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Clear request-scoped providers for a specific request
|
|
225
|
+
*/
|
|
226
|
+
clearRequestScope(requestId) {
|
|
227
|
+
if (logger_1.default.isDebugEnabled()) {
|
|
228
|
+
logger_1.default.debug(`Clearing request scope: ${requestId}`);
|
|
229
|
+
}
|
|
230
|
+
this.requestScopedProviders.delete(requestId);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Clear all providers
|
|
234
|
+
*/
|
|
235
|
+
clear() {
|
|
236
|
+
logger_1.default.debug('Clearing container');
|
|
237
|
+
this.providers.clear();
|
|
238
|
+
this.requestScopedProviders.clear();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Check if a token is registered
|
|
242
|
+
*/
|
|
243
|
+
has(token) {
|
|
244
|
+
return this.providers.has(token);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Get all registered tokens
|
|
248
|
+
*/
|
|
249
|
+
getTokens() {
|
|
250
|
+
return Array.from(this.providers.keys());
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Helper to get token name for logging
|
|
254
|
+
*/
|
|
255
|
+
getTokenName(token) {
|
|
256
|
+
if (typeof token === 'string')
|
|
257
|
+
return token;
|
|
258
|
+
if (typeof token === 'symbol')
|
|
259
|
+
return token.toString();
|
|
260
|
+
if (typeof token === 'function')
|
|
261
|
+
return token.name;
|
|
262
|
+
return 'unknown';
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Type guard to check if value is a Provider
|
|
266
|
+
*/
|
|
267
|
+
isProvider(value) {
|
|
268
|
+
return typeof value === 'object' && value !== null && 'token' in value;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
exports.Container = Container;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { Type, RequestContext, Request } from './types';
|
|
3
|
+
import { PipeTransform, PipeMetadata } from './pipes/pipe';
|
|
4
|
+
import { Interceptor, InterceptorMetadata } from './interceptors/interceptor';
|
|
5
|
+
import { HazelApp } from './hazel-app';
|
|
6
|
+
import type { Container } from './container';
|
|
7
|
+
export declare const CUSTOM_METADATA_PREFIX = "hazel:meta:";
|
|
8
|
+
export interface ControllerMetadata {
|
|
9
|
+
path: string;
|
|
10
|
+
interceptors?: InterceptorMetadata[];
|
|
11
|
+
}
|
|
12
|
+
export interface RouteMetadata {
|
|
13
|
+
path: string;
|
|
14
|
+
method: string;
|
|
15
|
+
handler: string | symbol;
|
|
16
|
+
middlewares?: Type<unknown>[];
|
|
17
|
+
pipes?: PipeMetadata[];
|
|
18
|
+
}
|
|
19
|
+
export interface ControllerOptions {
|
|
20
|
+
path: string;
|
|
21
|
+
version?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface RouteOptions {
|
|
24
|
+
path?: string;
|
|
25
|
+
middlewares?: Type<unknown>[];
|
|
26
|
+
pipes?: PipeMetadata[];
|
|
27
|
+
interceptors?: InterceptorMetadata[];
|
|
28
|
+
}
|
|
29
|
+
export interface ServiceOptions {
|
|
30
|
+
scope?: 'singleton' | 'transient' | 'request';
|
|
31
|
+
}
|
|
32
|
+
export interface InjectableOptions {
|
|
33
|
+
scope?: 'singleton' | 'transient' | 'request';
|
|
34
|
+
}
|
|
35
|
+
export interface RepositoryOptions {
|
|
36
|
+
model: string;
|
|
37
|
+
scope?: 'singleton' | 'transient' | 'request';
|
|
38
|
+
}
|
|
39
|
+
export interface OnModuleInit {
|
|
40
|
+
onModuleInit(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export interface OnModuleDestroy {
|
|
43
|
+
onModuleDestroy(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
export interface ExecutionContext {
|
|
46
|
+
switchToHttp(): {
|
|
47
|
+
getRequest(): unknown;
|
|
48
|
+
getResponse(): unknown;
|
|
49
|
+
/**
|
|
50
|
+
* Returns the fully parsed RequestContext for this request.
|
|
51
|
+
* Gives guards access to `params`, `query`, `headers`, `user`, and `body`
|
|
52
|
+
* without having to re-parse the raw Node.js IncomingMessage.
|
|
53
|
+
*/
|
|
54
|
+
getContext(): RequestContext;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export interface CanActivate {
|
|
58
|
+
canActivate(context: ExecutionContext): Promise<boolean> | boolean;
|
|
59
|
+
}
|
|
60
|
+
export { HazelModule, Module } from './hazel-module';
|
|
61
|
+
export declare function Controller(options: ControllerOptions | string): ClassDecorator;
|
|
62
|
+
export declare function Injectable(options?: InjectableOptions): ClassDecorator;
|
|
63
|
+
export declare function Get(options?: {
|
|
64
|
+
path?: string;
|
|
65
|
+
} | string): MethodDecorator;
|
|
66
|
+
export declare function Post(options?: {
|
|
67
|
+
path?: string;
|
|
68
|
+
} | string): MethodDecorator;
|
|
69
|
+
export declare function Put(options?: {
|
|
70
|
+
path?: string;
|
|
71
|
+
} | string): MethodDecorator;
|
|
72
|
+
export declare function Delete(options?: {
|
|
73
|
+
path?: string;
|
|
74
|
+
} | string): MethodDecorator;
|
|
75
|
+
export declare function Patch(options?: {
|
|
76
|
+
path?: string;
|
|
77
|
+
} | string): MethodDecorator;
|
|
78
|
+
export declare function Inject(token?: string | symbol | Type<unknown>): ParameterDecorator;
|
|
79
|
+
export declare function Service(options?: ServiceOptions): ClassDecorator;
|
|
80
|
+
export declare function Body(dtoType?: Type<unknown>): ParameterDecorator;
|
|
81
|
+
export declare function Request(): ParameterDecorator;
|
|
82
|
+
export declare function Param(paramName: string, pipe?: Type<PipeTransform>): ParameterDecorator;
|
|
83
|
+
export declare function Query(paramName?: string, pipe?: Type<PipeTransform>): ParameterDecorator;
|
|
84
|
+
export declare function UsePipes(...pipes: (Type<PipeTransform> | PipeMetadata)[]): ClassDecorator & MethodDecorator;
|
|
85
|
+
export declare function UseInterceptors(...interceptors: (Type<Interceptor> | InterceptorMetadata)[]): ClassDecorator & MethodDecorator;
|
|
86
|
+
export declare function UseGuards(...guards: Type<CanActivate>[]): ClassDecorator & MethodDecorator;
|
|
87
|
+
export declare function AITask(options: {
|
|
88
|
+
name: string;
|
|
89
|
+
prompt: string;
|
|
90
|
+
provider: string;
|
|
91
|
+
model: string;
|
|
92
|
+
outputType: string;
|
|
93
|
+
}): MethodDecorator;
|
|
94
|
+
export declare function Req(): ParameterDecorator;
|
|
95
|
+
export declare function Headers(headerName?: string): ParameterDecorator;
|
|
96
|
+
export declare function HttpCode(statusCode: number): MethodDecorator;
|
|
97
|
+
export declare function Header(name: string, value: string): MethodDecorator;
|
|
98
|
+
export declare function Redirect(url: string, statusCode?: number): MethodDecorator;
|
|
99
|
+
export declare function Res(): ParameterDecorator;
|
|
100
|
+
export declare function Ip(): ParameterDecorator;
|
|
101
|
+
export declare function Host(): ParameterDecorator;
|
|
102
|
+
/**
|
|
103
|
+
* Marks a controller or route as public (no auth required).
|
|
104
|
+
* Guards should check Reflect.getMetadata(PUBLIC_METADATA_KEY, target, propertyKey)
|
|
105
|
+
* or Reflect.getMetadata(PUBLIC_METADATA_KEY, target) and allow the request when true.
|
|
106
|
+
*/
|
|
107
|
+
export declare function Public(): ClassDecorator & MethodDecorator;
|
|
108
|
+
/** Alias for @Public(). Use when you want to skip auth for specific routes. */
|
|
109
|
+
export declare const SkipAuth: typeof Public;
|
|
110
|
+
export declare function Timeout(ms: number): MethodDecorator;
|
|
111
|
+
export declare function Optional(): ParameterDecorator;
|
|
112
|
+
export declare function Session(): ParameterDecorator;
|
|
113
|
+
export interface RetryDecoratorOptions {
|
|
114
|
+
count: number;
|
|
115
|
+
delay?: number;
|
|
116
|
+
retryIf?: (err: Error) => boolean;
|
|
117
|
+
}
|
|
118
|
+
export declare function Retry(options: RetryDecoratorOptions): MethodDecorator;
|
|
119
|
+
export declare function ApiTags(...tags: string[]): ClassDecorator & MethodDecorator;
|
|
120
|
+
export interface ApiOperationOptions {
|
|
121
|
+
summary?: string;
|
|
122
|
+
description?: string;
|
|
123
|
+
operationId?: string;
|
|
124
|
+
}
|
|
125
|
+
export declare function ApiOperation(options: ApiOperationOptions | string): MethodDecorator;
|
|
126
|
+
/**
|
|
127
|
+
* Sets arbitrary metadata on a class or method.
|
|
128
|
+
* Guards, interceptors, and other components can read it via getMetadata(key, target, propertyKey?).
|
|
129
|
+
*
|
|
130
|
+
* @param key - Metadata key (stored under hazel:meta:<key> to avoid collisions)
|
|
131
|
+
* @param value - Value to store (any serializable or object)
|
|
132
|
+
* @example
|
|
133
|
+
* SetMetadata('roles', ['admin'])(MyController)
|
|
134
|
+
* SetMetadata('roles', ['user'])(MyController.prototype, 'getProfile')
|
|
135
|
+
*/
|
|
136
|
+
export declare function SetMetadata(key: string, value: unknown): ClassDecorator & MethodDecorator;
|
|
137
|
+
/**
|
|
138
|
+
* Reads custom metadata set with SetMetadata.
|
|
139
|
+
*
|
|
140
|
+
* @param key - Key passed to SetMetadata(key, value)
|
|
141
|
+
* @param target - Class or prototype
|
|
142
|
+
* @param propertyKey - Optional method name (for method-level metadata)
|
|
143
|
+
*/
|
|
144
|
+
export declare function getMetadata<T = unknown>(key: string, target: object, propertyKey?: string | symbol): T | undefined;
|
|
145
|
+
/**
|
|
146
|
+
* Context passed to custom parameter decorator resolvers.
|
|
147
|
+
* The router calls the resolver with (req, context, container) when invoking the handler.
|
|
148
|
+
*/
|
|
149
|
+
export interface ParamDecoratorContext {
|
|
150
|
+
req: Request;
|
|
151
|
+
context: RequestContext;
|
|
152
|
+
container: Container;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Creates a custom parameter decorator that injects a value computed from the request.
|
|
156
|
+
* The resolver receives the raw request, parsed request context, and the DI container.
|
|
157
|
+
* Return value can be a Promise for async resolution (e.g. loading the current user from DB).
|
|
158
|
+
*
|
|
159
|
+
* @param resolve - Function (req, context, container) => value | Promise<value>
|
|
160
|
+
* @example
|
|
161
|
+
* const CurrentUser = createParamDecorator(async (req, ctx, container) => ctx.user ?? req.user);
|
|
162
|
+
* // In controller: getProfile(@CurrentUser() user: User) { ... }
|
|
163
|
+
*/
|
|
164
|
+
export declare function createParamDecorator<T = unknown>(resolve: (req: Request, context: RequestContext, container: Container) => T | Promise<T>): ParameterDecorator;
|
|
165
|
+
export { HazelApp };
|
|
166
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"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"}
|