Openstatus sdk www.openstatus.dev

feat: Add createOpenStatusClient factory for reusable auth configuration (#10)

Add a new `createOpenStatusClient(options)` factory function that allows
users to configure authentication once and reuse it across all API calls,
eliminating the need to pass headers on every request.

Changes:
- Add `OpenStatusClientOptions` interface with `apiKey` and `baseUrl` options
- Add `createAuthInterceptor` to automatically inject auth headers
- Add `createOpenStatusClient` factory function
- Update README with new recommended usage pattern
- Update all code examples to use the new client-based approach

Usage:
```typescript
const client = createOpenStatusClient({
apiKey: process.env.OPENSTATUS_API_KEY,
});

// No headers needed on each call
await client.monitor.v1.MonitorService.listMonitors({});
```

The default `openstatus` export is preserved for backwards compatibility.

authored by

Thibault Le Ouay and committed by
GitHub
e7a4a10a 32b20b63

+503 -453
+351 -403
README.md
··· 74 74 ### Deno 75 75 76 76 ```typescript 77 - import { openstatus } from "jsr:@openstatus/sdk-node"; 77 + import { createOpenStatusClient } from "jsr:@openstatus/sdk-node"; 78 78 ``` 79 79 80 80 ## Quick Start 81 81 82 82 ```typescript 83 83 import { 84 + createOpenStatusClient, 84 85 HTTPMethod, 85 86 NumberComparator, 86 - openstatus, 87 87 Periodicity, 88 88 Region, 89 89 } from "@openstatus/sdk-node"; 90 90 91 - const headers = { 92 - "x-openstatus-key": process.env.OPENSTATUS_API_KEY, 93 - }; 91 + // Create a client with your API key 92 + const client = createOpenStatusClient({ 93 + apiKey: process.env.OPENSTATUS_API_KEY, 94 + }); 94 95 95 96 // Create a monitor 96 - const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor( 97 - { 98 - monitor: { 99 - name: "My API", 100 - url: "https://api.example.com/health", 101 - periodicity: Periodicity.PERIODICITY_1M, 102 - method: HTTPMethod.HTTP_METHOD_GET, 103 - regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 104 - active: true, 105 - statusCodeAssertions: [ 106 - { comparator: NumberComparator.EQUAL, target: BigInt(200) }, 107 - ], 108 - }, 97 + const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 98 + monitor: { 99 + name: "My API", 100 + url: "https://api.example.com/health", 101 + periodicity: Periodicity.PERIODICITY_1M, 102 + method: HTTPMethod.HTTP_METHOD_GET, 103 + regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 104 + active: true, 105 + statusCodeAssertions: [ 106 + { comparator: NumberComparator.EQUAL, target: BigInt(200) }, 107 + ], 109 108 }, 110 - { headers }, 111 - ); 109 + }); 112 110 113 111 console.log(`Monitor created: ${monitor?.id}`); 114 112 115 113 // List all monitors 116 - const { httpMonitors, tcpMonitors, dnsMonitors, totalSize } = 117 - await openstatus.monitor.v1.MonitorService.listMonitors({}, { headers }); 114 + const { httpMonitors, tcpMonitors, dnsMonitors, totalSize } = await client 115 + .monitor.v1.MonitorService.listMonitors({}); 118 116 119 117 console.log(`Found ${totalSize} monitors`); 120 118 ``` ··· 124 122 All API requests require an API key. Get yours from the 125 123 [OpenStatus dashboard](https://www.openstatus.dev/app). 126 124 125 + ### Recommended: Configure client once 126 + 127 127 ```typescript 128 + import { createOpenStatusClient } from "@openstatus/sdk-node"; 129 + 130 + const client = createOpenStatusClient({ 131 + apiKey: process.env.OPENSTATUS_API_KEY, 132 + }); 133 + 134 + // No need to pass headers on each call 135 + await client.monitor.v1.MonitorService.listMonitors({}); 136 + ``` 137 + 138 + ### Alternative: Manual headers 139 + 140 + ```typescript 141 + import { openstatus } from "@openstatus/sdk-node"; 142 + 128 143 const headers = { 129 144 "x-openstatus-key": process.env.OPENSTATUS_API_KEY, 130 145 }; 131 146 132 - // Pass headers to any service method 147 + // Pass headers to each service method 133 148 await openstatus.monitor.v1.MonitorService.listMonitors({}, { headers }); 134 149 ``` 135 150 ··· 142 157 143 158 ## SDK Reference 144 159 160 + > **Note:** All examples below assume you've created a client: 161 + > 162 + > ```typescript 163 + > const client = createOpenStatusClient({ 164 + > apiKey: process.env.OPENSTATUS_API_KEY, 165 + > }); 166 + > ``` 167 + 145 168 ### Monitor Service 146 169 147 170 Manage HTTP, TCP, and DNS monitors. 148 171 149 - #### `createHTTPMonitor(request, options)` 172 + #### `createHTTPMonitor(request)` 150 173 151 174 Create an HTTP/HTTPS monitor. 152 175 153 176 ```typescript 154 - import { HTTPMethod, Periodicity, Region } from "@openstatus/sdk-node"; 177 + import { 178 + createOpenStatusClient, 179 + HTTPMethod, 180 + Periodicity, 181 + Region, 182 + } from "@openstatus/sdk-node"; 155 183 156 - const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor( 157 - { 158 - monitor: { 159 - name: "My Website", 160 - url: "https://example.com", 161 - periodicity: Periodicity.PERIODICITY_1M, 162 - method: HTTPMethod.HTTP_METHOD_GET, 163 - regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 164 - active: true, 165 - }, 184 + const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 185 + monitor: { 186 + name: "My Website", 187 + url: "https://example.com", 188 + periodicity: Periodicity.PERIODICITY_1M, 189 + method: HTTPMethod.HTTP_METHOD_GET, 190 + regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 191 + active: true, 166 192 }, 167 - { headers }, 168 - ); 193 + }); 169 194 ``` 170 195 171 - #### `updateHTTPMonitor(request, options)` 196 + #### `updateHTTPMonitor(request)` 172 197 173 198 Update an existing HTTP monitor. 174 199 175 200 ```typescript 176 - const { monitor } = await openstatus.monitor.v1.MonitorService.updateHTTPMonitor( 177 - { 178 - id: "mon_123", 179 - monitor: { 180 - name: "Updated Name", 181 - active: false, 182 - }, 201 + const { monitor } = await client.monitor.v1.MonitorService.updateHTTPMonitor({ 202 + id: "mon_123", 203 + monitor: { 204 + name: "Updated Name", 205 + active: false, 183 206 }, 184 - { headers }, 185 - ); 207 + }); 186 208 ``` 187 209 188 - #### `createTCPMonitor(request, options)` 210 + #### `createTCPMonitor(request)` 189 211 190 212 Create a TCP connection monitor. 191 213 192 214 ```typescript 193 - const { monitor } = await openstatus.monitor.v1.MonitorService.createTCPMonitor( 194 - { 195 - monitor: { 196 - name: "Database", 197 - uri: "db.example.com:5432", 198 - periodicity: Periodicity.PERIODICITY_5M, 199 - regions: [Region.FLY_AMS, Region.FLY_IAD], 200 - active: true, 201 - }, 215 + const { monitor } = await client.monitor.v1.MonitorService.createTCPMonitor({ 216 + monitor: { 217 + name: "Database", 218 + uri: "db.example.com:5432", 219 + periodicity: Periodicity.PERIODICITY_5M, 220 + regions: [Region.FLY_AMS, Region.FLY_IAD], 221 + active: true, 202 222 }, 203 - { headers }, 204 - ); 223 + }); 205 224 ``` 206 225 207 - #### `updateTCPMonitor(request, options)` 226 + #### `updateTCPMonitor(request)` 208 227 209 228 Update an existing TCP monitor. 210 229 211 230 ```typescript 212 - const { monitor } = await openstatus.monitor.v1.MonitorService.updateTCPMonitor( 213 - { 214 - id: "mon_123", 215 - monitor: { 216 - name: "Updated Database Monitor", 217 - }, 231 + const { monitor } = await client.monitor.v1.MonitorService.updateTCPMonitor({ 232 + id: "mon_123", 233 + monitor: { 234 + name: "Updated Database Monitor", 218 235 }, 219 - { headers }, 220 - ); 236 + }); 221 237 ``` 222 238 223 - #### `createDNSMonitor(request, options)` 239 + #### `createDNSMonitor(request)` 224 240 225 241 Create a DNS resolution monitor. 226 242 227 243 ```typescript 228 244 import { Periodicity, RecordComparator, Region } from "@openstatus/sdk-node"; 229 245 230 - const { monitor } = await openstatus.monitor.v1.MonitorService.createDNSMonitor( 231 - { 232 - monitor: { 233 - name: "DNS Check", 234 - uri: "example.com", 235 - periodicity: Periodicity.PERIODICITY_10M, 236 - regions: [Region.FLY_AMS], 237 - active: true, 238 - recordAssertions: [ 239 - { 240 - record: "A", 241 - comparator: RecordComparator.EQUAL, 242 - target: "93.184.216.34", 243 - }, 244 - ], 245 - }, 246 + const { monitor } = await client.monitor.v1.MonitorService.createDNSMonitor({ 247 + monitor: { 248 + name: "DNS Check", 249 + uri: "example.com", 250 + periodicity: Periodicity.PERIODICITY_10M, 251 + regions: [Region.FLY_AMS], 252 + active: true, 253 + recordAssertions: [ 254 + { 255 + record: "A", 256 + comparator: RecordComparator.EQUAL, 257 + target: "93.184.216.34", 258 + }, 259 + ], 246 260 }, 247 - { headers }, 248 - ); 261 + }); 249 262 ``` 250 263 251 - #### `updateDNSMonitor(request, options)` 264 + #### `updateDNSMonitor(request)` 252 265 253 266 Update an existing DNS monitor. 254 267 255 268 ```typescript 256 - const { monitor } = await openstatus.monitor.v1.MonitorService.updateDNSMonitor( 257 - { 258 - id: "mon_123", 259 - monitor: { 260 - name: "Updated DNS Check", 261 - }, 269 + const { monitor } = await client.monitor.v1.MonitorService.updateDNSMonitor({ 270 + id: "mon_123", 271 + monitor: { 272 + name: "Updated DNS Check", 262 273 }, 263 - { headers }, 264 - ); 274 + }); 265 275 ``` 266 276 267 - #### `listMonitors(request, options)` 277 + #### `listMonitors(request)` 268 278 269 279 List all monitors with pagination. Returns monitors grouped by type. 270 280 271 281 ```typescript 272 282 const { httpMonitors, tcpMonitors, dnsMonitors, nextPageToken, totalSize } = 273 - await openstatus.monitor.v1.MonitorService.listMonitors( 274 - { pageSize: 10, pageToken: "" }, 275 - { headers }, 276 - ); 283 + await client.monitor.v1.MonitorService.listMonitors({ 284 + pageSize: 10, 285 + pageToken: "", 286 + }); 277 287 ``` 278 288 279 - #### `triggerMonitor(request, options)` 289 + #### `triggerMonitor(request)` 280 290 281 291 Trigger an immediate check. 282 292 283 293 ```typescript 284 - const { success } = await openstatus.monitor.v1.MonitorService.triggerMonitor( 285 - { id: "mon_123" }, 286 - { headers }, 287 - ); 294 + const { success } = await client.monitor.v1.MonitorService.triggerMonitor({ 295 + id: "mon_123", 296 + }); 288 297 ``` 289 298 290 - #### `deleteMonitor(request, options)` 299 + #### `deleteMonitor(request)` 291 300 292 301 Delete a monitor. 293 302 294 303 ```typescript 295 - const { success } = await openstatus.monitor.v1.MonitorService.deleteMonitor( 296 - { id: "mon_123" }, 297 - { headers }, 298 - ); 304 + const { success } = await client.monitor.v1.MonitorService.deleteMonitor({ 305 + id: "mon_123", 306 + }); 299 307 ``` 300 308 301 - #### `getMonitorStatus(request, options)` 309 + #### `getMonitorStatus(request)` 302 310 303 311 Get the current status of a monitor across all configured regions. 304 312 305 313 ```typescript 306 314 import { MonitorStatus, Region } from "@openstatus/sdk-node"; 307 315 308 - const { id, regions } = await openstatus.monitor.v1.MonitorService.getMonitorStatus( 316 + const { id, regions } = await client.monitor.v1.MonitorService.getMonitorStatus( 309 317 { id: "mon_123" }, 310 - { headers }, 311 318 ); 312 319 313 320 for (const { region, status } of regions) { ··· 315 322 } 316 323 ``` 317 324 318 - #### `getMonitorSummary(request, options)` 325 + #### `getMonitorSummary(request)` 319 326 320 327 Get aggregated metrics and latency percentiles for a monitor. 321 328 322 329 ```typescript 323 330 import { TimeRange } from "@openstatus/sdk-node"; 324 331 325 - const summary = await openstatus.monitor.v1.MonitorService.getMonitorSummary( 326 - { 327 - id: "mon_123", 328 - timeRange: TimeRange.TIME_RANGE_7D, 329 - regions: [], // optional: filter by specific regions 330 - }, 331 - { headers }, 332 - ); 332 + const summary = await client.monitor.v1.MonitorService.getMonitorSummary({ 333 + id: "mon_123", 334 + timeRange: TimeRange.TIME_RANGE_7D, 335 + regions: [], // optional: filter by specific regions 336 + }); 333 337 334 338 console.log(`Last ping: ${summary.lastPingAt}`); 335 339 console.log(`Success: ${summary.totalSuccessful}`); ··· 346 350 Check API health status (no authentication required). 347 351 348 352 ```typescript 349 - import { ServingStatus } from "@openstatus/sdk-node"; 353 + import { openstatus, ServingStatus } from "@openstatus/sdk-node"; 350 354 351 355 const { status } = await openstatus.health.v1.HealthService.check({}); 352 356 console.log(ServingStatus[status]); // "SERVING" ··· 358 362 359 363 Manage incident reports with update timelines. 360 364 361 - #### `createStatusReport(request, options)` 365 + #### `createStatusReport(request)` 362 366 363 367 Create a new status report. 364 368 365 369 ```typescript 366 370 import { StatusReportStatus } from "@openstatus/sdk-node"; 367 371 368 - const { statusReport } = await openstatus.statusReport.v1.StatusReportService.createStatusReport( 369 - { 372 + const { statusReport } = await client.statusReport.v1.StatusReportService 373 + .createStatusReport({ 370 374 title: "API Degradation", 371 375 status: StatusReportStatus.INVESTIGATING, 372 376 message: "We are investigating reports of increased latency.", ··· 374 378 pageId: "page_123", 375 379 pageComponentIds: ["comp_456"], 376 380 notify: true, 377 - }, 378 - { headers }, 379 - ); 381 + }); 380 382 381 383 console.log(`Status report created: ${statusReport?.id}`); 382 384 ``` 383 385 384 - #### `getStatusReport(request, options)` 386 + #### `getStatusReport(request)` 385 387 386 388 Get a status report by ID (includes full update timeline). 387 389 388 390 ```typescript 389 391 import { StatusReportStatus } from "@openstatus/sdk-node"; 390 392 391 - const { statusReport } = await openstatus.statusReport.v1.StatusReportService.getStatusReport( 392 - { id: "sr_123" }, 393 - { headers }, 394 - ); 393 + const { statusReport } = await client.statusReport.v1.StatusReportService 394 + .getStatusReport({ 395 + id: "sr_123", 396 + }); 395 397 396 398 console.log(`Title: ${statusReport?.title}`); 397 399 console.log(`Status: ${StatusReportStatus[statusReport?.status ?? 0]}`); ··· 401 403 } 402 404 ``` 403 405 404 - #### `listStatusReports(request, options)` 406 + #### `listStatusReports(request)` 405 407 406 408 List all status reports with pagination and optional filtering. 407 409 408 410 ```typescript 409 411 import { StatusReportStatus } from "@openstatus/sdk-node"; 410 412 411 - const { statusReports, totalSize } = 412 - await openstatus.statusReport.v1.StatusReportService.listStatusReports( 413 - { 414 - limit: 10, 415 - offset: 0, 416 - statuses: [StatusReportStatus.INVESTIGATING, StatusReportStatus.IDENTIFIED], 417 - }, 418 - { headers }, 419 - ); 413 + const { statusReports, totalSize } = await client.statusReport.v1 414 + .StatusReportService.listStatusReports({ 415 + limit: 10, 416 + offset: 0, 417 + statuses: [StatusReportStatus.INVESTIGATING, StatusReportStatus.IDENTIFIED], 418 + }); 420 419 421 420 console.log(`Found ${totalSize} status reports`); 422 421 ``` 423 422 424 - #### `updateStatusReport(request, options)` 423 + #### `updateStatusReport(request)` 425 424 426 425 Update status report metadata. 427 426 428 427 ```typescript 429 - const { statusReport } = await openstatus.statusReport.v1.StatusReportService.updateStatusReport( 430 - { 428 + const { statusReport } = await client.statusReport.v1.StatusReportService 429 + .updateStatusReport({ 431 430 id: "sr_123", 432 431 title: "Updated Title", 433 432 pageComponentIds: ["comp_456", "comp_789"], 434 - }, 435 - { headers }, 436 - ); 433 + }); 437 434 ``` 438 435 439 - #### `deleteStatusReport(request, options)` 436 + #### `deleteStatusReport(request)` 440 437 441 438 Delete a status report and all its updates. 442 439 443 440 ```typescript 444 - const { success } = await openstatus.statusReport.v1.StatusReportService.deleteStatusReport( 445 - { id: "sr_123" }, 446 - { headers }, 447 - ); 441 + const { success } = await client.statusReport.v1.StatusReportService 442 + .deleteStatusReport({ 443 + id: "sr_123", 444 + }); 448 445 ``` 449 446 450 - #### `addStatusReportUpdate(request, options)` 447 + #### `addStatusReportUpdate(request)` 451 448 452 449 Add a new update to an existing status report timeline. 453 450 454 451 ```typescript 455 452 import { StatusReportStatus } from "@openstatus/sdk-node"; 456 453 457 - const { statusReport } = await openstatus.statusReport.v1.StatusReportService.addStatusReportUpdate( 458 - { 454 + const { statusReport } = await client.statusReport.v1.StatusReportService 455 + .addStatusReportUpdate({ 459 456 statusReportId: "sr_123", 460 457 status: StatusReportStatus.IDENTIFIED, 461 458 message: "The issue has been identified as a database connection problem.", 462 459 date: "2024-01-15T11:00:00Z", // optional, defaults to current time 463 460 notify: true, 464 - }, 465 - { headers }, 466 - ); 461 + }); 467 462 ``` 468 463 469 464 --- ··· 472 467 473 468 Manage status pages, components, and subscribers. 474 469 475 - #### `createStatusPage(request, options)` 470 + #### `createStatusPage(request)` 476 471 477 472 Create a new status page. 478 473 479 474 ```typescript 480 - const { statusPage } = await openstatus.statusPage.v1.StatusPageService.createStatusPage( 481 - { 475 + const { statusPage } = await client.statusPage.v1.StatusPageService 476 + .createStatusPage({ 482 477 title: "My Service Status", 483 478 slug: "my-service", 484 479 description: "Status page for My Service", 485 480 homepageUrl: "https://example.com", 486 481 contactUrl: "https://example.com/contact", 487 - }, 488 - { headers }, 489 - ); 482 + }); 490 483 491 484 console.log(`Status page created: ${statusPage?.id}`); 492 485 ``` 493 486 494 - #### `getStatusPage(request, options)` 487 + #### `getStatusPage(request)` 495 488 496 489 Get a status page by ID. 497 490 498 491 ```typescript 499 - const { statusPage } = await openstatus.statusPage.v1.StatusPageService.getStatusPage( 500 - { id: "page_123" }, 501 - { headers }, 502 - ); 492 + const { statusPage } = await client.statusPage.v1.StatusPageService 493 + .getStatusPage({ 494 + id: "page_123", 495 + }); 503 496 ``` 504 497 505 - #### `listStatusPages(request, options)` 498 + #### `listStatusPages(request)` 506 499 507 500 List all status pages with pagination. 508 501 509 502 ```typescript 510 - const { statusPages, totalSize } = 511 - await openstatus.statusPage.v1.StatusPageService.listStatusPages( 512 - { limit: 10, offset: 0 }, 513 - { headers }, 514 - ); 503 + const { statusPages, totalSize } = await client.statusPage.v1.StatusPageService 504 + .listStatusPages({ limit: 10, offset: 0 }); 515 505 516 506 console.log(`Found ${totalSize} status pages`); 517 507 ``` 518 508 519 - #### `updateStatusPage(request, options)` 509 + #### `updateStatusPage(request)` 520 510 521 511 Update a status page. 522 512 523 513 ```typescript 524 - const { statusPage } = await openstatus.statusPage.v1.StatusPageService.updateStatusPage( 525 - { 514 + const { statusPage } = await client.statusPage.v1.StatusPageService 515 + .updateStatusPage({ 526 516 id: "page_123", 527 517 title: "Updated Title", 528 518 description: "Updated description", 529 - }, 530 - { headers }, 531 - ); 519 + }); 532 520 ``` 533 521 534 - #### `deleteStatusPage(request, options)` 522 + #### `deleteStatusPage(request)` 535 523 536 524 Delete a status page. 537 525 538 526 ```typescript 539 - const { success } = await openstatus.statusPage.v1.StatusPageService.deleteStatusPage( 540 - { id: "page_123" }, 541 - { headers }, 542 - ); 527 + const { success } = await client.statusPage.v1.StatusPageService 528 + .deleteStatusPage({ 529 + id: "page_123", 530 + }); 543 531 ``` 544 532 545 - #### `addMonitorComponent(request, options)` 533 + #### `addMonitorComponent(request)` 546 534 547 535 Add a monitor-based component to a status page. 548 536 549 537 ```typescript 550 - const { component } = await openstatus.statusPage.v1.StatusPageService.addMonitorComponent( 551 - { 538 + const { component } = await client.statusPage.v1.StatusPageService 539 + .addMonitorComponent({ 552 540 pageId: "page_123", 553 541 monitorId: "mon_456", 554 542 name: "API Server", 555 543 description: "Main API endpoint", 556 544 order: 1, 557 - }, 558 - { headers }, 559 - ); 545 + }); 560 546 ``` 561 547 562 - #### `addStaticComponent(request, options)` 548 + #### `addStaticComponent(request)` 563 549 564 550 Add a static component (not linked to a monitor). 565 551 566 552 ```typescript 567 - const { component } = await openstatus.statusPage.v1.StatusPageService.addStaticComponent( 568 - { 553 + const { component } = await client.statusPage.v1.StatusPageService 554 + .addStaticComponent({ 569 555 pageId: "page_123", 570 556 name: "Third-party Service", 571 557 description: "External dependency", 572 558 order: 2, 573 - }, 574 - { headers }, 575 - ); 559 + }); 576 560 ``` 577 561 578 - #### `updateComponent(request, options)` 562 + #### `updateComponent(request)` 579 563 580 564 Update a component. 581 565 582 566 ```typescript 583 - const { component } = await openstatus.statusPage.v1.StatusPageService.updateComponent( 584 - { 567 + const { component } = await client.statusPage.v1.StatusPageService 568 + .updateComponent({ 585 569 id: "comp_123", 586 570 name: "Updated Component Name", 587 571 order: 3, 588 - }, 589 - { headers }, 590 - ); 572 + }); 591 573 ``` 592 574 593 - #### `removeComponent(request, options)` 575 + #### `removeComponent(request)` 594 576 595 577 Remove a component from a status page. 596 578 597 579 ```typescript 598 - const { success } = await openstatus.statusPage.v1.StatusPageService.removeComponent( 599 - { id: "comp_123" }, 600 - { headers }, 601 - ); 580 + const { success } = await client.statusPage.v1.StatusPageService 581 + .removeComponent({ 582 + id: "comp_123", 583 + }); 602 584 ``` 603 585 604 - #### `createComponentGroup(request, options)` 586 + #### `createComponentGroup(request)` 605 587 606 588 Create a component group. 607 589 608 590 ```typescript 609 - const { group } = await openstatus.statusPage.v1.StatusPageService.createComponentGroup( 610 - { 591 + const { group } = await client.statusPage.v1.StatusPageService 592 + .createComponentGroup({ 611 593 pageId: "page_123", 612 594 name: "Core Services", 613 - }, 614 - { headers }, 615 - ); 595 + }); 616 596 ``` 617 597 618 - #### `updateComponentGroup(request, options)` 598 + #### `updateComponentGroup(request)` 619 599 620 600 Update a component group. 621 601 622 602 ```typescript 623 - const { group } = await openstatus.statusPage.v1.StatusPageService.updateComponentGroup( 624 - { 603 + const { group } = await client.statusPage.v1.StatusPageService 604 + .updateComponentGroup({ 625 605 id: "group_123", 626 606 name: "Updated Group Name", 627 - }, 628 - { headers }, 629 - ); 607 + }); 630 608 ``` 631 609 632 - #### `deleteComponentGroup(request, options)` 610 + #### `deleteComponentGroup(request)` 633 611 634 612 Delete a component group. 635 613 636 614 ```typescript 637 - const { success } = await openstatus.statusPage.v1.StatusPageService.deleteComponentGroup( 638 - { id: "group_123" }, 639 - { headers }, 640 - ); 615 + const { success } = await client.statusPage.v1.StatusPageService 616 + .deleteComponentGroup({ 617 + id: "group_123", 618 + }); 641 619 ``` 642 620 643 - #### `subscribeToPage(request, options)` 621 + #### `subscribeToPage(request)` 644 622 645 623 Subscribe an email to status page updates. 646 624 647 625 ```typescript 648 - const { subscriber } = await openstatus.statusPage.v1.StatusPageService.subscribeToPage( 649 - { 626 + const { subscriber } = await client.statusPage.v1.StatusPageService 627 + .subscribeToPage({ 650 628 pageId: "page_123", 651 629 email: "user@example.com", 652 - }, 653 - { headers }, 654 - ); 630 + }); 655 631 ``` 656 632 657 - #### `unsubscribeFromPage(request, options)` 633 + #### `unsubscribeFromPage(request)` 658 634 659 635 Unsubscribe from a status page. 660 636 661 637 ```typescript 662 638 // By email 663 - const { success } = await openstatus.statusPage.v1.StatusPageService.unsubscribeFromPage( 664 - { 639 + const { success } = await client.statusPage.v1.StatusPageService 640 + .unsubscribeFromPage({ 665 641 pageId: "page_123", 666 642 identifier: { case: "email", value: "user@example.com" }, 667 - }, 668 - { headers }, 669 - ); 643 + }); 670 644 671 645 // Or by subscriber ID 672 - const { success: success2 } = await openstatus.statusPage.v1.StatusPageService.unsubscribeFromPage( 673 - { 646 + const { success: success2 } = await client.statusPage.v1.StatusPageService 647 + .unsubscribeFromPage({ 674 648 pageId: "page_123", 675 649 identifier: { case: "id", value: "sub_456" }, 676 - }, 677 - { headers }, 678 - ); 650 + }); 679 651 ``` 680 652 681 - #### `listSubscribers(request, options)` 653 + #### `listSubscribers(request)` 682 654 683 655 List all subscribers for a status page. 684 656 685 657 ```typescript 686 - const { subscribers, totalSize } = 687 - await openstatus.statusPage.v1.StatusPageService.listSubscribers( 688 - { 689 - pageId: "page_123", 690 - limit: 50, 691 - offset: 0, 692 - includeUnsubscribed: false, 693 - }, 694 - { headers }, 695 - ); 658 + const { subscribers, totalSize } = await client.statusPage.v1.StatusPageService 659 + .listSubscribers({ 660 + pageId: "page_123", 661 + limit: 50, 662 + offset: 0, 663 + includeUnsubscribed: false, 664 + }); 696 665 ``` 697 666 698 - #### `getStatusPageContent(request, options)` 667 + #### `getStatusPageContent(request)` 699 668 700 669 Get full status page content including components, groups, and active reports. 701 670 702 671 ```typescript 703 - const content = await openstatus.statusPage.v1.StatusPageService.getStatusPageContent( 704 - { identifier: { case: "slug", value: "my-service" } }, 705 - { headers }, 706 - ); 672 + const content = await client.statusPage.v1.StatusPageService 673 + .getStatusPageContent({ 674 + identifier: { case: "slug", value: "my-service" }, 675 + }); 707 676 708 677 console.log(`Page: ${content.statusPage?.title}`); 709 678 console.log(`Components: ${content.components.length}`); 710 679 console.log(`Active reports: ${content.statusReports.length}`); 711 680 ``` 712 681 713 - #### `getOverallStatus(request, options)` 682 + #### `getOverallStatus(request)` 714 683 715 684 Get the aggregated status of a status page. 716 685 717 686 ```typescript 718 687 import { OverallStatus } from "@openstatus/sdk-node"; 719 688 720 - const { overallStatus, componentStatuses } = 721 - await openstatus.statusPage.v1.StatusPageService.getOverallStatus( 722 - { identifier: { case: "id", value: "page_123" } }, 723 - { headers }, 724 - ); 689 + const { overallStatus, componentStatuses } = await client.statusPage.v1 690 + .StatusPageService.getOverallStatus({ 691 + identifier: { case: "id", value: "page_123" }, 692 + }); 725 693 726 694 console.log(`Overall: ${OverallStatus[overallStatus]}`); 727 695 for (const { componentId, status } of componentStatuses) { ··· 735 703 736 704 Manage scheduled maintenance windows. 737 705 738 - #### `createMaintenance(request, options)` 706 + #### `createMaintenance(request)` 739 707 740 708 Create a new maintenance window. 741 709 742 710 ```typescript 743 - const { maintenance } = await openstatus.maintenance.v1.MaintenanceService.createMaintenance( 744 - { 711 + const { maintenance } = await client.maintenance.v1.MaintenanceService 712 + .createMaintenance({ 745 713 title: "Database Upgrade", 746 714 message: "We will be upgrading our database infrastructure.", 747 715 from: "2024-01-20T02:00:00Z", ··· 749 717 pageId: "page_123", 750 718 pageComponentIds: ["comp_456"], 751 719 notify: true, 752 - }, 753 - { headers }, 754 - ); 720 + }); 755 721 756 722 console.log(`Maintenance created: ${maintenance?.id}`); 757 723 ``` 758 724 759 - #### `getMaintenance(request, options)` 725 + #### `getMaintenance(request)` 760 726 761 727 Get a maintenance window by ID. 762 728 763 729 ```typescript 764 - const { maintenance } = await openstatus.maintenance.v1.MaintenanceService.getMaintenance( 765 - { id: "maint_123" }, 766 - { headers }, 767 - ); 730 + const { maintenance } = await client.maintenance.v1.MaintenanceService 731 + .getMaintenance({ 732 + id: "maint_123", 733 + }); 768 734 769 735 console.log(`Title: ${maintenance?.title}`); 770 736 console.log(`From: ${maintenance?.from}`); 771 737 console.log(`To: ${maintenance?.to}`); 772 738 ``` 773 739 774 - #### `listMaintenances(request, options)` 740 + #### `listMaintenances(request)` 775 741 776 742 List all maintenance windows with pagination and optional filtering. 777 743 778 744 ```typescript 779 - const { maintenances, totalSize } = 780 - await openstatus.maintenance.v1.MaintenanceService.listMaintenances( 781 - { 782 - limit: 10, 783 - offset: 0, 784 - pageId: "page_123", // optional filter 785 - }, 786 - { headers }, 787 - ); 745 + const { maintenances, totalSize } = await client.maintenance.v1 746 + .MaintenanceService.listMaintenances({ 747 + limit: 10, 748 + offset: 0, 749 + pageId: "page_123", // optional filter 750 + }); 788 751 789 752 console.log(`Found ${totalSize} maintenance windows`); 790 753 ``` 791 754 792 - #### `updateMaintenance(request, options)` 755 + #### `updateMaintenance(request)` 793 756 794 757 Update a maintenance window. 795 758 796 759 ```typescript 797 - const { maintenance } = await openstatus.maintenance.v1.MaintenanceService.updateMaintenance( 798 - { 760 + const { maintenance } = await client.maintenance.v1.MaintenanceService 761 + .updateMaintenance({ 799 762 id: "maint_123", 800 763 title: "Extended Database Upgrade", 801 764 to: "2024-01-20T06:00:00Z", 802 - }, 803 - { headers }, 804 - ); 765 + }); 805 766 ``` 806 767 807 - #### `deleteMaintenance(request, options)` 768 + #### `deleteMaintenance(request)` 808 769 809 770 Delete a maintenance window. 810 771 811 772 ```typescript 812 - const { success } = await openstatus.maintenance.v1.MaintenanceService.deleteMaintenance( 813 - { id: "maint_123" }, 814 - { headers }, 815 - ); 773 + const { success } = await client.maintenance.v1.MaintenanceService 774 + .deleteMaintenance({ 775 + id: "maint_123", 776 + }); 816 777 ``` 817 778 818 779 --- ··· 822 783 Manage notification channels for monitor alerts. Supports 12 providers including 823 784 Slack, Discord, Email, PagerDuty, and custom webhooks. 824 785 825 - #### `createNotification(request, options)` 786 + #### `createNotification(request)` 826 787 827 788 Create a new notification channel. 828 789 829 790 ```typescript 830 791 import { NotificationProvider } from "@openstatus/sdk-node"; 831 792 832 - const { notification } = await openstatus.notification.v1.NotificationService.createNotification( 833 - { 793 + const { notification } = await client.notification.v1.NotificationService 794 + .createNotification({ 834 795 name: "Slack Alerts", 835 796 provider: NotificationProvider.SLACK, 836 797 data: { ··· 840 801 }, 841 802 }, 842 803 monitorIds: ["mon_123", "mon_456"], 843 - }, 844 - { headers }, 845 - ); 804 + }); 846 805 847 806 console.log(`Notification created: ${notification?.id}`); 848 807 ``` 849 808 850 - #### `getNotification(request, options)` 809 + #### `getNotification(request)` 851 810 852 811 Get a notification channel by ID. 853 812 854 813 ```typescript 855 814 import { NotificationProvider } from "@openstatus/sdk-node"; 856 815 857 - const { notification } = await openstatus.notification.v1.NotificationService.getNotification( 858 - { id: "notif_123" }, 859 - { headers }, 860 - ); 816 + const { notification } = await client.notification.v1.NotificationService 817 + .getNotification({ 818 + id: "notif_123", 819 + }); 861 820 862 821 console.log(`Name: ${notification?.name}`); 863 822 console.log(`Provider: ${NotificationProvider[notification?.provider ?? 0]}`); 864 823 ``` 865 824 866 - #### `listNotifications(request, options)` 825 + #### `listNotifications(request)` 867 826 868 827 List all notification channels with pagination. 869 828 870 829 ```typescript 871 - const { notifications, totalSize } = 872 - await openstatus.notification.v1.NotificationService.listNotifications( 873 - { limit: 10, offset: 0 }, 874 - { headers }, 875 - ); 830 + const { notifications, totalSize } = await client.notification.v1 831 + .NotificationService.listNotifications({ limit: 10, offset: 0 }); 876 832 877 833 console.log(`Found ${totalSize} notification channels`); 878 834 ``` 879 835 880 - #### `updateNotification(request, options)` 836 + #### `updateNotification(request)` 881 837 882 838 Update a notification channel. 883 839 884 840 ```typescript 885 - const { notification } = await openstatus.notification.v1.NotificationService.updateNotification( 886 - { 841 + const { notification } = await client.notification.v1.NotificationService 842 + .updateNotification({ 887 843 id: "notif_123", 888 844 name: "Updated Slack Alerts", 889 845 monitorIds: ["mon_123", "mon_456", "mon_789"], 890 - }, 891 - { headers }, 892 - ); 846 + }); 893 847 ``` 894 848 895 - #### `deleteNotification(request, options)` 849 + #### `deleteNotification(request)` 896 850 897 851 Delete a notification channel. 898 852 899 853 ```typescript 900 - const { success } = await openstatus.notification.v1.NotificationService.deleteNotification( 901 - { id: "notif_123" }, 902 - { headers }, 903 - ); 854 + const { success } = await client.notification.v1.NotificationService 855 + .deleteNotification({ 856 + id: "notif_123", 857 + }); 904 858 ``` 905 859 906 - #### `sendTestNotification(request, options)` 860 + #### `sendTestNotification(request)` 907 861 908 862 Send a test notification to verify configuration. 909 863 910 864 ```typescript 911 865 import { NotificationProvider } from "@openstatus/sdk-node"; 912 866 913 - const { success, errorMessage } = 914 - await openstatus.notification.v1.NotificationService.sendTestNotification( 915 - { 916 - provider: NotificationProvider.SLACK, 867 + const { success, errorMessage } = await client.notification.v1 868 + .NotificationService.sendTestNotification({ 869 + provider: NotificationProvider.SLACK, 870 + data: { 917 871 data: { 918 - data: { 919 - case: "slack", 920 - value: { webhookUrl: "https://hooks.slack.com/services/..." }, 921 - }, 872 + case: "slack", 873 + value: { webhookUrl: "https://hooks.slack.com/services/..." }, 922 874 }, 923 875 }, 924 - { headers }, 925 - ); 876 + }); 926 877 927 878 if (success) { 928 879 console.log("Test notification sent successfully"); ··· 931 882 } 932 883 ``` 933 884 934 - #### `checkNotificationLimit(request, options)` 885 + #### `checkNotificationLimit(request)` 935 886 936 887 Check if the workspace has reached its notification limit. 937 888 938 889 ```typescript 939 - const { limitReached, currentCount, maxCount } = 940 - await openstatus.notification.v1.NotificationService.checkNotificationLimit({}, { headers }); 890 + const { limitReached, currentCount, maxCount } = await client.notification.v1 891 + .NotificationService.checkNotificationLimit({}); 941 892 942 893 console.log(`${currentCount}/${maxCount} notification channels used`); 943 894 ``` ··· 1168 1119 1169 1120 #### HTTP Monitor 1170 1121 1171 - | Option | Type | Required | Description | 1172 - | ---------------------- | ------------------- | -------- | ------------------------------------------ | 1173 - | `name` | string | Yes | Monitor name (max 256 chars) | 1174 - | `url` | string | Yes | URL to monitor (max 2048 chars) | 1175 - | `periodicity` | Periodicity | Yes | Check interval | 1176 - | `method` | HTTPMethod | No | HTTP method (default: GET) | 1177 - | `body` | string | No | Request body | 1178 - | `headers` | Headers[] | No | Custom headers `{ key, value }[]` | 1179 - | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000)| 1180 - | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 1181 - | `followRedirects` | boolean | No | Follow redirects (default: true) | 1182 - | `regions` | Region[] | No | Regions for checks | 1183 - | `active` | boolean | No | Enable monitoring (default: false) | 1184 - | `public` | boolean | No | Public visibility (default: false) | 1185 - | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 1186 - | `description` | string | No | Monitor description (max 1024 chars) | 1187 - | `statusCodeAssertions` | array | No | Status code assertions | 1188 - | `bodyAssertions` | array | No | Body assertions | 1189 - | `headerAssertions` | array | No | Header assertions | 1190 - | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 1122 + | Option | Type | Required | Description | 1123 + | ---------------------- | ------------------- | -------- | ------------------------------------------- | 1124 + | `name` | string | Yes | Monitor name (max 256 chars) | 1125 + | `url` | string | Yes | URL to monitor (max 2048 chars) | 1126 + | `periodicity` | Periodicity | Yes | Check interval | 1127 + | `method` | HTTPMethod | No | HTTP method (default: GET) | 1128 + | `body` | string | No | Request body | 1129 + | `headers` | Headers[] | No | Custom headers `{ key, value }[]` | 1130 + | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) | 1131 + | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 1132 + | `followRedirects` | boolean | No | Follow redirects (default: true) | 1133 + | `regions` | Region[] | No | Regions for checks | 1134 + | `active` | boolean | No | Enable monitoring (default: false) | 1135 + | `public` | boolean | No | Public visibility (default: false) | 1136 + | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 1137 + | `description` | string | No | Monitor description (max 1024 chars) | 1138 + | `statusCodeAssertions` | array | No | Status code assertions | 1139 + | `bodyAssertions` | array | No | Body assertions | 1140 + | `headerAssertions` | array | No | Header assertions | 1141 + | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 1191 1142 1192 1143 #### TCP Monitor 1193 1144 1194 - | Option | Type | Required | Description | 1195 - | --------------- | ------------------- | -------- | ------------------------------------------ | 1196 - | `name` | string | Yes | Monitor name (max 256 chars) | 1197 - | `uri` | string | Yes | `host:port` to monitor (max 2048 chars) | 1198 - | `periodicity` | Periodicity | Yes | Check interval | 1199 - | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000)| 1200 - | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 1201 - | `regions` | Region[] | No | Regions for checks | 1202 - | `active` | boolean | No | Enable monitoring (default: false) | 1203 - | `public` | boolean | No | Public visibility (default: false) | 1204 - | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 1205 - | `description` | string | No | Monitor description (max 1024 chars) | 1206 - | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 1145 + | Option | Type | Required | Description | 1146 + | --------------- | ------------------- | -------- | ------------------------------------------- | 1147 + | `name` | string | Yes | Monitor name (max 256 chars) | 1148 + | `uri` | string | Yes | `host:port` to monitor (max 2048 chars) | 1149 + | `periodicity` | Periodicity | Yes | Check interval | 1150 + | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) | 1151 + | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 1152 + | `regions` | Region[] | No | Regions for checks | 1153 + | `active` | boolean | No | Enable monitoring (default: false) | 1154 + | `public` | boolean | No | Public visibility (default: false) | 1155 + | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 1156 + | `description` | string | No | Monitor description (max 1024 chars) | 1157 + | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 1207 1158 1208 1159 #### DNS Monitor 1209 1160 1210 - | Option | Type | Required | Description | 1211 - | ------------------ | ------------------- | -------- | ------------------------------------------ | 1212 - | `name` | string | Yes | Monitor name (max 256 chars) | 1213 - | `uri` | string | Yes | Domain to resolve (max 2048 chars) | 1214 - | `periodicity` | Periodicity | Yes | Check interval | 1215 - | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000)| 1216 - | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 1217 - | `regions` | Region[] | No | Regions for checks | 1218 - | `active` | boolean | No | Enable monitoring (default: false) | 1219 - | `public` | boolean | No | Public visibility (default: false) | 1220 - | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 1221 - | `description` | string | No | Monitor description (max 1024 chars) | 1222 - | `recordAssertions` | array | No | DNS record assertions | 1223 - | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 1161 + | Option | Type | Required | Description | 1162 + | ------------------ | ------------------- | -------- | ------------------------------------------- | 1163 + | `name` | string | Yes | Monitor name (max 256 chars) | 1164 + | `uri` | string | Yes | Domain to resolve (max 2048 chars) | 1165 + | `periodicity` | Periodicity | Yes | Check interval | 1166 + | `timeout` | bigint | No | Timeout in ms (default: 45000, max: 120000) | 1167 + | `retry` | bigint | No | Retry attempts (default: 3, max: 10) | 1168 + | `regions` | Region[] | No | Regions for checks | 1169 + | `active` | boolean | No | Enable monitoring (default: false) | 1170 + | `public` | boolean | No | Public visibility (default: false) | 1171 + | `degradedAt` | bigint | No | Latency threshold (ms) for degraded status | 1172 + | `description` | string | No | Monitor description (max 1024 chars) | 1173 + | `recordAssertions` | array | No | DNS record assertions | 1174 + | `openTelemetry` | OpenTelemetryConfig | No | OpenTelemetry export configuration | 1224 1175 1225 1176 --- 1226 1177 ··· 1381 1332 1382 1333 #### MonitorStatus 1383 1334 1384 - | Value | Description | 1385 - | ---------- | ------------------------ | 1386 - | `ACTIVE` | Monitor is healthy | 1335 + | Value | Description | 1336 + | ---------- | -------------------------- | 1337 + | `ACTIVE` | Monitor is healthy | 1387 1338 | `DEGRADED` | Latency threshold exceeded | 1388 - | `ERROR` | Monitor is failing | 1339 + | `ERROR` | Monitor is failing | 1389 1340 1390 1341 #### TimeRange 1391 1342 1392 - | Value | Description | 1393 - | ----------------- | ----------- | 1394 - | `TIME_RANGE_1D` | Last 1 day | 1395 - | `TIME_RANGE_7D` | Last 7 days | 1396 - | `TIME_RANGE_14D` | Last 14 days| 1343 + | Value | Description | 1344 + | ---------------- | ------------ | 1345 + | `TIME_RANGE_1D` | Last 1 day | 1346 + | `TIME_RANGE_7D` | Last 7 days | 1347 + | `TIME_RANGE_14D` | Last 14 days | 1397 1348 1398 1349 #### StatusReportStatus 1399 1350 ··· 1507 1458 import { ConnectError } from "@connectrpc/connect"; 1508 1459 1509 1460 try { 1510 - await openstatus.monitor.v1.MonitorService.deleteMonitor( 1511 - { id: "invalid" }, 1512 - { headers }, 1513 - ); 1461 + await client.monitor.v1.MonitorService.deleteMonitor({ id: "invalid" }); 1514 1462 } catch (error) { 1515 1463 if (error instanceof ConnectError) { 1516 1464 console.error(`Error ${error.code}: ${error.message}`);
+16
deno-example.ts
··· 1 + import { createOpenStatusClient } from "@openstatus/sdk-node"; 2 + 3 + const apiKey = Deno.env.get("OPENSTATUS_API_KEY"); 4 + 5 + const client = createOpenStatusClient({ 6 + apiKey: apiKey, 7 + }); 8 + 9 + const monitors = await client.monitor.v1.MonitorService.listMonitors({}); 10 + 11 + console.log(monitors); 12 + 13 + const notification = await client.notification.v1.NotificationService 14 + .listNotifications({}); 15 + 16 + console.log(notification);
+136 -50
src/mod.ts
··· 3 3 * 4 4 * Official Node.js SDK for OpenStatus - the open-source monitoring platform. 5 5 * 6 - * @example Basic usage 6 + * @example Basic usage (recommended) 7 7 * ```typescript 8 - * import { openstatus, Periodicity, Region } from "@openstatus/sdk-node"; 8 + * import { createOpenStatusClient, Periodicity, Region } from "@openstatus/sdk-node"; 9 9 * 10 - * const headers = { 11 - * "x-openstatus-key": `Bearer ${process.env.OPENSTATUS_API_KEY}`, 12 - * }; 10 + * // Create a client with your API key 11 + * const client = createOpenStatusClient({ 12 + * apiKey: process.env.OPENSTATUS_API_KEY, 13 + * }); 13 14 * 14 - * // List all monitors 15 + * // List all monitors - no need to pass headers 15 16 * const { httpMonitors, tcpMonitors, dnsMonitors } = 16 - * await openstatus.monitor.v1.MonitorService.listMonitors({}, { headers }); 17 + * await client.monitor.v1.MonitorService.listMonitors({}); 17 18 * 18 19 * // Create an HTTP monitor 19 - * const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor({ 20 + * const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 20 21 * monitor: { 21 22 * name: "My API", 22 23 * url: "https://api.example.com/health", ··· 24 25 * regions: [Region.FLY_AMS, Region.FLY_IAD, Region.FLY_SYD], 25 26 * active: true, 26 27 * }, 28 + * }); 29 + * ``` 30 + * 31 + * @example Alternative: Manual headers 32 + * ```typescript 33 + * import { openstatus, Periodicity } from "@openstatus/sdk-node"; 34 + * 35 + * const headers = { "x-openstatus-key": `Bearer ${process.env.OPENSTATUS_API_KEY}` }; 36 + * const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor({ 37 + * monitor: { name: "My API", url: "https://api.example.com", periodicity: Periodicity.PERIODICITY_1M, active: true }, 27 38 * }, { headers }); 28 39 * ``` 29 40 */ 30 41 31 - import type { Client } from "@connectrpc/connect"; 42 + import type { Client, Interceptor } from "@connectrpc/connect"; 32 43 import { createClient } from "@connectrpc/connect"; 33 44 import { createConnectTransport } from "@connectrpc/connect-node"; 34 45 import { MonitorService } from "./gen/openstatus/monitor/v1/service_pb.ts"; ··· 268 279 const DEFAULT_API_URL = "https://api.openstatus.dev/rpc"; 269 280 270 281 /** 282 + * Configuration options for creating an OpenStatus client. 283 + */ 284 + export interface OpenStatusClientOptions { 285 + /** 286 + * Your OpenStatus API key. 287 + * If provided, it will be automatically included in all requests. 288 + */ 289 + apiKey?: string; 290 + /** 291 + * Custom API base URL. Defaults to the OpenStatus production API. 292 + */ 293 + baseUrl?: string; 294 + } 295 + 296 + /** 297 + * Creates an interceptor that adds the API key header to all requests. 298 + */ 299 + function createAuthInterceptor(apiKey: string): Interceptor { 300 + return (next) => (req) => { 301 + req.header.set("x-openstatus-key", `${apiKey}`); 302 + return next(req); 303 + }; 304 + } 305 + 306 + /** 271 307 * Creates a Connect RPC transport configured for the OpenStatus API. 272 308 */ 273 - const transport = createConnectTransport({ 274 - baseUrl: process.env.OPENSTATUS_API_URL ?? DEFAULT_API_URL, 275 - httpVersion: "2", 276 - }); 309 + function createTransport(options?: OpenStatusClientOptions) { 310 + const interceptors: Interceptor[] = []; 311 + 312 + if (options?.apiKey) { 313 + interceptors.push(createAuthInterceptor(options.apiKey)); 314 + } 315 + 316 + return createConnectTransport({ 317 + baseUrl: options?.baseUrl ?? process.env.OPENSTATUS_API_URL ?? 318 + DEFAULT_API_URL, 319 + httpVersion: "2", 320 + interceptors, 321 + }); 322 + } 277 323 278 324 /** 279 325 * OpenStatus API client interface. ··· 409 455 } 410 456 411 457 /** 412 - * OpenStatus SDK client. 458 + * Creates a configured OpenStatus client with optional API key authentication. 413 459 * 414 - * Provides access to the OpenStatus API for managing monitors and checking service health. 460 + * Use this factory function to create a client that automatically includes 461 + * your API key in all requests, eliminating the need to pass headers manually. 415 462 * 416 463 * @example 417 464 * ```typescript 418 - * import { openstatus, Periodicity } from "@openstatus/sdk-node"; 465 + * import { createOpenStatusClient, Periodicity, Region } from "@openstatus/sdk-node"; 466 + * 467 + * // Create a configured client 468 + * const client = createOpenStatusClient({ 469 + * apiKey: process.env.OPENSTATUS_API_KEY, 470 + * }); 419 471 * 420 - * // Check API health (no auth required) 421 - * const { status } = await openstatus.health.v1.HealthService.check({}); 472 + * // No need to pass headers on each call 473 + * const { httpMonitors } = await client.monitor.v1.MonitorService.listMonitors({}); 422 474 * 423 - * // Create a monitor (auth required) 424 - * const headers = { "x-openstatus-key": `Bearer ${process.env.OPENSTATUS_API_KEY}` }; 425 - * const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor({ 475 + * const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 426 476 * monitor: { 427 - * name: "My Website", 428 - * url: "https://example.com", 477 + * name: "My API", 478 + * url: "https://api.example.com/health", 429 479 * periodicity: Periodicity.PERIODICITY_1M, 480 + * regions: [Region.FLY_AMS, Region.FLY_IAD], 430 481 * active: true, 431 482 * }, 432 - * }, { headers }); 483 + * }); 433 484 * ``` 434 485 */ 435 - export const openstatus: OpenStatusClient = { 436 - monitor: { 437 - v1: { 438 - MonitorService: createClient(MonitorService, transport), 486 + export function createOpenStatusClient( 487 + options?: OpenStatusClientOptions, 488 + ): OpenStatusClient { 489 + const transport = createTransport(options); 490 + 491 + return { 492 + monitor: { 493 + v1: { 494 + MonitorService: createClient(MonitorService, transport), 495 + }, 439 496 }, 440 - }, 441 - health: { 442 - v1: { 443 - HealthService: createClient(HealthService, transport), 497 + health: { 498 + v1: { 499 + HealthService: createClient(HealthService, transport), 500 + }, 444 501 }, 445 - }, 446 - statusReport: { 447 - v1: { 448 - StatusReportService: createClient(StatusReportService, transport), 502 + statusReport: { 503 + v1: { 504 + StatusReportService: createClient(StatusReportService, transport), 505 + }, 449 506 }, 450 - }, 451 - statusPage: { 452 - v1: { 453 - StatusPageService: createClient(StatusPageService, transport), 507 + statusPage: { 508 + v1: { 509 + StatusPageService: createClient(StatusPageService, transport), 510 + }, 454 511 }, 455 - }, 456 - maintenance: { 457 - v1: { 458 - MaintenanceService: createClient(MaintenanceService, transport), 512 + maintenance: { 513 + v1: { 514 + MaintenanceService: createClient(MaintenanceService, transport), 515 + }, 459 516 }, 460 - }, 461 - notification: { 462 - v1: { 463 - NotificationService: createClient(NotificationService, transport), 517 + notification: { 518 + v1: { 519 + NotificationService: createClient(NotificationService, transport), 520 + }, 464 521 }, 465 - }, 466 - }; 522 + }; 523 + } 524 + 525 + /** 526 + * Default OpenStatus SDK client (without pre-configured authentication). 527 + * 528 + * For authenticated requests, either: 529 + * 1. Use `createOpenStatusClient({ apiKey })` to create a pre-configured client (recommended) 530 + * 2. Pass headers manually on each call 531 + * 532 + * @example Using createOpenStatusClient (recommended) 533 + * ```typescript 534 + * import { createOpenStatusClient, Periodicity } from "@openstatus/sdk-node"; 535 + * 536 + * const client = createOpenStatusClient({ apiKey: process.env.OPENSTATUS_API_KEY }); 537 + * const { monitor } = await client.monitor.v1.MonitorService.createHTTPMonitor({ 538 + * monitor: { name: "My Website", url: "https://example.com", periodicity: Periodicity.PERIODICITY_1M, active: true }, 539 + * }); 540 + * ``` 541 + * 542 + * @example Using default client with manual headers 543 + * ```typescript 544 + * import { openstatus, Periodicity } from "@openstatus/sdk-node"; 545 + * 546 + * const headers = { "x-openstatus-key": `Bearer ${process.env.OPENSTATUS_API_KEY}` }; 547 + * const { monitor } = await openstatus.monitor.v1.MonitorService.createHTTPMonitor({ 548 + * monitor: { name: "My Website", url: "https://example.com", periodicity: Periodicity.PERIODICITY_1M, active: true }, 549 + * }, { headers }); 550 + * ``` 551 + */ 552 + export const openstatus: OpenStatusClient = createOpenStatusClient();