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

@feltdb/core

v0.6.9

Published

FeltDB Core - Application-facing database with Browser, Local, and Server runtimes. Durable state, reactive APIs.

Readme

@feltdb/core

The main FeltDB API. This package provides a simple, state-first interface for working with FeltDB.

Installation

npm install @feltdb/core

This single package includes the database SDK, WASM runtime, React bindings, migration tools, Studio application, feltdb CLI, and create-feltdb scaffolder. The only separate FeltDB package is the optional @feltdb/webllm.

npx --package @feltdb/core create-feltdb my-app
npx --package @feltdb/core feltdb studio

React bindings and migration tooling ship as subpath exports of this package:

import { createFeltDB } from '@feltdb/core';
import { useCollection } from '@feltdb/core/react';
import { migrate } from '@feltdb/core/migrate';
import { StudioApp } from '@feltdb/core/studio';

Install react and react-dom only when using the React bindings. The @feltdb/webllm package remains an optional, separately installed AI runtime. The feltdb studio command serves the Studio application bundled with core.

Quick Start

import { createFeltDB } from '@feltdb/core';

const db = createFeltDB({
  namespace: 'my-app',
  server: {
    url: 'https://db.example.com',
    token: process.env.FELTDB_API_KEY!,
  },
});

const todos = db.collection('todos');

// Insert
await todos.insert({
  id: '1',
  title: 'Learn FeltDB',
  completed: false,
});

// Query
const items = await todos.find({ completed: false });

// Update
await todos.update('1', { completed: true });

// Subscribe to changes
todos.subscribe((change) => {
  console.log('Collection changed:', change);
});

For a durable offline browser database using the same API:

const db = createFeltDB({ namespace: 'my-app', browser: true });
const todos = db.collection<Todo>('todos');

Browser mutations resolve after their IndexedDB transaction commits. The durable change journal replays after reload and coordinates live collections across tabs through BroadcastChannel when available.

Durable Operation Management

FeltDB provides atomic operation admission and lifecycle management for systems that need to survive process crashes with guaranteed identity stability.

Admit Operations (with atomic identity)

Guarantee: exactly-once operation identity across process crashes and concurrent callers.

import { OperationAdmissionInput, DurableOperation } from '@feltdb/core';

const db = createFeltDB({ namespace: 'my-app', path: './state' });

const result = await db.admitOperation({
  idempotencyKey: 'payment-123',
  kind: 'payment-processing',
  metadata: { amount: 99.99, currency: 'USD' }
});

// Same idempotencyKey always returns same operationId
console.log(result.operationId);  // 'op-xxx-yyy' (stable)
console.log(result.admitted);      // true if this caller admitted it, false if already existed

Transition Operations (atomic lifecycle)

Guarantee: all-or-nothing state transitions with version-based Compare-And-Set semantics.

import { OperationTransitionInput } from '@feltdb/core';

const transition = await db.transitionOperation({
  operationId: 'op-xxx-yyy',
  expectedVersion: 0,
  to: 'executing',
  metadata: { started_at: Date.now() }
});

if (transition.transitioned) {
  // We won the transition race
  console.log('Now executing...');
  
  // Do work...
  
  // Complete the operation
  await db.transitionOperation({
    operationId: 'op-xxx-yyy',
    expectedVersion: 1,
    to: 'completed',
    resultSnapshot: { paymentId: 'pay-456', timestamp: Date.now() }
  });
} else if (transition.reason === 'VERSION_CONFLICT') {
  // Another process already transitioned this operation
  console.log('Conflict - another process is handling this');
  console.log('Current status:', transition.operation.status);
}

Operation lifecycle: acceptedexecuting → (completed | failed | cancelled)

Terminal states (completed, failed, cancelled) cannot be transitioned from.

Recover Revisions (audited recovery from corruption)

Guarantee: audit trail with permanent untrust markers, no silent rollback.

import { StateContractClient, RevisionRecoveryInput } from '@feltdb/core';

const client = new StateContractClient({
  applicationId: 'my-app',
  revisionId: 'rev-clean-122',
  environment: 'staging'
});

const recovery = await client.recoverApplicationRevision({
  applicationId: 'my-app',
  expectedCurrentRevision: 'rev-corrupted-123',
  targetRevision: 'rev-clean-122',
  authorization: 'ELEVATED',
  actor: 'sherpa-admission',
  reason: 'Replace corrupt historical revision',
  environment: 'staging',
  recoveryId: 'sherpa-staging-recovery-v1'
});

// Result includes:
// - pointerMoved: Environment pointer moved to valid revision
// - sourceMarkedUntrusted: Corrupt revision permanently marked untrusted
// - auditDurable: Immutable audit trail persisted
console.log(recovery.pointerMoved);        // true
console.log(recovery.sourceMarkedUntrusted);  // true
console.log(recovery.auditDurable);        // true

Operation Types

import {
  OperationAdmissionInput,
  OperationAdmissionResult,
  DurableOperation,
  OperationStatus,
  OperationTransitionInput,
  OperationTransitionResult,
} from '@feltdb/core';

Error Semantics

All FeltDB APIs return deterministic, semantic error codes (never empty {}).

Error Codes

import { FeltDBErrorCode } from '@feltdb/core';

try {
  await db.transitionOperation({ ... });
} catch (error) {
  const felt_error = error.feltdb_error;
  
  switch (felt_error.code) {
    case FeltDBErrorCode.CONFLICT:
      // Version mismatch; another process won the race
      // → Retry with exponential backoff
      console.log('Conflict; retrying...');
      break;
    
    case FeltDBErrorCode.PRECONDITION_FAILED:
      // Validation or precondition error
      // → Do not retry; fix the input
      console.log('Validation error:', felt_error.message);
      break;
    
    case FeltDBErrorCode.TOO_BUSY:
      // Queue depth exceeded
      // → Retry with exponential backoff
      console.log('Server busy; retrying...');
      break;
    
    case FeltDBErrorCode.INTERNAL_ERROR:
      // Server error
      // → Log and escalate; audit trail in request_id
      console.log('Server error:', felt_error.request_id);
      break;
  }
}

Error Response Structure

import { FeltDBErrorResponse } from '@feltdb/core';

interface FeltDBErrorResponse {
  code: FeltDBErrorCode | string;           // Semantic code (CONFLICT, PRECONDITION_FAILED, etc.)
  message: string;                          // Human-readable message
  request_id: string;                       // Unique ID for debugging
  transaction_id?: string;                  // If applicable
  http_status: number;                      // HTTP status for routing
  recovery_hint?: 'retry_backoff' | 'dont_retry' | 'check_queue_depth' | 'contact_support';
}

Error Handling Utilities

import { isRetryableError, getRetryStrategy } from '@feltdb/core';

// Check if error should be retried
if (isRetryableError(error.feltdb_error.code)) {
  const strategy = getRetryStrategy(error.feltdb_error.code);
  if (strategy === 'exponential_backoff') {
    // Wait with exponential backoff before retry
  }
}

Concurrency Model

FeltDB 0.4.3 uses a single-writer, multi-reader model:

  • Single concurrent writer: Only one process may call database.mutate() at a time
  • Multiple readers: Any number of processes may call read operations (collection.all(), etc.)
  • Enforcement: File lock acquired at database open, held for lifetime
  • Multi-writer error: Attempting to open database from second process returns clear error: "Database is locked by another process. Only one process may write to a FeltDB database at a time."

Not suitable for: Multi-process concurrent writes. See Phase 3 roadmap for multi-writer replication model.

API

createFeltDB(options)

Initialize a new FeltDB instance.

Options:

  • namespace (string) - Application namespace for data isolation
  • server - Durable authenticated FeltDB server (url and token)
  • memory: true - Explicit ephemeral development/test runtime; never use for customer data
  • browser: true - Durable IndexedDB runtime with restart-safe change replay

Returns: Database instance

db.collection(name)

Get or create a collection.

Parameters:

  • name (string) - Collection name

Returns: Collection instance

collection.insert(item)

Insert a new item into the collection.

Parameters:

  • item (object) - Item to insert

Returns: Promise - Item ID

collection.find(query)

Query items from the collection.

Parameters:

  • query (object) - Query filter

Returns: Promise - Matching items

collection.update(id, updates)

Update an item in the collection.

Parameters:

  • id (string) - Item ID
  • updates (object) - Fields to update

Returns: Promise

collection.delete(id)

Remove an item from the collection.

Parameters:

  • id (string) - Item ID

Returns: Promise

collection.subscribe(callback)

Subscribe to collection changes.

Parameters:

  • callback (function) - Called when collection changes

Returns: Function - Unsubscribe function

Network acquisition and state-first execution

const task = await db.acquire<Task>('tasks', 'task-42');
const matches = await db.search<Task>('tasks', 'shipping blocker');
const artifact = await db.storeContent(new TextEncoder().encode('release artifact'));
const verifiedBytes = await db.acquireContent(artifact.hash);

await db.defineCapability('open-tasks', [
  { op: 'search', collection: 'tasks', query: '' },
  { op: 'filter_eq', field: 'done', value: false },
  { op: 'limit', count: 100 },
]);

await db.defineWorkflow('release', ['verify', 'publish']);
const run = await db.startWorkflow('release', { version: '1.0.0' });
const claimed = await db.claimWorkflowStep(run.value.id, 'verify', 'worker-1');
await db.completeWorkflowStep(
  run.value.id, 'verify', claimed.value.steps[0].claim_id, { ok: true },
);

await db.defineStateAgent('triage', ['search']);
const agentRun = await db.startStateAgent('triage', 'resolve customer blocker');

Acquisition synchronizes canonical causal operations from configured peers. Workflow and agent lifecycle records are canonical collections, so durability, live events, replication, authorization, and audit apply automatically. Execution claims use durable majority leases when peers are configured; stale or minority-partition workers cannot publish completion.

Embedded replica convergence and capability failover

const command = createFeltDB({ namespace: 'command', browser: true });
const field = createFeltDB({ namespace: 'field', browser: true });

// Both replicas continue accepting durable state while disconnected.
await command.collection('resources').insert(resource, 'water-team');
await field.collection('incidents').insert(incident, 'clinic');

// Transport-independent, bidirectional operation exchange. Replays deduplicate.
await command.synchronizeWith(field);

field.registerCapabilityWorker('AssessIncident', assessIncident);
const routed = await command.executeCapabilityWithFailover(
  'AssessIncident', { incident }, [field],
);

exportOperations() and applyOperations() are also available when the application supplies its own transport. Merges use stable operation identity and deterministic last-writer ordering, notify live collections, and retain the imported operations in the local audit journal. Capability routing records every provider attempt in _flow_capability_routes; each successful worker execution is materialized in _flow_executions.

License

MIT