Skip to content
sourcerer logoSourcererData
Framework-agnostic collection sources for local, page, cursor, and infinite pagination.
Version
v2.1.0
Size
2.2 KB gzip
Dependencies
Zero dependencies
BrowserNode ≥22SSRDeno
createCursorSourcecreateInfiniteSourcecreateLocalSourcecreatePageSourceAnyPagination View all 29 exports

Why Sourcerer?

Lists often combine pagination, search, request cancellation, and render state. Sourcerer gives local arrays and remote loaders one snapshot contract while leaving caching, retries, and transport policy to your application.

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

type User = { id: number; name: string };

// Before: query changes can mix old items with new loading and page state.
let items: User[] = [];
let page = 1;
let isLoading = false;

// After: one source publishes internally consistent loaded state.
const source = createPageSource<User>({
  autoStart: false,
  load: async () => ({ data: [{ id: 1, name: 'Ada' }], total: 1 }),
});
source.subscribe((snapshot) => console.log(snapshot.data));
source.dispose();
FeatureSourcererManual list stateCourier query cache
Bundle size2.2 KBApplication-defined4.9 KB
Zero runtime dependencies
Local and remote collectionsApplication-defined
Cursor and infinite paginationApplication-defined
Latest-request cancellationApplication-definedTransport-level

Use Sourcerer when one UI collection needs local or remote pagination with an explicit, framework-independent snapshot contract.

Consider Courier alone when you only need cached HTTP queries and pagination state belongs elsewhere.

Installation

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

Quick Start

Create a page source, load it, then dispose it with its owner.

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

type User = { id: number; name: string };

const source = createPageSource<User>({
  autoStart: false,
  load: async ({ query }) => {
    const users = [
      { id: 1, name: 'Ada' },
      { id: 2, name: 'Grace' },
      { id: 3, name: 'Linus' },
    ];
    const start = (query.page - 1) * query.pageSize;

    return { data: users.slice(start, start + query.pageSize), total: users.length };
  },
});

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

Features

  • createLocalSource() — synchronous search and numbered pagination over an array
  • createPageSource() — numbered remote pages with latest-request cancellation
  • createCursorSource() — sequential opaque-cursor navigation
  • createInfiniteSource() — append-only page loading
  • SourceSnapshot — loaded query, data, and pagination plus optional pendingQuery

Documentation

See Also

  • Courier — use as transport, caching, and retry policy inside a page loader
  • Scout — adapt an indexed search matcher for local sources
  • Ripple — project source snapshots into reactive application state
  • Wayfinder — validate and synchronize page query fields with route state