@zudojs/runtime 0.1.0 → 1.1.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/LICENSE +21 -0
- package/README.md +127 -6
- package/dist/dependencyGraph/dependencyGraph.core.d.ts +11 -5
- package/dist/dependencyGraph/dependencyGraph.core.js +13 -12
- package/dist/dependencyGraph/dependencyGraph.type.d.ts +0 -7
- package/dist/dependencyGraph/index.d.ts +2 -2
- package/dist/dependencyGraph/index.js +1 -1
- package/dist/health/health.core.d.ts +12 -0
- package/dist/health/health.core.js +55 -0
- package/dist/health/index.d.ts +5 -0
- package/dist/health/index.js +5 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -1
- package/dist/lifecycle/index.d.ts +1 -1
- package/dist/lifecycle/lifecycle.core.d.ts +41 -10
- package/dist/lifecycle/lifecycle.core.js +238 -61
- package/dist/lifecycle/lifecycle.type.d.ts +48 -1
- package/dist/readiness/index.d.ts +1 -1
- package/dist/readiness/readiness.core.d.ts +36 -4
- package/dist/readiness/readiness.core.js +122 -6
- package/dist/readiness/readiness.type.d.ts +15 -1
- package/dist/registry/registry.core.d.ts +14 -1
- package/dist/registry/registry.core.js +41 -2
- package/dist/runtime/runtime.core.d.ts +75 -5
- package/dist/runtime/runtime.core.js +210 -43
- package/dist/runtimeContext/index.d.ts +2 -2
- package/dist/runtimeContext/index.js +1 -1
- package/dist/runtimeContext/runtimeContext.core.d.ts +13 -4
- package/dist/runtimeContext/runtimeContext.core.js +22 -11
- package/dist/runtimeContext/runtimeContext.type.d.ts +12 -13
- package/dist/runtimeError/runtimeError.base.js +1 -1
- package/dist/runtimeEvents/index.d.ts +2 -2
- package/dist/runtimeEvents/index.js +1 -1
- package/dist/runtimeEvents/runtimeEvents.core.d.ts +15 -1
- package/dist/runtimeEvents/runtimeEvents.core.js +26 -0
- package/dist/runtimeEvents/runtimeEvents.type.d.ts +19 -4
- package/dist/runtimeOptions/runtimeOptions.core.d.ts +5 -0
- package/dist/runtimeOptions/runtimeOptions.core.js +14 -1
- package/dist/runtimeOptions/runtimeOptions.type.d.ts +29 -1
- package/dist/runtimeOptions/runtimeOptions.type.js +6 -0
- package/dist/runtimeState/index.d.ts +1 -1
- package/dist/runtimeState/runtimeState.core.d.ts +4 -0
- package/dist/runtimeState/runtimeState.core.js +17 -4
- package/dist/runtimeState/runtimeState.type.d.ts +14 -17
- package/dist/shutdown/shutdown.core.d.ts +20 -1
- package/dist/shutdown/shutdown.core.js +55 -29
- package/dist/signalHandler/signalHandler.core.d.ts +53 -13
- package/dist/signalHandler/signalHandler.core.js +97 -27
- package/dist/startup/startup.core.d.ts +3 -2
- package/dist/startup/startup.core.js +52 -46
- package/dist/testRuntime/index.d.ts +6 -1
- package/dist/testRuntime/index.js +5 -1
- package/dist/testRuntime/testRuntime.core.d.ts +21 -2
- package/dist/testRuntime/testRuntime.core.js +23 -6
- package/package.json +33 -22
- package/dist/.tsbuildinfo +0 -1
- package/dist/dependencyGraph/dependencyGraph.core.d.ts.map +0 -1
- package/dist/dependencyGraph/dependencyGraph.core.js.map +0 -1
- package/dist/dependencyGraph/dependencyGraph.type.d.ts.map +0 -1
- package/dist/dependencyGraph/dependencyGraph.type.js.map +0 -1
- package/dist/dependencyGraph/index.d.ts.map +0 -1
- package/dist/dependencyGraph/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lifecycle/index.d.ts.map +0 -1
- package/dist/lifecycle/index.js.map +0 -1
- package/dist/lifecycle/lifecycle.core.d.ts.map +0 -1
- package/dist/lifecycle/lifecycle.core.js.map +0 -1
- package/dist/lifecycle/lifecycle.type.d.ts.map +0 -1
- package/dist/lifecycle/lifecycle.type.js.map +0 -1
- package/dist/readiness/index.d.ts.map +0 -1
- package/dist/readiness/index.js.map +0 -1
- package/dist/readiness/readiness.core.d.ts.map +0 -1
- package/dist/readiness/readiness.core.js.map +0 -1
- package/dist/readiness/readiness.type.d.ts.map +0 -1
- package/dist/readiness/readiness.type.js.map +0 -1
- package/dist/registry/index.d.ts.map +0 -1
- package/dist/registry/index.js.map +0 -1
- package/dist/registry/registry.core.d.ts.map +0 -1
- package/dist/registry/registry.core.js.map +0 -1
- package/dist/runtime/runtime.core.d.ts.map +0 -1
- package/dist/runtime/runtime.core.js.map +0 -1
- package/dist/runtimeContext/index.d.ts.map +0 -1
- package/dist/runtimeContext/index.js.map +0 -1
- package/dist/runtimeContext/runtimeContext.core.d.ts.map +0 -1
- package/dist/runtimeContext/runtimeContext.core.js.map +0 -1
- package/dist/runtimeContext/runtimeContext.factory.d.ts.map +0 -1
- package/dist/runtimeContext/runtimeContext.factory.js.map +0 -1
- package/dist/runtimeContext/runtimeContext.type.d.ts.map +0 -1
- package/dist/runtimeContext/runtimeContext.type.js.map +0 -1
- package/dist/runtimeError/index.d.ts.map +0 -1
- package/dist/runtimeError/index.js.map +0 -1
- package/dist/runtimeError/runtimeError.base.d.ts.map +0 -1
- package/dist/runtimeError/runtimeError.base.js.map +0 -1
- package/dist/runtimeEvents/index.d.ts.map +0 -1
- package/dist/runtimeEvents/index.js.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.core.d.ts.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.core.js.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.type.d.ts.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.type.js.map +0 -1
- package/dist/runtimeOptions/index.d.ts.map +0 -1
- package/dist/runtimeOptions/index.js.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.core.d.ts.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.core.js.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.type.d.ts.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.type.js.map +0 -1
- package/dist/runtimeState/index.d.ts.map +0 -1
- package/dist/runtimeState/index.js.map +0 -1
- package/dist/runtimeState/runtimeState.core.d.ts.map +0 -1
- package/dist/runtimeState/runtimeState.core.js.map +0 -1
- package/dist/runtimeState/runtimeState.type.d.ts.map +0 -1
- package/dist/runtimeState/runtimeState.type.js.map +0 -1
- package/dist/shutdown/index.d.ts.map +0 -1
- package/dist/shutdown/index.js.map +0 -1
- package/dist/shutdown/shutdown.core.d.ts.map +0 -1
- package/dist/shutdown/shutdown.core.js.map +0 -1
- package/dist/signalHandler/index.d.ts.map +0 -1
- package/dist/signalHandler/index.js.map +0 -1
- package/dist/signalHandler/signalHandler.core.d.ts.map +0 -1
- package/dist/signalHandler/signalHandler.core.js.map +0 -1
- package/dist/startup/index.d.ts.map +0 -1
- package/dist/startup/index.js.map +0 -1
- package/dist/startup/startup.core.d.ts.map +0 -1
- package/dist/startup/startup.core.js.map +0 -1
- package/dist/testRuntime/index.d.ts.map +0 -1
- package/dist/testRuntime/index.js.map +0 -1
- package/dist/testRuntime/testRuntime.core.d.ts.map +0 -1
- package/dist/testRuntime/testRuntime.core.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zudojs Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -10,24 +10,145 @@ npm install @zudojs/runtime
|
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
|
+
`createRuntime` takes the framework services the runtime orchestrates,
|
|
14
|
+
then the runtime's own options.
|
|
15
|
+
|
|
13
16
|
```typescript
|
|
14
17
|
import { createRuntime } from "@zudojs/runtime";
|
|
15
18
|
|
|
16
|
-
const runtime = createRuntime(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
const runtime = createRuntime(
|
|
20
|
+
{
|
|
21
|
+
modules: new Map([
|
|
22
|
+
["database", database],
|
|
23
|
+
["api", api],
|
|
24
|
+
]),
|
|
25
|
+
logger,
|
|
26
|
+
container,
|
|
27
|
+
eventBus,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
environment: "production",
|
|
31
|
+
applicationName: "my-app",
|
|
32
|
+
},
|
|
33
|
+
);
|
|
19
34
|
|
|
20
35
|
await runtime.start();
|
|
21
36
|
await runtime.stop();
|
|
22
37
|
```
|
|
23
38
|
|
|
39
|
+
Modules start in dependency order and stop in reverse.
|
|
40
|
+
|
|
41
|
+
## Readiness and health
|
|
42
|
+
|
|
43
|
+
Readiness checks are registered on the runtime and re-evaluated on demand.
|
|
44
|
+
A registered check starts out failing until it is first run, so registering
|
|
45
|
+
one on a running runtime moves it to `degraded` until it passes.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
runtime.registerReadinessCheck("database", () => database.isConnected());
|
|
49
|
+
|
|
50
|
+
await runtime.runReadinessChecks();
|
|
51
|
+
|
|
52
|
+
runtime.ready; // false while any check fails
|
|
53
|
+
runtime.health.state; // "healthy" | "degraded" | ...
|
|
54
|
+
runtime.readiness.checks.get("database"); // per-check result and duration
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`runtime.health` is derived from the lifecycle state and the readiness
|
|
58
|
+
checks: a running runtime is `healthy` when every check passes and
|
|
59
|
+
`degraded` when any check fails; every other lifecycle state maps onto
|
|
60
|
+
`starting`, `stopping`, `unhealthy` or `unknown`. A change emits
|
|
61
|
+
`runtime.health.changed` on the event bus.
|
|
62
|
+
|
|
63
|
+
`runtime.status` and `runtime.context` are read live, so `state`, `ready`,
|
|
64
|
+
`health`, `startedAt`, `stoppedAt`, `failedAt` and `error` always reflect
|
|
65
|
+
the runtime as it is now — including on the failure path, where
|
|
66
|
+
`context.error` names what went wrong.
|
|
67
|
+
|
|
68
|
+
By default a readiness check that does not settle within 5 seconds is
|
|
69
|
+
recorded as failed; pass `readinessCheckTimeout` to change that bound, or
|
|
70
|
+
`0` to remove it.
|
|
71
|
+
|
|
72
|
+
## Module context
|
|
73
|
+
|
|
74
|
+
Modules receive a `ModuleContext` giving them the framework services they
|
|
75
|
+
are allowed to reach. Configuration and the application context are
|
|
76
|
+
supplied through the runtime's dependencies:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const runtime = createRuntime(
|
|
80
|
+
{ modules, logger, container, eventBus, configuration, application },
|
|
81
|
+
options,
|
|
82
|
+
);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`configuration` backs `context.getConfiguration()`, `context.getConfig()`
|
|
86
|
+
and `context.requireConfig()`; it defaults to an empty manager loaded at
|
|
87
|
+
startup. `application` backs `context.application` — a module that reads
|
|
88
|
+
it when none was supplied gets a clear error rather than an empty object.
|
|
89
|
+
`context.hasModule()` and `context.getModuleContext()` resolve against the
|
|
90
|
+
registered modules, and a module keeps the same context across every
|
|
91
|
+
lifecycle phase.
|
|
92
|
+
|
|
93
|
+
## Runtime events
|
|
94
|
+
|
|
95
|
+
With `emitEvents` (the default), the runtime publishes on the event bus.
|
|
96
|
+
Subscribe with `bus.on(type, handler)`; the payload types are in
|
|
97
|
+
`RuntimeEventMap`.
|
|
98
|
+
|
|
99
|
+
| Event | Payload |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| `runtime.initializing`, `runtime.running`, `runtime.stopping`, `runtime.stopped` | `RuntimeEventPayload` |
|
|
102
|
+
| `runtime.failed` | `RuntimeFailureEventPayload` |
|
|
103
|
+
| `runtime.module.initializing` / `initialized` / `starting` / `started` / `stopping` / `stopped` / `failed` | `RuntimeModuleEventPayload` |
|
|
104
|
+
| `runtime.shutdown.drain`, `runtime.shutdown.complete` | `RuntimeEventPayload` |
|
|
105
|
+
| `runtime.health.changed` | `RuntimeHealthEventPayload` |
|
|
106
|
+
| `runtime.readiness.changed` | `RuntimeReadinessEventPayload` |
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
bus.on("runtime.module.failed", (event) => {
|
|
110
|
+
const { moduleId, moduleName, error, durationMs } = event.payload;
|
|
111
|
+
alert(`${moduleName} (${moduleId}) failed after ${durationMs}ms`, error);
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Every `runtime.module.*` event names the module it is about. A listener
|
|
116
|
+
that throws is logged and contained; it never fails the lifecycle phase
|
|
117
|
+
that produced the event.
|
|
118
|
+
|
|
119
|
+
## Options
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
createRuntime(dependencies, {
|
|
123
|
+
environment: "production", // required
|
|
124
|
+
applicationName: "my-app", // required
|
|
125
|
+
applicationVersion: "1.4.0",
|
|
126
|
+
runtimeId: "rt_custom", // generated when omitted
|
|
127
|
+
handleSignals: true, // SIGTERM/SIGINT trigger a graceful stop
|
|
128
|
+
handleFatalErrors: true, // uncaughtException/unhandledRejection
|
|
129
|
+
startupTimeout: 60_000,
|
|
130
|
+
shutdownTimeout: 30_000,
|
|
131
|
+
emitEvents: true,
|
|
132
|
+
trackReadiness: true,
|
|
133
|
+
trackHealth: true,
|
|
134
|
+
readinessCheckTimeout: 5_000, // 0 removes the bound
|
|
135
|
+
parallelInitialization: false, // initialize each depth group at once
|
|
136
|
+
metadata: { region: "eu-west-1" },
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`parallelInitialization` initializes modules that share a dependency depth
|
|
141
|
+
concurrently. They do not depend on one another by construction, but
|
|
142
|
+
enabling it surfaces any ordering a module assumed without declaring, so
|
|
143
|
+
it is opt-in.
|
|
144
|
+
|
|
24
145
|
## Features
|
|
25
146
|
|
|
26
|
-
-
|
|
147
|
+
- Module dependency ordering
|
|
27
148
|
- Graceful shutdown with rollback
|
|
28
149
|
- Signal handling (SIGINT, SIGTERM)
|
|
29
|
-
- Readiness and health
|
|
30
|
-
- Lifecycle hooks (
|
|
150
|
+
- Readiness checks and derived health
|
|
151
|
+
- Lifecycle hooks (onInitialize, onReady, onShutdown, onDestroy)
|
|
31
152
|
|
|
32
153
|
## Use Cases
|
|
33
154
|
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import type { DependencyGraph, DependencyResolutionResult
|
|
1
|
+
import type { DependencyGraph, DependencyResolutionResult } from "./dependencyGraph.type.js";
|
|
2
2
|
/**
|
|
3
3
|
* Builds a dependency graph from module IDs and their dependencies.
|
|
4
4
|
*/
|
|
5
5
|
export declare function buildDependencyGraph(modules: ReadonlyMap<string, readonly string[]>): DependencyGraph;
|
|
6
6
|
/**
|
|
7
7
|
* Resolves module dependencies into an initialization order.
|
|
8
|
+
*
|
|
9
|
+
* Missing dependencies are rejected before ordering. Previously an
|
|
10
|
+
* unregistered dependency contributed depth `0` and was silently
|
|
11
|
+
* dropped, so a typo in a module's `dependencies` degraded into an
|
|
12
|
+
* unordered start that failed later inside `onInitialize`.
|
|
8
13
|
*/
|
|
9
14
|
export declare function resolveDependencies(modules: ReadonlyMap<string, readonly string[]>): DependencyResolutionResult;
|
|
10
|
-
/**
|
|
11
|
-
* Returns parallel module groups for concurrent initialization.
|
|
12
|
-
*/
|
|
13
|
-
export declare function getParallelGroups(modules: ReadonlyMap<string, readonly string[]>): readonly ParallelModuleGroup[];
|
|
14
15
|
/**
|
|
15
16
|
* Validates that all module dependencies exist.
|
|
17
|
+
*
|
|
18
|
+
* @throws {RuntimeDependencyError} naming both the module and the
|
|
19
|
+
* dependency it declared. Reporting a missing dependency as a circular
|
|
20
|
+
* one, as this previously did, sends the reader looking for a cycle that
|
|
21
|
+
* does not exist.
|
|
16
22
|
*/
|
|
17
23
|
export declare function validateDependencies(modules: ReadonlyMap<string, readonly string[]>): void;
|
|
18
24
|
//# sourceMappingURL=dependencyGraph.core.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RuntimeCircularDependencyError } from "../runtimeError/runtimeError.base.js";
|
|
1
|
+
import { RuntimeCircularDependencyError, RuntimeDependencyError, } from "../runtimeError/runtimeError.base.js";
|
|
2
2
|
/**
|
|
3
3
|
* Builds a dependency graph from module IDs and their dependencies.
|
|
4
4
|
*/
|
|
@@ -76,8 +76,14 @@ export function buildDependencyGraph(modules) {
|
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
78
|
* Resolves module dependencies into an initialization order.
|
|
79
|
+
*
|
|
80
|
+
* Missing dependencies are rejected before ordering. Previously an
|
|
81
|
+
* unregistered dependency contributed depth `0` and was silently
|
|
82
|
+
* dropped, so a typo in a module's `dependencies` degraded into an
|
|
83
|
+
* unordered start that failed later inside `onInitialize`.
|
|
79
84
|
*/
|
|
80
85
|
export function resolveDependencies(modules) {
|
|
86
|
+
validateDependencies(modules);
|
|
81
87
|
const graph = buildDependencyGraph(modules);
|
|
82
88
|
if (graph.hasCircularDependency) {
|
|
83
89
|
throw new RuntimeCircularDependencyError(graph.circularDependencies[0] ?? []);
|
|
@@ -99,24 +105,19 @@ export function resolveDependencies(modules) {
|
|
|
99
105
|
circularDependencies: [],
|
|
100
106
|
});
|
|
101
107
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Returns parallel module groups for concurrent initialization.
|
|
104
|
-
*/
|
|
105
|
-
export function getParallelGroups(modules) {
|
|
106
|
-
const result = resolveDependencies(modules);
|
|
107
|
-
return result.parallelGroups.map((group, index) => Object.freeze({
|
|
108
|
-
modules: group,
|
|
109
|
-
depth: index,
|
|
110
|
-
}));
|
|
111
|
-
}
|
|
112
108
|
/**
|
|
113
109
|
* Validates that all module dependencies exist.
|
|
110
|
+
*
|
|
111
|
+
* @throws {RuntimeDependencyError} naming both the module and the
|
|
112
|
+
* dependency it declared. Reporting a missing dependency as a circular
|
|
113
|
+
* one, as this previously did, sends the reader looking for a cycle that
|
|
114
|
+
* does not exist.
|
|
114
115
|
*/
|
|
115
116
|
export function validateDependencies(modules) {
|
|
116
117
|
for (const [moduleId, deps] of modules) {
|
|
117
118
|
for (const depId of deps) {
|
|
118
119
|
if (!modules.has(depId)) {
|
|
119
|
-
throw new
|
|
120
|
+
throw new RuntimeDependencyError(moduleId, depId);
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
}
|
|
@@ -25,13 +25,6 @@ export interface DependencyResolutionResult {
|
|
|
25
25
|
readonly hasCircularDependency: boolean;
|
|
26
26
|
readonly circularDependencies: readonly (readonly string[])[];
|
|
27
27
|
}
|
|
28
|
-
/**
|
|
29
|
-
* A group of modules that can be initialized concurrently.
|
|
30
|
-
*/
|
|
31
|
-
export interface ParallelModuleGroup {
|
|
32
|
-
readonly modules: readonly string[];
|
|
33
|
-
readonly depth: number;
|
|
34
|
-
}
|
|
35
28
|
/**
|
|
36
29
|
* Error information for circular dependencies.
|
|
37
30
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module dependency graph and resolution.
|
|
3
3
|
*/
|
|
4
|
-
export { buildDependencyGraph, resolveDependencies,
|
|
5
|
-
export type { DependencyNode, DependencyGraph, DependencyResolutionResult,
|
|
4
|
+
export { buildDependencyGraph, resolveDependencies, validateDependencies, } from "./dependencyGraph.core.js";
|
|
5
|
+
export type { DependencyNode, DependencyGraph, DependencyResolutionResult, CircularDependencyInfo, } from "./dependencyGraph.type.js";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module dependency graph and resolution.
|
|
3
3
|
*/
|
|
4
|
-
export { buildDependencyGraph, resolveDependencies,
|
|
4
|
+
export { buildDependencyGraph, resolveDependencies, validateDependencies, } from "./dependencyGraph.core.js";
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RuntimeHealth, RuntimeState } from "../runtimeState/runtimeState.type.js";
|
|
2
|
+
import type { ReadinessTrackerState } from "../readiness/readiness.type.js";
|
|
3
|
+
/**
|
|
4
|
+
* Computes runtime health from the lifecycle state and readiness checks.
|
|
5
|
+
*
|
|
6
|
+
* A running runtime is `healthy` when every readiness check passes (a
|
|
7
|
+
* runtime with no checks registered counts as healthy) and `degraded`
|
|
8
|
+
* when at least one check is failing. Every other lifecycle state maps
|
|
9
|
+
* directly onto a health state.
|
|
10
|
+
*/
|
|
11
|
+
export declare function computeRuntimeHealth(state: RuntimeState, readiness: ReadinessTrackerState): RuntimeHealth;
|
|
12
|
+
//# sourceMappingURL=health.core.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps the runtime lifecycle state onto a health state, for the states
|
|
3
|
+
* where health is determined by the lifecycle alone.
|
|
4
|
+
*
|
|
5
|
+
* Returns `undefined` while the runtime is running, because health then
|
|
6
|
+
* depends on the readiness checks rather than on the state.
|
|
7
|
+
*/
|
|
8
|
+
function healthStateFor(state) {
|
|
9
|
+
switch (state) {
|
|
10
|
+
case "created":
|
|
11
|
+
case "stopped":
|
|
12
|
+
return "unknown";
|
|
13
|
+
case "initializing":
|
|
14
|
+
case "initialized":
|
|
15
|
+
case "starting":
|
|
16
|
+
return "starting";
|
|
17
|
+
case "stopping":
|
|
18
|
+
return "stopping";
|
|
19
|
+
case "failed":
|
|
20
|
+
return "unhealthy";
|
|
21
|
+
case "running":
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Converts readiness checks into health checks.
|
|
27
|
+
*/
|
|
28
|
+
function toHealthChecks(readiness) {
|
|
29
|
+
return Object.freeze([...readiness.checks.values()].map((check) => Object.freeze({
|
|
30
|
+
name: check.name,
|
|
31
|
+
healthy: check.ready,
|
|
32
|
+
durationMs: check.durationMs,
|
|
33
|
+
...(check.message !== undefined && { message: check.message }),
|
|
34
|
+
})));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Computes runtime health from the lifecycle state and readiness checks.
|
|
38
|
+
*
|
|
39
|
+
* A running runtime is `healthy` when every readiness check passes (a
|
|
40
|
+
* runtime with no checks registered counts as healthy) and `degraded`
|
|
41
|
+
* when at least one check is failing. Every other lifecycle state maps
|
|
42
|
+
* directly onto a health state.
|
|
43
|
+
*/
|
|
44
|
+
export function computeRuntimeHealth(state, readiness) {
|
|
45
|
+
const checks = toHealthChecks(readiness);
|
|
46
|
+
const lifecycleState = healthStateFor(state);
|
|
47
|
+
const healthState = lifecycleState ??
|
|
48
|
+
(checks.every((check) => check.healthy) ? "healthy" : "degraded");
|
|
49
|
+
return Object.freeze({
|
|
50
|
+
state: healthState,
|
|
51
|
+
checks,
|
|
52
|
+
timestamp: new Date(),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=health.core.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -18,11 +18,11 @@ export * from "./runtimeEvents/index.js";
|
|
|
18
18
|
export * from "./runtimeContext/index.js";
|
|
19
19
|
export * from "./dependencyGraph/index.js";
|
|
20
20
|
export * from "./readiness/index.js";
|
|
21
|
+
export * from "./health/index.js";
|
|
21
22
|
export * from "./lifecycle/index.js";
|
|
22
23
|
export * from "./startup/index.js";
|
|
23
24
|
export * from "./shutdown/index.js";
|
|
24
25
|
export * from "./signalHandler/index.js";
|
|
25
26
|
export * from "./runtimeError/index.js";
|
|
26
27
|
export * from "./registry/index.js";
|
|
27
|
-
export * from "./testRuntime/index.js";
|
|
28
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -17,11 +17,14 @@ export * from "./runtimeEvents/index.js";
|
|
|
17
17
|
export * from "./runtimeContext/index.js";
|
|
18
18
|
export * from "./dependencyGraph/index.js";
|
|
19
19
|
export * from "./readiness/index.js";
|
|
20
|
+
export * from "./health/index.js";
|
|
20
21
|
export * from "./lifecycle/index.js";
|
|
21
22
|
export * from "./startup/index.js";
|
|
22
23
|
export * from "./shutdown/index.js";
|
|
23
24
|
export * from "./signalHandler/index.js";
|
|
24
25
|
export * from "./runtimeError/index.js";
|
|
25
26
|
export * from "./registry/index.js";
|
|
26
|
-
|
|
27
|
+
// `testRuntime` is intentionally NOT exported from the package root: it
|
|
28
|
+
// is a testing helper, and re-exporting it here put a test-only module
|
|
29
|
+
// on the main entry point. Import it from "@zudojs/runtime/testing".
|
|
27
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Module lifecycle management.
|
|
3
3
|
*/
|
|
4
4
|
export { LifecycleManager } from "./lifecycle.core.js";
|
|
5
|
-
export type { LifecyclePhase, LifecycleResult, LifecycleFailure, LifecycleContext, ManagedModule, LifecycleManagerOptions, } from "./lifecycle.type.js";
|
|
5
|
+
export type { LifecyclePhase, LifecycleResult, LifecycleFailure, LifecycleContext, ManagedModule, LifecycleManagerOptions, ModuleContextServices, ModuleEventListener, } from "./lifecycle.type.js";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,24 +1,41 @@
|
|
|
1
1
|
import type { Logger } from "@zudojs/logger";
|
|
2
|
-
import type { Container } from "@zudojs/container";
|
|
3
2
|
import type { Module } from "@zudojs/core";
|
|
4
|
-
import type { LifecycleResult, LifecycleManagerOptions } from "./lifecycle.type.js";
|
|
3
|
+
import type { LifecycleResult, LifecycleFailure, LifecycleManagerOptions, ModuleContextServices } from "./lifecycle.type.js";
|
|
5
4
|
/**
|
|
6
5
|
* Manages the lifecycle of runtime modules.
|
|
7
6
|
*/
|
|
8
7
|
export declare class LifecycleManager {
|
|
9
8
|
private readonly modules;
|
|
10
9
|
private readonly logger;
|
|
11
|
-
private readonly container;
|
|
12
|
-
private readonly runtimeId;
|
|
13
|
-
private readonly environment;
|
|
14
10
|
private readonly options;
|
|
15
|
-
private readonly
|
|
16
|
-
private readonly
|
|
17
|
-
|
|
11
|
+
private readonly onModuleEvent;
|
|
12
|
+
private readonly runtimeId;
|
|
13
|
+
private initializedModules;
|
|
14
|
+
private startedModules;
|
|
15
|
+
private readonly configuration;
|
|
16
|
+
private readonly application;
|
|
17
|
+
private readonly contexts;
|
|
18
|
+
constructor(modules: ReadonlyMap<string, Module>, logger: Logger, options?: LifecycleManagerOptions, services?: ModuleContextServices);
|
|
19
|
+
/**
|
|
20
|
+
* Publishes a per-module lifecycle event.
|
|
21
|
+
*
|
|
22
|
+
* A throwing listener must not fail the phase that produced the event,
|
|
23
|
+
* so delivery failures are contained here.
|
|
24
|
+
*/
|
|
25
|
+
private emitModuleEvent;
|
|
26
|
+
/**
|
|
27
|
+
* Loads the configuration manager once, before modules are initialized,
|
|
28
|
+
* so that `context.getConfiguration()` is usable from the first hook.
|
|
29
|
+
*/
|
|
30
|
+
private ensureConfigurationReady;
|
|
18
31
|
/**
|
|
19
32
|
* Initializes all modules in dependency order.
|
|
20
33
|
*/
|
|
21
34
|
initialize(): Promise<LifecycleResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Initializes a single module, converting a throw into a failure.
|
|
37
|
+
*/
|
|
38
|
+
private initializeModule;
|
|
22
39
|
/**
|
|
23
40
|
* Starts all modules in dependency order.
|
|
24
41
|
*/
|
|
@@ -32,9 +49,15 @@ export declare class LifecycleManager {
|
|
|
32
49
|
*/
|
|
33
50
|
destroy(): Promise<LifecycleResult>;
|
|
34
51
|
/**
|
|
35
|
-
* Rolls back
|
|
52
|
+
* Rolls back a failed startup.
|
|
53
|
+
*
|
|
54
|
+
* Started modules are shut down, and every module that reached
|
|
55
|
+
* `onInitialize` is then destroyed — including those that never
|
|
56
|
+
* started because an earlier module failed. Rolling back only the
|
|
57
|
+
* started ones leaves everything they had already acquired behind with
|
|
58
|
+
* no route to release it.
|
|
36
59
|
*/
|
|
37
|
-
rollback(): Promise<
|
|
60
|
+
rollback(): Promise<readonly LifecycleFailure[]>;
|
|
38
61
|
/**
|
|
39
62
|
* Creates a module context for lifecycle hooks.
|
|
40
63
|
*/
|
|
@@ -42,6 +65,14 @@ export declare class LifecycleManager {
|
|
|
42
65
|
/**
|
|
43
66
|
* Builds a dependency graph from registered modules.
|
|
44
67
|
*/
|
|
68
|
+
/**
|
|
69
|
+
* Modules that reached `onInitialize`, in initialization order.
|
|
70
|
+
*/
|
|
71
|
+
getInitializedModules(): readonly string[];
|
|
72
|
+
/**
|
|
73
|
+
* Modules that reached `onReady`, in start order.
|
|
74
|
+
*/
|
|
75
|
+
getStartedModules(): readonly string[];
|
|
45
76
|
private buildModuleDependencyGraph;
|
|
46
77
|
}
|
|
47
78
|
//# sourceMappingURL=lifecycle.core.d.ts.map
|