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

@roset/sdk

v0.1.2

Published

TypeScript SDK for the Roset transformation engine — upload files, get markdown, embeddings, metadata, thumbnails, and searchable index

Readme

Upload any unstructured file — get back markdown, embeddings, metadata, thumbnails, and a searchable index. The TypeScript SDK for the Roset unstructured-to-structured transformation engine.

Installation

npm install @roset/sdk

Quick Start

import { RosetClient } from "@roset/sdk";

const roset = new RosetClient({ apiKey: process.env.ROSET_API_KEY });

// Upload a file — Roset routes to the right extraction provider
const { file_id, job_id, upload_url } = await roset.files.upload({
  filename: "report.pdf",
  content_type: "application/pdf",
  size_bytes: 102400,
});

// PUT your file bytes directly to the signed URL
await fetch(upload_url, { method: "PUT", body: fileBuffer });

// Check processing status
const job = await roset.jobs.get(job_id);
console.log(job.status); // "completed"

// Retrieve extracted variants
const { variants } = await roset.files.getVariants(file_id);
for (const v of variants) {
  console.log(`${v.type} — ${v.provider} — ${v.size_bytes} bytes`);
}

Features

| Resource | Methods | Description | |----------|---------|-------------| | files | upload, list, get, delete, getVariants, process, processBatch, uploadBatch, getBatch | Upload files, retrieve variants (markdown, embeddings, thumbnails, metadata) | | jobs | list, get, cancel, retry | Track processing status, cancel or retry jobs | | connections | create, list, get, delete, test, sync, enumerate | Manage storage provider connections (S3, GCS, Azure, R2, MinIO, Supabase) | | nodes | list, get, delete, download, upload, move, rename, listChildren, search | Browse and manipulate files/folders in connected storage | | webhooks | create, list, get, update, delete, test, listDeliveries, replay, verify | Subscribe to processing lifecycle events | | search | query | Full-text, vector, or hybrid search across files | | qa | ask | RAG-powered Q&A with source citations | | spaces | list, getStats | Optional namespace isolation for multi-tenant apps | | apiKeys | create, list, delete | Create and revoke organization API keys | | providerKeys | set, get, delete | Manage BYOK extraction provider credentials | | analytics | overview, processing, fileTypes, spaces, failures, volume, trends, providers, topFailures, storageGrowth | Processing metrics and statistics |

Authentication

// API key auth (server-side)
const roset = new RosetClient({ apiKey: "rsk_..." });

// Dynamic token auth (browser with Clerk)
const roset = new RosetClient({
  getAccessToken: () => clerk.session.getToken(),
});

// Custom base URL for self-hosted or local development
const roset = new RosetClient({
  apiKey: "rsk_...",
  baseUrl: "http://localhost:8787",
});

Resources

Files

// Upload with progress tracking
const result = await roset.files.upload({
  filename: "report.pdf",
  content_type: "application/pdf",
  size_bytes: 102400,
  space: "acme-corp",
  onProgress: (event) => console.log(event.stage), // uploading -> queued -> processing -> completed
});

// List files with filtering
const { files, next_cursor } = await roset.files.list({
  space: "acme-corp",
  status: "completed",
  limit: 50,
});

// Get a single file
const file = await roset.files.get("file-id");

// Get processing variants
const { variants } = await roset.files.getVariants("file-id");

// Trigger processing on an existing file
await roset.files.process("file-id", {
  provider: "reducto",
  variants: ["markdown", "embeddings"],
});

// Batch upload with concurrency control
const batch = await roset.files.uploadBatch(
  [
    { filename: "a.pdf", content_type: "application/pdf", size_bytes: 1024 },
    { filename: "b.pdf", content_type: "application/pdf", size_bytes: 2048 },
  ],
  { concurrency: 3 },
);
console.log(`${batch.succeeded}/${batch.total} uploaded`);

// Delete a file
await roset.files.delete("file-id");

Jobs

// List processing jobs
const { jobs } = await roset.jobs.list({ status: "failed", limit: 10 });

// Get job details
const job = await roset.jobs.get("job-id");

// Cancel an in-progress job
await roset.jobs.cancel("job-id");

// Retry a failed job
await roset.jobs.retry("job-id");

Connections

// Create an S3 connection
const conn = await roset.connections.create({
  name: "Production S3",
  provider: "s3",
  bucket_name: "my-bucket",
  region: "us-east-1",
  credentials: { access_key_id: "...", secret_access_key: "..." },
});

// Test connectivity
const { success } = await roset.connections.test(conn.id);

// Trigger a metadata sync
await roset.connections.sync(conn.id);

// List all connections
const { connections } = await roset.connections.list();

// Enumerate bucket contents
const objects = await roset.connections.enumerate(conn.id, { prefix: "documents/" });

Nodes

// List nodes in a connection
const { nodes } = await roset.nodes.list({ connection_id: "conn-id" });

// Get a signed download URL
const { url } = await roset.nodes.download("node-id");

// Upload to connected storage
const { node, upload_url } = await roset.nodes.upload("conn-id", {
  filename: "invoice.pdf",
  content_type: "application/pdf",
});

// Move and rename
await roset.nodes.move("node-id", { parent_id: "folder-id" });
await roset.nodes.rename("node-id", "new-name.pdf");

// Search nodes by name
const results = await roset.nodes.search("invoice", { connection_id: "conn-id" });

Search

// Hybrid search (default — combines full-text and vector)
const { results } = await roset.search.query({
  query: "payment terms",
  space: "contracts",
});

// Full-text search
const { results } = await roset.search.query({
  query: "quarterly revenue",
  mode: "text",
  limit: 10,
});

// Vector similarity search
const { results } = await roset.search.query({
  query: "financial obligations and liabilities",
  mode: "vector",
});

Q&A

// Ask a question with RAG-powered answers
const { answer, sources } = await roset.qa.ask({
  question: "What are the payment terms in the contract?",
  space: "contracts",
  topK: 5,
});

console.log(answer);
for (const source of sources) {
  console.log(`  - ${source.filename} (score: ${source.score})`);
}

Webhooks

// Create a webhook subscription
const webhook = await roset.webhooks.create({
  url: "https://example.com/webhooks/roset",
  events: ["file.processing.completed", "file.processing.failed"],
});

// Update events or disable
await roset.webhooks.update(webhook.id, { enabled: false });

// Send a test event
await roset.webhooks.test(webhook.id);

// Inspect delivery history
const { deliveries } = await roset.webhooks.listDeliveries(webhook.id);

// Replay events
await roset.webhooks.replay(webhook.id, {
  since: "2026-01-01T00:00:00Z",
  event_types: ["file.processing.completed"],
});

Spaces

// List all spaces
const { spaces } = await roset.spaces.list();

// Get per-space statistics
const stats = await roset.spaces.getStats("acme-corp");

API Keys

// Create a new API key
const { key } = await roset.apiKeys.create({
  name: "CI/CD Pipeline",
  mode: "live",
  scopes: ["files:read", "files:write"],
});
// Store `key` securely — it is only returned once

// List keys (values are never returned)
const { api_keys } = await roset.apiKeys.list();

// Revoke a key
await roset.apiKeys.delete("key-id");

Provider Keys

// Set a BYOK extraction provider key
await roset.providerKeys.set({ provider: "reducto", key: "rdc_..." });

// Check which providers have keys configured
const { provider_keys } = await roset.providerKeys.get();

// Remove a provider key
await roset.providerKeys.delete("reducto");

Analytics

// High-level overview
const overview = await roset.analytics.overview();

// Processing pipeline stats (last 30 days)
const processing = await roset.analytics.processing(30);

// File type breakdown, volume, trends, storage growth
const types = await roset.analytics.fileTypes();
const volume = await roset.analytics.volume(7);
const trends = await roset.analytics.trends(30);
const storage = await roset.analytics.storageGrowth(90);

// Provider utilization
const providers = await roset.analytics.providers(30);

// Failure analysis
const failures = await roset.analytics.failures(20);
const topFailures = await roset.analytics.topFailures(10);

// Per-space analytics
const spacesAnalytics = await roset.analytics.spaces();

Webhook Verification

Verify incoming webhook signatures using HMAC-SHA256 (Web Crypto API, works everywhere):

import { verifyWebhookSignature } from "@roset/sdk";

// In your webhook handler (Express, Hono, etc.)
const event = await verifyWebhookSignature(
  rawBody,                              // raw request body string
  request.headers["x-roset-signature"], // "sha256=..." header
  process.env.WEBHOOK_SECRET,           // your signing secret
);

switch (event.type) {
  case "file.processing.completed":
    console.log(`File ${event.data.file_id} processed by ${event.data.provider}`);
    break;
  case "file.processing.failed":
    console.error(`Processing failed: ${event.data.error.message}`);
    break;
  case "file.variant.ready":
    console.log(`Variant ${event.data.variant_type} ready for file ${event.data.file_id}`);
    break;
}

Supported webhook event types:

  • file.created, file.deleted
  • file.processing.started, file.processing.completed, file.processing.failed
  • file.variant.ready
  • job.completed, job.failed
  • batch.completed
  • connection.synced

Error Handling

All API errors are mapped to typed error classes with instanceof support:

import {
  RosetClient,
  RosetError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  QuotaExceededError,
  UnauthorizedError,
  ForbiddenError,
  ConflictError,
  TimeoutError,
  ServerError,
  ServiceUnavailableError,
  NetworkError,
} from "@roset/sdk";

try {
  await roset.files.get("nonexistent-id");
} catch (err) {
  if (err instanceof NotFoundError) {
    console.error("File not found");
  } else if (err instanceof RateLimitError) {
    console.error(`Rate limited — retry after ${err.retryAfter}s`);
  } else if (err instanceof QuotaExceededError) {
    console.error("Upgrade your plan");
  } else if (err instanceof ValidationError) {
    console.error("Invalid request:", err.details);
  } else if (err instanceof RosetError) {
    console.error(`${err.code} (${err.statusCode}): ${err.message}`);
    if (err.retryable) {
      // Safe to retry: 429, 503, 504, 5xx
    }
  }
}

| Status | Error Class | Retryable | |--------|-------------|-----------| | 400 | ValidationError | No | | 401 | UnauthorizedError | No | | 402 | QuotaExceededError | No | | 403 | ForbiddenError | No | | 404 | NotFoundError | No | | 409 | ConflictError | No | | 429 | RateLimitError | Yes | | 500 | ServerError | Yes | | 503 | ServiceUnavailableError | Yes | | 504 | TimeoutError | Yes | | Network | NetworkError | Yes |

Environment Support

The SDK uses the Web fetch API and Web Crypto API with zero native dependencies, making it compatible with:

  • Node.js 18+
  • Cloudflare Workers
  • Deno
  • Bun

Documentation

Full API docs at docs.roset.dev/sdk/typescript.

License

Apache 2.0 © Roset