@velajs/vela 1.9.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 +122 -0
- package/dist/__tests__/workers-als/entry-als.d.ts +9 -0
- package/dist/application.d.ts +18 -0
- package/dist/application.js +45 -0
- package/dist/cache/cache.module.d.ts +5 -7
- package/dist/cache/cache.module.js +44 -66
- package/dist/cache/cache.types.d.ts +26 -0
- package/dist/cache/cache.types.js +1 -1
- package/dist/cache/index.d.ts +2 -1
- package/dist/cache/index.js +1 -0
- package/dist/cache/tiered-cache.store.d.ts +19 -0
- package/dist/cache/tiered-cache.store.js +40 -0
- package/dist/config/config.module.d.ts +6 -5
- package/dist/config/config.module.js +46 -49
- package/dist/container/container.d.ts +58 -0
- package/dist/container/container.js +223 -18
- package/dist/container/disposable.d.ts +5 -0
- package/dist/container/disposable.js +33 -0
- package/dist/container/types.d.ts +8 -0
- 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 +20 -2
- package/dist/factory.d.ts +11 -1
- package/dist/factory.js +23 -2
- package/dist/fetch/fetch.module.d.ts +5 -6
- package/dist/fetch/fetch.module.js +9 -42
- package/dist/http/ambient.d.ts +17 -0
- package/dist/http/ambient.js +44 -0
- package/dist/http/execution-context.js +4 -1
- package/dist/http/handler-executor.js +22 -19
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.js +1 -0
- package/dist/http/route-contributor.d.ts +68 -0
- package/dist/http/route-contributor.js +22 -0
- package/dist/http/route.manager.d.ts +19 -0
- package/dist/http/route.manager.js +112 -19
- package/dist/i18n/deep-merge.d.ts +2 -0
- package/dist/i18n/deep-merge.js +15 -0
- package/dist/i18n/i18n.middleware.d.ts +15 -0
- package/dist/i18n/i18n.middleware.js +94 -0
- package/dist/i18n/i18n.module.d.ts +13 -0
- package/dist/i18n/i18n.module.js +64 -0
- package/dist/i18n/i18n.options.d.ts +30 -0
- package/dist/i18n/i18n.options.js +16 -0
- package/dist/i18n/i18n.service.d.ts +20 -0
- package/dist/i18n/i18n.service.js +49 -0
- package/dist/i18n/i18n.tokens.d.ts +6 -0
- package/dist/i18n/i18n.tokens.js +3 -0
- package/dist/i18n/i18n.types.d.ts +6 -0
- package/dist/i18n/i18n.types.js +1 -0
- package/dist/i18n/index.d.ts +10 -0
- package/dist/i18n/index.js +8 -0
- package/dist/i18n/message-loader.service.d.ts +21 -0
- package/dist/i18n/message-loader.service.js +90 -0
- package/dist/i18n/message-registry.d.ts +16 -0
- package/dist/i18n/message-registry.js +49 -0
- package/dist/index.d.ts +17 -5
- package/dist/index.js +14 -3
- package/dist/internal.d.ts +0 -2
- package/dist/internal.js +0 -7
- package/dist/module/configurable-module.builder.d.ts +56 -0
- package/dist/module/configurable-module.builder.js +84 -0
- package/dist/module/configurable-module.types.d.ts +93 -0
- package/dist/module/configurable-module.types.js +5 -0
- package/dist/module/define-module.d.ts +105 -0
- package/dist/module/define-module.js +227 -0
- package/dist/module/index.d.ts +4 -0
- package/dist/module/index.js +3 -0
- 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/pipeline/types.d.ts +21 -4
- package/dist/registry/metadata.registry.d.ts +24 -18
- package/dist/registry/metadata.registry.js +137 -49
- 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/index.d.ts +5 -0
- package/dist/seeder/index.js +4 -0
- package/dist/seeder/seeder.decorator.d.ts +7 -0
- package/dist/seeder/seeder.decorator.js +15 -0
- package/dist/seeder/seeder.module.d.ts +16 -0
- package/dist/seeder/seeder.module.js +41 -0
- package/dist/seeder/seeder.registry.d.ts +23 -0
- package/dist/seeder/seeder.registry.js +83 -0
- package/dist/seeder/seeder.tokens.d.ts +2 -0
- package/dist/seeder/seeder.tokens.js +1 -0
- package/dist/seeder/seeder.types.d.ts +20 -0
- package/dist/seeder/seeder.types.js +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/path-template.d.ts +9 -0
- package/dist/storage/path-template.js +20 -0
- package/dist/storage/signed-url.d.ts +12 -0
- package/dist/storage/signed-url.js +55 -0
- package/dist/storage/storage.types.d.ts +41 -0
- package/dist/storage/storage.types.js +5 -0
- package/dist/throttler/throttler.module.d.ts +5 -8
- package/dist/throttler/throttler.module.js +27 -55
- package/dist/websocket/index.d.ts +12 -0
- package/dist/websocket/index.js +16 -0
- package/dist/websocket/websocket.decorators.d.ts +33 -0
- package/dist/websocket/websocket.decorators.js +58 -0
- package/dist/websocket/websocket.module.d.ts +35 -0
- package/dist/websocket/websocket.module.js +63 -0
- package/dist/websocket/websocket.tokens.d.ts +23 -0
- package/dist/websocket/websocket.tokens.js +21 -0
- package/dist/websocket/websocket.types.d.ts +86 -0
- package/dist/websocket/websocket.types.js +4 -0
- package/dist/websocket/ws-argument-resolver.d.ts +13 -0
- package/dist/websocket/ws-argument-resolver.js +40 -0
- package/dist/websocket/ws-dispatcher.d.ts +45 -0
- package/dist/websocket/ws-dispatcher.js +259 -0
- package/dist/websocket/ws-exception.d.ts +16 -0
- package/dist/websocket/ws-exception.js +32 -0
- package/dist/websocket/ws-execution-context.d.ts +9 -0
- package/dist/websocket/ws-execution-context.js +24 -0
- package/dist/websocket/ws-server.d.ts +31 -0
- package/dist/websocket/ws-server.js +74 -0
- package/dist/websocket/ws-sync.d.ts +47 -0
- package/dist/websocket/ws-sync.js +74 -0
- package/dist/websocket-node/index.d.ts +4 -0
- package/dist/websocket-node/index.js +5 -0
- package/dist/websocket-node/node-ws-client.d.ts +24 -0
- package/dist/websocket-node/node-ws-client.js +49 -0
- package/dist/websocket-node/redis-sync.d.ts +33 -0
- package/dist/websocket-node/redis-sync.js +56 -0
- package/dist/websocket-node/register-gateways.d.ts +20 -0
- package/dist/websocket-node/register-gateways.js +61 -0
- package/package.json +31 -1
- package/dist/http/crud-bridge.d.ts +0 -90
- package/dist/http/crud-bridge.js +0 -25
|
@@ -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
|
+
}
|
package/dist/pipeline/types.d.ts
CHANGED
|
@@ -11,16 +11,33 @@ export interface HttpArgumentsHost {
|
|
|
11
11
|
getRequest<T = Request>(): T;
|
|
12
12
|
getResponse<T = Context>(): T;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* WebSocket-specific arguments host returned by `ExecutionContext.switchToWs()`.
|
|
16
|
+
* Populated by `@velajs/vela/websocket` when a gateway message is dispatched.
|
|
17
|
+
*
|
|
18
|
+
* - `getClient()` — the connected socket (`WsClient`)
|
|
19
|
+
* - `getData()` — the inbound message payload (the envelope's `data`)
|
|
20
|
+
* - `getPattern()` — the subscribed event name that matched
|
|
21
|
+
*/
|
|
22
|
+
export interface WsArgumentsHost {
|
|
23
|
+
getClient<T = unknown>(): T;
|
|
24
|
+
getData<T = unknown>(): T;
|
|
25
|
+
getPattern<T = string>(): T;
|
|
26
|
+
}
|
|
27
|
+
/** The transport a component is executing under. `'http'` for routes, `'ws'` for gateway messages. */
|
|
28
|
+
export type ContextType = 'http' | 'ws';
|
|
14
29
|
export interface ExecutionContext {
|
|
15
|
-
getType<T extends string =
|
|
30
|
+
getType<T extends string = ContextType>(): T;
|
|
16
31
|
getClass(): Type;
|
|
17
32
|
getHandler(): string | symbol;
|
|
18
|
-
/** Returns the Hono `Context` directly. */
|
|
33
|
+
/** Returns the Hono `Context` directly. Throws on a WebSocket context. */
|
|
19
34
|
getContext<T = Context>(): T;
|
|
20
|
-
/** Shorthand for `switchToHttp().getRequest()` — returns the Web `Request`. */
|
|
35
|
+
/** Shorthand for `switchToHttp().getRequest()` — returns the Web `Request`. Throws on a WebSocket context. */
|
|
21
36
|
getRequest(): Request;
|
|
22
|
-
/** Switch to the HTTP arguments host
|
|
37
|
+
/** Switch to the HTTP arguments host. Throws on a WebSocket context. */
|
|
23
38
|
switchToHttp(): HttpArgumentsHost;
|
|
39
|
+
/** Switch to the WebSocket arguments host. Throws on an HTTP context. */
|
|
40
|
+
switchToWs(): WsArgumentsHost;
|
|
24
41
|
}
|
|
25
42
|
export interface CanActivate {
|
|
26
43
|
canActivate(context: ExecutionContext): boolean | Promise<boolean>;
|
|
@@ -5,22 +5,23 @@ export interface ControllerOptions {
|
|
|
5
5
|
version?: number | number[];
|
|
6
6
|
}
|
|
7
7
|
export declare class MetadataRegistry {
|
|
8
|
-
private static
|
|
9
|
-
private static
|
|
10
|
-
private static
|
|
11
|
-
private static
|
|
12
|
-
private static
|
|
13
|
-
private static
|
|
14
|
-
private static
|
|
15
|
-
private static
|
|
16
|
-
private static
|
|
17
|
-
private static
|
|
18
|
-
private static
|
|
19
|
-
private static
|
|
20
|
-
private static
|
|
21
|
-
private static
|
|
22
|
-
private static
|
|
23
|
-
private static
|
|
8
|
+
private static get routes();
|
|
9
|
+
private static get controllers();
|
|
10
|
+
private static get controllerOptions();
|
|
11
|
+
private static get modules();
|
|
12
|
+
private static get parameters();
|
|
13
|
+
private static get injectables();
|
|
14
|
+
private static get scopes();
|
|
15
|
+
private static get injectTokens();
|
|
16
|
+
private static get handlerHttpMeta();
|
|
17
|
+
private static get catchTypes();
|
|
18
|
+
private static get routeVersions();
|
|
19
|
+
private static get classMeta();
|
|
20
|
+
private static get handlerMeta();
|
|
21
|
+
private static get classMetaIndex();
|
|
22
|
+
private static get handlerMetaIndex();
|
|
23
|
+
private static get controllerComponents();
|
|
24
|
+
private static get handlerComponents();
|
|
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(),
|
|
@@ -17,37 +8,107 @@ function emptyComponentByOwner() {
|
|
|
17
8
|
filter: new Map()
|
|
18
9
|
};
|
|
19
10
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
pipe: new Map(),
|
|
46
|
-
interceptor: new Map(),
|
|
47
|
-
filter: new Map()
|
|
11
|
+
function createRegistryState() {
|
|
12
|
+
return {
|
|
13
|
+
routes: new Map(),
|
|
14
|
+
controllers: new Map(),
|
|
15
|
+
controllerOptions: new Map(),
|
|
16
|
+
modules: new Map(),
|
|
17
|
+
parameters: new Map(),
|
|
18
|
+
injectables: new Set(),
|
|
19
|
+
scopes: new Map(),
|
|
20
|
+
injectTokens: new Map(),
|
|
21
|
+
handlerHttpMeta: new Map(),
|
|
22
|
+
catchTypes: new Map(),
|
|
23
|
+
routeVersions: new Map(),
|
|
24
|
+
classMeta: new Map(),
|
|
25
|
+
handlerMeta: new Map(),
|
|
26
|
+
classMetaIndex: new Map(),
|
|
27
|
+
handlerMetaIndex: new Map(),
|
|
28
|
+
controllerComponents: emptyComponentByOwner(),
|
|
29
|
+
handlerComponents: {
|
|
30
|
+
middleware: new Map(),
|
|
31
|
+
guard: new Map(),
|
|
32
|
+
pipe: new Map(),
|
|
33
|
+
interceptor: new Map(),
|
|
34
|
+
filter: new Map()
|
|
35
|
+
}
|
|
48
36
|
};
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
}
|
|
38
|
+
// HMR-safe: anchor ALL backing state on `globalThis` so a Vite dev re-eval of
|
|
39
|
+
// this module reuses the SAME maps that classes were already decorated against.
|
|
40
|
+
// Without this, re-eval creates fresh empty statics → split-brain (lost routes,
|
|
41
|
+
// spurious "not @Injectable" warnings, duplicated global components). The
|
|
42
|
+
// versioned symbol avoids collisions across framework major versions in one
|
|
43
|
+
// process. `globalThis` + `Symbol.for` exist on every target runtime; no node:*.
|
|
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();
|
|
47
|
+
function registryState() {
|
|
48
|
+
const g = globalThis;
|
|
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
|
+
}
|
|
57
|
+
export class MetadataRegistry {
|
|
58
|
+
// Every field is a getter over the globalThis-anchored state (registryState).
|
|
59
|
+
// Method bodies keep using `this.<field>`; the getter returns the live map so
|
|
60
|
+
// `.set`/`.get`/`.clear` mutate the shared state.
|
|
61
|
+
static get routes() {
|
|
62
|
+
return registryState().routes;
|
|
63
|
+
}
|
|
64
|
+
static get controllers() {
|
|
65
|
+
return registryState().controllers;
|
|
66
|
+
}
|
|
67
|
+
static get controllerOptions() {
|
|
68
|
+
return registryState().controllerOptions;
|
|
69
|
+
}
|
|
70
|
+
static get modules() {
|
|
71
|
+
return registryState().modules;
|
|
72
|
+
}
|
|
73
|
+
static get parameters() {
|
|
74
|
+
return registryState().parameters;
|
|
75
|
+
}
|
|
76
|
+
static get injectables() {
|
|
77
|
+
return registryState().injectables;
|
|
78
|
+
}
|
|
79
|
+
static get scopes() {
|
|
80
|
+
return registryState().scopes;
|
|
81
|
+
}
|
|
82
|
+
static get injectTokens() {
|
|
83
|
+
return registryState().injectTokens;
|
|
84
|
+
}
|
|
85
|
+
static get handlerHttpMeta() {
|
|
86
|
+
return registryState().handlerHttpMeta;
|
|
87
|
+
}
|
|
88
|
+
static get catchTypes() {
|
|
89
|
+
return registryState().catchTypes;
|
|
90
|
+
}
|
|
91
|
+
static get routeVersions() {
|
|
92
|
+
return registryState().routeVersions;
|
|
93
|
+
}
|
|
94
|
+
static get classMeta() {
|
|
95
|
+
return registryState().classMeta;
|
|
96
|
+
}
|
|
97
|
+
static get handlerMeta() {
|
|
98
|
+
return registryState().handlerMeta;
|
|
99
|
+
}
|
|
100
|
+
static get classMetaIndex() {
|
|
101
|
+
return registryState().classMetaIndex;
|
|
102
|
+
}
|
|
103
|
+
static get handlerMetaIndex() {
|
|
104
|
+
return registryState().handlerMetaIndex;
|
|
105
|
+
}
|
|
106
|
+
static get controllerComponents() {
|
|
107
|
+
return registryState().controllerComponents;
|
|
108
|
+
}
|
|
109
|
+
static get handlerComponents() {
|
|
110
|
+
return registryState().handlerComponents;
|
|
111
|
+
}
|
|
51
112
|
// Routes
|
|
52
113
|
static getRoutes(controller) {
|
|
53
114
|
return this.routes.get(controller) ?? [];
|
|
@@ -83,14 +144,9 @@ export class MetadataRegistry {
|
|
|
83
144
|
const methodMap = getOrCreateMap(this.parameters, controller);
|
|
84
145
|
getOrCreateArray(methodMap, methodName).push(param);
|
|
85
146
|
}
|
|
86
|
-
// Component registration —
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
static getGlobal(type) {
|
|
91
|
-
return this.globalComponents[type];
|
|
92
|
-
}
|
|
93
|
-
// 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.)
|
|
94
150
|
static registerController(type, controller, component) {
|
|
95
151
|
const map = this.controllerComponents[type];
|
|
96
152
|
getOrCreateArray(map, controller).push(component);
|
|
@@ -170,6 +226,9 @@ export class MetadataRegistry {
|
|
|
170
226
|
// external Reflect.defineMetadata calls — one model, one source of truth.
|
|
171
227
|
static setCustomClassMeta(target, key, value) {
|
|
172
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
|
+
}
|
|
173
232
|
}
|
|
174
233
|
static getCustomClassMeta(target, key) {
|
|
175
234
|
return this.classMeta.get(target)?.get(key);
|
|
@@ -180,6 +239,9 @@ export class MetadataRegistry {
|
|
|
180
239
|
static setCustomHandlerMeta(target, handler, key, value) {
|
|
181
240
|
const byHandler = getOrCreate(this.handlerMeta, target, ()=>new Map());
|
|
182
241
|
getOrCreate(byHandler, handler, ()=>new Map()).set(key, value);
|
|
242
|
+
if (!key.startsWith('design:')) {
|
|
243
|
+
getOrCreate(this.handlerMetaIndex, key, ()=>new Set()).add(target);
|
|
244
|
+
}
|
|
183
245
|
}
|
|
184
246
|
static getCustomHandlerMeta(target, handler, key) {
|
|
185
247
|
return this.handlerMeta.get(target)?.get(handler)?.get(key);
|
|
@@ -198,6 +260,28 @@ export class MetadataRegistry {
|
|
|
198
260
|
list.push(item);
|
|
199
261
|
this.setCustomHandlerMeta(target, handler, key, list);
|
|
200
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
|
+
}
|
|
201
285
|
// Reflect-style API — same storage as the typed setters above. Lets external
|
|
202
286
|
// code (and the SWC shim's Reflect.metadata polyfill) write/read uniformly.
|
|
203
287
|
static setReflectMetadata(target, key, value, propertyKey) {
|
|
@@ -236,8 +320,11 @@ export class MetadataRegistry {
|
|
|
236
320
|
}
|
|
237
321
|
// Clear app-time state. Decoration metadata persists — once a class is
|
|
238
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.
|
|
239
326
|
static clear() {
|
|
240
|
-
|
|
327
|
+
// no app-time state to clear
|
|
241
328
|
}
|
|
242
329
|
// Full reset, including decoration metadata. Used in framework-internal scenarios.
|
|
243
330
|
static reset() {
|
|
@@ -254,6 +341,8 @@ export class MetadataRegistry {
|
|
|
254
341
|
this.routeVersions.clear();
|
|
255
342
|
this.classMeta.clear();
|
|
256
343
|
this.handlerMeta.clear();
|
|
344
|
+
this.classMetaIndex.clear();
|
|
345
|
+
this.handlerMetaIndex.clear();
|
|
257
346
|
for (const type of [
|
|
258
347
|
'middleware',
|
|
259
348
|
'guard',
|
|
@@ -264,6 +353,5 @@ export class MetadataRegistry {
|
|
|
264
353
|
this.controllerComponents[type].clear();
|
|
265
354
|
this.handlerComponents[type].clear();
|
|
266
355
|
}
|
|
267
|
-
this.globalComponents = emptyComponentStore();
|
|
268
356
|
}
|
|
269
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);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Seeder } from './seeder.decorator';
|
|
2
|
+
export { SeederRegistry } from './seeder.registry';
|
|
3
|
+
export { SeederModule, runSeeders } from './seeder.module';
|
|
4
|
+
export { SEEDER_METADATA } from './seeder.tokens';
|
|
5
|
+
export type { Seeder as ISeeder, SeederMetadata, RegisteredSeeder, SeederResult, } from './seeder.types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SeederMetadata } from './seeder.types';
|
|
2
|
+
/**
|
|
3
|
+
* Mark a class as a seeder. Also marks it `@Injectable()` (singleton) so it only
|
|
4
|
+
* needs to be listed in a module's providers (or `SeederModule.forRoot({ seeders })`)
|
|
5
|
+
* to be discovered by {@link SeederRegistry} at bootstrap.
|
|
6
|
+
*/
|
|
7
|
+
export declare function Seeder(options?: SeederMetadata): ClassDecorator;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Scope } from "../constants.js";
|
|
2
|
+
import { MetadataRegistry } from "../registry/metadata.registry.js";
|
|
3
|
+
import { SEEDER_METADATA } from "./seeder.tokens.js";
|
|
4
|
+
/**
|
|
5
|
+
* Mark a class as a seeder. Also marks it `@Injectable()` (singleton) so it only
|
|
6
|
+
* needs to be listed in a module's providers (or `SeederModule.forRoot({ seeders })`)
|
|
7
|
+
* to be discovered by {@link SeederRegistry} at bootstrap.
|
|
8
|
+
*/ export function Seeder(options = {}) {
|
|
9
|
+
return (target)=>{
|
|
10
|
+
const ctor = target;
|
|
11
|
+
MetadataRegistry.markInjectable(ctor);
|
|
12
|
+
MetadataRegistry.setScope(ctor, Scope.SINGLETON);
|
|
13
|
+
MetadataRegistry.setCustomClassMeta(target, SEEDER_METADATA, options);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { VelaApplication } from '../application';
|
|
2
|
+
import type { Type } from '../container/types';
|
|
3
|
+
import type { SeederResult } from './seeder.types';
|
|
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 {
|
|
11
|
+
}
|
|
12
|
+
/** Convenience runner: resolve the registry from a built app and run all seeders. */
|
|
13
|
+
export declare function runSeeders(app: VelaApplication, options?: {
|
|
14
|
+
stopOnError?: boolean;
|
|
15
|
+
}): Promise<SeederResult[]>;
|
|
16
|
+
export {};
|