npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@prisma/compute-sdk

v0.2.0

Published

TypeScript SDK for deploying and managing applications on Prisma Compute

Readme

@prisma/compute-sdk

TypeScript SDK for deploying and managing applications on Prisma Compute.

Installation

npm install @prisma/compute-sdk @prisma/management-api-sdk

@prisma/management-api-sdk is a peer dependency that provides the authenticated API client.

Prerequisites

You need an authenticated ManagementApiClient from @prisma/management-api-sdk. There are two ways to create one:

Using a service token

import { createManagementApiClient } from "@prisma/management-api-sdk";

const apiClient = createManagementApiClient({
  token: process.env.PRISMA_API_TOKEN,
});

Using OAuth

import { createManagementApiSdk } from "@prisma/management-api-sdk";

const sdk = createManagementApiSdk({
  clientId: "your-client-id",
  redirectUri: "http://localhost:3000/callback",
  tokenStorage: yourTokenStorageImpl, // implements TokenStorage interface
});

// sdk.client is a ManagementApiClient with automatic token refresh
const apiClient = sdk.client;

See the @prisma/management-api-sdk documentation for full details on authentication setup.

Quick start

import { ComputeClient, PreBuilt, Ok } from "@prisma/compute-sdk";
import { createManagementApiClient } from "@prisma/management-api-sdk";

const apiClient = createManagementApiClient({
  token: process.env.PRISMA_API_TOKEN,
});

const compute = new ComputeClient(apiClient);

// Deploy a pre-built application
const result = await compute.deploy({
  strategy: new PreBuilt({
    appPath: "./dist",
    entrypoint: "index.js",
  }),
  projectId: "your-project-id",
  serviceName: "my-app",
  region: "us-east-1",
});

if (result.isOk()) {
  console.log(`Deployed to ${result.value.deploymentUrl}`);
} else {
  console.error(`Deploy failed: ${result.error.message}`);
}

API reference

ComputeClient

The main entry point for all operations. Created from a ManagementApiClient:

import { ComputeClient } from "@prisma/compute-sdk";

const compute = new ComputeClient(apiClient);

All methods return Promise<Result<T, E>> — a discriminated union that is either Ok with a value or Err with a typed error. Each method declares only the error variants it can actually produce. See Error handling for details.


deploy(options): Promise<Result<DeployResult, DeployError>>

Builds, uploads, and deploys an application version.

const result = await compute.deploy({
  // Required: how to produce the deployable artifact
  strategy: new PreBuilt({ appPath: "./dist", entrypoint: "index.js" }),

  // Target (provide serviceId OR projectId + serviceName + region)
  projectId: "proj_abc",
  serviceName: "my-app",
  region: "us-east-1",
  // OR:
  serviceId: "svc_xyz",

  // Optional
  envVars: { DATABASE_URL: "postgresql://..." },
  portMapping: { http: 3000 },
  timeoutSeconds: 120,       // max time to wait for "running" status
  pollIntervalMs: 1000,      // how often to check status
  signal: abortController.signal,
  progress: { /* DeployProgress callbacks */ },
  interaction: { /* DeployInteraction callbacks */ },
});

if (result.isOk()) {
  const { deploymentUrl, versionId, serviceId, resolvedConfig } = result.value;
}

Returns DeployResult:

| Field | Type | Description | | ---------------- | ---------------- | ---------------------------------------- | | projectId | string | Project ID | | serviceId | string | Service ID | | serviceName | string | Service display name | | region | string | Region identifier | | versionId | string | Created version ID | | deploymentUrl | string | Live URL of the deployment | | resolvedConfig | ResolvedConfig | Final resolved configuration |


updateEnv(options): Promise<Result<UpdateEnvResult, UpdateEnvError>>

Creates a new version with updated environment variables and/or port mapping, reusing the code from the most recent deployment.

const result = await compute.updateEnv({
  serviceId: "svc_xyz",
  envVars: { DATABASE_URL: "postgresql://new-url..." },
  portMapping: { http: 8080 },
});

The service must have at least one existing version. If not, this returns a NoExistingVersionError.


destroyVersion(options): Promise<Result<DestroyVersionResult, DestroyVersionError>>

Stops (if running) and deletes a single version.

const result = await compute.destroyVersion({
  versionId: "ver_abc",
  // OR provide serviceId + interaction.selectVersion for interactive selection
});

Returns DestroyVersionResult:

| Field | Type | Description | | ---------------- | --------- | ---------------------------------------- | | versionId | string | The destroyed version ID | | previousStatus | string | Status before destruction | | stopped | boolean | Whether a stop was required | | deleted | boolean | Whether deletion succeeded |


destroyService(options): Promise<Result<DestroyServiceResult, DestroyServiceError>>

Stops all running versions, deletes all versions, and optionally deletes the service itself.

const result = await compute.destroyService({
  serviceId: "svc_xyz",
  keepService: false, // set to true to keep the service record
});

If some versions fail to stop or delete, returns a DestroyAggregateError with details on which succeeded and which failed.


listProjects(options?): Promise<Result<ProjectInfo[], ApiRequestError>>

const result = await compute.listProjects();
if (result.isOk()) {
  for (const project of result.value) {
    console.log(`${project.name} (${project.id})`);
  }
}

listServices(options): Promise<Result<ServiceInfo[], ApiRequestError>>

const result = await compute.listServices({ projectId: "proj_abc" });

createService(options): Promise<Result<ServiceInfo, ApiRequestError>>

const result = await compute.createService({
  projectId: "proj_abc",
  serviceName: "my-new-service",
  region: "eu-west-3",
});

showService(options): Promise<Result<ServiceDetail, ApiRequestError>>

const result = await compute.showService({ serviceId: "svc_xyz" });
if (result.isOk()) {
  console.log(`Latest version: ${result.value.latestVersionId}`);
}

deleteService(options): Promise<Result<void, ApiRequestError>>

Deletes a service record. The service should have no versions (use destroyService to clean up versions first).

await compute.deleteService({ serviceId: "svc_xyz" });

listVersions(options): Promise<Result<VersionInfo[], ApiRequestError>>

const result = await compute.listVersions({ serviceId: "svc_xyz" });

showVersion(options): Promise<Result<VersionDetail, ApiRequestError>>

const result = await compute.showVersion({ versionId: "ver_abc" });
if (result.isOk()) {
  console.log(`Status: ${result.value.status}`);
  console.log(`URL: https://${result.value.previewDomain}`);
}

startVersion(options): Promise<Result<void, ApiRequestError>>

await compute.startVersion({ versionId: "ver_abc" });

stopVersion(options): Promise<Result<void, ApiRequestError>>

await compute.stopVersion({ versionId: "ver_abc" });

deleteVersion(options): Promise<Result<void, ApiRequestError>>

await compute.deleteVersion({ versionId: "ver_abc" });

Build strategies

A build strategy produces a deployable artifact (a directory with an entrypoint file). The SDK ships with two built-in strategies:

PreBuilt

Use when your application is already built (e.g., output of tsc, esbuild, or any other bundler):

import { PreBuilt } from "@prisma/compute-sdk";

const strategy = new PreBuilt({
  appPath: "./dist",        // absolute or relative path to the build output
  entrypoint: "index.js",   // relative to appPath
});

PreBuilt validates that the entrypoint exists and is a relative path that doesn't escape the application directory. It performs no copying or transformation.

BunBuild

Use when you want the SDK to bundle your application using Bun:

import { BunBuild } from "@prisma/compute-sdk";

const strategy = new BunBuild({
  appPath: "./my-app",          // path to your application source
  entrypoint: "src/index.ts",   // optional: resolved from package.json "main" if omitted
});

BunBuild runs bun build with --target bun --sourcemap=external, manages a temporary output directory, and cleans it up after the archive is created. Requires Bun to be installed on the machine.

Custom strategies

Implement the BuildStrategy interface to use any build tool:

import type { BuildStrategy, BuildArtifact } from "@prisma/compute-sdk";

class MyCustomBuild implements BuildStrategy {
  async execute(): Promise<BuildArtifact> {
    // Run your build process...
    return {
      directory: "/path/to/output",   // absolute path to the built files
      entrypoint: "index.js",         // relative to directory, posix separators
      cleanup: async () => {          // optional: called after archiving
        // clean up temp files
      },
    };
  }
}

Error handling

All ComputeClient methods return Result<T, E> from the better-result library instead of throwing exceptions. This gives you exhaustive, type-safe error handling.

Checking results

const result = await compute.deploy({ /* ... */ });

// Pattern 1: isOk / isErr
if (result.isOk()) {
  console.log(result.value.deploymentUrl);
} else {
  console.error(result.error.message);
}

// Pattern 2: match
result.match({
  Ok: (value) => console.log(value.deploymentUrl),
  Err: (error) => console.error(error.message),
});

Error types

Every error extends TaggedError and has a _tag discriminant for pattern matching:

| Error class | _tag | Description | | ------------------------ | ------------------------- | ------------------------------------------------------------- | | AuthenticationError | "AuthenticationError" | API returned HTTP 401 | | ApiError | "ApiError" | API returned a non-401 error | | MissingArgumentError | "MissingArgumentError" | A required argument was not provided | | BuildError | "BuildError" | Build strategy failed | | ArtifactError | "ArtifactError" | Archive creation or upload failed | | TimeoutError | "TimeoutError" | Version didn't reach target status in time | | VersionFailedError | "VersionFailedError" | Version transitioned to "failed" status | | NoExistingVersionError | "NoExistingVersionError"| updateEnv called on a service with no prior deployments | | CancelledError | "CancelledError" | Operation cancelled via AbortSignal | | DestroyAggregateError | "DestroyAggregateError" | Some versions failed during destroyService |

Matching specific errors

import { matchError, ApiError, AuthenticationError } from "@prisma/compute-sdk";

const result = await compute.deploy({ /* ... */ });

if (result.isErr()) {
  matchError(result.error, {
    AuthenticationError: (e) => {
      console.error("Not authenticated. Check your token.");
    },
    ApiError: (e) => {
      console.error(`API error (${e.statusCode}): ${e.message}`);
      if (e.hint) console.error(`Hint: ${e.hint}`);
    },
    BuildError: (e) => {
      console.error(`Build failed: ${e.message}`);
    },
    TimeoutError: (e) => {
      console.error(`Timed out after ${Math.round(e.elapsedMs / 1000)}s`);
    },
    _: (e) => {
      console.error(`Unexpected error: ${e.message}`);
    },
  });
}

Error type unions

The SDK exports narrowed error unions for each operation:

  • DeployError — errors from deploy(): CancelledError | MissingArgumentError | AuthenticationError | ApiError | BuildError | ArtifactError | TimeoutError | VersionFailedError
  • UpdateEnvError — errors from updateEnv(): CancelledError | MissingArgumentError | AuthenticationError | ApiError | NoExistingVersionError | TimeoutError | VersionFailedError
  • DestroyVersionError — errors from destroyVersion(): CancelledError | MissingArgumentError | AuthenticationError | ApiError | TimeoutError | VersionFailedError
  • DestroyServiceError — errors from destroyService(): CancelledError | AuthenticationError | ApiError | DestroyAggregateError
  • ApiRequestError — errors from simple CRUD methods (listProjects, listServices, createService, etc.): CancelledError | AuthenticationError | ApiError

Progress and interaction callbacks

Long-running operations accept progress and interaction callbacks for UI integration.

Deploy progress

await compute.deploy({
  strategy,
  projectId: "proj_abc",
  serviceName: "my-app",
  region: "us-east-1",
  progress: {
    onBuildStart() {
      console.log("Building...");
    },
    onBuildComplete(artifact) {
      console.log(`Built to ${artifact.directory}`);
    },
    onArchiveCreating() {
      console.log("Creating archive...");
    },
    onArchiveReady(sizeBytes) {
      console.log(`Archive: ${(sizeBytes / 1024).toFixed(1)} KB`);
    },
    onVersionCreated(versionId) {
      console.log(`Version: ${versionId}`);
    },
    onUploadStart() {
      console.log("Uploading...");
    },
    onUploadComplete() {
      console.log("Upload complete.");
    },
    onStartRequested() {
      console.log("Starting...");
    },
    onStatusChange(status) {
      console.log(`Status: ${status}`);
    },
    onRunning(deploymentUrl) {
      console.log(`Live at ${deploymentUrl}`);
    },
  },
});

Deploy interaction

When projectId, serviceId, or region are not provided, the SDK calls interaction callbacks to let the consumer resolve them (e.g., by prompting the user):

await compute.deploy({
  strategy,
  interaction: {
    async selectProject(projects) {
      // projects: ProjectInfo[] — return the chosen project ID
      return projects[0].id;
    },
    async selectService(services) {
      // services: ServiceInfo[] — return a service ID, or null to create a new one
      return null;
    },
    async provideServiceName() {
      // return a name for the new service
      return "my-new-service";
    },
    async selectRegion(regions) {
      // regions: RegionInfo[] — return the chosen region ID
      return "us-east-1";
    },
  },
});

Destroy progress

await compute.destroyService({
  serviceId: "svc_xyz",
  progress: {
    onStoppingVersions(versionIds) { /* ... */ },
    onVersionStopped(versionId) { /* ... */ },
    onAllVersionsStopped() { /* ... */ },
    onDeletingVersions(versionIds) { /* ... */ },
    onVersionDeleted(versionId) { /* ... */ },
    onAllVersionsDeleted() { /* ... */ },
    onServiceDeleted(serviceId) { /* ... */ },
  },
});

Cancellation

All operations support cancellation via the standard AbortSignal:

const controller = new AbortController();

// Cancel after 30 seconds
setTimeout(() => controller.abort(), 30_000);

const result = await compute.deploy({
  strategy,
  serviceId: "svc_xyz",
  signal: controller.signal,
});

if (result.isErr() && result.error._tag === "CancelledError") {
  console.log("Deployment was cancelled.");
}

Domain types

import type {
  ProjectInfo,       // { id, name, defaultRegion? }
  ServiceInfo,       // { id, name, region, projectId, createdAt? }
  ServiceDetail,     // ServiceInfo & { latestVersionId? }
  VersionInfo,       // { id, status, createdAt, previewDomain? }
  VersionDetail,     // VersionInfo & { envVars? }
  RegionInfo,        // { id, displayName }
  ResolvedConfig,    // { projectId, serviceId, serviceName, region, portMapping? }
  PortMapping,       // { http?: number | null }
} from "@prisma/compute-sdk";

Available regions

import { REGIONS, KNOWN_REGION_IDS } from "@prisma/compute-sdk";

// KNOWN_REGION_IDS: readonly ["us-east-1", "us-west-1", "eu-west-3", "eu-central-1", "ap-northeast-1", "ap-southeast-1"]
// REGIONS: RegionInfo[] — same IDs with displayName

Full example

import { ComputeClient, PreBuilt, matchError } from "@prisma/compute-sdk";
import { createManagementApiClient } from "@prisma/management-api-sdk";

async function main() {
  const apiClient = createManagementApiClient({
    token: process.env.PRISMA_API_TOKEN!,
  });

  const compute = new ComputeClient(apiClient);

  // Deploy
  const deployResult = await compute.deploy({
    strategy: new PreBuilt({
      appPath: "./dist",
      entrypoint: "server.js",
    }),
    projectId: process.env.PROJECT_ID!,
    serviceName: "my-api",
    region: "us-east-1",
    envVars: {
      DATABASE_URL: process.env.DATABASE_URL!,
      NODE_ENV: "production",
    },
    portMapping: { http: 3000 },
    progress: {
      onBuildStart: () => console.log("Preparing artifact..."),
      onUploadStart: () => console.log("Uploading..."),
      onStartRequested: () => console.log("Starting..."),
      onStatusChange: (s) => console.log(`  Status: ${s}`),
      onRunning: (url) => console.log(`Deployed: ${url}`),
    },
  });

  if (deployResult.isErr()) {
    matchError(deployResult.error, {
      AuthenticationError: () => {
        console.error("Invalid token. Set PRISMA_API_TOKEN.");
        process.exit(1);
      },
      BuildError: (e) => {
        console.error(`Build failed: ${e.message}`);
        process.exit(1);
      },
      TimeoutError: (e) => {
        console.error(`Deploy timed out (${Math.round(e.elapsedMs / 1000)}s).`);
        console.error(`Version ${e.versionId} may still be starting.`);
        process.exit(1);
      },
      _: (e) => {
        console.error(`Error: ${e.message}`);
        process.exit(1);
      },
    });
    return;
  }

  const { serviceId, versionId, deploymentUrl } = deployResult.value;
  console.log(`\nService: ${serviceId}`);
  console.log(`Version: ${versionId}`);
  console.log(`URL:     ${deploymentUrl}`);

  // List versions
  const versionsResult = await compute.listVersions({ serviceId });
  if (versionsResult.isOk()) {
    console.log(`\nVersions (${versionsResult.value.length}):`);
    for (const v of versionsResult.value) {
      console.log(`  ${v.id} — ${v.status} (${v.createdAt})`);
    }
  }
}

main();

Requirements

  • Node.js >= 18.0.0
  • @prisma/management-api-sdk >= 1.20.1

License

Apache-2.0