openstead
Developer tools & integrations

TypeScript SDK

Call the Openstead core API from Node.js with typed resources, async iterators, and cancellation.

Suggest a change

The Openstead TypeScript SDK supports Node.js 22 and newer, ESM and CommonJS. It provides types and helpers for all 28 core operations.

Install

Build the SDK from the private TypeScript repository with an authenticated Git credential helper:

git clone https://github.com/Layerrail/openstead-typescript.git
cd openstead-typescript
git checkout 0b9b2a7664546bcbbf5841f256e6496c61ea54ad
npm ci
npm run build
npm pack

Install the resulting tarball in your application:

npm install /absolute/path/to/layerrail-openstead-0.1.0.tgz

The installed package is @layerrail/openstead. It is not published to the public npm registry. Pin a reviewed source commit when building production artifacts. Contact Openstead support if your GitHub identity needs repository access.

The examples below use the Openstead source version. Named Runivo classes and error aliases remain available in the new package for existing code. OPENSTEAD_API_KEY takes precedence, with RUNIVO_API_KEY retained as a fallback. Existing installations of the previous package continue to work; update the package dependency when adopting these imports.

Connect from your server

import Openstead from '@layerrail/openstead';

const client = new Openstead(); // Reads OPENSTEAD_API_KEY.
const workspaceId = process.env.OPENSTEAD_WORKSPACE_ID!;

const { workspace } = await client.workspaces.get({ workspaceId });
console.log(workspace.name);

for await (const service of client.services.iterate({ workspaceId })) {
  console.log(service.name, service.status);
}

CommonJS can use const { Openstead } = require('@layerrail/openstead'). The default API root is https://api.openstead.tech/api/v1.

Keep this client in server code. Browser use is disabled by default because a bundled bearer credential would expose workspace access. In Next.js, call it from a server-only module or Route Handler and return only the data that the requesting user is authorized to read.

Create configuration

Methods accept an argument object and a separate request-options object:

const { project } = await client.projects.create(
  {
    workspaceId,
    body: { name: 'example-project', color: 'violet' },
  },
  {
    idempotencyKey: 'create-example-project-001',
    requestId: 'trace-project-01',
  },
);

console.log(project.id);

idempotencyKey identifies a logical write. The options-level requestId sets the diagnostic X-Request-ID header. They are separate controls. The SDK preserves API JSON envelopes and camelCase fields.

Resources

catalog, workspaces, projects, services, variables, deployments, operations, and logs expose the corresponding API methods. Projects, services, variables, and deployments provide iterate() async generators. A plain list() returns one exact API envelope.

client.request(operationId, args, options) calls the same typed core operations by their OpenAPI operation ID. Use the reference for fields and constraints.

Observe an existing deployment

import { OpensteadDeploymentError, OpensteadTimeoutError } from '@layerrail/openstead';

try {
  const deployment = await client.deployments.wait(
    {
      workspaceId,
      serviceId: process.env.OPENSTEAD_SERVICE_ID!,
      deploymentId: process.env.OPENSTEAD_DEPLOYMENT_ID!,
    },
    { timeoutMs: 300_000, intervalMs: 2_000, maxAttempts: 150 },
  );
  console.log(deployment.status);
} catch (error) {
  if (error instanceof OpensteadDeploymentError) {
    console.error('The deployment ended unsuccessfully.');
  } else if (error instanceof OpensteadTimeoutError) {
    console.error('The wait ended; the remote deployment may still be running.');
  } else {
    throw error;
  }
}

Wait returns at live and raises for failed, cancelled, or superseded. operations.wait() returns at complete. Local cancellation stops observation; use an explicit deployment cancellation request to stop a remote deployment.

Timeouts, retries, and cancellation

const controlled = new Openstead({
  timeoutMs: 30_000,
  maxRetries: 2,
  retryDelayMs: 250,
  maxRetryDelayMs: 10_000,
});

const controller = new AbortController();
const response = await controlled.services.list(
  { workspaceId, query: { limit: 100 } },
  { signal: controller.signal, timeoutMs: 10_000 },
);
console.log(response.services.length);

The per-call deadline covers network work, response consumption, and retry sleeps. Reads and supported keyed writes retry eligible transport failures, 408, 429, and 5xx responses. Retry-After is honored. Set maxRetries: 0 to disable retries.

Supported writes receive an automatic key that stays fixed across the call's retries. Supply your own key for retries across separate calls. Secret reveal is never retried and rejects an idempotency key.

Logs and errors

logs.batches() drains available batches; logs.tail() polls for lines. Both use numeric log cursors and accept cancellation and deadline controls. Their default observation deadline is five minutes.

import { OpensteadAPIError, getResponseMetadata } from '@layerrail/openstead';

try {
  const result = await client.workspaces.get({ workspaceId });
  console.log(getResponseMetadata(result)?.requestId);
} catch (error) {
  if (error instanceof OpensteadAPIError) {
    console.error({ status: error.status, code: error.code, requestId: error.requestId });
  } else {
    throw error;
  }
}

Detailed error.errors and log lines may contain application data. Choose what to expose deliberately. Successful response metadata is separate from the wire JSON; inspect it before cloning the result.

Need a hand? Contact Openstead support.

On this page