@hono-di/core 0.0.6
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/core.cjs +1554 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +339 -0
- package/dist/core.d.ts +339 -0
- package/dist/core.js +1519 -0
- package/dist/core.js.map +1 -0
- package/dist/decorators.cjs +345 -0
- package/dist/decorators.cjs.map +1 -0
- package/dist/decorators.d.cts +70 -0
- package/dist/decorators.d.ts +70 -0
- package/dist/decorators.js +302 -0
- package/dist/decorators.js.map +1 -0
- package/dist/index.cjs +1850 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +32 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +1772 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces-4oTuNIHA.d.cts +139 -0
- package/dist/interfaces-4oTuNIHA.d.ts +139 -0
- package/package.json +39 -0
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,1554 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('reflect-metadata');
|
|
4
|
+
var hono = require('hono');
|
|
5
|
+
var rxjs = require('rxjs');
|
|
6
|
+
var operators = require('rxjs/operators');
|
|
7
|
+
|
|
8
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
10
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
11
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
12
|
+
if (decorator = decorators[i])
|
|
13
|
+
result = (decorator(result)) || result;
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/interfaces.ts
|
|
18
|
+
var RequestMethod = /* @__PURE__ */ ((RequestMethod2) => {
|
|
19
|
+
RequestMethod2["GET"] = "get";
|
|
20
|
+
RequestMethod2["POST"] = "post";
|
|
21
|
+
RequestMethod2["PUT"] = "put";
|
|
22
|
+
RequestMethod2["DELETE"] = "delete";
|
|
23
|
+
RequestMethod2["PATCH"] = "patch";
|
|
24
|
+
RequestMethod2["ALL"] = "all";
|
|
25
|
+
RequestMethod2["OPTIONS"] = "options";
|
|
26
|
+
RequestMethod2["HEAD"] = "head";
|
|
27
|
+
return RequestMethod2;
|
|
28
|
+
})(RequestMethod || {});
|
|
29
|
+
|
|
30
|
+
// src/injector/module.ts
|
|
31
|
+
var Module = class {
|
|
32
|
+
constructor(metatype, token) {
|
|
33
|
+
this.metatype = metatype;
|
|
34
|
+
this.token = token;
|
|
35
|
+
}
|
|
36
|
+
_providers = /* @__PURE__ */ new Map();
|
|
37
|
+
_imports = /* @__PURE__ */ new Set();
|
|
38
|
+
_exports = /* @__PURE__ */ new Set();
|
|
39
|
+
_controllers = /* @__PURE__ */ new Map();
|
|
40
|
+
get providers() {
|
|
41
|
+
return this._providers;
|
|
42
|
+
}
|
|
43
|
+
get imports() {
|
|
44
|
+
return this._imports;
|
|
45
|
+
}
|
|
46
|
+
get exports() {
|
|
47
|
+
return this._exports;
|
|
48
|
+
}
|
|
49
|
+
get controllers() {
|
|
50
|
+
return this._controllers;
|
|
51
|
+
}
|
|
52
|
+
addProvider(provider) {
|
|
53
|
+
this._providers.set(provider.token, provider);
|
|
54
|
+
}
|
|
55
|
+
addController(controller) {
|
|
56
|
+
this._controllers.set(controller.token, controller);
|
|
57
|
+
}
|
|
58
|
+
addImport(module) {
|
|
59
|
+
this._imports.add(module);
|
|
60
|
+
}
|
|
61
|
+
addExport(token) {
|
|
62
|
+
this._exports.add(token);
|
|
63
|
+
}
|
|
64
|
+
hasProvider(token) {
|
|
65
|
+
return this._providers.has(token);
|
|
66
|
+
}
|
|
67
|
+
getProvider(token) {
|
|
68
|
+
return this._providers.get(token);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/injector/container.ts
|
|
73
|
+
var Container = class {
|
|
74
|
+
modules = /* @__PURE__ */ new Map();
|
|
75
|
+
globalModules = /* @__PURE__ */ new Set();
|
|
76
|
+
addModule(moduleMeta, token) {
|
|
77
|
+
if (!this.modules.has(token)) {
|
|
78
|
+
const module = new Module(moduleMeta, token);
|
|
79
|
+
this.modules.set(token, module);
|
|
80
|
+
return module;
|
|
81
|
+
}
|
|
82
|
+
return this.modules.get(token);
|
|
83
|
+
}
|
|
84
|
+
addGlobalModule(module) {
|
|
85
|
+
this.globalModules.add(module);
|
|
86
|
+
}
|
|
87
|
+
getGlobalModules() {
|
|
88
|
+
return this.globalModules;
|
|
89
|
+
}
|
|
90
|
+
getModuleByToken(token) {
|
|
91
|
+
return this.modules.get(token);
|
|
92
|
+
}
|
|
93
|
+
getModules() {
|
|
94
|
+
return this.modules;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// src/injector/context-id.ts
|
|
99
|
+
var ContextId = class _ContextId {
|
|
100
|
+
static idCounter = 0;
|
|
101
|
+
id;
|
|
102
|
+
constructor() {
|
|
103
|
+
this.id = _ContextId.idCounter++;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
new ContextId();
|
|
107
|
+
|
|
108
|
+
// src/injector/module-ref.ts
|
|
109
|
+
var ModuleRef = class {
|
|
110
|
+
};
|
|
111
|
+
var ModuleRefImpl = class extends ModuleRef {
|
|
112
|
+
constructor(container, injector, moduleRef) {
|
|
113
|
+
super();
|
|
114
|
+
this.container = container;
|
|
115
|
+
this.injector = injector;
|
|
116
|
+
this.moduleRef = moduleRef;
|
|
117
|
+
}
|
|
118
|
+
get(typeOrToken, options = { strict: true }) {
|
|
119
|
+
const token = typeOrToken;
|
|
120
|
+
let wrapper = this.moduleRef.getProvider(token);
|
|
121
|
+
if (!wrapper && !options.strict) ;
|
|
122
|
+
if (!wrapper) {
|
|
123
|
+
throw new Error(`ModuleRef cannot find provider for ${token.toString()}`);
|
|
124
|
+
}
|
|
125
|
+
if (wrapper.scope !== 0 /* DEFAULT */) {
|
|
126
|
+
throw new Error(`Cannot use get() for scoped provider ${token.toString()}. Use resolve() instead.`);
|
|
127
|
+
}
|
|
128
|
+
return wrapper.instance;
|
|
129
|
+
}
|
|
130
|
+
async resolve(typeOrToken, contextId, options = { strict: true }) {
|
|
131
|
+
const token = typeOrToken;
|
|
132
|
+
const wrapper = this.moduleRef.getProvider(token);
|
|
133
|
+
if (!wrapper) {
|
|
134
|
+
throw new Error(`ModuleRef cannot find provider for ${token.toString()}`);
|
|
135
|
+
}
|
|
136
|
+
return this.injector.loadInstance(wrapper, contextId || new ContextId());
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// src/injector/injector.ts
|
|
141
|
+
var Injector = class {
|
|
142
|
+
constructor(container) {
|
|
143
|
+
this.container = container;
|
|
144
|
+
}
|
|
145
|
+
async resolveConstructorParams(wrapper, module, inject, callback, contextId = new ContextId(), inquire = [], parentInquire = []) {
|
|
146
|
+
if (inquire.some((item) => item === wrapper) && wrapper.scope === 0 /* DEFAULT */) {
|
|
147
|
+
throw new Error(`Circular dependency detected: ${wrapper.name}`);
|
|
148
|
+
}
|
|
149
|
+
const args = [];
|
|
150
|
+
for (const [index, token] of inject.entries()) {
|
|
151
|
+
const isOptional = wrapper.isOptional ? wrapper.isOptional[index] : false;
|
|
152
|
+
const paramWrapper = await this.resolveSingleParam(token, module, contextId, [...inquire, wrapper], isOptional);
|
|
153
|
+
args.push(paramWrapper);
|
|
154
|
+
}
|
|
155
|
+
return args;
|
|
156
|
+
}
|
|
157
|
+
async resolveSingleParam(token, targetModule, contextId, inquire, isOptional = false) {
|
|
158
|
+
let isForwardRef = false;
|
|
159
|
+
if (token && token.forwardRef) {
|
|
160
|
+
token = token.forwardRef();
|
|
161
|
+
isForwardRef = true;
|
|
162
|
+
}
|
|
163
|
+
if (token === ModuleRef) {
|
|
164
|
+
return new ModuleRefImpl(this.container, this, targetModule);
|
|
165
|
+
}
|
|
166
|
+
const wrapper = this.lookupProvider(token, targetModule);
|
|
167
|
+
if (!wrapper) {
|
|
168
|
+
if (isOptional) {
|
|
169
|
+
return void 0;
|
|
170
|
+
}
|
|
171
|
+
throw new Error(`HonoDi can't resolve dependencies of the ${targetModule.metatype.name} (??). Please make sure that the argument "${token.toString()}" at index [?] is available in the ${targetModule.metatype.name} context.`);
|
|
172
|
+
}
|
|
173
|
+
if (isForwardRef) {
|
|
174
|
+
return new Proxy({}, {
|
|
175
|
+
get: (target, prop) => {
|
|
176
|
+
if (prop === "then") return void 0;
|
|
177
|
+
if (!wrapper.instance) ;
|
|
178
|
+
return wrapper.instance?.[prop];
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return this.loadInstance(wrapper, contextId, inquire);
|
|
183
|
+
}
|
|
184
|
+
lookupProvider(token, module) {
|
|
185
|
+
if (module.hasProvider(token)) {
|
|
186
|
+
return module.getProvider(token);
|
|
187
|
+
}
|
|
188
|
+
for (const importedModule of module.imports) {
|
|
189
|
+
if (importedModule.exports.has(token)) {
|
|
190
|
+
if (importedModule.hasProvider(token)) {
|
|
191
|
+
return importedModule.getProvider(token);
|
|
192
|
+
}
|
|
193
|
+
const nestedWrapper = this.lookupProvider(token, importedModule);
|
|
194
|
+
if (nestedWrapper) return nestedWrapper;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (this.container) {
|
|
198
|
+
for (const globalModule of this.container.getGlobalModules()) {
|
|
199
|
+
if (globalModule === module) continue;
|
|
200
|
+
if (globalModule.exports.has(token)) {
|
|
201
|
+
if (globalModule.hasProvider(token)) {
|
|
202
|
+
return globalModule.getProvider(token);
|
|
203
|
+
}
|
|
204
|
+
const nestedWrapper = this.lookupProvider(token, globalModule);
|
|
205
|
+
if (nestedWrapper) return nestedWrapper;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
async loadInstance(wrapper, contextId, inquire = []) {
|
|
212
|
+
if (wrapper.isResolved && wrapper.scope === 0 /* DEFAULT */) {
|
|
213
|
+
return wrapper.instance;
|
|
214
|
+
}
|
|
215
|
+
if (wrapper.scope === 2 /* REQUEST */) {
|
|
216
|
+
const existing = wrapper.getInstanceByContextId(contextId);
|
|
217
|
+
if (existing) return existing;
|
|
218
|
+
}
|
|
219
|
+
if (wrapper.isAlias) {
|
|
220
|
+
const targetToken = wrapper.useExisting;
|
|
221
|
+
const instance2 = await this.resolveSingleParam(targetToken, wrapper.host, contextId, inquire);
|
|
222
|
+
if (wrapper.scope === 0 /* DEFAULT */) {
|
|
223
|
+
wrapper.instance = instance2;
|
|
224
|
+
wrapper.isResolved = true;
|
|
225
|
+
} else {
|
|
226
|
+
wrapper.setInstanceByContextId(contextId, instance2);
|
|
227
|
+
}
|
|
228
|
+
return instance2;
|
|
229
|
+
}
|
|
230
|
+
if (wrapper.useValue !== void 0) {
|
|
231
|
+
wrapper.instance = wrapper.useValue;
|
|
232
|
+
wrapper.isResolved = true;
|
|
233
|
+
return wrapper.instance;
|
|
234
|
+
}
|
|
235
|
+
if (wrapper.useFactory) {
|
|
236
|
+
const dependencies2 = wrapper.inject || [];
|
|
237
|
+
const args = await this.resolveConstructorParams(
|
|
238
|
+
wrapper,
|
|
239
|
+
wrapper.host,
|
|
240
|
+
dependencies2,
|
|
241
|
+
(args2) => {
|
|
242
|
+
},
|
|
243
|
+
contextId,
|
|
244
|
+
inquire
|
|
245
|
+
);
|
|
246
|
+
const instance2 = await wrapper.useFactory(...args);
|
|
247
|
+
if (wrapper.scope === 0 /* DEFAULT */) {
|
|
248
|
+
wrapper.instance = instance2;
|
|
249
|
+
wrapper.isResolved = true;
|
|
250
|
+
} else {
|
|
251
|
+
wrapper.setInstanceByContextId(contextId, instance2);
|
|
252
|
+
}
|
|
253
|
+
return instance2;
|
|
254
|
+
}
|
|
255
|
+
const { metatype } = wrapper;
|
|
256
|
+
if (!metatype || typeof metatype !== "function") {
|
|
257
|
+
throw new Error("Invalid metatype");
|
|
258
|
+
}
|
|
259
|
+
let dependencies = wrapper.inject || [];
|
|
260
|
+
const constructorArgs = await this.resolveConstructorParams(
|
|
261
|
+
wrapper,
|
|
262
|
+
wrapper.host,
|
|
263
|
+
dependencies,
|
|
264
|
+
(args) => {
|
|
265
|
+
},
|
|
266
|
+
contextId,
|
|
267
|
+
inquire
|
|
268
|
+
);
|
|
269
|
+
const instance = new metatype(...constructorArgs);
|
|
270
|
+
if (wrapper.properties) {
|
|
271
|
+
for (const prop of wrapper.properties) {
|
|
272
|
+
const propInstance = await this.resolveSingleParam(
|
|
273
|
+
prop.token,
|
|
274
|
+
wrapper.host,
|
|
275
|
+
contextId,
|
|
276
|
+
inquire,
|
|
277
|
+
prop.isOptional
|
|
278
|
+
);
|
|
279
|
+
if (propInstance !== void 0) {
|
|
280
|
+
instance[prop.key] = propInstance;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (wrapper.scope === 0 /* DEFAULT */) {
|
|
285
|
+
wrapper.instance = instance;
|
|
286
|
+
wrapper.isResolved = true;
|
|
287
|
+
} else {
|
|
288
|
+
wrapper.setInstanceByContextId(contextId, instance);
|
|
289
|
+
}
|
|
290
|
+
return instance;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// src/injector/instance-wrapper.ts
|
|
295
|
+
var InstanceWrapper = class {
|
|
296
|
+
id;
|
|
297
|
+
token;
|
|
298
|
+
name;
|
|
299
|
+
metatype;
|
|
300
|
+
scope = 0 /* DEFAULT */;
|
|
301
|
+
host;
|
|
302
|
+
// Generic logic
|
|
303
|
+
inject;
|
|
304
|
+
isOptional;
|
|
305
|
+
properties;
|
|
306
|
+
instance;
|
|
307
|
+
// Singleton instance
|
|
308
|
+
instancesPerContext = /* @__PURE__ */ new Map();
|
|
309
|
+
isResolved = false;
|
|
310
|
+
isPending = false;
|
|
311
|
+
// For circular dependency detection
|
|
312
|
+
isAlias = false;
|
|
313
|
+
useFactory;
|
|
314
|
+
useValue;
|
|
315
|
+
useExisting;
|
|
316
|
+
constructor(metadata) {
|
|
317
|
+
this.token = metadata.token;
|
|
318
|
+
this.name = metadata.name;
|
|
319
|
+
this.metatype = metadata.metatype;
|
|
320
|
+
this.scope = metadata.scope ?? 0 /* DEFAULT */;
|
|
321
|
+
this.host = metadata.host;
|
|
322
|
+
this.instance = metadata.instance;
|
|
323
|
+
this.inject = metadata.inject;
|
|
324
|
+
this.useFactory = metadata.useFactory;
|
|
325
|
+
this.useValue = metadata.useValue;
|
|
326
|
+
this.useExisting = metadata.useExisting;
|
|
327
|
+
this.isAlias = !!metadata.useExisting;
|
|
328
|
+
this.isOptional = metadata.isOptional;
|
|
329
|
+
this.id = Math.random().toString(36).substring(7);
|
|
330
|
+
}
|
|
331
|
+
getInstanceByContextId(contextId) {
|
|
332
|
+
if (this.scope === 1 /* TRANSIENT */) {
|
|
333
|
+
return void 0;
|
|
334
|
+
}
|
|
335
|
+
if (this.scope === 0 /* DEFAULT */) {
|
|
336
|
+
return this.instance;
|
|
337
|
+
}
|
|
338
|
+
return this.instancesPerContext.get(contextId);
|
|
339
|
+
}
|
|
340
|
+
setInstanceByContextId(contextId, instance) {
|
|
341
|
+
if (this.scope === 0 /* DEFAULT */) {
|
|
342
|
+
this.instance = instance;
|
|
343
|
+
} else if (this.scope === 2 /* REQUEST */) {
|
|
344
|
+
this.instancesPerContext.set(contextId, instance);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
addCtorMetadata(index, token) {
|
|
348
|
+
if (!this.inject) {
|
|
349
|
+
this.inject = [];
|
|
350
|
+
}
|
|
351
|
+
this.inject[index] = token;
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// src/constants.ts
|
|
356
|
+
var METADATA_KEYS = {
|
|
357
|
+
MODULE: /* @__PURE__ */ Symbol("module"),
|
|
358
|
+
GLOBAL: /* @__PURE__ */ Symbol("global"),
|
|
359
|
+
CONTROLLER: /* @__PURE__ */ Symbol("controller"),
|
|
360
|
+
FLUSH_ROLES: /* @__PURE__ */ Symbol("flush_roles"),
|
|
361
|
+
OPTS: /* @__PURE__ */ Symbol("opts"),
|
|
362
|
+
PARAMS: /* @__PURE__ */ Symbol("params"),
|
|
363
|
+
ROUTES: /* @__PURE__ */ Symbol("routes"),
|
|
364
|
+
FILTER_CATCH: /* @__PURE__ */ Symbol("filter_catch"),
|
|
365
|
+
FILTER_EXCEPTION: /* @__PURE__ */ Symbol("filter_exception"),
|
|
366
|
+
USE_FILTERS: /* @__PURE__ */ Symbol("use_filters"),
|
|
367
|
+
USE_PIPES: /* @__PURE__ */ Symbol("use_pipes"),
|
|
368
|
+
USE_GUARDS: /* @__PURE__ */ Symbol("use_guards"),
|
|
369
|
+
USE_INTERCEPTORS: /* @__PURE__ */ Symbol("use_interceptors"),
|
|
370
|
+
ROUTE_ARGS_METADATA: /* @__PURE__ */ Symbol("route_args_metadata"),
|
|
371
|
+
INJECTIONS: /* @__PURE__ */ Symbol("injections"),
|
|
372
|
+
OPTIONAL: /* @__PURE__ */ Symbol("optional"),
|
|
373
|
+
SCOPE: /* @__PURE__ */ Symbol("scope"),
|
|
374
|
+
METHOD_INJECTIONS: /* @__PURE__ */ Symbol("method_injections"),
|
|
375
|
+
METHOD_OPTIONAL: /* @__PURE__ */ Symbol("method_optional"),
|
|
376
|
+
PROPERTY_DEPS: /* @__PURE__ */ Symbol("property_deps"),
|
|
377
|
+
HTTP_CODE: /* @__PURE__ */ Symbol("http_code"),
|
|
378
|
+
HEADERS: /* @__PURE__ */ Symbol("headers"),
|
|
379
|
+
REDIRECT: /* @__PURE__ */ Symbol("redirect")
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// src/services/logger.service.ts
|
|
383
|
+
var Logger = class _Logger {
|
|
384
|
+
static lastTimestamp;
|
|
385
|
+
static instance;
|
|
386
|
+
context;
|
|
387
|
+
constructor(context) {
|
|
388
|
+
this.context = context;
|
|
389
|
+
}
|
|
390
|
+
info(message, ...meta) {
|
|
391
|
+
const metaStr = meta.length > 0 ? ` ${JSON.stringify(meta)}` : "";
|
|
392
|
+
this.log(message + metaStr, "info");
|
|
393
|
+
}
|
|
394
|
+
static log(message, context = "") {
|
|
395
|
+
this.printMessage("log", message, context);
|
|
396
|
+
}
|
|
397
|
+
static error(message, trace = "", context = "") {
|
|
398
|
+
this.printMessage("error", message, context, trace);
|
|
399
|
+
}
|
|
400
|
+
static warn(message, context = "") {
|
|
401
|
+
this.printMessage("warn", message, context);
|
|
402
|
+
}
|
|
403
|
+
static debug(message, context = "") {
|
|
404
|
+
this.printMessage("debug", message, context);
|
|
405
|
+
}
|
|
406
|
+
static verbose(message, context = "") {
|
|
407
|
+
this.printMessage("verbose", message, context);
|
|
408
|
+
}
|
|
409
|
+
log(message, context) {
|
|
410
|
+
_Logger.log(message, context || this.context);
|
|
411
|
+
}
|
|
412
|
+
error(message, trace = "", context) {
|
|
413
|
+
_Logger.error(message, trace, context || this.context);
|
|
414
|
+
}
|
|
415
|
+
warn(message, context) {
|
|
416
|
+
_Logger.warn(message, context || this.context);
|
|
417
|
+
}
|
|
418
|
+
debug(message, context) {
|
|
419
|
+
_Logger.debug(message, context || this.context);
|
|
420
|
+
}
|
|
421
|
+
verbose(message, context) {
|
|
422
|
+
_Logger.verbose(message, context || this.context);
|
|
423
|
+
}
|
|
424
|
+
static printMessage(level, message, context = "", trace = "") {
|
|
425
|
+
const color = this.getColorByLevel(level);
|
|
426
|
+
const date = /* @__PURE__ */ new Date();
|
|
427
|
+
const timestamp = date.toLocaleString();
|
|
428
|
+
const pid = process.pid;
|
|
429
|
+
const contextMessage = context ? `[${context}] ` : "";
|
|
430
|
+
const output = message instanceof Object ? JSON.stringify(message, null, 2) : message;
|
|
431
|
+
const currentTimestamp = Date.now();
|
|
432
|
+
const timeDiff = _Logger.updateAndGetTimestampDiff(currentTimestamp);
|
|
433
|
+
const C = {
|
|
434
|
+
reset: "\x1B[0m",
|
|
435
|
+
red: "\x1B[31m",
|
|
436
|
+
green: "\x1B[32m",
|
|
437
|
+
yellow: "\x1B[33m"};
|
|
438
|
+
process.stdout.write(
|
|
439
|
+
`${C.green}[Hono] ${pid}${C.reset} - ${timestamp}${color}${level.toUpperCase().padStart(7)}${C.reset} ${C.yellow}${contextMessage}${C.reset}${C.green}${output}${C.reset} ${C.yellow}${timeDiff}${C.reset}
|
|
440
|
+
`
|
|
441
|
+
);
|
|
442
|
+
if (trace) {
|
|
443
|
+
process.stdout.write(`${C.red}${trace}${C.reset}
|
|
444
|
+
`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
static updateAndGetTimestampDiff(timestamp) {
|
|
448
|
+
let result = "";
|
|
449
|
+
if (this.lastTimestamp) {
|
|
450
|
+
result = `+${timestamp - this.lastTimestamp}ms`;
|
|
451
|
+
}
|
|
452
|
+
this.lastTimestamp = timestamp;
|
|
453
|
+
return result;
|
|
454
|
+
}
|
|
455
|
+
static getColorByLevel(level) {
|
|
456
|
+
const C = {
|
|
457
|
+
red: "\x1B[31m",
|
|
458
|
+
green: "\x1B[32m",
|
|
459
|
+
yellow: "\x1B[33m",
|
|
460
|
+
magenta: "\x1B[35m",
|
|
461
|
+
cyan: "\x1B[36m"
|
|
462
|
+
};
|
|
463
|
+
switch (level) {
|
|
464
|
+
case "debug":
|
|
465
|
+
return C.magenta;
|
|
466
|
+
case "warn":
|
|
467
|
+
return C.yellow;
|
|
468
|
+
case "error":
|
|
469
|
+
return C.red;
|
|
470
|
+
case "verbose":
|
|
471
|
+
return C.cyan;
|
|
472
|
+
default:
|
|
473
|
+
return C.green;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/scanner.ts
|
|
479
|
+
var HonoDiScanner = class {
|
|
480
|
+
constructor(container) {
|
|
481
|
+
this.container = container;
|
|
482
|
+
}
|
|
483
|
+
logger = new Logger("HonoDiScanner");
|
|
484
|
+
async scan(module) {
|
|
485
|
+
await this.scanModule(module);
|
|
486
|
+
}
|
|
487
|
+
async scanModule(moduleDefinition, scope = []) {
|
|
488
|
+
let moduleClass;
|
|
489
|
+
let dynamicMetadata = {};
|
|
490
|
+
if (moduleDefinition && "module" in moduleDefinition) {
|
|
491
|
+
moduleClass = moduleDefinition.module;
|
|
492
|
+
dynamicMetadata = moduleDefinition;
|
|
493
|
+
} else {
|
|
494
|
+
moduleClass = moduleDefinition;
|
|
495
|
+
}
|
|
496
|
+
const token = moduleClass.name;
|
|
497
|
+
if (this.container.getModuleByToken(token)) {
|
|
498
|
+
return this.container.getModuleByToken(token);
|
|
499
|
+
}
|
|
500
|
+
const moduleRef = this.container.addModule(moduleClass, token);
|
|
501
|
+
const moduleWrapper = new InstanceWrapper({
|
|
502
|
+
token: moduleClass,
|
|
503
|
+
name: moduleClass.name,
|
|
504
|
+
metatype: moduleClass,
|
|
505
|
+
host: moduleRef,
|
|
506
|
+
scope: 0 /* DEFAULT */
|
|
507
|
+
});
|
|
508
|
+
this.scanDependencies(moduleWrapper);
|
|
509
|
+
moduleRef.addProvider(moduleWrapper);
|
|
510
|
+
const decoratorOptions = Reflect.getMetadata(METADATA_KEYS.MODULE, moduleClass) || {};
|
|
511
|
+
const isGlobal = Reflect.getMetadata(METADATA_KEYS.GLOBAL, moduleClass);
|
|
512
|
+
if (isGlobal) {
|
|
513
|
+
this.container.addGlobalModule(moduleRef);
|
|
514
|
+
}
|
|
515
|
+
const options = {
|
|
516
|
+
...decoratorOptions,
|
|
517
|
+
...dynamicMetadata,
|
|
518
|
+
imports: [...decoratorOptions.imports || [], ...dynamicMetadata.imports || []],
|
|
519
|
+
providers: [...decoratorOptions.providers || [], ...dynamicMetadata.providers || []],
|
|
520
|
+
exports: [...decoratorOptions.exports || [], ...dynamicMetadata.exports || []],
|
|
521
|
+
controllers: [...decoratorOptions.controllers || [], ...dynamicMetadata.controllers || []]
|
|
522
|
+
};
|
|
523
|
+
if (options.imports) {
|
|
524
|
+
for (const importedModule of options.imports) {
|
|
525
|
+
let actualImport = importedModule;
|
|
526
|
+
if (importedModule && typeof importedModule.forwardRef === "function") {
|
|
527
|
+
actualImport = importedModule.forwardRef();
|
|
528
|
+
}
|
|
529
|
+
const importedRef = await this.scanModule(actualImport, [...scope, moduleClass]);
|
|
530
|
+
if (importedRef) {
|
|
531
|
+
moduleRef.addImport(importedRef);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (options.providers) {
|
|
536
|
+
for (const provider of options.providers) {
|
|
537
|
+
this.insertProvider(provider, moduleRef);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (options.controllers) {
|
|
541
|
+
for (const controller of options.controllers) {
|
|
542
|
+
this.insertController(controller, moduleRef);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
if (options.exports) {
|
|
546
|
+
for (const exportToken of options.exports) {
|
|
547
|
+
moduleRef.addExport(exportToken);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return moduleRef;
|
|
551
|
+
}
|
|
552
|
+
insertProvider(provider, moduleRef) {
|
|
553
|
+
provider && !provider.constructor;
|
|
554
|
+
const isPlainObject = provider && typeof provider === "object" && "provide" in provider;
|
|
555
|
+
if (!isPlainObject) {
|
|
556
|
+
const token2 = provider;
|
|
557
|
+
const wrapper2 = new InstanceWrapper({
|
|
558
|
+
token: token2,
|
|
559
|
+
name: token2.name,
|
|
560
|
+
metatype: provider,
|
|
561
|
+
host: moduleRef,
|
|
562
|
+
scope: 0 /* DEFAULT */
|
|
563
|
+
});
|
|
564
|
+
this.scanDependencies(wrapper2);
|
|
565
|
+
moduleRef.addProvider(wrapper2);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
const token = provider.provide;
|
|
569
|
+
const wrapper = new InstanceWrapper({
|
|
570
|
+
token,
|
|
571
|
+
name: token && token.name ? token.name : typeof token === "string" ? token : "CustomProvider",
|
|
572
|
+
host: moduleRef,
|
|
573
|
+
scope: provider.scope || 0 /* DEFAULT */
|
|
574
|
+
});
|
|
575
|
+
if (provider.useValue !== void 0) {
|
|
576
|
+
wrapper.useValue = provider.useValue;
|
|
577
|
+
} else if (provider.useFactory) {
|
|
578
|
+
wrapper.useFactory = provider.useFactory;
|
|
579
|
+
wrapper.inject = provider.inject || [];
|
|
580
|
+
} else if (provider.useClass) {
|
|
581
|
+
wrapper.metatype = provider.useClass;
|
|
582
|
+
this.scanDependencies(wrapper);
|
|
583
|
+
} else if (provider.useExisting) {
|
|
584
|
+
wrapper.useExisting = provider.useExisting;
|
|
585
|
+
wrapper.isAlias = true;
|
|
586
|
+
}
|
|
587
|
+
moduleRef.addProvider(wrapper);
|
|
588
|
+
}
|
|
589
|
+
insertController(controller, moduleRef) {
|
|
590
|
+
const token = controller;
|
|
591
|
+
const wrapper = new InstanceWrapper({
|
|
592
|
+
token,
|
|
593
|
+
name: token.name,
|
|
594
|
+
metatype: controller,
|
|
595
|
+
host: moduleRef,
|
|
596
|
+
scope: 0 /* DEFAULT */
|
|
597
|
+
});
|
|
598
|
+
this.scanDependencies(wrapper);
|
|
599
|
+
moduleRef.addController(wrapper);
|
|
600
|
+
}
|
|
601
|
+
scanDependencies(wrapper) {
|
|
602
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", wrapper.metatype) || [];
|
|
603
|
+
const injections = Reflect.getMetadata(METADATA_KEYS.INJECTIONS, wrapper.metatype) || [];
|
|
604
|
+
const optionals = Reflect.getMetadata(METADATA_KEYS.OPTIONAL, wrapper.metatype) || [];
|
|
605
|
+
const mergedInject = [];
|
|
606
|
+
const mergedOptional = [];
|
|
607
|
+
for (let i = 0; i < paramTypes.length; i++) {
|
|
608
|
+
mergedInject[i] = injections[i] || paramTypes[i];
|
|
609
|
+
mergedOptional[i] = optionals[i] || false;
|
|
610
|
+
}
|
|
611
|
+
wrapper.inject = mergedInject;
|
|
612
|
+
wrapper.isOptional = mergedOptional;
|
|
613
|
+
const propertyDeps = Reflect.getMetadata(METADATA_KEYS.PROPERTY_DEPS, wrapper.metatype) || [];
|
|
614
|
+
const optionalProps = Reflect.getMetadata(METADATA_KEYS.OPTIONAL, wrapper.metatype) || [];
|
|
615
|
+
wrapper.properties = propertyDeps.map((dep) => {
|
|
616
|
+
return {
|
|
617
|
+
key: dep.key,
|
|
618
|
+
token: dep.token,
|
|
619
|
+
isOptional: optionalProps.includes(dep.key)
|
|
620
|
+
};
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
// src/execution-context-host.ts
|
|
626
|
+
var ExecutionContextHost = class {
|
|
627
|
+
args;
|
|
628
|
+
constructorRef;
|
|
629
|
+
handler;
|
|
630
|
+
context;
|
|
631
|
+
next;
|
|
632
|
+
constructor(args, constructorRef, handler) {
|
|
633
|
+
this.args = args;
|
|
634
|
+
this.constructorRef = constructorRef;
|
|
635
|
+
this.handler = handler;
|
|
636
|
+
this.context = args[0];
|
|
637
|
+
this.next = args[1];
|
|
638
|
+
}
|
|
639
|
+
getClass() {
|
|
640
|
+
return this.constructorRef;
|
|
641
|
+
}
|
|
642
|
+
getHandler() {
|
|
643
|
+
return this.handler;
|
|
644
|
+
}
|
|
645
|
+
getArgs() {
|
|
646
|
+
return this.args;
|
|
647
|
+
}
|
|
648
|
+
getType() {
|
|
649
|
+
return "http";
|
|
650
|
+
}
|
|
651
|
+
switchToHttp() {
|
|
652
|
+
return {
|
|
653
|
+
getRequest: () => this.context.req,
|
|
654
|
+
getResponse: () => this.context,
|
|
655
|
+
getNext: () => this.next ?? (() => Promise.resolve()),
|
|
656
|
+
getContext: () => this.context
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
function Injectable(options) {
|
|
661
|
+
return (target) => {
|
|
662
|
+
Reflect.defineMetadata(METADATA_KEYS.SCOPE, 0 /* DEFAULT */, target);
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function Catch(...exceptions) {
|
|
666
|
+
return (target) => {
|
|
667
|
+
Reflect.defineMetadata(METADATA_KEYS.FILTER_CATCH, exceptions, target);
|
|
668
|
+
Reflect.defineMetadata(METADATA_KEYS.SCOPE, 0 /* DEFAULT */, target);
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// src/middleware/builder.ts
|
|
673
|
+
var MiddlewareBuilder = class {
|
|
674
|
+
constructor(module) {
|
|
675
|
+
this.module = module;
|
|
676
|
+
}
|
|
677
|
+
configs = [];
|
|
678
|
+
apply(...middleware) {
|
|
679
|
+
return new MiddlewareConfigProxyImpl(this, middleware);
|
|
680
|
+
}
|
|
681
|
+
addConfig(middleware, routes, excludes = []) {
|
|
682
|
+
this.configs.push({
|
|
683
|
+
middleware,
|
|
684
|
+
routes,
|
|
685
|
+
excludes,
|
|
686
|
+
module: this.module
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
getConfigs() {
|
|
690
|
+
return this.configs;
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
var MiddlewareConfigProxyImpl = class {
|
|
694
|
+
constructor(builder, middleware) {
|
|
695
|
+
this.builder = builder;
|
|
696
|
+
this.middleware = middleware;
|
|
697
|
+
}
|
|
698
|
+
excludes = [];
|
|
699
|
+
exclude(...routes) {
|
|
700
|
+
this.excludes = routes;
|
|
701
|
+
return this;
|
|
702
|
+
}
|
|
703
|
+
forRoutes(...routes) {
|
|
704
|
+
this.builder.addConfig(this.middleware, routes, this.excludes);
|
|
705
|
+
return this.builder;
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
// src/common/exceptions/http.exception.ts
|
|
710
|
+
var HttpException = class extends Error {
|
|
711
|
+
constructor(response, status) {
|
|
712
|
+
super();
|
|
713
|
+
this.response = response;
|
|
714
|
+
this.status = status;
|
|
715
|
+
this.message = typeof response === "string" ? response : JSON.stringify(response);
|
|
716
|
+
}
|
|
717
|
+
getResponse() {
|
|
718
|
+
return this.response;
|
|
719
|
+
}
|
|
720
|
+
getStatus() {
|
|
721
|
+
return this.status;
|
|
722
|
+
}
|
|
723
|
+
static createBody(message, error, statusCode) {
|
|
724
|
+
if (!message) {
|
|
725
|
+
return { statusCode, error };
|
|
726
|
+
}
|
|
727
|
+
return typeof message === "object" && !Array.isArray(message) ? message : { statusCode, error, message };
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
// src/common/exceptions/index.ts
|
|
732
|
+
var BadRequestException = class extends HttpException {
|
|
733
|
+
constructor(message, error = "Bad Request") {
|
|
734
|
+
super(HttpException.createBody(message, error, 400), 400);
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
var UnauthorizedException = class extends HttpException {
|
|
738
|
+
constructor(message, error = "Unauthorized") {
|
|
739
|
+
super(HttpException.createBody(message, error, 401), 401);
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
var NotFoundException = class extends HttpException {
|
|
743
|
+
constructor(message, error = "Not Found") {
|
|
744
|
+
super(HttpException.createBody(message, error, 404), 404);
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
var ForbiddenException = class extends HttpException {
|
|
748
|
+
constructor(message, error = "Forbidden") {
|
|
749
|
+
super(HttpException.createBody(message, error, 403), 403);
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
var NotAcceptableException = class extends HttpException {
|
|
753
|
+
constructor(message, error = "Not Acceptable") {
|
|
754
|
+
super(HttpException.createBody(message, error, 406), 406);
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
var RequestTimeoutException = class extends HttpException {
|
|
758
|
+
constructor(message, error = "Request Timeout") {
|
|
759
|
+
super(HttpException.createBody(message, error, 408), 408);
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
var ConflictException = class extends HttpException {
|
|
763
|
+
constructor(message, error = "Conflict") {
|
|
764
|
+
super(HttpException.createBody(message, error, 409), 409);
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
var GoneException = class extends HttpException {
|
|
768
|
+
constructor(message, error = "Gone") {
|
|
769
|
+
super(HttpException.createBody(message, error, 410), 410);
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
var PayloadTooLargeException = class extends HttpException {
|
|
773
|
+
constructor(message, error = "Payload Too Large") {
|
|
774
|
+
super(HttpException.createBody(message, error, 413), 413);
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
var UnsupportedMediaTypeException = class extends HttpException {
|
|
778
|
+
constructor(message, error = "Unsupported Media Type") {
|
|
779
|
+
super(HttpException.createBody(message, error, 415), 415);
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
var UnprocessableEntityException = class extends HttpException {
|
|
783
|
+
constructor(message, error = "Unprocessable Entity") {
|
|
784
|
+
super(HttpException.createBody(message, error, 422), 422);
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
var InternalServerErrorException = class extends HttpException {
|
|
788
|
+
constructor(message, error = "Internal Server Error") {
|
|
789
|
+
super(HttpException.createBody(message, error, 500), 500);
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
var NotImplementedException = class extends HttpException {
|
|
793
|
+
constructor(message, error = "Not Implemented") {
|
|
794
|
+
super(HttpException.createBody(message, error, 501), 501);
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
var BadGatewayException = class extends HttpException {
|
|
798
|
+
constructor(message, error = "Bad Gateway") {
|
|
799
|
+
super(HttpException.createBody(message, error, 502), 502);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
var ServiceUnavailableException = class extends HttpException {
|
|
803
|
+
constructor(message, error = "Service Unavailable") {
|
|
804
|
+
super(HttpException.createBody(message, error, 503), 503);
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
var GatewayTimeoutException = class extends HttpException {
|
|
808
|
+
constructor(message, error = "Gateway Timeout") {
|
|
809
|
+
super(HttpException.createBody(message, error, 504), 504);
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
// src/application.ts
|
|
814
|
+
var HonoDiApplication = class {
|
|
815
|
+
constructor(app, container, injector) {
|
|
816
|
+
this.app = app;
|
|
817
|
+
this.container = container;
|
|
818
|
+
this.injector = injector;
|
|
819
|
+
}
|
|
820
|
+
globalFilters = [];
|
|
821
|
+
globalPipes = [];
|
|
822
|
+
globalGuards = [];
|
|
823
|
+
globalInterceptors = [];
|
|
824
|
+
useGlobalFilters(...filters) {
|
|
825
|
+
this.globalFilters.push(...filters);
|
|
826
|
+
return this;
|
|
827
|
+
}
|
|
828
|
+
useGlobalPipes(...pipes) {
|
|
829
|
+
this.globalPipes.push(...pipes);
|
|
830
|
+
return this;
|
|
831
|
+
}
|
|
832
|
+
useGlobalInterceptors(...interceptors) {
|
|
833
|
+
this.globalInterceptors.push(...interceptors);
|
|
834
|
+
return this;
|
|
835
|
+
}
|
|
836
|
+
useGlobalGuards(...guards) {
|
|
837
|
+
this.globalGuards.push(...guards);
|
|
838
|
+
return this;
|
|
839
|
+
}
|
|
840
|
+
globalPrefix = "";
|
|
841
|
+
setGlobalPrefix(prefix) {
|
|
842
|
+
if (this.isInitialized) {
|
|
843
|
+
this.logger.warn("Setting global prefix after initialization will not affect existing routes. Use { autoInit: false } in HonoDiFactory.create() if you need to set a prefix.");
|
|
844
|
+
}
|
|
845
|
+
this.globalPrefix = prefix;
|
|
846
|
+
return this;
|
|
847
|
+
}
|
|
848
|
+
getGlobalPrefix() {
|
|
849
|
+
return this.globalPrefix;
|
|
850
|
+
}
|
|
851
|
+
logger = new Logger("HonoDiApplication");
|
|
852
|
+
isInitialized = false;
|
|
853
|
+
async init() {
|
|
854
|
+
if (this.isInitialized) return this;
|
|
855
|
+
this.logger.log("Initializing middleware...");
|
|
856
|
+
await this.initializeMiddleware();
|
|
857
|
+
this.logger.log("Registering controllers...");
|
|
858
|
+
this.registerControllersFromContainer();
|
|
859
|
+
this.logger.log("Calling OnApplicationBootstrap...");
|
|
860
|
+
await this.callLifecycleHook("onApplicationBootstrap");
|
|
861
|
+
this.isInitialized = true;
|
|
862
|
+
return this;
|
|
863
|
+
}
|
|
864
|
+
async listen(port, callback) {
|
|
865
|
+
if (!this.isInitialized) await this.init();
|
|
866
|
+
const server = Bun.serve({
|
|
867
|
+
port: Number(port),
|
|
868
|
+
fetch: this.app.fetch
|
|
869
|
+
});
|
|
870
|
+
if (callback) callback();
|
|
871
|
+
return server;
|
|
872
|
+
}
|
|
873
|
+
async callLifecycleHook(hook) {
|
|
874
|
+
const modules = this.container.getModules();
|
|
875
|
+
for (const module of modules.values()) {
|
|
876
|
+
for (const wrapper of module.providers.values()) {
|
|
877
|
+
if (wrapper.instance && wrapper.instance[hook]) {
|
|
878
|
+
await wrapper.instance[hook]();
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
for (const wrapper of module.controllers.values()) {
|
|
882
|
+
if (wrapper.instance && wrapper.instance[hook]) {
|
|
883
|
+
await wrapper.instance[hook]();
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
registerControllersFromContainer() {
|
|
889
|
+
const modules = this.container.getModules();
|
|
890
|
+
modules.forEach((module) => {
|
|
891
|
+
module.controllers.forEach((wrapper) => {
|
|
892
|
+
this.registerControllerRoutes(wrapper.metatype, this.app, module);
|
|
893
|
+
});
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
registerControllerRoutes(controllerClass, app, moduleRef) {
|
|
897
|
+
if (!Reflect.hasMetadata(METADATA_KEYS.CONTROLLER, controllerClass)) {
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
const { prefix } = Reflect.getMetadata(METADATA_KEYS.CONTROLLER, controllerClass);
|
|
901
|
+
const routes = Reflect.getMetadata(METADATA_KEYS.ROUTES, controllerClass);
|
|
902
|
+
if (!routes) return;
|
|
903
|
+
routes.forEach((route) => {
|
|
904
|
+
const globalPrefix = this.getGlobalPrefix();
|
|
905
|
+
const fullPath = this.combinePaths(globalPrefix, this.combinePaths(prefix, route.path));
|
|
906
|
+
app[route.requestMethod](fullPath, async (c) => {
|
|
907
|
+
const contextId = new ContextId();
|
|
908
|
+
const executionContext = new ExecutionContextHost([c], controllerClass, controllerClass.prototype[route.methodName]);
|
|
909
|
+
try {
|
|
910
|
+
const wrapper = moduleRef.getProvider(controllerClass) || moduleRef.controllers.get(controllerClass);
|
|
911
|
+
if (!wrapper) {
|
|
912
|
+
throw new Error(`Controller ${controllerClass.name} not found in module ${moduleRef.metatype.name}`);
|
|
913
|
+
}
|
|
914
|
+
const controllerInstance = await this.injector.loadInstance(wrapper, contextId);
|
|
915
|
+
const handler = controllerInstance[route.methodName].bind(controllerInstance);
|
|
916
|
+
const guards = await this.resolveContextItems(
|
|
917
|
+
[
|
|
918
|
+
...this.globalGuards,
|
|
919
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_GUARDS, controllerClass) || [],
|
|
920
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_GUARDS, controllerInstance[route.methodName]) || []
|
|
921
|
+
],
|
|
922
|
+
moduleRef,
|
|
923
|
+
contextId
|
|
924
|
+
);
|
|
925
|
+
if (!await this.runGuards(guards, executionContext)) {
|
|
926
|
+
c.status(403);
|
|
927
|
+
return c.json({ statusCode: 403, message: "Forbidden resource" });
|
|
928
|
+
}
|
|
929
|
+
const interceptors = await this.resolveContextItems(
|
|
930
|
+
[
|
|
931
|
+
...this.globalInterceptors,
|
|
932
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_INTERCEPTORS, controllerClass) || [],
|
|
933
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_INTERCEPTORS, controllerInstance[route.methodName]) || []
|
|
934
|
+
],
|
|
935
|
+
moduleRef,
|
|
936
|
+
contextId
|
|
937
|
+
);
|
|
938
|
+
const pipes = await this.resolveContextItems(
|
|
939
|
+
[
|
|
940
|
+
...this.globalPipes,
|
|
941
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_PIPES, controllerClass) || [],
|
|
942
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_PIPES, controllerInstance[route.methodName]) || []
|
|
943
|
+
],
|
|
944
|
+
moduleRef,
|
|
945
|
+
contextId
|
|
946
|
+
);
|
|
947
|
+
const args = await this.resolveArgs(
|
|
948
|
+
contextId,
|
|
949
|
+
executionContext,
|
|
950
|
+
controllerClass,
|
|
951
|
+
route.methodName,
|
|
952
|
+
moduleRef,
|
|
953
|
+
pipes
|
|
954
|
+
);
|
|
955
|
+
if (args.length === 0 && !Reflect.hasMetadata(METADATA_KEYS.ROUTE_ARGS_METADATA, controllerClass, route.methodName)) {
|
|
956
|
+
args.push(c);
|
|
957
|
+
}
|
|
958
|
+
const interceptorChain = async (index) => {
|
|
959
|
+
if (index >= interceptors.length) {
|
|
960
|
+
return new rxjs.Observable((subscriber) => {
|
|
961
|
+
try {
|
|
962
|
+
const result2 = handler(...args);
|
|
963
|
+
if (result2 instanceof Promise) {
|
|
964
|
+
result2.then((data) => {
|
|
965
|
+
subscriber.next(data);
|
|
966
|
+
subscriber.complete();
|
|
967
|
+
}).catch((err) => subscriber.error(err));
|
|
968
|
+
} else {
|
|
969
|
+
subscriber.next(result2);
|
|
970
|
+
subscriber.complete();
|
|
971
|
+
}
|
|
972
|
+
} catch (err) {
|
|
973
|
+
subscriber.error(err);
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
return interceptors[index].intercept(executionContext, {
|
|
978
|
+
handle: () => rxjs.from(interceptorChain(index + 1)).pipe(operators.mergeMap((obs2) => obs2))
|
|
979
|
+
});
|
|
980
|
+
};
|
|
981
|
+
const obs = await interceptorChain(0);
|
|
982
|
+
const result = await rxjs.lastValueFrom(obs);
|
|
983
|
+
const httpCode = Reflect.getMetadata(METADATA_KEYS.HTTP_CODE, controllerInstance[route.methodName]);
|
|
984
|
+
if (httpCode) {
|
|
985
|
+
c.status(httpCode);
|
|
986
|
+
}
|
|
987
|
+
const headers = Reflect.getMetadata(METADATA_KEYS.HEADERS, controllerInstance[route.methodName]);
|
|
988
|
+
if (headers) {
|
|
989
|
+
headers.forEach((h) => c.header(h.name, h.value));
|
|
990
|
+
}
|
|
991
|
+
const redirect = Reflect.getMetadata(METADATA_KEYS.REDIRECT, controllerInstance[route.methodName]);
|
|
992
|
+
if (redirect) {
|
|
993
|
+
if (result && typeof result === "object" && result.url) {
|
|
994
|
+
return c.redirect(result.url, result.statusCode || redirect.statusCode);
|
|
995
|
+
}
|
|
996
|
+
return c.redirect(redirect.url, redirect.statusCode);
|
|
997
|
+
}
|
|
998
|
+
if (result instanceof Response) {
|
|
999
|
+
return result;
|
|
1000
|
+
}
|
|
1001
|
+
if (result && typeof result.text === "function" && typeof result.headers === "object") {
|
|
1002
|
+
return result;
|
|
1003
|
+
}
|
|
1004
|
+
return c.json(result);
|
|
1005
|
+
} catch (exception) {
|
|
1006
|
+
return await this.handleException(exception, c, controllerClass, route.methodName, moduleRef, contextId);
|
|
1007
|
+
}
|
|
1008
|
+
});
|
|
1009
|
+
this.logger.log(`[Route] Mapped {${fullPath}, ${route.requestMethod.toUpperCase()}}`);
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
async handleException(exception, c, controllerClass, methodName, moduleRef, contextId) {
|
|
1013
|
+
const filters = await this.resolveContextItems(
|
|
1014
|
+
[
|
|
1015
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_FILTERS, moduleRef.controllers.get(controllerClass)?.instance?.[methodName]) || [],
|
|
1016
|
+
...Reflect.getMetadata(METADATA_KEYS.USE_FILTERS, controllerClass) || [],
|
|
1017
|
+
...this.globalFilters
|
|
1018
|
+
],
|
|
1019
|
+
moduleRef,
|
|
1020
|
+
contextId
|
|
1021
|
+
);
|
|
1022
|
+
for (const filter of filters) {
|
|
1023
|
+
const catchExceptions = Reflect.getMetadata(METADATA_KEYS.FILTER_CATCH, filter.constructor) || [];
|
|
1024
|
+
if (catchExceptions.length === 0 || catchExceptions.some((e) => exception instanceof e)) {
|
|
1025
|
+
const host = new ExecutionContextHost([c], controllerClass, moduleRef.controllers.get(controllerClass)?.instance?.[methodName]);
|
|
1026
|
+
return await filter.catch(exception, host);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
this.logger.error(exception);
|
|
1030
|
+
if (exception instanceof HttpException) {
|
|
1031
|
+
const status = exception.getStatus();
|
|
1032
|
+
const response = exception.getResponse();
|
|
1033
|
+
c.status(status);
|
|
1034
|
+
return c.json(response);
|
|
1035
|
+
}
|
|
1036
|
+
if (exception instanceof Error) {
|
|
1037
|
+
c.status(500);
|
|
1038
|
+
return c.json({
|
|
1039
|
+
statusCode: 500,
|
|
1040
|
+
message: "Internal Server Error",
|
|
1041
|
+
cause: exception.message
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
async resolveContextItems(items, moduleRef, contextId) {
|
|
1046
|
+
const instances = [];
|
|
1047
|
+
const scanner = new HonoDiScanner(this.container);
|
|
1048
|
+
for (const item of items) {
|
|
1049
|
+
if (typeof item === "function") {
|
|
1050
|
+
let wrapper = moduleRef.getProvider(item);
|
|
1051
|
+
if (!wrapper) {
|
|
1052
|
+
wrapper = new InstanceWrapper({
|
|
1053
|
+
token: item,
|
|
1054
|
+
name: item.name,
|
|
1055
|
+
metatype: item,
|
|
1056
|
+
host: moduleRef,
|
|
1057
|
+
scope: 1 /* TRANSIENT */
|
|
1058
|
+
});
|
|
1059
|
+
scanner.scanDependencies(wrapper);
|
|
1060
|
+
}
|
|
1061
|
+
const instance = await this.injector.loadInstance(wrapper, contextId);
|
|
1062
|
+
instances.push(instance);
|
|
1063
|
+
} else {
|
|
1064
|
+
instances.push(item);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
return instances;
|
|
1068
|
+
}
|
|
1069
|
+
async resolveArgs(contextId, context, controller, methodName, moduleRef, methodPipes = []) {
|
|
1070
|
+
const argsMetadata = Reflect.getMetadata(METADATA_KEYS.ROUTE_ARGS_METADATA, controller, methodName) || {};
|
|
1071
|
+
const args = [];
|
|
1072
|
+
const c = context.getArgs()[0];
|
|
1073
|
+
const sortedArgs = Object.values(argsMetadata).sort((a, b) => a.index - b.index);
|
|
1074
|
+
for (const arg of sortedArgs) {
|
|
1075
|
+
let value;
|
|
1076
|
+
const { index, data, pipes, paramtype } = arg;
|
|
1077
|
+
switch (paramtype) {
|
|
1078
|
+
case 0 /* REQUEST */:
|
|
1079
|
+
value = c.req;
|
|
1080
|
+
break;
|
|
1081
|
+
case 1 /* RESPONSE */:
|
|
1082
|
+
value = c;
|
|
1083
|
+
break;
|
|
1084
|
+
case 2 /* NEXT */:
|
|
1085
|
+
value = context.getArgs()[1];
|
|
1086
|
+
break;
|
|
1087
|
+
case 12 /* CONTEXT */:
|
|
1088
|
+
value = c;
|
|
1089
|
+
break;
|
|
1090
|
+
case 3 /* BODY */:
|
|
1091
|
+
if (data && c.req.parseBody) {
|
|
1092
|
+
const body = await c.req.parseBody();
|
|
1093
|
+
value = body[data];
|
|
1094
|
+
} else {
|
|
1095
|
+
try {
|
|
1096
|
+
const body = await c.req.json();
|
|
1097
|
+
value = data ? body[data] : body;
|
|
1098
|
+
} catch (e) {
|
|
1099
|
+
value = null;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
break;
|
|
1103
|
+
case 4 /* QUERY */:
|
|
1104
|
+
value = data ? c.req.query(data) : c.req.query();
|
|
1105
|
+
break;
|
|
1106
|
+
case 5 /* PARAM */:
|
|
1107
|
+
value = data ? c.req.param(data) : c.req.param();
|
|
1108
|
+
break;
|
|
1109
|
+
case 6 /* HEADERS */:
|
|
1110
|
+
value = data ? c.req.header(data) : c.req.header();
|
|
1111
|
+
break;
|
|
1112
|
+
case 11 /* IP */:
|
|
1113
|
+
value = c.req.header("x-forwarded-for") || "127.0.0.1";
|
|
1114
|
+
break;
|
|
1115
|
+
case 13 /* CUSTOM */:
|
|
1116
|
+
const factory = arg.pipes[0];
|
|
1117
|
+
if (typeof factory === "function") {
|
|
1118
|
+
value = factory(data, context);
|
|
1119
|
+
}
|
|
1120
|
+
break;
|
|
1121
|
+
default:
|
|
1122
|
+
value = null;
|
|
1123
|
+
}
|
|
1124
|
+
const paramPipeInstances = await this.resolveContextItems(pipes || [], moduleRef, contextId);
|
|
1125
|
+
const allPipes = [...methodPipes, ...paramPipeInstances];
|
|
1126
|
+
for (const pipe of allPipes) {
|
|
1127
|
+
value = await pipe.transform(value, { type: "custom", metatype: null, data });
|
|
1128
|
+
}
|
|
1129
|
+
args[index] = value;
|
|
1130
|
+
}
|
|
1131
|
+
return args;
|
|
1132
|
+
}
|
|
1133
|
+
async runGuards(guards, context) {
|
|
1134
|
+
for (const guard of guards) {
|
|
1135
|
+
const result = await guard.canActivate(context);
|
|
1136
|
+
if (!result) return false;
|
|
1137
|
+
}
|
|
1138
|
+
return true;
|
|
1139
|
+
}
|
|
1140
|
+
async initializeMiddleware() {
|
|
1141
|
+
const configs = [];
|
|
1142
|
+
const modules = this.container.getModules();
|
|
1143
|
+
for (const module of modules.values()) {
|
|
1144
|
+
const moduleClass = module.metatype;
|
|
1145
|
+
const wrapper = module.getProvider(moduleClass);
|
|
1146
|
+
if (wrapper && wrapper.instance && wrapper.instance.configure) {
|
|
1147
|
+
const builder = new MiddlewareBuilder(module);
|
|
1148
|
+
wrapper.instance.configure(builder);
|
|
1149
|
+
configs.push(...builder.getConfigs());
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
if (configs.length === 0) return;
|
|
1153
|
+
const resolvedConfigs = [];
|
|
1154
|
+
const globalContextId = new ContextId();
|
|
1155
|
+
for (const config of configs) {
|
|
1156
|
+
const instances = [];
|
|
1157
|
+
for (const m of config.middleware) {
|
|
1158
|
+
if (typeof m === "function" && !m.prototype?.use) {
|
|
1159
|
+
instances.push(m);
|
|
1160
|
+
} else {
|
|
1161
|
+
const wrapper = new InstanceWrapper({
|
|
1162
|
+
token: m,
|
|
1163
|
+
name: m.name,
|
|
1164
|
+
metatype: m,
|
|
1165
|
+
scope: 1 /* TRANSIENT */
|
|
1166
|
+
});
|
|
1167
|
+
const scanner = new HonoDiScanner(this.container);
|
|
1168
|
+
scanner.scanDependencies(wrapper);
|
|
1169
|
+
const hostModule = config.module || modules.values().next().value;
|
|
1170
|
+
wrapper.host = hostModule;
|
|
1171
|
+
const instance = await this.injector.loadInstance(wrapper, globalContextId);
|
|
1172
|
+
instances.push(instance);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
resolvedConfigs.push({ ...config, instances });
|
|
1176
|
+
}
|
|
1177
|
+
this.app.use("*", async (c, next) => {
|
|
1178
|
+
const path = c.req.path;
|
|
1179
|
+
const method = c.req.method;
|
|
1180
|
+
const matchingMiddleware = [];
|
|
1181
|
+
for (const config of resolvedConfigs) {
|
|
1182
|
+
if (this.isRouteExcluded(config.excludes, path, method)) continue;
|
|
1183
|
+
if (this.isRouteMatch(config.routes, path, method)) {
|
|
1184
|
+
matchingMiddleware.push(...config.instances);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
if (matchingMiddleware.length === 0) {
|
|
1188
|
+
return await next();
|
|
1189
|
+
}
|
|
1190
|
+
const executeChain = async (index, finalNext) => {
|
|
1191
|
+
if (index >= matchingMiddleware.length) {
|
|
1192
|
+
return await finalNext();
|
|
1193
|
+
}
|
|
1194
|
+
const middleware = matchingMiddleware[index];
|
|
1195
|
+
return new Promise((resolve, reject) => {
|
|
1196
|
+
let nextCalled = false;
|
|
1197
|
+
const nextFn = async () => {
|
|
1198
|
+
nextCalled = true;
|
|
1199
|
+
try {
|
|
1200
|
+
await executeChain(index + 1, finalNext);
|
|
1201
|
+
resolve();
|
|
1202
|
+
} catch (e) {
|
|
1203
|
+
reject(e);
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
try {
|
|
1207
|
+
const useFn = middleware.use ? middleware.use.bind(middleware) : middleware;
|
|
1208
|
+
const result = useFn(c, nextFn);
|
|
1209
|
+
if (result instanceof Promise) {
|
|
1210
|
+
result.then(() => {
|
|
1211
|
+
if (!nextCalled) resolve();
|
|
1212
|
+
}).catch(reject);
|
|
1213
|
+
} else {
|
|
1214
|
+
if (!nextCalled) resolve();
|
|
1215
|
+
}
|
|
1216
|
+
} catch (e) {
|
|
1217
|
+
reject(e);
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
};
|
|
1221
|
+
await executeChain(0, next);
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
isRouteMatch(routes, path, method) {
|
|
1225
|
+
for (const route of routes) {
|
|
1226
|
+
if (typeof route === "string") {
|
|
1227
|
+
const normalizedRoute = route === "*" ? "*" : route.startsWith("/") ? route : `/${route}`;
|
|
1228
|
+
if (normalizedRoute === "*" || path.startsWith(normalizedRoute)) return true;
|
|
1229
|
+
if (path === normalizedRoute) return true;
|
|
1230
|
+
} else if (typeof route === "object" && route.path && route.method) {
|
|
1231
|
+
if (route.method !== -1 && route.method !== "all" /* ALL */ && route.method !== method.toLowerCase()) {
|
|
1232
|
+
continue;
|
|
1233
|
+
}
|
|
1234
|
+
if (route.path === "*" || path === route.path) return true;
|
|
1235
|
+
} else if (typeof route === "function") {
|
|
1236
|
+
const prefix = Reflect.getMetadata(METADATA_KEYS.CONTROLLER, route)?.prefix || "";
|
|
1237
|
+
if (path.startsWith(this.combinePaths(prefix, ""))) return true;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
return false;
|
|
1241
|
+
}
|
|
1242
|
+
isRouteExcluded(routes, path, method) {
|
|
1243
|
+
return this.isRouteMatch(routes, path, method);
|
|
1244
|
+
}
|
|
1245
|
+
combinePaths(prefix, path) {
|
|
1246
|
+
const cleanPrefix = prefix ? prefix.replace(/^\/+/, "").replace(/\/+$/, "") : "";
|
|
1247
|
+
const cleanPath = path ? path.replace(/^\/+/, "").replace(/\/+$/, "") : "";
|
|
1248
|
+
let result = "";
|
|
1249
|
+
if (cleanPrefix) result += `/${cleanPrefix}`;
|
|
1250
|
+
if (cleanPath) result += `/${cleanPath}`;
|
|
1251
|
+
return result || "/";
|
|
1252
|
+
}
|
|
1253
|
+
getHttpAdapter() {
|
|
1254
|
+
return this.app;
|
|
1255
|
+
}
|
|
1256
|
+
get(typeOrToken, options) {
|
|
1257
|
+
const modules = this.container.getModules();
|
|
1258
|
+
for (const module of modules.values()) {
|
|
1259
|
+
const provider = module.getProvider(typeOrToken);
|
|
1260
|
+
if (provider && provider.instance) {
|
|
1261
|
+
return provider.instance;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
throw new Error(`Provider ${String(typeOrToken)} not found`);
|
|
1265
|
+
}
|
|
1266
|
+
async close() {
|
|
1267
|
+
}
|
|
1268
|
+
// Getters for global items (internal use)
|
|
1269
|
+
getGlobalFilters() {
|
|
1270
|
+
return this.globalFilters;
|
|
1271
|
+
}
|
|
1272
|
+
getGlobalPipes() {
|
|
1273
|
+
return this.globalPipes;
|
|
1274
|
+
}
|
|
1275
|
+
getGlobalGuards() {
|
|
1276
|
+
return this.globalGuards;
|
|
1277
|
+
}
|
|
1278
|
+
getGlobalInterceptors() {
|
|
1279
|
+
return this.globalInterceptors;
|
|
1280
|
+
}
|
|
1281
|
+
getContainer() {
|
|
1282
|
+
return this.container;
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1285
|
+
|
|
1286
|
+
// src/factory.ts
|
|
1287
|
+
var HonoDiFactory = class {
|
|
1288
|
+
static logger = new Logger("HonoDiFactory");
|
|
1289
|
+
static async create(rootModule, appOrOptions) {
|
|
1290
|
+
let app;
|
|
1291
|
+
let autoInit = true;
|
|
1292
|
+
if (appOrOptions && "fetch" in appOrOptions && typeof appOrOptions.fetch === "function") {
|
|
1293
|
+
app = appOrOptions;
|
|
1294
|
+
} else if (appOrOptions) {
|
|
1295
|
+
const options = appOrOptions;
|
|
1296
|
+
app = options.app;
|
|
1297
|
+
if (options.autoInit !== void 0) {
|
|
1298
|
+
autoInit = options.autoInit;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
const container = new Container();
|
|
1302
|
+
const scanner = new HonoDiScanner(container);
|
|
1303
|
+
const injector = new Injector(container);
|
|
1304
|
+
const honoApp = app || new hono.Hono();
|
|
1305
|
+
const bunApp = new HonoDiApplication(honoApp, container, injector);
|
|
1306
|
+
this.logger.log("Scanning modules...");
|
|
1307
|
+
await scanner.scan(rootModule);
|
|
1308
|
+
this.logger.log("Instantiating providers...");
|
|
1309
|
+
await this.instantiateProviders(container, injector);
|
|
1310
|
+
this.logger.log("Calling OnModuleInit...");
|
|
1311
|
+
await this.callLifecycleHook("onModuleInit", container);
|
|
1312
|
+
if (autoInit) {
|
|
1313
|
+
await bunApp.init();
|
|
1314
|
+
}
|
|
1315
|
+
return bunApp;
|
|
1316
|
+
}
|
|
1317
|
+
static async instantiateProviders(container, injector) {
|
|
1318
|
+
const modules = container.getModules();
|
|
1319
|
+
const globalContextId = new ContextId();
|
|
1320
|
+
for (const module of modules.values()) {
|
|
1321
|
+
for (const wrapper of module.providers.values()) {
|
|
1322
|
+
if (wrapper.scope === 0 /* DEFAULT */) {
|
|
1323
|
+
await injector.loadInstance(wrapper, globalContextId);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
for (const wrapper of module.controllers.values()) {
|
|
1327
|
+
if (wrapper.scope === 0 /* DEFAULT */) {
|
|
1328
|
+
await injector.loadInstance(wrapper, globalContextId);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
static async callLifecycleHook(hook, container) {
|
|
1334
|
+
const modules = container.getModules();
|
|
1335
|
+
for (const module of modules.values()) {
|
|
1336
|
+
for (const wrapper of module.providers.values()) {
|
|
1337
|
+
if (wrapper.instance && wrapper.instance[hook]) {
|
|
1338
|
+
await wrapper.instance[hook]();
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
for (const wrapper of module.controllers.values()) {
|
|
1342
|
+
if (wrapper.instance && wrapper.instance[hook]) {
|
|
1343
|
+
await wrapper.instance[hook]();
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
};
|
|
1349
|
+
|
|
1350
|
+
// src/utils.ts
|
|
1351
|
+
function forwardRef(fn) {
|
|
1352
|
+
return { forwardRef: fn };
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
// src/services/reflector.service.ts
|
|
1356
|
+
exports.Reflector = class Reflector {
|
|
1357
|
+
get(metadataKey, target) {
|
|
1358
|
+
return Reflect.getMetadata(metadataKey, target);
|
|
1359
|
+
}
|
|
1360
|
+
getAllAndOverride(metadataKey, targets) {
|
|
1361
|
+
for (const target of targets) {
|
|
1362
|
+
const result = Reflect.getMetadata(metadataKey, target);
|
|
1363
|
+
if (result !== void 0) {
|
|
1364
|
+
return result;
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
return void 0;
|
|
1368
|
+
}
|
|
1369
|
+
getAllAndMerge(metadataKey, targets) {
|
|
1370
|
+
const result = [];
|
|
1371
|
+
for (const target of targets) {
|
|
1372
|
+
const metadata = Reflect.getMetadata(metadataKey, target);
|
|
1373
|
+
if (metadata) {
|
|
1374
|
+
if (Array.isArray(metadata)) {
|
|
1375
|
+
result.push(...metadata);
|
|
1376
|
+
} else {
|
|
1377
|
+
result.push(metadata);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
return result;
|
|
1382
|
+
}
|
|
1383
|
+
};
|
|
1384
|
+
exports.Reflector = __decorateClass([
|
|
1385
|
+
Injectable()
|
|
1386
|
+
], exports.Reflector);
|
|
1387
|
+
|
|
1388
|
+
// src/common/pipes/index.ts
|
|
1389
|
+
exports.ParseIntPipe = class ParseIntPipe {
|
|
1390
|
+
transform(value, metadata) {
|
|
1391
|
+
const isNumeric = !isNaN(parseFloat(value)) && isFinite(value);
|
|
1392
|
+
if (!isNumeric) {
|
|
1393
|
+
throw new BadRequestException("Validation failed (numeric string is expected)");
|
|
1394
|
+
}
|
|
1395
|
+
return parseInt(value, 10);
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
exports.ParseIntPipe = __decorateClass([
|
|
1399
|
+
Injectable()
|
|
1400
|
+
], exports.ParseIntPipe);
|
|
1401
|
+
exports.ParseFloatPipe = class ParseFloatPipe {
|
|
1402
|
+
transform(value, metadata) {
|
|
1403
|
+
const isNumeric = !isNaN(parseFloat(value)) && isFinite(value);
|
|
1404
|
+
if (!isNumeric) {
|
|
1405
|
+
throw new BadRequestException("Validation failed (numeric string is expected)");
|
|
1406
|
+
}
|
|
1407
|
+
return parseFloat(value);
|
|
1408
|
+
}
|
|
1409
|
+
};
|
|
1410
|
+
exports.ParseFloatPipe = __decorateClass([
|
|
1411
|
+
Injectable()
|
|
1412
|
+
], exports.ParseFloatPipe);
|
|
1413
|
+
exports.ParseBoolPipe = class ParseBoolPipe {
|
|
1414
|
+
transform(value, metadata) {
|
|
1415
|
+
if (value === true || value === "true") {
|
|
1416
|
+
return true;
|
|
1417
|
+
}
|
|
1418
|
+
if (value === false || value === "false") {
|
|
1419
|
+
return false;
|
|
1420
|
+
}
|
|
1421
|
+
throw new BadRequestException("Validation failed (boolean string is expected)");
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
exports.ParseBoolPipe = __decorateClass([
|
|
1425
|
+
Injectable()
|
|
1426
|
+
], exports.ParseBoolPipe);
|
|
1427
|
+
exports.ValidationPipe = class ValidationPipe {
|
|
1428
|
+
transform(value, metadata) {
|
|
1429
|
+
return value;
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
exports.ValidationPipe = __decorateClass([
|
|
1433
|
+
Injectable()
|
|
1434
|
+
], exports.ValidationPipe);
|
|
1435
|
+
|
|
1436
|
+
// src/common/errors/AppError.ts
|
|
1437
|
+
var AppError = class _AppError extends Error {
|
|
1438
|
+
constructor(statusCode, message, isOperational = true) {
|
|
1439
|
+
super(message);
|
|
1440
|
+
this.statusCode = statusCode;
|
|
1441
|
+
this.message = message;
|
|
1442
|
+
this.isOperational = isOperational;
|
|
1443
|
+
Object.setPrototypeOf(this, _AppError.prototype);
|
|
1444
|
+
Error.captureStackTrace(this, this.constructor);
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
var NotFoundError = class extends AppError {
|
|
1448
|
+
constructor(message = "Resource not found") {
|
|
1449
|
+
super(404, message);
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
var BadRequestError = class extends AppError {
|
|
1453
|
+
constructor(message = "Bad request") {
|
|
1454
|
+
super(400, message);
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
var UnauthorizedError = class extends AppError {
|
|
1458
|
+
constructor(message = "Unauthorized") {
|
|
1459
|
+
super(401, message);
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
var ForbiddenError = class extends AppError {
|
|
1463
|
+
constructor(message = "Forbidden") {
|
|
1464
|
+
super(403, message);
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
var ConflictError = class extends AppError {
|
|
1468
|
+
constructor(message = "Resource already exists") {
|
|
1469
|
+
super(409, message);
|
|
1470
|
+
}
|
|
1471
|
+
};
|
|
1472
|
+
|
|
1473
|
+
// src/common/exceptions/HttpException.ts
|
|
1474
|
+
var HttpException2 = class extends Error {
|
|
1475
|
+
constructor(response, status) {
|
|
1476
|
+
super();
|
|
1477
|
+
this.response = response;
|
|
1478
|
+
this.status = status;
|
|
1479
|
+
this.message = typeof response === "string" ? response : JSON.stringify(response);
|
|
1480
|
+
}
|
|
1481
|
+
getResponse() {
|
|
1482
|
+
return this.response;
|
|
1483
|
+
}
|
|
1484
|
+
getStatus() {
|
|
1485
|
+
return this.status;
|
|
1486
|
+
}
|
|
1487
|
+
static createBody(message, error, statusCode) {
|
|
1488
|
+
if (!message) {
|
|
1489
|
+
return { statusCode, error };
|
|
1490
|
+
}
|
|
1491
|
+
return typeof message === "object" && !Array.isArray(message) ? message : { statusCode, error, message };
|
|
1492
|
+
}
|
|
1493
|
+
};
|
|
1494
|
+
|
|
1495
|
+
// src/common/filters/BaseExceptionFilter.ts
|
|
1496
|
+
exports.BaseExceptionFilter = class BaseExceptionFilter {
|
|
1497
|
+
catch(exception, host) {
|
|
1498
|
+
const ctx = host.switchToHttp();
|
|
1499
|
+
ctx.getResponse();
|
|
1500
|
+
const honoCtx = ctx.getContext();
|
|
1501
|
+
if (exception instanceof HttpException2) {
|
|
1502
|
+
const status = exception.getStatus();
|
|
1503
|
+
const res = exception.getResponse();
|
|
1504
|
+
honoCtx.status(status);
|
|
1505
|
+
return honoCtx.json(res);
|
|
1506
|
+
}
|
|
1507
|
+
console.error(exception);
|
|
1508
|
+
honoCtx.status(500);
|
|
1509
|
+
return honoCtx.json({
|
|
1510
|
+
statusCode: 500,
|
|
1511
|
+
message: "Internal Server Error"
|
|
1512
|
+
});
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1515
|
+
exports.BaseExceptionFilter = __decorateClass([
|
|
1516
|
+
Catch()
|
|
1517
|
+
], exports.BaseExceptionFilter);
|
|
1518
|
+
|
|
1519
|
+
exports.AppError = AppError;
|
|
1520
|
+
exports.BadGatewayException = BadGatewayException;
|
|
1521
|
+
exports.BadRequestError = BadRequestError;
|
|
1522
|
+
exports.BadRequestException = BadRequestException;
|
|
1523
|
+
exports.ConflictError = ConflictError;
|
|
1524
|
+
exports.ConflictException = ConflictException;
|
|
1525
|
+
exports.Container = Container;
|
|
1526
|
+
exports.ExecutionContextHost = ExecutionContextHost;
|
|
1527
|
+
exports.ForbiddenError = ForbiddenError;
|
|
1528
|
+
exports.ForbiddenException = ForbiddenException;
|
|
1529
|
+
exports.GatewayTimeoutException = GatewayTimeoutException;
|
|
1530
|
+
exports.GoneException = GoneException;
|
|
1531
|
+
exports.HonoDiApplication = HonoDiApplication;
|
|
1532
|
+
exports.HonoDiFactory = HonoDiFactory;
|
|
1533
|
+
exports.HonoDiScanner = HonoDiScanner;
|
|
1534
|
+
exports.HttpException = HttpException;
|
|
1535
|
+
exports.InternalServerErrorException = InternalServerErrorException;
|
|
1536
|
+
exports.METADATA_KEYS = METADATA_KEYS;
|
|
1537
|
+
exports.MiddlewareBuilder = MiddlewareBuilder;
|
|
1538
|
+
exports.ModuleRef = ModuleRef;
|
|
1539
|
+
exports.ModuleRefImpl = ModuleRefImpl;
|
|
1540
|
+
exports.NotAcceptableException = NotAcceptableException;
|
|
1541
|
+
exports.NotFoundError = NotFoundError;
|
|
1542
|
+
exports.NotFoundException = NotFoundException;
|
|
1543
|
+
exports.NotImplementedException = NotImplementedException;
|
|
1544
|
+
exports.PayloadTooLargeException = PayloadTooLargeException;
|
|
1545
|
+
exports.RequestMethod = RequestMethod;
|
|
1546
|
+
exports.RequestTimeoutException = RequestTimeoutException;
|
|
1547
|
+
exports.ServiceUnavailableException = ServiceUnavailableException;
|
|
1548
|
+
exports.UnauthorizedError = UnauthorizedError;
|
|
1549
|
+
exports.UnauthorizedException = UnauthorizedException;
|
|
1550
|
+
exports.UnprocessableEntityException = UnprocessableEntityException;
|
|
1551
|
+
exports.UnsupportedMediaTypeException = UnsupportedMediaTypeException;
|
|
1552
|
+
exports.forwardRef = forwardRef;
|
|
1553
|
+
//# sourceMappingURL=core.cjs.map
|
|
1554
|
+
//# sourceMappingURL=core.cjs.map
|