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

@kethosbase/client

v0.3.0

Published

Official Kethosbase JavaScript/TypeScript client — auth, database (REST), storage, and realtime. Zero third-party runtime dependencies.

Readme

@kethosbase/client

The official Kethosbase JavaScript/TypeScript client — auth, database (REST), storage, and realtime in one small package.

  • Zero third-party runtime dependencies — nothing but the platform's fetch.
  • Familiar, ergonomic API: createClient, from(...).select().eq(), auth.signInWithPassword, storage.from(...).upload, realtime channels, …
  • TypeScript-first, browser and Node (18+).

Install

npm install @kethosbase/client

Quick start

import { createClient } from "@kethosbase/client";

const kb = createClient("https://<ref>.kethosbase.com", "kbp_your_publishable_key");

// Database
const { data, error } = await kb
  .from("todos")
  .select("*")
  .eq("done", false)
  .order("created_at", { ascending: false })
  .limit(20);

// Auth
await kb.auth.signInWithPassword({ email, password });
const { data: { session } } = await kb.auth.getSession();

// Storage
await kb.storage.from("avatars").upload("me.png", file, { upsert: true });
const { data: signed } = await kb.storage.from("avatars").createSignedUrl("me.png", 60);

Typed client

Pass a generated Database type to createClient<Database>() and from(...) becomes schema-aware: table names are checked, and each query is typed to that table's row and write shapes.

import { createClient } from "@kethosbase/client";
import type { Database } from "./database.types";

const kb = createClient<Database>("https://<ref>.kethosbase.com", "kbp_key");

const { data } = await kb.from("todos").select("*"); // data: Todo[] | null
const { data: one } = await kb.from("todos").select("*").eq("id", 1).single(); // Todo | null

await kb.from("todos").insert({ title: "buy milk" }); // payload checked against Insert
await kb.from("todos").update({ done: true }).eq("id", 1); // Partial<Update>

// @ts-expect-error — unknown column is rejected at compile time
await kb.from("todos").insert({ nope: true });

Generate the Database type from your project's schema with the Kethosbase CLI:

npx @kethosbase/cli gen types > database.types.ts

select() and delete() resolve to Row[]; single()/maybeSingle() to Row | null; insert()/upsert() accept Insert | Insert[]; update() takes Partial<Update>. Calling createClient(...) without a type argument keeps the original loosely-typed behavior, so existing code compiles unchanged.

Limitation: the returned row is always the full table row. The SDK does not yet narrow results from the select("col1,col2") string or from embedded resource selects — that PostgREST select-string inference is out of scope for now. Use an explicit cast if you need a narrowed shape.

Realtime

Kethosbase realtime is a small, native protocol: one WebSocket per channel. You subscribe to a channel by name, receive broadcasts (and database changes on db:<table> channels), and publish broadcasts back. The client reconnects with backoff and re-authenticates with the current session token automatically.

// Broadcast: a lightweight pub/sub channel any client can read and write.
const room = kb
  .channel("room:1")
  .on("broadcast", (payload) => console.log("got", payload))
  .subscribe((status) => console.log(status)); // SUBSCRIBED | CLOSED | CHANNEL_ERROR | TIMED_OUT

await room.send({ msg: "hello", at: Date.now() }); // delivered to all subscribers (incl. you)

// Database changes (CDC): subscribe to a `db:<table>` channel.
const feed = kb
  .channel("db:todos")
  .on("change", (c) => console.log(c.action, c.record, c.old))
  .subscribe();

// Clean up
await kb.removeChannel(room);
await kb.removeAllChannels();

Database-change channels (db:<table>) require a service_role key — they are server-side only and are rejected for anon/publishable keys. Broadcast channels work with any key. The protocol is broadcast-first and live-only (messages are not persisted or replayed); presence and per-table filters are not part of v1.

On non-browser runtimes without a global WebSocket (Node < 22), pass one in:

import WebSocket from "ws";
const kb = createClient(url, key, { realtime: { WebSocket } });

Supported

  • Database: select/insert/update/upsert/delete; filters (eq/neq/gt/gte/lt/lte/like/ilike/is/in); order/limit/range; single/maybeSingle; count: "exact"; schema(name); rpc(fn, args).
  • Auth: signUp, signInWithPassword, signInWithOtp + verifyOtp, signInAnonymously, signInWithOAuth, signOut({ scope }), getSession, getUser, updateUser, refreshSession, setSession, onAuthStateChange. Sessions persist in localStorage (browser) and are auto-recovered from the redirect URL fragment after magic-link / OAuth sign-in. The access token is refreshed automatically — proactively before it expires (auth.autoRefreshToken, default true) and reactively once on a 401 from a data/storage call when a session exists; TOKEN_REFRESHED fires on onAuthStateChange either way.
  • Storage: upload/update, download, list, remove, createSignedUrl, getPublicUrl.
  • Realtime: channel(name) with on("broadcast"|"change"|"system", …), subscribe(onStatus), send(payload), unsubscribe(); removeChannel / removeAllChannels. Auto-reconnect with backoff; token follows the session.

Not yet

  • Chained filters on rpc() results, and MFA helpers.
  • Realtime presence and per-table change filters (not part of the platform's v1 protocol).

These are planned; the wire endpoints already exist on the platform.

License

MIT © Kerythos AI LLC. See LICENSE.