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

@koo-io/sdk

v0.2.0

Published

Koo SDK — a framework-free, typed Node client for the Koo API.

Readme

@koo-io/sdk

A framework-free, typed Node client for the Koo API. No React, no global state, zero runtime dependencies — one KooClient instance per credential, generated from the same OpenAPI spec as the API itself.

npm install @koo-io/sdk

Requires Node >= 20.19. Authenticate with a kc_… service-account API token.

Quickstart

import { KooClient, KooError } from '@koo-io/sdk';

const koo = new KooClient({
  baseUrl: 'https://api.koo.io',
  token: process.env.KOO_TOKEN, // a kc_… service-account token
});

// Who am I? (works with a kc_ token, unlike the browser /me)
const me = await koo.whoami();
if (me.kind !== 'service_account') throw new Error('expected a service-account token');

// Navigate the resource tree: account → project → environment → service.
const svc = koo.account(me.accountId).project('web').environment('prod').service('api');

// Ship an image and watch the deployment pipeline.
const deployment = await svc.deploy({ image: 'ghcr.io/acme/api:sha' });
// status advances: queued → building → built → applied
// `applied` = the release is on the platform; the service then becomes "online" (running).

try {
  await svc.get();
} catch (error) {
  if (error instanceof KooError) {
    console.error(`[${error.code}] ${error.message} (ref ${error.requestId})`);
  }
}

The scope chain

new KooClient({ baseUrl, token | getToken })
  .whoami() / .me()
  .account(accountId)
      .get() · .tokens{ list, create, revoke } · .projects{ list, create }
      .project(projectId)
          .get() · .environments{ list, create }
          .environment(environmentId)
              .get() · .services{ list, create }
              .service(name)
                  .get() · .deploy() · .rollback() · .deployFromArchive()
                  .deployments{ list, buildLogs } · .uploads{ create }
                  .variables{ batch, resolved } · .logs() · .metrics()

Every call takes a trailing { idempotencyKey?, signal? } and returns the unwrapped response body. Every request/response shape is exported as a type.

Variables

A service's variables are written with a single merge-shaped batch{ set, unset } applied atomically, with no read-modify-write and no full-set replace, so untouched variables stay put. resolved returns the effective environment the service receives (project ∪ environment ∪ service, nearest wins) with sensitive values withheld.

const vars = svc.variables;

// Merge in two values and drop one, in one atomic write.
await vars.batch({
  set: [
    { name: 'LOG_LEVEL', value: 'info' },
    { name: 'API_KEY', value: process.env.API_KEY, sensitive: true },
  ],
  unset: ['LEGACY_FLAG'],
});

// What the service actually receives (sensitive values are withheld).
const { data, dangling } = await vars.resolved();

Reveal, blast-radius impact, and the project/environment scopes are deliberately kept off the fluent client — reach for the console or the raw API for those.

Errors

Every call rejects with a KooError carrying a stable code, a human message, optional details, the HTTP status, and a requestId (from the x-request-id response header) to quote to support.

Retries

Idempotent verbs (GET/HEAD/PUT/DELETE) and POSTs that carry an Idempotency-Key are retried on network errors, 429, and 5xx, with full-jitter exponential backoff (250ms · 2^n, capped at 4s) that honours Retry-After. A 4xx other than 429 fails fast on the first request. POSTs get an automatic, stable Idempotency-Key so they are safe to retry (turn off with autoIdempotency: false). The exact policy is documented in the repo's docs/arch/client-http-policy.md.

Options

new KooClient({
  baseUrl: 'https://api.koo.io',
  token: 'kc_…',                 // or getToken: () => Promise<string>
  fetchImpl: customFetch,        // defaults to the global fetch
  retry: { maxAttempts: 3 },     // override any retry knob
  autoIdempotency: true,         // auto-stamp Idempotency-Key on POSTs (default)
});

Publishing

Publishing @koo-io/sdk to npm is an ops step (it is the first artifact in the developer/agent surface release, ahead of @koo-io/mcp-server and the CLI). See the consolidated runbook: docs/runbooks/release-sdk-node.md.

License

MIT