@mika/blackcurrant (1.0.0)

Published 2026-04-21 17:17:45 +00:00 by mika

Installation

@mika:registry=
npm install @mika/blackcurrant@1.0.0
"@mika/blackcurrant": "1.0.0"

About this package

@mika/blackcurrant

Blackcurrant is a client-side data runtime for request-driven stores, journal-backed sync, durable persistence, public and private data lanes, and optimistic/offline mutations.

Install

npm install @mika/blackcurrant @mika/signals uuid

@mika/signals is a peer dependency.

Exports

import {
  createCommunication,
  createIndexedDbStorage,
  createPersistence,
  createStore,
} from "@mika/blackcurrant"

Typical Setup

import {
  createCommunication,
  createIndexedDbStorage,
  createPersistence,
  createStore,
} from "@mika/blackcurrant"

const persistence = createPersistence({
  storage: createIndexedDbStorage(),
})

const communication = createCommunication({
  baseUrl: window.location.origin,
})

const users = createStore({
  name: "user",
  communication,
  persistence,
})

const bulletin = createStore({
  name: "bulletin",
  public: true,
  communication,
  persistence,
})

Concepts

Blackcurrant is built around three cooperating parts:

  • Communication
  • Persistence
  • Store

Together they provide:

  • single-stream public/private sync
  • journal-backed SSE sync
  • durable client data
  • request-driven stores
  • public and private store visibility
  • optimistic mutations
  • offline mutation replay

Visibility

Stores are private by default.

const inbox = createStore({
  name: "inbox",
  communication,
  persistence,
})

Public stores opt in with public: true.

const bulletin = createStore({
  name: "bulletin",
  public: true,
  communication,
  persistence,
})

Key rules:

  • public: true uses anonymous transport semantics
  • omitted public means authenticated transport semantics
  • store names must be globally unique across public and private resources
  • public stores continue working across login/logout
  • private stores clear on logout

Sync Model

Blackcurrant now uses one SSE connection at a time with separate public and private frontiers.

Typical sync URLs look like:

/sync?public=3:120&private=7:45

The stream keeps the existing { type, ... } envelope and may emit:

  • hello
  • entry
  • resetRequired
  • error

Private sync startup requires either:

  • hello with userId
  • or error followed by stream close

Every entry must include its lane in entry.scope.

Logout And Reset

logout() now rejects with machine-readable codes in two cases:

  • ERR_LOGOUT_OFFLINE
  • ERR_LOGOUT_PENDING_MUTATIONS

Any sync reset clears the full mutation queue, even if only one lane was invalidated.

Migration

See CHANGELOG.md for the step-by-step migration guide for 1.0.0.

Further Reading

Notes

  • The package is plain ESM.
  • There is no build step.
  • Application-specific views, filtering, sorting, and UI belong to the consuming app.

Dependencies

Dependencies

ID Version
uuid ^13.0.0

Peer dependencies

ID Version
@mika/signals ^0.1.0
Details
npm
2026-04-21 17:17:45 +00:00
3
24 KiB
Assets (1)
Versions (15) View all
4.0.0 2026-06-24
3.1.1 2026-06-17
3.0.2 2026-05-25
3.0.1 2026-05-19
3.0.0 2026-05-19