Node.js SDK

Official Node.js client library for the RaidFrame API.

Install

npm install @raidframe/sdk

Initialize

import { RaidFrame } from "@raidframe/sdk";

const rf = new RaidFrame({
  token: process.env.RAIDFRAME_TOKEN,
  project: "my-saas", // optional, auto-detected from raidframe.yaml
});

Projects

const projects = await rf.projects.list();
const project = await rf.projects.get("my-saas");
const newProject = await rf.projects.create({ name: "new-app", region: "us-east-1" });
await rf.projects.delete("old-app");

Services

const services = await rf.services.list();
const api = await rf.services.get("api");

// Scale
await rf.services.scale("api", { min: 4, max: 20 });

// Restart
await rf.services.restart("api");

// Create
await rf.services.create({
  name: "worker",
  type: "worker",
  command: "node worker.js",
});

Deployments

// Trigger deploy
const deployment = await rf.deploy({ watch: true });
console.log(`Deployed: ${deployment.id} (${deployment.version})`);

// List deployments
const deployments = await rf.deployments.list({ limit: 10 });

// Rollback
await rf.deployments.rollback();
// Or to specific version
await rf.deployments.rollback("dep_abc123");

Databases

// Provision
await rf.databases.create({ engine: "postgres", name: "main", plan: "pro" });

// Query
const result = await rf.databases.query("main", "SELECT count(*) FROM users");
console.log(result.rows[0].count);

// Backup
await rf.databases.backup("main", { name: "before-migration" });

// Branch
await rf.databases.branch("main", { name: "feature-x" });

Environment Variables

// Set
await rf.env.set({ STRIPE_KEY: "sk_live_xxx", API_SECRET: "secret" });

// Get
const value = await rf.env.get("STRIPE_KEY");

// List
const vars = await rf.env.list();

// Delete
await rf.env.delete("OLD_KEY");

Logs

// Query logs
const logs = await rf.logs.query({
  service: "api",
  since: "1h",
  level: "error",
  search: "timeout",
  limit: 50,
});

// Stream logs
const stream = rf.logs.stream({ service: "api" });
stream.on("log", (entry) => {
  console.log(`[${entry.service}] ${entry.message}`);
});
stream.on("error", (err) => console.error(err));
// Stop streaming
stream.close();

Metrics

const metrics = await rf.metrics.get({
  service: "api",
  metrics: ["cpu_percent", "response_time_p99"],
  period: "24h",
});

console.log(`CPU: ${metrics.cpu_percent.avg}%`);
console.log(`P99: ${metrics.response_time_p99.avg}ms`);

Queues

import { Queue, Worker } from "@raidframe/sdk";

// Publish
const queue = new Queue("tasks");
await queue.publish({ type: "send-email", to: "[email protected]" });

// Consume
const worker = new Worker("tasks", async (job) => {
  await sendEmail(job.data.to);
});
worker.start({ concurrency: 10 });

KV Store

import { KV } from "@raidframe/sdk";

const kv = new KV();
await kv.set("feature:dark-mode", "true", { ttl: 3600 });
const value = await kv.get("feature:dark-mode");
await kv.delete("feature:dark-mode");
const count = await kv.incr("rate:ip:192.168.1.1");

Email

import { Email } from "@raidframe/sdk";

const email = new Email();
await email.send({
  from: "[email protected]",
  to: "[email protected]",
  subject: "Welcome",
  template: "welcome",
  data: { name: "Alice" },
});

Error Handling

import { RaidFrameError, NotFoundError, RateLimitError } from "@raidframe/sdk";

try {
  await rf.services.get("nonexistent");
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log("Service not found");
  } else if (err instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${err.retryAfter}s`);
  } else {
    throw err;
  }
}

TypeScript

The SDK is fully typed. All methods, parameters, and responses have TypeScript definitions:

import type { Service, Deployment, Database, LogEntry } from "@raidframe/sdk";

const service: Service = await rf.services.get("api");
const deployment: Deployment = await rf.deploy();