@velajs/vela 1.4.0 → 1.5.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/CHANGELOG.md +13 -1
- package/README.md +52 -0
- package/dist/cache/cache.module.d.ts +1 -0
- package/dist/cache/cache.module.js +6 -0
- package/dist/config/config.module.d.ts +4 -1
- package/dist/config/config.module.js +6 -0
- package/dist/container/container.d.ts +32 -4
- package/dist/container/container.js +252 -103
- package/dist/container/decorators.d.ts +8 -1
- package/dist/container/decorators.js +7 -4
- package/dist/container/index.d.ts +1 -1
- package/dist/container/index.js +1 -1
- package/dist/container/types.d.ts +13 -0
- package/dist/container/types.js +10 -0
- package/dist/cors/cors.module.d.ts +3 -1
- package/dist/cors/cors.module.js +2 -0
- package/dist/fetch/fetch.module.d.ts +3 -1
- package/dist/fetch/fetch.module.js +8 -3
- package/dist/http/argument-resolver.d.ts +10 -0
- package/dist/http/argument-resolver.js +89 -0
- package/dist/http/handler-executor.d.ts +20 -0
- package/dist/http/handler-executor.js +108 -0
- package/dist/http/instantiate.d.ts +4 -0
- package/dist/http/instantiate.js +18 -0
- package/dist/http/response-mapper.d.ts +8 -0
- package/dist/http/response-mapper.js +42 -0
- package/dist/http/route.manager.d.ts +1 -9
- package/dist/http/route.manager.js +23 -240
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/module/decorators.d.ts +6 -2
- package/dist/module/decorators.js +7 -6
- package/dist/module/index.d.ts +2 -1
- package/dist/module/index.js +2 -1
- package/dist/module/module-loader.d.ts +6 -1
- package/dist/module/module-loader.js +127 -47
- package/dist/module/stable-hash.d.ts +15 -0
- package/dist/module/stable-hash.js +52 -0
- package/dist/registry/types.d.ts +11 -0
- package/dist/throttler/throttler.module.d.ts +6 -2
- package/dist/throttler/throttler.module.js +6 -0
- package/package.json +1 -1
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import {
|
|
3
|
-
import { HttpMethod, ParamType } from "../constants.js";
|
|
2
|
+
import { HttpMethod } from "../constants.js";
|
|
4
3
|
import { getMetadata } from "../metadata.js";
|
|
5
4
|
import { joinPaths } from "../registry/paths.js";
|
|
6
|
-
import {
|
|
5
|
+
import { ArgumentResolver } from "./argument-resolver.js";
|
|
6
|
+
import { HandlerExecutor } from "./handler-executor.js";
|
|
7
|
+
import { instantiate, instantiateMany } from "./instantiate.js";
|
|
7
8
|
import { REQUEST_CONTEXT, createRequestContext } from "./request-context.js";
|
|
8
|
-
import { ForbiddenException, HttpException } from "../errors/http-exception.js";
|
|
9
9
|
import { ComponentManager } from "../pipeline/component.manager.js";
|
|
10
|
-
import { shouldFilterCatch } from "../pipeline/decorators.js";
|
|
11
10
|
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
12
|
-
import { getHttpCode, getRedirect, getResponseHeaders } from "./decorators.js";
|
|
13
11
|
const defaultGetClientIp = (c)=>c.req.raw.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ?? c.req.raw.headers.get('x-real-ip') ?? null;
|
|
14
|
-
function parseRedirectResult(result) {
|
|
15
|
-
if (typeof result !== 'object' || result === null) return undefined;
|
|
16
|
-
if (!('url' in result)) return undefined;
|
|
17
|
-
const obj = result;
|
|
18
|
-
if (typeof obj.url !== 'string') return undefined;
|
|
19
|
-
return {
|
|
20
|
-
url: obj.url,
|
|
21
|
-
...typeof obj.statusCode === 'number' ? {
|
|
22
|
-
statusCode: obj.statusCode
|
|
23
|
-
} : {}
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
12
|
export class RouteManager {
|
|
27
13
|
container;
|
|
28
14
|
static METHOD_REGISTRAR = new Map([
|
|
@@ -59,48 +45,6 @@ export class RouteManager {
|
|
|
59
45
|
(app, p, h)=>app.all(p, h)
|
|
60
46
|
]
|
|
61
47
|
]);
|
|
62
|
-
static PARAM_EXTRACTORS = new Map([
|
|
63
|
-
[
|
|
64
|
-
ParamType.PARAM,
|
|
65
|
-
(c, p)=>p.name ? c.req.param(p.name) : c.req.param()
|
|
66
|
-
],
|
|
67
|
-
[
|
|
68
|
-
ParamType.QUERY,
|
|
69
|
-
(c, p)=>p.name ? c.req.query(p.name) : c.req.query()
|
|
70
|
-
],
|
|
71
|
-
[
|
|
72
|
-
ParamType.BODY,
|
|
73
|
-
async (c, p)=>{
|
|
74
|
-
let body;
|
|
75
|
-
try {
|
|
76
|
-
body = await c.req.json();
|
|
77
|
-
} catch {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
return p.name && body !== null && typeof body === 'object' ? body[p.name] : body;
|
|
81
|
-
}
|
|
82
|
-
],
|
|
83
|
-
[
|
|
84
|
-
ParamType.HEADERS,
|
|
85
|
-
(c, p)=>p.name ? c.req.header(p.name) : c.req.header()
|
|
86
|
-
],
|
|
87
|
-
[
|
|
88
|
-
ParamType.REQUEST,
|
|
89
|
-
(c)=>c
|
|
90
|
-
],
|
|
91
|
-
[
|
|
92
|
-
ParamType.RESPONSE,
|
|
93
|
-
(c)=>c
|
|
94
|
-
],
|
|
95
|
-
[
|
|
96
|
-
ParamType.COOKIE,
|
|
97
|
-
(c, p)=>p.name ? getCookie(c, p.name) : getCookie(c)
|
|
98
|
-
],
|
|
99
|
-
[
|
|
100
|
-
ParamType.RAW_BODY,
|
|
101
|
-
async (c)=>new Uint8Array(await c.req.arrayBuffer())
|
|
102
|
-
]
|
|
103
|
-
]);
|
|
104
48
|
controllers = [];
|
|
105
49
|
globalMiddleware = [];
|
|
106
50
|
globalPipes = [];
|
|
@@ -109,10 +53,16 @@ export class RouteManager {
|
|
|
109
53
|
globalFilters = [];
|
|
110
54
|
globalPrefix = '';
|
|
111
55
|
consumerMiddlewareDefinitions = [];
|
|
112
|
-
|
|
56
|
+
handlerExecutor;
|
|
113
57
|
constructor(container, options = {}){
|
|
114
58
|
this.container = container;
|
|
115
|
-
|
|
59
|
+
const argumentResolver = new ArgumentResolver(options.getClientIp ?? defaultGetClientIp);
|
|
60
|
+
this.handlerExecutor = new HandlerExecutor(argumentResolver, ()=>({
|
|
61
|
+
guards: this.globalGuards,
|
|
62
|
+
pipes: this.globalPipes,
|
|
63
|
+
interceptors: this.globalInterceptors,
|
|
64
|
+
filters: this.globalFilters
|
|
65
|
+
}), (c)=>this.getRequestContainer(c));
|
|
116
66
|
}
|
|
117
67
|
registerConsumerMiddleware(definitions) {
|
|
118
68
|
this.consumerMiddlewareDefinitions.push(...definitions);
|
|
@@ -162,21 +112,6 @@ export class RouteManager {
|
|
|
162
112
|
this.globalFilters.push(...filterTokens);
|
|
163
113
|
return this;
|
|
164
114
|
}
|
|
165
|
-
instantiate(classOrInstance, container) {
|
|
166
|
-
if (typeof classOrInstance === 'function') {
|
|
167
|
-
if (container.has(classOrInstance)) {
|
|
168
|
-
return container.resolve(classOrInstance);
|
|
169
|
-
}
|
|
170
|
-
return new classOrInstance();
|
|
171
|
-
}
|
|
172
|
-
if (container.has(classOrInstance)) {
|
|
173
|
-
return container.resolve(classOrInstance);
|
|
174
|
-
}
|
|
175
|
-
return classOrInstance;
|
|
176
|
-
}
|
|
177
|
-
instantiateMany(items, container) {
|
|
178
|
-
return items.map((item)=>this.instantiate(item, container));
|
|
179
|
-
}
|
|
180
115
|
getMiddlewarePriority(entry) {
|
|
181
116
|
if (entry == null) return 0;
|
|
182
117
|
if (typeof entry === 'function') {
|
|
@@ -189,7 +124,7 @@ export class RouteManager {
|
|
|
189
124
|
if (typeof inst.constructor?.priority === 'number') return inst.constructor.priority;
|
|
190
125
|
}
|
|
191
126
|
try {
|
|
192
|
-
const resolved =
|
|
127
|
+
const resolved = instantiate(entry, this.container);
|
|
193
128
|
if (resolved && typeof resolved === 'object') {
|
|
194
129
|
const p = resolved.priority;
|
|
195
130
|
if (typeof p === 'number') return p;
|
|
@@ -215,6 +150,9 @@ export class RouteManager {
|
|
|
215
150
|
const prefix = MetadataRegistry.getControllerPath(controller);
|
|
216
151
|
const options = MetadataRegistry.getControllerOptions(controller);
|
|
217
152
|
const routes = MetadataRegistry.getRoutes(controller);
|
|
153
|
+
// The ModuleLoader registers controllers in their owning module's bucket;
|
|
154
|
+
// fall back to a `__root__` registration only for controllers that arrive
|
|
155
|
+
// here outside the module-loading flow (test harnesses, custom adapters).
|
|
218
156
|
if (!this.container.has(controller)) {
|
|
219
157
|
this.container.register(controller);
|
|
220
158
|
}
|
|
@@ -237,21 +175,18 @@ export class RouteManager {
|
|
|
237
175
|
index,
|
|
238
176
|
priority: this.getMiddlewarePriority(entry)
|
|
239
177
|
})).sort((a, b)=>a.priority - b.priority || a.index - b.index);
|
|
240
|
-
// Register global middleware on the Hono app
|
|
241
178
|
for (const { entry } of sortedGlobal){
|
|
242
179
|
app.use('*', (c, next)=>{
|
|
243
180
|
const requestContainer = this.getRequestContainer(c);
|
|
244
|
-
const resolved =
|
|
181
|
+
const resolved = instantiate(entry, requestContainer);
|
|
245
182
|
return resolved.use(c, next);
|
|
246
183
|
});
|
|
247
184
|
}
|
|
248
|
-
// Sort consumer middleware with the same stable-by-index rule.
|
|
249
185
|
const sortedConsumer = this.consumerMiddlewareDefinitions.map((def, index)=>({
|
|
250
186
|
def,
|
|
251
187
|
index,
|
|
252
188
|
priority: def.priority ?? 0
|
|
253
189
|
})).sort((a, b)=>a.priority - b.priority || a.index - b.index);
|
|
254
|
-
// Register MiddlewareConsumer-configured middleware
|
|
255
190
|
for (const { def } of sortedConsumer){
|
|
256
191
|
const matchRoute = this.compileRouteMatcher(def.routes);
|
|
257
192
|
const matchExclude = this.compileRouteMatcher(def.excludes);
|
|
@@ -262,30 +197,27 @@ export class RouteManager {
|
|
|
262
197
|
const requestContainer = this.getRequestContainer(c);
|
|
263
198
|
const runChain = (index)=>{
|
|
264
199
|
if (index >= def.middleware.length) return next();
|
|
265
|
-
const instance =
|
|
200
|
+
const instance = instantiate(def.middleware[index], requestContainer);
|
|
266
201
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
267
202
|
return instance.use(c, ()=>runChain(index + 1)).then(()=>{});
|
|
268
203
|
};
|
|
269
204
|
return runChain(0);
|
|
270
205
|
});
|
|
271
206
|
}
|
|
272
|
-
// First pass: register all custom routes (must come before CRUD /:id routes)
|
|
207
|
+
// First pass: register all custom routes (must come before CRUD /:id routes).
|
|
273
208
|
for (const { controller, metadata, routes } of this.controllers){
|
|
274
209
|
if (routes.length > 0) {
|
|
275
210
|
const allParamMetadata = MetadataRegistry.getParameters(controller);
|
|
276
211
|
for (const route of routes){
|
|
277
|
-
// Determine effective version: route-level overrides controller-level
|
|
278
212
|
const effectiveVersion = route.version ?? metadata.version;
|
|
279
|
-
// Build versioned paths
|
|
280
213
|
const versionedPaths = this.buildVersionedPaths(this.globalPrefix, metadata.prefix, route.path, effectiveVersion);
|
|
281
|
-
// Register per-route middleware as Hono middleware before the handler
|
|
282
214
|
const middlewareItems = ComponentManager.getComponents('middleware', controller, route.handlerName);
|
|
283
|
-
const handler = this.
|
|
215
|
+
const handler = this.handlerExecutor.create(route, controller, allParamMetadata);
|
|
284
216
|
for (const fullPath of versionedPaths){
|
|
285
217
|
for (const middlewareItem of middlewareItems){
|
|
286
218
|
app.use(fullPath, (c, next)=>{
|
|
287
219
|
const requestContainer = this.getRequestContainer(c);
|
|
288
|
-
const resolved =
|
|
220
|
+
const resolved = instantiate(middlewareItem, requestContainer);
|
|
289
221
|
return resolved.use(c, next);
|
|
290
222
|
});
|
|
291
223
|
}
|
|
@@ -294,7 +226,7 @@ export class RouteManager {
|
|
|
294
226
|
}
|
|
295
227
|
}
|
|
296
228
|
}
|
|
297
|
-
// Second pass: mount CRUD sub-apps (/:id routes registered last)
|
|
229
|
+
// Second pass: mount CRUD sub-apps (/:id routes registered last).
|
|
298
230
|
for (const { controller, metadata } of this.controllers){
|
|
299
231
|
const crudConfig = getMetadata('vela:crud', controller);
|
|
300
232
|
if (crudConfig) {
|
|
@@ -303,7 +235,7 @@ export class RouteManager {
|
|
|
303
235
|
const { buildCrudRoutes } = await import(pkg);
|
|
304
236
|
await buildCrudRoutes(app, controller, metadata.prefix, crudConfig, {
|
|
305
237
|
globalPrefix: this.globalPrefix,
|
|
306
|
-
globalGuards:
|
|
238
|
+
globalGuards: instantiateMany(this.globalGuards, this.container),
|
|
307
239
|
joinPaths
|
|
308
240
|
});
|
|
309
241
|
} catch (err) {
|
|
@@ -315,155 +247,6 @@ export class RouteManager {
|
|
|
315
247
|
}
|
|
316
248
|
return app;
|
|
317
249
|
}
|
|
318
|
-
createExecutionContext(c, controller, route) {
|
|
319
|
-
return buildExecutionContext(c, controller, route.handlerName);
|
|
320
|
-
}
|
|
321
|
-
createHandler(route, controller, allParamMetadata) {
|
|
322
|
-
const paramMetadata = (allParamMetadata.get(route.handlerName) || []).sort((a, b)=>a.index - b.index);
|
|
323
|
-
// Read param types once at build time for metatype population.
|
|
324
|
-
// Routed via Reflect so the polyfill funnels both src-level and dist-level
|
|
325
|
-
// consumers to the same registry (matters in tests that import from dist).
|
|
326
|
-
const paramTypes = Reflect.getMetadata('design:paramtypes', controller.prototype, route.handlerName);
|
|
327
|
-
// Collect controller + method level components at build time
|
|
328
|
-
const methodGuards = ComponentManager.getComponents('guard', controller, route.handlerName);
|
|
329
|
-
const methodPipes = ComponentManager.getComponents('pipe', controller, route.handlerName);
|
|
330
|
-
const methodInterceptors = ComponentManager.getComponents('interceptor', controller, route.handlerName);
|
|
331
|
-
// Filters: reverse order (handler → controller → global) — closest to handler runs first
|
|
332
|
-
const methodFilters = [
|
|
333
|
-
...ComponentManager.getComponents('filter', controller, route.handlerName)
|
|
334
|
-
].reverse();
|
|
335
|
-
// Read response decorators at build time
|
|
336
|
-
const httpCode = getHttpCode(controller, route.handlerName);
|
|
337
|
-
const responseHeaders = getResponseHeaders(controller, route.handlerName);
|
|
338
|
-
const redirect = getRedirect(controller, route.handlerName);
|
|
339
|
-
return async (c)=>{
|
|
340
|
-
// Combine global + method at request time (allows post-create registration)
|
|
341
|
-
const requestContainer = this.getRequestContainer(c);
|
|
342
|
-
const guards = [
|
|
343
|
-
...this.instantiateMany(this.globalGuards, requestContainer),
|
|
344
|
-
...this.instantiateMany(methodGuards, requestContainer)
|
|
345
|
-
];
|
|
346
|
-
const pipes = [
|
|
347
|
-
...this.instantiateMany(this.globalPipes, requestContainer),
|
|
348
|
-
...this.instantiateMany(methodPipes, requestContainer)
|
|
349
|
-
];
|
|
350
|
-
const interceptors = [
|
|
351
|
-
...this.instantiateMany(this.globalInterceptors, requestContainer),
|
|
352
|
-
...this.instantiateMany(methodInterceptors, requestContainer)
|
|
353
|
-
];
|
|
354
|
-
const filters = [
|
|
355
|
-
...this.instantiateMany(methodFilters, requestContainer),
|
|
356
|
-
...this.instantiateMany(this.globalFilters, requestContainer)
|
|
357
|
-
];
|
|
358
|
-
const executionContext = this.createExecutionContext(c, controller, route);
|
|
359
|
-
try {
|
|
360
|
-
const instance = requestContainer.resolve(controller);
|
|
361
|
-
// 1. Extract args + run pipes
|
|
362
|
-
const args = await this.extractArguments(c, paramMetadata, pipes, requestContainer, paramTypes);
|
|
363
|
-
// 2. Guards (fail-fast)
|
|
364
|
-
for (const guard of guards){
|
|
365
|
-
const canActivate = await guard.canActivate(executionContext);
|
|
366
|
-
if (!canActivate) {
|
|
367
|
-
throw new ForbiddenException();
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
// 3. Get handler method
|
|
371
|
-
const method = Reflect.get(instance, route.handlerName);
|
|
372
|
-
if (typeof method !== 'function') {
|
|
373
|
-
throw new Error(`Method ${String(route.handlerName)} not found on controller`);
|
|
374
|
-
}
|
|
375
|
-
// 4. Build core handler
|
|
376
|
-
const coreHandler = async ()=>Reflect.apply(method, instance, args);
|
|
377
|
-
// 5. Run interceptor chain
|
|
378
|
-
const result = await ComponentManager.runInterceptorChain(interceptors, executionContext, coreHandler);
|
|
379
|
-
// Handle @Redirect
|
|
380
|
-
if (redirect) {
|
|
381
|
-
const overrides = parseRedirectResult(result);
|
|
382
|
-
const finalUrl = overrides?.url ?? redirect.url;
|
|
383
|
-
const finalStatus = overrides?.statusCode ?? redirect.statusCode;
|
|
384
|
-
return c.redirect(finalUrl, finalStatus);
|
|
385
|
-
}
|
|
386
|
-
// Build response with @HttpCode and @Header support
|
|
387
|
-
const response = this.createResponse(c, result, httpCode);
|
|
388
|
-
// Apply @Header decorators
|
|
389
|
-
for (const [headerName, headerValue] of responseHeaders){
|
|
390
|
-
response.headers.set(headerName, headerValue);
|
|
391
|
-
}
|
|
392
|
-
return response;
|
|
393
|
-
} catch (error) {
|
|
394
|
-
// Run exception filters
|
|
395
|
-
for (const filter of filters){
|
|
396
|
-
if (shouldFilterCatch(filter, error)) {
|
|
397
|
-
try {
|
|
398
|
-
const result = await filter.catch(error, executionContext);
|
|
399
|
-
return this.createResponse(c, result);
|
|
400
|
-
} catch {
|
|
401
|
-
break;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
// Default HttpException handling
|
|
406
|
-
if (error instanceof HttpException) {
|
|
407
|
-
const response = error.getResponse();
|
|
408
|
-
const status = error.getStatus();
|
|
409
|
-
return c.json(response, status);
|
|
410
|
-
}
|
|
411
|
-
// Default 500
|
|
412
|
-
return c.json({
|
|
413
|
-
statusCode: 500,
|
|
414
|
-
message: 'Internal Server Error'
|
|
415
|
-
}, 500);
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
async extractArguments(c, paramMetadata, pipes, requestContainer, paramTypes) {
|
|
420
|
-
if (paramMetadata.length === 0) {
|
|
421
|
-
return [
|
|
422
|
-
c
|
|
423
|
-
];
|
|
424
|
-
}
|
|
425
|
-
const maxIndex = paramMetadata.at(-1).index;
|
|
426
|
-
const args = new Array(maxIndex + 1).fill(undefined);
|
|
427
|
-
for (const param of paramMetadata){
|
|
428
|
-
let value = await this.extractParam(c, param);
|
|
429
|
-
const metadata = {
|
|
430
|
-
type: param.type,
|
|
431
|
-
data: param.name,
|
|
432
|
-
metatype: paramTypes?.[param.index]
|
|
433
|
-
};
|
|
434
|
-
// Run shared pipes (global + controller + method)
|
|
435
|
-
for (const pipe of pipes){
|
|
436
|
-
value = await pipe.transform(value, metadata);
|
|
437
|
-
}
|
|
438
|
-
// Run param-level pipes
|
|
439
|
-
if (param.pipes && param.pipes.length > 0) {
|
|
440
|
-
for (const paramPipe of param.pipes){
|
|
441
|
-
const pipeInstance = this.instantiate(paramPipe, requestContainer);
|
|
442
|
-
value = await pipeInstance.transform(value, metadata);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
args[param.index] = value;
|
|
446
|
-
}
|
|
447
|
-
return args;
|
|
448
|
-
}
|
|
449
|
-
extractParam(c, param) {
|
|
450
|
-
if (param.type === ParamType.IP) return this.ipExtractor(c);
|
|
451
|
-
const extractor = RouteManager.PARAM_EXTRACTORS.get(param.type);
|
|
452
|
-
if (extractor) return extractor(c, param);
|
|
453
|
-
return param.factory ? param.factory(param.name, c) : undefined;
|
|
454
|
-
}
|
|
455
|
-
createResponse(c, result, statusCode) {
|
|
456
|
-
if (result instanceof Response) {
|
|
457
|
-
return result;
|
|
458
|
-
}
|
|
459
|
-
if (result === null || result === undefined) {
|
|
460
|
-
return c.body(null, statusCode ?? 204);
|
|
461
|
-
}
|
|
462
|
-
if (typeof result === 'string') {
|
|
463
|
-
return c.text(result, statusCode ?? 200);
|
|
464
|
-
}
|
|
465
|
-
return c.json(result, statusCode ?? 200);
|
|
466
|
-
}
|
|
467
250
|
registerRoute(app, method, path, handler) {
|
|
468
251
|
const normalizedPath = path || '/';
|
|
469
252
|
const registrar = RouteManager.METHOD_REGISTRAR.get(method);
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { bootstrap } from './factory/bootstrap';
|
|
|
6
6
|
export type { BootstrapOptions, BootstrapResult } from './factory/bootstrap';
|
|
7
7
|
export { createOpenApiDocument, ApiDoc, ApiTags, ApiResponse, zodToJsonSchema, } from './openapi/index';
|
|
8
8
|
export type { OpenApiDocument, OpenApiInfo, OpenApiOperation, OpenApiParameter, OpenApiPathItem, OpenApiRequestBody, OpenApiResponse, ApiDocMetadata, ApiResponseEntry, ApiResponseOptions, CreateOpenApiDocumentOptions, HttpVerb, JsonSchema, } from './openapi/index';
|
|
9
|
-
export { Container, Injectable, Inject, Optional, InjectionToken, ForwardRef, forwardRef, ModuleRef, ModuleVisibilityError, mixin, } from './container/index';
|
|
9
|
+
export { Container, Injectable, Inject, Optional, InjectionToken, ForwardRef, forwardRef, ModuleRef, ModuleVisibilityError, MultipleProvidersFoundError, ROOT_MODULE_ID, mixin, } from './container/index';
|
|
10
10
|
export type { Type, Token, InjectableOptions, ProviderOptions, ModuleScope, ContainerOptions, Diagnostics, } from './container/index';
|
|
11
11
|
export { METADATA_KEYS, HttpMethod, ParamType, Scope } from './constants';
|
|
12
12
|
export { Controller, Version, Get, Post, Put, Patch, Delete, Options, Head, All, Sse, Param, Query, Body, Headers, Req, Res, Ip, Cookie, Cookies, RawBody, HttpCode, Header, Redirect, createParamDecorator, applyDecorators, } from './http/index';
|
|
@@ -30,7 +30,7 @@ export { HealthModule, HealthCheckService, HealthIndicatorService, HttpHealthInd
|
|
|
30
30
|
export type { HealthCheckResult, HealthCheckStatus, HealthIndicatorResult, HealthIndicatorFunction, ResponseCheckCallback, HttpPingOptions, } from './health/index';
|
|
31
31
|
export { ThrottlerModule, ThrottlerGuard, ThrottlerStorage, Throttle, SkipThrottle, THROTTLER_OPTIONS, THROTTLER_STORAGE, THROTTLE_METADATA, SKIP_THROTTLE_METADATA, } from './throttler/index';
|
|
32
32
|
export type { ThrottlerModuleOptions, ThrottleConfig, ThrottlerStore, ThrottlerStorageRecord, RateLimitInfo, } from './throttler/index';
|
|
33
|
-
export { Global, Module,
|
|
33
|
+
export { Global, Module, defineDynamicModule, stableHash, } from './module/index';
|
|
34
34
|
export type { ModuleOptions, DynamicModule, AsyncModuleOptions, ModuleImport } from './module/index';
|
|
35
35
|
export type { MiddlewareConsumer, NestModule, RouteInfo } from './http/index';
|
|
36
36
|
export { definePlugin, composePlugins, PluginRegistry, PluginRootModule, PLUGIN_REGISTRY_TOKEN, } from './plugin/plugin';
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { bootstrap } from "./factory/bootstrap.js";
|
|
|
7
7
|
// OpenAPI
|
|
8
8
|
export { createOpenApiDocument, ApiDoc, ApiTags, ApiResponse, zodToJsonSchema } from "./openapi/index.js";
|
|
9
9
|
// DI Container
|
|
10
|
-
export { Container, Injectable, Inject, Optional, InjectionToken, ForwardRef, forwardRef, ModuleRef, ModuleVisibilityError, mixin } from "./container/index.js";
|
|
10
|
+
export { Container, Injectable, Inject, Optional, InjectionToken, ForwardRef, forwardRef, ModuleRef, ModuleVisibilityError, MultipleProvidersFoundError, ROOT_MODULE_ID, mixin } from "./container/index.js";
|
|
11
11
|
// Constants
|
|
12
12
|
export { METADATA_KEYS, HttpMethod, ParamType, Scope } from "./constants.js";
|
|
13
13
|
// HTTP Decorators
|
|
@@ -33,7 +33,7 @@ export { HealthModule, HealthCheckService, HealthIndicatorService, HttpHealthInd
|
|
|
33
33
|
// Throttler
|
|
34
34
|
export { ThrottlerModule, ThrottlerGuard, ThrottlerStorage, Throttle, SkipThrottle, THROTTLER_OPTIONS, THROTTLER_STORAGE, THROTTLE_METADATA, SKIP_THROTTLE_METADATA } from "./throttler/index.js";
|
|
35
35
|
// Module
|
|
36
|
-
export { Global, Module,
|
|
36
|
+
export { Global, Module, defineDynamicModule, stableHash } from "./module/index.js";
|
|
37
37
|
// Plugin manifest + composer
|
|
38
38
|
export { definePlugin, composePlugins, PluginRegistry, PluginRootModule, PLUGIN_REGISTRY_TOKEN } from "./plugin/plugin.js";
|
|
39
39
|
// Pipeline Decorators
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import type { Constructor, ModuleMetadata, ModuleOptions
|
|
1
|
+
import type { Constructor, DynamicModule, ModuleMetadata, ModuleOptions } from '../registry/types';
|
|
2
2
|
export declare function Global(): ClassDecorator;
|
|
3
3
|
export declare function Module(options?: ModuleOptions): ClassDecorator;
|
|
4
4
|
export declare function isModule(target: Constructor): boolean;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Normalize a DynamicModule, defaulting `key` to `"default"`. Module authors
|
|
7
|
+
* call this from `forRoot()` so the loader always sees an explicit key.
|
|
8
|
+
*/
|
|
9
|
+
export declare function defineDynamicModule(input: DynamicModule): DynamicModule;
|
|
6
10
|
export declare function getModuleMetadata(target: Constructor): ModuleMetadata | undefined;
|
|
@@ -23,13 +23,14 @@ export function Module(options = {}) {
|
|
|
23
23
|
export function isModule(target) {
|
|
24
24
|
return MetadataRegistry.getModuleOptions(target) !== undefined;
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Normalize a DynamicModule, defaulting `key` to `"default"`. Module authors
|
|
28
|
+
* call this from `forRoot()` so the loader always sees an explicit key.
|
|
29
|
+
*/ export function defineDynamicModule(input) {
|
|
30
|
+
return {
|
|
31
|
+
...input,
|
|
32
|
+
key: input.key ?? 'default'
|
|
28
33
|
};
|
|
29
|
-
Object.defineProperty(moduleClass, 'name', {
|
|
30
|
-
value: name
|
|
31
|
-
});
|
|
32
|
-
return moduleClass;
|
|
33
34
|
}
|
|
34
35
|
export function getModuleMetadata(target) {
|
|
35
36
|
const options = MetadataRegistry.getModuleOptions(target);
|
package/dist/module/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { Global, Module, isModule, getModuleMetadata,
|
|
1
|
+
export { Global, Module, isModule, getModuleMetadata, defineDynamicModule, } from './decorators';
|
|
2
|
+
export { stableHash } from './stable-hash';
|
|
2
3
|
export { ModuleLoader } from './module-loader';
|
|
3
4
|
export { MiddlewareBuilder } from './middleware';
|
|
4
5
|
export type { MiddlewareConsumer, MiddlewareConfigProxy, MiddlewareRouteDefinition, NestModule, RouteInfo, } from './middleware';
|
package/dist/module/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export { Global, Module, isModule, getModuleMetadata,
|
|
1
|
+
export { Global, Module, isModule, getModuleMetadata, defineDynamicModule } from "./decorators.js";
|
|
2
|
+
export { stableHash } from "./stable-hash.js";
|
|
2
3
|
export { ModuleLoader } from "./module-loader.js";
|
|
3
4
|
export { MiddlewareBuilder } from "./middleware.js";
|
|
@@ -14,12 +14,17 @@ export declare class ModuleLoader {
|
|
|
14
14
|
private consumerMiddlewareDefinitions;
|
|
15
15
|
private appProviderCounter;
|
|
16
16
|
private appProviderTokens;
|
|
17
|
-
private
|
|
17
|
+
private moduleIdByClassKey;
|
|
18
18
|
private seenModuleIds;
|
|
19
19
|
constructor(container: Container, router: RouteManager);
|
|
20
20
|
load(rootModule: Type): void;
|
|
21
21
|
private getModuleId;
|
|
22
|
+
private isProcessed;
|
|
23
|
+
private markProcessed;
|
|
24
|
+
private getCachedExports;
|
|
25
|
+
private cacheExports;
|
|
22
26
|
private processModule;
|
|
27
|
+
private warnOnMixedDefaultAndKeyed;
|
|
23
28
|
private registerProvider;
|
|
24
29
|
private isAppToken;
|
|
25
30
|
private buildExportSet;
|