dominus-sdk-nodejs
v1.2.44
Published
Node.js SDK for the Dominus Orchestrator Platform
Maintainers
Readme
CB Dominus SDK for Node.js
TypeScript SDK for the Dominus Orchestrator Platform
A unified, async-first TypeScript SDK providing seamless access to all Dominus backend services including secrets management, database operations, caching, file storage, authentication, schema management, and structured logging.
Features
- Namespace-based API - Intuitive access via
dominus.db,dominus.redis,dominus.files, etc. - Async/Await - Built for modern async TypeScript/JavaScript applications
- Automatic JWT Management - Token minting, caching, and refresh handled transparently
- Resilience Built-in - Circuit breaker, exponential backoff with jitter, retry logic
- Cold Start Handling - Special retry logic for orchestrator cold starts
- Typed Errors - 9 specific error classes for different failure modes
- Secure by Default - Client-side password hashing, audit trail support
- Server-Side Only - Designed for Next.js API routes, Express, and Node.js backends
Quick Start
import { dominus } from 'dominus-sdk-nodejs';
// Set your token (or use DOMINUS_TOKEN environment variable)
process.env.DOMINUS_TOKEN = "your-psk-token";
// Secrets
const dbUrl = await dominus.secrets.get("DATABASE_URL");
// Database queries
const users = await dominus.db.query("users", { filters: { status: "active" } });
// Redis caching
await dominus.redis.set("session:123", { user: "john" }, { ttl: 3600 });
// File storage
const result = await dominus.files.upload(buffer, "report.pdf", { category: "reports" });
// Structured logging
await dominus.logs.info("User logged in", { user_id: "123" });Installation
npm install dominus-sdk-nodejsOr add directly from GitHub:
npm install github:carebridgesystems/cb-dominus-sdk-nodejsRequirements
- Node.js 18+ (uses native fetch)
- TypeScript 5.0+ (optional, but recommended)
Namespaces
| Namespace | Service | Purpose |
|-----------|---------|---------|
| dominus.secrets | Warden | Secrets management |
| dominus.db | Scribe | Database CRUD operations |
| dominus.secure | Scribe | Secure table access with audit logging |
| dominus.redis | Whisperer | Redis caching & distributed locks |
| dominus.files | Archivist | Object storage (Backblaze B2) |
| dominus.auth | Guardian | Users, roles, scopes, tenants, pages, navigation |
| dominus.ddl | Smith | Schema DDL & migrations |
| dominus.logs | Herald | Structured logging (BetterStack) |
| dominus.portal | Portal | User auth, sessions, profiles, navigation |
| dominus.courier | Courier | Email delivery (Postmark) |
| dominus.open | Scribe | Direct database access |
| dominus.health | Health | Service health checks |
Usage Examples
Secrets Management
// Get a secret
const value = await dominus.secrets.get("API_KEY");
// Create or update
await dominus.secrets.upsert("API_KEY", "new-value", "Updated API key");
// List secrets with prefix
const secrets = await dominus.secrets.list("DB_");
// Delete
await dominus.secrets.delete("OLD_KEY");
// Root-level shortcuts
const dbUrl = await dominus.get("DATABASE_URL");
await dominus.upsert("KEY", "value");Database Operations
// List tables
const tables = await dominus.db.tables();
const tenantTables = await dominus.db.tables("tenant_acme");
// Query with filters and pagination
const users = await dominus.db.query("users", {
filters: { status: "active", role: ["admin", "manager"] },
sortBy: "created_at",
sortOrder: "DESC",
limit: 50,
offset: 0
});
// Insert
const user = await dominus.db.insert("users", {
email: "[email protected]",
name: "John Doe"
});
// Update
await dominus.db.update("users", { status: "inactive" }, { id: userId });
// Delete
await dominus.db.delete("users", { id: userId });
// Bulk insert
await dominus.db.bulkInsert("events", [
{ type: "login", user_id: "123" },
{ type: "login", user_id: "456" }
]);
// Secure table access (requires audit reason)
const patients = await dominus.db.query("patients", {
schema: "tenant_acme",
reason: "Reviewing records for appointment #123",
actor: "dr.smith"
});Redis Caching
// Key-value operations
await dominus.redis.set("user:123", { name: "John" }, { ttl: 3600 });
const value = await dominus.redis.get("user:123");
// Distributed locks
const acquired = await dominus.redis.setnx("lock:job", "worker-1", { ttl: 60 });
if (acquired) {
try {
// Do exclusive work
} finally {
await dominus.redis.delete("lock:job");
}
}
// Counters
await dominus.redis.incr("page:views", 1);
// Hash operations
await dominus.redis.hset("user:123", "email", "[email protected]", { ttl: 3600 });
const email = await dominus.redis.hget("user:123", "email");
const allFields = await dominus.redis.hgetall("user:123");File Storage
import { readFileSync } from 'fs';
// Upload file
const data = readFileSync("report.pdf");
const result = await dominus.files.upload(data, "report.pdf", {
category: "reports",
contentType: "application/pdf"
});
// Get download URL
const download = await dominus.files.download({ id: result.id });
console.log(download.download_url);
// Fetch file from URL and store
const fetched = await dominus.files.fetch("https://example.com/doc.pdf", {
filename: "external-doc.pdf",
category: "imports"
});
// List files
const files = await dominus.files.list({ category: "reports", prefix: "2025/" });
// Delete file
await dominus.files.delete({ id: result.id });Structured Logging
// Simple logging (auto-captures file and function)
await dominus.logs.info("User logged in", { user_id: "123" });
await dominus.logs.error("Payment failed", { order_id: "456" });
// All log levels
await dominus.logs.debug("Debug message", { data: "..." });
await dominus.logs.notice("Important notice", {});
await dominus.logs.warn("Warning message", {});
await dominus.logs.critical("Critical error", {});
// With category
await dominus.logs.info("Cache hit", { key: "user:123" }, "cache");
// With exception
try {
riskyOperation();
} catch (error) {
await dominus.logs.error("Operation failed", {}, { exception: error as Error });
}
// Batch logging
await dominus.logs.batch([
{ level: "info", message: "Step 1 complete", data: {} },
{ level: "info", message: "Step 2 complete", data: {} }
]);
// Query logs
const errors = await dominus.logs.query({ level: "error", limit: 100 });Authentication & Authorization (Guardian)
// User management
const users = await dominus.auth.listUsers();
const user = await dominus.auth.getUser("user-uuid");
const newUser = await dominus.auth.addUser({
username: "john",
password: "secure-password",
email: "[email protected]"
});
await dominus.auth.updateUser("user-uuid", { status: "active" });
await dominus.auth.deleteUser("user-uuid");
// Role management
const roles = await dominus.auth.listRoles();
const role = await dominus.auth.addRole({
name: "Editor",
scopeSlugs: ["read", "write", "publish"]
});
// Scope management
const scopes = await dominus.auth.listScopes();
await dominus.auth.addScope({ name: "publish", slug: "publish" });
// Tenant management
const tenants = await dominus.auth.listTenants();
const categories = await dominus.auth.listTenantCategories();
// Page and navigation
const pages = await dominus.auth.listPages();
const navItems = await dominus.auth.listNavigation();
// Secure tables registry
const secureTables = await dominus.auth.listSecureTables();
await dominus.auth.addSecureTable("patients", "tenant_acme");Schema Management (DDL)
// Create table
await dominus.ddl.createTable("orders", [
{ name: "id", type: "UUID", constraints: ["PRIMARY KEY"] },
{ name: "user_id", type: "UUID", constraints: ["NOT NULL"] },
{ name: "total", type: "DECIMAL(10,2)" },
{ name: "created_at", type: "TIMESTAMPTZ", default: "NOW()" }
]);
// Add column
await dominus.ddl.addColumn("orders", {
name: "status",
type: "VARCHAR(50)",
default: "'pending'"
});
// Alter column
await dominus.ddl.alterColumn("orders", "status", { type: "VARCHAR(100)" });
// Create index
await dominus.ddl.createIndex("orders", "idx_orders_user", ["user_id"]);
// Migrations
const migrations = await dominus.ddl.listMigrations();
await dominus.ddl.applyMigration("20250101_add_orders");
// Provision tenant schema from category template
await dominus.ddl.provisionTenantFromCategory("customer_acme", "healthcare");User Authentication (Portal)
// User login (tenant_id is optional)
const session = await dominus.portal.login(
"[email protected]",
"secret123",
"tenant-uuid" // optional
);
// Client login with PSK (for service-to-service)
const clientSession = await dominus.portal.loginClient("psk-token");
// Get current user
const me = await dominus.portal.me();
// Get navigation (access-filtered for current user)
const nav = await dominus.portal.getNavigation();
// Check page access
const hasAccess = await dominus.portal.checkPageAccess("/dashboard/admin/users");
// Switch tenant
await dominus.portal.switchTenant("other-tenant-uuid");
// Profile & preferences
const profile = await dominus.portal.getProfile();
await dominus.portal.updateProfile({ displayName: "John Doe" });
const prefs = await dominus.portal.getPreferences();
await dominus.portal.updatePreferences({
theme: "dark",
timezone: "America/New_York"
});
// Password management
await dominus.portal.changePassword("old-password", "new-password");
await dominus.portal.requestPasswordReset("[email protected]");
await dominus.portal.confirmPasswordReset("reset-token", "new-password");
// Session management
const sessions = await dominus.portal.listSessions();
await dominus.portal.revokeSession("session-id");
await dominus.portal.revokeAllSessions();
// Registration & email verification
await dominus.portal.register("newuser", "[email protected]", "password", "tenant-id");
await dominus.portal.verifyEmail("verification-token");
await dominus.portal.resendVerification("[email protected]");
// Logout
await dominus.portal.logout();Email Delivery (Courier)
// Send email via Postmark template
const result = await dominus.courier.send(
"welcome",
"[email protected]",
"[email protected]",
{ name: "John", product_name: "My App" }
);
// Convenience methods
await dominus.courier.sendWelcome(
"[email protected]",
"[email protected]",
{ name: "John", actionUrl: "https://myapp.com/start", productName: "My App" }
);
await dominus.courier.sendPasswordReset(
"[email protected]",
"[email protected]",
{ name: "John", resetUrl: "https://myapp.com/reset?token=abc", productName: "My App" }
);
await dominus.courier.sendEmailVerification(
"[email protected]",
"[email protected]",
{ name: "John", verifyUrl: "https://myapp.com/verify?token=xyz", productName: "My App" }
);
await dominus.courier.sendInvitation(
"[email protected]",
"[email protected]",
{
name: "Invited User",
inviteUrl: "https://myapp.com/invite?token=abc",
inviterName: "John",
productName: "My App"
}
);Health Checks
// Basic health check
const status = await dominus.health.check();
// Ping (lightweight)
await dominus.health.ping();
// Warmup (for cold start tolerance)
await dominus.health.warmup();Error Handling
import {
dominus,
DominusError,
AuthenticationError,
AuthorizationError,
NotFoundError,
ValidationError,
ConflictError,
ServiceError,
SecureTableError,
ConnectionError,
TimeoutError,
} from 'dominus-sdk-nodejs';
try {
const user = await dominus.auth.getUser("invalid-id");
} catch (error) {
if (error instanceof NotFoundError) {
console.log(`User not found: ${error.message}`);
} else if (error instanceof SecureTableError) {
console.log("Secure table requires 'reason' and 'actor' parameters");
} else if (error instanceof AuthenticationError) {
console.log("Invalid or expired token");
} else if (error instanceof AuthorizationError) {
console.log("Insufficient permissions");
} else if (error instanceof ValidationError) {
console.log(`Invalid request: ${error.message}`);
} else if (error instanceof TimeoutError) {
console.log("Request timed out");
} else if (error instanceof DominusError) {
console.log(`Error ${error.statusCode}: ${error.message}`);
if (error.details) {
console.log(`Details: ${JSON.stringify(error.details)}`);
}
}
}Error Types
| Error | Status | Description |
|-------|--------|-------------|
| AuthenticationError | 401 | Invalid or missing token |
| AuthorizationError | 403 | Insufficient permissions |
| NotFoundError | 404 | Resource not found |
| ValidationError | 400 | Invalid request data |
| ConflictError | 409 | Duplicate or version conflict |
| ServiceError | 5xx | Backend service error |
| SecureTableError | 403 | Missing reason for secure table |
| ConnectionError | - | Network connection failed |
| TimeoutError | 504 | Request timed out |
Configuration
Environment Variables
# Required: PSK token for authentication
export DOMINUS_TOKEN="your-psk-token"Resilience Configuration
The SDK includes built-in resilience features:
| Feature | Configuration | |---------|---------------| | Request Timeout | 30 seconds | | Max Retries | 3 with exponential backoff | | Circuit Breaker | Opens after 5 failures, resets after 30s | | JWT Cache TTL | Refreshes when <60 seconds remain | | JWT Mint Retries | 3 with backoff (handles cold starts) | | Backoff Delays | Base 1s, max 15s with jitter |
Architecture
┌─────────────────┐
│ Your App │
│ (Next.js API) │
└────────┬────────┘
│ await dominus.db.query(...)
▼
┌─────────────────┐
│ Dominus SDK │ ← JWT caching, circuit breaker, retries
│ (this package) │
└────────┬────────┘
│ HTTPS (base64-encoded JSON)
▼
┌─────────────────────────────────┐
│ Dominus Orchestrator │
│ (Cloud Run FastAPI backend) │
│ │
│ ┌─────────┬─────────┬────────┐ │
│ │ Warden │Guardian │Archivist│ │
│ │ Scribe │ Smith │Whisperer│ │
│ │ Herald │ Portal │ Courier │ │
│ └─────────┴─────────┴────────┘ │
└─────────────────────────────────┘Next.js Integration
// app/api/users/route.ts
import { dominus, NotFoundError } from 'dominus-sdk-nodejs';
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
try {
const users = await dominus.db.query("users", {
filters: { status: "active" },
limit: 50
});
return NextResponse.json(users);
} catch (error) {
if (error instanceof NotFoundError) {
return NextResponse.json({ error: "Not found" }, { status: 404 });
}
return NextResponse.json({ error: "Failed to fetch users" }, { status: 500 });
}
}Crypto Helpers
The SDK exports utility functions for password and token handling:
import {
hashPassword,
verifyPasswordLocal,
hashPsk,
verifyPskLocal,
generatePskLocal,
hashToken,
generateToken
} from 'dominus-sdk-nodejs';
// Password hashing (bcrypt)
const hash = await hashPassword("user-password");
const isValid = await verifyPasswordLocal("user-password", hash);
// PSK generation and verification
const psk = generatePskLocal();
const pskHash = await hashPsk(psk);
const pskValid = await verifyPskLocal(psk, pskHash);
// Token generation
const token = generateToken(32); // 32-byte random token
const tokenHash = hashToken(token); // SHA-256 hashDependencies
bcryptjs- Password hashing
Version
v1.2.2 - Latest release with navigation routes fix and page scope methods
Changelog
- v1.2.2 - Fix
checkPageAccessto send correct parameter - v1.2.0 - Add navigation routes and page scope methods
- v1.1.6 - Add user token support for user-authenticated requests
- v1.1.5 - Make
tenant_idoptional in login methods - v1.1.3 - Add retry with backoff for JWT mint (cold start handling)
- v1.1.0 - Fix SDK routes and improve error messaging
- v1.0.0 - Initial release with full namespace API
License
Proprietary - CareBridge Systems
