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

@openfactory/sdk

v0.2.4

Published

Typed client for the complete openfactory GraphQL API and event ingestion.

Readme

OpenFactory TypeScript SDK

OpenFactory TypeScript SDK

The official, type-safe TypeScript client for the complete OpenFactory GraphQL API and API-channel event ingestion. It has zero runtime dependencies and works in Node.js 18+, browsers, and edge runtimes wherever fetch is available.

For guides and product documentation, visit openfactory.build/docs. For every generated GraphQL operation and its SDK path, see the GraphQL API reference.

Installation

Install @openfactory/sdk with your preferred package manager:

npm

npm install @openfactory/sdk

pnpm

pnpm add @openfactory/sdk

Bun

bun add @openfactory/sdk

Yarn

yarn add @openfactory/sdk

Quickstart

Create a client for your factory and call any generated GraphQL operation:

import { OpenFactory } from "@openfactory/sdk";

const factory = new OpenFactory({
  baseUrl: "https://factory.example.com",
  apiKey: process.env.OPENFACTORY_API_KEY!,
  teamId: process.env.OPENFACTORY_TEAM_ID,
});

const environments = await factory.environments.list();
const task = await factory.tasks.create({
  title: "Fix checkout retries",
});

if (task.taskId) {
  const checks = await factory.tasks.checks.list({ taskId: task.taskId });
  console.log(checks);
}

When an operation accepts teamId, the configured default is inserted automatically. You can override it for an individual call:

const environments = await factory.environments.list({
  teamId: "team_other",
});

Authentication

OpenFactory supports different credentials for GraphQL and ingestion. Most server-to-server integrations only need an API key.

| Option | Used for | Authorization header | | --- | --- | --- | | apiKey | GraphQL and permitted ingestion calls | ApiKey ofk_... | | accessToken | GraphQL operations that require a human Auth0 session | Bearer ... |

At least one credential is required. If several are provided, the SDK chooses the most specific credential for each transport.

API key permissions

API keys use AWS-style action grants:

  • * grants full access.
  • openfactory:<rootField> grants one GraphQL operation.
  • openfactory:* grants all GraphQL operations.
  • ingestion:events.create permits issues.create and events.emit.
  • ingestion:* grants all ingestion actions.

For example, create an ingestion-only key for an event forwarder:

const key = await factory.apiKeys.create({
  name: "event-forwarder",
  permissions: ["ingestion:events.create"],
});

Send issues and typed events

Use issues.create to send a plain request into OpenFactory:

const { issueId } = await factory.issues.create({
  title: "Checkout returns 500 on Safari",
  body: "The failure started after the latest deploy.",
  authorName: "Sentry",
  externalId: "sentry-123",
});

externalId is an idempotency key. Redelivering the same value deduplicates the request instead of opening another issue.

For named events, parameterize the client with the events declared by your blueprints. TypeScript then validates both the event name and its payload:

type Events = {
  CustomerTicket: {
    ticketId: string;
    subject: string;
    body: string;
  };
  DeployFailed: {
    deployId: string;
    project: string;
    url: string;
  };
};

const factory = new OpenFactory<Events>({
  baseUrl: "https://factory.example.com",
  apiKey: process.env.OPENFACTORY_API_KEY!,
});

await factory.events.emit("CustomerTicket", {
  ticketId: "T-42",
  subject: "Can't export CSV",
  body: "The export button never finishes.",
});

The SDK sends the event name and payload as metadata.event and metadata.payload, where blueprint sensors and trigger filters can use them. The event name is also used as the issue title unless you provide an override:

await factory.events.emit(
  "DeployFailed",
  {
    deployId: "dep_123",
    project: "storefront",
    url: "https://deployments.example.com/dep_123",
  },
  {
    title: "Storefront production deploy failed",
    externalId: "dep_123",
  },
);

List ingested requests

Request history uses explicit page-based pagination and supports user and date filters:

const result = await factory.requests.list({
  externalId: "user_42",
  from: new Date("2026-07-01T00:00:00Z"),
  to: new Date("2026-08-01T00:00:00Z"),
  page: 1,
  limit: 50,
});

console.log(result.requests);
console.log(result.total, result.hasMore);

Pages are 1-based, the default page size is 20, and the maximum page size is 100.

GraphQL namespaces

The generated client organizes the complete GraphQL schema into domain-oriented paths, including:

  • factory.environments.*, factory.tasks.*, and factory.issues.*
  • factory.automations.*, factory.featureRequests.*, and factory.taskQueue.*
  • factory.blueprints.*, factory.repos.*, and factory.pullRequests.*
  • factory.teams.*, factory.users.*, and factory.apiKeys.*
  • factory.agents.*, factory.channels.*, and factory.slack.*
  • factory.qualityAssurance.* and factory.serviceIntegrations.*

Each method accepts typed variables and returns the GraphQL root field directly, without a { data: { ... } } envelope. The complete, operation-by-operation list is in GRAPHQL_API.md.

Raw GraphQL

Use the raw escape hatch for custom queries or operations introduced after your installed SDK version:

const data = await factory.raw.graphql<{
  getTeams: Array<{ id: string; name: string }>;
}>(`
  query Teams {
    getTeams {
      id
      name
    }
  }
`);

console.log(data.getTeams);

Configuration

const factory = new OpenFactory({
  baseUrl: "https://factory.example.com",
  apiKey: process.env.OPENFACTORY_API_KEY!,
  teamId: process.env.OPENFACTORY_TEAM_ID,
  maxRetries: 2,
  timeoutMs: 10_000,
});

| Option | Description | Default | | --- | --- | --- | | baseUrl | OpenFactory origin. Required. | — | | apiKey | ofk_... API key for GraphQL and authorized ingestion. | — | | accessToken | Human access token for GraphQL. | — | | teamId | Default team for GraphQL operations that accept teamId. | — | | graphqlUrl | Override for the GraphQL endpoint. | {baseUrl}/graphql | | maxRetries | Retries after network errors or retryable responses. | 2 | | timeoutMs | Timeout for each request attempt, in milliseconds. | 10_000 | | fetch | Custom fetch implementation for tests or polyfills. | globalThis.fetch |

Retries and errors

The SDK retries network errors and HTTP 408, 429, 500, 502, 503, and 504 responses with exponential backoff. Authentication, validation, and other non-retryable errors fail immediately.

All failed responses and GraphQL errors are surfaced as OpenFactoryError:

import { OpenFactoryError } from "@openfactory/sdk";

try {
  await factory.environments.list();
} catch (error) {
  if (error instanceof OpenFactoryError) {
    console.error(error.message);
    console.error(error.status);
    console.error(error.body);
  }
}

status is the HTTP status when one is available. GraphQL errors returned in a successful HTTP response use status 200, with the GraphQL error list exposed through body.

Runtime and module support

@openfactory/sdk ships both ESM and CommonJS builds with bundled TypeScript declarations. It requires Node.js 18+ or another runtime with a standards-based fetch implementation.

// ESM / TypeScript
import { OpenFactory } from "@openfactory/sdk";
// CommonJS
const { OpenFactory } = require("@openfactory/sdk");

Development

From packages/sdk/typescript:

npm install
npm run generate:graphql
npm run typecheck
npm test
npm run build

generate:graphql regenerates the TypeScript operations and GRAPHQL_API.md from the current OpenFactory GraphQL schema.

License

MIT