Skip to content

Commit 0ec1abc

Browse files
authored
fix: transport (#17)
* feat: support custom transport for edge runtimes, export service descriptors * feat: switch default transport to connect-web (drop connect-node)
1 parent 905587f commit 0ec1abc

8 files changed

Lines changed: 163 additions & 49 deletions

File tree

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"imports": {
2121
"@bufbuild/protobuf": "npm:@bufbuild/protobuf@^2.11.0",
2222
"@connectrpc/connect": "npm:@connectrpc/connect@^2.1.1",
23-
"@connectrpc/connect-node": "npm:@connectrpc/connect-node@^2.1.1"
23+
"@connectrpc/connect-web": "npm:@connectrpc/connect-web@^2.1.1"
2424
},
2525
"compilerOptions": {
2626
"strict": true,

deno.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/getting-started.md

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,49 @@ console.log(`Found ${totalSize} monitors`);
6363

6464
## Runtime Support
6565

66-
| Runtime | Version | Module Format |
67-
| ------- | ------- | ------------- |
68-
| Node.js | >= 18 | ESM and CJS |
69-
| Deno | >= 2 | ESM (native) |
70-
| Bun | Latest | ESM |
66+
The SDK talks to the API over a fetch-based Connect transport
67+
(`@connectrpc/connect-web`), so it runs on any runtime with a global `fetch`
68+
no HTTP/2 or `node:*` modules required:
69+
70+
| Runtime | Version | Module Format |
71+
| ------------------ | ------- | ------------- |
72+
| Node.js | >= 18 | ESM and CJS |
73+
| Deno | >= 2 | ESM (native) |
74+
| Bun | Latest | ESM |
75+
| Cloudflare Workers || ESM (edge) |
76+
77+
### Cloudflare Workers and edge runtimes
78+
79+
The default client works on the edge as-is. The one caveat is that
80+
`@connectrpc/connect-web` issues requests with `redirect: "error"`, which
81+
`workerd` doesn't implement. If you hit
82+
`The redirect mode 'error' is not supported`, pass a transport with a
83+
redirect-tolerant `fetch` (the SDK re-exports `createAuthInterceptor` and the
84+
service descriptors for this):
85+
86+
```typescript
87+
import { createConnectTransport } from "@connectrpc/connect-web";
88+
import {
89+
createAuthInterceptor,
90+
createOpenStatusClient,
91+
} from "@openstatus/sdk-node";
92+
93+
const client = createOpenStatusClient({
94+
transport: createConnectTransport({
95+
baseUrl: "https://api.openstatus.dev/rpc",
96+
interceptors: [createAuthInterceptor(env.OPENSTATUS_API_KEY)],
97+
// workerd doesn't implement fetch's `redirect: "error"`; normalise it.
98+
fetch: (input, init) =>
99+
fetch(
100+
input,
101+
init?.redirect === "error" ? { ...init, redirect: "manual" } : init,
102+
),
103+
}),
104+
});
105+
```
106+
107+
When you pass a `transport`, the `apiKey` and `baseUrl` options are ignored —
108+
configure authentication on the transport via `createAuthInterceptor`.
71109

72110
## Full Workflow Example
73111

docs/monitor-service.md

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Monitor Service
44

5-
Manage HTTP, TCP, and DNS monitors. The Monitor Service provides 14 RPC methods
5+
Manage HTTP, TCP, and DNS monitors. The Monitor Service provides 15 RPC methods
66
for creating, updating, listing, triggering, deleting, querying monitor status
77
and metrics, and inspecting HTTP response logs.
88

@@ -80,7 +80,7 @@ Updates are partial — only include the fields you want to change.
8080

8181
```typescript
8282
const { monitor } = await client.monitor.v1.MonitorService.updateHTTPMonitor({
83-
id: "mon_123",
83+
id: "123456",
8484
monitor: {
8585
name: "Updated API Monitor",
8686
active: false,
@@ -141,7 +141,7 @@ const { monitor } = await client.monitor.v1.MonitorService.createTCPMonitor({
141141

142142
```typescript
143143
const { monitor } = await client.monitor.v1.MonitorService.updateTCPMonitor({
144-
id: "mon_123",
144+
id: "123456",
145145
monitor: {
146146
name: "Updated Database Monitor",
147147
},
@@ -207,7 +207,7 @@ const { monitor } = await client.monitor.v1.MonitorService.createDNSMonitor({
207207

208208
```typescript
209209
const { monitor } = await client.monitor.v1.MonitorService.updateDNSMonitor({
210-
id: "mon_123",
210+
id: "123456",
211211
monitor: {
212212
name: "Updated DNS Check",
213213
},
@@ -263,7 +263,7 @@ contains one of HTTP, TCP, or DNS configuration.
263263

264264
```typescript
265265
const { monitor } = await client.monitor.v1.MonitorService.getMonitor({
266-
id: "mon_123",
266+
id: "123456",
267267
});
268268

269269
if (monitor?.config.case === "http") {
@@ -287,7 +287,7 @@ Trigger an immediate check for a monitor.
287287

288288
```typescript
289289
const { success } = await client.monitor.v1.MonitorService.triggerMonitor({
290-
id: "mon_123",
290+
id: "123456",
291291
});
292292

293293
console.log(`Trigger successful: ${success}`);
@@ -297,7 +297,7 @@ console.log(`Trigger successful: ${success}`);
297297

298298
```typescript
299299
const { success } = await client.monitor.v1.MonitorService.deleteMonitor({
300-
id: "mon_123",
300+
id: "123456",
301301
});
302302
```
303303

@@ -317,7 +317,7 @@ const client = createOpenStatusClient({
317317
});
318318

319319
const { id, regions } = await client.monitor.v1.MonitorService.getMonitorStatus(
320-
{ id: "mon_123" },
320+
{ id: "123456" },
321321
);
322322

323323
for (const { region, status } of regions) {
@@ -337,7 +337,7 @@ const client = createOpenStatusClient({
337337
});
338338

339339
const summary = await client.monitor.v1.MonitorService.getMonitorSummary({
340-
id: "mon_123",
340+
id: "123456",
341341
timeRange: TimeRange.TIME_RANGE_7D,
342342
regions: [],
343343
});
@@ -358,11 +358,61 @@ The latency fields (`p50`, `p75`, `p90`, `p95`, `p99`) and count fields
358358
`regions` parameter is optional — pass an empty array to get metrics across all
359359
regions.
360360

361+
`getMonitorSummary` returns a single aggregate over the window and `TimeRange`
362+
caps at 14 days. For a per-day series (e.g. to render status bars), use
363+
`getMonitorDailySummary` below.
364+
365+
## Get Monitor Daily Summary
366+
367+
Get per-day status buckets for one or more monitors over the last N days (max
368+
45). Each bucket is tagged with its `monitorId`, so you can render a status bar
369+
per monitor.
370+
371+
```typescript
372+
import { createOpenStatusClient } from "@openstatus/sdk-node";
373+
374+
const client = createOpenStatusClient({
375+
apiKey: process.env.OPENSTATUS_API_KEY,
376+
});
377+
378+
const { dailyStats } = await client.monitor.v1.MonitorService
379+
.getMonitorDailySummary({
380+
monitorIds: ["123456", "123457"],
381+
days: 45,
382+
});
383+
384+
for (const stat of dailyStats) {
385+
console.log(
386+
`[${stat.monitorId}] ${stat.day}: ` +
387+
`${stat.ok}/${stat.count} ok, ${stat.degraded} degraded, ${stat.error} error`,
388+
);
389+
}
390+
```
391+
392+
Request parameters:
393+
394+
| Parameter | Type | Description |
395+
| ------------ | ----------------- | ---------------------------------------------------- |
396+
| `monitorIds` | string[] | One or more monitor IDs (1–50, required) |
397+
| `days` | number (optional) | Days to return (1–45, default 45; values >45 reject) |
398+
399+
Each `MonitorDailyStat` has `monitorId`, `day` (RFC 3339, UTC midnight), and the
400+
`bigint` counts `count`, `ok`, `degraded`, `error`. Days with no checks are
401+
omitted — fill gaps client-side. Daily data is retained for 45 days.
402+
403+
> The REST endpoint `GET /v1/monitor/{id}/summary` also returns a daily series,
404+
> but only `{ ok, count, day }` for a single monitor. Prefer
405+
> `getMonitorDailySummary` — it is multi-monitor and includes
406+
> `degraded`/`error`.
407+
361408
## List Monitor HTTP Response Logs
362409

363410
List HTTP response logs for a monitor within the 14-day retention window.
364411
Supports time-window filtering and offset-based pagination.
365412

413+
> Response logs are a paid feature. On the free plan these methods return
414+
> `permission_denied` ("Upgrade for response logs").
415+
366416
```typescript
367417
import {
368418
createOpenStatusClient,
@@ -377,7 +427,7 @@ const client = createOpenStatusClient({
377427

378428
const { logs, pagination } = await client.monitor.v1.MonitorService
379429
.listMonitorHTTPResponseLogs({
380-
id: "mon_123",
430+
id: "123456",
381431
fromTimestamp: BigInt(Date.now() - 24 * 60 * 60 * 1000),
382432
toTimestamp: BigInt(Date.now()),
383433
limit: 25,
@@ -421,7 +471,7 @@ redacted response headers, error message, and serialized assertions.
421471
```typescript
422472
const { log } = await client.monitor.v1.MonitorService
423473
.getMonitorHTTPResponseLog({
424-
id: "mon_123",
474+
id: "123456",
425475
logId: "log_456",
426476
});
427477

docs/notification-service.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const { notification } = await client.notification.v1.NotificationService
2727
value: { webhookUrl: "https://hooks.slack.com/services/..." },
2828
},
2929
},
30-
monitorIds: ["mon_123", "mon_456"],
30+
monitorIds: ["123456", "123457"],
3131
});
3232

3333
console.log(`Notification created: ${notification?.id}`);
@@ -55,7 +55,7 @@ const { notification } = await client.notification.v1.NotificationService
5555
value: { webhookUrl: "https://hooks.slack.com/services/..." },
5656
},
5757
},
58-
monitorIds: ["mon_123"],
58+
monitorIds: ["123456"],
5959
});
6060
```
6161

@@ -72,7 +72,7 @@ const { notification } = await client.notification.v1.NotificationService
7272
value: { webhookUrl: "https://discord.com/api/webhooks/..." },
7373
},
7474
},
75-
monitorIds: ["mon_123"],
75+
monitorIds: ["123456"],
7676
});
7777
```
7878

@@ -89,7 +89,7 @@ const { notification } = await client.notification.v1.NotificationService
8989
value: { email: "alerts@example.com" },
9090
},
9191
},
92-
monitorIds: ["mon_123"],
92+
monitorIds: ["123456"],
9393
});
9494
```
9595

@@ -106,7 +106,7 @@ const { notification } = await client.notification.v1.NotificationService
106106
value: { integrationKey: "your-integration-key" },
107107
},
108108
},
109-
monitorIds: ["mon_123"],
109+
monitorIds: ["123456"],
110110
});
111111
```
112112

@@ -125,7 +125,7 @@ const { notification } = await client.notification.v1.NotificationService
125125
value: { apiKey: "your-api-key", region: OpsgenieRegion.US },
126126
},
127127
},
128-
monitorIds: ["mon_123"],
128+
monitorIds: ["123456"],
129129
});
130130
```
131131

@@ -142,7 +142,7 @@ const { notification } = await client.notification.v1.NotificationService
142142
value: { chatId: "123456789" },
143143
},
144144
},
145-
monitorIds: ["mon_123"],
145+
monitorIds: ["123456"],
146146
});
147147
```
148148

@@ -159,7 +159,7 @@ const { notification } = await client.notification.v1.NotificationService
159159
value: { webhookUrl: "https://chat.googleapis.com/v1/spaces/..." },
160160
},
161161
},
162-
monitorIds: ["mon_123"],
162+
monitorIds: ["123456"],
163163
});
164164
```
165165

@@ -176,7 +176,7 @@ const { notification } = await client.notification.v1.NotificationService
176176
value: { webhookUrl: "https://oncall.example.com/..." },
177177
},
178178
},
179-
monitorIds: ["mon_123"],
179+
monitorIds: ["123456"],
180180
});
181181
```
182182

@@ -197,7 +197,7 @@ const { notification } = await client.notification.v1.NotificationService
197197
},
198198
},
199199
},
200-
monitorIds: ["mon_123"],
200+
monitorIds: ["123456"],
201201
});
202202
```
203203

@@ -214,7 +214,7 @@ const { notification } = await client.notification.v1.NotificationService
214214
value: { phoneNumber: "+1234567890" },
215215
},
216216
},
217-
monitorIds: ["mon_123"],
217+
monitorIds: ["123456"],
218218
});
219219
```
220220

@@ -231,7 +231,7 @@ const { notification } = await client.notification.v1.NotificationService
231231
value: { phoneNumber: "+1234567890" },
232232
},
233233
},
234-
monitorIds: ["mon_123"],
234+
monitorIds: ["123456"],
235235
});
236236
```
237237

@@ -253,7 +253,7 @@ const { notification } = await client.notification.v1.NotificationService
253253
},
254254
},
255255
},
256-
monitorIds: ["mon_123"],
256+
monitorIds: ["123456"],
257257
});
258258
```
259259

@@ -276,7 +276,7 @@ const { notification } = await client.notification.v1.NotificationService
276276
},
277277
},
278278
},
279-
monitorIds: ["mon_123"],
279+
monitorIds: ["123456"],
280280
});
281281
```
282282

@@ -349,7 +349,7 @@ const { notification } = await client.notification.v1.NotificationService
349349
.updateNotification({
350350
id: "notif_123",
351351
name: "Updated Slack Alerts",
352-
monitorIds: ["mon_123", "mon_456", "mon_789"],
352+
monitorIds: ["123456", "123457", "123458"],
353353
});
354354
```
355355

0 commit comments

Comments
 (0)