node-honest 0.0.7 → 0.1.0
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/index.cjs +2185 -0
- package/dist/index.d.cts +1539 -0
- package/dist/index.d.ts +1539 -16
- package/dist/index.js +2116 -15
- package/package.json +12 -9
- package/dist/application/plugin-entries.d.ts +0 -13
- package/dist/application/plugin-entries.js +0 -38
- package/dist/application/startup-guide.d.ts +0 -4
- package/dist/application/startup-guide.js +0 -53
- package/dist/application-context.d.ts +0 -13
- package/dist/application-context.js +0 -22
- package/dist/application.d.ts +0 -34
- package/dist/application.js +0 -224
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.js +0 -1
- package/dist/components/layout.component.d.ts +0 -31
- package/dist/components/layout.component.js +0 -94
- package/dist/constants/index.d.ts +0 -2
- package/dist/constants/index.js +0 -2
- package/dist/constants/pipeline.constants.d.ts +0 -6
- package/dist/constants/pipeline.constants.js +0 -6
- package/dist/constants/version.constants.d.ts +0 -5
- package/dist/constants/version.constants.js +0 -5
- package/dist/decorators/controller.decorator.d.ts +0 -9
- package/dist/decorators/controller.decorator.js +0 -16
- package/dist/decorators/http-method.decorator.d.ts +0 -43
- package/dist/decorators/http-method.decorator.js +0 -44
- package/dist/decorators/index.d.ts +0 -11
- package/dist/decorators/index.js +0 -11
- package/dist/decorators/module.decorator.d.ts +0 -8
- package/dist/decorators/module.decorator.js +0 -12
- package/dist/decorators/mvc.decorator.d.ts +0 -26
- package/dist/decorators/mvc.decorator.js +0 -36
- package/dist/decorators/parameter.decorator.d.ts +0 -41
- package/dist/decorators/parameter.decorator.js +0 -59
- package/dist/decorators/service.decorator.d.ts +0 -6
- package/dist/decorators/service.decorator.js +0 -11
- package/dist/decorators/use-component.decorator.d.ts +0 -10
- package/dist/decorators/use-component.decorator.js +0 -19
- package/dist/decorators/use-filters.decorator.d.ts +0 -8
- package/dist/decorators/use-filters.decorator.js +0 -17
- package/dist/decorators/use-guards.decorator.d.ts +0 -9
- package/dist/decorators/use-guards.decorator.js +0 -18
- package/dist/decorators/use-middleware.decorator.d.ts +0 -9
- package/dist/decorators/use-middleware.decorator.js +0 -18
- package/dist/decorators/use-pipes.decorator.d.ts +0 -9
- package/dist/decorators/use-pipes.decorator.js +0 -18
- package/dist/di/container.d.ts +0 -34
- package/dist/di/container.js +0 -114
- package/dist/di/index.d.ts +0 -1
- package/dist/di/index.js +0 -1
- package/dist/errors/framework.error.d.ts +0 -19
- package/dist/errors/framework.error.js +0 -23
- package/dist/errors/index.d.ts +0 -1
- package/dist/errors/index.js +0 -1
- package/dist/handlers/error.handler.d.ts +0 -28
- package/dist/handlers/error.handler.js +0 -17
- package/dist/handlers/index.d.ts +0 -2
- package/dist/handlers/index.js +0 -2
- package/dist/handlers/not-found.handler.d.ts +0 -14
- package/dist/handlers/not-found.handler.js +0 -17
- package/dist/helpers/create-error-response.helper.d.ts +0 -25
- package/dist/helpers/create-error-response.helper.js +0 -90
- package/dist/helpers/create-http-method-decorator.helper.d.ts +0 -16
- package/dist/helpers/create-http-method-decorator.helper.js +0 -30
- package/dist/helpers/create-param-decorator.helper.d.ts +0 -16
- package/dist/helpers/create-param-decorator.helper.js +0 -60
- package/dist/helpers/index.d.ts +0 -3
- package/dist/helpers/index.js +0 -3
- package/dist/interfaces/application-context.interface.d.ts +0 -35
- package/dist/interfaces/application-context.interface.js +0 -1
- package/dist/interfaces/controller-options.interface.d.ts +0 -17
- package/dist/interfaces/controller-options.interface.js +0 -1
- package/dist/interfaces/di-container.interface.d.ts +0 -35
- package/dist/interfaces/di-container.interface.js +0 -1
- package/dist/interfaces/error-response.interface.d.ts +0 -13
- package/dist/interfaces/error-response.interface.js +0 -1
- package/dist/interfaces/filter.interface.d.ts +0 -20
- package/dist/interfaces/filter.interface.js +0 -1
- package/dist/interfaces/guard.interface.d.ts +0 -21
- package/dist/interfaces/guard.interface.js +0 -1
- package/dist/interfaces/handler-invocation.interface.d.ts +0 -10
- package/dist/interfaces/handler-invocation.interface.js +0 -1
- package/dist/interfaces/honest-options.interface.d.ts +0 -121
- package/dist/interfaces/honest-options.interface.js +0 -1
- package/dist/interfaces/http-method-options.interface.d.ts +0 -38
- package/dist/interfaces/http-method-options.interface.js +0 -1
- package/dist/interfaces/index.d.ts +0 -21
- package/dist/interfaces/index.js +0 -21
- package/dist/interfaces/logger.interface.d.ts +0 -23
- package/dist/interfaces/logger.interface.js +0 -1
- package/dist/interfaces/metadata-repository.interface.d.ts +0 -30
- package/dist/interfaces/metadata-repository.interface.js +0 -1
- package/dist/interfaces/middleware.interface.d.ts +0 -22
- package/dist/interfaces/middleware.interface.js +0 -1
- package/dist/interfaces/module-options.interface.d.ts +0 -18
- package/dist/interfaces/module-options.interface.js +0 -1
- package/dist/interfaces/parameter-metadata.interface.d.ts +0 -27
- package/dist/interfaces/parameter-metadata.interface.js +0 -1
- package/dist/interfaces/parameter-resolution.interface.d.ts +0 -14
- package/dist/interfaces/parameter-resolution.interface.js +0 -1
- package/dist/interfaces/pipe.interface.d.ts +0 -37
- package/dist/interfaces/pipe.interface.js +0 -1
- package/dist/interfaces/pipeline-context.interface.d.ts +0 -9
- package/dist/interfaces/pipeline-context.interface.js +0 -1
- package/dist/interfaces/plugin.interface.d.ts +0 -74
- package/dist/interfaces/plugin.interface.js +0 -1
- package/dist/interfaces/route-definition.interface.d.ts +0 -51
- package/dist/interfaces/route-definition.interface.js +0 -1
- package/dist/interfaces/route-info.interface.d.ts +0 -42
- package/dist/interfaces/route-info.interface.js +0 -1
- package/dist/interfaces/service-registry.interface.d.ts +0 -7
- package/dist/interfaces/service-registry.interface.js +0 -1
- package/dist/loggers/console.logger.d.ts +0 -7
- package/dist/loggers/console.logger.js +0 -21
- package/dist/loggers/index.d.ts +0 -2
- package/dist/loggers/index.js +0 -2
- package/dist/loggers/noop.logger.d.ts +0 -7
- package/dist/loggers/noop.logger.js +0 -8
- package/dist/managers/component.manager.d.ts +0 -48
- package/dist/managers/component.manager.js +0 -209
- package/dist/managers/handler.invoker.d.ts +0 -7
- package/dist/managers/handler.invoker.js +0 -37
- package/dist/managers/index.d.ts +0 -5
- package/dist/managers/index.js +0 -5
- package/dist/managers/parameter.resolver.d.ts +0 -13
- package/dist/managers/parameter.resolver.js +0 -57
- package/dist/managers/pipeline.executor.d.ts +0 -28
- package/dist/managers/pipeline.executor.js +0 -68
- package/dist/managers/route.manager.d.ts +0 -36
- package/dist/managers/route.manager.js +0 -147
- package/dist/registries/index.d.ts +0 -4
- package/dist/registries/index.js +0 -4
- package/dist/registries/metadata.registry.d.ts +0 -163
- package/dist/registries/metadata.registry.js +0 -250
- package/dist/registries/metadata.repository.d.ts +0 -30
- package/dist/registries/metadata.repository.js +0 -151
- package/dist/registries/route.registry.d.ts +0 -16
- package/dist/registries/route.registry.js +0 -46
- package/dist/registries/service.registry.d.ts +0 -8
- package/dist/registries/service.registry.js +0 -9
- package/dist/testing/create-controller-test-application.d.ts +0 -5
- package/dist/testing/create-controller-test-application.js +0 -11
- package/dist/testing/create-service-test-container.d.ts +0 -5
- package/dist/testing/create-service-test-container.js +0 -31
- package/dist/testing/create-test-application.d.ts +0 -5
- package/dist/testing/create-test-application.js +0 -20
- package/dist/testing/create-testing-module.d.ts +0 -6
- package/dist/testing/create-testing-module.js +0 -13
- package/dist/testing/fixtures/application-test-fixtures.d.ts +0 -17
- package/dist/testing/fixtures/application-test-fixtures.js +0 -230
- package/dist/testing/index.d.ts +0 -5
- package/dist/testing/index.js +0 -5
- package/dist/testing/testing.interface.d.ts +0 -96
- package/dist/testing/testing.interface.js +0 -1
- package/dist/types/constructor.type.d.ts +0 -12
- package/dist/types/constructor.type.js +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/utils/common.util.d.ts +0 -117
- package/dist/utils/common.util.js +0 -140
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2185 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('reflect-metadata');
|
|
4
|
+
var hono = require('hono');
|
|
5
|
+
var httpException = require('hono/http-exception');
|
|
6
|
+
var html = require('hono/html');
|
|
7
|
+
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
10
|
+
|
|
11
|
+
// src/application/startup-guide.ts
|
|
12
|
+
function createStartupGuideHints(errorMessage) {
|
|
13
|
+
const hints = /* @__PURE__ */ new Set();
|
|
14
|
+
hints.add("Check module wiring: root module imports, controllers, and services should be registered correctly.");
|
|
15
|
+
if (errorMessage.includes("not decorated with @Controller()")) {
|
|
16
|
+
hints.add("Add @Controller() to the class or remove it from module.controllers.");
|
|
17
|
+
}
|
|
18
|
+
if (errorMessage.includes("has no route handlers")) {
|
|
19
|
+
hints.add("Add at least one HTTP method decorator such as @Get() or @Post() in the controller.");
|
|
20
|
+
}
|
|
21
|
+
if (errorMessage.includes("not decorated with @Service()")) {
|
|
22
|
+
hints.add("Add @Service() to injectable classes used in constructor dependencies.");
|
|
23
|
+
}
|
|
24
|
+
if (errorMessage.includes("constructor metadata is missing") || errorMessage.includes("reflect-metadata")) {
|
|
25
|
+
hints.add("Import 'reflect-metadata' in your entry file and enable 'emitDecoratorMetadata' in tsconfig.");
|
|
26
|
+
}
|
|
27
|
+
if (errorMessage.includes("Strict mode: no routes were registered")) {
|
|
28
|
+
hints.add("Disable strict.requireRoutes for empty modules, or add a controller with at least one route.");
|
|
29
|
+
}
|
|
30
|
+
return [
|
|
31
|
+
...hints
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
__name(createStartupGuideHints, "createStartupGuideHints");
|
|
35
|
+
function emitStartupGuide(logger, startupGuide, error, rootModule) {
|
|
36
|
+
if (!startupGuide) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const verbose = typeof startupGuide === "object" && Boolean(startupGuide.verbose);
|
|
40
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
41
|
+
const hints = createStartupGuideHints(errorMessage);
|
|
42
|
+
logger.emit({
|
|
43
|
+
level: "warn",
|
|
44
|
+
category: "startup",
|
|
45
|
+
message: "Startup guide",
|
|
46
|
+
details: {
|
|
47
|
+
rootModule: rootModule.name,
|
|
48
|
+
errorMessage,
|
|
49
|
+
hints,
|
|
50
|
+
verbose
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (verbose) {
|
|
54
|
+
logger.emit({
|
|
55
|
+
level: "warn",
|
|
56
|
+
category: "startup",
|
|
57
|
+
message: "Startup guide (verbose)",
|
|
58
|
+
details: {
|
|
59
|
+
steps: [
|
|
60
|
+
"Verify decorators are present for controllers/services used by DI and routing.",
|
|
61
|
+
"Ensure 'reflect-metadata' is imported once at entry and 'emitDecoratorMetadata' is enabled.",
|
|
62
|
+
"Enable debug.startup for extra startup diagnostics and timing details."
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
__name(emitStartupGuide, "emitStartupGuide");
|
|
69
|
+
|
|
70
|
+
// src/utils/common.util.ts
|
|
71
|
+
var isUndefined = /* @__PURE__ */ __name((obj) => typeof obj === "undefined", "isUndefined");
|
|
72
|
+
var isNil = /* @__PURE__ */ __name((val) => val === null || typeof val === "undefined", "isNil");
|
|
73
|
+
var isObject = /* @__PURE__ */ __name((val) => val !== null && typeof val === "object", "isObject");
|
|
74
|
+
var isPlainObject = /* @__PURE__ */ __name((val) => {
|
|
75
|
+
if (!isObject(val)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const proto = Object.getPrototypeOf(val);
|
|
79
|
+
if (proto === null) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
const ctor = Object.prototype.hasOwnProperty.call(proto, "constructor") && proto.constructor;
|
|
83
|
+
return typeof ctor === "function" && ctor instanceof ctor && Function.prototype.toString.call(ctor) === Function.prototype.toString.call(Object);
|
|
84
|
+
}, "isPlainObject");
|
|
85
|
+
var isFunction = /* @__PURE__ */ __name((val) => typeof val === "function", "isFunction");
|
|
86
|
+
var isString = /* @__PURE__ */ __name((val) => typeof val === "string", "isString");
|
|
87
|
+
var isNumber = /* @__PURE__ */ __name((val) => typeof val === "number", "isNumber");
|
|
88
|
+
var isEmpty = /* @__PURE__ */ __name((array) => array.length === 0, "isEmpty");
|
|
89
|
+
var isSymbol = /* @__PURE__ */ __name((val) => typeof val === "symbol", "isSymbol");
|
|
90
|
+
var addLeadingSlash = /* @__PURE__ */ __name((path) => typeof path === "string" ? path.charAt(0) !== "/" ? "/" + path : path : "", "addLeadingSlash");
|
|
91
|
+
var normalizePath = /* @__PURE__ */ __name((path) => path ? path.startsWith("/") ? ("/" + path.replace(/\/+$/, "")).replace(/\/+/g, "/") : "/" + path.replace(/\/+$/, "") : "/", "normalizePath");
|
|
92
|
+
var stripEndSlash = /* @__PURE__ */ __name((path) => path.endsWith("/") ? path.slice(0, -1) : path, "stripEndSlash");
|
|
93
|
+
var isConstructor = /* @__PURE__ */ __name((val) => {
|
|
94
|
+
return isFunction(val) && !isNil(val.prototype) && !isFunction(val.prototype) && Object.getOwnPropertyNames(val.prototype).length >= 1;
|
|
95
|
+
}, "isConstructor");
|
|
96
|
+
|
|
97
|
+
// src/application/plugin-entries.ts
|
|
98
|
+
var DEFAULT_PLUGIN_NAME = "AnonymousPlugin";
|
|
99
|
+
function resolvePlugin(pluginType) {
|
|
100
|
+
if (isConstructor(pluginType)) {
|
|
101
|
+
return new pluginType();
|
|
102
|
+
}
|
|
103
|
+
return pluginType;
|
|
104
|
+
}
|
|
105
|
+
__name(resolvePlugin, "resolvePlugin");
|
|
106
|
+
function resolvePluginName(plugin, index, override) {
|
|
107
|
+
const resolved = override || plugin.meta?.name || plugin.constructor?.name;
|
|
108
|
+
if (!resolved || resolved === DEFAULT_PLUGIN_NAME) {
|
|
109
|
+
return `${DEFAULT_PLUGIN_NAME}#${index + 1}`;
|
|
110
|
+
}
|
|
111
|
+
return resolved;
|
|
112
|
+
}
|
|
113
|
+
__name(resolvePluginName, "resolvePluginName");
|
|
114
|
+
function normalizePluginEntry(entry, index) {
|
|
115
|
+
if (entry && typeof entry === "object" && "plugin" in entry) {
|
|
116
|
+
const obj = entry;
|
|
117
|
+
const plugin2 = resolvePlugin(obj.plugin);
|
|
118
|
+
const name = resolvePluginName(plugin2, index, obj.name);
|
|
119
|
+
return {
|
|
120
|
+
plugin: plugin2,
|
|
121
|
+
name,
|
|
122
|
+
preProcessors: obj.preProcessors ?? [],
|
|
123
|
+
postProcessors: obj.postProcessors ?? []
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const plugin = resolvePlugin(entry);
|
|
127
|
+
return {
|
|
128
|
+
plugin,
|
|
129
|
+
name: resolvePluginName(plugin, index),
|
|
130
|
+
preProcessors: [],
|
|
131
|
+
postProcessors: []
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
__name(normalizePluginEntry, "normalizePluginEntry");
|
|
135
|
+
function normalizePluginEntries(plugins) {
|
|
136
|
+
return (plugins ?? []).map((entry, index) => normalizePluginEntry(entry, index));
|
|
137
|
+
}
|
|
138
|
+
__name(normalizePluginEntries, "normalizePluginEntries");
|
|
139
|
+
|
|
140
|
+
// src/application-context.ts
|
|
141
|
+
var ApplicationContext = class {
|
|
142
|
+
static {
|
|
143
|
+
__name(this, "ApplicationContext");
|
|
144
|
+
}
|
|
145
|
+
store = /* @__PURE__ */ new Map();
|
|
146
|
+
get(key) {
|
|
147
|
+
return this.store.get(key);
|
|
148
|
+
}
|
|
149
|
+
set(key, value) {
|
|
150
|
+
this.store.set(key, value);
|
|
151
|
+
}
|
|
152
|
+
has(key) {
|
|
153
|
+
return this.store.has(key);
|
|
154
|
+
}
|
|
155
|
+
delete(key) {
|
|
156
|
+
return this.store.delete(key);
|
|
157
|
+
}
|
|
158
|
+
keys() {
|
|
159
|
+
return this.store.keys();
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// src/loggers/console.logger.ts
|
|
164
|
+
var ConsoleLogger = class {
|
|
165
|
+
static {
|
|
166
|
+
__name(this, "ConsoleLogger");
|
|
167
|
+
}
|
|
168
|
+
emit(event) {
|
|
169
|
+
const prefix = `[HonestJS:${event.category}]`;
|
|
170
|
+
const payload = event.details ? [
|
|
171
|
+
prefix,
|
|
172
|
+
event.message,
|
|
173
|
+
event.details
|
|
174
|
+
] : [
|
|
175
|
+
prefix,
|
|
176
|
+
event.message
|
|
177
|
+
];
|
|
178
|
+
switch (event.level) {
|
|
179
|
+
case "debug":
|
|
180
|
+
case "info":
|
|
181
|
+
console.info(...payload);
|
|
182
|
+
break;
|
|
183
|
+
case "warn":
|
|
184
|
+
console.warn(...payload);
|
|
185
|
+
break;
|
|
186
|
+
case "error":
|
|
187
|
+
console.error(...payload);
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// src/loggers/noop.logger.ts
|
|
194
|
+
var NoopLogger = class {
|
|
195
|
+
static {
|
|
196
|
+
__name(this, "NoopLogger");
|
|
197
|
+
}
|
|
198
|
+
emit(_event) {
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// src/registries/metadata.registry.ts
|
|
203
|
+
var MetadataRegistry = class {
|
|
204
|
+
static {
|
|
205
|
+
__name(this, "MetadataRegistry");
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Stores route definitions for each controller
|
|
209
|
+
* Maps controller classes to their route configurations
|
|
210
|
+
*/
|
|
211
|
+
static routes = /* @__PURE__ */ new Map();
|
|
212
|
+
/**
|
|
213
|
+
* Stores base paths for controllers
|
|
214
|
+
* Maps controller classes to their route prefixes
|
|
215
|
+
*/
|
|
216
|
+
static controllers = /* @__PURE__ */ new Map();
|
|
217
|
+
/**
|
|
218
|
+
* Stores configuration options for controllers
|
|
219
|
+
* Includes settings like versioning and prefix options
|
|
220
|
+
*/
|
|
221
|
+
static controllerOptions = /* @__PURE__ */ new Map();
|
|
222
|
+
/**
|
|
223
|
+
* Registry of service classes
|
|
224
|
+
* Used for dependency injection and lifecycle management
|
|
225
|
+
*/
|
|
226
|
+
static services = /* @__PURE__ */ new Set();
|
|
227
|
+
/**
|
|
228
|
+
* Stores configuration options for modules
|
|
229
|
+
* Includes imports, exports, providers, and controllers
|
|
230
|
+
*/
|
|
231
|
+
static modules = /* @__PURE__ */ new Map();
|
|
232
|
+
/**
|
|
233
|
+
* Stores parameter metadata for controller methods
|
|
234
|
+
* Used for parameter transformation and validation
|
|
235
|
+
*/
|
|
236
|
+
static parameters = /* @__PURE__ */ new Map();
|
|
237
|
+
/**
|
|
238
|
+
* Stores indices of context parameters in controller methods
|
|
239
|
+
* Used for optimizing context injection
|
|
240
|
+
*/
|
|
241
|
+
static contextIndices = /* @__PURE__ */ new Map();
|
|
242
|
+
/**
|
|
243
|
+
* Registry for controller-level components
|
|
244
|
+
* Components registered here apply to all routes in a specific controller
|
|
245
|
+
*/
|
|
246
|
+
static controller = /* @__PURE__ */ new Map([
|
|
247
|
+
[
|
|
248
|
+
"middleware",
|
|
249
|
+
/* @__PURE__ */ new Map()
|
|
250
|
+
],
|
|
251
|
+
[
|
|
252
|
+
"guard",
|
|
253
|
+
/* @__PURE__ */ new Map()
|
|
254
|
+
],
|
|
255
|
+
[
|
|
256
|
+
"pipe",
|
|
257
|
+
/* @__PURE__ */ new Map()
|
|
258
|
+
],
|
|
259
|
+
[
|
|
260
|
+
"filter",
|
|
261
|
+
/* @__PURE__ */ new Map()
|
|
262
|
+
]
|
|
263
|
+
]);
|
|
264
|
+
/**
|
|
265
|
+
* Registry for handler-level components
|
|
266
|
+
* Components registered here apply to specific route handlers
|
|
267
|
+
* Keyed by controller constructor then handler name for collision-safe lookups
|
|
268
|
+
*/
|
|
269
|
+
static handler = /* @__PURE__ */ new Map([
|
|
270
|
+
[
|
|
271
|
+
"middleware",
|
|
272
|
+
/* @__PURE__ */ new Map()
|
|
273
|
+
],
|
|
274
|
+
[
|
|
275
|
+
"guard",
|
|
276
|
+
/* @__PURE__ */ new Map()
|
|
277
|
+
],
|
|
278
|
+
[
|
|
279
|
+
"pipe",
|
|
280
|
+
/* @__PURE__ */ new Map()
|
|
281
|
+
],
|
|
282
|
+
[
|
|
283
|
+
"filter",
|
|
284
|
+
/* @__PURE__ */ new Map()
|
|
285
|
+
]
|
|
286
|
+
]);
|
|
287
|
+
/**
|
|
288
|
+
* Gets all route definitions for a controller
|
|
289
|
+
* @param controller - The controller class to get routes for
|
|
290
|
+
* @returns Array of route definitions for the controller
|
|
291
|
+
*/
|
|
292
|
+
static getRoutes(controller) {
|
|
293
|
+
return this.routes.get(controller) || [];
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Set routes for a controller
|
|
297
|
+
*/
|
|
298
|
+
static setRoutes(controller, routes) {
|
|
299
|
+
this.routes.set(controller, routes);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Add a route to a controller
|
|
303
|
+
*/
|
|
304
|
+
static addRoute(controller, route) {
|
|
305
|
+
if (!this.routes.has(controller)) {
|
|
306
|
+
this.routes.set(controller, []);
|
|
307
|
+
}
|
|
308
|
+
this.routes.get(controller).push(route);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Get controller path
|
|
312
|
+
*/
|
|
313
|
+
static getControllerPath(controller) {
|
|
314
|
+
return this.controllers.get(controller) || "";
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Check if a class is registered as a controller.
|
|
318
|
+
*/
|
|
319
|
+
static hasController(controller) {
|
|
320
|
+
return this.controllers.has(controller);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Set controller path
|
|
324
|
+
*/
|
|
325
|
+
static setControllerPath(controller, path) {
|
|
326
|
+
this.controllers.set(controller, path);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get controller options
|
|
330
|
+
*/
|
|
331
|
+
static getControllerOptions(controller) {
|
|
332
|
+
return this.controllerOptions.get(controller) || {};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Set controller options
|
|
336
|
+
*/
|
|
337
|
+
static setControllerOptions(controller, options) {
|
|
338
|
+
this.controllerOptions.set(controller, options);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Check if class is a service
|
|
342
|
+
*/
|
|
343
|
+
static isService(service) {
|
|
344
|
+
return this.services.has(service);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Add a service
|
|
348
|
+
*/
|
|
349
|
+
static addService(service) {
|
|
350
|
+
this.services.add(service);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Get all services
|
|
354
|
+
*/
|
|
355
|
+
static getAllServices() {
|
|
356
|
+
return this.services;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Get module options
|
|
360
|
+
*/
|
|
361
|
+
static getModuleOptions(module) {
|
|
362
|
+
return this.modules.get(module);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Set module options
|
|
366
|
+
*/
|
|
367
|
+
static setModuleOptions(module, options) {
|
|
368
|
+
this.modules.set(module, options);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Get parameter metadata
|
|
372
|
+
*/
|
|
373
|
+
static getParameters(controller) {
|
|
374
|
+
return this.parameters.get(controller) || /* @__PURE__ */ new Map();
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Set parameter metadata
|
|
378
|
+
*/
|
|
379
|
+
static setParameterMap(controller, params) {
|
|
380
|
+
this.parameters.set(controller, params);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Get context indices
|
|
384
|
+
*/
|
|
385
|
+
static getContextIndices(controller) {
|
|
386
|
+
return this.contextIndices.get(controller) || /* @__PURE__ */ new Map();
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Set context indices
|
|
390
|
+
*/
|
|
391
|
+
static setContextIndices(controller, indices) {
|
|
392
|
+
this.contextIndices.set(controller, indices);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Register a component at the controller level
|
|
396
|
+
*/
|
|
397
|
+
static registerController(type, controller, component) {
|
|
398
|
+
const typeMap = this.controller.get(type);
|
|
399
|
+
if (!typeMap.has(controller)) {
|
|
400
|
+
typeMap.set(controller, []);
|
|
401
|
+
}
|
|
402
|
+
typeMap.get(controller).push(component);
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Get all controller-level components of a specific type for a controller
|
|
406
|
+
*/
|
|
407
|
+
static getController(type, controller) {
|
|
408
|
+
const typeMap = this.controller.get(type);
|
|
409
|
+
return typeMap.get(controller) || [];
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Register a component at the handler level
|
|
413
|
+
*/
|
|
414
|
+
static registerHandler(type, controller, handlerName, component) {
|
|
415
|
+
const typeMap = this.handler.get(type);
|
|
416
|
+
if (!typeMap.has(controller)) {
|
|
417
|
+
typeMap.set(controller, /* @__PURE__ */ new Map());
|
|
418
|
+
}
|
|
419
|
+
const controllerMap = typeMap.get(controller);
|
|
420
|
+
if (!controllerMap.has(handlerName)) {
|
|
421
|
+
controllerMap.set(handlerName, []);
|
|
422
|
+
}
|
|
423
|
+
controllerMap.get(handlerName).push(component);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Get all handler-level components of a specific type for a handler
|
|
427
|
+
*/
|
|
428
|
+
static getHandler(type, controller, handlerName) {
|
|
429
|
+
const typeMap = this.handler.get(type);
|
|
430
|
+
const controllerMap = typeMap.get(controller);
|
|
431
|
+
if (!controllerMap) {
|
|
432
|
+
return [];
|
|
433
|
+
}
|
|
434
|
+
return controllerMap.get(handlerName) || [];
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Clears handler-level component registrations created via {@link registerHandler}.
|
|
438
|
+
* Does not remove decorator-defined routes, controllers, or modules.
|
|
439
|
+
*/
|
|
440
|
+
static clearHandlerComponents() {
|
|
441
|
+
for (const typeMap of this.handler.values()) {
|
|
442
|
+
for (const controllerMap of typeMap.values()) {
|
|
443
|
+
controllerMap.clear();
|
|
444
|
+
}
|
|
445
|
+
typeMap.clear();
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Clears all registered decorator metadata.
|
|
450
|
+
* Primarily used for testing. Warning: clearing after importing decorated classes
|
|
451
|
+
* (e.g. shared fixtures) removes their metadata until those modules are re-evaluated.
|
|
452
|
+
*/
|
|
453
|
+
static clear() {
|
|
454
|
+
this.routes.clear();
|
|
455
|
+
this.controllers.clear();
|
|
456
|
+
this.controllerOptions.clear();
|
|
457
|
+
this.services.clear();
|
|
458
|
+
this.modules.clear();
|
|
459
|
+
this.parameters.clear();
|
|
460
|
+
this.contextIndices.clear();
|
|
461
|
+
for (const map of this.controller.values()) {
|
|
462
|
+
map.clear();
|
|
463
|
+
}
|
|
464
|
+
for (const typeMap of this.handler.values()) {
|
|
465
|
+
for (const controllerMap of typeMap.values()) {
|
|
466
|
+
controllerMap.clear();
|
|
467
|
+
}
|
|
468
|
+
typeMap.clear();
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
// src/registries/metadata.repository.ts
|
|
474
|
+
var MetadataRepository = class _MetadataRepository {
|
|
475
|
+
static {
|
|
476
|
+
__name(this, "MetadataRepository");
|
|
477
|
+
}
|
|
478
|
+
controllerPaths = /* @__PURE__ */ new Map();
|
|
479
|
+
controllerOptions = /* @__PURE__ */ new Map();
|
|
480
|
+
routes = /* @__PURE__ */ new Map();
|
|
481
|
+
parameters = /* @__PURE__ */ new Map();
|
|
482
|
+
contextIndices = /* @__PURE__ */ new Map();
|
|
483
|
+
modules = /* @__PURE__ */ new Map();
|
|
484
|
+
controllerComponents = /* @__PURE__ */ new Map([
|
|
485
|
+
[
|
|
486
|
+
"middleware",
|
|
487
|
+
/* @__PURE__ */ new Map()
|
|
488
|
+
],
|
|
489
|
+
[
|
|
490
|
+
"guard",
|
|
491
|
+
/* @__PURE__ */ new Map()
|
|
492
|
+
],
|
|
493
|
+
[
|
|
494
|
+
"pipe",
|
|
495
|
+
/* @__PURE__ */ new Map()
|
|
496
|
+
],
|
|
497
|
+
[
|
|
498
|
+
"filter",
|
|
499
|
+
/* @__PURE__ */ new Map()
|
|
500
|
+
]
|
|
501
|
+
]);
|
|
502
|
+
handlerComponents = /* @__PURE__ */ new Map([
|
|
503
|
+
[
|
|
504
|
+
"middleware",
|
|
505
|
+
/* @__PURE__ */ new Map()
|
|
506
|
+
],
|
|
507
|
+
[
|
|
508
|
+
"guard",
|
|
509
|
+
/* @__PURE__ */ new Map()
|
|
510
|
+
],
|
|
511
|
+
[
|
|
512
|
+
"pipe",
|
|
513
|
+
/* @__PURE__ */ new Map()
|
|
514
|
+
],
|
|
515
|
+
[
|
|
516
|
+
"filter",
|
|
517
|
+
/* @__PURE__ */ new Map()
|
|
518
|
+
]
|
|
519
|
+
]);
|
|
520
|
+
static fromRootModule(rootModule) {
|
|
521
|
+
const snapshot = new _MetadataRepository();
|
|
522
|
+
snapshot.captureModuleGraph(rootModule);
|
|
523
|
+
return snapshot;
|
|
524
|
+
}
|
|
525
|
+
hasController(controller) {
|
|
526
|
+
return this.controllerPaths.has(controller);
|
|
527
|
+
}
|
|
528
|
+
getControllerPath(controller) {
|
|
529
|
+
return this.controllerPaths.get(controller) || "";
|
|
530
|
+
}
|
|
531
|
+
getControllerOptions(controller) {
|
|
532
|
+
const options = this.controllerOptions.get(controller);
|
|
533
|
+
return options ? {
|
|
534
|
+
...options
|
|
535
|
+
} : {};
|
|
536
|
+
}
|
|
537
|
+
getRoutes(controller) {
|
|
538
|
+
return (this.routes.get(controller) || []).map((route) => this.cloneRouteDefinition(route));
|
|
539
|
+
}
|
|
540
|
+
getParameters(controller) {
|
|
541
|
+
const parameters = this.parameters.get(controller);
|
|
542
|
+
if (!parameters) {
|
|
543
|
+
return /* @__PURE__ */ new Map();
|
|
544
|
+
}
|
|
545
|
+
const cloned = /* @__PURE__ */ new Map();
|
|
546
|
+
for (const [handlerName, entries] of parameters.entries()) {
|
|
547
|
+
cloned.set(handlerName, entries.map((entry) => ({
|
|
548
|
+
...entry
|
|
549
|
+
})));
|
|
550
|
+
}
|
|
551
|
+
return cloned;
|
|
552
|
+
}
|
|
553
|
+
getContextIndices(controller) {
|
|
554
|
+
return new Map(this.contextIndices.get(controller) || /* @__PURE__ */ new Map());
|
|
555
|
+
}
|
|
556
|
+
getModuleOptions(module) {
|
|
557
|
+
const options = this.modules.get(module);
|
|
558
|
+
if (!options) {
|
|
559
|
+
return void 0;
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
controllers: options.controllers ? [
|
|
563
|
+
...options.controllers
|
|
564
|
+
] : void 0,
|
|
565
|
+
services: options.services ? [
|
|
566
|
+
...options.services
|
|
567
|
+
] : void 0,
|
|
568
|
+
imports: options.imports ? [
|
|
569
|
+
...options.imports
|
|
570
|
+
] : void 0
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
getControllerComponents(type, controller) {
|
|
574
|
+
const map = this.controllerComponents.get(type);
|
|
575
|
+
const components = map.get(controller) || [];
|
|
576
|
+
return [
|
|
577
|
+
...components
|
|
578
|
+
];
|
|
579
|
+
}
|
|
580
|
+
getHandlerComponents(type, controller, handlerName) {
|
|
581
|
+
const typeMap = this.handlerComponents.get(type);
|
|
582
|
+
const controllerMap = typeMap.get(controller);
|
|
583
|
+
if (!controllerMap) {
|
|
584
|
+
return [];
|
|
585
|
+
}
|
|
586
|
+
const components = controllerMap.get(handlerName) || [];
|
|
587
|
+
return [
|
|
588
|
+
...components
|
|
589
|
+
];
|
|
590
|
+
}
|
|
591
|
+
captureModuleGraph(rootModule) {
|
|
592
|
+
const visitedModules = /* @__PURE__ */ new Set();
|
|
593
|
+
const controllers = /* @__PURE__ */ new Set();
|
|
594
|
+
const visitModule = /* @__PURE__ */ __name((moduleClass) => {
|
|
595
|
+
if (visitedModules.has(moduleClass)) {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
visitedModules.add(moduleClass);
|
|
599
|
+
const moduleOptions = MetadataRegistry.getModuleOptions(moduleClass);
|
|
600
|
+
if (!moduleOptions) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const moduleSnapshot = {
|
|
604
|
+
controllers: moduleOptions.controllers ? [
|
|
605
|
+
...moduleOptions.controllers
|
|
606
|
+
] : void 0,
|
|
607
|
+
services: moduleOptions.services ? [
|
|
608
|
+
...moduleOptions.services
|
|
609
|
+
] : void 0,
|
|
610
|
+
imports: moduleOptions.imports ? [
|
|
611
|
+
...moduleOptions.imports
|
|
612
|
+
] : void 0
|
|
613
|
+
};
|
|
614
|
+
this.modules.set(moduleClass, moduleSnapshot);
|
|
615
|
+
for (const controller of moduleSnapshot.controllers || []) {
|
|
616
|
+
controllers.add(controller);
|
|
617
|
+
}
|
|
618
|
+
for (const importedModule of moduleSnapshot.imports || []) {
|
|
619
|
+
visitModule(importedModule);
|
|
620
|
+
}
|
|
621
|
+
}, "visitModule");
|
|
622
|
+
visitModule(rootModule);
|
|
623
|
+
for (const controller of controllers) {
|
|
624
|
+
this.captureController(controller);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
captureController(controller) {
|
|
628
|
+
if (!MetadataRegistry.hasController(controller)) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
this.controllerPaths.set(controller, MetadataRegistry.getControllerPath(controller) || "");
|
|
632
|
+
this.controllerOptions.set(controller, {
|
|
633
|
+
...MetadataRegistry.getControllerOptions(controller)
|
|
634
|
+
});
|
|
635
|
+
const routes = (MetadataRegistry.getRoutes(controller) || []).map((route) => this.cloneRouteDefinition(route));
|
|
636
|
+
this.routes.set(controller, routes);
|
|
637
|
+
const parameters = MetadataRegistry.getParameters(controller);
|
|
638
|
+
const parameterSnapshot = /* @__PURE__ */ new Map();
|
|
639
|
+
for (const [handlerName, entries] of parameters.entries()) {
|
|
640
|
+
parameterSnapshot.set(handlerName, (entries || []).map((entry) => ({
|
|
641
|
+
...entry
|
|
642
|
+
})));
|
|
643
|
+
}
|
|
644
|
+
this.parameters.set(controller, parameterSnapshot);
|
|
645
|
+
this.contextIndices.set(controller, new Map(MetadataRegistry.getContextIndices(controller) || /* @__PURE__ */ new Map()));
|
|
646
|
+
for (const type of [
|
|
647
|
+
"middleware",
|
|
648
|
+
"guard",
|
|
649
|
+
"pipe",
|
|
650
|
+
"filter"
|
|
651
|
+
]) {
|
|
652
|
+
const controllerMap = this.controllerComponents.get(type);
|
|
653
|
+
controllerMap.set(controller, [
|
|
654
|
+
...MetadataRegistry.getController(type, controller) || []
|
|
655
|
+
]);
|
|
656
|
+
}
|
|
657
|
+
for (const route of routes) {
|
|
658
|
+
for (const type of [
|
|
659
|
+
"middleware",
|
|
660
|
+
"guard",
|
|
661
|
+
"pipe",
|
|
662
|
+
"filter"
|
|
663
|
+
]) {
|
|
664
|
+
const typeMap = this.handlerComponents.get(type);
|
|
665
|
+
if (!typeMap.has(controller)) {
|
|
666
|
+
typeMap.set(controller, /* @__PURE__ */ new Map());
|
|
667
|
+
}
|
|
668
|
+
const controllerHandlers = typeMap.get(controller);
|
|
669
|
+
controllerHandlers.set(route.handlerName, [
|
|
670
|
+
...MetadataRegistry.getHandler(type, controller, route.handlerName)
|
|
671
|
+
]);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
cloneRouteDefinition(route) {
|
|
676
|
+
return {
|
|
677
|
+
...route,
|
|
678
|
+
version: Array.isArray(route.version) ? [
|
|
679
|
+
...route.version
|
|
680
|
+
] : route.version
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
// src/registries/route.registry.ts
|
|
686
|
+
var RouteRegistry = class {
|
|
687
|
+
static {
|
|
688
|
+
__name(this, "RouteRegistry");
|
|
689
|
+
}
|
|
690
|
+
routes = [];
|
|
691
|
+
registerRoute(routeInfo) {
|
|
692
|
+
if (!routeInfo) {
|
|
693
|
+
throw new Error("Route info is required");
|
|
694
|
+
}
|
|
695
|
+
if (!routeInfo.controller) {
|
|
696
|
+
throw new Error("Route controller is required");
|
|
697
|
+
}
|
|
698
|
+
if (!routeInfo.handler) {
|
|
699
|
+
throw new Error("Route handler is required");
|
|
700
|
+
}
|
|
701
|
+
if (!routeInfo.method) {
|
|
702
|
+
throw new Error("Route method is required");
|
|
703
|
+
}
|
|
704
|
+
if (!routeInfo.fullPath) {
|
|
705
|
+
throw new Error("Route fullPath is required");
|
|
706
|
+
}
|
|
707
|
+
const isDuplicate = this.routes.some((route) => route.fullPath === routeInfo.fullPath && route.method.toUpperCase() === routeInfo.method.toUpperCase());
|
|
708
|
+
if (isDuplicate) {
|
|
709
|
+
throw new Error(`Duplicate route detected: ${routeInfo.method.toUpperCase()} ${routeInfo.fullPath} (${String(routeInfo.controller)}.${String(routeInfo.handler)})`);
|
|
710
|
+
}
|
|
711
|
+
this.routes.push(routeInfo);
|
|
712
|
+
}
|
|
713
|
+
getRoutes() {
|
|
714
|
+
return this.routes;
|
|
715
|
+
}
|
|
716
|
+
getRoutesByController(controllerName) {
|
|
717
|
+
return this.routes.filter((route) => route.controller === controllerName);
|
|
718
|
+
}
|
|
719
|
+
getRoutesByMethod(method) {
|
|
720
|
+
return this.routes.filter((route) => route.method.toUpperCase() === method.toUpperCase());
|
|
721
|
+
}
|
|
722
|
+
getRoutesByPath(pattern) {
|
|
723
|
+
return this.routes.filter((route) => pattern.test(route.fullPath));
|
|
724
|
+
}
|
|
725
|
+
clear() {
|
|
726
|
+
this.routes.length = 0;
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// src/registries/service.registry.ts
|
|
731
|
+
var StaticServiceRegistry = class {
|
|
732
|
+
static {
|
|
733
|
+
__name(this, "StaticServiceRegistry");
|
|
734
|
+
}
|
|
735
|
+
isService(service) {
|
|
736
|
+
return MetadataRegistry.isService(service);
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
|
|
740
|
+
// src/di/container.ts
|
|
741
|
+
var Container = class {
|
|
742
|
+
static {
|
|
743
|
+
__name(this, "Container");
|
|
744
|
+
}
|
|
745
|
+
serviceRegistry;
|
|
746
|
+
logger;
|
|
747
|
+
debugDi;
|
|
748
|
+
constructor(serviceRegistry = new StaticServiceRegistry(), logger = new NoopLogger(), debugDi = false) {
|
|
749
|
+
this.serviceRegistry = serviceRegistry;
|
|
750
|
+
this.logger = logger;
|
|
751
|
+
this.debugDi = debugDi;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Map of class constructors to their instances
|
|
755
|
+
*/
|
|
756
|
+
instances = /* @__PURE__ */ new Map();
|
|
757
|
+
emitLog(event) {
|
|
758
|
+
if (!this.debugDi) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
this.logger.emit(event);
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Resolves a class instance, creating it if necessary and injecting its dependencies
|
|
765
|
+
* @param target - The class constructor to resolve
|
|
766
|
+
* @returns An instance of the target class
|
|
767
|
+
*/
|
|
768
|
+
resolve(target) {
|
|
769
|
+
return this.resolveWithTracking(target, /* @__PURE__ */ new Set());
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Internal recursive resolver with circular dependency tracking
|
|
773
|
+
*/
|
|
774
|
+
resolveWithTracking(target, resolving) {
|
|
775
|
+
if (this.instances.has(target)) {
|
|
776
|
+
this.emitLog({
|
|
777
|
+
level: "debug",
|
|
778
|
+
category: "di",
|
|
779
|
+
message: `Resolved ${target.name} from DI cache`
|
|
780
|
+
});
|
|
781
|
+
return this.instances.get(target);
|
|
782
|
+
}
|
|
783
|
+
if (resolving.has(target)) {
|
|
784
|
+
const cycle = [
|
|
785
|
+
...resolving.keys(),
|
|
786
|
+
target
|
|
787
|
+
].map((t) => t.name).join(" -> ");
|
|
788
|
+
this.emitLog({
|
|
789
|
+
level: "error",
|
|
790
|
+
category: "di",
|
|
791
|
+
message: `Circular dependency detected while resolving ${target.name}`,
|
|
792
|
+
details: {
|
|
793
|
+
cycle
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
throw new Error(`Circular dependency detected: ${cycle}`);
|
|
797
|
+
}
|
|
798
|
+
resolving.add(target);
|
|
799
|
+
this.emitLog({
|
|
800
|
+
level: "debug",
|
|
801
|
+
category: "di",
|
|
802
|
+
message: `Resolving ${target.name}`,
|
|
803
|
+
details: {
|
|
804
|
+
resolving: [
|
|
805
|
+
...resolving
|
|
806
|
+
].map((constructor) => constructor.name)
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
|
|
810
|
+
if (target.length > 0 && paramTypes.length === 0) {
|
|
811
|
+
if (!this.serviceRegistry.isService(target)) {
|
|
812
|
+
this.emitLog({
|
|
813
|
+
level: "error",
|
|
814
|
+
category: "di",
|
|
815
|
+
message: `Cannot resolve ${target.name}: missing @Service() decorator`
|
|
816
|
+
});
|
|
817
|
+
throw new Error(`Cannot resolve ${target.name}: it is not decorated with @Service(). Did you forget to add @Service() to the class?`);
|
|
818
|
+
}
|
|
819
|
+
this.emitLog({
|
|
820
|
+
level: "error",
|
|
821
|
+
category: "di",
|
|
822
|
+
message: `Cannot resolve ${target.name}: missing constructor metadata`
|
|
823
|
+
});
|
|
824
|
+
throw new Error(`Cannot resolve dependencies for ${target.name}: constructor metadata is missing. Ensure 'reflect-metadata' is imported and 'emitDecoratorMetadata' is enabled.`);
|
|
825
|
+
}
|
|
826
|
+
const dependencies = paramTypes.map((paramType, index) => {
|
|
827
|
+
if (!paramType || paramType === Object || paramType === Array || paramType === Function) {
|
|
828
|
+
this.emitLog({
|
|
829
|
+
level: "error",
|
|
830
|
+
category: "di",
|
|
831
|
+
message: `Cannot resolve dependency at index ${index} of ${target.name}`
|
|
832
|
+
});
|
|
833
|
+
throw new Error(`Cannot resolve dependency at index ${index} of ${target.name}. Use concrete class types for constructor dependencies.`);
|
|
834
|
+
}
|
|
835
|
+
return this.resolveWithTracking(paramType, new Set(resolving));
|
|
836
|
+
});
|
|
837
|
+
const instance = new target(...dependencies);
|
|
838
|
+
this.instances.set(target, instance);
|
|
839
|
+
this.emitLog({
|
|
840
|
+
level: "debug",
|
|
841
|
+
category: "di",
|
|
842
|
+
message: `Created ${target.name} instance`,
|
|
843
|
+
details: {
|
|
844
|
+
dependencyCount: dependencies.length
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
return instance;
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Registers a pre-created instance for a class
|
|
851
|
+
* @param target - The class constructor to register
|
|
852
|
+
* @param instance - The instance to register
|
|
853
|
+
*/
|
|
854
|
+
register(target, instance) {
|
|
855
|
+
this.instances.set(target, instance);
|
|
856
|
+
}
|
|
857
|
+
has(target) {
|
|
858
|
+
return this.instances.has(target);
|
|
859
|
+
}
|
|
860
|
+
clear() {
|
|
861
|
+
this.instances.clear();
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
// src/errors/framework.error.ts
|
|
866
|
+
var FrameworkError = class extends Error {
|
|
867
|
+
static {
|
|
868
|
+
__name(this, "FrameworkError");
|
|
869
|
+
}
|
|
870
|
+
status;
|
|
871
|
+
code;
|
|
872
|
+
category;
|
|
873
|
+
remediation;
|
|
874
|
+
details;
|
|
875
|
+
constructor(message, options) {
|
|
876
|
+
super(message);
|
|
877
|
+
this.name = "FrameworkError";
|
|
878
|
+
this.status = options.status;
|
|
879
|
+
this.code = options.code;
|
|
880
|
+
this.category = options.category;
|
|
881
|
+
this.remediation = options.remediation;
|
|
882
|
+
this.details = options.details;
|
|
883
|
+
if (options.cause !== void 0) {
|
|
884
|
+
this.cause = options.cause;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
// src/helpers/create-error-response.helper.ts
|
|
890
|
+
function createErrorResponse(exception, context, options) {
|
|
891
|
+
const normalizedException = exception instanceof Error ? exception : new Error(String(exception));
|
|
892
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
893
|
+
const requestId = context.get("requestId");
|
|
894
|
+
const path = context.req.path;
|
|
895
|
+
if (normalizedException instanceof httpException.HTTPException) {
|
|
896
|
+
const response2 = {
|
|
897
|
+
status: options?.status || normalizedException.status,
|
|
898
|
+
message: options?.title || normalizedException.message,
|
|
899
|
+
timestamp,
|
|
900
|
+
path,
|
|
901
|
+
requestId,
|
|
902
|
+
code: options?.code,
|
|
903
|
+
details: options?.additionalDetails,
|
|
904
|
+
...options?.detail && {
|
|
905
|
+
detail: options.detail
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
return {
|
|
909
|
+
response: response2,
|
|
910
|
+
status: options?.status || normalizedException.status
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
if (normalizedException instanceof FrameworkError) {
|
|
914
|
+
const status2 = options?.status || normalizedException.status || 500;
|
|
915
|
+
const response2 = {
|
|
916
|
+
status: status2,
|
|
917
|
+
message: options?.title || normalizedException.message,
|
|
918
|
+
timestamp,
|
|
919
|
+
path,
|
|
920
|
+
requestId,
|
|
921
|
+
code: options?.code || normalizedException.code,
|
|
922
|
+
details: {
|
|
923
|
+
category: normalizedException.category,
|
|
924
|
+
remediation: normalizedException.remediation,
|
|
925
|
+
...normalizedException.details,
|
|
926
|
+
...options?.additionalDetails
|
|
927
|
+
},
|
|
928
|
+
...options?.detail && {
|
|
929
|
+
detail: options.detail
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
return {
|
|
933
|
+
response: response2,
|
|
934
|
+
status: status2
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
if (normalizedException.statusCode || normalizedException.status) {
|
|
938
|
+
const defaultStatus = normalizedException.statusCode || normalizedException.status || 500;
|
|
939
|
+
const status2 = options?.status || defaultStatus;
|
|
940
|
+
const response2 = {
|
|
941
|
+
status: status2,
|
|
942
|
+
message: options?.title || normalizedException.message,
|
|
943
|
+
timestamp,
|
|
944
|
+
path,
|
|
945
|
+
requestId,
|
|
946
|
+
code: options?.code || normalizedException.name,
|
|
947
|
+
details: options?.additionalDetails,
|
|
948
|
+
...options?.detail && {
|
|
949
|
+
detail: options.detail
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
return {
|
|
953
|
+
response: response2,
|
|
954
|
+
status: status2
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
const status = options?.status || 500;
|
|
958
|
+
const response = {
|
|
959
|
+
status,
|
|
960
|
+
message: options?.title || (process.env.NODE_ENV === "production" ? "Internal Server Error" : normalizedException.message),
|
|
961
|
+
timestamp,
|
|
962
|
+
path,
|
|
963
|
+
requestId,
|
|
964
|
+
code: options?.code || normalizedException.name,
|
|
965
|
+
details: options?.additionalDetails || (process.env.NODE_ENV === "development" ? {
|
|
966
|
+
stack: normalizedException.stack
|
|
967
|
+
} : void 0),
|
|
968
|
+
...options?.detail && {
|
|
969
|
+
detail: options.detail
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
return {
|
|
973
|
+
response,
|
|
974
|
+
status
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
__name(createErrorResponse, "createErrorResponse");
|
|
978
|
+
|
|
979
|
+
// src/helpers/create-http-method-decorator.helper.ts
|
|
980
|
+
function createHttpMethodDecorator(method) {
|
|
981
|
+
return (path = "", options = {}) => {
|
|
982
|
+
return (target, propertyKey, descriptor) => {
|
|
983
|
+
const controllerClass = target.constructor;
|
|
984
|
+
MetadataRegistry.addRoute(controllerClass, {
|
|
985
|
+
path,
|
|
986
|
+
method,
|
|
987
|
+
handlerName: propertyKey,
|
|
988
|
+
version: options.version,
|
|
989
|
+
prefix: options.prefix
|
|
990
|
+
});
|
|
991
|
+
};
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
__name(createHttpMethodDecorator, "createHttpMethodDecorator");
|
|
995
|
+
|
|
996
|
+
// src/helpers/create-param-decorator.helper.ts
|
|
997
|
+
function createParamDecorator(type, factory) {
|
|
998
|
+
const fallbackFactory = /* @__PURE__ */ __name((data, ctx) => {
|
|
999
|
+
if (data === void 0) {
|
|
1000
|
+
return ctx;
|
|
1001
|
+
}
|
|
1002
|
+
return ctx.get(String(data));
|
|
1003
|
+
}, "fallbackFactory");
|
|
1004
|
+
return (data) => {
|
|
1005
|
+
return (target, propertyKey, parameterIndex) => {
|
|
1006
|
+
const controllerClass = target.constructor;
|
|
1007
|
+
if (!MetadataRegistry.getParameters(controllerClass).size) {
|
|
1008
|
+
MetadataRegistry.setParameterMap(controllerClass, /* @__PURE__ */ new Map());
|
|
1009
|
+
}
|
|
1010
|
+
const parametersMap = MetadataRegistry.getParameters(controllerClass);
|
|
1011
|
+
if (!parametersMap.has(propertyKey)) {
|
|
1012
|
+
parametersMap.set(propertyKey, []);
|
|
1013
|
+
}
|
|
1014
|
+
const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey);
|
|
1015
|
+
const metatype = paramTypes?.[parameterIndex];
|
|
1016
|
+
const parameters = parametersMap.get(propertyKey);
|
|
1017
|
+
parameters.push({
|
|
1018
|
+
index: parameterIndex,
|
|
1019
|
+
name: type,
|
|
1020
|
+
data,
|
|
1021
|
+
factory: factory || fallbackFactory,
|
|
1022
|
+
metatype
|
|
1023
|
+
});
|
|
1024
|
+
if (type === "context") {
|
|
1025
|
+
if (!MetadataRegistry.getContextIndices(controllerClass).size) {
|
|
1026
|
+
MetadataRegistry.setContextIndices(controllerClass, /* @__PURE__ */ new Map());
|
|
1027
|
+
}
|
|
1028
|
+
const contextIndices = MetadataRegistry.getContextIndices(controllerClass);
|
|
1029
|
+
contextIndices.set(propertyKey, parameterIndex);
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
__name(createParamDecorator, "createParamDecorator");
|
|
1035
|
+
|
|
1036
|
+
// src/handlers/error.handler.ts
|
|
1037
|
+
var ErrorHandler = class {
|
|
1038
|
+
static {
|
|
1039
|
+
__name(this, "ErrorHandler");
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Creates a middleware function that handles error responses
|
|
1043
|
+
* @returns A middleware function that formats and returns error responses using createErrorResponse
|
|
1044
|
+
*/
|
|
1045
|
+
static handle() {
|
|
1046
|
+
return async (err, c) => {
|
|
1047
|
+
const { response, status } = createErrorResponse(err, c);
|
|
1048
|
+
return c.json(response, status);
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
// src/handlers/not-found.handler.ts
|
|
1054
|
+
var NotFoundHandler = class {
|
|
1055
|
+
static {
|
|
1056
|
+
__name(this, "NotFoundHandler");
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Creates a middleware function that handles 404 Not Found responses
|
|
1060
|
+
* @returns A middleware function that returns a JSON response with a 404 status
|
|
1061
|
+
*/
|
|
1062
|
+
static handle() {
|
|
1063
|
+
return async (c) => {
|
|
1064
|
+
return c.json({
|
|
1065
|
+
message: `Not Found - ${c.req.path}`
|
|
1066
|
+
}, 404);
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
|
|
1071
|
+
// src/constants/version.constants.ts
|
|
1072
|
+
var VERSION_NEUTRAL = /* @__PURE__ */ Symbol("VERSION_NEUTRAL");
|
|
1073
|
+
|
|
1074
|
+
// src/constants/pipeline.constants.ts
|
|
1075
|
+
var HONEST_PIPELINE_CONTROLLER_KEY = "__honest_controllerClass";
|
|
1076
|
+
var HONEST_PIPELINE_HANDLER_KEY = "__honest_handlerName";
|
|
1077
|
+
var HONEST_PIPELINE_BODY_CACHE_KEY = "__honest.body.cache";
|
|
1078
|
+
|
|
1079
|
+
// src/managers/component.manager.ts
|
|
1080
|
+
var ComponentManager = class {
|
|
1081
|
+
static {
|
|
1082
|
+
__name(this, "ComponentManager");
|
|
1083
|
+
}
|
|
1084
|
+
container;
|
|
1085
|
+
metadataRepository;
|
|
1086
|
+
logger;
|
|
1087
|
+
globalComponents = /* @__PURE__ */ new Map([
|
|
1088
|
+
[
|
|
1089
|
+
"middleware",
|
|
1090
|
+
/* @__PURE__ */ new Set()
|
|
1091
|
+
],
|
|
1092
|
+
[
|
|
1093
|
+
"guard",
|
|
1094
|
+
/* @__PURE__ */ new Set()
|
|
1095
|
+
],
|
|
1096
|
+
[
|
|
1097
|
+
"pipe",
|
|
1098
|
+
/* @__PURE__ */ new Set()
|
|
1099
|
+
],
|
|
1100
|
+
[
|
|
1101
|
+
"filter",
|
|
1102
|
+
/* @__PURE__ */ new Set()
|
|
1103
|
+
]
|
|
1104
|
+
]);
|
|
1105
|
+
constructor(container, metadataRepository, logger = new NoopLogger()) {
|
|
1106
|
+
this.container = container;
|
|
1107
|
+
this.metadataRepository = metadataRepository;
|
|
1108
|
+
this.logger = logger;
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* Configures global components from application options.
|
|
1112
|
+
*/
|
|
1113
|
+
setupGlobalComponents(options) {
|
|
1114
|
+
const components = options.components || {};
|
|
1115
|
+
if (components.middleware) {
|
|
1116
|
+
this.registerGlobal("middleware", ...components.middleware);
|
|
1117
|
+
}
|
|
1118
|
+
if (components.guards) {
|
|
1119
|
+
this.registerGlobal("guard", ...components.guards);
|
|
1120
|
+
}
|
|
1121
|
+
if (components.pipes) {
|
|
1122
|
+
this.registerGlobal("pipe", ...components.pipes);
|
|
1123
|
+
}
|
|
1124
|
+
if (components.filters) {
|
|
1125
|
+
this.registerGlobal("filter", ...components.filters);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
registerGlobal(type, ...components) {
|
|
1129
|
+
components.forEach((component) => {
|
|
1130
|
+
this.globalComponents.get(type).add(component);
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
getGlobal(type) {
|
|
1134
|
+
return this.globalComponents.get(type);
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Gets all components of a specific type for a handler.
|
|
1138
|
+
* Merges: instance global → static controller → static handler.
|
|
1139
|
+
*/
|
|
1140
|
+
getComponents(type, controller, handlerName) {
|
|
1141
|
+
const handlerComponents = this.metadataRepository.getHandlerComponents(type, controller, handlerName);
|
|
1142
|
+
const controllerComponents = this.metadataRepository.getControllerComponents(type, controller);
|
|
1143
|
+
const globalComponents = Array.from(this.globalComponents.get(type) || []);
|
|
1144
|
+
return [
|
|
1145
|
+
...globalComponents,
|
|
1146
|
+
...controllerComponents,
|
|
1147
|
+
...handlerComponents
|
|
1148
|
+
];
|
|
1149
|
+
}
|
|
1150
|
+
// -- Middleware --
|
|
1151
|
+
resolveMiddleware(middlewareItems) {
|
|
1152
|
+
return middlewareItems.map((middlewareItem) => {
|
|
1153
|
+
if (isObject(middlewareItem) && "use" in middlewareItem) {
|
|
1154
|
+
return middlewareItem.use.bind(middlewareItem);
|
|
1155
|
+
}
|
|
1156
|
+
const middleware = this.container.resolve(middlewareItem);
|
|
1157
|
+
return middleware.use.bind(middleware);
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
getHandlerMiddleware(controller, handlerName) {
|
|
1161
|
+
const controllerMiddleware = this.metadataRepository.getControllerComponents("middleware", controller);
|
|
1162
|
+
const handlerMiddleware = this.metadataRepository.getHandlerComponents("middleware", controller, handlerName);
|
|
1163
|
+
return this.resolveMiddleware([
|
|
1164
|
+
...controllerMiddleware,
|
|
1165
|
+
...handlerMiddleware
|
|
1166
|
+
]);
|
|
1167
|
+
}
|
|
1168
|
+
getGlobalMiddleware() {
|
|
1169
|
+
const globalMiddleware = Array.from(this.globalComponents.get("middleware") || []);
|
|
1170
|
+
return this.resolveMiddleware(globalMiddleware);
|
|
1171
|
+
}
|
|
1172
|
+
// -- Guards --
|
|
1173
|
+
resolveGuards(guardItems) {
|
|
1174
|
+
return guardItems.map((guardItem) => {
|
|
1175
|
+
if (isObject(guardItem) && "canActivate" in guardItem) {
|
|
1176
|
+
return guardItem;
|
|
1177
|
+
}
|
|
1178
|
+
return this.container.resolve(guardItem);
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
getHandlerGuards(controller, handlerName) {
|
|
1182
|
+
const guardItems = this.getComponents("guard", controller, handlerName);
|
|
1183
|
+
return this.resolveGuards(guardItems);
|
|
1184
|
+
}
|
|
1185
|
+
// -- Pipes --
|
|
1186
|
+
resolvePipes(pipeItems) {
|
|
1187
|
+
return pipeItems.map((pipeItem) => {
|
|
1188
|
+
if (isObject(pipeItem) && "transform" in pipeItem) {
|
|
1189
|
+
return pipeItem;
|
|
1190
|
+
}
|
|
1191
|
+
return this.container.resolve(pipeItem);
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
getHandlerPipes(controller, handlerName) {
|
|
1195
|
+
const pipeItems = this.getComponents("pipe", controller, handlerName);
|
|
1196
|
+
return this.resolvePipes(pipeItems);
|
|
1197
|
+
}
|
|
1198
|
+
async executePipes(value, metadata, pipes) {
|
|
1199
|
+
let transformedValue = value;
|
|
1200
|
+
for (const pipe of pipes) {
|
|
1201
|
+
transformedValue = await pipe.transform(transformedValue, metadata);
|
|
1202
|
+
}
|
|
1203
|
+
return transformedValue;
|
|
1204
|
+
}
|
|
1205
|
+
// -- Filters --
|
|
1206
|
+
async handleException(exception, context) {
|
|
1207
|
+
const normalizedException = exception instanceof Error ? exception : new Error(String(exception));
|
|
1208
|
+
const controller = context.get(HONEST_PIPELINE_CONTROLLER_KEY);
|
|
1209
|
+
const handlerName = context.get(HONEST_PIPELINE_HANDLER_KEY);
|
|
1210
|
+
if (controller && handlerName) {
|
|
1211
|
+
const handlerFilters = this.metadataRepository.getHandlerComponents("filter", controller, handlerName);
|
|
1212
|
+
if (handlerFilters.length > 0) {
|
|
1213
|
+
const response2 = await this.executeFilters(handlerFilters, normalizedException, context);
|
|
1214
|
+
if (response2) return response2;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
if (controller) {
|
|
1218
|
+
const controllerFilters = this.metadataRepository.getControllerComponents("filter", controller);
|
|
1219
|
+
if (controllerFilters.length > 0) {
|
|
1220
|
+
const response2 = await this.executeFilters(controllerFilters, normalizedException, context);
|
|
1221
|
+
if (response2) return response2;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
const globalFilters = Array.from(this.globalComponents.get("filter") || []);
|
|
1225
|
+
if (globalFilters.length > 0) {
|
|
1226
|
+
const response2 = await this.executeFilters(globalFilters, normalizedException, context);
|
|
1227
|
+
if (response2) return response2;
|
|
1228
|
+
}
|
|
1229
|
+
const { response, status } = createErrorResponse(normalizedException, context);
|
|
1230
|
+
return context.json(response, status);
|
|
1231
|
+
}
|
|
1232
|
+
async executeFilters(filterItems, exception, context) {
|
|
1233
|
+
for (const filterItem of filterItems) {
|
|
1234
|
+
let filter;
|
|
1235
|
+
if (isObject(filterItem) && "catch" in filterItem) {
|
|
1236
|
+
filter = filterItem;
|
|
1237
|
+
} else {
|
|
1238
|
+
filter = this.container.resolve(filterItem);
|
|
1239
|
+
}
|
|
1240
|
+
try {
|
|
1241
|
+
const result = await filter.catch(exception, context);
|
|
1242
|
+
if (result !== void 0) {
|
|
1243
|
+
return result;
|
|
1244
|
+
}
|
|
1245
|
+
} catch (filterError) {
|
|
1246
|
+
const filterName = filter.constructor?.name || "UnknownFilter";
|
|
1247
|
+
this.logger.emit({
|
|
1248
|
+
level: "error",
|
|
1249
|
+
category: "errors",
|
|
1250
|
+
message: `Error in exception filter ${filterName}`,
|
|
1251
|
+
details: {
|
|
1252
|
+
error: filterError instanceof Error ? filterError.message : String(filterError)
|
|
1253
|
+
}
|
|
1254
|
+
});
|
|
1255
|
+
const { response, status } = createErrorResponse(filterError, context);
|
|
1256
|
+
return context.json(response, status);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return void 0;
|
|
1260
|
+
}
|
|
1261
|
+
// -- Module registration --
|
|
1262
|
+
async registerModule(moduleClass, registered = /* @__PURE__ */ new Set()) {
|
|
1263
|
+
if (registered.has(moduleClass)) {
|
|
1264
|
+
return [];
|
|
1265
|
+
}
|
|
1266
|
+
registered.add(moduleClass);
|
|
1267
|
+
const moduleOptions = this.metadataRepository.getModuleOptions(moduleClass);
|
|
1268
|
+
if (!moduleOptions) {
|
|
1269
|
+
this.logger.emit({
|
|
1270
|
+
level: "error",
|
|
1271
|
+
category: "startup",
|
|
1272
|
+
message: `Module ${moduleClass.name} is not properly decorated with @Module()`
|
|
1273
|
+
});
|
|
1274
|
+
throw new Error(`Module ${moduleClass.name} is not properly decorated with @Module()`);
|
|
1275
|
+
}
|
|
1276
|
+
const controllers = [];
|
|
1277
|
+
if (moduleOptions.imports && moduleOptions.imports.length > 0) {
|
|
1278
|
+
for (const importedModule of moduleOptions.imports) {
|
|
1279
|
+
const importedControllers = await this.registerModule(importedModule, registered);
|
|
1280
|
+
controllers.push(...importedControllers);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
if (moduleOptions.services && moduleOptions.services.length > 0) {
|
|
1284
|
+
for (const serviceClass of moduleOptions.services) {
|
|
1285
|
+
this.container.resolve(serviceClass);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
if (moduleOptions.controllers && moduleOptions.controllers.length > 0) {
|
|
1289
|
+
controllers.push(...moduleOptions.controllers);
|
|
1290
|
+
}
|
|
1291
|
+
return controllers;
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
|
|
1295
|
+
// src/managers/handler.invoker.ts
|
|
1296
|
+
var HandlerInvoker = class {
|
|
1297
|
+
static {
|
|
1298
|
+
__name(this, "HandlerInvoker");
|
|
1299
|
+
}
|
|
1300
|
+
async invoke({ handler, args, context, contextIndex }) {
|
|
1301
|
+
const result = await handler(...args);
|
|
1302
|
+
if (contextIndex !== void 0) {
|
|
1303
|
+
return result;
|
|
1304
|
+
}
|
|
1305
|
+
if (result instanceof Response) {
|
|
1306
|
+
return result;
|
|
1307
|
+
}
|
|
1308
|
+
if (isNil(result)) {
|
|
1309
|
+
return context.json(null);
|
|
1310
|
+
}
|
|
1311
|
+
if (isString(result)) {
|
|
1312
|
+
return context.text(result);
|
|
1313
|
+
}
|
|
1314
|
+
try {
|
|
1315
|
+
return context.json(result);
|
|
1316
|
+
} catch (error) {
|
|
1317
|
+
throw new FrameworkError("Handler return value could not be serialized as JSON.", {
|
|
1318
|
+
status: 500,
|
|
1319
|
+
code: "RESPONSE_SERIALIZATION_FAILED",
|
|
1320
|
+
category: "pipeline",
|
|
1321
|
+
remediation: "Return JSON-serializable values from handlers or map custom values in a filter before returning.",
|
|
1322
|
+
details: {
|
|
1323
|
+
handlerResultType: typeof result
|
|
1324
|
+
},
|
|
1325
|
+
cause: error
|
|
1326
|
+
});
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
|
|
1331
|
+
// src/managers/parameter.resolver.ts
|
|
1332
|
+
var ParameterResolver = class {
|
|
1333
|
+
static {
|
|
1334
|
+
__name(this, "ParameterResolver");
|
|
1335
|
+
}
|
|
1336
|
+
componentManager;
|
|
1337
|
+
logger;
|
|
1338
|
+
debugPipeline;
|
|
1339
|
+
constructor(componentManager, logger = new NoopLogger(), debugPipeline = false) {
|
|
1340
|
+
this.componentManager = componentManager;
|
|
1341
|
+
this.logger = logger;
|
|
1342
|
+
this.debugPipeline = debugPipeline;
|
|
1343
|
+
}
|
|
1344
|
+
async resolveArguments(input) {
|
|
1345
|
+
const { controllerName, handlerName, handlerArity, handlerParams, handlerPipes, context } = input;
|
|
1346
|
+
const maxDecoratorIndex = handlerParams.length > 0 ? Math.max(...handlerParams.map((parameter) => parameter.index)) : -1;
|
|
1347
|
+
const args = new Array(Math.max(handlerArity, maxDecoratorIndex + 1));
|
|
1348
|
+
const decoratedIndices = new Set(handlerParams.map((parameter) => parameter.index));
|
|
1349
|
+
if (this.debugPipeline && maxDecoratorIndex >= 0) {
|
|
1350
|
+
const sparseIndices = [];
|
|
1351
|
+
for (let i = 0; i <= maxDecoratorIndex; i++) {
|
|
1352
|
+
if (!decoratedIndices.has(i)) {
|
|
1353
|
+
sparseIndices.push(i);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
const hasOutOfRangeDecoratorIndex = maxDecoratorIndex >= handlerArity;
|
|
1357
|
+
if (sparseIndices.length > 0 || hasOutOfRangeDecoratorIndex) {
|
|
1358
|
+
this.logger.emit({
|
|
1359
|
+
level: "warn",
|
|
1360
|
+
category: "pipeline",
|
|
1361
|
+
message: `Potential parameter binding mismatch at ${controllerName}.${String(handlerName)}`,
|
|
1362
|
+
details: {
|
|
1363
|
+
handlerArity,
|
|
1364
|
+
maxDecoratorIndex,
|
|
1365
|
+
sparseIndices,
|
|
1366
|
+
handlerParamCount: handlerParams.length
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
for (const parameter of handlerParams) {
|
|
1372
|
+
if (typeof parameter.factory !== "function") {
|
|
1373
|
+
throw new Error(`Invalid parameter decorator metadata for ${controllerName}.${String(handlerName)}`);
|
|
1374
|
+
}
|
|
1375
|
+
const rawValue = await parameter.factory(parameter.data, context);
|
|
1376
|
+
const transformedValue = await this.componentManager.executePipes(rawValue, {
|
|
1377
|
+
type: parameter.name,
|
|
1378
|
+
metatype: parameter.metatype,
|
|
1379
|
+
data: typeof parameter.data === "string" || typeof parameter.data === "undefined" ? parameter.data : String(parameter.data)
|
|
1380
|
+
}, handlerPipes);
|
|
1381
|
+
args[parameter.index] = transformedValue;
|
|
1382
|
+
}
|
|
1383
|
+
return args;
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
var PipelineExecutor = class {
|
|
1387
|
+
static {
|
|
1388
|
+
__name(this, "PipelineExecutor");
|
|
1389
|
+
}
|
|
1390
|
+
componentManager;
|
|
1391
|
+
parameterResolver;
|
|
1392
|
+
handlerInvoker;
|
|
1393
|
+
logger;
|
|
1394
|
+
debugPipeline;
|
|
1395
|
+
constructor(componentManager, parameterResolver, handlerInvoker, logger = new NoopLogger(), debugPipeline = false) {
|
|
1396
|
+
this.componentManager = componentManager;
|
|
1397
|
+
this.parameterResolver = parameterResolver;
|
|
1398
|
+
this.handlerInvoker = handlerInvoker;
|
|
1399
|
+
this.logger = logger;
|
|
1400
|
+
this.debugPipeline = debugPipeline;
|
|
1401
|
+
}
|
|
1402
|
+
async execute(input) {
|
|
1403
|
+
const { controllerClass, handlerName, handler, handlerParams, handlerPipes, contextIndex, context } = input;
|
|
1404
|
+
context.set(HONEST_PIPELINE_CONTROLLER_KEY, controllerClass);
|
|
1405
|
+
context.set(HONEST_PIPELINE_HANDLER_KEY, String(handlerName));
|
|
1406
|
+
const guards = this.componentManager.getHandlerGuards(controllerClass, handlerName);
|
|
1407
|
+
for (const guard of guards) {
|
|
1408
|
+
const canActivate = await guard.canActivate(context);
|
|
1409
|
+
if (!canActivate) {
|
|
1410
|
+
if (this.debugPipeline) {
|
|
1411
|
+
this.logger.emit({
|
|
1412
|
+
level: "warn",
|
|
1413
|
+
category: "pipeline",
|
|
1414
|
+
message: `Guard rejected request at ${controllerClass.name}.${String(handlerName)}`,
|
|
1415
|
+
details: {
|
|
1416
|
+
guard: guard.constructor?.name || "UnknownGuard"
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
throw new httpException.HTTPException(403, {
|
|
1421
|
+
message: `Forbidden by ${guard.constructor?.name || "UnknownGuard"} at ${controllerClass.name}.${String(handlerName)}`
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
const args = await this.parameterResolver.resolveArguments({
|
|
1426
|
+
controllerName: controllerClass.name,
|
|
1427
|
+
handlerName,
|
|
1428
|
+
handlerArity: handler.length,
|
|
1429
|
+
handlerParams,
|
|
1430
|
+
handlerPipes,
|
|
1431
|
+
context
|
|
1432
|
+
});
|
|
1433
|
+
if (this.debugPipeline) {
|
|
1434
|
+
this.logger.emit({
|
|
1435
|
+
level: "debug",
|
|
1436
|
+
category: "pipeline",
|
|
1437
|
+
message: `Resolved handler arguments for ${controllerClass.name}.${String(handlerName)}`,
|
|
1438
|
+
details: {
|
|
1439
|
+
guardCount: guards.length,
|
|
1440
|
+
parameterCount: handlerParams.length,
|
|
1441
|
+
pipeCount: handlerPipes.length
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
}
|
|
1445
|
+
return this.handlerInvoker.invoke({
|
|
1446
|
+
handler,
|
|
1447
|
+
args,
|
|
1448
|
+
context,
|
|
1449
|
+
contextIndex
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
|
|
1454
|
+
// src/managers/route.manager.ts
|
|
1455
|
+
var RouteManager = class {
|
|
1456
|
+
static {
|
|
1457
|
+
__name(this, "RouteManager");
|
|
1458
|
+
}
|
|
1459
|
+
hono;
|
|
1460
|
+
container;
|
|
1461
|
+
routeRegistry;
|
|
1462
|
+
componentManager;
|
|
1463
|
+
parameterResolver;
|
|
1464
|
+
pipelineExecutor;
|
|
1465
|
+
metadataRepository;
|
|
1466
|
+
logger;
|
|
1467
|
+
globalPrefix;
|
|
1468
|
+
globalVersion;
|
|
1469
|
+
constructor(hono, container, routeRegistry, componentManager, metadataRepository, logger = new NoopLogger(), options = {}) {
|
|
1470
|
+
this.hono = hono;
|
|
1471
|
+
this.container = container;
|
|
1472
|
+
this.routeRegistry = routeRegistry;
|
|
1473
|
+
this.componentManager = componentManager;
|
|
1474
|
+
this.logger = logger;
|
|
1475
|
+
this.parameterResolver = new ParameterResolver(this.componentManager, this.logger, Boolean(options.debugPipeline));
|
|
1476
|
+
this.pipelineExecutor = new PipelineExecutor(this.componentManager, this.parameterResolver, new HandlerInvoker(), this.logger, Boolean(options.debugPipeline));
|
|
1477
|
+
this.metadataRepository = metadataRepository;
|
|
1478
|
+
this.globalPrefix = options.prefix !== void 0 ? this.normalizePath(options.prefix) : void 0;
|
|
1479
|
+
this.globalVersion = options.version;
|
|
1480
|
+
this.applyGlobalMiddleware();
|
|
1481
|
+
}
|
|
1482
|
+
applyGlobalMiddleware() {
|
|
1483
|
+
const globalMiddleware = this.componentManager.getGlobalMiddleware();
|
|
1484
|
+
for (const middleware of globalMiddleware) {
|
|
1485
|
+
this.hono.use("*", middleware);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
normalizePath(path) {
|
|
1489
|
+
if (!isString(path)) {
|
|
1490
|
+
throw new Error(`Invalid path: expected a string but received ${typeof path}. Check your @Controller() and route decorator arguments.`);
|
|
1491
|
+
}
|
|
1492
|
+
return normalizePath(path);
|
|
1493
|
+
}
|
|
1494
|
+
registerRouteHandler(method, path, handlerMiddleware, wrapperHandler) {
|
|
1495
|
+
if (handlerMiddleware.length > 0) {
|
|
1496
|
+
this.hono.on(method.toUpperCase(), [
|
|
1497
|
+
path
|
|
1498
|
+
], ...handlerMiddleware, wrapperHandler);
|
|
1499
|
+
} else {
|
|
1500
|
+
this.hono.on(method.toUpperCase(), [
|
|
1501
|
+
path
|
|
1502
|
+
], wrapperHandler);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
buildRoutePath(prefix, version, controllerPath, methodPath) {
|
|
1506
|
+
return normalizePath(`${prefix}${version}${controllerPath}${methodPath}`);
|
|
1507
|
+
}
|
|
1508
|
+
formatVersionSegment(version) {
|
|
1509
|
+
if (isNil(version)) {
|
|
1510
|
+
return "";
|
|
1511
|
+
}
|
|
1512
|
+
return version === VERSION_NEUTRAL ? "" : `/v${String(version)}`;
|
|
1513
|
+
}
|
|
1514
|
+
async registerController(controllerClass) {
|
|
1515
|
+
if (!this.metadataRepository.hasController(controllerClass)) {
|
|
1516
|
+
throw new Error(`Controller ${controllerClass.name} is not decorated with @Controller()`);
|
|
1517
|
+
}
|
|
1518
|
+
const controllerPath = this.metadataRepository.getControllerPath(controllerClass) || "";
|
|
1519
|
+
const controllerOptions = this.metadataRepository.getControllerOptions(controllerClass) || {};
|
|
1520
|
+
const routes = this.metadataRepository.getRoutes(controllerClass) || [];
|
|
1521
|
+
const parameterMetadata = this.metadataRepository.getParameters(controllerClass) || /* @__PURE__ */ new Map();
|
|
1522
|
+
const contextIndices = this.metadataRepository.getContextIndices(controllerClass) || /* @__PURE__ */ new Map();
|
|
1523
|
+
const controllerSegment = this.normalizePath(controllerPath);
|
|
1524
|
+
const controllerInstance = this.container.resolve(controllerClass);
|
|
1525
|
+
const effectiveControllerPrefix = controllerOptions.prefix !== void 0 ? controllerOptions.prefix : this.globalPrefix;
|
|
1526
|
+
const effectiveControllerVersion = controllerOptions.version !== void 0 ? controllerOptions.version : this.globalVersion;
|
|
1527
|
+
if (routes.length === 0) {
|
|
1528
|
+
throw new Error(`Controller ${controllerClass.name} has no route handlers. Add HTTP method decorators like @Get()`);
|
|
1529
|
+
}
|
|
1530
|
+
for (const route of routes) {
|
|
1531
|
+
const { path, method, version: routeVersion, prefix: routePrefix } = route;
|
|
1532
|
+
const effectivePrefix = routePrefix !== void 0 ? routePrefix : effectiveControllerPrefix;
|
|
1533
|
+
const prefixSegment = !isNil(effectivePrefix) ? this.normalizePath(effectivePrefix) : "";
|
|
1534
|
+
const effectiveVersion = routeVersion !== void 0 ? routeVersion : effectiveControllerVersion;
|
|
1535
|
+
const methodSegment = this.normalizePath(path);
|
|
1536
|
+
if (isNil(effectiveVersion)) {
|
|
1537
|
+
this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, "", controllerSegment, methodSegment, method);
|
|
1538
|
+
continue;
|
|
1539
|
+
}
|
|
1540
|
+
if (effectiveVersion === VERSION_NEUTRAL) {
|
|
1541
|
+
this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, "", controllerSegment, methodSegment, method);
|
|
1542
|
+
this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, "/:version{v[0-9]+}", controllerSegment, methodSegment, method);
|
|
1543
|
+
continue;
|
|
1544
|
+
}
|
|
1545
|
+
if (Array.isArray(effectiveVersion)) {
|
|
1546
|
+
for (const version of effectiveVersion) {
|
|
1547
|
+
const versionSegment2 = this.formatVersionSegment(version);
|
|
1548
|
+
this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, versionSegment2, controllerSegment, methodSegment, method);
|
|
1549
|
+
}
|
|
1550
|
+
continue;
|
|
1551
|
+
}
|
|
1552
|
+
const versionSegment = this.formatVersionSegment(effectiveVersion);
|
|
1553
|
+
this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, versionSegment, controllerSegment, methodSegment, method);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, versionSegment, controllerSegment, methodSegment, method) {
|
|
1557
|
+
const { handlerName } = route;
|
|
1558
|
+
const fullPath = this.buildRoutePath(prefixSegment, versionSegment, controllerSegment, methodSegment);
|
|
1559
|
+
const handler = controllerInstance[handlerName].bind(controllerInstance);
|
|
1560
|
+
const handlerParams = parameterMetadata.get(handlerName) || [];
|
|
1561
|
+
const contextIndex = contextIndices.get(handlerName);
|
|
1562
|
+
const handlerMiddleware = this.componentManager.getHandlerMiddleware(controllerClass, handlerName);
|
|
1563
|
+
const handlerPipes = this.componentManager.getHandlerPipes(controllerClass, handlerName);
|
|
1564
|
+
this.routeRegistry.registerRoute({
|
|
1565
|
+
controller: controllerClass.name,
|
|
1566
|
+
handler: handlerName,
|
|
1567
|
+
method,
|
|
1568
|
+
prefix: prefixSegment,
|
|
1569
|
+
version: versionSegment,
|
|
1570
|
+
route: controllerSegment,
|
|
1571
|
+
path: methodSegment,
|
|
1572
|
+
fullPath,
|
|
1573
|
+
parameters: handlerParams
|
|
1574
|
+
});
|
|
1575
|
+
const componentManager = this.componentManager;
|
|
1576
|
+
const pipelineExecutor = this.pipelineExecutor;
|
|
1577
|
+
const wrapperHandler = /* @__PURE__ */ __name(async (c) => {
|
|
1578
|
+
try {
|
|
1579
|
+
return await pipelineExecutor.execute({
|
|
1580
|
+
controllerClass,
|
|
1581
|
+
handlerName,
|
|
1582
|
+
handler,
|
|
1583
|
+
handlerParams,
|
|
1584
|
+
handlerPipes,
|
|
1585
|
+
contextIndex,
|
|
1586
|
+
context: c
|
|
1587
|
+
});
|
|
1588
|
+
} catch (error) {
|
|
1589
|
+
return componentManager.handleException(error, c);
|
|
1590
|
+
}
|
|
1591
|
+
}, "wrapperHandler");
|
|
1592
|
+
this.registerRouteHandler(method, fullPath, handlerMiddleware, wrapperHandler);
|
|
1593
|
+
}
|
|
1594
|
+
};
|
|
1595
|
+
|
|
1596
|
+
// src/application.ts
|
|
1597
|
+
var Application = class _Application {
|
|
1598
|
+
static {
|
|
1599
|
+
__name(this, "Application");
|
|
1600
|
+
}
|
|
1601
|
+
hono;
|
|
1602
|
+
container;
|
|
1603
|
+
context;
|
|
1604
|
+
routeRegistry;
|
|
1605
|
+
metadataRepository;
|
|
1606
|
+
componentManager;
|
|
1607
|
+
routeManager;
|
|
1608
|
+
logger;
|
|
1609
|
+
options;
|
|
1610
|
+
constructor(options = {}, metadataRepository) {
|
|
1611
|
+
this.options = isObject(options) ? options : {};
|
|
1612
|
+
const debugPipeline = this.options.debug === true || typeof this.options.debug === "object" && Boolean(this.options.debug.pipeline);
|
|
1613
|
+
const debugDi = this.options.debug === true || typeof this.options.debug === "object" && Boolean(this.options.debug.di);
|
|
1614
|
+
this.hono = new hono.Hono(this.options.hono);
|
|
1615
|
+
this.logger = this.options.logger || new ConsoleLogger();
|
|
1616
|
+
this.container = this.options.container || new Container(void 0, this.logger, debugDi);
|
|
1617
|
+
this.context = new ApplicationContext();
|
|
1618
|
+
this.routeRegistry = new RouteRegistry();
|
|
1619
|
+
this.metadataRepository = metadataRepository;
|
|
1620
|
+
this.componentManager = new ComponentManager(this.container, this.metadataRepository, this.logger);
|
|
1621
|
+
this.componentManager.setupGlobalComponents(this.options);
|
|
1622
|
+
this.setupErrorHandlers();
|
|
1623
|
+
this.routeManager = new RouteManager(this.hono, this.container, this.routeRegistry, this.componentManager, this.metadataRepository, this.logger, {
|
|
1624
|
+
prefix: this.options.routing?.prefix,
|
|
1625
|
+
version: this.options.routing?.version,
|
|
1626
|
+
debugPipeline
|
|
1627
|
+
});
|
|
1628
|
+
if (this.options.deprecations?.printPreV1Warning) {
|
|
1629
|
+
this.logger.emit({
|
|
1630
|
+
level: "warn",
|
|
1631
|
+
category: "deprecations",
|
|
1632
|
+
message: "Pre-v1 warning: APIs may change before 1.0.0."
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
setupErrorHandlers() {
|
|
1637
|
+
this.hono.notFound(this.options.notFound || NotFoundHandler.handle());
|
|
1638
|
+
this.hono.onError(this.options.onError || ErrorHandler.handle());
|
|
1639
|
+
}
|
|
1640
|
+
shouldEmitRouteDiagnostics() {
|
|
1641
|
+
const debug = this.options.debug;
|
|
1642
|
+
return debug === true || typeof debug === "object" && Boolean(debug.routes);
|
|
1643
|
+
}
|
|
1644
|
+
emitStartupGuide(error, rootModule) {
|
|
1645
|
+
emitStartupGuide(this.logger, this.options.startupGuide, error, rootModule);
|
|
1646
|
+
}
|
|
1647
|
+
async register(moduleClass) {
|
|
1648
|
+
const controllers = await this.componentManager.registerModule(moduleClass);
|
|
1649
|
+
const debugRoutes = this.shouldEmitRouteDiagnostics();
|
|
1650
|
+
for (const controller of controllers) {
|
|
1651
|
+
const controllerStartedAt = Date.now();
|
|
1652
|
+
const routeCountBefore = this.routeRegistry.getRoutes().length;
|
|
1653
|
+
try {
|
|
1654
|
+
await this.routeManager.registerController(controller);
|
|
1655
|
+
if (debugRoutes) {
|
|
1656
|
+
this.logger.emit({
|
|
1657
|
+
level: "info",
|
|
1658
|
+
category: "routes",
|
|
1659
|
+
message: "Registered controller routes",
|
|
1660
|
+
details: {
|
|
1661
|
+
controller: controller.name,
|
|
1662
|
+
routeCountAdded: this.routeRegistry.getRoutes().length - routeCountBefore,
|
|
1663
|
+
registrationDurationMs: Date.now() - controllerStartedAt
|
|
1664
|
+
}
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
} catch (error) {
|
|
1668
|
+
if (debugRoutes) {
|
|
1669
|
+
this.logger.emit({
|
|
1670
|
+
level: "error",
|
|
1671
|
+
category: "routes",
|
|
1672
|
+
message: "Failed to register controller routes",
|
|
1673
|
+
details: {
|
|
1674
|
+
controller: controller.name,
|
|
1675
|
+
registrationDurationMs: Date.now() - controllerStartedAt,
|
|
1676
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
1677
|
+
}
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1680
|
+
throw error;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
return this;
|
|
1684
|
+
}
|
|
1685
|
+
static async create(rootModule, options = {}) {
|
|
1686
|
+
const startupStartedAt = Date.now();
|
|
1687
|
+
const metadataSnapshot = MetadataRepository.fromRootModule(rootModule);
|
|
1688
|
+
const app = new _Application(options, metadataSnapshot);
|
|
1689
|
+
const entries = normalizePluginEntries(options.plugins);
|
|
1690
|
+
const ctx = app.getContext();
|
|
1691
|
+
const debug = options.debug;
|
|
1692
|
+
const debugPlugins = debug === true || typeof debug === "object" && debug.plugins;
|
|
1693
|
+
const debugRoutes = debug === true || typeof debug === "object" && debug.routes;
|
|
1694
|
+
const debugStartup = debug === true || typeof debug === "object" && (debug.startup || debugRoutes);
|
|
1695
|
+
let strictNoRoutesFailureEmitted = false;
|
|
1696
|
+
try {
|
|
1697
|
+
if (debugPlugins && entries.length > 0) {
|
|
1698
|
+
app.logger.emit({
|
|
1699
|
+
level: "info",
|
|
1700
|
+
category: "plugins",
|
|
1701
|
+
message: `Plugin order: ${entries.map(({ name }) => name).join(" -> ")}`
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
for (const { plugin, preProcessors } of entries) {
|
|
1705
|
+
plugin.logger = app.logger;
|
|
1706
|
+
for (const fn of preProcessors) {
|
|
1707
|
+
await fn(app, app.hono, ctx);
|
|
1708
|
+
}
|
|
1709
|
+
if (plugin.beforeModulesRegistered) {
|
|
1710
|
+
await plugin.beforeModulesRegistered(app, app.hono);
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
await app.register(rootModule);
|
|
1714
|
+
const routes = app.getRoutes();
|
|
1715
|
+
if (debugStartup) {
|
|
1716
|
+
app.logger.emit({
|
|
1717
|
+
level: "info",
|
|
1718
|
+
category: "startup",
|
|
1719
|
+
message: `Application registered ${routes.length} route(s)`,
|
|
1720
|
+
details: {
|
|
1721
|
+
routeCount: routes.length,
|
|
1722
|
+
rootModule: rootModule.name
|
|
1723
|
+
}
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
if (options.strict?.requireRoutes && routes.length === 0) {
|
|
1727
|
+
strictNoRoutesFailureEmitted = true;
|
|
1728
|
+
app.logger.emit({
|
|
1729
|
+
level: "error",
|
|
1730
|
+
category: "startup",
|
|
1731
|
+
message: "Strict mode failed: no routes were registered",
|
|
1732
|
+
details: {
|
|
1733
|
+
rootModule: rootModule.name,
|
|
1734
|
+
requireRoutes: true,
|
|
1735
|
+
startupDurationMs: Date.now() - startupStartedAt
|
|
1736
|
+
}
|
|
1737
|
+
});
|
|
1738
|
+
const strictError = new Error("Strict mode: no routes were registered. Check your module/controller decorators.");
|
|
1739
|
+
app.emitStartupGuide(strictError, rootModule);
|
|
1740
|
+
throw strictError;
|
|
1741
|
+
}
|
|
1742
|
+
if (debugRoutes) {
|
|
1743
|
+
app.logger.emit({
|
|
1744
|
+
level: "info",
|
|
1745
|
+
category: "routes",
|
|
1746
|
+
message: "Registered routes",
|
|
1747
|
+
details: {
|
|
1748
|
+
routes: routes.map((route) => `${route.method.toUpperCase()} ${route.fullPath}`)
|
|
1749
|
+
}
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
for (const { plugin, postProcessors } of entries) {
|
|
1753
|
+
if (plugin.afterModulesRegistered) {
|
|
1754
|
+
await plugin.afterModulesRegistered(app, app.hono);
|
|
1755
|
+
}
|
|
1756
|
+
for (const fn of postProcessors) {
|
|
1757
|
+
await fn(app, app.hono, ctx);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (debugStartup) {
|
|
1761
|
+
app.logger.emit({
|
|
1762
|
+
level: "info",
|
|
1763
|
+
category: "startup",
|
|
1764
|
+
message: "Application startup completed",
|
|
1765
|
+
details: {
|
|
1766
|
+
rootModule: rootModule.name,
|
|
1767
|
+
pluginCount: entries.length,
|
|
1768
|
+
routeCount: routes.length,
|
|
1769
|
+
startupDurationMs: Date.now() - startupStartedAt
|
|
1770
|
+
}
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
return {
|
|
1774
|
+
app,
|
|
1775
|
+
hono: app.getApp()
|
|
1776
|
+
};
|
|
1777
|
+
} catch (error) {
|
|
1778
|
+
app.emitStartupGuide(error, rootModule);
|
|
1779
|
+
if (debugStartup && !strictNoRoutesFailureEmitted) {
|
|
1780
|
+
app.logger.emit({
|
|
1781
|
+
level: "error",
|
|
1782
|
+
category: "startup",
|
|
1783
|
+
message: "Application startup failed",
|
|
1784
|
+
details: {
|
|
1785
|
+
rootModule: rootModule.name,
|
|
1786
|
+
startupDurationMs: Date.now() - startupStartedAt,
|
|
1787
|
+
errorMessage: error instanceof Error ? error.message : String(error)
|
|
1788
|
+
}
|
|
1789
|
+
});
|
|
1790
|
+
}
|
|
1791
|
+
throw error;
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
getApp() {
|
|
1795
|
+
return this.hono;
|
|
1796
|
+
}
|
|
1797
|
+
getContainer() {
|
|
1798
|
+
return this.container;
|
|
1799
|
+
}
|
|
1800
|
+
getContext() {
|
|
1801
|
+
return this.context;
|
|
1802
|
+
}
|
|
1803
|
+
getRoutes() {
|
|
1804
|
+
return this.routeRegistry.getRoutes();
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
var defaultSiteData = {
|
|
1808
|
+
type: "website",
|
|
1809
|
+
locale: "en_US"
|
|
1810
|
+
};
|
|
1811
|
+
var attrsToString = /* @__PURE__ */ __name((attrs) => {
|
|
1812
|
+
if (!attrs) {
|
|
1813
|
+
return "";
|
|
1814
|
+
}
|
|
1815
|
+
return Object.entries(attrs).map(([key, value]) => {
|
|
1816
|
+
if (typeof value === "boolean") {
|
|
1817
|
+
return value ? key : "";
|
|
1818
|
+
}
|
|
1819
|
+
const escapedValue = String(value).replace(/"/g, """);
|
|
1820
|
+
return `${key}="${escapedValue}"`;
|
|
1821
|
+
}).filter(Boolean).join(" ");
|
|
1822
|
+
}, "attrsToString");
|
|
1823
|
+
var Layout = /* @__PURE__ */ __name((props) => {
|
|
1824
|
+
const data = {
|
|
1825
|
+
...defaultSiteData,
|
|
1826
|
+
...props
|
|
1827
|
+
};
|
|
1828
|
+
return html.html`
|
|
1829
|
+
<!DOCTYPE html>
|
|
1830
|
+
<html lang="${data.locale?.split("_")[0] || "en"}" ${html.raw(attrsToString(data.htmlAttributes))}>
|
|
1831
|
+
<head ${html.raw(attrsToString(data.headAttributes))}>
|
|
1832
|
+
<meta charset="UTF-8" />
|
|
1833
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1834
|
+
${data.csp ? html.html`<meta http-equiv="Content-Security-Policy" content="${data.csp}" />` : ""}
|
|
1835
|
+
<title>${data.title}</title>
|
|
1836
|
+
${data.description ? html.html`<meta name="description" content="${data.description}" />` : ""}
|
|
1837
|
+
|
|
1838
|
+
<!-- Open Graph / Facebook -->
|
|
1839
|
+
<meta prefix="og: http://ogp.me/ns#" />
|
|
1840
|
+
<meta property="og:title" content="${data.title}" />
|
|
1841
|
+
${data.description ? html.html`<meta property="og:description" content="${data.description}" />` : ""}
|
|
1842
|
+
${data.image ? html.html`<meta property="og:image" content="${data.image}" />` : ""}
|
|
1843
|
+
${data.url ? html.html`<meta property="og:url" content="${data.url}" />` : ""}
|
|
1844
|
+
${data.locale ? html.html`<meta property="og:locale" content="${data.locale}" />` : ""}
|
|
1845
|
+
${data.type ? html.html`<meta property="og:type" content="${data.type}" />` : ""}
|
|
1846
|
+
${data.siteName ? html.html`<meta property="og:site_name" content="${data.siteName}" />` : ""}
|
|
1847
|
+
|
|
1848
|
+
<!-- Twitter -->
|
|
1849
|
+
<meta
|
|
1850
|
+
name="twitter:card"
|
|
1851
|
+
content="${data.twitterCard || (data.image ? "summary_large_image" : "summary")}"
|
|
1852
|
+
/>
|
|
1853
|
+
<meta name="twitter:title" content="${data.title}" />
|
|
1854
|
+
${data.description ? html.html`<meta name="twitter:description" content="${data.description}" />` : ""}
|
|
1855
|
+
${data.image ? html.html`<meta name="twitter:image" content="${data.image}" />` : ""}
|
|
1856
|
+
|
|
1857
|
+
<!-- Custom Meta Tags -->
|
|
1858
|
+
${data.customMeta ? data.customMeta.map((meta) => {
|
|
1859
|
+
const nameAttr = meta.name ? `name="${meta.name}"` : "";
|
|
1860
|
+
const propertyAttr = meta.property ? `property="${meta.property}"` : "";
|
|
1861
|
+
return html.html`<meta ${nameAttr} ${propertyAttr} content="${meta.content}" />`;
|
|
1862
|
+
}) : ""}
|
|
1863
|
+
|
|
1864
|
+
<!-- Favicon -->
|
|
1865
|
+
${data.favicon ? html.html`<link rel="icon" href="${data.favicon}" />` : ""}
|
|
1866
|
+
|
|
1867
|
+
<!-- Stylesheets -->
|
|
1868
|
+
${data.stylesheets ? data.stylesheets.map((href) => html.html`<link rel="stylesheet" href="${href}" />`) : ""}
|
|
1869
|
+
|
|
1870
|
+
<!-- Scripts -->
|
|
1871
|
+
${data.scripts ? data.scripts.map((script) => {
|
|
1872
|
+
if (typeof script === "string") {
|
|
1873
|
+
return html.html`<script src="${script}"></script>`;
|
|
1874
|
+
}
|
|
1875
|
+
const { src, async, defer } = script;
|
|
1876
|
+
if (async && defer) {
|
|
1877
|
+
return html.html`<script src="${src}" async defer></script>`;
|
|
1878
|
+
}
|
|
1879
|
+
if (async) {
|
|
1880
|
+
return html.html`<script src="${src}" async></script>`;
|
|
1881
|
+
}
|
|
1882
|
+
if (defer) {
|
|
1883
|
+
return html.html`<script src="${src}" defer></script>`;
|
|
1884
|
+
}
|
|
1885
|
+
return html.html`<script src="${src}"></script>`;
|
|
1886
|
+
}) : ""}
|
|
1887
|
+
</head>
|
|
1888
|
+
<body ${html.raw(attrsToString(data.bodyAttributes))}>
|
|
1889
|
+
${data.children}
|
|
1890
|
+
</body>
|
|
1891
|
+
</html>
|
|
1892
|
+
`;
|
|
1893
|
+
}, "Layout");
|
|
1894
|
+
|
|
1895
|
+
// src/decorators/controller.decorator.ts
|
|
1896
|
+
function Controller(route = "", options = {}) {
|
|
1897
|
+
return (target) => {
|
|
1898
|
+
MetadataRegistry.setControllerPath(target, route);
|
|
1899
|
+
MetadataRegistry.setControllerOptions(target, options);
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
__name(Controller, "Controller");
|
|
1903
|
+
|
|
1904
|
+
// src/decorators/http-method.decorator.ts
|
|
1905
|
+
var Get = createHttpMethodDecorator("get");
|
|
1906
|
+
var Post = createHttpMethodDecorator("post");
|
|
1907
|
+
var Put = createHttpMethodDecorator("put");
|
|
1908
|
+
var Delete = createHttpMethodDecorator("delete");
|
|
1909
|
+
var Patch = createHttpMethodDecorator("patch");
|
|
1910
|
+
var Options = createHttpMethodDecorator("options");
|
|
1911
|
+
var All = createHttpMethodDecorator("all");
|
|
1912
|
+
|
|
1913
|
+
// src/decorators/module.decorator.ts
|
|
1914
|
+
function Module(options = {}) {
|
|
1915
|
+
return (target) => {
|
|
1916
|
+
MetadataRegistry.setModuleOptions(target, options);
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
__name(Module, "Module");
|
|
1920
|
+
|
|
1921
|
+
// src/decorators/mvc.decorator.ts
|
|
1922
|
+
function View(route = "", options = {
|
|
1923
|
+
prefix: null,
|
|
1924
|
+
version: null
|
|
1925
|
+
}) {
|
|
1926
|
+
return Controller(route, options);
|
|
1927
|
+
}
|
|
1928
|
+
__name(View, "View");
|
|
1929
|
+
var Page = Get;
|
|
1930
|
+
function MvcModule(options = {}) {
|
|
1931
|
+
return Module({
|
|
1932
|
+
imports: options.imports,
|
|
1933
|
+
services: options.services,
|
|
1934
|
+
controllers: (options.views || []).concat(options.controllers || [])
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
__name(MvcModule, "MvcModule");
|
|
1938
|
+
|
|
1939
|
+
// src/decorators/parameter.decorator.ts
|
|
1940
|
+
var Body = createParamDecorator("body", async (data, ctx) => {
|
|
1941
|
+
let body = ctx.get(HONEST_PIPELINE_BODY_CACHE_KEY);
|
|
1942
|
+
if (body === void 0) {
|
|
1943
|
+
body = await ctx.req.json();
|
|
1944
|
+
ctx.set(HONEST_PIPELINE_BODY_CACHE_KEY, body);
|
|
1945
|
+
}
|
|
1946
|
+
if (data && body && typeof body === "object") {
|
|
1947
|
+
return body[String(data)];
|
|
1948
|
+
}
|
|
1949
|
+
return body;
|
|
1950
|
+
});
|
|
1951
|
+
var Param = createParamDecorator("param", (data, ctx) => {
|
|
1952
|
+
return data ? ctx.req.param(String(data)) : ctx.req.param();
|
|
1953
|
+
});
|
|
1954
|
+
var Query = createParamDecorator("query", (data, ctx) => {
|
|
1955
|
+
return data ? ctx.req.query(String(data)) : ctx.req.query();
|
|
1956
|
+
});
|
|
1957
|
+
var Header = createParamDecorator("header", (data, ctx) => {
|
|
1958
|
+
return data ? ctx.req.header(String(data)) : ctx.req.header();
|
|
1959
|
+
});
|
|
1960
|
+
var Req = createParamDecorator("request", (_, ctx) => ctx.req);
|
|
1961
|
+
var Request = createParamDecorator("request", (_, ctx) => ctx.req);
|
|
1962
|
+
var Res = createParamDecorator("response", (_, ctx) => ctx.res);
|
|
1963
|
+
var Response2 = createParamDecorator("response", (_, ctx) => ctx.res);
|
|
1964
|
+
var Ctx = createParamDecorator("context", (_, ctx) => ctx);
|
|
1965
|
+
var Context = createParamDecorator("context", (_, ctx) => ctx);
|
|
1966
|
+
var Var = createParamDecorator("variable", (data, ctx) => data === void 0 ? void 0 : ctx.get(String(data)));
|
|
1967
|
+
var Variable = createParamDecorator("variable", (data, ctx) => data === void 0 ? void 0 : ctx.get(String(data)));
|
|
1968
|
+
|
|
1969
|
+
// src/decorators/service.decorator.ts
|
|
1970
|
+
function Service() {
|
|
1971
|
+
return (target) => {
|
|
1972
|
+
MetadataRegistry.addService(target);
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
__name(Service, "Service");
|
|
1976
|
+
|
|
1977
|
+
// src/decorators/use-component.decorator.ts
|
|
1978
|
+
function UseComponent(type, ...components) {
|
|
1979
|
+
return (target, propertyKey) => {
|
|
1980
|
+
if (propertyKey) {
|
|
1981
|
+
const controllerClass = target.constructor;
|
|
1982
|
+
components.forEach((component) => MetadataRegistry.registerHandler(type, controllerClass, propertyKey, component));
|
|
1983
|
+
} else {
|
|
1984
|
+
components.forEach((component) => MetadataRegistry.registerController(type, target, component));
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
__name(UseComponent, "UseComponent");
|
|
1989
|
+
|
|
1990
|
+
// src/decorators/use-filters.decorator.ts
|
|
1991
|
+
function UseFilters(...filters) {
|
|
1992
|
+
return (target, propertyKey) => {
|
|
1993
|
+
if (propertyKey) {
|
|
1994
|
+
const controllerClass = target.constructor;
|
|
1995
|
+
filters.forEach((filter) => MetadataRegistry.registerHandler("filter", controllerClass, propertyKey, filter));
|
|
1996
|
+
} else {
|
|
1997
|
+
filters.forEach((filter) => MetadataRegistry.registerController("filter", target, filter));
|
|
1998
|
+
}
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
__name(UseFilters, "UseFilters");
|
|
2002
|
+
|
|
2003
|
+
// src/decorators/use-guards.decorator.ts
|
|
2004
|
+
function UseGuards(...guards) {
|
|
2005
|
+
return (target, propertyKey) => {
|
|
2006
|
+
if (propertyKey) {
|
|
2007
|
+
const controllerClass = target.constructor;
|
|
2008
|
+
guards.forEach((guard) => MetadataRegistry.registerHandler("guard", controllerClass, propertyKey, guard));
|
|
2009
|
+
} else {
|
|
2010
|
+
guards.forEach((guard) => MetadataRegistry.registerController("guard", target, guard));
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
}
|
|
2014
|
+
__name(UseGuards, "UseGuards");
|
|
2015
|
+
|
|
2016
|
+
// src/decorators/use-middleware.decorator.ts
|
|
2017
|
+
function UseMiddleware(...middleware) {
|
|
2018
|
+
return (target, propertyKey) => {
|
|
2019
|
+
if (propertyKey) {
|
|
2020
|
+
const controllerClass = target.constructor;
|
|
2021
|
+
middleware.forEach((mw) => MetadataRegistry.registerHandler("middleware", controllerClass, propertyKey, mw));
|
|
2022
|
+
} else {
|
|
2023
|
+
middleware.forEach((mw) => MetadataRegistry.registerController("middleware", target, mw));
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2026
|
+
}
|
|
2027
|
+
__name(UseMiddleware, "UseMiddleware");
|
|
2028
|
+
|
|
2029
|
+
// src/decorators/use-pipes.decorator.ts
|
|
2030
|
+
function UsePipes(...pipes) {
|
|
2031
|
+
return (target, propertyKey) => {
|
|
2032
|
+
if (propertyKey) {
|
|
2033
|
+
const controllerClass = target.constructor;
|
|
2034
|
+
pipes.forEach((pipe) => MetadataRegistry.registerHandler("pipe", controllerClass, propertyKey, pipe));
|
|
2035
|
+
} else {
|
|
2036
|
+
pipes.forEach((pipe) => MetadataRegistry.registerController("pipe", target, pipe));
|
|
2037
|
+
}
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
__name(UsePipes, "UsePipes");
|
|
2041
|
+
|
|
2042
|
+
// src/testing/create-testing-module.ts
|
|
2043
|
+
function createTestingModule(options = {}) {
|
|
2044
|
+
const { controllers, services, imports, name = "TestModule" } = options;
|
|
2045
|
+
const dynamicModule = {
|
|
2046
|
+
[name]: class {
|
|
2047
|
+
}
|
|
2048
|
+
}[name];
|
|
2049
|
+
Module({
|
|
2050
|
+
controllers,
|
|
2051
|
+
services,
|
|
2052
|
+
imports
|
|
2053
|
+
})(dynamicModule);
|
|
2054
|
+
return dynamicModule;
|
|
2055
|
+
}
|
|
2056
|
+
__name(createTestingModule, "createTestingModule");
|
|
2057
|
+
|
|
2058
|
+
// src/testing/create-test-application.ts
|
|
2059
|
+
async function createTestApplication(options = {}) {
|
|
2060
|
+
const { module, appOptions, ...moduleOptions } = options;
|
|
2061
|
+
const rootModule = module ?? createTestingModule(moduleOptions);
|
|
2062
|
+
const { app, hono } = await Application.create(rootModule, appOptions);
|
|
2063
|
+
const request = /* @__PURE__ */ __name((input, init) => {
|
|
2064
|
+
if (typeof input === "string") {
|
|
2065
|
+
const normalizedInput = input.startsWith("http://") || input.startsWith("https://") ? input : `http://localhost${input.startsWith("/") ? input : `/${input}`}`;
|
|
2066
|
+
return Promise.resolve(hono.request(normalizedInput, init));
|
|
2067
|
+
}
|
|
2068
|
+
return Promise.resolve(hono.request(input));
|
|
2069
|
+
}, "request");
|
|
2070
|
+
return {
|
|
2071
|
+
app,
|
|
2072
|
+
hono,
|
|
2073
|
+
request
|
|
2074
|
+
};
|
|
2075
|
+
}
|
|
2076
|
+
__name(createTestApplication, "createTestApplication");
|
|
2077
|
+
|
|
2078
|
+
// src/testing/create-controller-test-application.ts
|
|
2079
|
+
async function createControllerTestApplication(options) {
|
|
2080
|
+
const { controller, ...rest } = options;
|
|
2081
|
+
return createTestApplication({
|
|
2082
|
+
...rest,
|
|
2083
|
+
controllers: [
|
|
2084
|
+
controller
|
|
2085
|
+
]
|
|
2086
|
+
});
|
|
2087
|
+
}
|
|
2088
|
+
__name(createControllerTestApplication, "createControllerTestApplication");
|
|
2089
|
+
|
|
2090
|
+
// src/testing/create-service-test-container.ts
|
|
2091
|
+
function createServiceTestContainer(options = {}) {
|
|
2092
|
+
const logger = options.logger ?? new NoopLogger();
|
|
2093
|
+
const container = new Container(void 0, logger, Boolean(options.debugDi));
|
|
2094
|
+
for (const override of options.overrides ?? []) {
|
|
2095
|
+
const typedOverride = override;
|
|
2096
|
+
container.register(typedOverride.provide, typedOverride.useValue);
|
|
2097
|
+
}
|
|
2098
|
+
for (const service of options.preload ?? []) {
|
|
2099
|
+
container.resolve(service);
|
|
2100
|
+
}
|
|
2101
|
+
return {
|
|
2102
|
+
container,
|
|
2103
|
+
get(target) {
|
|
2104
|
+
return container.resolve(target);
|
|
2105
|
+
},
|
|
2106
|
+
register(target, instance) {
|
|
2107
|
+
container.register(target, instance);
|
|
2108
|
+
},
|
|
2109
|
+
has(target) {
|
|
2110
|
+
return container.has(target);
|
|
2111
|
+
},
|
|
2112
|
+
clear() {
|
|
2113
|
+
container.clear();
|
|
2114
|
+
}
|
|
2115
|
+
};
|
|
2116
|
+
}
|
|
2117
|
+
__name(createServiceTestContainer, "createServiceTestContainer");
|
|
2118
|
+
|
|
2119
|
+
exports.All = All;
|
|
2120
|
+
exports.Application = Application;
|
|
2121
|
+
exports.ApplicationContext = ApplicationContext;
|
|
2122
|
+
exports.Body = Body;
|
|
2123
|
+
exports.ConsoleLogger = ConsoleLogger;
|
|
2124
|
+
exports.Container = Container;
|
|
2125
|
+
exports.Context = Context;
|
|
2126
|
+
exports.Controller = Controller;
|
|
2127
|
+
exports.Ctx = Ctx;
|
|
2128
|
+
exports.Delete = Delete;
|
|
2129
|
+
exports.ErrorHandler = ErrorHandler;
|
|
2130
|
+
exports.FrameworkError = FrameworkError;
|
|
2131
|
+
exports.Get = Get;
|
|
2132
|
+
exports.HONEST_PIPELINE_BODY_CACHE_KEY = HONEST_PIPELINE_BODY_CACHE_KEY;
|
|
2133
|
+
exports.HONEST_PIPELINE_CONTROLLER_KEY = HONEST_PIPELINE_CONTROLLER_KEY;
|
|
2134
|
+
exports.HONEST_PIPELINE_HANDLER_KEY = HONEST_PIPELINE_HANDLER_KEY;
|
|
2135
|
+
exports.Header = Header;
|
|
2136
|
+
exports.Layout = Layout;
|
|
2137
|
+
exports.MetadataRegistry = MetadataRegistry;
|
|
2138
|
+
exports.MetadataRepository = MetadataRepository;
|
|
2139
|
+
exports.Module = Module;
|
|
2140
|
+
exports.MvcModule = MvcModule;
|
|
2141
|
+
exports.NoopLogger = NoopLogger;
|
|
2142
|
+
exports.NotFoundHandler = NotFoundHandler;
|
|
2143
|
+
exports.Options = Options;
|
|
2144
|
+
exports.Page = Page;
|
|
2145
|
+
exports.Param = Param;
|
|
2146
|
+
exports.Patch = Patch;
|
|
2147
|
+
exports.Post = Post;
|
|
2148
|
+
exports.Put = Put;
|
|
2149
|
+
exports.Query = Query;
|
|
2150
|
+
exports.Req = Req;
|
|
2151
|
+
exports.Request = Request;
|
|
2152
|
+
exports.Res = Res;
|
|
2153
|
+
exports.Response = Response2;
|
|
2154
|
+
exports.RouteRegistry = RouteRegistry;
|
|
2155
|
+
exports.Service = Service;
|
|
2156
|
+
exports.StaticServiceRegistry = StaticServiceRegistry;
|
|
2157
|
+
exports.UseComponent = UseComponent;
|
|
2158
|
+
exports.UseFilters = UseFilters;
|
|
2159
|
+
exports.UseGuards = UseGuards;
|
|
2160
|
+
exports.UseMiddleware = UseMiddleware;
|
|
2161
|
+
exports.UsePipes = UsePipes;
|
|
2162
|
+
exports.VERSION_NEUTRAL = VERSION_NEUTRAL;
|
|
2163
|
+
exports.Var = Var;
|
|
2164
|
+
exports.Variable = Variable;
|
|
2165
|
+
exports.View = View;
|
|
2166
|
+
exports.addLeadingSlash = addLeadingSlash;
|
|
2167
|
+
exports.createControllerTestApplication = createControllerTestApplication;
|
|
2168
|
+
exports.createErrorResponse = createErrorResponse;
|
|
2169
|
+
exports.createHttpMethodDecorator = createHttpMethodDecorator;
|
|
2170
|
+
exports.createParamDecorator = createParamDecorator;
|
|
2171
|
+
exports.createServiceTestContainer = createServiceTestContainer;
|
|
2172
|
+
exports.createTestApplication = createTestApplication;
|
|
2173
|
+
exports.createTestingModule = createTestingModule;
|
|
2174
|
+
exports.isConstructor = isConstructor;
|
|
2175
|
+
exports.isEmpty = isEmpty;
|
|
2176
|
+
exports.isFunction = isFunction;
|
|
2177
|
+
exports.isNil = isNil;
|
|
2178
|
+
exports.isNumber = isNumber;
|
|
2179
|
+
exports.isObject = isObject;
|
|
2180
|
+
exports.isPlainObject = isPlainObject;
|
|
2181
|
+
exports.isString = isString;
|
|
2182
|
+
exports.isSymbol = isSymbol;
|
|
2183
|
+
exports.isUndefined = isUndefined;
|
|
2184
|
+
exports.normalizePath = normalizePath;
|
|
2185
|
+
exports.stripEndSlash = stripEndSlash;
|