Version v3.0.0 Size 2.5 KB gzip
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));| Feature | Sourcerer | Manual store | General query cache |
|---|---|---|---|
| Bundle size | 2.5 KB | Application-defined | Package-defined |
| Zero runtime dependencies | |||
| Page, cursor, and infinite navigation | Application-defined | Application-defined | |
| Framework-neutral subscriptions | Application-defined | ||
| HTTP transport policy | Loader-defined | Application-defined | Loader-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/sourcerersh
npm install @vielzeug/sourcerersh
yarn add @vielzeug/sourcererQuick 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 synchronouslycreatePageSource()— loads numbered pages and exposes direct navigation commandscreateCursorSource()— follows opaque cursors returned by the loadercreateInfiniteSource()— appends pages while preserving loaded itemssetParams()— replaces consumer-owned loader parameters and resets paginationsubscribe()— 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