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

@cosmicdrift/kumiko-framework

v0.5.2

Published

Framework core — engine, pipeline, API, DB, and every other bit that makes Kumiko go.

Readme

@cosmicdrift/kumiko-framework

License: BUSL-1.1 TypeScript

Framework core for Kumiko — engine, pipeline, API, DB, event-store, and every other bit that makes Kumiko go.

Multi-tenant, command-based, event-sourced app framework for Bun + Hono + Drizzle. Define features, register entities, write commands — the framework wires dispatch, persistence, projections, async subscribers, and realtime delivery.

See the monorepo root README for the broader pitch, the docs/plans directory for architecture, and samples/ for runnable examples of every feature.

Install

yarn add @cosmicdrift/kumiko-framework
# peers you probably already have:
yarn add drizzle-orm hono ioredis zod

Bun is the intended runtime. Node 20+ works for the CLI and tests.

At-a-glance

import { defineFeature, createEntity, createTextField } from "@cosmicdrift/kumiko-framework/engine";

export const taskEntity = createEntity({
  fields: {
    title: createTextField({ required: true, searchable: true }),
    done: createTextField(),
  },
  softDelete: true,
});

const taskTable = buildDrizzleTable("task", taskEntity);
const taskExecutor = createEventStoreExecutor(taskTable, taskEntity, { entityName: "task" });

export const taskFeature = defineFeature("tasks", (r) => {
  r.entity("task", taskEntity);

  // Write handlers go through createEventStoreExecutor — events + projection in one TX,
  // optimistic locking, access control, all explicit.
  r.writeHandler(
    "task:create",
    z.object({ title: z.string() }),
    async (event, ctx) => taskExecutor.create(event.payload, event.user, ctx.db),
    { access: { roles: ["User"] } },
  );
  r.writeHandler(
    "task:update",
    z.object({ id: z.uuid(), version: z.number(), changes: z.object({ title: z.string().optional() }) }),
    async (event, ctx) => taskExecutor.update(event.payload, event.user, ctx.db),
    { access: { roles: ["User"] } },
  );
  r.writeHandler(
    "task:delete",
    z.object({ id: z.uuid() }),
    async (event, ctx) => taskExecutor.delete(event.payload, event.user, ctx.db),
    { access: { roles: ["Admin"] } },
  );
  r.queryHandler(
    "task:list",
    z.object({}),
    async (query, ctx) => taskExecutor.list(query.payload, query.user, ctx.db),
    { access: { openToAll: true } },
  );
  r.queryHandler(
    "task:detail",
    z.object({ id: z.uuid() }),
    async (query, ctx) => taskExecutor.detail(query.payload, query.user, ctx.db),
    { access: { openToAll: true } },
  );

  // Read-model fed from task events, rebuildable via the CLI
  r.projection({
    name: "tasks-per-day",
    source: "task",
    table: tasksPerDayTable,
    apply: {
      "task.created": async (event, tx) => {
        /* count++ */
      },
    },
  });

  // Async consumer — runs after commit via the event-dispatcher,
  // cursor-based, at-least-once, per-consumer dead-letter semantics.
  // Omit `table` for pure side-effect handlers (mail, webhooks, ...).
  r.multiStreamProjection({
    name: "notify-new-task",
    apply: {
      "task.created": async (event) => {
        // e.g. push to an external notification service
      },
    },
  });
});

Package exports

| Entry | What's in it | |---|---| | @cosmicdrift/kumiko-framework/engine | defineFeature, createEntity, field helpers, access rules, registry | | @cosmicdrift/kumiko-framework/db | Drizzle re-exports, createEventStoreExecutor, table builders, tenant-db | | @cosmicdrift/kumiko-framework/event-store | events table, append, loadAggregate, loadAggregateAsOf | | @cosmicdrift/kumiko-framework/pipeline | Dispatcher, event-dispatcher (AsyncDaemon), projection-rebuild, SSE + search consumers | | @cosmicdrift/kumiko-framework/api | buildServer, auth middleware, SSE route, error contract | | @cosmicdrift/kumiko-framework/auth | JWT helper, password hashing, session users | | @cosmicdrift/kumiko-framework/search | SearchAdapter interface, in-memory adapter, Meili wrapper | | @cosmicdrift/kumiko-framework/jobs | BullMQ-backed job runner, cron scheduling | | @cosmicdrift/kumiko-framework/files | Signed-URL upload/download, tenant-scoped storage | | @cosmicdrift/kumiko-framework/i18n | i18next setup, per-feature translation registration | | @cosmicdrift/kumiko-framework/ui | React hooks (Zustand stores, SSE subscription, optimistic mutations) | | @cosmicdrift/kumiko-framework/testing | setupTestStack, createTestDb, request helpers | | @cosmicdrift/kumiko-framework/utils | Safe JSON, qualified-name helpers | | @cosmicdrift/kumiko-framework/errors | Error classes, writeFailure, reason contracts |

Core concepts

  • Feature as unit of deployment. defineFeature registers entities, write/query handlers, projections, post-event subscribers, lifecycle hooks, access rules, and translations.
  • Commands in, state out. Writes are commands dispatched through HTTP; the dispatcher validates, enforces access, runs lifecycle hooks, persists events, and triggers projections in a single TX.
  • Event-sourced by default. Every write goes through createEventStoreExecutor and appends a domain event to the aggregate stream. Auto-generated CRUD events (<entity>.created/updated/deleted/restored) for record writes, explicit ctx.appendEvent for domain events with intent. Projections feed off the stream for same-TX read-after-write consistency.
  • Async side-effects via cursor. SSE broadcast, search indexing, and feature-registered r.multiStreamProjection consumers run on a single cursor-based dispatcher (AsyncDaemon pattern). Per-consumer checkpoints, halt-on-poison, dead-letter after N retries.
  • Multi-tenant scoping. Every event, entity, projection, and search index carries tenantId. TenantDb is a TX-scoped wrapper that refuses writes outside the current tenant.
  • Optimistic concurrency. UNIQUE(aggregate_id, version) on events gives atomic append + conflict detection; VersionConflictError surfaces races as a first-class value.
  • Idempotency + dedup. Request-id backed unique index on the events table turns retries into replays. IdempotencyGuard caches write outcomes per tenant.

Status

This framework is pre-1.0 and evolves fast. Every feature has a runnable sample under samples/; the roadmap lives in docs/plans/uebersicht.md.

License

BUSL-1.1 — see LICENSE.