@theruntimehq/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +202 -0
- package/dist/index.d.mts +54 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +99 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TheRuntimeHQ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# @theruntimehq/react
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@theruntimehq/react)
|
|
4
|
+
[](https://github.com/TheRuntimeHQ/runtimehq-react/blob/main/LICENSE)
|
|
5
|
+
|
|
6
|
+
The official React state management SDK for [RuntimeHQ](https://theruntimehq.com). Connect your status checks directly to your React primitives.
|
|
7
|
+
|
|
8
|
+
This SDK is a **pure state management SDK** with:
|
|
9
|
+
- 🚫 **No visual UI components** (Customers use their own design systems).
|
|
10
|
+
- 🚫 **No CSS, Tailwind, or style sheet dependencies**.
|
|
11
|
+
- 🚫 **No external state libraries**.
|
|
12
|
+
- ⚛️ Full support for **React 18+ and 19+**.
|
|
13
|
+
- 🌐 Native compatibility with Server-Side Rendering (SSR), Vite, Next.js, and Remix.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Ensure you have `@theruntimehq/js` and React installed in your project:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @theruntimehq/react @theruntimehq/js
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Core Hooks & Provider APIs
|
|
28
|
+
|
|
29
|
+
### 1. Global Provider (`RuntimeHQProvider`)
|
|
30
|
+
|
|
31
|
+
Wrap your root application with the `RuntimeHQProvider`. It internally manages a single `RuntimeHQClient` and handles global state subscription and cleanup.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { RuntimeHQProvider } from "@theruntimehq/react";
|
|
35
|
+
|
|
36
|
+
export default function Root() {
|
|
37
|
+
return (
|
|
38
|
+
<RuntimeHQProvider
|
|
39
|
+
runtimeKey="rt_prod_your_key_here"
|
|
40
|
+
intervalSeconds={15}
|
|
41
|
+
>
|
|
42
|
+
<App />
|
|
43
|
+
</RuntimeHQProvider>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### Provider Props
|
|
49
|
+
| Prop | Type | Required | Default | Description |
|
|
50
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
51
|
+
| `runtimeKey` | `string` | **Yes** | - | Your RuntimeHQ API status key (must start with `rt_prod_` or `rt_test_`). |
|
|
52
|
+
| `intervalSeconds` | `number` | No | `15` | Polling interval for updates in seconds. |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### 2. Context Hook (`useRuntimeHQ`)
|
|
57
|
+
|
|
58
|
+
Consume the global status state anywhere inside the provider.
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { useRuntimeHQ, isOperational } from "@theruntimehq/react";
|
|
62
|
+
|
|
63
|
+
function StatusBanner() {
|
|
64
|
+
const { runtime, loading, error } = useRuntimeHQ();
|
|
65
|
+
|
|
66
|
+
if (loading) return <div>Checking status...</div>;
|
|
67
|
+
if (error) return <div>Error fetching status: {error.message}</div>;
|
|
68
|
+
if (!runtime || isOperational(runtime)) return null;
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div className={`banner ${runtime.state.toLowerCase()}`}>
|
|
72
|
+
⚠️ {runtime.message}
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### Return Value
|
|
79
|
+
```typescript
|
|
80
|
+
interface RuntimeHQContextValue {
|
|
81
|
+
runtime: RuntimeResponse | null; // Detailed status info or null before first fetch
|
|
82
|
+
loading: boolean; // true until the first fetch (success or failure) completes
|
|
83
|
+
error: Error | null; // Captured network or validation error (if any)
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
> [!IMPORTANT]
|
|
88
|
+
> If `useRuntimeHQ` is invoked outside a `<RuntimeHQProvider>`, it throws a descriptive error:
|
|
89
|
+
> `useRuntimeHQ must be used within a RuntimeHQProvider`
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### 3. Standalone Direct Hook (`useRuntimeHQState`)
|
|
94
|
+
|
|
95
|
+
If you want to read runtime status inside isolated widgets without setting up a context provider at the root level, use `useRuntimeHQState`. It shares the same state management and cleanup logic as the provider.
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { useRuntimeHQState } from "@theruntimehq/react";
|
|
99
|
+
|
|
100
|
+
function IndependentWidget() {
|
|
101
|
+
const { runtime, loading, error } = useRuntimeHQState({
|
|
102
|
+
runtimeKey: "rt_prod_your_key_here",
|
|
103
|
+
intervalSeconds: 30,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (loading) return <Spinner />;
|
|
107
|
+
return <div>State: {runtime?.state}</div>;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Convenience Helpers
|
|
114
|
+
|
|
115
|
+
Quickly determine states using utility checkers. These accept either the full `RuntimeResponse` object, the `RuntimeState` string, or `null`/`undefined`.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import {
|
|
119
|
+
isOperational,
|
|
120
|
+
isMaintenance,
|
|
121
|
+
isDegraded,
|
|
122
|
+
isOutage
|
|
123
|
+
} from "@theruntimehq/react";
|
|
124
|
+
|
|
125
|
+
// Usage
|
|
126
|
+
isOperational(runtime) // returns boolean
|
|
127
|
+
isMaintenance(runtime) // returns boolean
|
|
128
|
+
isDegraded(runtime) // returns boolean
|
|
129
|
+
isOutage(runtime) // returns boolean
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Server Rendering (SSR) & Next.js App Router Integration
|
|
135
|
+
|
|
136
|
+
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:
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
// src/app/page.tsx (Next.js Server Component)
|
|
140
|
+
import { RuntimeHQClient } from "@theruntimehq/js";
|
|
141
|
+
import ClientSidePoller from "./ClientSidePoller";
|
|
142
|
+
|
|
143
|
+
export default async function Page() {
|
|
144
|
+
const client = new RuntimeHQClient({ runtimeKey: process.env.RUNTIMEHQ_KEY! });
|
|
145
|
+
let initialRuntime = null;
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
initialRuntime = await client.getRuntime();
|
|
149
|
+
} catch (err) {
|
|
150
|
+
// Fail-open: ignore server-side fetch errors during build/request
|
|
151
|
+
console.error("Failed to check status during SSR:", err);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<main>
|
|
156
|
+
{/* 1. SSR Static Layout (Zero layout shift on load) */}
|
|
157
|
+
{initialRuntime && initialRuntime.state !== "OPERATIONAL" && (
|
|
158
|
+
<div className="banner">
|
|
159
|
+
⚠️ {initialRuntime.message}
|
|
160
|
+
</div>
|
|
161
|
+
)}
|
|
162
|
+
|
|
163
|
+
{/* 2. Client Side Poller (Handles live updates) */}
|
|
164
|
+
<ClientSidePoller initialData={initialRuntime} />
|
|
165
|
+
</main>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
// src/app/ClientSidePoller.tsx (Client Component)
|
|
172
|
+
"use client";
|
|
173
|
+
|
|
174
|
+
import { useRuntimeHQState } from "@theruntimehq/react";
|
|
175
|
+
import type { RuntimeResponse } from "@theruntimehq/react";
|
|
176
|
+
|
|
177
|
+
interface ClientSidePollerProps {
|
|
178
|
+
initialData: RuntimeResponse | null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export default function ClientSidePoller({ initialData }: ClientSidePollerProps) {
|
|
182
|
+
const { runtime } = useRuntimeHQState({
|
|
183
|
+
runtimeKey: "rt_prod_your_key_here",
|
|
184
|
+
intervalSeconds: 15,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Hydrate client-side with server-fetched data initially
|
|
188
|
+
const currentRuntime = runtime || initialData;
|
|
189
|
+
|
|
190
|
+
if (!currentRuntime || currentRuntime.state === "OPERATIONAL") return null;
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<div className="interactive-status">
|
|
194
|
+
Status is {currentRuntime.state} (Polled: {runtime ? "Yes" : "No"})
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { RuntimeResponse, RuntimeState } from '@theruntimehq/js';
|
|
3
|
+
export { RuntimeHQClientOptions, RuntimeResponse, RuntimeSourceType, RuntimeState, WatchRuntimeOptions } from '@theruntimehq/js';
|
|
4
|
+
|
|
5
|
+
interface RuntimeHQProviderProps {
|
|
6
|
+
runtimeKey: string;
|
|
7
|
+
intervalSeconds?: number;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Context Provider that manages a global RuntimeHQ client subscription and polling loop,
|
|
12
|
+
* making the status state available to all child components using `useRuntimeHQ()`.
|
|
13
|
+
*/
|
|
14
|
+
declare function RuntimeHQProvider({ runtimeKey, intervalSeconds, children, }: RuntimeHQProviderProps): React.JSX.Element;
|
|
15
|
+
|
|
16
|
+
interface RuntimeHQContextValue {
|
|
17
|
+
runtime: RuntimeResponse | null;
|
|
18
|
+
loading: boolean;
|
|
19
|
+
error: Error | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Accesses the global RuntimeHQ status check context.
|
|
24
|
+
* Must be used within a `<RuntimeHQProvider>`.
|
|
25
|
+
*/
|
|
26
|
+
declare function useRuntimeHQ(): RuntimeHQContextValue;
|
|
27
|
+
|
|
28
|
+
interface UseRuntimeHQStateOptions {
|
|
29
|
+
runtimeKey: string;
|
|
30
|
+
intervalSeconds?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.
|
|
34
|
+
*/
|
|
35
|
+
declare function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the application runtime status is OPERATIONAL.
|
|
39
|
+
*/
|
|
40
|
+
declare function isOperational(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Checks if the application runtime status is MAINTENANCE.
|
|
43
|
+
*/
|
|
44
|
+
declare function isMaintenance(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Checks if the application runtime status is DEGRADED.
|
|
47
|
+
*/
|
|
48
|
+
declare function isDegraded(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if the application runtime status is OUTAGE.
|
|
51
|
+
*/
|
|
52
|
+
declare function isOutage(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
53
|
+
|
|
54
|
+
export { type RuntimeHQContextValue, RuntimeHQProvider, type RuntimeHQProviderProps, type UseRuntimeHQStateOptions, isDegraded, isMaintenance, isOperational, isOutage, useRuntimeHQ, useRuntimeHQState };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { RuntimeResponse, RuntimeState } from '@theruntimehq/js';
|
|
3
|
+
export { RuntimeHQClientOptions, RuntimeResponse, RuntimeSourceType, RuntimeState, WatchRuntimeOptions } from '@theruntimehq/js';
|
|
4
|
+
|
|
5
|
+
interface RuntimeHQProviderProps {
|
|
6
|
+
runtimeKey: string;
|
|
7
|
+
intervalSeconds?: number;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Context Provider that manages a global RuntimeHQ client subscription and polling loop,
|
|
12
|
+
* making the status state available to all child components using `useRuntimeHQ()`.
|
|
13
|
+
*/
|
|
14
|
+
declare function RuntimeHQProvider({ runtimeKey, intervalSeconds, children, }: RuntimeHQProviderProps): React.JSX.Element;
|
|
15
|
+
|
|
16
|
+
interface RuntimeHQContextValue {
|
|
17
|
+
runtime: RuntimeResponse | null;
|
|
18
|
+
loading: boolean;
|
|
19
|
+
error: Error | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Accesses the global RuntimeHQ status check context.
|
|
24
|
+
* Must be used within a `<RuntimeHQProvider>`.
|
|
25
|
+
*/
|
|
26
|
+
declare function useRuntimeHQ(): RuntimeHQContextValue;
|
|
27
|
+
|
|
28
|
+
interface UseRuntimeHQStateOptions {
|
|
29
|
+
runtimeKey: string;
|
|
30
|
+
intervalSeconds?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A direct React hook to fetch and watch RuntimeHQ status without using a Context Provider.
|
|
34
|
+
*/
|
|
35
|
+
declare function useRuntimeHQState(options: UseRuntimeHQStateOptions): RuntimeHQContextValue;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the application runtime status is OPERATIONAL.
|
|
39
|
+
*/
|
|
40
|
+
declare function isOperational(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Checks if the application runtime status is MAINTENANCE.
|
|
43
|
+
*/
|
|
44
|
+
declare function isMaintenance(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Checks if the application runtime status is DEGRADED.
|
|
47
|
+
*/
|
|
48
|
+
declare function isDegraded(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if the application runtime status is OUTAGE.
|
|
51
|
+
*/
|
|
52
|
+
declare function isOutage(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean;
|
|
53
|
+
|
|
54
|
+
export { type RuntimeHQContextValue, RuntimeHQProvider, type RuntimeHQProviderProps, type UseRuntimeHQStateOptions, isDegraded, isMaintenance, isOperational, isOutage, useRuntimeHQ, useRuntimeHQState };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var js = require('@theruntimehq/js');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// src/context/index.ts
|
|
8
|
+
var RuntimeHQContext = react.createContext(null);
|
|
9
|
+
function useRuntimeHQState(options) {
|
|
10
|
+
const { runtimeKey, intervalSeconds = 15 } = options;
|
|
11
|
+
const [client, clientInitError] = react.useMemo(() => {
|
|
12
|
+
if (!runtimeKey) {
|
|
13
|
+
return [null, new Error("runtimeKey is required")];
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return [new js.RuntimeHQClient({ runtimeKey }), null];
|
|
17
|
+
} catch (err) {
|
|
18
|
+
return [null, err instanceof Error ? err : new Error(String(err))];
|
|
19
|
+
}
|
|
20
|
+
}, [runtimeKey]);
|
|
21
|
+
const [runtime, setRuntime] = react.useState(null);
|
|
22
|
+
const [error, setError] = react.useState(clientInitError || null);
|
|
23
|
+
const [loading, setLoading] = react.useState(!clientInitError);
|
|
24
|
+
react.useEffect(() => {
|
|
25
|
+
if (clientInitError) {
|
|
26
|
+
setError(clientInitError);
|
|
27
|
+
setLoading(false);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!client) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
setRuntime(null);
|
|
34
|
+
setError(null);
|
|
35
|
+
setLoading(true);
|
|
36
|
+
let active = true;
|
|
37
|
+
const unsubscribe = client.watchRuntime({
|
|
38
|
+
intervalSeconds,
|
|
39
|
+
onUpdate: (data) => {
|
|
40
|
+
if (active) {
|
|
41
|
+
setRuntime(data);
|
|
42
|
+
setError(null);
|
|
43
|
+
setLoading(false);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
onError: (err) => {
|
|
47
|
+
if (active) {
|
|
48
|
+
setError(err);
|
|
49
|
+
setLoading(false);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return () => {
|
|
54
|
+
active = false;
|
|
55
|
+
unsubscribe();
|
|
56
|
+
};
|
|
57
|
+
}, [client, clientInitError, intervalSeconds]);
|
|
58
|
+
return {
|
|
59
|
+
runtime,
|
|
60
|
+
loading,
|
|
61
|
+
error
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function RuntimeHQProvider({
|
|
65
|
+
runtimeKey,
|
|
66
|
+
intervalSeconds,
|
|
67
|
+
children
|
|
68
|
+
}) {
|
|
69
|
+
const value = useRuntimeHQState({ runtimeKey, intervalSeconds });
|
|
70
|
+
return /* @__PURE__ */ jsxRuntime.jsx(RuntimeHQContext.Provider, { value, children });
|
|
71
|
+
}
|
|
72
|
+
function useRuntimeHQ() {
|
|
73
|
+
const context = react.useContext(RuntimeHQContext);
|
|
74
|
+
if (!context) {
|
|
75
|
+
throw new Error("useRuntimeHQ must be used within a RuntimeHQProvider");
|
|
76
|
+
}
|
|
77
|
+
return context;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/helpers/index.ts
|
|
81
|
+
function getState(runtime) {
|
|
82
|
+
if (!runtime) return null;
|
|
83
|
+
if (typeof runtime === "string") return runtime;
|
|
84
|
+
return runtime.state || null;
|
|
85
|
+
}
|
|
86
|
+
function isOperational(runtime) {
|
|
87
|
+
return getState(runtime) === "OPERATIONAL";
|
|
88
|
+
}
|
|
89
|
+
function isMaintenance(runtime) {
|
|
90
|
+
return getState(runtime) === "MAINTENANCE";
|
|
91
|
+
}
|
|
92
|
+
function isDegraded(runtime) {
|
|
93
|
+
return getState(runtime) === "DEGRADED";
|
|
94
|
+
}
|
|
95
|
+
function isOutage(runtime) {
|
|
96
|
+
return getState(runtime) === "OUTAGE";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
exports.RuntimeHQProvider = RuntimeHQProvider;
|
|
100
|
+
exports.isDegraded = isDegraded;
|
|
101
|
+
exports.isMaintenance = isMaintenance;
|
|
102
|
+
exports.isOperational = isOperational;
|
|
103
|
+
exports.isOutage = isOutage;
|
|
104
|
+
exports.useRuntimeHQ = useRuntimeHQ;
|
|
105
|
+
exports.useRuntimeHQState = useRuntimeHQState;
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
107
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context/index.ts","../src/hooks/useRuntimeHQState.ts","../src/provider/index.tsx","../src/hooks/useRuntimeHQ.ts","../src/helpers/index.ts"],"names":["createContext","useMemo","RuntimeHQClient","useState","useEffect","jsx","useContext"],"mappings":"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","file":"index.js","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 } 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 return {\n runtime,\n loading,\n error,\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 } from \"../types\";\n\nfunction getState(runtime: RuntimeResponse | RuntimeState | null | undefined): RuntimeState | null {\n if (!runtime) return null;\n if (typeof runtime === \"string\") return runtime;\n return runtime.state || null;\n}\n\n/**\n * Checks if the application runtime status is OPERATIONAL.\n */\nexport function isOperational(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"OPERATIONAL\";\n}\n\n/**\n * Checks if the application runtime status is MAINTENANCE.\n */\nexport function isMaintenance(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"MAINTENANCE\";\n}\n\n/**\n * Checks if the application runtime status is DEGRADED.\n */\nexport function isDegraded(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"DEGRADED\";\n}\n\n/**\n * Checks if the application runtime status is OUTAGE.\n */\nexport function isOutage(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"OUTAGE\";\n}\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createContext, useMemo, useState, useEffect, useContext } from 'react';
|
|
2
|
+
import { RuntimeHQClient } from '@theruntimehq/js';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/context/index.ts
|
|
6
|
+
var RuntimeHQContext = createContext(null);
|
|
7
|
+
function useRuntimeHQState(options) {
|
|
8
|
+
const { runtimeKey, intervalSeconds = 15 } = options;
|
|
9
|
+
const [client, clientInitError] = useMemo(() => {
|
|
10
|
+
if (!runtimeKey) {
|
|
11
|
+
return [null, new Error("runtimeKey is required")];
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
return [new RuntimeHQClient({ runtimeKey }), null];
|
|
15
|
+
} catch (err) {
|
|
16
|
+
return [null, err instanceof Error ? err : new Error(String(err))];
|
|
17
|
+
}
|
|
18
|
+
}, [runtimeKey]);
|
|
19
|
+
const [runtime, setRuntime] = useState(null);
|
|
20
|
+
const [error, setError] = useState(clientInitError || null);
|
|
21
|
+
const [loading, setLoading] = useState(!clientInitError);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (clientInitError) {
|
|
24
|
+
setError(clientInitError);
|
|
25
|
+
setLoading(false);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (!client) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
setRuntime(null);
|
|
32
|
+
setError(null);
|
|
33
|
+
setLoading(true);
|
|
34
|
+
let active = true;
|
|
35
|
+
const unsubscribe = client.watchRuntime({
|
|
36
|
+
intervalSeconds,
|
|
37
|
+
onUpdate: (data) => {
|
|
38
|
+
if (active) {
|
|
39
|
+
setRuntime(data);
|
|
40
|
+
setError(null);
|
|
41
|
+
setLoading(false);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
onError: (err) => {
|
|
45
|
+
if (active) {
|
|
46
|
+
setError(err);
|
|
47
|
+
setLoading(false);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return () => {
|
|
52
|
+
active = false;
|
|
53
|
+
unsubscribe();
|
|
54
|
+
};
|
|
55
|
+
}, [client, clientInitError, intervalSeconds]);
|
|
56
|
+
return {
|
|
57
|
+
runtime,
|
|
58
|
+
loading,
|
|
59
|
+
error
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function RuntimeHQProvider({
|
|
63
|
+
runtimeKey,
|
|
64
|
+
intervalSeconds,
|
|
65
|
+
children
|
|
66
|
+
}) {
|
|
67
|
+
const value = useRuntimeHQState({ runtimeKey, intervalSeconds });
|
|
68
|
+
return /* @__PURE__ */ jsx(RuntimeHQContext.Provider, { value, children });
|
|
69
|
+
}
|
|
70
|
+
function useRuntimeHQ() {
|
|
71
|
+
const context = useContext(RuntimeHQContext);
|
|
72
|
+
if (!context) {
|
|
73
|
+
throw new Error("useRuntimeHQ must be used within a RuntimeHQProvider");
|
|
74
|
+
}
|
|
75
|
+
return context;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/helpers/index.ts
|
|
79
|
+
function getState(runtime) {
|
|
80
|
+
if (!runtime) return null;
|
|
81
|
+
if (typeof runtime === "string") return runtime;
|
|
82
|
+
return runtime.state || null;
|
|
83
|
+
}
|
|
84
|
+
function isOperational(runtime) {
|
|
85
|
+
return getState(runtime) === "OPERATIONAL";
|
|
86
|
+
}
|
|
87
|
+
function isMaintenance(runtime) {
|
|
88
|
+
return getState(runtime) === "MAINTENANCE";
|
|
89
|
+
}
|
|
90
|
+
function isDegraded(runtime) {
|
|
91
|
+
return getState(runtime) === "DEGRADED";
|
|
92
|
+
}
|
|
93
|
+
function isOutage(runtime) {
|
|
94
|
+
return getState(runtime) === "OUTAGE";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { RuntimeHQProvider, isDegraded, isMaintenance, isOperational, isOutage, useRuntimeHQ, useRuntimeHQState };
|
|
98
|
+
//# sourceMappingURL=index.mjs.map
|
|
99
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context/index.ts","../src/hooks/useRuntimeHQState.ts","../src/provider/index.tsx","../src/hooks/useRuntimeHQ.ts","../src/helpers/index.ts"],"names":[],"mappings":"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","file":"index.mjs","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 } 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 return {\n runtime,\n loading,\n error,\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 } from \"../types\";\n\nfunction getState(runtime: RuntimeResponse | RuntimeState | null | undefined): RuntimeState | null {\n if (!runtime) return null;\n if (typeof runtime === \"string\") return runtime;\n return runtime.state || null;\n}\n\n/**\n * Checks if the application runtime status is OPERATIONAL.\n */\nexport function isOperational(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"OPERATIONAL\";\n}\n\n/**\n * Checks if the application runtime status is MAINTENANCE.\n */\nexport function isMaintenance(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"MAINTENANCE\";\n}\n\n/**\n * Checks if the application runtime status is DEGRADED.\n */\nexport function isDegraded(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"DEGRADED\";\n}\n\n/**\n * Checks if the application runtime status is OUTAGE.\n */\nexport function isOutage(runtime: RuntimeResponse | RuntimeState | null | undefined): boolean {\n return getState(runtime) === \"OUTAGE\";\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@theruntimehq/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official React SDK for RuntimeHQ status checking and monitoring.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"import": "./dist/index.mjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"runtimehq",
|
|
25
|
+
"status",
|
|
26
|
+
"monitoring",
|
|
27
|
+
"sdk",
|
|
28
|
+
"react",
|
|
29
|
+
"hooks"
|
|
30
|
+
],
|
|
31
|
+
"author": "RuntimeHQ",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/TheRuntimeHQ/runtimehq-react.git"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"react": ">=18.0.0",
|
|
39
|
+
"react-dom": ">=18.0.0"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@theruntimehq/js": "^0.1.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@testing-library/react": "^15.0.7",
|
|
46
|
+
"@types/react": "^18.2.79",
|
|
47
|
+
"@types/react-dom": "^18.2.25",
|
|
48
|
+
"jsdom": "^24.0.0",
|
|
49
|
+
"react": "^18.2.0",
|
|
50
|
+
"react-dom": "^18.2.0",
|
|
51
|
+
"tsup": "^8.0.2",
|
|
52
|
+
"typescript": "^5.4.5",
|
|
53
|
+
"vitest": "^1.6.0"
|
|
54
|
+
}
|
|
55
|
+
}
|