Results, errors, and streams
Handle operation failures, deployment outcomes, pagination, and cancellation.
An operation can fail immediately, or it can submit work that later finishes unsuccessfully. Handle both the call and the final deployment outcome.
Operation errors
import { OperationError, type OpenshipClient, type ScopedShip } from "openship";
export async function readProject(ship: OpenshipClient | ScopedShip, projectId: string) {
try {
return await ship.projects.get(projectId);
} catch (error) {
if (error instanceof OperationError) {
console.error(error.statusCode, error.code, error.message);
}
throw error;
}
}OperationError exposes statusCode, code, and public details. Remote ApiError also exposes
status and the HTTP response body. Input validation can throw ValidationError; network,
configuration, and abort failures may be other error types.
| Case | Response |
|---|---|
| Invalid input | Fix the reported fields; do not repeat the same input. |
| Missing or inaccessible resource | Check the ID, identity, and organization. Inaccessible resources can appear as NOT_FOUND. |
| Expired or revoked identity | Authenticate again through your host or remote login flow. |
| Unsupported fixed scope | Upgrade the API; see compatibility. |
| Rate limit | Observe the API's retry guidance. |
| Lost mutation response | Inspect stored state before resubmitting; mutations are not retried automatically. |
See HTTP errors for transport status codes.
Deployment outcomes
deploy() returns IDs. deployment(id).wait() returns an outcome with status, success, and any
pending prompt or cancellation. ready and no_changes are successful outcomes. A failed or
partially failed deployment does not become successful because its log stream ended.
Handle an action_required prompt explicitly, or supply an onPrompt callback that returns one of
the offered action IDs. See deployment decisions.
Streams
Stream methods return async iterables. Pass an abort signal or stop iteration to release a stream:
import { consumeDeploymentEvents, type OpenshipClient, type ScopedShip } from "openship";
export async function watchLogs(
ship: OpenshipClient | ScopedShip,
deploymentId: string,
signal: AbortSignal,
) {
return consumeDeploymentEvents(ship.deployment(deploymentId).events({ signal }), (event) => {
if (event.log) process.stdout.write(event.log);
});
}Aborting a stream or wait does not cancel the underlying workload. Request that separately with
deployment(id).cancel(). Durable replay across worker restarts is not currently supported.
Pagination
import { iteratePages, type OpenshipClient, type ScopedShip } from "openship";
export async function allProjects(ship: OpenshipClient | ScopedShip, signal?: AbortSignal) {
const ids: string[] = [];
for await (const project of iteratePages((page) => ship.projects.list(page), {
perPage: 50,
signal,
})) {
ids.push(project.id);
}
return ids;
}Use iteratePages with methods returning a page containing data. Methods that return plain arrays
do not use this helper. Authorization applies to every page.