@fluojs/terminus 1.0.2 → 1.0.4

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.ko.md CHANGED
@@ -24,7 +24,11 @@ fluo 애플리케이션을 위한 헬스 인디케이터(Health Indicator) 툴
24
24
  pnpm add @fluojs/terminus
25
25
  ```
26
26
 
27
- `path`로 health endpointcustom path 아래에 mount할 수 있고, `readinessChecks`로 애플리케이션별 readiness logic을 Terminus indicator 및 platform readiness check와 합성할 수 있습니다.
27
+ Redis indicator subpath사용할 때만 선택적 peer를 설치하세요.
28
+
29
+ ```bash
30
+ pnpm add @fluojs/redis ioredis
31
+ ```
28
32
 
29
33
  ## 사용 시점
30
34
 
@@ -68,7 +72,7 @@ class AppModule {}
68
72
 
69
73
  ### DI 기반 인디케이터
70
74
 
71
- Redis나 DB 클라이언트와 같이 DI 컨테이너의 의존성이 필요한 인디케이터를 사용할 때는, 모듈 로드 시점에 피어 의존성을 import하지 않도록 제공되는 provider 팩토리를 사용하세요.
75
+ Redis나 DB 클라이언트와 같이 DI 컨테이너의 의존성이 필요한 인디케이터를 사용할 때는, 모듈 로드 시점에 피어 의존성을 import하지 않도록 문서화된 provider 팩토리를 사용하세요. 이 helper들은 `TerminusModule.forRoot({ indicatorProviders })`에 전달할 indicator provider entry를 만들며 module facade를 대체하지 않습니다.
72
76
 
73
77
  ```typescript
74
78
  import { TerminusModule } from '@fluojs/terminus';
@@ -92,6 +96,8 @@ TerminusModule.forRoot({
92
96
  });
93
97
  ```
94
98
 
99
+ `@fluojs/terminus/redis`를 통해 만든 Redis indicator는 `@fluojs/redis`에서 받은 client가 있으면 lifecycle-aware로 동작합니다. Terminus는 `PING`을 보내기 전에 Redis connection state를 `createRedisPlatformStatusSnapshot(...)`으로 매핑하므로, client가 `wait`, `connecting`, `reconnecting`, `close`, `end` 상태이면 raw ping만 믿지 않고 `/health`와 `/ready`를 unavailable로 표시합니다. Custom `ping` callback은 manual probe용으로 계속 지원되지만, lifecycle metadata는 Redis client가 `status`를 노출할 때만 붙습니다.
100
+
95
101
  Drizzle의 경우 `createDrizzleHealthIndicatorProvider()`는 `@fluojs/drizzle`이 노출하는 lifecycle-aware `DrizzleDatabase` wrapper를 우선 사용합니다. Drizzle이 종료 중이거나 중지되었거나 `DrizzleDatabase.createPlatformStatusSnapshot()` 기준으로 준비되지 않은 상태이면 SQL probe를 실행하기 전에 해당 indicator를 `down`으로 보고합니다. legacy raw `DRIZZLE_DATABASE` handle만 등록된 경우에는 기존 lightweight SQL probe 동작을 유지합니다.
96
102
 
97
103
  Provider factory는 반복 등록할 수 있습니다. 각 인스턴스가 서로 다른 indicator key나 dependency option을 사용한다면 같은 factory가 만든 provider 여러 개를 하나의 `indicatorProviders` 배열에 등록할 수 있으며, Terminus는 나중에 등록된 같은 타입 provider가 앞선 provider를 덮어쓰지 않도록 각 provider 인스턴스를 별도 DI token으로 보관합니다.
@@ -111,6 +117,8 @@ TerminusModule.forRoot({
111
117
  });
112
118
  ```
113
119
 
120
+ `path`로 health endpoint를 custom path 아래에 mount할 수 있고, `readinessChecks`로 애플리케이션별 readiness logic을 Terminus indicator 및 platform readiness check와 합성할 수 있습니다.
121
+
114
122
  ### 실패 시맨틱
115
123
 
116
124
  인디케이터가 실패하면 `HealthCheckError`를 던집니다. `TerminusHealthService`는 이 실패들을 모아 보고서를 작성합니다.
@@ -125,6 +133,7 @@ TerminusModule.forRoot({
125
133
  - 플랫폼 health/readiness 실패는 `/health` 응답에서 결정적인 `fluo-platform-health`, `fluo-platform-readiness` contributor로 노출됩니다.
126
134
  - Runtime diagnostics가 있으면 `/health` response에 platform health/readiness detail을 담은 `platform` block이 포함될 수 있습니다.
127
135
  - DI provider로 생성한 Drizzle indicator는 SQL probe보다 먼저 Drizzle lifecycle readiness/health state를 반영하므로, underlying driver가 raw ping을 아직 받을 수 있어도 종료 중이거나 중지된 통합은 `/health`와 `/ready`를 unavailable로 표시합니다.
136
+ - Redis subpath로 생성한 Redis indicator는 `PING` 전에 `@fluojs/redis` client lifecycle state를 반영하므로, 종료 중이거나 연결이 끊긴 Redis client는 command 실행 전에도 `/health`와 `/ready`를 unavailable로 표시합니다.
128
137
 
129
138
  ## 공개 API 개요
130
139
 
@@ -145,12 +154,13 @@ TerminusModule.forRoot({
145
154
 
146
155
  - `runHealthCheck(...)`, `assertHealthCheck(...)`: 직접 aggregation/testing helper입니다.
147
156
  - `TERMINUS_HEALTH_INDICATORS`, `TERMINUS_INDICATOR_PROVIDER_TOKENS`: 등록된 indicator와 provider token을 위한 DI token입니다.
148
- - Built-in indicator는 `create*HealthIndicator()` 및 `create*HealthIndicatorProvider()` helper도 노출합니다.
157
+ - Built-in indicator는 `create*HealthIndicator()` 및 `create*HealthIndicatorProvider()` helper도 노출합니다. Provider helper는 `indicatorProviders`를 위한 의도적인 DI composition 예외이며, 애플리케이션 등록은 계속 `TerminusModule.forRoot(...)`를 사용해야 합니다.
149
158
 
150
159
  ### `@fluojs/terminus/redis`
151
160
 
152
161
  - `RedisHealthIndicator`, `createRedisHealthIndicator()`, `createRedisHealthIndicatorProvider()`
153
162
  - Redis 전용 인디케이터 헬퍼는 선택적 Redis 피어가 설치되지 않은 환경에서도 루트 패키지 import가 안전하도록 전용 subpath에서 export됩니다.
163
+ - Provider는 기본적으로 default `@fluojs/redis` client token을 resolve하고, `clientName`이 있으면 named token을 resolve하며, Redis platform status semantics를 readiness 진단에 재사용합니다.
154
164
 
155
165
  ### `@fluojs/terminus/node`
156
166
 
package/README.md CHANGED
@@ -24,6 +24,12 @@ Health indicator toolkit for fluo applications. `@fluojs/terminus` layers on top
24
24
  pnpm add @fluojs/terminus
25
25
  ```
26
26
 
27
+ Install the optional peer only when you use the Redis indicator subpath:
28
+
29
+ ```bash
30
+ pnpm add @fluojs/redis ioredis
31
+ ```
32
+
27
33
  ## When to Use
28
34
 
29
35
  - When you need to monitor external dependencies (databases, Redis, APIs) as part of your application's health status.
@@ -66,7 +72,7 @@ The package provides several indicators out of the box:
66
72
 
67
73
  ### DI-Backed Indicators
68
74
 
69
- To use indicators that require dependencies from the DI container (like Redis or Database clients) without importing peer dependencies at module load time, use the provider factories.
75
+ To use indicators that require dependencies from the DI container (like Redis or Database clients) without importing peer dependencies at module load time, use the documented provider factories. These helpers create indicator provider entries for `TerminusModule.forRoot({ indicatorProviders })`; they do not replace the module facade.
70
76
 
71
77
  ```typescript
72
78
  import { TerminusModule } from '@fluojs/terminus';
@@ -90,6 +96,8 @@ TerminusModule.forRoot({
90
96
  });
91
97
  ```
92
98
 
99
+ Redis indicators created through `@fluojs/terminus/redis` are lifecycle-aware when they receive a client from `@fluojs/redis`. Terminus maps the Redis connection state with `createRedisPlatformStatusSnapshot(...)` before sending `PING`, so clients in `wait`, `connecting`, `reconnecting`, `close`, or `end` states mark `/health` and `/ready` unavailable instead of relying on a raw ping alone. Custom `ping` callbacks remain supported for manual probes, but lifecycle metadata is only attached when a Redis client exposes its `status`.
100
+
93
101
  For Drizzle, `createDrizzleHealthIndicatorProvider()` prefers the lifecycle-aware `DrizzleDatabase` wrapper exported by `@fluojs/drizzle`. The indicator reports `down` before probing SQL whenever Drizzle is shutting down, stopped, or otherwise not ready according to `DrizzleDatabase.createPlatformStatusSnapshot()`. If only the legacy raw `DRIZZLE_DATABASE` handle is registered, the provider keeps the previous lightweight SQL probe behavior.
94
102
 
95
103
  Provider factories are repeatable. You may register multiple providers created by the same factory in one `indicatorProviders` array when each instance uses a distinct indicator key or dependency option; Terminus keeps every provider instance under its own DI token instead of letting later same-type providers overwrite earlier ones.
@@ -125,6 +133,7 @@ When an indicator fails, it throws a `HealthCheckError`. The `TerminusHealthServ
125
133
  - Platform health/readiness failures are surfaced as deterministic `fluo-platform-health` and `fluo-platform-readiness` contributors in `/health` responses.
126
134
  - `/health` responses may include a `platform` block with platform health/readiness details when runtime diagnostics are available.
127
135
  - Drizzle indicators created through the DI provider map Drizzle lifecycle readiness/health state before SQL probing, so shutdown or stopped integrations mark `/health` and `/ready` as unavailable even if the underlying driver still accepts a raw ping.
136
+ - Redis indicators created through the Redis subpath map `@fluojs/redis` client lifecycle state before `PING`, so shutdown or disconnected Redis clients mark `/health` and `/ready` as unavailable even before command execution.
128
137
 
129
138
  ## Public API Overview
130
139
 
@@ -145,12 +154,13 @@ When an indicator fails, it throws a `HealthCheckError`. The `TerminusHealthServ
145
154
 
146
155
  - `runHealthCheck(...)`, `assertHealthCheck(...)`: Direct aggregation/testing helpers.
147
156
  - `TERMINUS_HEALTH_INDICATORS`, `TERMINUS_INDICATOR_PROVIDER_TOKENS`: DI tokens for registered indicators and provider tokens.
148
- - Built-in indicators also expose `create*HealthIndicator()` and `create*HealthIndicatorProvider()` helpers.
157
+ - Built-in indicators also expose `create*HealthIndicator()` and `create*HealthIndicatorProvider()` helpers. Provider helpers are intentional DI-composition exceptions for `indicatorProviders`, while application registration should still go through `TerminusModule.forRoot(...)`.
149
158
 
150
159
  ### `@fluojs/terminus/redis`
151
160
 
152
161
  - `RedisHealthIndicator`, `createRedisHealthIndicator()`, `createRedisHealthIndicatorProvider()`
153
162
  - Redis-specific indicator helpers are exported from the dedicated subpath so the root package stays import-safe without the optional Redis peer installed.
163
+ - The provider resolves the default `@fluojs/redis` client token by default, or a named token when `clientName` is supplied, and reuses Redis platform status semantics for readiness diagnostics.
154
164
 
155
165
  ### `@fluojs/terminus/node`
156
166
 
@@ -1,17 +1,28 @@
1
1
  import type { Provider } from '@fluojs/di';
2
2
  import type { HealthIndicator, HealthIndicatorResult } from '../types.js';
3
+ /** Snapshot returned by a memory usage sampler. */
4
+ export interface MemoryUsageSnapshot {
5
+ arrayBuffers: number;
6
+ external: number;
7
+ heapTotal: number;
8
+ heapUsed: number;
9
+ rss: number;
10
+ }
11
+ /** Function that samples runtime memory usage for `MemoryHealthIndicator`. */
12
+ export type MemoryUsageSampler = () => MemoryUsageSnapshot;
3
13
  /** Options for checking process heap and RSS thresholds. */
4
14
  export interface MemoryHealthIndicatorOptions {
5
15
  heapUsedThresholdBytes?: number;
6
16
  heapUsedThresholdRatio?: number;
7
17
  key?: string;
18
+ memoryUsage?: MemoryUsageSampler;
8
19
  rssThresholdBytes?: number;
9
20
  }
10
21
  /**
11
22
  * Create a process-memory health indicator.
12
23
  *
13
24
  * @param options Optional heap and RSS thresholds plus an indicator key override.
14
- * @returns A health indicator backed by `process.memoryUsage()`.
25
+ * @returns A health indicator backed by the Node runtime memory sampler.
15
26
  */
16
27
  export declare function createMemoryHealthIndicator(options?: MemoryHealthIndicatorOptions): HealthIndicator;
17
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/indicators/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE1E,4DAA4D;AAC5D,MAAM,WAAW,4BAA4B;IAC3C,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAYD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,4BAAiC,GAAG,eAAe,CAEvG;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,OAAO,GAAE,4BAAiC,GAAG,QAAQ,CAOxG;AAED,qEAAqE;AACrE,qBAAa,qBAAsB,YAAW,eAAe;IAG/C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEJ,OAAO,GAAE,4BAAiC;IAIjE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAiCzD"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/indicators/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE1E,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,MAAM,mBAAmB,CAAC;AAE3D,4DAA4D;AAC5D,MAAM,WAAW,4BAA4B;IAC3C,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAYD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,4BAAiC,GAAG,eAAe,CAEvG;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,OAAO,GAAE,4BAAiC,GAAG,QAAQ,CAOxG;AAED,qEAAqE;AACrE,qBAAa,qBAAsB,YAAW,eAAe;IAG/C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEJ,OAAO,GAAE,4BAAiC;IAIjE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAiCzD"}
@@ -1,4 +1,9 @@
1
1
  import { createDownResult, createUpResult, resolveIndicatorKey, throwHealthCheckError } from './utils.js';
2
+ import { readNodeMemoryUsage } from '../node-runtime.js';
3
+
4
+ /** Snapshot returned by a memory usage sampler. */
5
+
6
+ /** Function that samples runtime memory usage for `MemoryHealthIndicator`. */
2
7
 
3
8
  /** Options for checking process heap and RSS thresholds. */
4
9
 
@@ -14,7 +19,7 @@ function exceedsRatioThreshold(used, total, threshold) {
14
19
  * Create a process-memory health indicator.
15
20
  *
16
21
  * @param options Optional heap and RSS thresholds plus an indicator key override.
17
- * @returns A health indicator backed by `process.memoryUsage()`.
22
+ * @returns A health indicator backed by the Node runtime memory sampler.
18
23
  */
19
24
  export function createMemoryHealthIndicator(options = {}) {
20
25
  return new MemoryHealthIndicator(options);
@@ -44,7 +49,7 @@ export class MemoryHealthIndicator {
44
49
  async check(key) {
45
50
  const indicatorKey = resolveIndicatorKey('memory', this.options.key ?? key);
46
51
  const heapRatioThreshold = this.options.heapUsedThresholdRatio ?? DEFAULT_HEAP_RATIO_THRESHOLD;
47
- const usage = process.memoryUsage();
52
+ const usage = (this.options.memoryUsage ?? readNodeMemoryUsage)();
48
53
  const usageDetails = {
49
54
  arrayBuffers: usage.arrayBuffers,
50
55
  external: usage.external,
@@ -1,31 +1,49 @@
1
1
  import type { Provider } from '@fluojs/di';
2
+ import { type RedisStatusAdapterInput } from '@fluojs/redis';
2
3
  import type { HealthIndicator, HealthIndicatorResult } from '../types.js';
3
4
  interface RedisClientLike {
4
5
  ping?: () => Promise<unknown>;
6
+ status?: RedisStatusAdapterInput['status'];
5
7
  }
6
- /** Options for probing Redis connectivity. */
8
+ /**
9
+ * Options for probing Redis connectivity.
10
+ *
11
+ * `client` may be a raw `ioredis`-compatible handle resolved from `@fluojs/redis`.
12
+ * When that handle exposes a Redis `status`, Terminus maps the lifecycle state into
13
+ * health/readiness metadata before issuing `PING`, so shutdown or disconnected clients
14
+ * fail readiness even if a raw ping callback would still be callable.
15
+ */
7
16
  export interface RedisHealthIndicatorOptions {
17
+ /** Raw Redis client to probe. Its `status` is used for lifecycle-aware readiness when available. */
8
18
  client?: RedisClientLike;
19
+ /** Named Redis registration to resolve when using `createRedisHealthIndicatorProvider(...)`. */
9
20
  clientName?: string;
21
+ /** Indicator result key override. Defaults to the key passed to `check(...)`, then `redis`. */
10
22
  key?: string;
23
+ /** Custom ping callback for manual probes or tests. Lifecycle state is only mapped when `client.status` is available. */
11
24
  ping?: () => Promise<unknown> | unknown;
25
+ /** Maximum time to wait for the ping operation. Defaults to `2_000` ms. */
12
26
  timeoutMs?: number;
13
27
  }
14
28
  /**
15
29
  * Create a Redis health indicator.
16
30
  *
17
- * @param options Optional Redis client, ping callback, timeout, and key override.
18
- * @returns A health indicator that checks Redis with `PING` semantics.
31
+ * @param options Optional Redis client, named-client hint, ping callback, timeout, and key override.
32
+ * @returns A health indicator that checks Redis lifecycle status before `PING` when client state is available.
19
33
  */
20
34
  export declare function createRedisHealthIndicator(options?: RedisHealthIndicatorOptions): HealthIndicator;
21
35
  /**
22
36
  * Create a provider that resolves a Redis client from DI and wraps it as an indicator.
23
37
  *
24
- * @param options Optional timeout, key override, or custom ping callback.
38
+ * The provider resolves `getRedisClientToken(options.clientName)`, preserving the
39
+ * default-vs-named client lifecycle boundary from `@fluojs/redis` while keeping the
40
+ * Redis-specific peer dependency isolated to `@fluojs/terminus/redis`.
41
+ *
42
+ * @param options Optional named-client hint, timeout, key override, or custom ping callback.
25
43
  * @returns A factory provider that exposes `RedisHealthIndicator` from the DI container.
26
44
  */
27
45
  export declare function createRedisHealthIndicatorProvider(options?: Omit<RedisHealthIndicatorOptions, 'client'>): Provider;
28
- /** Health indicator that checks Redis reachability with a ping-like operation. */
46
+ /** Health indicator that maps Redis lifecycle status and checks reachability with a ping-like operation. */
29
47
  export declare class RedisHealthIndicator implements HealthIndicator {
30
48
  private readonly options;
31
49
  readonly key: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/indicators/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE1E,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/B;AAED,8CAA8C;AAC9C,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmBD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,2BAAgC,GAAG,eAAe,CAErG;AAED;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,GAAE,IAAI,CAAC,2BAA2B,EAAE,QAAQ,CAAM,GAAG,QAAQ,CAQtH;AAED,kFAAkF;AAClF,qBAAa,oBAAqB,YAAW,eAAe;IAG9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEJ,OAAO,GAAE,2BAAgC;IAIhE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAczD"}
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/indicators/redis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAA+E,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAG1I,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAE1E,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;CAC5C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C,oGAAoG;IACpG,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,gGAAgG;IAChG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yHAAyH;IACzH,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACxC,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,2BAAgC,GAAG,eAAe,CAErG;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,GAAE,IAAI,CAAC,2BAA2B,EAAE,QAAQ,CAAM,GAAG,QAAQ,CAQtH;AAED,4GAA4G;AAC5G,qBAAa,oBAAqB,YAAW,eAAe;IAG9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;gBAEJ,OAAO,GAAE,2BAAgC;IAIhE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAwBzD"}
@@ -1,7 +1,14 @@
1
- import { getRedisClientToken } from '@fluojs/redis';
1
+ import { createRedisPlatformStatusSnapshot, getRedisClientToken, getRedisComponentId } from '@fluojs/redis';
2
2
  import { createDownResult, createUpResult, resolveIndicatorKey, throwHealthCheckError, withIndicatorTimeout } from './utils.js';
3
3
 
4
- /** Options for probing Redis connectivity. */
4
+ /**
5
+ * Options for probing Redis connectivity.
6
+ *
7
+ * `client` may be a raw `ioredis`-compatible handle resolved from `@fluojs/redis`.
8
+ * When that handle exposes a Redis `status`, Terminus maps the lifecycle state into
9
+ * health/readiness metadata before issuing `PING`, so shutdown or disconnected clients
10
+ * fail readiness even if a raw ping callback would still be callable.
11
+ */
5
12
 
6
13
  const DEFAULT_REDIS_TIMEOUT_MS = 2_000;
7
14
  async function runRedisPing(options) {
@@ -15,12 +22,46 @@ async function runRedisPing(options) {
15
22
  }
16
23
  await client.ping();
17
24
  }
25
+ function createRedisLifecycleDownResult(indicatorKey, options) {
26
+ const status = options.client?.status;
27
+ if (!status) {
28
+ return undefined;
29
+ }
30
+ const snapshot = createRedisPlatformStatusSnapshot({
31
+ componentId: getRedisComponentId(options.clientName),
32
+ status
33
+ });
34
+ if (snapshot.health.status === 'healthy' && snapshot.readiness.status === 'ready') {
35
+ return undefined;
36
+ }
37
+ const message = snapshot.readiness.reason ?? snapshot.health.reason ?? `Redis lifecycle reported health=${snapshot.health.status} readiness=${snapshot.readiness.status}.`;
38
+ return createDownResult(indicatorKey, message, {
39
+ details: snapshot.details,
40
+ healthStatus: snapshot.health.status,
41
+ readinessStatus: snapshot.readiness.status
42
+ });
43
+ }
44
+ function createRedisLifecycleUpDetails(options) {
45
+ const status = options.client?.status;
46
+ if (!status) {
47
+ return {};
48
+ }
49
+ const snapshot = createRedisPlatformStatusSnapshot({
50
+ componentId: getRedisComponentId(options.clientName),
51
+ status
52
+ });
53
+ return {
54
+ details: snapshot.details,
55
+ healthStatus: snapshot.health.status,
56
+ readinessStatus: snapshot.readiness.status
57
+ };
58
+ }
18
59
 
19
60
  /**
20
61
  * Create a Redis health indicator.
21
62
  *
22
- * @param options Optional Redis client, ping callback, timeout, and key override.
23
- * @returns A health indicator that checks Redis with `PING` semantics.
63
+ * @param options Optional Redis client, named-client hint, ping callback, timeout, and key override.
64
+ * @returns A health indicator that checks Redis lifecycle status before `PING` when client state is available.
24
65
  */
25
66
  export function createRedisHealthIndicator(options = {}) {
26
67
  return new RedisHealthIndicator(options);
@@ -29,7 +70,11 @@ export function createRedisHealthIndicator(options = {}) {
29
70
  /**
30
71
  * Create a provider that resolves a Redis client from DI and wraps it as an indicator.
31
72
  *
32
- * @param options Optional timeout, key override, or custom ping callback.
73
+ * The provider resolves `getRedisClientToken(options.clientName)`, preserving the
74
+ * default-vs-named client lifecycle boundary from `@fluojs/redis` while keeping the
75
+ * Redis-specific peer dependency isolated to `@fluojs/terminus/redis`.
76
+ *
77
+ * @param options Optional named-client hint, timeout, key override, or custom ping callback.
33
78
  * @returns A factory provider that exposes `RedisHealthIndicator` from the DI container.
34
79
  */
35
80
  export function createRedisHealthIndicatorProvider(options = {}) {
@@ -44,7 +89,7 @@ export function createRedisHealthIndicatorProvider(options = {}) {
44
89
  };
45
90
  }
46
91
 
47
- /** Health indicator that checks Redis reachability with a ping-like operation. */
92
+ /** Health indicator that maps Redis lifecycle status and checks reachability with a ping-like operation. */
48
93
  export class RedisHealthIndicator {
49
94
  key;
50
95
  constructor(options = {}) {
@@ -55,9 +100,16 @@ export class RedisHealthIndicator {
55
100
  const indicatorKey = resolveIndicatorKey('redis', this.options.key ?? key);
56
101
  const timeoutMs = this.options.timeoutMs ?? DEFAULT_REDIS_TIMEOUT_MS;
57
102
  try {
103
+ const lifecycleDownResult = createRedisLifecycleDownResult(indicatorKey, this.options);
104
+ if (lifecycleDownResult) {
105
+ throwHealthCheckError('Redis health check failed.', lifecycleDownResult);
106
+ }
58
107
  await withIndicatorTimeout(runRedisPing(this.options), timeoutMs, indicatorKey);
59
- return createUpResult(indicatorKey);
108
+ return createUpResult(indicatorKey, createRedisLifecycleUpDetails(this.options));
60
109
  } catch (error) {
110
+ if (error instanceof Error && error.name === 'HealthCheckError') {
111
+ throw error;
112
+ }
61
113
  throwHealthCheckError('Redis health check failed.', createDownResult(indicatorKey, error instanceof Error ? error.message : 'Redis health check failed.'));
62
114
  }
63
115
  }
@@ -0,0 +1,11 @@
1
+ interface NodeMemoryUsageSnapshot {
2
+ arrayBuffers: number;
3
+ external: number;
4
+ heapTotal: number;
5
+ heapUsed: number;
6
+ rss: number;
7
+ }
8
+ /** Read Node.js process memory usage through the Terminus Node runtime seam. */
9
+ export declare function readNodeMemoryUsage(): NodeMemoryUsageSnapshot;
10
+ export {};
11
+ //# sourceMappingURL=node-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-runtime.d.ts","sourceRoot":"","sources":["../src/node-runtime.ts"],"names":[],"mappings":"AAAA,UAAU,uBAAuB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAkBD,gFAAgF;AAChF,wBAAgB,mBAAmB,IAAI,uBAAuB,CAQ7D"}
@@ -0,0 +1,13 @@
1
+ function resolveNodeProcess() {
2
+ const runtimeGlobal = globalThis;
3
+ return runtimeGlobal.process;
4
+ }
5
+
6
+ /** Read Node.js process memory usage through the Terminus Node runtime seam. */
7
+ export function readNodeMemoryUsage() {
8
+ const memoryUsage = resolveNodeProcess()?.memoryUsage;
9
+ if (typeof memoryUsage !== 'function') {
10
+ throw new Error('Node.js process.memoryUsage() is not available in this runtime.');
11
+ }
12
+ return memoryUsage();
13
+ }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "liveness",
10
10
  "health-check"
11
11
  ],
12
- "version": "1.0.2",
12
+ "version": "1.0.4",
13
13
  "private": false,
14
14
  "license": "MIT",
15
15
  "repository": {
@@ -44,15 +44,15 @@
44
44
  "dist"
45
45
  ],
46
46
  "dependencies": {
47
- "@fluojs/core": "^1.0.2",
48
- "@fluojs/di": "^1.0.2",
49
- "@fluojs/http": "^1.0.0",
50
- "@fluojs/runtime": "^1.1.0"
47
+ "@fluojs/core": "^1.0.3",
48
+ "@fluojs/di": "^1.1.0",
49
+ "@fluojs/http": "^1.1.0",
50
+ "@fluojs/runtime": "^1.1.6"
51
51
  },
52
52
  "peerDependencies": {
53
- "@fluojs/drizzle": "^1.0.0",
54
- "@fluojs/prisma": "^1.0.0",
55
- "@fluojs/redis": "^1.0.0"
53
+ "@fluojs/drizzle": "^1.0.2",
54
+ "@fluojs/prisma": "^1.0.2",
55
+ "@fluojs/redis": "^1.0.1"
56
56
  },
57
57
  "peerDependenciesMeta": {
58
58
  "@fluojs/drizzle": {
@@ -67,7 +67,7 @@
67
67
  },
68
68
  "devDependencies": {
69
69
  "vitest": "^3.2.4",
70
- "@fluojs/testing": "^1.0.2"
70
+ "@fluojs/testing": "^1.0.5"
71
71
  },
72
72
  "scripts": {
73
73
  "prebuild": "node ../../tooling/scripts/clean-dist.mjs",