@velajs/testing 0.2.0 → 0.4.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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 (2026-07-04)
4
+
5
+ - `ComponentManager.init` call removed; provider overrides use the supported `Container.replaceProvider`; registers `DiscoveryService` mirroring bootstrap. Requires `@velajs/vela >=1.11.0`.
6
+
7
+
8
+ ## 0.2.1 (2026-05-14)
9
+
10
+ ### Fixes
11
+
12
+ - **`compile()` now replicates `bootstrap()`'s global token setup.** Registers `Container`, `ModuleRef`, and `REQUEST_CONTEXT` as global tokens (the last is the canonical seam for the per-request bag that `RouteManager.setRequestInstance` populates). Marks `APP_GUARD/PIPE/INTERCEPTOR/FILTER/MIDDLEWARE` as global so multi-provider pipeline registration via `bindAppProviders` resolves cleanly. Before this fix, guards / services that injected `REQUEST_CONTEXT` (the documented `@CurrentUser` lazy-decorator pattern) crashed at request time with "REQUEST_CONTEXT can only be resolved inside a request". New test pins the behavior end-to-end.
13
+ - **Overrides now win for controller-internal constructor injection.** Pre-registering an override at the root container's `__root__` bucket only beat framework-internal lookups (no `requestingModuleId`). Controller constructor injection passes the controller's module id, which finds the module's own registration before the root override and short-circuits. The builder now post-processes after `loader.load()` and overwrites the registration in every module bucket that already holds the token.
14
+
15
+ ### Breaking changes
16
+
17
+ - **`@velajs/vela` peer bumped to `>=1.6.0`.** Needs `REQUEST_CONTEXT` and `createLazyParamDecorator` re-exports (added in vela 1.6.0).
18
+
3
19
  ## 0.2.0 (2026-04-30)
4
20
 
5
21
  Bugs fixed, rebuilt on `@velajs/vela/internal`, no more `reflect-metadata` dep.
@@ -1,4 +1,4 @@
1
- import type { ModuleOptions, Token, Type } from '@velajs/vela';
1
+ import { type ModuleOptions, type Token, type Type } from '@velajs/vela';
2
2
  import { TestingModule } from './testing-module.js';
3
3
  export declare class OverrideBy {
4
4
  private readonly builder;
@@ -1,4 +1,5 @@
1
- import { ComponentManager, Container, MetadataRegistry, ModuleLoader, RouteManager, VelaApplication, bindAppProviders } from "@velajs/vela/internal";
1
+ import { DiscoveryService, REQUEST_CONTEXT, Scope } from "@velajs/vela";
2
+ import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_MIDDLEWARE, APP_PIPE, Container, MetadataRegistry, ModuleLoader, ModuleRef, RouteManager, VelaApplication, bindAppProviders } from "@velajs/vela/internal";
2
3
  import { TestingModule } from "./testing-module.js";
3
4
  export class OverrideBy {
4
5
  builder;
@@ -78,18 +79,75 @@ export class TestingModuleBuilder {
78
79
  exports: this.metadata.exports
79
80
  });
80
81
  const container = new Container();
82
+ // Replicate bootstrap()'s global token setup so request-pipeline tests
83
+ // can resolve REQUEST_CONTEXT, ModuleRef, and the APP_* sentinel tokens
84
+ // from any module scope. Without this, guards / decorators that inject
85
+ // REQUEST_CONTEXT through ExecutionContext fail with "no provider"
86
+ // when the request enters the pipeline. See vela/src/factory/bootstrap.ts.
81
87
  container.register({
82
88
  provide: Container,
83
89
  useValue: container
84
90
  });
85
- // Register overrides BEFORE module loading so ModuleLoader skips originals.
91
+ container.markGlobalToken(Container);
92
+ container.register({
93
+ provide: ModuleRef,
94
+ useFactory: (c)=>new ModuleRef(c),
95
+ inject: [
96
+ Container
97
+ ]
98
+ });
99
+ container.markGlobalToken(ModuleRef);
100
+ // Decorator-driven discovery — global so any provider can inject it, and so
101
+ // callOnApplicationBootstrap() reuses this instance instead of self-building
102
+ // one. Mirrors vela/src/factory/bootstrap.ts.
103
+ container.register({
104
+ provide: DiscoveryService,
105
+ useFactory: (c)=>new DiscoveryService(c),
106
+ inject: [
107
+ Container
108
+ ]
109
+ });
110
+ container.markGlobalToken(DiscoveryService);
111
+ for (const t of [
112
+ APP_GUARD,
113
+ APP_PIPE,
114
+ APP_INTERCEPTOR,
115
+ APP_FILTER,
116
+ APP_MIDDLEWARE
117
+ ]){
118
+ container.markGlobalToken(t);
119
+ }
120
+ // REQUEST_CONTEXT is seeded into each per-request child container by
121
+ // RouteManager via setRequestInstance. Registering with a throw-factory
122
+ // here ensures findRegistration succeeds (so the child's cached request
123
+ // instance is returned) while surfacing a clear error if the token is
124
+ // ever resolved outside the request path.
125
+ container.register({
126
+ provide: REQUEST_CONTEXT,
127
+ scope: Scope.REQUEST,
128
+ useFactory: ()=>{
129
+ throw new Error('REQUEST_CONTEXT can only be resolved inside a request — ' + 'it is seeded by RouteManager when the request enters the pipeline.');
130
+ }
131
+ });
132
+ container.markGlobalToken(REQUEST_CONTEXT);
133
+ // Pre-register at root so `moduleRef.get(token)` and framework-internal
134
+ // resolves (instantiate(guard, container) with no requestingModuleId) see
135
+ // the override immediately.
86
136
  for (const override of this.overrides){
87
137
  container.register(override.provider);
88
138
  }
89
139
  const routeManager = new RouteManager(container);
90
- ComponentManager.init(container);
91
140
  const loader = new ModuleLoader(container, routeManager);
92
141
  loader.load(TestRootModule);
142
+ // Force-apply overrides into every module bucket that already holds the
143
+ // token (plus root). Without this, controller constructor-injection (which
144
+ // passes requestingModuleId to findRegistration) finds the module's own
145
+ // registration first and never consults the root override. The default
146
+ // 'all-existing' buckets replace every non-root bucket holding the token
147
+ // and re-register at root — the supported form of the old private loop.
148
+ for (const override of this.overrides){
149
+ container.replaceProvider(override.provider);
150
+ }
93
151
  bindAppProviders(routeManager, container, loader);
94
152
  const app = new VelaApplication(container, routeManager);
95
153
  const instances = await loader.resolveAllInstances();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velajs/testing",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Testing utilities for Vela framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,12 +17,6 @@
17
17
  "LICENSE",
18
18
  "CHANGELOG.md"
19
19
  ],
20
- "scripts": {
21
- "build": "rm -rf dist && swc src -d dist --strip-leading-paths && tsc --emitDeclarationOnly",
22
- "test": "vitest run",
23
- "typecheck": "tsc --noEmit",
24
- "prepublishOnly": "pnpm run typecheck && pnpm test"
25
- },
26
20
  "sideEffects": false,
27
21
  "keywords": [
28
22
  "vela",
@@ -47,24 +41,22 @@
47
41
  "node": ">=20"
48
42
  },
49
43
  "peerDependencies": {
50
- "@velajs/vela": ">=1.1.0",
44
+ "@velajs/vela": ">=1.11.0",
51
45
  "hono": ">=4"
52
46
  },
53
47
  "devDependencies": {
54
- "@swc/cli": "^0.8.0",
55
- "@swc/core": "^1.15.11",
48
+ "@swc/cli": "^0.8.1",
49
+ "@swc/core": "^1.15.41",
56
50
  "@types/bun": "latest",
57
- "@velajs/vela": "^1.1.0",
58
- "hono": "^4",
59
- "typescript": "^5",
51
+ "@velajs/vela": "^1.12.0",
52
+ "hono": "^4.12.26",
53
+ "typescript": "^6.0.3",
60
54
  "unplugin-swc": "^1.5.9",
61
- "vitest": "^4.0.18"
55
+ "vitest": "^4.1.9"
62
56
  },
63
- "packageManager": "pnpm@10.20.0",
64
- "pnpm": {
65
- "onlyBuiltDependencies": [
66
- "@swc/core",
67
- "esbuild"
68
- ]
57
+ "scripts": {
58
+ "build": "rm -rf dist && swc src -d dist --strip-leading-paths && tsc --emitDeclarationOnly",
59
+ "test": "vitest run",
60
+ "typecheck": "tsc --noEmit"
69
61
  }
70
- }
62
+ }