@theruntimehq/react 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@theruntimehq/react.svg)](https://www.npmjs.com/package/@theruntimehq/react)
4
4
  [![license](https://img.shields.io/npm/l/@theruntimehq/react.svg)](https://github.com/TheRuntimeHQ/runtimehq-react/blob/main/LICENSE)
5
5
 
6
- The official React state management SDK for [RuntimeHQ](https://theruntimehq.com). Connect your status checks directly to your React primitives.
6
+ The official [Runtime React SDK](https://docs.theruntimehq.com/runtime-sdks/react) for [RuntimeHQ](https://theruntimehq.com). The SDK provides a context provider and hooks to easily consume the effective runtime state in your application components.
7
7
 
8
8
  This SDK is a **pure state management SDK** with:
9
9
  - 🚫 **No visual UI components** (Customers use their own design systems).
@@ -19,9 +19,11 @@ This SDK is a **pure state management SDK** with:
19
19
  - [Installation](#installation)
20
20
  - [Core Hooks & Provider APIs](#core-hooks--provider-apis)
21
21
  - [1. Global Provider (\`RuntimeHQProvider\`)](#1-global-provider-runtimehqprovider)
22
- - [2. Context Hook (\`useRuntimeHQ\`)](#2-context-hook-useruntimehq)
23
- - [3. Standalone Direct Hook (\`useRuntimeHQState\`)](#3-standalone-direct-hook-useruntimehqstate)
22
+ - [2. Capability Hook (\`useCapability\`)](#2-capability-hook-usecapability)
23
+ - [3. Context Hook (\`useRuntimeHQ\`)](#3-context-hook-useruntimehq)
24
+ - [4. Standalone Direct Hook (\`useRuntimeHQState\`)](#4-standalone-direct-hook-useruntimehqstate)
24
25
  - [Convenience Helpers](#convenience-helpers)
26
+ - [State Resolution Architecture](#state-resolution-architecture)
25
27
  - [Server Rendering (SSR) & Next.js App Router Integration](#server-rendering-ssr--nextjs-app-router-integration)
26
28
  - [Examples Directory](#examples-directory)
27
29
  - [License](#license)
@@ -51,7 +53,7 @@ export default function Root() {
51
53
  return (
52
54
  <RuntimeHQProvider
53
55
  runtimeKey="rt_prod_your_key_here"
54
- intervalSeconds={15}
56
+ intervalSeconds={60}
55
57
  >
56
58
  <App />
57
59
  </RuntimeHQProvider>
@@ -62,14 +64,63 @@ export default function Root() {
62
64
  #### Provider Props
63
65
  | Prop | Type | Required | Default | Description |
64
66
  | :--- | :--- | :--- | :--- | :--- |
65
- | `runtimeKey` | `string` | **Yes** | - | Your RuntimeHQ API status key (must start with `rt_prod_` or `rt_test_`). |
66
- | `intervalSeconds` | `number` | No | `15` | Polling interval for updates in seconds. |
67
+ | `runtimeKey` | `string` | **Yes** | - | The [Runtime Key](https://docs.theruntimehq.com/runtime-keys) required to get the resolved operational state of the application's capabilities. This is a public, read-only key that is absolutely safe for client-side exposure or browser environments. |
68
+ | `intervalSeconds` | `number` | No | `60` | Configurable polling interval for updates in seconds. Defaults to 60 seconds. |
67
69
 
68
70
  ---
69
71
 
70
- ### 2. Context Hook (`useRuntimeHQ`)
72
+ ### 2. Capability Hook (`useCapability`)
71
73
 
72
- Consume the global status state anywhere inside the provider.
74
+ The recommended, idiomatic way to monitor feature health inside components. Encapsulates fail-open defaults (`isOperational: true`, `isOutage: false` when unconfigured or loading).
75
+
76
+ ```tsx
77
+ import { useCapability } from "@theruntimehq/react";
78
+
79
+ function SearchComponent() {
80
+ const { isOutage, isDegraded, message } = useCapability("search");
81
+
82
+ // Dynamically back off request frequency when search capability is degraded
83
+ const debounceDelayMs = isDegraded ? 1200 : 300;
84
+
85
+ return (
86
+ <div className="search-container">
87
+ <input
88
+ type="text"
89
+ placeholder="Search products..."
90
+ disabled={isOutage}
91
+ onChange={debounce(handleSearch, debounceDelayMs)}
92
+ />
93
+ {(isOutage || isDegraded) && message && (
94
+ <p className={`helper-message ${isOutage ? 'text-red-600' : 'text-amber-600'}`}>
95
+ {message}
96
+ </p>
97
+ )}
98
+ </div>
99
+ );
100
+ }
101
+ ```
102
+
103
+ #### Return Value
104
+ ```typescript
105
+ interface UseCapabilityResult {
106
+ capability: CapabilityState | undefined; // Raw capability state object (or undefined if not present)
107
+ state: RuntimeState; // Current state, defaults to "OPERATIONAL" (fail-open)
108
+ message: string; // Operational or degraded message (defaults to "")
109
+ isOperational: boolean; // true by default (fail-open)
110
+ isDegraded: boolean; // true if state === "DEGRADED"
111
+ isOutage: boolean; // true if state === "OUTAGE"
112
+ isMaintenance: boolean; // true if state === "MAINTENANCE"
113
+ exists: boolean; // true if capability is registered in configuration
114
+ loading: boolean; // true until the first fetch completes
115
+ error: Error | null; // Captured network or validation error (if any)
116
+ }
117
+ ```
118
+
119
+ ---
120
+
121
+ ### 3. Context Hook (`useRuntimeHQ`)
122
+
123
+ Consume the global status state anywhere inside the provider for application-wide status banners, dashboards, or lower-level inspection.
73
124
 
74
125
  ```tsx
75
126
  import { useRuntimeHQ, isOperational } from "@theruntimehq/react";
@@ -92,15 +143,16 @@ function StatusBanner() {
92
143
  #### Return Value
93
144
  ```typescript
94
145
  interface RuntimeHQContextValue {
95
- runtime: RuntimeResponse | null; // Detailed status info or null before first fetch
96
- loading: boolean; // true until the first fetch (success or failure) completes
97
- error: Error | null; // Captured network or validation error (if any)
146
+ runtime: RuntimeResponse | null; // Detailed status info or null before first fetch
147
+ loading: boolean; // true until the first fetch (success or failure) completes
148
+ error: Error | null; // Captured network or validation error (if any)
149
+ hasCapability: (name: string) => boolean; // Checks if a capability is registered
150
+ getCapabilityState: (name: string) => CapabilityState | undefined; // Returns resolved capability state
98
151
  }
99
152
  ```
100
153
 
101
154
  > [!IMPORTANT]
102
- > If `useRuntimeHQ` is invoked outside a `<RuntimeHQProvider>`, it throws a descriptive error:
103
- > `useRuntimeHQ must be used within a RuntimeHQProvider`
155
+ > Both `useCapability` and `useRuntimeHQ` must be used within a `<RuntimeHQProvider>`, or they will throw a descriptive error.
104
156
 
105
157
  ---
106
158
 
@@ -114,7 +166,7 @@ import { useRuntimeHQState } from "@theruntimehq/react";
114
166
  function IndependentWidget() {
115
167
  const { runtime, loading, error } = useRuntimeHQState({
116
168
  runtimeKey: "rt_prod_your_key_here",
117
- intervalSeconds: 30,
169
+ intervalSeconds: 60,
118
170
  });
119
171
 
120
172
  if (loading) return <Spinner />;
@@ -145,6 +197,29 @@ isOutage(runtime) // returns boolean
145
197
 
146
198
  ---
147
199
 
200
+ ## State Resolution Architecture
201
+
202
+ ```mermaid
203
+ sequenceDiagram
204
+ participant App as React Application
205
+ participant SDK as @theruntimehq/react
206
+ participant Edge as Global Edge Cache
207
+
208
+ Note over SDK, Edge: 1. Asynchronous Background Polling
209
+ loop Every intervalSeconds
210
+ SDK->>Edge: Fetch latest operational state
211
+ Edge-->>SDK: Cached State JSON (High Availability)
212
+ SDK->>SDK: Update local React Context
213
+ end
214
+
215
+ Note over App, SDK: 2. Instant Local Resolution
216
+ App->>SDK: getCapabilityState("capability-name")
217
+ SDK-->>App: Returns state from local memory instantly
218
+ Note over App: Zero network latency impact on application speed
219
+ ```
220
+
221
+ ---
222
+
148
223
  ## Server Rendering (SSR) & Next.js App Router Integration
149
224
 
150
225
  To avoid layout shifts and flashes of loading states on initial load, fetch the status server-side using the underlying `@theruntimehq/js` SDK directly, and render a static warning component on the server:
@@ -195,7 +270,7 @@ interface ClientSidePollerProps {
195
270
  export default function ClientSidePoller({ initialData }: ClientSidePollerProps) {
196
271
  const { runtime } = useRuntimeHQState({
197
272
  runtimeKey: "rt_prod_your_key_here",
198
- intervalSeconds: 15,
273
+ intervalSeconds: 60,
199
274
  });
200
275
 
201
276
  // Hydrate client-side with server-fetched data initially
@@ -238,6 +313,7 @@ Check out the [examples directory](./examples) for common integration patterns:
238
313
  | `19-maintenance-lock-screen.tsx` | Restrict access to workflows during active maintenance windows. |
239
314
  | `20-live-system-health-widget.tsx` | Embed a reusable health widget anywhere in the application. |
240
315
  | `21-production-ready-provider.tsx` | Complete production integration including provider setup, refresh handling, and resilience patterns. |
316
+ | `22-adaptive-debounce-search.tsx` | Adapt client input debounce delay to shed backend load during degraded states. |
241
317
 
242
318
  ---
243
319
 
package/dist/index.cjs CHANGED
@@ -40,7 +40,7 @@ const RuntimeHQContext = (0, react.createContext)(null);
40
40
  * A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.
41
41
  */
42
42
  function useRuntimeHQState(options) {
43
- const { runtimeKey, intervalSeconds = 15 } = options;
43
+ const { runtimeKey, intervalSeconds = 60 } = options;
44
44
  const [client, clientInitError] = (0, react.useMemo)(() => {
45
45
  if (!runtimeKey) return [null, /* @__PURE__ */ new Error("runtimeKey is required")];
46
46
  try {
@@ -130,6 +130,45 @@ function useRuntimeHQ() {
130
130
  return context;
131
131
  }
132
132
 
133
+ //#endregion
134
+ //#region src/hooks/useCapability.ts
135
+ /**
136
+ * Accesses and monitors the health state of a specific capability.
137
+ * Must be used within a `<RuntimeHQProvider>`.
138
+ *
139
+ * Implements a fail-open pattern: if the capability is not present or
140
+ * RuntimeHQ is loading/errored, the state defaults to "OPERATIONAL"
141
+ * and isOperational is true.
142
+ *
143
+ * @param name The unique name of the capability to check (e.g. "search", "payments")
144
+ */
145
+ function useCapability(name) {
146
+ const { getCapabilityState, hasCapability, loading, error } = useRuntimeHQ();
147
+ return (0, react.useMemo)(() => {
148
+ const capability = getCapabilityState(name);
149
+ const exists = hasCapability(name);
150
+ const state = capability?.state ?? "OPERATIONAL";
151
+ return {
152
+ capability,
153
+ state,
154
+ message: capability?.message ?? "",
155
+ isOperational: state === "OPERATIONAL",
156
+ isDegraded: state === "DEGRADED",
157
+ isOutage: state === "OUTAGE",
158
+ isMaintenance: state === "MAINTENANCE",
159
+ exists,
160
+ loading,
161
+ error
162
+ };
163
+ }, [
164
+ getCapabilityState,
165
+ hasCapability,
166
+ name,
167
+ loading,
168
+ error
169
+ ]);
170
+ }
171
+
133
172
  //#endregion
134
173
  //#region src/helpers/index.ts
135
174
  function getState(input) {
@@ -168,6 +207,7 @@ exports.isDegraded = isDegraded;
168
207
  exports.isMaintenance = isMaintenance;
169
208
  exports.isOperational = isOperational;
170
209
  exports.isOutage = isOutage;
210
+ exports.useCapability = useCapability;
171
211
  exports.useRuntimeHQ = useRuntimeHQ;
172
212
  exports.useRuntimeHQState = useRuntimeHQState;
173
213
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["RuntimeHQClient"],"sources":["../src/context/index.ts","../src/hooks/useRuntimeHQState.ts","../src/provider/index.tsx","../src/hooks/useRuntimeHQ.ts","../src/helpers/index.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext } from \"react\";\nimport { RuntimeHQContextValue } from \"../types\";\n\nexport const RuntimeHQContext = createContext<RuntimeHQContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, useCallback } from \"react\";\nimport { RuntimeHQClient } from \"@theruntimehq/js\";\nimport { RuntimeResponse, RuntimeHQContextValue } from \"../types\";\n\nexport interface UseRuntimeHQStateOptions {\n runtimeKey: string;\n intervalSeconds?: number;\n}\n\n/**\n * A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.\n */\nexport function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue {\n const { runtimeKey, intervalSeconds = 15 } = options;\n\n // Safely instantiate RuntimeHQClient\n const [client, clientInitError] = useMemo(() => {\n if (!runtimeKey) {\n return [null, new Error(\"runtimeKey is required\")] as const;\n }\n try {\n return [new RuntimeHQClient({ runtimeKey }), null] as const;\n } catch (err) {\n return [null, err instanceof Error ? err : new Error(String(err))] as const;\n }\n }, [runtimeKey]);\n\n const [runtime, setRuntime] = useState<RuntimeResponse | null>(null);\n const [error, setError] = useState<Error | null>(clientInitError || null);\n const [loading, setLoading] = useState<boolean>(!clientInitError);\n\n useEffect(() => {\n if (clientInitError) {\n setError(clientInitError);\n setLoading(false);\n return;\n }\n\n if (!client) {\n return;\n }\n\n // Reset states when the client or key changes\n setRuntime(null);\n setError(null);\n setLoading(true);\n\n let active = true;\n\n const unsubscribe = client.watchRuntime({\n intervalSeconds,\n onUpdate: (data) => {\n if (active) {\n setRuntime(data);\n setError(null);\n setLoading(false);\n }\n },\n onError: (err) => {\n if (active) {\n setError(err);\n setLoading(false);\n }\n },\n });\n\n return () => {\n active = false;\n unsubscribe();\n };\n }, [client, clientInitError, intervalSeconds]);\n\n const hasCapability = useCallback((name: string) => {\n return runtime ? runtime.hasCapability(name) : false;\n }, [runtime]);\n\n const getCapabilityState = useCallback((name: string) => {\n return runtime ? runtime.getCapabilityState(name) : undefined;\n }, [runtime]);\n\n return {\n runtime,\n loading,\n error,\n hasCapability,\n getCapabilityState,\n };\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { useRuntimeHQState } from \"../hooks/useRuntimeHQState\";\n\nexport interface RuntimeHQProviderProps {\n runtimeKey: string;\n intervalSeconds?: number;\n children: React.ReactNode;\n}\n\n/**\n * Context Provider that manages a global RuntimeHQ client subscription and polling loop,\n * making the status state available to all child components using `useRuntimeHQ()`.\n */\nexport function RuntimeHQProvider({\n runtimeKey,\n intervalSeconds,\n children,\n}: RuntimeHQProviderProps) {\n const value = useRuntimeHQState({ runtimeKey, intervalSeconds });\n\n return (\n <RuntimeHQContext.Provider value={value}>\n {children}\n </RuntimeHQContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { RuntimeHQContextValue } from \"../types\";\n\n/**\n * Accesses the global RuntimeHQ status check context.\n * Must be used within a `<RuntimeHQProvider>`.\n */\nexport function useRuntimeHQ(): RuntimeHQContextValue {\n const context = useContext(RuntimeHQContext);\n if (!context) {\n throw new Error(\"useRuntimeHQ must be used within a RuntimeHQProvider\");\n }\n return context;\n}\n","import { RuntimeResponse, RuntimeState, CapabilityState } from \"../types\";\n\ntype StateInput = RuntimeResponse | CapabilityState | RuntimeState | null | undefined;\n\nfunction getState(input: StateInput): RuntimeState | null {\n if (!input) return null;\n if (typeof input === \"string\") return input;\n return input.state || null;\n}\n\n/**\n * Checks if the application runtime status is OPERATIONAL.\n */\nexport function isOperational(input: StateInput): boolean {\n return getState(input) === \"OPERATIONAL\";\n}\n\n/**\n * Checks if the application runtime status is MAINTENANCE.\n */\nexport function isMaintenance(input: StateInput): boolean {\n return getState(input) === \"MAINTENANCE\";\n}\n\n/**\n * Checks if the application runtime status is DEGRADED.\n */\nexport function isDegraded(input: StateInput): boolean {\n return getState(input) === \"DEGRADED\";\n}\n\n/**\n * Checks if the application runtime status is OUTAGE.\n */\nexport function isOutage(input: StateInput): boolean {\n return getState(input) === \"OUTAGE\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAa,4CAA+D,IAAI;;;;;;;ACShF,SAAgB,kBAAkB,SAA0D;CAC1F,MAAM,EAAE,YAAY,kBAAkB,OAAO;CAG7C,MAAM,CAAC,QAAQ,4CAAiC;EAC9C,IAAI,CAAC,YACH,OAAO,CAAC,sBAAM,IAAI,MAAM,wBAAwB,CAAC;EAEnD,IAAI;GACF,OAAO,CAAC,IAAIA,iCAAgB,EAAE,WAAW,CAAC,GAAG,IAAI;EACnD,SAAS,KAAK;GACZ,OAAO,CAAC,MAAM,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;EACnE;CACF,GAAG,CAAC,UAAU,CAAC;CAEf,MAAM,CAAC,SAAS,kCAA+C,IAAI;CACnE,MAAM,CAAC,OAAO,gCAAmC,mBAAmB,IAAI;CACxE,MAAM,CAAC,SAAS,kCAAgC,CAAC,eAAe;CAEhE,2BAAgB;EACd,IAAI,iBAAiB;GACnB,SAAS,eAAe;GACxB,WAAW,KAAK;GAChB;EACF;EAEA,IAAI,CAAC,QACH;EAIF,WAAW,IAAI;EACf,SAAS,IAAI;EACb,WAAW,IAAI;EAEf,IAAI,SAAS;EAEb,MAAM,cAAc,OAAO,aAAa;GACtC;GACA,WAAW,SAAS;IAClB,IAAI,QAAQ;KACV,WAAW,IAAI;KACf,SAAS,IAAI;KACb,WAAW,KAAK;IAClB;GACF;GACA,UAAU,QAAQ;IAChB,IAAI,QAAQ;KACV,SAAS,GAAG;KACZ,WAAW,KAAK;IAClB;GACF;EACF,CAAC;EAED,aAAa;GACX,SAAS;GACT,YAAY;EACd;CACF,GAAG;EAAC;EAAQ;EAAiB;CAAe,CAAC;CAU7C,OAAO;EACL;EACA;EACA;EACA,uCAZiC,SAAiB;GAClD,OAAO,UAAU,QAAQ,cAAc,IAAI,IAAI;EACjD,GAAG,CAAC,OAAO,CAUG;EACZ,4CATsC,SAAiB;GACvD,OAAO,UAAU,QAAQ,mBAAmB,IAAI,IAAI;EACtD,GAAG,CAAC,OAAO,CAOQ;CACnB;AACF;;;;;;;;ACzEA,SAAgB,kBAAkB,EAChC,YACA,iBACA,YACyB;CACzB,MAAM,QAAQ,kBAAkB;EAAE;EAAY;CAAgB,CAAC;CAE/D,OACE,2CAAC,iBAAiB,UAAlB;EAAkC;EAC/B;CACwB;AAE/B;;;;;;;;AClBA,SAAgB,eAAsC;CACpD,MAAM,gCAAqB,gBAAgB;CAC3C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,sDAAsD;CAExE,OAAO;AACT;;;;ACZA,SAAS,SAAS,OAAwC;CACxD,IAAI,CAAC,OAAO,OAAO;CACnB,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,OAAO,MAAM,SAAS;AACxB;;;;AAKA,SAAgB,cAAc,OAA4B;CACxD,OAAO,SAAS,KAAK,MAAM;AAC7B;;;;AAKA,SAAgB,cAAc,OAA4B;CACxD,OAAO,SAAS,KAAK,MAAM;AAC7B;;;;AAKA,SAAgB,WAAW,OAA4B;CACrD,OAAO,SAAS,KAAK,MAAM;AAC7B;;;;AAKA,SAAgB,SAAS,OAA4B;CACnD,OAAO,SAAS,KAAK,MAAM;AAC7B"}
1
+ {"version":3,"file":"index.cjs","names":["RuntimeHQClient"],"sources":["../src/context/index.ts","../src/hooks/useRuntimeHQState.ts","../src/provider/index.tsx","../src/hooks/useRuntimeHQ.ts","../src/hooks/useCapability.ts","../src/helpers/index.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext } from \"react\";\nimport { RuntimeHQContextValue } from \"../types\";\n\nexport const RuntimeHQContext = createContext<RuntimeHQContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, useCallback } from \"react\";\nimport { RuntimeHQClient } from \"@theruntimehq/js\";\nimport { RuntimeResponse, RuntimeHQContextValue } from \"../types\";\n\nexport interface UseRuntimeHQStateOptions {\n runtimeKey: string;\n intervalSeconds?: number;\n}\n\n/**\n * A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.\n */\nexport function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue {\n const { runtimeKey, intervalSeconds = 60 } = options;\n\n // Safely instantiate RuntimeHQClient\n const [client, clientInitError] = useMemo(() => {\n if (!runtimeKey) {\n return [null, new Error(\"runtimeKey is required\")] as const;\n }\n try {\n return [new RuntimeHQClient({ runtimeKey }), null] as const;\n } catch (err) {\n return [null, err instanceof Error ? err : new Error(String(err))] as const;\n }\n }, [runtimeKey]);\n\n const [runtime, setRuntime] = useState<RuntimeResponse | null>(null);\n const [error, setError] = useState<Error | null>(clientInitError || null);\n const [loading, setLoading] = useState<boolean>(!clientInitError);\n\n useEffect(() => {\n if (clientInitError) {\n setError(clientInitError);\n setLoading(false);\n return;\n }\n\n if (!client) {\n return;\n }\n\n // Reset states when the client or key changes\n setRuntime(null);\n setError(null);\n setLoading(true);\n\n let active = true;\n\n const unsubscribe = client.watchRuntime({\n intervalSeconds,\n onUpdate: (data) => {\n if (active) {\n setRuntime(data);\n setError(null);\n setLoading(false);\n }\n },\n onError: (err) => {\n if (active) {\n setError(err);\n setLoading(false);\n }\n },\n });\n\n return () => {\n active = false;\n unsubscribe();\n };\n }, [client, clientInitError, intervalSeconds]);\n\n const hasCapability = useCallback((name: string) => {\n return runtime ? runtime.hasCapability(name) : false;\n }, [runtime]);\n\n const getCapabilityState = useCallback((name: string) => {\n return runtime ? runtime.getCapabilityState(name) : undefined;\n }, [runtime]);\n\n return {\n runtime,\n loading,\n error,\n hasCapability,\n getCapabilityState,\n };\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { useRuntimeHQState } from \"../hooks/useRuntimeHQState\";\n\nexport interface RuntimeHQProviderProps {\n runtimeKey: string;\n intervalSeconds?: number;\n children: React.ReactNode;\n}\n\n/**\n * Context Provider that manages a global RuntimeHQ client subscription and polling loop,\n * making the status state available to all child components using `useRuntimeHQ()`.\n */\nexport function RuntimeHQProvider({\n runtimeKey,\n intervalSeconds,\n children,\n}: RuntimeHQProviderProps) {\n const value = useRuntimeHQState({ runtimeKey, intervalSeconds });\n\n return (\n <RuntimeHQContext.Provider value={value}>\n {children}\n </RuntimeHQContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { RuntimeHQContextValue } from \"../types\";\n\n/**\n * Accesses the global RuntimeHQ status check context.\n * Must be used within a `<RuntimeHQProvider>`.\n */\nexport function useRuntimeHQ(): RuntimeHQContextValue {\n const context = useContext(RuntimeHQContext);\n if (!context) {\n throw new Error(\"useRuntimeHQ must be used within a RuntimeHQProvider\");\n }\n return context;\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { useRuntimeHQ } from \"./useRuntimeHQ\";\nimport { UseCapabilityResult, RuntimeState } from \"../types\";\n\n/**\n * Accesses and monitors the health state of a specific capability.\n * Must be used within a `<RuntimeHQProvider>`.\n *\n * Implements a fail-open pattern: if the capability is not present or\n * RuntimeHQ is loading/errored, the state defaults to \"OPERATIONAL\"\n * and isOperational is true.\n *\n * @param name The unique name of the capability to check (e.g. \"search\", \"payments\")\n */\nexport function useCapability(name: string): UseCapabilityResult {\n const { getCapabilityState, hasCapability, loading, error } = useRuntimeHQ();\n\n return useMemo(() => {\n const capability = getCapabilityState(name);\n const exists = hasCapability(name);\n const state: RuntimeState = capability?.state ?? \"OPERATIONAL\";\n const message = capability?.message ?? \"\";\n\n return {\n capability,\n state,\n message,\n isOperational: state === \"OPERATIONAL\",\n isDegraded: state === \"DEGRADED\",\n isOutage: state === \"OUTAGE\",\n isMaintenance: state === \"MAINTENANCE\",\n exists,\n loading,\n error,\n };\n }, [getCapabilityState, hasCapability, name, loading, error]);\n}\n","import { RuntimeResponse, RuntimeState, CapabilityState } from \"../types\";\n\ntype StateInput = RuntimeResponse | CapabilityState | RuntimeState | null | undefined;\n\nfunction getState(input: StateInput): RuntimeState | null {\n if (!input) return null;\n if (typeof input === \"string\") return input;\n return input.state || null;\n}\n\n/**\n * Checks if the application runtime status is OPERATIONAL.\n */\nexport function isOperational(input: StateInput): boolean {\n return getState(input) === \"OPERATIONAL\";\n}\n\n/**\n * Checks if the application runtime status is MAINTENANCE.\n */\nexport function isMaintenance(input: StateInput): boolean {\n return getState(input) === \"MAINTENANCE\";\n}\n\n/**\n * Checks if the application runtime status is DEGRADED.\n */\nexport function isDegraded(input: StateInput): boolean {\n return getState(input) === \"DEGRADED\";\n}\n\n/**\n * Checks if the application runtime status is OUTAGE.\n */\nexport function isOutage(input: StateInput): boolean {\n return getState(input) === \"OUTAGE\";\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { CapabilityState, CapabilityState as CapabilityState$1, RuntimeHQClientOptions, RuntimeResponse, RuntimeResponse as RuntimeResponse$1, RuntimeState, WatchRuntimeOptions } from "@theruntimehq/js";
2
+ import { CapabilityState, CapabilityState as CapabilityState$1, RuntimeHQClientOptions, RuntimeResponse, RuntimeResponse as RuntimeResponse$1, RuntimeState as RuntimeState$1, WatchRuntimeOptions } from "@theruntimehq/js";
3
3
 
4
4
  //#region src/provider/index.d.ts
5
5
  interface RuntimeHQProviderProps {
@@ -25,6 +25,18 @@ interface RuntimeHQContextValue {
25
25
  hasCapability: (name: string) => boolean;
26
26
  getCapabilityState: (name: string) => CapabilityState$1 | undefined;
27
27
  }
28
+ interface UseCapabilityResult {
29
+ capability: CapabilityState$1 | undefined;
30
+ state: RuntimeState;
31
+ message: string;
32
+ isOperational: boolean;
33
+ isDegraded: boolean;
34
+ isOutage: boolean;
35
+ isMaintenance: boolean;
36
+ exists: boolean;
37
+ loading: boolean;
38
+ error: Error | null;
39
+ }
28
40
  //#endregion
29
41
  //#region src/hooks/useRuntimeHQ.d.ts
30
42
  /**
@@ -43,8 +55,21 @@ interface UseRuntimeHQStateOptions {
43
55
  */
44
56
  declare function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue;
45
57
  //#endregion
58
+ //#region src/hooks/useCapability.d.ts
59
+ /**
60
+ * Accesses and monitors the health state of a specific capability.
61
+ * Must be used within a `<RuntimeHQProvider>`.
62
+ *
63
+ * Implements a fail-open pattern: if the capability is not present or
64
+ * RuntimeHQ is loading/errored, the state defaults to "OPERATIONAL"
65
+ * and isOperational is true.
66
+ *
67
+ * @param name The unique name of the capability to check (e.g. "search", "payments")
68
+ */
69
+ declare function useCapability(name: string): UseCapabilityResult;
70
+ //#endregion
46
71
  //#region src/helpers/index.d.ts
47
- type StateInput = RuntimeResponse | CapabilityState | RuntimeState | null | undefined;
72
+ type StateInput = RuntimeResponse | CapabilityState | RuntimeState$1 | null | undefined;
48
73
  /**
49
74
  * Checks if the application runtime status is OPERATIONAL.
50
75
  */
@@ -62,5 +87,5 @@ declare function isDegraded(input: StateInput): boolean;
62
87
  */
63
88
  declare function isOutage(input: StateInput): boolean;
64
89
  //#endregion
65
- export { type CapabilityState, type RuntimeHQClientOptions, RuntimeHQContextValue, RuntimeHQProvider, type RuntimeHQProviderProps, type RuntimeResponse, type RuntimeState, type UseRuntimeHQStateOptions, type WatchRuntimeOptions, isDegraded, isMaintenance, isOperational, isOutage, useRuntimeHQ, useRuntimeHQState };
90
+ export { type CapabilityState, type RuntimeHQClientOptions, RuntimeHQContextValue, RuntimeHQProvider, type RuntimeHQProviderProps, type RuntimeResponse, type RuntimeState$1 as RuntimeState, UseCapabilityResult, type UseRuntimeHQStateOptions, type WatchRuntimeOptions, isDegraded, isMaintenance, isOperational, isOutage, useCapability, useRuntimeHQ, useRuntimeHQState };
66
91
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/provider/index.tsx","../src/types/index.ts","../src/hooks/useRuntimeHQ.ts","../src/hooks/useRuntimeHQState.ts","../src/helpers/index.ts"],"mappings":";;;;UAMiB,sBAAA;EACf,UAAA;EACA,eAAA;EACA,QAAA,EAAU,KAAA,CAAM,SAAS;AAAA;;;;;iBAOX,iBAAA;EACd,UAAA;EACA,eAAA;EACA;AAAA,GACC,sBAAA,GAAsB,KAAA,CAAA,GAAA,CAAA,OAAA;;;UCVR,qBAAA;EACf,OAAA,EAAS,iBAAA;EACT,OAAA;EACA,KAAA,EAAO,KAAA;EACP,aAAA,GAAgB,IAAA;EAChB,kBAAA,GAAqB,IAAA,aAAiB,iBAAA;AAAA;;;;;;ADTxC;iBEIgB,YAAA,IAAgB,qBAAqB;;;UCJpC,wBAAA;EACf,UAAA;EACA,eAAe;AAAA;;;;iBAMD,iBAAA,CAAkB,OAAA,EAAS,wBAAA,GAA2B,qBAAqB;;;KCZtF,UAAA,GAAa,eAAA,GAAkB,eAAA,GAAkB,YAAA;;;AJItD;iBIOgB,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,UAAA,CAAW,KAAiB,EAAV,UAAU;AJlBjB;AAO3B;;AAP2B,iBIyBX,QAAA,CAAS,KAAiB,EAAV,UAAU"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/provider/index.tsx","../src/types/index.ts","../src/hooks/useRuntimeHQ.ts","../src/hooks/useRuntimeHQState.ts","../src/hooks/useCapability.ts","../src/helpers/index.ts"],"mappings":";;;;UAMiB,sBAAA;EACf,UAAA;EACA,eAAA;EACA,QAAA,EAAU,KAAA,CAAM,SAAS;AAAA;;;;;iBAOX,iBAAA;EACd,UAAA;EACA,eAAA;EACA;AAAA,GACC,sBAAA,GAAsB,KAAA,CAAA,GAAA,CAAA,OAAA;;;UCVR,qBAAA;EACf,OAAA,EAAS,iBAAA;EACT,OAAA;EACA,KAAA,EAAO,KAAA;EACP,aAAA,GAAgB,IAAA;EAChB,kBAAA,GAAqB,IAAA,aAAiB,iBAAA;AAAA;AAAA,UAGvB,mBAAA;EACf,UAAA,EAAY,iBAAA;EACZ,KAAA,EAAO,YAAA;EACP,OAAA;EACA,aAAA;EACA,UAAA;EACA,QAAA;EACA,aAAA;EACA,MAAA;EACA,OAAA;EACA,KAAA,EAAO,KAAA;AAAA;;;;;;ADtBT;iBEIgB,YAAA,IAAgB,qBAAqB;;;UCJpC,wBAAA;EACf,UAAA;EACA,eAAe;AAAA;;;;iBAMD,iBAAA,CAAkB,OAAA,EAAS,wBAAA,GAA2B,qBAAqB;;;;;;AHR3F;;;;;;;iBIUgB,aAAA,CAAc,IAAA,WAAe,mBAAmB;;;KCd3D,UAAA,GAAa,eAAA,GAAkB,eAAA,GAAkB,cAAA;;;ALItD;iBKOgB,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,UAAA,CAAW,KAAiB,EAAV,UAAU;ALlBjB;AAO3B;;AAP2B,iBKyBX,QAAA,CAAS,KAAiB,EAAV,UAAU"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { CapabilityState, CapabilityState as CapabilityState$1, RuntimeHQClientOptions, RuntimeResponse, RuntimeResponse as RuntimeResponse$1, RuntimeState, WatchRuntimeOptions } from "@theruntimehq/js";
2
+ import { CapabilityState, CapabilityState as CapabilityState$1, RuntimeHQClientOptions, RuntimeResponse, RuntimeResponse as RuntimeResponse$1, RuntimeState as RuntimeState$1, WatchRuntimeOptions } from "@theruntimehq/js";
3
3
 
4
4
  //#region src/provider/index.d.ts
5
5
  interface RuntimeHQProviderProps {
@@ -25,6 +25,18 @@ interface RuntimeHQContextValue {
25
25
  hasCapability: (name: string) => boolean;
26
26
  getCapabilityState: (name: string) => CapabilityState$1 | undefined;
27
27
  }
28
+ interface UseCapabilityResult {
29
+ capability: CapabilityState$1 | undefined;
30
+ state: RuntimeState;
31
+ message: string;
32
+ isOperational: boolean;
33
+ isDegraded: boolean;
34
+ isOutage: boolean;
35
+ isMaintenance: boolean;
36
+ exists: boolean;
37
+ loading: boolean;
38
+ error: Error | null;
39
+ }
28
40
  //#endregion
29
41
  //#region src/hooks/useRuntimeHQ.d.ts
30
42
  /**
@@ -43,8 +55,21 @@ interface UseRuntimeHQStateOptions {
43
55
  */
44
56
  declare function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue;
45
57
  //#endregion
58
+ //#region src/hooks/useCapability.d.ts
59
+ /**
60
+ * Accesses and monitors the health state of a specific capability.
61
+ * Must be used within a `<RuntimeHQProvider>`.
62
+ *
63
+ * Implements a fail-open pattern: if the capability is not present or
64
+ * RuntimeHQ is loading/errored, the state defaults to "OPERATIONAL"
65
+ * and isOperational is true.
66
+ *
67
+ * @param name The unique name of the capability to check (e.g. "search", "payments")
68
+ */
69
+ declare function useCapability(name: string): UseCapabilityResult;
70
+ //#endregion
46
71
  //#region src/helpers/index.d.ts
47
- type StateInput = RuntimeResponse | CapabilityState | RuntimeState | null | undefined;
72
+ type StateInput = RuntimeResponse | CapabilityState | RuntimeState$1 | null | undefined;
48
73
  /**
49
74
  * Checks if the application runtime status is OPERATIONAL.
50
75
  */
@@ -62,5 +87,5 @@ declare function isDegraded(input: StateInput): boolean;
62
87
  */
63
88
  declare function isOutage(input: StateInput): boolean;
64
89
  //#endregion
65
- export { type CapabilityState, type RuntimeHQClientOptions, RuntimeHQContextValue, RuntimeHQProvider, type RuntimeHQProviderProps, type RuntimeResponse, type RuntimeState, type UseRuntimeHQStateOptions, type WatchRuntimeOptions, isDegraded, isMaintenance, isOperational, isOutage, useRuntimeHQ, useRuntimeHQState };
90
+ export { type CapabilityState, type RuntimeHQClientOptions, RuntimeHQContextValue, RuntimeHQProvider, type RuntimeHQProviderProps, type RuntimeResponse, type RuntimeState$1 as RuntimeState, UseCapabilityResult, type UseRuntimeHQStateOptions, type WatchRuntimeOptions, isDegraded, isMaintenance, isOperational, isOutage, useCapability, useRuntimeHQ, useRuntimeHQState };
66
91
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/provider/index.tsx","../src/types/index.ts","../src/hooks/useRuntimeHQ.ts","../src/hooks/useRuntimeHQState.ts","../src/helpers/index.ts"],"mappings":";;;;UAMiB,sBAAA;EACf,UAAA;EACA,eAAA;EACA,QAAA,EAAU,KAAA,CAAM,SAAS;AAAA;;;;;iBAOX,iBAAA;EACd,UAAA;EACA,eAAA;EACA;AAAA,GACC,sBAAA,GAAsB,KAAA,CAAA,GAAA,CAAA,OAAA;;;UCVR,qBAAA;EACf,OAAA,EAAS,iBAAA;EACT,OAAA;EACA,KAAA,EAAO,KAAA;EACP,aAAA,GAAgB,IAAA;EAChB,kBAAA,GAAqB,IAAA,aAAiB,iBAAA;AAAA;;;;;;ADTxC;iBEIgB,YAAA,IAAgB,qBAAqB;;;UCJpC,wBAAA;EACf,UAAA;EACA,eAAe;AAAA;;;;iBAMD,iBAAA,CAAkB,OAAA,EAAS,wBAAA,GAA2B,qBAAqB;;;KCZtF,UAAA,GAAa,eAAA,GAAkB,eAAA,GAAkB,YAAA;;;AJItD;iBIOgB,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,UAAA,CAAW,KAAiB,EAAV,UAAU;AJlBjB;AAO3B;;AAP2B,iBIyBX,QAAA,CAAS,KAAiB,EAAV,UAAU"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/provider/index.tsx","../src/types/index.ts","../src/hooks/useRuntimeHQ.ts","../src/hooks/useRuntimeHQState.ts","../src/hooks/useCapability.ts","../src/helpers/index.ts"],"mappings":";;;;UAMiB,sBAAA;EACf,UAAA;EACA,eAAA;EACA,QAAA,EAAU,KAAA,CAAM,SAAS;AAAA;;;;;iBAOX,iBAAA;EACd,UAAA;EACA,eAAA;EACA;AAAA,GACC,sBAAA,GAAsB,KAAA,CAAA,GAAA,CAAA,OAAA;;;UCVR,qBAAA;EACf,OAAA,EAAS,iBAAA;EACT,OAAA;EACA,KAAA,EAAO,KAAA;EACP,aAAA,GAAgB,IAAA;EAChB,kBAAA,GAAqB,IAAA,aAAiB,iBAAA;AAAA;AAAA,UAGvB,mBAAA;EACf,UAAA,EAAY,iBAAA;EACZ,KAAA,EAAO,YAAA;EACP,OAAA;EACA,aAAA;EACA,UAAA;EACA,QAAA;EACA,aAAA;EACA,MAAA;EACA,OAAA;EACA,KAAA,EAAO,KAAA;AAAA;;;;;;ADtBT;iBEIgB,YAAA,IAAgB,qBAAqB;;;UCJpC,wBAAA;EACf,UAAA;EACA,eAAe;AAAA;;;;iBAMD,iBAAA,CAAkB,OAAA,EAAS,wBAAA,GAA2B,qBAAqB;;;;;;AHR3F;;;;;;;iBIUgB,aAAA,CAAc,IAAA,WAAe,mBAAmB;;;KCd3D,UAAA,GAAa,eAAA,GAAkB,eAAA,GAAkB,cAAA;;;ALItD;iBKOgB,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,aAAA,CAAc,KAAiB,EAAV,UAAU;;;;iBAO/B,UAAA,CAAW,KAAiB,EAAV,UAAU;ALlBjB;AAO3B;;AAP2B,iBKyBX,QAAA,CAAS,KAAiB,EAAV,UAAU"}
package/dist/index.mjs CHANGED
@@ -11,7 +11,7 @@ const RuntimeHQContext = createContext(null);
11
11
  * A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.
12
12
  */
13
13
  function useRuntimeHQState(options) {
14
- const { runtimeKey, intervalSeconds = 15 } = options;
14
+ const { runtimeKey, intervalSeconds = 60 } = options;
15
15
  const [client, clientInitError] = useMemo(() => {
16
16
  if (!runtimeKey) return [null, /* @__PURE__ */ new Error("runtimeKey is required")];
17
17
  try {
@@ -101,6 +101,45 @@ function useRuntimeHQ() {
101
101
  return context;
102
102
  }
103
103
 
104
+ //#endregion
105
+ //#region src/hooks/useCapability.ts
106
+ /**
107
+ * Accesses and monitors the health state of a specific capability.
108
+ * Must be used within a `<RuntimeHQProvider>`.
109
+ *
110
+ * Implements a fail-open pattern: if the capability is not present or
111
+ * RuntimeHQ is loading/errored, the state defaults to "OPERATIONAL"
112
+ * and isOperational is true.
113
+ *
114
+ * @param name The unique name of the capability to check (e.g. "search", "payments")
115
+ */
116
+ function useCapability(name) {
117
+ const { getCapabilityState, hasCapability, loading, error } = useRuntimeHQ();
118
+ return useMemo(() => {
119
+ const capability = getCapabilityState(name);
120
+ const exists = hasCapability(name);
121
+ const state = capability?.state ?? "OPERATIONAL";
122
+ return {
123
+ capability,
124
+ state,
125
+ message: capability?.message ?? "",
126
+ isOperational: state === "OPERATIONAL",
127
+ isDegraded: state === "DEGRADED",
128
+ isOutage: state === "OUTAGE",
129
+ isMaintenance: state === "MAINTENANCE",
130
+ exists,
131
+ loading,
132
+ error
133
+ };
134
+ }, [
135
+ getCapabilityState,
136
+ hasCapability,
137
+ name,
138
+ loading,
139
+ error
140
+ ]);
141
+ }
142
+
104
143
  //#endregion
105
144
  //#region src/helpers/index.ts
106
145
  function getState(input) {
@@ -134,5 +173,5 @@ function isOutage(input) {
134
173
  }
135
174
 
136
175
  //#endregion
137
- export { RuntimeHQProvider, isDegraded, isMaintenance, isOperational, isOutage, useRuntimeHQ, useRuntimeHQState };
176
+ export { RuntimeHQProvider, isDegraded, isMaintenance, isOperational, isOutage, useCapability, useRuntimeHQ, useRuntimeHQState };
138
177
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/context/index.ts","../src/hooks/useRuntimeHQState.ts","../src/provider/index.tsx","../src/hooks/useRuntimeHQ.ts","../src/helpers/index.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext } from \"react\";\nimport { RuntimeHQContextValue } from \"../types\";\n\nexport const RuntimeHQContext = createContext<RuntimeHQContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, useCallback } from \"react\";\nimport { RuntimeHQClient } from \"@theruntimehq/js\";\nimport { RuntimeResponse, RuntimeHQContextValue } from \"../types\";\n\nexport interface UseRuntimeHQStateOptions {\n runtimeKey: string;\n intervalSeconds?: number;\n}\n\n/**\n * A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.\n */\nexport function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue {\n const { runtimeKey, intervalSeconds = 15 } = options;\n\n // Safely instantiate RuntimeHQClient\n const [client, clientInitError] = useMemo(() => {\n if (!runtimeKey) {\n return [null, new Error(\"runtimeKey is required\")] as const;\n }\n try {\n return [new RuntimeHQClient({ runtimeKey }), null] as const;\n } catch (err) {\n return [null, err instanceof Error ? err : new Error(String(err))] as const;\n }\n }, [runtimeKey]);\n\n const [runtime, setRuntime] = useState<RuntimeResponse | null>(null);\n const [error, setError] = useState<Error | null>(clientInitError || null);\n const [loading, setLoading] = useState<boolean>(!clientInitError);\n\n useEffect(() => {\n if (clientInitError) {\n setError(clientInitError);\n setLoading(false);\n return;\n }\n\n if (!client) {\n return;\n }\n\n // Reset states when the client or key changes\n setRuntime(null);\n setError(null);\n setLoading(true);\n\n let active = true;\n\n const unsubscribe = client.watchRuntime({\n intervalSeconds,\n onUpdate: (data) => {\n if (active) {\n setRuntime(data);\n setError(null);\n setLoading(false);\n }\n },\n onError: (err) => {\n if (active) {\n setError(err);\n setLoading(false);\n }\n },\n });\n\n return () => {\n active = false;\n unsubscribe();\n };\n }, [client, clientInitError, intervalSeconds]);\n\n const hasCapability = useCallback((name: string) => {\n return runtime ? runtime.hasCapability(name) : false;\n }, [runtime]);\n\n const getCapabilityState = useCallback((name: string) => {\n return runtime ? runtime.getCapabilityState(name) : undefined;\n }, [runtime]);\n\n return {\n runtime,\n loading,\n error,\n hasCapability,\n getCapabilityState,\n };\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { useRuntimeHQState } from \"../hooks/useRuntimeHQState\";\n\nexport interface RuntimeHQProviderProps {\n runtimeKey: string;\n intervalSeconds?: number;\n children: React.ReactNode;\n}\n\n/**\n * Context Provider that manages a global RuntimeHQ client subscription and polling loop,\n * making the status state available to all child components using `useRuntimeHQ()`.\n */\nexport function RuntimeHQProvider({\n runtimeKey,\n intervalSeconds,\n children,\n}: RuntimeHQProviderProps) {\n const value = useRuntimeHQState({ runtimeKey, intervalSeconds });\n\n return (\n <RuntimeHQContext.Provider value={value}>\n {children}\n </RuntimeHQContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { RuntimeHQContextValue } from \"../types\";\n\n/**\n * Accesses the global RuntimeHQ status check context.\n * Must be used within a `<RuntimeHQProvider>`.\n */\nexport function useRuntimeHQ(): RuntimeHQContextValue {\n const context = useContext(RuntimeHQContext);\n if (!context) {\n throw new Error(\"useRuntimeHQ must be used within a RuntimeHQProvider\");\n }\n return context;\n}\n","import { RuntimeResponse, RuntimeState, CapabilityState } from \"../types\";\n\ntype StateInput = RuntimeResponse | CapabilityState | RuntimeState | null | undefined;\n\nfunction getState(input: StateInput): RuntimeState | null {\n if (!input) return null;\n if (typeof input === \"string\") return input;\n return input.state || null;\n}\n\n/**\n * Checks if the application runtime status is OPERATIONAL.\n */\nexport function isOperational(input: StateInput): boolean {\n return getState(input) === \"OPERATIONAL\";\n}\n\n/**\n * Checks if the application runtime status is MAINTENANCE.\n */\nexport function isMaintenance(input: StateInput): boolean {\n return getState(input) === \"MAINTENANCE\";\n}\n\n/**\n * Checks if the application runtime status is DEGRADED.\n */\nexport function isDegraded(input: StateInput): boolean {\n return getState(input) === \"DEGRADED\";\n}\n\n/**\n * Checks if the application runtime status is OUTAGE.\n */\nexport function isOutage(input: StateInput): boolean {\n return getState(input) === \"OUTAGE\";\n}\n"],"mappings":";;;;;AAKA,MAAa,mBAAmB,cAA4C,IAAI;;;;;;;ACShF,SAAgB,kBAAkB,SAA0D;CAC1F,MAAM,EAAE,YAAY,kBAAkB,OAAO;CAG7C,MAAM,CAAC,QAAQ,mBAAmB,cAAc;EAC9C,IAAI,CAAC,YACH,OAAO,CAAC,sBAAM,IAAI,MAAM,wBAAwB,CAAC;EAEnD,IAAI;GACF,OAAO,CAAC,IAAI,gBAAgB,EAAE,WAAW,CAAC,GAAG,IAAI;EACnD,SAAS,KAAK;GACZ,OAAO,CAAC,MAAM,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;EACnE;CACF,GAAG,CAAC,UAAU,CAAC;CAEf,MAAM,CAAC,SAAS,cAAc,SAAiC,IAAI;CACnE,MAAM,CAAC,OAAO,YAAY,SAAuB,mBAAmB,IAAI;CACxE,MAAM,CAAC,SAAS,cAAc,SAAkB,CAAC,eAAe;CAEhE,gBAAgB;EACd,IAAI,iBAAiB;GACnB,SAAS,eAAe;GACxB,WAAW,KAAK;GAChB;EACF;EAEA,IAAI,CAAC,QACH;EAIF,WAAW,IAAI;EACf,SAAS,IAAI;EACb,WAAW,IAAI;EAEf,IAAI,SAAS;EAEb,MAAM,cAAc,OAAO,aAAa;GACtC;GACA,WAAW,SAAS;IAClB,IAAI,QAAQ;KACV,WAAW,IAAI;KACf,SAAS,IAAI;KACb,WAAW,KAAK;IAClB;GACF;GACA,UAAU,QAAQ;IAChB,IAAI,QAAQ;KACV,SAAS,GAAG;KACZ,WAAW,KAAK;IAClB;GACF;EACF,CAAC;EAED,aAAa;GACX,SAAS;GACT,YAAY;EACd;CACF,GAAG;EAAC;EAAQ;EAAiB;CAAe,CAAC;CAU7C,OAAO;EACL;EACA;EACA;EACA,eAZoB,aAAa,SAAiB;GAClD,OAAO,UAAU,QAAQ,cAAc,IAAI,IAAI;EACjD,GAAG,CAAC,OAAO,CAUG;EACZ,oBATyB,aAAa,SAAiB;GACvD,OAAO,UAAU,QAAQ,mBAAmB,IAAI,IAAI;EACtD,GAAG,CAAC,OAAO,CAOQ;CACnB;AACF;;;;;;;;ACzEA,SAAgB,kBAAkB,EAChC,YACA,iBACA,YACyB;CACzB,MAAM,QAAQ,kBAAkB;EAAE;EAAY;CAAgB,CAAC;CAE/D,OACE,oBAAC,iBAAiB,UAAlB;EAAkC;EAC/B;CACwB;AAE/B;;;;;;;;AClBA,SAAgB,eAAsC;CACpD,MAAM,UAAU,WAAW,gBAAgB;CAC3C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,sDAAsD;CAExE,OAAO;AACT;;;;ACZA,SAAS,SAAS,OAAwC;CACxD,IAAI,CAAC,OAAO,OAAO;CACnB,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,OAAO,MAAM,SAAS;AACxB;;;;AAKA,SAAgB,cAAc,OAA4B;CACxD,OAAO,SAAS,KAAK,MAAM;AAC7B;;;;AAKA,SAAgB,cAAc,OAA4B;CACxD,OAAO,SAAS,KAAK,MAAM;AAC7B;;;;AAKA,SAAgB,WAAW,OAA4B;CACrD,OAAO,SAAS,KAAK,MAAM;AAC7B;;;;AAKA,SAAgB,SAAS,OAA4B;CACnD,OAAO,SAAS,KAAK,MAAM;AAC7B"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/context/index.ts","../src/hooks/useRuntimeHQState.ts","../src/provider/index.tsx","../src/hooks/useRuntimeHQ.ts","../src/hooks/useCapability.ts","../src/helpers/index.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext } from \"react\";\nimport { RuntimeHQContextValue } from \"../types\";\n\nexport const RuntimeHQContext = createContext<RuntimeHQContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, useCallback } from \"react\";\nimport { RuntimeHQClient } from \"@theruntimehq/js\";\nimport { RuntimeResponse, RuntimeHQContextValue } from \"../types\";\n\nexport interface UseRuntimeHQStateOptions {\n runtimeKey: string;\n intervalSeconds?: number;\n}\n\n/**\n * A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.\n */\nexport function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue {\n const { runtimeKey, intervalSeconds = 60 } = options;\n\n // Safely instantiate RuntimeHQClient\n const [client, clientInitError] = useMemo(() => {\n if (!runtimeKey) {\n return [null, new Error(\"runtimeKey is required\")] as const;\n }\n try {\n return [new RuntimeHQClient({ runtimeKey }), null] as const;\n } catch (err) {\n return [null, err instanceof Error ? err : new Error(String(err))] as const;\n }\n }, [runtimeKey]);\n\n const [runtime, setRuntime] = useState<RuntimeResponse | null>(null);\n const [error, setError] = useState<Error | null>(clientInitError || null);\n const [loading, setLoading] = useState<boolean>(!clientInitError);\n\n useEffect(() => {\n if (clientInitError) {\n setError(clientInitError);\n setLoading(false);\n return;\n }\n\n if (!client) {\n return;\n }\n\n // Reset states when the client or key changes\n setRuntime(null);\n setError(null);\n setLoading(true);\n\n let active = true;\n\n const unsubscribe = client.watchRuntime({\n intervalSeconds,\n onUpdate: (data) => {\n if (active) {\n setRuntime(data);\n setError(null);\n setLoading(false);\n }\n },\n onError: (err) => {\n if (active) {\n setError(err);\n setLoading(false);\n }\n },\n });\n\n return () => {\n active = false;\n unsubscribe();\n };\n }, [client, clientInitError, intervalSeconds]);\n\n const hasCapability = useCallback((name: string) => {\n return runtime ? runtime.hasCapability(name) : false;\n }, [runtime]);\n\n const getCapabilityState = useCallback((name: string) => {\n return runtime ? runtime.getCapabilityState(name) : undefined;\n }, [runtime]);\n\n return {\n runtime,\n loading,\n error,\n hasCapability,\n getCapabilityState,\n };\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { useRuntimeHQState } from \"../hooks/useRuntimeHQState\";\n\nexport interface RuntimeHQProviderProps {\n runtimeKey: string;\n intervalSeconds?: number;\n children: React.ReactNode;\n}\n\n/**\n * Context Provider that manages a global RuntimeHQ client subscription and polling loop,\n * making the status state available to all child components using `useRuntimeHQ()`.\n */\nexport function RuntimeHQProvider({\n runtimeKey,\n intervalSeconds,\n children,\n}: RuntimeHQProviderProps) {\n const value = useRuntimeHQState({ runtimeKey, intervalSeconds });\n\n return (\n <RuntimeHQContext.Provider value={value}>\n {children}\n </RuntimeHQContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { RuntimeHQContext } from \"../context\";\nimport { RuntimeHQContextValue } from \"../types\";\n\n/**\n * Accesses the global RuntimeHQ status check context.\n * Must be used within a `<RuntimeHQProvider>`.\n */\nexport function useRuntimeHQ(): RuntimeHQContextValue {\n const context = useContext(RuntimeHQContext);\n if (!context) {\n throw new Error(\"useRuntimeHQ must be used within a RuntimeHQProvider\");\n }\n return context;\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { useRuntimeHQ } from \"./useRuntimeHQ\";\nimport { UseCapabilityResult, RuntimeState } from \"../types\";\n\n/**\n * Accesses and monitors the health state of a specific capability.\n * Must be used within a `<RuntimeHQProvider>`.\n *\n * Implements a fail-open pattern: if the capability is not present or\n * RuntimeHQ is loading/errored, the state defaults to \"OPERATIONAL\"\n * and isOperational is true.\n *\n * @param name The unique name of the capability to check (e.g. \"search\", \"payments\")\n */\nexport function useCapability(name: string): UseCapabilityResult {\n const { getCapabilityState, hasCapability, loading, error } = useRuntimeHQ();\n\n return useMemo(() => {\n const capability = getCapabilityState(name);\n const exists = hasCapability(name);\n const state: RuntimeState = capability?.state ?? \"OPERATIONAL\";\n const message = capability?.message ?? \"\";\n\n return {\n capability,\n state,\n message,\n isOperational: state === \"OPERATIONAL\",\n isDegraded: state === \"DEGRADED\",\n isOutage: state === \"OUTAGE\",\n isMaintenance: state === \"MAINTENANCE\",\n exists,\n loading,\n error,\n };\n }, [getCapabilityState, hasCapability, name, loading, error]);\n}\n","import { RuntimeResponse, RuntimeState, CapabilityState } from \"../types\";\n\ntype StateInput = RuntimeResponse | CapabilityState | RuntimeState | null | undefined;\n\nfunction getState(input: StateInput): RuntimeState | null {\n if (!input) return null;\n if (typeof input === \"string\") return input;\n return input.state || null;\n}\n\n/**\n * Checks if the application runtime status is OPERATIONAL.\n */\nexport function isOperational(input: StateInput): boolean {\n return getState(input) === \"OPERATIONAL\";\n}\n\n/**\n * Checks if the application runtime status is MAINTENANCE.\n */\nexport function isMaintenance(input: StateInput): boolean {\n return getState(input) === \"MAINTENANCE\";\n}\n\n/**\n * Checks if the application runtime status is DEGRADED.\n */\nexport function isDegraded(input: StateInput): boolean {\n return getState(input) === \"DEGRADED\";\n}\n\n/**\n * Checks if the application runtime status is OUTAGE.\n */\nexport function isOutage(input: StateInput): boolean {\n return getState(input) === \"OUTAGE\";\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theruntimehq/react",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Official React SDK for RuntimeHQ status checking and monitoring.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -43,7 +43,7 @@
43
43
  "react-dom": ">=18.0.0"
44
44
  },
45
45
  "dependencies": {
46
- "@theruntimehq/js": "^0.2.1"
46
+ "@theruntimehq/js": "^0.2.2"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@testing-library/react": "^15.0.7",