TypeScript SDK for Spanwise - monitoring, tracing, and error tracking
npm install @spanwise/sdkTypeScript SDK for Spanwise observability - monitoring, tracing, and error tracking.
``bash`
npm install @spanwise/sdk
`typescript
import { Spanwise } from "@spanwise/sdk"
const client = new Spanwise({ apiKey: "sw_..." })
// Wrap your cron job - automatically tracks start/success/fail
await client.wrap("check-id", async () => {
await myDatabaseBackup()
})
`
The wrap() method automatically sends start/success/fail signals:
`typescript`
await client.wrap("check-id", async () => {
// Your job logic here
await syncUsers()
await sendReports()
})
// Sends "start" → runs function → sends "success" (or "fail" if error thrown)
For more control, use ping() directly:
`typescript`
await client.ping("check-id") // Success
await client.ping("check-id", { type: "start" }) // Job started
await client.ping("check-id", { type: "fail" }) // Job failed
await client.ping("check-id", { type: "fail", body: "Error details" })
`typescript`
const client = new Spanwise({
apiKey: "sw_...",
timeout: 30000, // optional, default 30s
retries: 2, // optional, default 2 retries with exponential backoff
})
When apiKey is undefined, ping() and wrap() silently no-op. This allows running in development without setting up monitoring:
`typescript
const client = new Spanwise({ apiKey: process.env.SPANWISE_API_KEY })
// Works in dev (no-op) and prod (sends pings)
await client.wrap("check-id", async () => {
await myJob()
})
`
Management APIs (projects, checks, etc.) still require an API key and will throw if accessed without one.
`typescript`
const projects = await client.projects.list()
const project = await client.projects.get("project-id")
const project = await client.projects.create({ name: "My Project", slug: "my-project", orgId: "org-id" })
await client.projects.update("project-id", { name: "New Name" })
await client.projects.delete("project-id")
`typescript
const checks = await client.checks.list("project-id")
const check = await client.checks.get("check-id")
const check = await client.checks.create("project-id", {
name: "DB Backup",
scheduleType: "PERIOD",
scheduleValue: "3600", // every hour
})
await client.checks.update("check-id", { name: "New Name" })
await client.checks.pause("check-id")
await client.checks.resume("check-id")
await client.checks.delete("check-id")
// Uptime stats
const stats = await client.checks.stats("check-id", 90) // last 90 days
`
`typescript`
const channels = await client.channels.list("project-id")
const channel = await client.channels.create("project-id", {
type: "SLACK_WEBHOOK",
name: "Slack Alerts",
config: { webhookUrl: "https://hooks.slack.com/..." },
})
await client.channels.update("project-id", "channel-id", { name: "New Name" })
await client.channels.test("project-id", "channel-id") // Test notification
await client.channels.delete("project-id", "channel-id")
`typescript
const incidents = await client.incidents.list("project-id")
const incidents = await client.incidents.list("project-id", { status: "INVESTIGATING" })
const incident = await client.incidents.create("project-id", {
title: "API Degradation",
impact: "MINOR",
})
await client.incidents.update("project-id", "incident-id", { status: "IDENTIFIED" })
// Add status update
await client.incidents.addUpdate("project-id", "incident-id", {
status: "MONITORING",
message: "Fix deployed, monitoring for stability",
})
await client.incidents.delete("project-id", "incident-id")
`
`typescript
const windows = await client.maintenance.list("project-id")
const windows = await client.maintenance.list("project-id", { upcoming: true })
const maintenance = await client.maintenance.create("project-id", {
title: "Database Migration",
startsAt: "2024-01-15T03:00:00Z",
endsAt: "2024-01-15T05:00:00Z",
checkIds: ["check-1", "check-2"],
})
await client.maintenance.update("project-id", "maintenance-id", { title: "Updated Title" })
await client.maintenance.delete("project-id", "maintenance-id")
`
`typescript`
const orgs = await client.organizations.list()
const org = await client.organizations.get("org-id")
const org = await client.organizations.create({ name: "My Org", slug: "my-org" })
await client.organizations.update("org-id", { autoCreateIncidents: true })
await client.organizations.delete("org-id")
`typescript`
const keys = await client.apiKeys.list("project-id")
const newKey = await client.apiKeys.create("project-id", { name: "CI/CD" })
console.log(newKey.key) // Full key shown only once
await client.apiKeys.delete("project-id", "key-id")
`typescript
import { SpanwiseError, NotFoundError, UnauthorizedError } from "@spanwise/sdk"
try {
await client.checks.get("invalid-id")
} catch (error) {
if (error instanceof NotFoundError) {
console.log("Check not found")
} else if (error instanceof UnauthorizedError) {
console.log("Invalid API key")
} else if (error instanceof SpanwiseError) {
console.log(Error: ${error.message} (${error.code}))`
}
}
All types are exported for TypeScript users:
`typescript``
import type {
Check,
CheckStatus,
Channel,
ChannelType,
Incident,
IncidentStatus,
Maintenance,
Organization,
Project,
} from "@spanwise/sdk"
MIT