Skip to content
sourcerer logoSourcererData
Framework-agnostic local and remote collection state with page, cursor, and infinite pagination.
Version
v3.0.0
Size
2.5 KB gzip
BrowserNode ≥22SSRDeno
createCursorSourcecreateInfiniteSourcecreateLocalSourcecreatePageSourceCursorLoadContext View all 27 exports

Why Sourcerer?

Paginated views need collection data, loading state, errors, parameters, and navigation to change coherently. Sourcerer owns that state and request succession without coupling it to a framework or transport client.

ts
// Before
let items = [];
let loading = false;
let page = 1;

// After
const source = createPageSource({
  load: async ({ page, pageSize }) => ({ items: await loadUsers(page, pageSize), totalItems: 100 }),
});
source.subscribe((state) => render(state));
FeatureSourcererManual storeGeneral query cache
Bundle size2.5 KBApplication-definedPackage-defined
Zero runtime dependencies
Page, cursor, and infinite navigationApplication-definedApplication-defined
Framework-neutral subscriptionsApplication-defined
HTTP transport policyLoader-definedApplication-definedLoader-defined

Use Sourcerer when a collection view needs explicit pagination, observable state, cancellation, and lifecycle ownership.

Consider a general query cache when your primary requirement is shared keyed caching, invalidation, mutations, or server-state normalization rather than collection navigation.

Installation

sh
pnpm add @vielzeug/sourcerer
sh
npm install @vielzeug/sourcerer
sh
yarn add @vielzeug/sourcerer

Quick Start

Create a page source, load it, read its state, and dispose it with its owner.

ts
import { createPageSource } from '@vielzeug/sourcerer';

type User = { id: number; name: string };
const users: User[] = [
  { id: 1, name: 'Ada' },
  { id: 2, name: 'Grace' },
];
const source = createPageSource({
  load: async ({ page, pageSize }) => {
    const start = (page - 1) * pageSize;
    return { items: users.slice(start, start + pageSize), totalItems: users.length };
  },
  pageSize: 1,
});

try {
  await source.reload();
  console.log(source.state.items);
} catch (error) {
  console.error(error);
} finally {
  source.dispose();
}

Features

  • createLocalSource() — filters and paginates an in-memory collection synchronously
  • createPageSource() — loads numbered pages and exposes direct navigation commands
  • createCursorSource() — follows opaque cursors returned by the loader
  • createInfiniteSource() — appends pages while preserving loaded items
  • setParams() — replaces consumer-owned loader parameters and resets pagination
  • subscribe() — publishes complete immutable state replacements

Documentation

See Also

  • Courier — provide HTTP transport, middleware, and structured transport errors inside loaders
  • Scout — index larger in-memory collections before passing matches to a local source
  • Ripple — project source state into reactive computations
  • Wayfinder — validate and synchronize source parameters with route state