@zudojs/runtime 1.3.3 → 1.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/README.md +15 -2
- package/dist/dependencyGraph/dependencyGraph.core.d.ts +0 -1
- package/dist/dependencyGraph/dependencyGraph.core.js +0 -1
- package/dist/dependencyGraph/dependencyGraph.type.d.ts +0 -1
- package/dist/dependencyGraph/dependencyGraph.type.js +0 -1
- package/dist/dependencyGraph/index.d.ts +0 -1
- package/dist/dependencyGraph/index.js +0 -1
- package/dist/health/health.core.d.ts +0 -1
- package/dist/health/health.core.js +0 -1
- package/dist/health/index.d.ts +0 -1
- package/dist/health/index.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lifecycle/index.d.ts +0 -1
- package/dist/lifecycle/index.js +0 -1
- package/dist/lifecycle/lifecycle.cancellation.d.ts +0 -1
- package/dist/lifecycle/lifecycle.cancellation.js +0 -1
- package/dist/lifecycle/lifecycle.core.d.ts +0 -1
- package/dist/lifecycle/lifecycle.core.js +0 -1
- package/dist/lifecycle/lifecycle.type.d.ts +0 -1
- package/dist/lifecycle/lifecycle.type.js +0 -1
- package/dist/readiness/index.d.ts +1 -2
- package/dist/readiness/index.js +0 -1
- package/dist/readiness/readiness.check.d.ts +26 -0
- package/dist/readiness/readiness.check.js +70 -0
- package/dist/readiness/readiness.core.d.ts +20 -15
- package/dist/readiness/readiness.core.js +54 -85
- package/dist/readiness/readiness.type.d.ts +30 -5
- package/dist/readiness/readiness.type.js +0 -1
- package/dist/registry/index.d.ts +0 -1
- package/dist/registry/index.js +0 -1
- package/dist/registry/registry.core.d.ts +0 -1
- package/dist/registry/registry.core.js +0 -1
- package/dist/runtime/runtime.core.d.ts +6 -5
- package/dist/runtime/runtime.core.js +2 -3
- package/dist/runtimeContext/index.d.ts +0 -1
- package/dist/runtimeContext/index.js +0 -1
- package/dist/runtimeContext/runtimeContext.core.d.ts +0 -1
- package/dist/runtimeContext/runtimeContext.core.js +0 -1
- package/dist/runtimeContext/runtimeContext.factory.d.ts +0 -1
- package/dist/runtimeContext/runtimeContext.factory.js +0 -1
- package/dist/runtimeContext/runtimeContext.type.d.ts +0 -1
- package/dist/runtimeContext/runtimeContext.type.js +0 -1
- package/dist/runtimeError/index.d.ts +0 -1
- package/dist/runtimeError/index.js +0 -1
- package/dist/runtimeError/runtimeError.base.d.ts +0 -1
- package/dist/runtimeError/runtimeError.base.js +0 -1
- package/dist/runtimeEvents/index.d.ts +0 -1
- package/dist/runtimeEvents/index.js +0 -1
- package/dist/runtimeEvents/runtimeEvents.core.d.ts +0 -1
- package/dist/runtimeEvents/runtimeEvents.core.js +0 -1
- package/dist/runtimeEvents/runtimeEvents.type.d.ts +0 -1
- package/dist/runtimeEvents/runtimeEvents.type.js +0 -1
- package/dist/runtimeOptions/index.d.ts +0 -1
- package/dist/runtimeOptions/index.js +0 -1
- package/dist/runtimeOptions/runtimeOptions.core.d.ts +0 -1
- package/dist/runtimeOptions/runtimeOptions.core.js +0 -1
- package/dist/runtimeOptions/runtimeOptions.type.d.ts +0 -1
- package/dist/runtimeOptions/runtimeOptions.type.js +0 -1
- package/dist/runtimeState/index.d.ts +0 -1
- package/dist/runtimeState/index.js +0 -1
- package/dist/runtimeState/runtimeState.core.d.ts +0 -1
- package/dist/runtimeState/runtimeState.core.js +0 -1
- package/dist/runtimeState/runtimeState.type.d.ts +0 -1
- package/dist/runtimeState/runtimeState.type.js +0 -1
- package/dist/shutdown/index.d.ts +0 -1
- package/dist/shutdown/index.js +0 -1
- package/dist/shutdown/shutdown.container.d.ts +0 -1
- package/dist/shutdown/shutdown.container.js +0 -1
- package/dist/shutdown/shutdown.core.d.ts +0 -1
- package/dist/shutdown/shutdown.core.js +5 -2
- package/dist/signalHandler/index.d.ts +0 -1
- package/dist/signalHandler/index.js +0 -1
- package/dist/signalHandler/signalHandler.core.d.ts +0 -1
- package/dist/signalHandler/signalHandler.core.js +0 -1
- package/dist/signalHandler/signalHandler.keepAlive.d.ts +0 -1
- package/dist/signalHandler/signalHandler.keepAlive.js +0 -1
- package/dist/startup/index.d.ts +0 -1
- package/dist/startup/index.js +0 -1
- package/dist/startup/startup.core.d.ts +0 -1
- package/dist/startup/startup.core.js +0 -1
- package/dist/testRuntime/index.d.ts +0 -1
- package/dist/testRuntime/index.js +0 -1
- package/dist/testRuntime/testRuntime.core.d.ts +0 -1
- package/dist/testRuntime/testRuntime.core.js +0 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -162,14 +162,27 @@ one on a running runtime moves it to `degraded` until it passes.
|
|
|
162
162
|
|
|
163
163
|
```typescript
|
|
164
164
|
runtime.registerReadinessCheck("database", () => database.isConnected());
|
|
165
|
+
runtime.registerReadinessCheck("cache", () => cache.isWarm(), { critical: false });
|
|
165
166
|
|
|
166
167
|
await runtime.runReadinessChecks();
|
|
167
168
|
|
|
168
|
-
runtime.ready; // false while any check fails
|
|
169
|
+
runtime.ready; // false while any critical check fails
|
|
169
170
|
runtime.health.state; // "healthy" | "degraded" | ...
|
|
170
|
-
runtime.readiness.checks.get("database"); // per-check result and duration
|
|
171
|
+
runtime.readiness.checks.get("database"); // per-check result, message and duration
|
|
172
|
+
runtime.readiness.reason; // "Readiness checks failing: database."
|
|
171
173
|
```
|
|
172
174
|
|
|
175
|
+
A check registered with `{ critical: false }` is evaluated and reported
|
|
176
|
+
(health shows it as `degraded`) but never gates `ready`. A check that
|
|
177
|
+
returns `false` carries the message `"Check returned false."`; one that
|
|
178
|
+
throws or exceeds the timeout carries the error.
|
|
179
|
+
|
|
180
|
+
Readiness is pinned at `false` in two situations regardless of the checks:
|
|
181
|
+
while the runtime is `shutting_down` (entered by `stop()`, so a `/ready`
|
|
182
|
+
probe that re-runs the checks during or after shutdown never reports
|
|
183
|
+
ready again), and after a manual `tracker.markNotReady()`, which holds
|
|
184
|
+
until `markReady()`.
|
|
185
|
+
|
|
173
186
|
`runtime.health` is derived from the lifecycle state and the readiness
|
|
174
187
|
checks: a running runtime is `healthy` when every check passes and
|
|
175
188
|
`degraded` when any check fails; every other lifecycle state maps onto
|
|
@@ -3,4 +3,3 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { buildDependencyGraph, resolveDependencies, validateDependencies, } from "./dependencyGraph.core.js";
|
|
5
5
|
export type { DependencyNode, DependencyGraph, DependencyResolutionResult, CircularDependencyInfo, } from "./dependencyGraph.type.js";
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -9,4 +9,3 @@ import type { ReadinessTrackerState } from "../readiness/readiness.type.js";
|
|
|
9
9
|
* directly onto a health state.
|
|
10
10
|
*/
|
|
11
11
|
export declare function computeRuntimeHealth(state: RuntimeState, readiness: ReadinessTrackerState): RuntimeHealth;
|
|
12
|
-
//# sourceMappingURL=health.core.d.ts.map
|
package/dist/health/index.d.ts
CHANGED
package/dist/health/index.js
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -27,4 +27,3 @@ export * from "./registry/index.js";
|
|
|
27
27
|
// `testRuntime` is intentionally NOT exported from the package root: it
|
|
28
28
|
// is a testing helper, and re-exporting it here put a test-only module
|
|
29
29
|
// on the main entry point. Import it from "@zudojs/runtime/testing".
|
|
30
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -3,4 +3,3 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { LifecycleManager } from "./lifecycle.core.js";
|
|
5
5
|
export type { LifecyclePhase, LifecycleResult, LifecycleFailure, LifecycleContext, ManagedModule, LifecycleManagerOptions, ModuleContextServices, ModuleEventListener, } from "./lifecycle.type.js";
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/lifecycle/index.js
CHANGED
|
@@ -2,5 +2,4 @@
|
|
|
2
2
|
* Runtime readiness tracking.
|
|
3
3
|
*/
|
|
4
4
|
export { ReadinessTracker } from "./readiness.core.js";
|
|
5
|
-
export type { ReadinessState, ReadinessCheck, ReadinessCheckFn, ReadinessTrackerState, ReadinessOptions, } from "./readiness.type.js";
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
|
5
|
+
export type { ReadinessState, ReadinessCheck, ReadinessCheckFn, ReadinessCheckOptions, ReadinessInitialCheck, ReadinessTrackerState, ReadinessOptions, } from "./readiness.type.js";
|
package/dist/readiness/index.js
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ReadinessCheck, ReadinessCheckFn } from "./readiness.type.js";
|
|
2
|
+
/**
|
|
3
|
+
* How long a single readiness check may run before it counts as failed.
|
|
4
|
+
*
|
|
5
|
+
* Without a bound, one hanging probe hangs the readiness endpoint
|
|
6
|
+
* indefinitely — a health check that never answers is worse than one
|
|
7
|
+
* that answers "unhealthy".
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_CHECK_TIMEOUT = 5000;
|
|
10
|
+
/**
|
|
11
|
+
* Runs a check under a timeout, clearing the timer either way.
|
|
12
|
+
*
|
|
13
|
+
* The timer is deliberately NOT `unref`'d. It is cleared as soon as the
|
|
14
|
+
* check settles, so it never outlives a healthy check; while a check
|
|
15
|
+
* hangs it is the only thing guaranteeing an answer. Unref'd, a short
|
|
16
|
+
* script that awaited `runChecks()` on a hanging check exited with
|
|
17
|
+
* "unsettled top-level await" (code 13) instead of recording a timeout.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runCheckWithTimeout(name: string, fn: ReadinessCheckFn, timeoutMs: number): Promise<boolean>;
|
|
20
|
+
/**
|
|
21
|
+
* Evaluates one check and produces the result to record for it.
|
|
22
|
+
*
|
|
23
|
+
* A check that returns `false` used to be recorded with no message at
|
|
24
|
+
* all, indistinguishable from one that was never run.
|
|
25
|
+
*/
|
|
26
|
+
export declare function evaluateReadinessCheck(name: string, fn: ReadinessCheckFn, timeoutMs: number, critical: boolean): Promise<ReadinessCheck>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How long a single readiness check may run before it counts as failed.
|
|
3
|
+
*
|
|
4
|
+
* Without a bound, one hanging probe hangs the readiness endpoint
|
|
5
|
+
* indefinitely — a health check that never answers is worse than one
|
|
6
|
+
* that answers "unhealthy".
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_CHECK_TIMEOUT = 5_000;
|
|
9
|
+
/**
|
|
10
|
+
* Runs a check under a timeout, clearing the timer either way.
|
|
11
|
+
*
|
|
12
|
+
* The timer is deliberately NOT `unref`'d. It is cleared as soon as the
|
|
13
|
+
* check settles, so it never outlives a healthy check; while a check
|
|
14
|
+
* hangs it is the only thing guaranteeing an answer. Unref'd, a short
|
|
15
|
+
* script that awaited `runChecks()` on a hanging check exited with
|
|
16
|
+
* "unsettled top-level await" (code 13) instead of recording a timeout.
|
|
17
|
+
*/
|
|
18
|
+
export async function runCheckWithTimeout(name, fn, timeoutMs) {
|
|
19
|
+
if (timeoutMs <= 0) {
|
|
20
|
+
return fn();
|
|
21
|
+
}
|
|
22
|
+
let timer;
|
|
23
|
+
try {
|
|
24
|
+
return await Promise.race([
|
|
25
|
+
Promise.resolve(fn()),
|
|
26
|
+
new Promise((_, reject) => {
|
|
27
|
+
timer = setTimeout(() => {
|
|
28
|
+
reject(new Error(`Readiness check "${name}" did not settle within ${timeoutMs}ms.`));
|
|
29
|
+
}, timeoutMs);
|
|
30
|
+
}),
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
if (timer !== undefined) {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Evaluates one check and produces the result to record for it.
|
|
41
|
+
*
|
|
42
|
+
* A check that returns `false` used to be recorded with no message at
|
|
43
|
+
* all, indistinguishable from one that was never run.
|
|
44
|
+
*/
|
|
45
|
+
export async function evaluateReadinessCheck(name, fn, timeoutMs, critical) {
|
|
46
|
+
const startedAt = Date.now();
|
|
47
|
+
try {
|
|
48
|
+
const ready = await runCheckWithTimeout(name, fn, timeoutMs);
|
|
49
|
+
return {
|
|
50
|
+
name,
|
|
51
|
+
ready,
|
|
52
|
+
critical,
|
|
53
|
+
lastCheckedAt: new Date(),
|
|
54
|
+
durationMs: Date.now() - startedAt,
|
|
55
|
+
...(ready ? {} : { message: "Check returned false." }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return {
|
|
60
|
+
name,
|
|
61
|
+
ready: false,
|
|
62
|
+
critical,
|
|
63
|
+
lastCheckedAt: new Date(),
|
|
64
|
+
durationMs: Date.now() - startedAt,
|
|
65
|
+
message: error instanceof Error
|
|
66
|
+
? `Check threw an error: ${error.message}`
|
|
67
|
+
: "Check threw an error",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import type { ReadinessState, ReadinessCheckFn, ReadinessTrackerState, ReadinessOptions } from "./readiness.type.js";
|
|
1
|
+
import type { ReadinessState, ReadinessCheckFn, ReadinessCheckOptions, ReadinessTrackerState, ReadinessOptions } from "./readiness.type.js";
|
|
2
2
|
/**
|
|
3
3
|
* Tracks runtime readiness state.
|
|
4
|
+
*
|
|
5
|
+
* Two things pin readiness at `false` regardless of what the checks
|
|
6
|
+
* say: the `shutting_down` state (entered by the runtime in `stop()`)
|
|
7
|
+
* and a manual `markNotReady()`, which holds until `markReady()`.
|
|
8
|
+
* Before, the next `runChecks()` — a `/ready` probe, typically —
|
|
9
|
+
* overwrote both and sent traffic to an instance that was going away.
|
|
4
10
|
*/
|
|
5
11
|
export declare class ReadinessTracker {
|
|
6
12
|
private state;
|
|
@@ -9,6 +15,7 @@ export declare class ReadinessTracker {
|
|
|
9
15
|
private readonly autoMarkReady;
|
|
10
16
|
private readonly checkTimeout;
|
|
11
17
|
private ready;
|
|
18
|
+
private held;
|
|
12
19
|
private reason?;
|
|
13
20
|
private running;
|
|
14
21
|
constructor(options?: ReadinessOptions);
|
|
@@ -17,9 +24,11 @@ export declare class ReadinessTracker {
|
|
|
17
24
|
*
|
|
18
25
|
* The check function is retained so it can be re-evaluated later by
|
|
19
26
|
* `updateCheck(name)` or `runChecks()`. Registration does not run the
|
|
20
|
-
* check: it starts out not-ready until it is first evaluated.
|
|
27
|
+
* check: it starts out not-ready until it is first evaluated. Pass
|
|
28
|
+
* `{ critical: false }` for a check that should be reported but must
|
|
29
|
+
* not gate readiness.
|
|
21
30
|
*/
|
|
22
|
-
registerCheck(name: string, check: ReadinessCheckFn): void;
|
|
31
|
+
registerCheck(name: string, check: ReadinessCheckFn, options?: ReadinessCheckOptions): void;
|
|
23
32
|
/**
|
|
24
33
|
* Removes a readiness check.
|
|
25
34
|
*
|
|
@@ -42,19 +51,13 @@ export declare class ReadinessTracker {
|
|
|
42
51
|
*/
|
|
43
52
|
hasChecks(): boolean;
|
|
44
53
|
/**
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
private evaluateCheck;
|
|
48
|
-
/**
|
|
49
|
-
* Runs a check under a timeout, clearing the timer either way.
|
|
50
|
-
*/
|
|
51
|
-
private withCheckTimeout;
|
|
52
|
-
/**
|
|
53
|
-
* Marks the runtime as ready.
|
|
54
|
+
* Marks the runtime as ready and releases a `markNotReady()` hold.
|
|
55
|
+
* Ignored while `shutting_down`; leave that state with `setState()`.
|
|
54
56
|
*/
|
|
55
57
|
markReady(reason?: string): void;
|
|
56
58
|
/**
|
|
57
|
-
* Marks the runtime as not ready
|
|
59
|
+
* Marks the runtime as not ready and holds it there: automatic
|
|
60
|
+
* evaluation will not report ready again until `markReady()`.
|
|
58
61
|
*/
|
|
59
62
|
markNotReady(reason?: string): void;
|
|
60
63
|
/**
|
|
@@ -69,9 +72,11 @@ export declare class ReadinessTracker {
|
|
|
69
72
|
* Returns the current readiness state.
|
|
70
73
|
*/
|
|
71
74
|
getState(): ReadinessTrackerState;
|
|
75
|
+
private evaluate;
|
|
76
|
+
private becomeNotReady;
|
|
72
77
|
/**
|
|
73
|
-
* Evaluates overall readiness
|
|
78
|
+
* Evaluates overall readiness from the critical checks. Never acts
|
|
79
|
+
* while shutting down or under a manual hold.
|
|
74
80
|
*/
|
|
75
81
|
private evaluateReadiness;
|
|
76
82
|
}
|
|
77
|
-
//# sourceMappingURL=readiness.core.d.ts.map
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
+
import { DEFAULT_CHECK_TIMEOUT, evaluateReadinessCheck, } from "./readiness.check.js";
|
|
1
2
|
import { RuntimeStateError } from "../runtimeError/index.js";
|
|
2
|
-
/**
|
|
3
|
-
* How long a single readiness check may run before it counts as failed.
|
|
4
|
-
*
|
|
5
|
-
* Without a bound, one hanging probe hangs the readiness endpoint
|
|
6
|
-
* indefinitely — a health check that never answers is worse than one
|
|
7
|
-
* that answers "unhealthy".
|
|
8
|
-
*/
|
|
9
|
-
const DEFAULT_CHECK_TIMEOUT = 5_000;
|
|
10
3
|
/**
|
|
11
4
|
* Tracks runtime readiness state.
|
|
5
|
+
*
|
|
6
|
+
* Two things pin readiness at `false` regardless of what the checks
|
|
7
|
+
* say: the `shutting_down` state (entered by the runtime in `stop()`)
|
|
8
|
+
* and a manual `markNotReady()`, which holds until `markReady()`.
|
|
9
|
+
* Before, the next `runChecks()` — a `/ready` probe, typically —
|
|
10
|
+
* overwrote both and sent traffic to an instance that was going away.
|
|
12
11
|
*/
|
|
13
12
|
export class ReadinessTracker {
|
|
14
13
|
state = "not_ready";
|
|
@@ -17,15 +16,14 @@ export class ReadinessTracker {
|
|
|
17
16
|
autoMarkReady;
|
|
18
17
|
checkTimeout;
|
|
19
18
|
ready = false;
|
|
19
|
+
held = false;
|
|
20
20
|
reason;
|
|
21
21
|
running;
|
|
22
22
|
constructor(options = {}) {
|
|
23
23
|
this.autoMarkReady = options.autoMarkReady ?? true;
|
|
24
24
|
this.checkTimeout = options.checkTimeout ?? DEFAULT_CHECK_TIMEOUT;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this.registerCheck(check.name, check.check);
|
|
28
|
-
}
|
|
25
|
+
for (const check of options.initialChecks ?? []) {
|
|
26
|
+
this.registerCheck(check.name, check.check, { critical: check.critical });
|
|
29
27
|
}
|
|
30
28
|
}
|
|
31
29
|
/**
|
|
@@ -33,13 +31,16 @@ export class ReadinessTracker {
|
|
|
33
31
|
*
|
|
34
32
|
* The check function is retained so it can be re-evaluated later by
|
|
35
33
|
* `updateCheck(name)` or `runChecks()`. Registration does not run the
|
|
36
|
-
* check: it starts out not-ready until it is first evaluated.
|
|
34
|
+
* check: it starts out not-ready until it is first evaluated. Pass
|
|
35
|
+
* `{ critical: false }` for a check that should be reported but must
|
|
36
|
+
* not gate readiness.
|
|
37
37
|
*/
|
|
38
|
-
registerCheck(name, check) {
|
|
38
|
+
registerCheck(name, check, options = {}) {
|
|
39
39
|
this.checkFns.set(name, check);
|
|
40
40
|
this.checks.set(name, {
|
|
41
41
|
name,
|
|
42
42
|
ready: false,
|
|
43
|
+
critical: options.critical ?? true,
|
|
43
44
|
lastCheckedAt: new Date(),
|
|
44
45
|
durationMs: 0,
|
|
45
46
|
});
|
|
@@ -58,7 +59,8 @@ export class ReadinessTracker {
|
|
|
58
59
|
}
|
|
59
60
|
if (this.autoMarkReady &&
|
|
60
61
|
this.checks.size === 0 &&
|
|
61
|
-
this.state === "degraded"
|
|
62
|
+
this.state === "degraded" &&
|
|
63
|
+
!this.held) {
|
|
62
64
|
// `degraded` is only ever entered from `ready` because a check
|
|
63
65
|
// failed. Removing the last check leaves nothing failing, so the
|
|
64
66
|
// tracker returns to ready — otherwise `evaluateReadiness()` (which
|
|
@@ -85,7 +87,7 @@ export class ReadinessTracker {
|
|
|
85
87
|
if (fn === undefined) {
|
|
86
88
|
throw new RuntimeStateError(`Readiness check "${name}" is not registered.`);
|
|
87
89
|
}
|
|
88
|
-
await this.
|
|
90
|
+
await this.evaluate(name, fn);
|
|
89
91
|
this.evaluateReadiness();
|
|
90
92
|
}
|
|
91
93
|
/**
|
|
@@ -99,7 +101,7 @@ export class ReadinessTracker {
|
|
|
99
101
|
}
|
|
100
102
|
this.running = (async () => {
|
|
101
103
|
try {
|
|
102
|
-
await Promise.all([...this.checkFns].map(([name, fn]) => this.
|
|
104
|
+
await Promise.all([...this.checkFns].map(([name, fn]) => this.evaluate(name, fn)));
|
|
103
105
|
this.evaluateReadiness();
|
|
104
106
|
}
|
|
105
107
|
finally {
|
|
@@ -115,73 +117,24 @@ export class ReadinessTracker {
|
|
|
115
117
|
return this.checkFns.size > 0;
|
|
116
118
|
}
|
|
117
119
|
/**
|
|
118
|
-
*
|
|
119
|
-
|
|
120
|
-
async evaluateCheck(name, fn) {
|
|
121
|
-
const startedAt = Date.now();
|
|
122
|
-
try {
|
|
123
|
-
const result = await this.withCheckTimeout(name, fn);
|
|
124
|
-
this.checks.set(name, {
|
|
125
|
-
name,
|
|
126
|
-
ready: result,
|
|
127
|
-
lastCheckedAt: new Date(),
|
|
128
|
-
durationMs: Date.now() - startedAt,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
this.checks.set(name, {
|
|
133
|
-
name,
|
|
134
|
-
ready: false,
|
|
135
|
-
lastCheckedAt: new Date(),
|
|
136
|
-
durationMs: Date.now() - startedAt,
|
|
137
|
-
message: error instanceof Error
|
|
138
|
-
? `Check threw an error: ${error.message}`
|
|
139
|
-
: "Check threw an error",
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Runs a check under a timeout, clearing the timer either way.
|
|
145
|
-
*/
|
|
146
|
-
async withCheckTimeout(name, fn) {
|
|
147
|
-
if (this.checkTimeout <= 0) {
|
|
148
|
-
return fn();
|
|
149
|
-
}
|
|
150
|
-
let timer;
|
|
151
|
-
try {
|
|
152
|
-
return await Promise.race([
|
|
153
|
-
Promise.resolve(fn()),
|
|
154
|
-
new Promise((_, reject) => {
|
|
155
|
-
timer = setTimeout(() => {
|
|
156
|
-
reject(new Error(`Readiness check "${name}" did not settle within ${this.checkTimeout}ms.`));
|
|
157
|
-
}, this.checkTimeout);
|
|
158
|
-
timer.unref?.();
|
|
159
|
-
}),
|
|
160
|
-
]);
|
|
161
|
-
}
|
|
162
|
-
finally {
|
|
163
|
-
if (timer !== undefined) {
|
|
164
|
-
clearTimeout(timer);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Marks the runtime as ready.
|
|
120
|
+
* Marks the runtime as ready and releases a `markNotReady()` hold.
|
|
121
|
+
* Ignored while `shutting_down`; leave that state with `setState()`.
|
|
170
122
|
*/
|
|
171
123
|
markReady(reason) {
|
|
124
|
+
if (this.state === "shutting_down")
|
|
125
|
+
return;
|
|
126
|
+
this.held = false;
|
|
172
127
|
this.state = "ready";
|
|
173
128
|
this.ready = true;
|
|
174
129
|
this.reason = reason;
|
|
175
130
|
}
|
|
176
131
|
/**
|
|
177
|
-
* Marks the runtime as not ready
|
|
132
|
+
* Marks the runtime as not ready and holds it there: automatic
|
|
133
|
+
* evaluation will not report ready again until `markReady()`.
|
|
178
134
|
*/
|
|
179
135
|
markNotReady(reason) {
|
|
180
|
-
this.
|
|
181
|
-
this.reason
|
|
182
|
-
if (this.state === "ready") {
|
|
183
|
-
this.state = "degraded";
|
|
184
|
-
}
|
|
136
|
+
this.held = true;
|
|
137
|
+
this.becomeNotReady(reason);
|
|
185
138
|
}
|
|
186
139
|
/**
|
|
187
140
|
* Updates the readiness state.
|
|
@@ -190,6 +143,7 @@ export class ReadinessTracker {
|
|
|
190
143
|
this.state = state;
|
|
191
144
|
if (state === "ready") {
|
|
192
145
|
this.ready = true;
|
|
146
|
+
this.held = false;
|
|
193
147
|
}
|
|
194
148
|
else if (state === "not_ready" || state === "shutting_down") {
|
|
195
149
|
this.ready = false;
|
|
@@ -213,19 +167,34 @@ export class ReadinessTracker {
|
|
|
213
167
|
reason: this.reason,
|
|
214
168
|
});
|
|
215
169
|
}
|
|
170
|
+
async evaluate(name, fn) {
|
|
171
|
+
const critical = this.checks.get(name)?.critical ?? true;
|
|
172
|
+
this.checks.set(name, await evaluateReadinessCheck(name, fn, this.checkTimeout, critical));
|
|
173
|
+
}
|
|
174
|
+
becomeNotReady(reason) {
|
|
175
|
+
this.ready = false;
|
|
176
|
+
this.reason = reason;
|
|
177
|
+
if (this.state === "ready") {
|
|
178
|
+
this.state = "degraded";
|
|
179
|
+
}
|
|
180
|
+
}
|
|
216
181
|
/**
|
|
217
|
-
* Evaluates overall readiness
|
|
182
|
+
* Evaluates overall readiness from the critical checks. Never acts
|
|
183
|
+
* while shutting down or under a manual hold.
|
|
218
184
|
*/
|
|
219
185
|
evaluateReadiness() {
|
|
220
|
-
if (this.autoMarkReady
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
186
|
+
if (!this.autoMarkReady || this.checks.size === 0)
|
|
187
|
+
return;
|
|
188
|
+
if (this.state === "shutting_down" || this.held)
|
|
189
|
+
return;
|
|
190
|
+
const failing = [...this.checks.values()]
|
|
191
|
+
.filter((check) => check.critical && !check.ready)
|
|
192
|
+
.map((check) => check.name);
|
|
193
|
+
if (failing.length > 0) {
|
|
194
|
+
this.becomeNotReady(`Readiness checks failing: ${failing.join(", ")}.`);
|
|
195
|
+
}
|
|
196
|
+
else if (!this.ready) {
|
|
197
|
+
this.markReady("All readiness checks passed.");
|
|
228
198
|
}
|
|
229
199
|
}
|
|
230
200
|
}
|
|
231
|
-
//# sourceMappingURL=readiness.core.js.map
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Readiness state of the runtime.
|
|
3
|
+
*
|
|
4
|
+
* `shutting_down` is sticky: once entered (the runtime does so in
|
|
5
|
+
* `stop()`), automatic evaluation and `markReady()` never report ready
|
|
6
|
+
* again; only `setState()` leaves it.
|
|
3
7
|
*/
|
|
4
8
|
export type ReadinessState = "not_ready" | "initializing" | "ready" | "degraded" | "shutting_down";
|
|
5
9
|
/**
|
|
@@ -8,6 +12,10 @@ export type ReadinessState = "not_ready" | "initializing" | "ready" | "degraded"
|
|
|
8
12
|
export interface ReadinessCheck {
|
|
9
13
|
readonly name: string;
|
|
10
14
|
readonly ready: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Why the check is not ready: the error it threw, the timeout it hit,
|
|
17
|
+
* or `"Check returned false."`. Absent while it passes.
|
|
18
|
+
*/
|
|
11
19
|
readonly message?: string;
|
|
12
20
|
readonly lastCheckedAt: Date;
|
|
13
21
|
/**
|
|
@@ -15,11 +23,25 @@ export interface ReadinessCheck {
|
|
|
15
23
|
* `0` for a check that has been registered but not yet run.
|
|
16
24
|
*/
|
|
17
25
|
readonly durationMs: number;
|
|
26
|
+
/**
|
|
27
|
+
* Whether a failure of this check makes the runtime not ready.
|
|
28
|
+
*
|
|
29
|
+
* A non-critical check is still evaluated and reported — health shows
|
|
30
|
+
* it as `degraded` — but never gates `ready`. Defaults to true.
|
|
31
|
+
*/
|
|
32
|
+
readonly critical: boolean;
|
|
18
33
|
}
|
|
19
34
|
/**
|
|
20
35
|
* A readiness check function.
|
|
21
36
|
*/
|
|
22
37
|
export type ReadinessCheckFn = () => boolean | Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Options for a single readiness check.
|
|
40
|
+
*/
|
|
41
|
+
export interface ReadinessCheckOptions {
|
|
42
|
+
/** See {@link ReadinessCheck.critical}. Defaults to true. */
|
|
43
|
+
readonly critical?: boolean;
|
|
44
|
+
}
|
|
23
45
|
/**
|
|
24
46
|
* Readiness tracker state.
|
|
25
47
|
*/
|
|
@@ -29,6 +51,13 @@ export interface ReadinessTrackerState {
|
|
|
29
51
|
readonly ready: boolean;
|
|
30
52
|
readonly reason?: string;
|
|
31
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* A check registered through {@link ReadinessOptions.initialChecks}.
|
|
56
|
+
*/
|
|
57
|
+
export interface ReadinessInitialCheck extends ReadinessCheckOptions {
|
|
58
|
+
readonly name: string;
|
|
59
|
+
readonly check: ReadinessCheckFn;
|
|
60
|
+
}
|
|
32
61
|
/**
|
|
33
62
|
* Options for readiness tracking.
|
|
34
63
|
*/
|
|
@@ -36,10 +65,7 @@ export interface ReadinessOptions {
|
|
|
36
65
|
/**
|
|
37
66
|
* Initial readiness checks to register.
|
|
38
67
|
*/
|
|
39
|
-
readonly initialChecks?: ReadonlyArray<
|
|
40
|
-
readonly name: string;
|
|
41
|
-
readonly check: ReadinessCheckFn;
|
|
42
|
-
}>;
|
|
68
|
+
readonly initialChecks?: ReadonlyArray<ReadinessInitialCheck>;
|
|
43
69
|
/**
|
|
44
70
|
* Whether to automatically mark as ready when all checks pass.
|
|
45
71
|
* @default true
|
|
@@ -51,4 +77,3 @@ export interface ReadinessOptions {
|
|
|
51
77
|
*/
|
|
52
78
|
readonly checkTimeout?: number;
|
|
53
79
|
}
|
|
54
|
-
//# sourceMappingURL=readiness.type.d.ts.map
|
package/dist/registry/index.d.ts
CHANGED
package/dist/registry/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import type { ConfigurationManager, Module, ModuleContext } from "@zudojs/core";
|
|
|
5
5
|
import type { RuntimeState, RuntimeStatus, RuntimeHealth } from "../runtimeState/index.js";
|
|
6
6
|
import type { RuntimeOptions } from "../runtimeOptions/index.js";
|
|
7
7
|
import type { RuntimeContext } from "../runtimeContext/index.js";
|
|
8
|
-
import type { ReadinessCheckFn, ReadinessTrackerState } from "../readiness/index.js";
|
|
8
|
+
import type { ReadinessCheckFn, ReadinessCheckOptions, ReadinessTrackerState } from "../readiness/index.js";
|
|
9
9
|
/**
|
|
10
10
|
* Zudojs runtime interface.
|
|
11
11
|
*
|
|
@@ -25,9 +25,11 @@ export interface Runtime {
|
|
|
25
25
|
*
|
|
26
26
|
* A registered check starts out failing until it is first evaluated by
|
|
27
27
|
* `runReadinessChecks`, so registering one on a running runtime moves it
|
|
28
|
-
* to `degraded` until the check passes.
|
|
28
|
+
* to `degraded` until the check passes. Pass `{ critical: false }` for
|
|
29
|
+
* a check that is reported (and shows in `health`) but must not gate
|
|
30
|
+
* `ready`.
|
|
29
31
|
*/
|
|
30
|
-
registerReadinessCheck(name: string, check: ReadinessCheckFn): void;
|
|
32
|
+
registerReadinessCheck(name: string, check: ReadinessCheckFn, options?: ReadinessCheckOptions): void;
|
|
31
33
|
/**
|
|
32
34
|
* Removes a readiness check. Returns whether one was registered.
|
|
33
35
|
*/
|
|
@@ -104,7 +106,7 @@ export declare class DefaultRuntime implements Runtime {
|
|
|
104
106
|
/**
|
|
105
107
|
* Registers a readiness check.
|
|
106
108
|
*/
|
|
107
|
-
registerReadinessCheck(name: string, check: ReadinessCheckFn): void;
|
|
109
|
+
registerReadinessCheck(name: string, check: ReadinessCheckFn, options?: ReadinessCheckOptions): void;
|
|
108
110
|
/**
|
|
109
111
|
* Removes a readiness check.
|
|
110
112
|
*/
|
|
@@ -178,4 +180,3 @@ export declare class DefaultRuntime implements Runtime {
|
|
|
178
180
|
* Creates a runtime instance.
|
|
179
181
|
*/
|
|
180
182
|
export declare function createRuntime(dependencies: RuntimeDependencies, options: RuntimeOptions): Runtime;
|
|
181
|
-
//# sourceMappingURL=runtime.core.d.ts.map
|
|
@@ -133,9 +133,9 @@ export class DefaultRuntime {
|
|
|
133
133
|
/**
|
|
134
134
|
* Registers a readiness check.
|
|
135
135
|
*/
|
|
136
|
-
registerReadinessCheck(name, check) {
|
|
136
|
+
registerReadinessCheck(name, check, options) {
|
|
137
137
|
const previousHealth = this.health.state;
|
|
138
|
-
this.readinessTracker.registerCheck(name, check);
|
|
138
|
+
this.readinessTracker.registerCheck(name, check, options);
|
|
139
139
|
this.emitHealthChange(previousHealth);
|
|
140
140
|
}
|
|
141
141
|
/**
|
|
@@ -487,4 +487,3 @@ export class DefaultRuntime {
|
|
|
487
487
|
export function createRuntime(dependencies, options) {
|
|
488
488
|
return new DefaultRuntime(dependencies, options);
|
|
489
489
|
}
|
|
490
|
-
//# sourceMappingURL=runtime.core.js.map
|
|
@@ -4,4 +4,3 @@
|
|
|
4
4
|
export { createRuntimeContext, withRuntimeContextState, } from "./runtimeContext.core.js";
|
|
5
5
|
export { createRuntimeId, createCorrelationId, createRequestId, } from "./runtimeContext.factory.js";
|
|
6
6
|
export type { RuntimeContext, RuntimeContextDependencies, RuntimeContextState, } from "./runtimeContext.type.js";
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -17,4 +17,3 @@ export declare function createRuntimeContext(dependencies: RuntimeContextDepende
|
|
|
17
17
|
* a clean runtime on the failure path.
|
|
18
18
|
*/
|
|
19
19
|
export declare function withRuntimeContextState(base: RuntimeContext, state: RuntimeContextState): RuntimeContext;
|
|
20
|
-
//# sourceMappingURL=runtimeContext.core.d.ts.map
|
|
@@ -2,4 +2,3 @@
|
|
|
2
2
|
* Runtime error types.
|
|
3
3
|
*/
|
|
4
4
|
export { RuntimeStateError, RuntimeStartError, RuntimeStopError, RuntimeInitializationError, RuntimeTimeoutError, RuntimeRollbackError, RuntimeCircularDependencyError, RuntimeDependencyError, RuntimeSignalError, toRuntimeError, } from "./runtimeError.base.js";
|
|
5
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,4 +2,3 @@
|
|
|
2
2
|
* Runtime error types.
|
|
3
3
|
*/
|
|
4
4
|
export { RuntimeStateError, RuntimeStartError, RuntimeStopError, RuntimeInitializationError, RuntimeTimeoutError, RuntimeRollbackError, RuntimeCircularDependencyError, RuntimeDependencyError, RuntimeSignalError, toRuntimeError, } from "./runtimeError.base.js";
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -3,4 +3,3 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { publishRuntimeEvent, createRuntimeEventPayload, createModuleEventPayload, createFailureEventPayload, createHealthEventPayload, createReadinessEventPayload, } from "./runtimeEvents.core.js";
|
|
5
5
|
export type { RuntimeEventType, RuntimeModuleEventType, RuntimeEventPayload, RuntimeModuleEventPayload, RuntimeFailureEventPayload, RuntimeHealthEventPayload, RuntimeReadinessEventPayload, RuntimeEventMap, } from "./runtimeEvents.type.js";
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -4,4 +4,3 @@
|
|
|
4
4
|
export { resolveRuntimeOptions, validateRuntimeOptions, createRuntimeOptions, } from "./runtimeOptions.core.js";
|
|
5
5
|
export { DEFAULT_RUNTIME_OPTIONS } from "./runtimeOptions.type.js";
|
|
6
6
|
export type { RuntimeOptions, ResolvedRuntimeOptions, } from "./runtimeOptions.type.js";
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -16,4 +16,3 @@ export declare function validateRuntimeOptions(options: ResolvedRuntimeOptions):
|
|
|
16
16
|
* Creates a runtime options object with all defaults applied.
|
|
17
17
|
*/
|
|
18
18
|
export declare function createRuntimeOptions(options: ResolvedRuntimeOptions): ResolvedRuntimeOptions;
|
|
19
|
-
//# sourceMappingURL=runtimeOptions.core.d.ts.map
|
|
@@ -3,4 +3,3 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { RUNTIME_STATE_TRANSITIONS, TERMINAL_STATES, STARTABLE_STATES, STOPPABLE_STATES, canTransition, assertTransition, isTerminalState, canStart, canStop, isRunning, hasFailed, createStatus, } from "./runtimeState.core.js";
|
|
5
5
|
export type { RuntimeState, RuntimeFailureState, RuntimeId, RuntimeStatus, RuntimeShutdownFailure, RuntimeHealthState, RuntimeHealth, RuntimeHealthCheck, } from "./runtimeState.type.js";
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,4 +2,3 @@
|
|
|
2
2
|
* Runtime state types and state machine.
|
|
3
3
|
*/
|
|
4
4
|
export { RUNTIME_STATE_TRANSITIONS, TERMINAL_STATES, STARTABLE_STATES, STOPPABLE_STATES, canTransition, assertTransition, isTerminalState, canStart, canStop, isRunning, hasFailed, createStatus, } from "./runtimeState.core.js";
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
package/dist/shutdown/index.d.ts
CHANGED
package/dist/shutdown/index.js
CHANGED
|
@@ -19,4 +19,3 @@ export declare const CONTAINER_SHUTDOWN_ID = "(container)";
|
|
|
19
19
|
* @returns The failure, or `undefined` when disposal succeeded.
|
|
20
20
|
*/
|
|
21
21
|
export declare function disposeRuntimeContainer(container: Container, logger: Logger): Promise<LifecycleFailure | undefined>;
|
|
22
|
-
//# sourceMappingURL=shutdown.container.d.ts.map
|
|
@@ -24,4 +24,3 @@ export interface ShutdownResult {
|
|
|
24
24
|
* identical to one that shut down cleanly.
|
|
25
25
|
*/
|
|
26
26
|
export declare function executeShutdown(lifecycle: LifecycleManager, runtimeId: string, eventBus: EventBus | undefined, logger: Logger, shutdownTimeout: number, emitEvents: boolean): Promise<ShutdownResult>;
|
|
27
|
-
//# sourceMappingURL=shutdown.core.d.ts.map
|
|
@@ -50,11 +50,15 @@ export async function executeShutdown(lifecycle, runtimeId, eventBus, logger, sh
|
|
|
50
50
|
// handler now so its eventual rejection is never unhandled.
|
|
51
51
|
stopPromise.catch(() => { });
|
|
52
52
|
let timer;
|
|
53
|
+
// Not unref'd: the timer is cleared as soon as the race settles, and
|
|
54
|
+
// while a module's onShutdown hangs it is the only thing that will
|
|
55
|
+
// ever settle it. Unref'd, a script that awaited stop() with nothing
|
|
56
|
+
// else on the loop exited (code 13, "unsettled top-level await")
|
|
57
|
+
// instead of reporting the RuntimeTimeoutError.
|
|
53
58
|
const timeoutPromise = new Promise((_, reject) => {
|
|
54
59
|
timer = setTimeout(() => {
|
|
55
60
|
reject(new RuntimeTimeoutError("shutdown", shutdownTimeout));
|
|
56
61
|
}, Math.min(Math.max(0, shutdownTimeout), MAX_TIMER_DELAY));
|
|
57
|
-
timer.unref?.();
|
|
58
62
|
});
|
|
59
63
|
try {
|
|
60
64
|
const failures = await Promise.race([stopPromise, timeoutPromise]);
|
|
@@ -131,4 +135,3 @@ async function performShutdown(lifecycle, logger) {
|
|
|
131
135
|
});
|
|
132
136
|
return failures;
|
|
133
137
|
}
|
|
134
|
-
//# sourceMappingURL=shutdown.core.js.map
|
|
@@ -27,4 +27,3 @@ export declare function holdEventLoop(): () => void;
|
|
|
27
27
|
export declare function flushPendingSignals(): void;
|
|
28
28
|
/** Sets the exit code the process ends with once the loop drains. */
|
|
29
29
|
export declare function setProcessExitCode(code: number): void;
|
|
30
|
-
//# sourceMappingURL=signalHandler.keepAlive.d.ts.map
|
package/dist/startup/index.d.ts
CHANGED
package/dist/startup/index.js
CHANGED
|
@@ -13,4 +13,3 @@ export declare function executeStartup(lifecycle: LifecycleManager, runtimeId: s
|
|
|
13
13
|
* Rolls back a failed startup.
|
|
14
14
|
*/
|
|
15
15
|
export declare function rollbackStartup(lifecycle: LifecycleManager, logger: Logger): Promise<readonly LifecycleFailure[]>;
|
|
16
|
-
//# sourceMappingURL=startup.core.d.ts.map
|
|
@@ -53,4 +53,3 @@ export declare function createMockModule(id: string, dependencies?: string[]): M
|
|
|
53
53
|
* @param options - Optional runtime options.
|
|
54
54
|
*/
|
|
55
55
|
export declare function withTestRuntime<T>(fn: (runtime: DefaultRuntime) => Promise<T>, modules?: Module[], options?: Partial<RuntimeOptions>): Promise<T>;
|
|
56
|
-
//# sourceMappingURL=testRuntime.core.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zudojs/runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Application lifecycle orchestrator with dependency ordering, rollback, signals, and readiness checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"vitest": "^5.0.1"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@zudojs/constants": "1.
|
|
31
|
-
"@zudojs/container": "1.
|
|
32
|
-
"@zudojs/core": "1.
|
|
33
|
-
"@zudojs/errors": "1.
|
|
34
|
-
"@zudojs/events": "1.
|
|
35
|
-
"@zudojs/logger": "1.
|
|
30
|
+
"@zudojs/constants": "1.2.0",
|
|
31
|
+
"@zudojs/container": "1.3.0",
|
|
32
|
+
"@zudojs/core": "1.3.0",
|
|
33
|
+
"@zudojs/errors": "1.4.0",
|
|
34
|
+
"@zudojs/events": "1.4.0",
|
|
35
|
+
"@zudojs/logger": "1.5.0"
|
|
36
36
|
},
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"author": {
|