@velajs/vela 1.10.0 → 1.12.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 +102 -0
- package/dist/application.d.ts +8 -0
- package/dist/application.js +20 -0
- package/dist/container/container.d.ts +25 -0
- package/dist/container/container.js +67 -11
- package/dist/container/disposable.js +1 -1
- package/dist/cors/cors.module.d.ts +5 -5
- package/dist/cors/cors.module.js +26 -25
- package/dist/discovery/discoverable.decorator.d.ts +38 -0
- package/dist/discovery/discoverable.decorator.js +42 -0
- package/dist/discovery/discovery.service.d.ts +94 -0
- package/dist/discovery/discovery.service.js +166 -0
- package/dist/discovery/index.d.ts +2 -0
- package/dist/discovery/index.js +2 -0
- package/dist/entrypoint/entrypoint.registry.d.ts +40 -0
- package/dist/entrypoint/entrypoint.registry.js +106 -0
- package/dist/entrypoint/entrypoint.types.d.ts +41 -0
- package/dist/entrypoint/entrypoint.types.js +3 -0
- package/dist/entrypoint/execution-context.d.ts +15 -0
- package/dist/entrypoint/execution-context.js +21 -0
- package/dist/entrypoint/execution-scope.d.ts +21 -0
- package/dist/entrypoint/execution-scope.js +28 -0
- package/dist/entrypoint/index.d.ts +4 -0
- package/dist/entrypoint/index.js +4 -0
- package/dist/event-emitter/event-emitter.subscriber.d.ts +3 -3
- package/dist/event-emitter/event-emitter.subscriber.js +12 -29
- package/dist/factory/adapter.d.ts +36 -0
- package/dist/factory/adapter.js +18 -0
- package/dist/factory/bootstrap.js +10 -2
- package/dist/factory.d.ts +11 -1
- package/dist/factory.js +23 -2
- package/dist/http/handler-executor.js +22 -19
- package/dist/http/route-contributor.d.ts +68 -0
- package/dist/http/route-contributor.js +22 -0
- package/dist/http/route.manager.js +28 -19
- package/dist/i18n/i18n.module.js +4 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +9 -2
- package/dist/internal.d.ts +0 -2
- package/dist/internal.js +0 -7
- package/dist/module/configurable-module.builder.d.ts +12 -0
- package/dist/module/configurable-module.builder.js +21 -114
- package/dist/module/define-module.d.ts +105 -0
- package/dist/module/define-module.js +227 -0
- package/dist/module/index.d.ts +3 -1
- package/dist/module/index.js +3 -1
- package/dist/module/lazy-provider.d.ts +65 -0
- package/dist/module/lazy-provider.js +111 -0
- package/dist/openapi/document.js +16 -15
- package/dist/pipeline/component.manager.d.ts +15 -9
- package/dist/pipeline/component.manager.js +32 -46
- package/dist/pipeline/index.d.ts +2 -0
- package/dist/pipeline/index.js +1 -0
- package/dist/pipeline/pipeline-runner.d.ts +31 -0
- package/dist/pipeline/pipeline-runner.js +40 -0
- package/dist/registry/metadata.registry.d.ts +9 -3
- package/dist/registry/metadata.registry.js +55 -25
- package/dist/schedule/schedule.module.d.ts +5 -0
- package/dist/schedule/schedule.module.js +18 -8
- package/dist/schedule/schedule.registry.d.ts +3 -3
- package/dist/schedule/schedule.registry.js +23 -44
- package/dist/schedule-node/schedule-node.module.d.ts +5 -0
- package/dist/schedule-node/schedule-node.module.js +20 -10
- package/dist/seeder/seeder.module.d.ts +8 -10
- package/dist/seeder/seeder.module.js +16 -15
- package/dist/websocket/index.d.ts +1 -1
- package/dist/websocket/index.js +1 -1
- package/dist/websocket/websocket.module.d.ts +20 -3
- package/dist/websocket/websocket.module.js +50 -39
- package/dist/websocket/websocket.tokens.d.ts +2 -1
- package/dist/websocket/websocket.tokens.js +3 -2
- package/dist/websocket/ws-dispatcher.d.ts +21 -9
- package/dist/websocket/ws-dispatcher.js +44 -38
- package/dist/websocket-node/register-gateways.js +3 -3
- package/package.json +1 -1
- package/dist/http/crud-bridge.d.ts +0 -90
- package/dist/http/crud-bridge.js +0 -25
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
2
|
+
import { PipelineRunner } from "./pipeline-runner.js";
|
|
2
3
|
function isObject(value) {
|
|
3
4
|
return typeof value === 'object' && value !== null;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
6
|
+
/**
|
|
7
|
+
* Component registration + resolution for the controller/handler tiers.
|
|
8
|
+
* App-wide (global) components have exactly ONE source: the per-app
|
|
9
|
+
* `RouteManager` (`APP_*` provider tokens + `useGlobalX()`) — callers merge
|
|
10
|
+
* `routeManager.getGlobalComponents()` with {@link getScopedComponents}.
|
|
11
|
+
*
|
|
12
|
+
* Stateless by design: no process-global container (two apps in one process
|
|
13
|
+
* never cross-talk) — every `resolve*` takes the resolving container.
|
|
14
|
+
*/ export class ComponentManager {
|
|
15
|
+
// Scoped registration: controller → handler
|
|
16
16
|
static registerController(type, controller, ...components) {
|
|
17
17
|
for (const component of components){
|
|
18
18
|
MetadataRegistry.registerController(type, controller, component);
|
|
@@ -23,34 +23,32 @@ export class ComponentManager {
|
|
|
23
23
|
MetadataRegistry.registerHandler(type, controller, handlerName, component);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const handlerComponents = MetadataRegistry.getHandler(type, controller, handlerName);
|
|
26
|
+
// Scoped resolution: controller → handler. App-wide components come from
|
|
27
|
+
// RouteManager (APP_* tokens + useGlobalX()) — merged by the caller.
|
|
28
|
+
static getScopedComponents(type, controller, handlerName) {
|
|
30
29
|
return [
|
|
31
|
-
...MetadataRegistry.
|
|
32
|
-
...
|
|
33
|
-
...handlerComponents
|
|
30
|
+
...MetadataRegistry.getController(type, controller),
|
|
31
|
+
...MetadataRegistry.getHandler(type, controller, handlerName)
|
|
34
32
|
];
|
|
35
33
|
}
|
|
36
|
-
// Type-specific resolvers
|
|
37
|
-
static resolveAll(items, methodKey) {
|
|
38
|
-
return items.map((item)=>isObject(item) && methodKey in item ? item :
|
|
34
|
+
// Type-specific resolvers — explicit container, always.
|
|
35
|
+
static resolveAll(items, methodKey, container) {
|
|
36
|
+
return items.map((item)=>isObject(item) && methodKey in item ? item : container.resolve(item));
|
|
39
37
|
}
|
|
40
|
-
static resolveMiddleware(items) {
|
|
41
|
-
return this.resolveAll(items, 'use');
|
|
38
|
+
static resolveMiddleware(items, container) {
|
|
39
|
+
return this.resolveAll(items, 'use', container);
|
|
42
40
|
}
|
|
43
|
-
static resolveGuards(items) {
|
|
44
|
-
return this.resolveAll(items, 'canActivate');
|
|
41
|
+
static resolveGuards(items, container) {
|
|
42
|
+
return this.resolveAll(items, 'canActivate', container);
|
|
45
43
|
}
|
|
46
|
-
static resolvePipes(items) {
|
|
47
|
-
return this.resolveAll(items, 'transform');
|
|
44
|
+
static resolvePipes(items, container) {
|
|
45
|
+
return this.resolveAll(items, 'transform', container);
|
|
48
46
|
}
|
|
49
|
-
static resolveInterceptors(items) {
|
|
50
|
-
return this.resolveAll(items, 'intercept');
|
|
47
|
+
static resolveInterceptors(items, container) {
|
|
48
|
+
return this.resolveAll(items, 'intercept', container);
|
|
51
49
|
}
|
|
52
|
-
static resolveFilters(items) {
|
|
53
|
-
return this.resolveAll(items, 'catch');
|
|
50
|
+
static resolveFilters(items, container) {
|
|
51
|
+
return this.resolveAll(items, 'catch', container);
|
|
54
52
|
}
|
|
55
53
|
// Pipe execution
|
|
56
54
|
static async executePipes(value, metadata, pipes) {
|
|
@@ -60,21 +58,9 @@ export class ComponentManager {
|
|
|
60
58
|
}
|
|
61
59
|
return transformed;
|
|
62
60
|
}
|
|
63
|
-
// Interceptor chain (onion pattern)
|
|
61
|
+
// Interceptor chain (onion pattern) — canonical implementation lives in
|
|
62
|
+
// PipelineRunner; kept here as a stable alias.
|
|
64
63
|
static async runInterceptorChain(interceptors, context, coreHandler) {
|
|
65
|
-
|
|
66
|
-
return coreHandler();
|
|
67
|
-
}
|
|
68
|
-
let next = {
|
|
69
|
-
handle: coreHandler
|
|
70
|
-
};
|
|
71
|
-
for(let i = interceptors.length - 1; i >= 0; i--){
|
|
72
|
-
const interceptor = interceptors[i];
|
|
73
|
-
const currentNext = next;
|
|
74
|
-
next = {
|
|
75
|
-
handle: ()=>interceptor.intercept(context, currentNext)
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
return next.handle();
|
|
64
|
+
return PipelineRunner.chainInterceptors(interceptors, context, coreHandler);
|
|
79
65
|
}
|
|
80
66
|
}
|
package/dist/pipeline/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { ComponentManager } from './component.manager';
|
|
2
|
+
export { PipelineRunner } from './pipeline-runner';
|
|
3
|
+
export type { PipelineRunOptions } from './pipeline-runner';
|
|
2
4
|
export { UseMiddleware, UseGuards, UsePipes, UseInterceptors, UseFilters, Catch, getCatchTypes, shouldFilterCatch, } from './decorators';
|
|
3
5
|
export { SetMetadata, Reflector } from './reflector';
|
|
4
6
|
export type { ReflectableDecorator, CreateDecoratorOptions } from './reflector';
|
package/dist/pipeline/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { ComponentManager } from "./component.manager.js";
|
|
2
|
+
export { PipelineRunner } from "./pipeline-runner.js";
|
|
2
3
|
export { UseMiddleware, UseGuards, UsePipes, UseInterceptors, UseFilters, Catch, getCatchTypes, shouldFilterCatch } from "./decorators.js";
|
|
3
4
|
export { SetMetadata, Reflector } from "./reflector.js";
|
|
4
5
|
export { APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER, APP_MIDDLEWARE } from "./tokens.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CanActivate, ExecutionContext, NestInterceptor } from './types';
|
|
2
|
+
export interface PipelineRunOptions {
|
|
3
|
+
context: ExecutionContext;
|
|
4
|
+
/** Pre-merged (global ++ scoped), pre-instantiated. */
|
|
5
|
+
guards: CanActivate[];
|
|
6
|
+
interceptors: NestInterceptor[];
|
|
7
|
+
/** Extract handler arguments (pipes already bound inside the closure). */
|
|
8
|
+
resolveArgs: () => Promise<unknown[]>;
|
|
9
|
+
/** Call the actual handler. */
|
|
10
|
+
invoke: (args: unknown[]) => Promise<unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* HTTP runs argument extraction + pipes BEFORE guards (a deliberate vela
|
|
13
|
+
* deviation — see handler-executor); WebSocket runs guards first. Default
|
|
14
|
+
* false (guards first).
|
|
15
|
+
*/
|
|
16
|
+
argsBeforeGuards?: boolean;
|
|
17
|
+
/** Error thrown when a guard rejects (default `ForbiddenException`). */
|
|
18
|
+
onGuardReject?: () => Error;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The transport-agnostic guard → pipe → interceptor execution core shared by
|
|
22
|
+
* the HTTP `HandlerExecutor` and the WebSocket `WsDispatcher` (and any future
|
|
23
|
+
* entrypoint dispatcher: queue consumers, scheduled jobs, …). Exception
|
|
24
|
+
* FILTERS stay with the caller — their terminal behavior is transport-specific
|
|
25
|
+
* (HTTP maps to a Response, WS sends an error frame).
|
|
26
|
+
*/
|
|
27
|
+
export declare class PipelineRunner {
|
|
28
|
+
static run(options: PipelineRunOptions): Promise<unknown>;
|
|
29
|
+
/** Interceptor onion — innermost is the core handler. */
|
|
30
|
+
static chainInterceptors(interceptors: NestInterceptor[], context: ExecutionContext, coreHandler: () => Promise<unknown>): Promise<unknown>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ForbiddenException } from "../errors/http-exception.js";
|
|
2
|
+
/**
|
|
3
|
+
* The transport-agnostic guard → pipe → interceptor execution core shared by
|
|
4
|
+
* the HTTP `HandlerExecutor` and the WebSocket `WsDispatcher` (and any future
|
|
5
|
+
* entrypoint dispatcher: queue consumers, scheduled jobs, …). Exception
|
|
6
|
+
* FILTERS stay with the caller — their terminal behavior is transport-specific
|
|
7
|
+
* (HTTP maps to a Response, WS sends an error frame).
|
|
8
|
+
*/ export class PipelineRunner {
|
|
9
|
+
static async run(options) {
|
|
10
|
+
let args;
|
|
11
|
+
if (options.argsBeforeGuards) {
|
|
12
|
+
args = await options.resolveArgs();
|
|
13
|
+
}
|
|
14
|
+
for (const guard of options.guards){
|
|
15
|
+
const canActivate = await guard.canActivate(options.context);
|
|
16
|
+
if (!canActivate) {
|
|
17
|
+
throw options.onGuardReject?.() ?? new ForbiddenException();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
args ??= await options.resolveArgs();
|
|
21
|
+
const resolvedArgs = args;
|
|
22
|
+
return PipelineRunner.chainInterceptors(options.interceptors, options.context, ()=>options.invoke(resolvedArgs));
|
|
23
|
+
}
|
|
24
|
+
/** Interceptor onion — innermost is the core handler. */ static async chainInterceptors(interceptors, context, coreHandler) {
|
|
25
|
+
if (interceptors.length === 0) {
|
|
26
|
+
return coreHandler();
|
|
27
|
+
}
|
|
28
|
+
let next = {
|
|
29
|
+
handle: coreHandler
|
|
30
|
+
};
|
|
31
|
+
for(let i = interceptors.length - 1; i >= 0; i--){
|
|
32
|
+
const interceptor = interceptors[i];
|
|
33
|
+
const currentNext = next;
|
|
34
|
+
next = {
|
|
35
|
+
handle: ()=>interceptor.intercept(context, currentNext)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return next.handle();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -18,9 +18,10 @@ export declare class MetadataRegistry {
|
|
|
18
18
|
private static get routeVersions();
|
|
19
19
|
private static get classMeta();
|
|
20
20
|
private static get handlerMeta();
|
|
21
|
+
private static get classMetaIndex();
|
|
22
|
+
private static get handlerMetaIndex();
|
|
21
23
|
private static get controllerComponents();
|
|
22
24
|
private static get handlerComponents();
|
|
23
|
-
private static get globalComponents();
|
|
24
25
|
static getRoutes(controller: Constructor): RouteDefinition[];
|
|
25
26
|
static addRoute(controller: Constructor, route: RouteDefinition): void;
|
|
26
27
|
static getControllerPath(controller: Constructor): string;
|
|
@@ -31,8 +32,6 @@ export declare class MetadataRegistry {
|
|
|
31
32
|
static setModuleOptions(module: Constructor, options: ModuleOptions): void;
|
|
32
33
|
static getParameters(controller: Constructor): Map<string | symbol, ParameterMetadata[]>;
|
|
33
34
|
static addParameter(controller: Constructor, methodName: string | symbol, param: ParameterMetadata): void;
|
|
34
|
-
static registerGlobal<T extends ComponentType>(type: T, component: ComponentTypeMap[T]): void;
|
|
35
|
-
static getGlobal<T extends ComponentType>(type: T): Set<ComponentTypeMap[T]>;
|
|
36
35
|
static registerController<T extends ComponentType>(type: T, controller: Constructor, component: ComponentTypeMap[T]): void;
|
|
37
36
|
static getController<T extends ComponentType>(type: T, controller: Constructor): ComponentTypeMap[T][];
|
|
38
37
|
static registerHandler<T extends ComponentType>(type: T, controller: Constructor, methodName: string | symbol, component: ComponentTypeMap[T]): void;
|
|
@@ -58,6 +57,13 @@ export declare class MetadataRegistry {
|
|
|
58
57
|
static getCustomHandlerMetaAll(target: object, handler: string | symbol): Map<string, unknown> | undefined;
|
|
59
58
|
static appendCustomClassMeta<T>(target: object, key: string, item: T): void;
|
|
60
59
|
static appendCustomHandlerMeta<T>(target: object, handler: string | symbol, key: string, item: T): void;
|
|
60
|
+
static getClassesWithClassMeta(key: string): ReadonlySet<object>;
|
|
61
|
+
static getClassesWithHandlerMeta(key: string): ReadonlySet<object>;
|
|
62
|
+
/** Every (handler, value) pair on `target` carrying metadata under `key`. */
|
|
63
|
+
static getHandlersWithMeta(target: object, key: string): Array<{
|
|
64
|
+
handler: string | symbol;
|
|
65
|
+
value: unknown;
|
|
66
|
+
}>;
|
|
61
67
|
static setReflectMetadata(target: object, key: string, value: unknown, propertyKey?: string | symbol): void;
|
|
62
68
|
static getReflectMetadata<T = unknown>(target: object, key: string, propertyKey?: string | symbol): T | undefined;
|
|
63
69
|
static getParamTypes(target: object, propertyKey?: string | symbol): unknown[] | undefined;
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import { getOrCreate, getOrCreateArray, getOrCreateMap } from "./util.js";
|
|
2
|
-
function emptyComponentStore() {
|
|
3
|
-
return {
|
|
4
|
-
middleware: new Set(),
|
|
5
|
-
guard: new Set(),
|
|
6
|
-
pipe: new Set(),
|
|
7
|
-
interceptor: new Set(),
|
|
8
|
-
filter: new Set()
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
2
|
function emptyComponentByOwner() {
|
|
12
3
|
return {
|
|
13
4
|
middleware: new Map(),
|
|
@@ -32,6 +23,8 @@ function createRegistryState() {
|
|
|
32
23
|
routeVersions: new Map(),
|
|
33
24
|
classMeta: new Map(),
|
|
34
25
|
handlerMeta: new Map(),
|
|
26
|
+
classMetaIndex: new Map(),
|
|
27
|
+
handlerMetaIndex: new Map(),
|
|
35
28
|
controllerComponents: emptyComponentByOwner(),
|
|
36
29
|
handlerComponents: {
|
|
37
30
|
middleware: new Map(),
|
|
@@ -39,8 +32,7 @@ function createRegistryState() {
|
|
|
39
32
|
pipe: new Map(),
|
|
40
33
|
interceptor: new Map(),
|
|
41
34
|
filter: new Map()
|
|
42
|
-
}
|
|
43
|
-
globalComponents: emptyComponentStore()
|
|
35
|
+
}
|
|
44
36
|
};
|
|
45
37
|
}
|
|
46
38
|
// HMR-safe: anchor ALL backing state on `globalThis` so a Vite dev re-eval of
|
|
@@ -50,9 +42,17 @@ function createRegistryState() {
|
|
|
50
42
|
// versioned symbol avoids collisions across framework major versions in one
|
|
51
43
|
// process. `globalThis` + `Symbol.for` exist on every target runtime; no node:*.
|
|
52
44
|
const REGISTRY_STATE_KEY = Symbol.for('vela:registry:v1');
|
|
45
|
+
// Shared empty result for index misses — avoids allocating per lookup.
|
|
46
|
+
const EMPTY_TARGET_SET = new Set();
|
|
53
47
|
function registryState() {
|
|
54
48
|
const g = globalThis;
|
|
55
|
-
|
|
49
|
+
const state = g[REGISTRY_STATE_KEY] ??= createRegistryState();
|
|
50
|
+
// Backfill fields added after the v1 state shape was first anchored: a state
|
|
51
|
+
// created by an older copy of this module (dist/src coexistence in tests,
|
|
52
|
+
// mixed package versions in one process) must not crash newer readers.
|
|
53
|
+
state.classMetaIndex ??= new Map();
|
|
54
|
+
state.handlerMetaIndex ??= new Map();
|
|
55
|
+
return state;
|
|
56
56
|
}
|
|
57
57
|
export class MetadataRegistry {
|
|
58
58
|
// Every field is a getter over the globalThis-anchored state (registryState).
|
|
@@ -97,15 +97,18 @@ export class MetadataRegistry {
|
|
|
97
97
|
static get handlerMeta() {
|
|
98
98
|
return registryState().handlerMeta;
|
|
99
99
|
}
|
|
100
|
+
static get classMetaIndex() {
|
|
101
|
+
return registryState().classMetaIndex;
|
|
102
|
+
}
|
|
103
|
+
static get handlerMetaIndex() {
|
|
104
|
+
return registryState().handlerMetaIndex;
|
|
105
|
+
}
|
|
100
106
|
static get controllerComponents() {
|
|
101
107
|
return registryState().controllerComponents;
|
|
102
108
|
}
|
|
103
109
|
static get handlerComponents() {
|
|
104
110
|
return registryState().handlerComponents;
|
|
105
111
|
}
|
|
106
|
-
static get globalComponents() {
|
|
107
|
-
return registryState().globalComponents;
|
|
108
|
-
}
|
|
109
112
|
// Routes
|
|
110
113
|
static getRoutes(controller) {
|
|
111
114
|
return this.routes.get(controller) ?? [];
|
|
@@ -141,14 +144,9 @@ export class MetadataRegistry {
|
|
|
141
144
|
const methodMap = getOrCreateMap(this.parameters, controller);
|
|
142
145
|
getOrCreateArray(methodMap, methodName).push(param);
|
|
143
146
|
}
|
|
144
|
-
// Component registration —
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
static getGlobal(type) {
|
|
149
|
-
return this.globalComponents[type];
|
|
150
|
-
}
|
|
151
|
-
// Component registration — controller-level
|
|
147
|
+
// Component registration — controller-level. (There is deliberately NO
|
|
148
|
+
// global tier here: app-wide components live on the per-app RouteManager,
|
|
149
|
+
// one source, never process-global state.)
|
|
152
150
|
static registerController(type, controller, component) {
|
|
153
151
|
const map = this.controllerComponents[type];
|
|
154
152
|
getOrCreateArray(map, controller).push(component);
|
|
@@ -228,6 +226,9 @@ export class MetadataRegistry {
|
|
|
228
226
|
// external Reflect.defineMetadata calls — one model, one source of truth.
|
|
229
227
|
static setCustomClassMeta(target, key, value) {
|
|
230
228
|
getOrCreate(this.classMeta, target, ()=>new Map()).set(key, value);
|
|
229
|
+
if (!key.startsWith('design:')) {
|
|
230
|
+
getOrCreate(this.classMetaIndex, key, ()=>new Set()).add(target);
|
|
231
|
+
}
|
|
231
232
|
}
|
|
232
233
|
static getCustomClassMeta(target, key) {
|
|
233
234
|
return this.classMeta.get(target)?.get(key);
|
|
@@ -238,6 +239,9 @@ export class MetadataRegistry {
|
|
|
238
239
|
static setCustomHandlerMeta(target, handler, key, value) {
|
|
239
240
|
const byHandler = getOrCreate(this.handlerMeta, target, ()=>new Map());
|
|
240
241
|
getOrCreate(byHandler, handler, ()=>new Map()).set(key, value);
|
|
242
|
+
if (!key.startsWith('design:')) {
|
|
243
|
+
getOrCreate(this.handlerMetaIndex, key, ()=>new Set()).add(target);
|
|
244
|
+
}
|
|
241
245
|
}
|
|
242
246
|
static getCustomHandlerMeta(target, handler, key) {
|
|
243
247
|
return this.handlerMeta.get(target)?.get(handler)?.get(key);
|
|
@@ -256,6 +260,28 @@ export class MetadataRegistry {
|
|
|
256
260
|
list.push(item);
|
|
257
261
|
this.setCustomHandlerMeta(target, handler, key, list);
|
|
258
262
|
}
|
|
263
|
+
// Reverse-index readers — the DiscoveryService seam. Return the constructors
|
|
264
|
+
// known to carry class-level (resp. handler-level) metadata under `key`.
|
|
265
|
+
// Callers must still intersect with container-registered tokens: decoration
|
|
266
|
+
// alone does not make a class a provider.
|
|
267
|
+
static getClassesWithClassMeta(key) {
|
|
268
|
+
return this.classMetaIndex.get(key) ?? EMPTY_TARGET_SET;
|
|
269
|
+
}
|
|
270
|
+
static getClassesWithHandlerMeta(key) {
|
|
271
|
+
return this.handlerMetaIndex.get(key) ?? EMPTY_TARGET_SET;
|
|
272
|
+
}
|
|
273
|
+
/** Every (handler, value) pair on `target` carrying metadata under `key`. */ static getHandlersWithMeta(target, key) {
|
|
274
|
+
const byHandler = this.handlerMeta.get(target);
|
|
275
|
+
if (!byHandler) return [];
|
|
276
|
+
const out = [];
|
|
277
|
+
for (const [handler, metaMap] of byHandler){
|
|
278
|
+
if (metaMap.has(key)) out.push({
|
|
279
|
+
handler,
|
|
280
|
+
value: metaMap.get(key)
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return out;
|
|
284
|
+
}
|
|
259
285
|
// Reflect-style API — same storage as the typed setters above. Lets external
|
|
260
286
|
// code (and the SWC shim's Reflect.metadata polyfill) write/read uniformly.
|
|
261
287
|
static setReflectMetadata(target, key, value, propertyKey) {
|
|
@@ -294,8 +320,11 @@ export class MetadataRegistry {
|
|
|
294
320
|
}
|
|
295
321
|
// Clear app-time state. Decoration metadata persists — once a class is
|
|
296
322
|
// decorated, that fact is permanent for the lifetime of the process.
|
|
323
|
+
// Currently a no-op: the last piece of app-time registry state (the global
|
|
324
|
+
// component tier) moved to the per-app RouteManager. Kept because test
|
|
325
|
+
// suites call it between cases and future app-time state belongs here.
|
|
297
326
|
static clear() {
|
|
298
|
-
|
|
327
|
+
// no app-time state to clear
|
|
299
328
|
}
|
|
300
329
|
// Full reset, including decoration metadata. Used in framework-internal scenarios.
|
|
301
330
|
static reset() {
|
|
@@ -312,6 +341,8 @@ export class MetadataRegistry {
|
|
|
312
341
|
this.routeVersions.clear();
|
|
313
342
|
this.classMeta.clear();
|
|
314
343
|
this.handlerMeta.clear();
|
|
344
|
+
this.classMetaIndex.clear();
|
|
345
|
+
this.handlerMetaIndex.clear();
|
|
315
346
|
for (const type of [
|
|
316
347
|
'middleware',
|
|
317
348
|
'guard',
|
|
@@ -322,6 +353,5 @@ export class MetadataRegistry {
|
|
|
322
353
|
this.controllerComponents[type].clear();
|
|
323
354
|
this.handlerComponents[type].clear();
|
|
324
355
|
}
|
|
325
|
-
registryState().globalComponents = emptyComponentStore();
|
|
326
356
|
}
|
|
327
357
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { DynamicModule } from '../module/types';
|
|
2
|
+
/**
|
|
3
|
+
* Zero-config module (Tier C): providers live on the `@Module` bag; the
|
|
4
|
+
* `forRoot()` static is NestJS-parity sugar returning the bare dynamic module
|
|
5
|
+
* (default key — repeated calls dedup).
|
|
6
|
+
*/
|
|
2
7
|
export declare class ScheduleModule {
|
|
3
8
|
static forRoot(): DynamicModule;
|
|
4
9
|
}
|
|
@@ -1,15 +1,25 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
import { Module } from "../module/decorators.js";
|
|
1
8
|
import { ScheduleRegistry } from "./schedule.registry.js";
|
|
2
9
|
export class ScheduleModule {
|
|
3
10
|
static forRoot() {
|
|
4
|
-
const providers = [
|
|
5
|
-
ScheduleRegistry
|
|
6
|
-
];
|
|
7
11
|
return {
|
|
8
|
-
module: ScheduleModule
|
|
9
|
-
providers,
|
|
10
|
-
exports: [
|
|
11
|
-
ScheduleRegistry
|
|
12
|
-
]
|
|
12
|
+
module: ScheduleModule
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
+
ScheduleModule = _ts_decorate([
|
|
17
|
+
Module({
|
|
18
|
+
providers: [
|
|
19
|
+
ScheduleRegistry
|
|
20
|
+
],
|
|
21
|
+
exports: [
|
|
22
|
+
ScheduleRegistry
|
|
23
|
+
]
|
|
24
|
+
})
|
|
25
|
+
], ScheduleModule);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DiscoveryService } from '../discovery/discovery.service';
|
|
2
2
|
import type { OnApplicationBootstrap } from '../lifecycle/index';
|
|
3
3
|
export interface RegisteredCronJob {
|
|
4
4
|
expression: string;
|
|
@@ -13,10 +13,10 @@ export interface RegisteredIntervalJob {
|
|
|
13
13
|
target: Function;
|
|
14
14
|
}
|
|
15
15
|
export declare class ScheduleRegistry implements OnApplicationBootstrap {
|
|
16
|
-
private
|
|
16
|
+
private readonly discovery;
|
|
17
17
|
private cronJobs;
|
|
18
18
|
private intervalJobs;
|
|
19
|
-
constructor(
|
|
19
|
+
constructor(discovery: DiscoveryService);
|
|
20
20
|
onApplicationBootstrap(): void;
|
|
21
21
|
getCronJobs(): RegisteredCronJob[];
|
|
22
22
|
getIntervalJobs(): RegisteredIntervalJob[];
|
|
@@ -13,54 +13,33 @@ function _ts_param(paramIndex, decorator) {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
import { Injectable, Inject } from "../container/index.js";
|
|
16
|
-
import {
|
|
17
|
-
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
16
|
+
import { DiscoveryService } from "../discovery/discovery.service.js";
|
|
18
17
|
import { CRON_METADATA, INTERVAL_METADATA } from "./schedule.tokens.js";
|
|
19
18
|
export class ScheduleRegistry {
|
|
20
|
-
|
|
19
|
+
discovery;
|
|
21
20
|
cronJobs = [];
|
|
22
21
|
intervalJobs = [];
|
|
23
|
-
constructor(
|
|
24
|
-
this.
|
|
22
|
+
constructor(discovery){
|
|
23
|
+
this.discovery = discovery;
|
|
25
24
|
}
|
|
26
25
|
onApplicationBootstrap() {
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
if (cronMeta) {
|
|
45
|
-
for (const { expression, methodName } of cronMeta){
|
|
46
|
-
this.cronJobs.push({
|
|
47
|
-
expression,
|
|
48
|
-
methodName,
|
|
49
|
-
instance,
|
|
50
|
-
target: token
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (intervalMeta) {
|
|
55
|
-
for (const { ms, methodName } of intervalMeta){
|
|
56
|
-
this.intervalJobs.push({
|
|
57
|
-
ms,
|
|
58
|
-
methodName,
|
|
59
|
-
instance,
|
|
60
|
-
target: token
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
26
|
+
for (const found of this.discovery.methodsWithMeta(CRON_METADATA)){
|
|
27
|
+
if (!found.class.instance) continue;
|
|
28
|
+
this.cronJobs.push({
|
|
29
|
+
expression: found.meta.expression,
|
|
30
|
+
methodName: String(found.methodName),
|
|
31
|
+
instance: found.class.instance,
|
|
32
|
+
target: found.class.metatype
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
for (const found of this.discovery.methodsWithMeta(INTERVAL_METADATA)){
|
|
36
|
+
if (!found.class.instance) continue;
|
|
37
|
+
this.intervalJobs.push({
|
|
38
|
+
ms: found.meta.ms,
|
|
39
|
+
methodName: String(found.methodName),
|
|
40
|
+
instance: found.class.instance,
|
|
41
|
+
target: found.class.metatype
|
|
42
|
+
});
|
|
64
43
|
}
|
|
65
44
|
}
|
|
66
45
|
getCronJobs() {
|
|
@@ -76,9 +55,9 @@ export class ScheduleRegistry {
|
|
|
76
55
|
}
|
|
77
56
|
ScheduleRegistry = _ts_decorate([
|
|
78
57
|
Injectable(),
|
|
79
|
-
_ts_param(0, Inject(
|
|
58
|
+
_ts_param(0, Inject(DiscoveryService)),
|
|
80
59
|
_ts_metadata("design:type", Function),
|
|
81
60
|
_ts_metadata("design:paramtypes", [
|
|
82
|
-
typeof
|
|
61
|
+
typeof DiscoveryService === "undefined" ? Object : DiscoveryService
|
|
83
62
|
])
|
|
84
63
|
], ScheduleRegistry);
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { DynamicModule } from '../module/types';
|
|
2
|
+
/**
|
|
3
|
+
* Zero-config module (Tier C): providers live on the `@Module` bag; the
|
|
4
|
+
* `forRoot()` static is NestJS-parity sugar returning the bare dynamic module
|
|
5
|
+
* (default key — repeated calls dedup).
|
|
6
|
+
*/
|
|
2
7
|
export declare class ScheduleNodeModule {
|
|
3
8
|
static forRoot(): DynamicModule;
|
|
4
9
|
}
|
|
@@ -1,18 +1,28 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
import { Module } from "../module/decorators.js";
|
|
1
8
|
import { ScheduleRegistry } from "../schedule/schedule.registry.js";
|
|
2
9
|
import { ScheduleExecutor } from "./schedule.executor.js";
|
|
3
10
|
export class ScheduleNodeModule {
|
|
4
11
|
static forRoot() {
|
|
5
|
-
const providers = [
|
|
6
|
-
ScheduleRegistry,
|
|
7
|
-
ScheduleExecutor
|
|
8
|
-
];
|
|
9
12
|
return {
|
|
10
|
-
module: ScheduleNodeModule
|
|
11
|
-
providers,
|
|
12
|
-
exports: [
|
|
13
|
-
ScheduleRegistry,
|
|
14
|
-
ScheduleExecutor
|
|
15
|
-
]
|
|
13
|
+
module: ScheduleNodeModule
|
|
16
14
|
};
|
|
17
15
|
}
|
|
18
16
|
}
|
|
17
|
+
ScheduleNodeModule = _ts_decorate([
|
|
18
|
+
Module({
|
|
19
|
+
providers: [
|
|
20
|
+
ScheduleRegistry,
|
|
21
|
+
ScheduleExecutor
|
|
22
|
+
],
|
|
23
|
+
exports: [
|
|
24
|
+
ScheduleRegistry,
|
|
25
|
+
ScheduleExecutor
|
|
26
|
+
]
|
|
27
|
+
})
|
|
28
|
+
], ScheduleNodeModule);
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import type { VelaApplication } from '../application';
|
|
2
|
-
import type { DynamicModule } from '../module/types';
|
|
3
2
|
import type { Type } from '../container/types';
|
|
4
3
|
import type { SeederResult } from './seeder.types';
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
seeders?: Type[];
|
|
13
|
-
}): DynamicModule;
|
|
4
|
+
export interface SeederModuleOptions {
|
|
5
|
+
seeders?: Type[];
|
|
6
|
+
}
|
|
7
|
+
declare const ConfigurableModuleClass: import("..").ConfigurableModuleClassType<SeederModuleOptions, "forRoot", "create", {
|
|
8
|
+
isGlobal?: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
export declare class SeederModule extends ConfigurableModuleClass {
|
|
14
11
|
}
|
|
15
12
|
/** Convenience runner: resolve the registry from a built app and run all seeders. */
|
|
16
13
|
export declare function runSeeders(app: VelaApplication, options?: {
|
|
17
14
|
stopOnError?: boolean;
|
|
18
15
|
}): Promise<SeederResult[]>;
|
|
16
|
+
export {};
|