Skip to content
sourcerer logoSourcererData
Framework-agnostic local and remote collection state with page, cursor, and infinite pagination.
Version
v3.0.0
Size
2.6 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.6 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