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

emit.run

v0.1.7

Published

TypeScript client library for the full emit.run API surface

Readme

emit.run

TypeScript SDK for emit.run workers, producers, and realtime clients.

This package covers:

  • Jobs API (create/list/poll/claim/lifecycle/progress/log reads)
  • Worker helpers (polling loop + push wake handling)
  • Realtime sockets (connectJob can be anonymous, connectSpace stays authenticated)
  • Claimed job helper object with batched job.log.* writes

The SDK is space-scoped at client initialization.

Installation

npm install emit.run

Create a client

import { EmitClient } from "emit.run";

const client = new EmitClient({
  spaceId: process.env.EMIT_SPACE_ID!,
  apiKey: process.env.EMIT_API_KEY!,
  // optional:
  // baseUrl: "https://emit.run/api/v1",
});

apiKey is optional when you only use public single-job realtime streams (client.realtime.connectJob(...)).

Producer example

const job = await client.jobs.create({
  name: "transcode",
  payload: {
    inputUrl: "s3://bucket/input.mp4",
    outputKey: "output/video-720p.mp4",
  },
  maxRetries: 5,
  timeoutSeconds: 600,
});

console.log(job.id, job.spaceId);

jobs.create() returns a minimal reference for each created job:

// { id: string, spaceId: string }

Worker example (polling)

onJob receives a claimed job helper with lifecycle methods and logger helpers.

await client.workers.runPolling({
  types: ["transcode", "thumbnail"],
  count: 5,
  autoAck: true,
  autoFailOnError: true,
  autoComplete: false,
  keepaliveIntervalMs: 60_000,
  logger: {
    source: "worker-gpu-a",
    maxBatchSize: 100,
    flushIntervalMs: 1_000,
    gzip: true,
  },
  onJob: async (job) => {
    job.log.info("job started", { metadata: { jobId: job.id } });

    await job.progress({
      percent: 15,
      message: "Downloading source",
      subProgress: {
        download: { percent: 15, message: "Connecting" },
      },
    });

    // ...work...

    await job.checkpoint({ offsetSeconds: 90 });
    await job.event({ phase: "transcode", codec: "h264" });

    await job.complete({ outputUrl: "s3://bucket/output.mp4" });
  },
});

Push wake handler example

Use this for emit.run HTTP push payloads (event: "job.pending").

const handlePush = client.workers.createPushHandler({
  autoAck: true,
  autoFailOnError: true,
  onJob: async (job) => {
    job.log.info("woken by push", { metadata: { jobId: job.id } });
    await job.complete({ ok: true });
  },
});

// HTTP handler
// const payload = await request.json()
// const result = await handlePush(payload)

Realtime examples

Job stream

connectJob supports anonymous progress-only streams (no apiKey required).

const connection = client.realtime.connectJob("job_123", {
  autoReconnect: true,
  onEvent: (event) => {
    if (event.type === "progress") {
      console.log("progress", event.data);
    }
    if (event.type === "completed") {
      connection.close();
    }
  },
});

Space stream

client.realtime.connectSpace(client.spaceId, {
  autoReconnect: true,
  onEvent: (event) => {
    console.log(event.type, event.jobId, event.status, event.seq);
  },
});

Surface area

client.jobs

  • create(job | jobs[])
  • list(query?)
  • poll(request?)
  • claim(jobId)
  • get(jobId)
  • getProgress(jobId)
  • getLogs(jobId, query?)
  • ack(jobId)
  • progress(jobId, payload)
  • checkpoint(jobId, payload)
  • event(jobId, payload)
  • complete(jobId, result?)
  • fail(jobId, error?)
  • kill(jobId, reason?)
  • keepalive(jobId)
  • createClaimedJob(snapshot, loggerOptions?)

Claimed job helper (onJob arg)

  • job.ack()
  • job.progress(payload)
  • job.checkpoint(payload)
  • job.event(payload)
  • job.complete(result?)
  • job.fail(error?)
  • job.kill(reason?)
  • job.keepalive()
  • job.getDetails()
  • job.getProgress()
  • job.getLogs(query?)
  • job.log.trace/debug/info/warn/error/fatal(message, options?)
  • job.log.flush()
  • job.log.close()

client.workers

  • runPolling(options)
  • handlePush(payload, options)
  • createPushHandler(options)

client.realtime

  • connectJob(jobId, options?)
  • connectSpace(spaceId, options?)

Defaults and optional options

EmitClient options

| Option | Required | Default | Notes | | --- | --- | --- | --- | | spaceId | Yes | - | Space bound to this client instance | | apiKey | No | - | Required for authenticated REST calls and connectSpace; optional for anonymous connectJob | | baseUrl | No | https://emit.run/api/v1 | Set for staging/self-hosted | | apiKeyHeader | No | x-api-key | x-api-key or authorization | | headers | No | {} | Merged into every request | | credentials | No | same-origin | Passed to fetch | | fetch | No | globalThis.fetch | Custom runtime fetch | | webSocketFactory | No | globalThis.WebSocket | Needed on runtimes without global WS |

workers.runPolling options

| Option | Required | Default | Notes | | --- | --- | --- | --- | | onJob | Yes | - | Claimed job handler | | count | No | 1 | Poll batch size | | types | No | none | Name/type filter for poll | | pollIntervalMs | No | 1000 | Base idle delay | | maxBackoffMs | No | 15000 | Backoff cap when no jobs/errors | | autoAck | No | true | Calls job.ack() before handler | | autoFailOnError | No | true | Calls job.fail(...) on thrown errors | | autoComplete | No | false | Completes with handler return value | | keepaliveIntervalMs | No | disabled | Calls job.keepalive() on interval | | stopOnError | No | false | Rethrows worker loop errors | | onError | No | none | Error callback after handler failure | | logger | No | defaults below | Claimed-job logger config | | signal | No | none | Abort signal for loop shutdown |

Logger options (logger)

| Option | Required | Default | Notes | | --- | --- | --- | --- | | flushIntervalMs | No | 1000 | Time-based flush interval | | maxBatchSize | No | 100 | Flush when queue reaches this size | | maxBufferedEntries | No | 10000 | Queue cap (oldest entries dropped) | | gzip | No | true | gzip NDJSON body when runtime supports it | | source | No | none | Default source for job.log.* calls |

workers.handlePush / createPushHandler options

Uses the same execution options as runPolling (onJob, autoAck, autoFailOnError, autoComplete, keepaliveIntervalMs, stopOnError, onError, logger).

Realtime options

| Option | Required | Default | Notes | | --- | --- | --- | --- | | token | No | client apiKey (when configured) | Explicit realtime token override | | autoReconnect | No | false | Reconnect on close/error | | reconnectDelayMs | No | 1000 | Initial reconnect delay | | maxReconnectDelayMs | No | 15000 | Exponential backoff cap | | signal | No | none | Abort closes connection | | onOpen | No | none | Open callback | | onEvent | No | none | Message callback | | onError | No | none | Error callback | | onClose | No | none | Close callback |

For connectSpace, you can also pass:

| Option | Required | Default | Notes | | --- | --- | --- | --- | | since | No | none | Resume cursor | | streamInstanceId | No | none | Restart detection cursor |

Development

npm install
npm run typecheck
npm test
npm run build