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

@tacticdb/client

v0.1.0

Published

TacticDB client SDK: list, read, and (where an app's access policy allows) create, update, or delete records from a browser or any fetch-capable runtime.

Readme

@tacticdb/client

The official client SDK for TacticDB. List, read, and — where an app's access policy allows — create, update, and delete records from a browser, Node.js, or any other fetch-capable JavaScript runtime.

  • Tiny and dependency-free. Ships as ESM with full TypeScript types; no runtime dependencies.
  • Type-safe records. Bring your own record type and every method is typed end to end.
  • Predictable errors. Every failure — network, HTTP, or bad configuration — is thrown as a single TacticDbError.
  • Runs anywhere fetch does. Browsers, Node 18+, Deno, Bun, Cloudflare Workers, and more.
import { createTacticDbClient } from '@tacticdb/client';

const db = createTacticDbClient({
  baseUrl: 'https://api.example.com',
  appId: 'product-catalog',
  apiKey: 'pk_live_…', // optional; see Authentication
});

const products = db.table('products');
const { items } = await products.list({ where: { status: 'active' }, take: 20 });

Installation

npm install @tacticdb/client
# or
pnpm add @tacticdb/client
# or
yarn add @tacticdb/client

Requires Node.js 18+ (for a global fetch) or any runtime with a fetch implementation you can pass in. The package is ESM-only.

Without a build step (CDN)

<script type="module">
  import { createTacticDbClient } from 'https://unpkg.com/@tacticdb/client/dist/tacticdb-client.esm.js';
  const db = createTacticDbClient({ baseUrl: 'https://api.example.com', appId: 'product-catalog' });
</script>

A UMD/global build is also published at dist/tacticdb-client.global.js (exposes window.TacticDB).

Quick start

import { createTacticDbClient, TacticDbError } from '@tacticdb/client';

// Describe your record's data shape (the fields you defined on the table).
interface Product {
  name: string;
  sku: string;
  price: number;
  status: 'active' | 'draft';
}

const db = createTacticDbClient({
  baseUrl: 'https://api.example.com',
  appId: 'product-catalog',
  apiKey: import.meta.env.TACTICDB_KEY,
});

const products = db.table<Product>('products');

try {
  // Create
  const created = await products.create({ name: 'Drill', sku: 'DR-01', price: 79, status: 'active' });

  // Read one
  const one = await products.get(created.id);

  // List with filters + paging
  const { items } = await products.list({
    where: { status: 'active' },
    orderBy: 'price',
    direction: 'desc',
    take: 25,
  });

  // Update
  await products.update(created.id, { price: 69 });

  // Delete (archives the record)
  await products.delete(created.id);
} catch (err) {
  if (err instanceof TacticDbError) {
    console.error(err.code, err.status, err.message);
  }
}

Core concepts

ClientcreateTacticDbClient(options) returns a client scoped to a single TacticDB app. Construction is synchronous and makes no network request; an invalid baseUrl or appId throws immediately.

Table clientdb.table<T>(name) returns a handle scoped to one table with five methods: list, get, create, update, delete.

Record — every read or write resolves to a TacticDbRecord<T>:

type TacticDbRecord<T> = {
  id: string;          // the record's unique id
  name: string;        // display value derived from the table's display field
  isArchived: boolean; // archived records are hidden from normal listings
  data: T;             // your fields
};

API at a glance

| Method | Description | | --- | --- | | db.table<T>(name) | Get a table client scoped to name. | | table.list(options?) | List records. Returns { items, total? }. Default page size is 50. | | table.get(id) | Fetch one record by id. | | table.create(data) | Create a record. Generates an id if data.id is absent. | | table.update(id, data, opts?) | Update a record's fields. | | table.delete(id, opts?) | Archive a record. |

list options: where, parentId, orderBy, direction ('asc' | 'desc'), skip, take, includeFields. See docs/querying-records.md.

Error handling

Nothing rejects with a raw fetch error or an unhandled non-2xx response — every failure is a TacticDbError carrying a machine-readable code, the HTTP status (0 when no response was received), and optional details and traceId.

import { TacticDbError } from '@tacticdb/client';

try {
  await products.get('does-not-exist');
} catch (err) {
  if (err instanceof TacticDbError && err.code === 'not_found') {
    // handle a missing record
  }
}

See docs/error-handling.md for the full list of codes.

Documentation

Full guides live in docs/:

Contributing

npm install
npm run typecheck   # tsc --noEmit
npm test            # vitest run
npm run build       # tsup -> dist/

License

MIT