@btravstack/testing 0.13.0 → 0.15.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/README.md CHANGED
@@ -92,6 +92,14 @@ answers the very instances the running graph holds once it is built — after
92
92
  provides it where a starter would; `unit` is a module every submitted unit
93
93
  forks, with no seed, before its work runs — and what that module needs joins
94
94
  `module`'s own, so `start` names it instead of the first `submit()` failing.
95
+ - **`overridden(module, [providers])`** — substitute named providers into your
96
+ **real** composition root, rather than maintaining a parallel test root
97
+ beside it. It replaces one **provider**, never a subsystem: the replaced
98
+ provider's siblings still construct, so swapping a whole adapter stack is
99
+ still a different module composed in its place. An override for a port the
100
+ tree stopped providing is a `WiringDefect` ("nothing to override"), which is
101
+ what keeps a test root from drifting silently away from the real one — the
102
+ drift that four hand-maintained parallel roots had already produced here.
95
103
  - **`createFakeClock(start?)`** — a `Clock` for `StartOptions.clock` whose
96
104
  time moves only on `advance(ms)`.
97
105
 
package/dist/index.cjs CHANGED
@@ -21,8 +21,9 @@ let _btravstack_di = require("@btravstack/di");
21
21
  * ```
22
22
  *
23
23
  * The defaults are a test's: `signals: false` always (process-wide handlers
24
- * would fight across a file), `probes: false`, `preDrainDelayMs: 0` and a silent
25
- * `onEvent` — each overridable by `defaults` and again per call.
24
+ * would fight across a file), `probes: false`, `preDrainDelayMs: 0`, a
25
+ * `stopTimeoutMs` far out of reach and a silent `onEvent` — each overridable by
26
+ * `defaults` and again per call.
26
27
  *
27
28
  * Teardown is `stop()`, then `exited` is examined: a **`Defect`** fails the test
28
29
  * even when the test never looked at `exited`, while a modeled `Err` passes
@@ -33,6 +34,7 @@ const bootFixture = (defaults = {}) => async ({}, use) => {
33
34
  const boot = ((module, options = {}) => {
34
35
  const app = (0, _btravstack_core.start)(module, {
35
36
  preDrainDelayMs: 0,
37
+ stopTimeoutMs: 6e5,
36
38
  onEvent: () => {},
37
39
  probes: false,
38
40
  ...defaults,
package/dist/index.d.cts CHANGED
@@ -27,14 +27,15 @@ type BootDefaults = Omit<StartOptions, "signals">;
27
27
  * ```
28
28
  *
29
29
  * The defaults are a test's: `signals: false` always (process-wide handlers
30
- * would fight across a file), `probes: false`, `preDrainDelayMs: 0` and a silent
31
- * `onEvent` — each overridable by `defaults` and again per call.
30
+ * would fight across a file), `probes: false`, `preDrainDelayMs: 0`, a
31
+ * `stopTimeoutMs` far out of reach and a silent `onEvent` — each overridable by
32
+ * `defaults` and again per call.
32
33
  *
33
34
  * Teardown is `stop()`, then `exited` is examined: a **`Defect`** fails the test
34
35
  * even when the test never looked at `exited`, while a modeled `Err` passes
35
36
  * through, since a startup failure is an outcome a test may be asserting.
36
37
  */
37
- declare const bootFixture: (defaults?: BootDefaults) => ({}: object, use: (boot: Boot) => Promise<void>) => Promise<void>;
38
+ export declare const bootFixture: (defaults?: BootDefaults) => ({}: object, use: (boot: Boot) => Promise<void>) => Promise<void>;
38
39
  //#endregion
39
40
  //#region src/fake-clock.d.ts
40
41
  type FakeClock = Clock & {
@@ -63,7 +64,7 @@ type FakeClock = Clock & {
63
64
  * await clock.advance(20_000); // the drain deadline
64
65
  * ```
65
66
  */
66
- declare const createFakeClock: (start?: number) => FakeClock;
67
+ export declare const createFakeClock: (start?: number) => FakeClock;
67
68
  //#endregion
68
69
  //#region src/overridden.d.ts
69
70
  /** One override's error channel, unioned across the tuple by `overridden`. */
@@ -91,7 +92,7 @@ type AnyProviderFor = Provider<never, unknown, unknown>;
91
92
  * root to re-export internals to be overridable. They are checked at build
92
93
  * instead, by `plan`'s missing-provider defect.
93
94
  */
94
- declare const overridden: <X, E, N, const O extends readonly AnyProviderFor[]>(module: Module<X, E, N>, overrides: O) => Module<X, E | ErrorsOf<O>, N>;
95
+ export declare const overridden: <X, E, N, const O extends readonly AnyProviderFor[]>(module: Module<X, E, N>, overrides: O) => Module<X, E | ErrorsOf<O>, N>;
95
96
  //#endregion
96
97
  //#region src/tapped.d.ts
97
98
  /** The services behind `ports`, in order — what `tapped(...).services()` answers once the graph is built. */
@@ -122,7 +123,7 @@ type ServicesOf<P extends readonly AnyPort[]> = { readonly [K in keyof P]: Servi
122
123
  type TapGate<P extends readonly AnyPort[], X> = [Exclude<InstanceType<P[number]>, X>] extends [never] ? unknown : {
123
124
  readonly "NOT EXPORTED — tap only what the module exports": Exclude<InstanceType<P[number]>, X>;
124
125
  };
125
- declare const tapped: <X, E, N, const P extends readonly AnyPort[]>(module: Module<X, E, N>, ports: P & TapGate<P, X>) => {
126
+ export declare const tapped: <X, E, N, const P extends readonly AnyPort[]>(module: Module<X, E, N>, ports: P & TapGate<P, X>) => {
126
127
  readonly module: Module<X, E, N>;
127
128
  readonly services: () => ServicesOf<P>;
128
129
  };
@@ -141,7 +142,7 @@ type TestRuntimeInfo = {
141
142
  readonly name: string;
142
143
  };
143
144
  /** The in-memory runtime's port: what `TestRuntime.module` provides, and what a test composition exports. */
144
- declare class TestRuntimePort extends RuntimePort<Runtime<never, TestRuntimeInfo>> {}
145
+ export declare class TestRuntimePort extends RuntimePort<Runtime<never, TestRuntimeInfo>> {}
145
146
  /**
146
147
  * A module `options.unit` may bind, as the upper bound `testRuntime`
147
148
  * constrains its own `Unit` type parameter to. `Module`'s `_exports` channel is
@@ -191,6 +192,6 @@ type TestRuntime<Unit extends AnyUnitModule | undefined = undefined> = Runtime<n
191
192
  /** The `RuntimeHost` the kernel last called `start` with. **Throws** if the runtime was never started — the same misuse guard as `serving()`. */
192
193
  readonly host: () => RuntimeHost<never>;
193
194
  };
194
- declare const testRuntime: <Unit extends AnyUnitModule | undefined = undefined>(name?: string, options?: TestRuntimeOptions<Unit>) => TestRuntime<Unit>;
195
+ export declare const testRuntime: <Unit extends AnyUnitModule | undefined = undefined>(name?: string, options?: TestRuntimeOptions<Unit>) => TestRuntime<Unit>;
195
196
  //#endregion
196
- export { type Boot, type BootDefaults, type FakeClock, type ServicesOf, type SubmittedUnit, type TestRuntime, type TestRuntimeInfo, type TestRuntimeOptions, TestRuntimePort, bootFixture, createFakeClock, overridden, tapped, testRuntime };
197
+ export type { Boot, BootDefaults, FakeClock, ServicesOf, SubmittedUnit, TestRuntime, TestRuntimeInfo, TestRuntimeOptions };
package/dist/index.d.mts CHANGED
@@ -27,14 +27,15 @@ type BootDefaults = Omit<StartOptions, "signals">;
27
27
  * ```
28
28
  *
29
29
  * The defaults are a test's: `signals: false` always (process-wide handlers
30
- * would fight across a file), `probes: false`, `preDrainDelayMs: 0` and a silent
31
- * `onEvent` — each overridable by `defaults` and again per call.
30
+ * would fight across a file), `probes: false`, `preDrainDelayMs: 0`, a
31
+ * `stopTimeoutMs` far out of reach and a silent `onEvent` — each overridable by
32
+ * `defaults` and again per call.
32
33
  *
33
34
  * Teardown is `stop()`, then `exited` is examined: a **`Defect`** fails the test
34
35
  * even when the test never looked at `exited`, while a modeled `Err` passes
35
36
  * through, since a startup failure is an outcome a test may be asserting.
36
37
  */
37
- declare const bootFixture: (defaults?: BootDefaults) => ({}: object, use: (boot: Boot) => Promise<void>) => Promise<void>;
38
+ export declare const bootFixture: (defaults?: BootDefaults) => ({}: object, use: (boot: Boot) => Promise<void>) => Promise<void>;
38
39
  //#endregion
39
40
  //#region src/fake-clock.d.ts
40
41
  type FakeClock = Clock & {
@@ -63,7 +64,7 @@ type FakeClock = Clock & {
63
64
  * await clock.advance(20_000); // the drain deadline
64
65
  * ```
65
66
  */
66
- declare const createFakeClock: (start?: number) => FakeClock;
67
+ export declare const createFakeClock: (start?: number) => FakeClock;
67
68
  //#endregion
68
69
  //#region src/overridden.d.ts
69
70
  /** One override's error channel, unioned across the tuple by `overridden`. */
@@ -91,7 +92,7 @@ type AnyProviderFor = Provider<never, unknown, unknown>;
91
92
  * root to re-export internals to be overridable. They are checked at build
92
93
  * instead, by `plan`'s missing-provider defect.
93
94
  */
94
- declare const overridden: <X, E, N, const O extends readonly AnyProviderFor[]>(module: Module<X, E, N>, overrides: O) => Module<X, E | ErrorsOf<O>, N>;
95
+ export declare const overridden: <X, E, N, const O extends readonly AnyProviderFor[]>(module: Module<X, E, N>, overrides: O) => Module<X, E | ErrorsOf<O>, N>;
95
96
  //#endregion
96
97
  //#region src/tapped.d.ts
97
98
  /** The services behind `ports`, in order — what `tapped(...).services()` answers once the graph is built. */
@@ -122,7 +123,7 @@ type ServicesOf<P extends readonly AnyPort[]> = { readonly [K in keyof P]: Servi
122
123
  type TapGate<P extends readonly AnyPort[], X> = [Exclude<InstanceType<P[number]>, X>] extends [never] ? unknown : {
123
124
  readonly "NOT EXPORTED — tap only what the module exports": Exclude<InstanceType<P[number]>, X>;
124
125
  };
125
- declare const tapped: <X, E, N, const P extends readonly AnyPort[]>(module: Module<X, E, N>, ports: P & TapGate<P, X>) => {
126
+ export declare const tapped: <X, E, N, const P extends readonly AnyPort[]>(module: Module<X, E, N>, ports: P & TapGate<P, X>) => {
126
127
  readonly module: Module<X, E, N>;
127
128
  readonly services: () => ServicesOf<P>;
128
129
  };
@@ -141,7 +142,7 @@ type TestRuntimeInfo = {
141
142
  readonly name: string;
142
143
  };
143
144
  /** The in-memory runtime's port: what `TestRuntime.module` provides, and what a test composition exports. */
144
- declare class TestRuntimePort extends RuntimePort<Runtime<never, TestRuntimeInfo>> {}
145
+ export declare class TestRuntimePort extends RuntimePort<Runtime<never, TestRuntimeInfo>> {}
145
146
  /**
146
147
  * A module `options.unit` may bind, as the upper bound `testRuntime`
147
148
  * constrains its own `Unit` type parameter to. `Module`'s `_exports` channel is
@@ -191,6 +192,6 @@ type TestRuntime<Unit extends AnyUnitModule | undefined = undefined> = Runtime<n
191
192
  /** The `RuntimeHost` the kernel last called `start` with. **Throws** if the runtime was never started — the same misuse guard as `serving()`. */
192
193
  readonly host: () => RuntimeHost<never>;
193
194
  };
194
- declare const testRuntime: <Unit extends AnyUnitModule | undefined = undefined>(name?: string, options?: TestRuntimeOptions<Unit>) => TestRuntime<Unit>;
195
+ export declare const testRuntime: <Unit extends AnyUnitModule | undefined = undefined>(name?: string, options?: TestRuntimeOptions<Unit>) => TestRuntime<Unit>;
195
196
  //#endregion
196
- export { type Boot, type BootDefaults, type FakeClock, type ServicesOf, type SubmittedUnit, type TestRuntime, type TestRuntimeInfo, type TestRuntimeOptions, TestRuntimePort, bootFixture, createFakeClock, overridden, tapped, testRuntime };
197
+ export type { Boot, BootDefaults, FakeClock, ServicesOf, SubmittedUnit, TestRuntime, TestRuntimeInfo, TestRuntimeOptions };
package/dist/index.mjs CHANGED
@@ -20,8 +20,9 @@ import { Module, Port, Provider, overrideProvider } from "@btravstack/di";
20
20
  * ```
21
21
  *
22
22
  * The defaults are a test's: `signals: false` always (process-wide handlers
23
- * would fight across a file), `probes: false`, `preDrainDelayMs: 0` and a silent
24
- * `onEvent` — each overridable by `defaults` and again per call.
23
+ * would fight across a file), `probes: false`, `preDrainDelayMs: 0`, a
24
+ * `stopTimeoutMs` far out of reach and a silent `onEvent` — each overridable by
25
+ * `defaults` and again per call.
25
26
  *
26
27
  * Teardown is `stop()`, then `exited` is examined: a **`Defect`** fails the test
27
28
  * even when the test never looked at `exited`, while a modeled `Err` passes
@@ -32,6 +33,7 @@ const bootFixture = (defaults = {}) => async ({}, use) => {
32
33
  const boot = ((module, options = {}) => {
33
34
  const app = start(module, {
34
35
  preDrainDelayMs: 0,
36
+ stopTimeoutMs: 6e5,
35
37
  onEvent: () => {},
36
38
  probes: false,
37
39
  ...defaults,
package/dist/jwt.d.cts CHANGED
@@ -1,19 +1,19 @@
1
1
  import { AsyncResult } from "unthrown";
2
2
  import { JWK, JWTPayload } from "jose";
3
3
  //#region src/jwt.d.ts
4
- type LocalIssuerOptions = {
4
+ export type LocalIssuerOptions = {
5
5
  readonly issuer: string;
6
6
  readonly audience: string;
7
7
  /** Asymmetric only, the same list `jwtAuthenticator` accepts; default `"RS256"`. */
8
8
  readonly algorithm?: "RS256" | "RS384" | "RS512" | "ES256" | "ES384";
9
9
  };
10
- type SignOptions = {
10
+ export type SignOptions = {
11
11
  readonly issuer?: string;
12
12
  readonly audience?: string;
13
13
  /** `"5m"` by default; `false` mints a token with no `exp` at all. */
14
14
  readonly expiresIn?: string | false;
15
15
  };
16
- type LocalIssuer = {
16
+ export type LocalIssuer = {
17
17
  /** `http://127.0.0.1:<port>/jwks.json` — served on ANY path, so a caller need not match it exactly. */
18
18
  readonly jwks: string;
19
19
  /** The public key as served, with `kid`/`alg`/`use` already set. */
@@ -31,6 +31,5 @@ type LocalIssuer = {
31
31
  * listener answering the JWKS on any path, and `sign` closing over the
32
32
  * private key. `close()` stops the listener; nothing else needs tearing down.
33
33
  */
34
- declare const localIssuer: (options: LocalIssuerOptions) => AsyncResult<LocalIssuer, never>;
35
- //#endregion
36
- export { LocalIssuer, LocalIssuerOptions, SignOptions, localIssuer };
34
+ export declare const localIssuer: (options: LocalIssuerOptions) => AsyncResult<LocalIssuer, never>;
35
+ //#endregion
package/dist/jwt.d.mts CHANGED
@@ -1,19 +1,19 @@
1
1
  import { AsyncResult } from "unthrown";
2
2
  import { JWK, JWTPayload } from "jose";
3
3
  //#region src/jwt.d.ts
4
- type LocalIssuerOptions = {
4
+ export type LocalIssuerOptions = {
5
5
  readonly issuer: string;
6
6
  readonly audience: string;
7
7
  /** Asymmetric only, the same list `jwtAuthenticator` accepts; default `"RS256"`. */
8
8
  readonly algorithm?: "RS256" | "RS384" | "RS512" | "ES256" | "ES384";
9
9
  };
10
- type SignOptions = {
10
+ export type SignOptions = {
11
11
  readonly issuer?: string;
12
12
  readonly audience?: string;
13
13
  /** `"5m"` by default; `false` mints a token with no `exp` at all. */
14
14
  readonly expiresIn?: string | false;
15
15
  };
16
- type LocalIssuer = {
16
+ export type LocalIssuer = {
17
17
  /** `http://127.0.0.1:<port>/jwks.json` — served on ANY path, so a caller need not match it exactly. */
18
18
  readonly jwks: string;
19
19
  /** The public key as served, with `kid`/`alg`/`use` already set. */
@@ -31,6 +31,5 @@ type LocalIssuer = {
31
31
  * listener answering the JWKS on any path, and `sign` closing over the
32
32
  * private key. `close()` stops the listener; nothing else needs tearing down.
33
33
  */
34
- declare const localIssuer: (options: LocalIssuerOptions) => AsyncResult<LocalIssuer, never>;
35
- //#endregion
36
- export { LocalIssuer, LocalIssuerOptions, SignOptions, localIssuer };
34
+ export declare const localIssuer: (options: LocalIssuerOptions) => AsyncResult<LocalIssuer, never>;
35
+ //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/testing",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "Test the applications @btravstack/core boots: an in-memory runtime, a fake clock, a boot fixture that stops what it started, and a tap into a running graph",
5
5
  "keywords": [
6
6
  "dependency-injection",
@@ -54,25 +54,25 @@
54
54
  }
55
55
  },
56
56
  "devDependencies": {
57
+ "@btravstack/config": "0.15.0",
58
+ "@btravstack/core": "0.15.0",
59
+ "@btravstack/di": "0.15.0",
57
60
  "@btravstack/tsconfig": "0.4.0",
58
- "@types/node": "26.4.0",
59
- "@unthrown/vitest": "5.7.0",
61
+ "@types/node": "26.4.1",
62
+ "@unthrown/vitest": "5.8.0",
60
63
  "@vitest/coverage-v8": "4.1.11",
61
- "jose": "6.2.10",
62
- "tsdown": "0.22.14",
64
+ "jose": "6.2.12",
65
+ "tsdown": "0.23.0",
63
66
  "typescript": "7.0.2",
64
- "unthrown": "5.7.0",
65
- "vitest": "4.1.11",
66
- "@btravstack/config": "0.13.0",
67
- "@btravstack/core": "0.13.0",
68
- "@btravstack/di": "0.13.0"
67
+ "unthrown": "5.8.0",
68
+ "vitest": "4.1.11"
69
69
  },
70
70
  "peerDependencies": {
71
+ "@btravstack/config": "^0.15.0",
72
+ "@btravstack/core": "^0.15.0",
73
+ "@btravstack/di": "^0.15.0",
71
74
  "jose": "^6",
72
- "unthrown": "^5.0.0",
73
- "@btravstack/config": "^0.13.0",
74
- "@btravstack/core": "^0.13.0",
75
- "@btravstack/di": "^0.13.0"
75
+ "unthrown": "^5.0.0"
76
76
  },
77
77
  "peerDependenciesMeta": {
78
78
  "jose": {
@@ -86,7 +86,6 @@
86
86
  "build": "tsdown src/index.ts src/jwt.ts --format cjs,esm --dts --clean",
87
87
  "dev": "tsdown src/index.ts src/jwt.ts --format cjs,esm --dts --watch",
88
88
  "test": "vitest run --coverage",
89
- "test:types": "tsc --noEmit -p tsconfig.test-d.json",
90
89
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test-d.json"
91
90
  }
92
91
  }