@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.
Files changed (77) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/dist/application.d.ts +8 -0
  3. package/dist/application.js +20 -0
  4. package/dist/container/container.d.ts +25 -0
  5. package/dist/container/container.js +67 -11
  6. package/dist/container/disposable.js +1 -1
  7. package/dist/cors/cors.module.d.ts +5 -5
  8. package/dist/cors/cors.module.js +26 -25
  9. package/dist/discovery/discoverable.decorator.d.ts +38 -0
  10. package/dist/discovery/discoverable.decorator.js +42 -0
  11. package/dist/discovery/discovery.service.d.ts +94 -0
  12. package/dist/discovery/discovery.service.js +166 -0
  13. package/dist/discovery/index.d.ts +2 -0
  14. package/dist/discovery/index.js +2 -0
  15. package/dist/entrypoint/entrypoint.registry.d.ts +40 -0
  16. package/dist/entrypoint/entrypoint.registry.js +106 -0
  17. package/dist/entrypoint/entrypoint.types.d.ts +41 -0
  18. package/dist/entrypoint/entrypoint.types.js +3 -0
  19. package/dist/entrypoint/execution-context.d.ts +15 -0
  20. package/dist/entrypoint/execution-context.js +21 -0
  21. package/dist/entrypoint/execution-scope.d.ts +21 -0
  22. package/dist/entrypoint/execution-scope.js +28 -0
  23. package/dist/entrypoint/index.d.ts +4 -0
  24. package/dist/entrypoint/index.js +4 -0
  25. package/dist/event-emitter/event-emitter.subscriber.d.ts +3 -3
  26. package/dist/event-emitter/event-emitter.subscriber.js +12 -29
  27. package/dist/factory/adapter.d.ts +36 -0
  28. package/dist/factory/adapter.js +18 -0
  29. package/dist/factory/bootstrap.js +10 -2
  30. package/dist/factory.d.ts +11 -1
  31. package/dist/factory.js +23 -2
  32. package/dist/http/handler-executor.js +22 -19
  33. package/dist/http/route-contributor.d.ts +68 -0
  34. package/dist/http/route-contributor.js +22 -0
  35. package/dist/http/route.manager.js +28 -19
  36. package/dist/i18n/i18n.module.js +4 -1
  37. package/dist/index.d.ts +12 -3
  38. package/dist/index.js +9 -2
  39. package/dist/internal.d.ts +0 -2
  40. package/dist/internal.js +0 -7
  41. package/dist/module/configurable-module.builder.d.ts +12 -0
  42. package/dist/module/configurable-module.builder.js +21 -114
  43. package/dist/module/define-module.d.ts +105 -0
  44. package/dist/module/define-module.js +227 -0
  45. package/dist/module/index.d.ts +3 -1
  46. package/dist/module/index.js +3 -1
  47. package/dist/module/lazy-provider.d.ts +65 -0
  48. package/dist/module/lazy-provider.js +111 -0
  49. package/dist/openapi/document.js +16 -15
  50. package/dist/pipeline/component.manager.d.ts +15 -9
  51. package/dist/pipeline/component.manager.js +32 -46
  52. package/dist/pipeline/index.d.ts +2 -0
  53. package/dist/pipeline/index.js +1 -0
  54. package/dist/pipeline/pipeline-runner.d.ts +31 -0
  55. package/dist/pipeline/pipeline-runner.js +40 -0
  56. package/dist/registry/metadata.registry.d.ts +9 -3
  57. package/dist/registry/metadata.registry.js +55 -25
  58. package/dist/schedule/schedule.module.d.ts +5 -0
  59. package/dist/schedule/schedule.module.js +18 -8
  60. package/dist/schedule/schedule.registry.d.ts +3 -3
  61. package/dist/schedule/schedule.registry.js +23 -44
  62. package/dist/schedule-node/schedule-node.module.d.ts +5 -0
  63. package/dist/schedule-node/schedule-node.module.js +20 -10
  64. package/dist/seeder/seeder.module.d.ts +8 -10
  65. package/dist/seeder/seeder.module.js +16 -15
  66. package/dist/websocket/index.d.ts +1 -1
  67. package/dist/websocket/index.js +1 -1
  68. package/dist/websocket/websocket.module.d.ts +20 -3
  69. package/dist/websocket/websocket.module.js +50 -39
  70. package/dist/websocket/websocket.tokens.d.ts +2 -1
  71. package/dist/websocket/websocket.tokens.js +3 -2
  72. package/dist/websocket/ws-dispatcher.d.ts +21 -9
  73. package/dist/websocket/ws-dispatcher.js +44 -38
  74. package/dist/websocket-node/register-gateways.js +3 -3
  75. package/package.json +1 -1
  76. package/dist/http/crud-bridge.d.ts +0 -90
  77. 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
- export class ComponentManager {
6
- static container;
7
- static init(container) {
8
- this.container = container;
9
- }
10
- // 3-level registration
11
- static registerGlobal(type, ...components) {
12
- for (const component of components){
13
- MetadataRegistry.registerGlobal(type, component);
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
- // 3-level resolution: globalcontroller handler
27
- static getComponents(type, controller, handlerName) {
28
- const controllerComponents = MetadataRegistry.getController(type, controller);
29
- const handlerComponents = MetadataRegistry.getHandler(type, controller, handlerName);
26
+ // Scoped resolution: controllerhandler. 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.getGlobal(type),
32
- ...controllerComponents,
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 : this.container.resolve(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
- if (interceptors.length === 0) {
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
  }
@@ -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';
@@ -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
- return g[REGISTRY_STATE_KEY] ??= createRegistryState();
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 — global
145
- static registerGlobal(type, component) {
146
- this.globalComponents[type].add(component);
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
- registryState().globalComponents = emptyComponentStore();
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 { Container } from '../container/container';
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 container;
16
+ private readonly discovery;
17
17
  private cronJobs;
18
18
  private intervalJobs;
19
- constructor(container: Container);
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 { Container } from "../container/container.js";
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
- container;
19
+ discovery;
21
20
  cronJobs = [];
22
21
  intervalJobs = [];
23
- constructor(container){
24
- this.container = container;
22
+ constructor(discovery){
23
+ this.discovery = discovery;
25
24
  }
26
25
  onApplicationBootstrap() {
27
- const tokens = this.container.getTokens();
28
- for (const token of tokens){
29
- if (typeof token !== 'function') continue;
30
- const cronMeta = MetadataRegistry.getCustomClassMeta(token, CRON_METADATA);
31
- const intervalMeta = MetadataRegistry.getCustomClassMeta(token, INTERVAL_METADATA);
32
- if (!cronMeta && !intervalMeta) continue;
33
- let instance;
34
- try {
35
- instance = this.container.resolve(token);
36
- } catch (err) {
37
- const mode = this.container.getDiagnostics();
38
- if (mode === 'throw') throw err;
39
- if (mode === 'log') {
40
- console.warn(`[vela] schedule discovery: cannot resolve ${token.name || String(token)}:`, err);
41
- }
42
- continue;
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(Container)),
58
+ _ts_param(0, Inject(DiscoveryService)),
80
59
  _ts_metadata("design:type", Function),
81
60
  _ts_metadata("design:paramtypes", [
82
- typeof Container === "undefined" ? Object : Container
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 declare class SeederModule {
6
- /**
7
- * Register seeder classes as providers so they're discovered at bootstrap.
8
- * (Seeders declared in other modules' providers are also discovered — this is
9
- * just a convenience to co-locate them.)
10
- */
11
- static forRoot(options?: {
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 {};