stacks/table
publicClone
Push over the same URL. A password will not work: create a token under access tokens and use it in place of one.
- .config
- .github
- .vscode
- examples
- resources
- tests
- .editorconfig 147 B
- .env.example 21 B
- .gitattributes 89 B
- .gitignore 120 B
- .node-version 8 B
- .npmignore 277 B
- build.ts 348 B
- bun.lock 34.7 KB
- bunfig.toml 29 B
- CHANGELOG.md 12.4 KB
- CLAUDE.md 1.1 KB
- LICENSE.md 1.1 KB
- package.json 1.8 KB
- README.md 3.4 KB
- tsconfig.json 498 B
@stacksjs/table
Add to a Stacks project
The registry version installs project-shaped source files directly into your application:
buddy add tableThis adds resources/components/DataTable.stx and the table functions under resources/functions/table/. The installed STX and TypeScript source remains fully owned and editable by the application.
Typed searching, filtering, sorting, faceting, ranking, and pagination for data tables. The core has no runtime dependencies and works with an in-memory dataset, Meilisearch, Algolia, or Typesense.
Install
bun add @stacksjs/tableIn-memory development
The memory driver provides realistic table behavior without a search service, credentials, Docker, or network access.
import { createTable, MemoryTableDriver } from '@stacksjs/table'
const driver = new MemoryTableDriver({
products: [
{ id: 1, name: 'Mechanical Keyboard', category: 'hardware', price: 149 },
{ id: 2, name: 'TypeScript Handbook', category: 'books', price: 39 },
{ id: 3, name: 'Wireless Keyboard', category: 'hardware', price: 89 },
],
})
const products = createTable({
driver,
index: 'products',
searchFields: ['name'],
ranking: { rules: ['price:asc'] },
})
const result = await products.search({
query: 'keyboard',
filters: { category: 'hardware' },
facets: ['category'],
})Run the included dummy database example with bun run demo:memory.
Meilisearch
import { createTable, MeilisearchTableDriver } from '@stacksjs/table'
const products = createTable({
driver: new MeilisearchTableDriver({
host: 'https://search.example.com',
apiKey: process.env.MEILISEARCH_API_KEY,
}),
index: 'products',
ranking: { rules: ['words', 'typo', 'proximity', 'sort', 'exactness'] },
})Algolia
import { AlgoliaTableDriver, createTable } from '@stacksjs/table'
const products = createTable({
driver: new AlgoliaTableDriver({
appId: process.env.ALGOLIA_APP_ID,
apiKey: process.env.ALGOLIA_API_KEY,
}),
index: 'products',
ranking: { rules: ['desc(popularity)', 'asc(price)'] },
})Algolia searches use its distributed search host. Ranking updates use the write host and finish before the first table search. Use a search-only key when no ranking is configured, and a key with settings permission when it is.
Typesense
import { createTable, TypesenseTableDriver } from '@stacksjs/table'
const products = createTable({
driver: new TypesenseTableDriver({
host: 'https://typesense.example.com',
apiKey: process.env.TYPESENSE_API_KEY,
queryBy: ['name', 'description'],
}),
index: 'products',
})
const result = await products.search({
query: 'keyboard',
filters: { category: ['hardware', 'accessories'] },
sort: ['price:asc'],
})Typesense ranking is expressed per query through sort, which matches its API model. Remote index-ranking configuration is only exposed by drivers whose engines support that operation.
Driver contract
Custom drivers implement two methods:
interface TableDriver<Row> {
readonly name: string
search(request: TableSearchRequest): Promise<TableSearchResult<Row>>
setRanking?(index: string, ranking: TableRanking): Promise<void>
}Every driver returns the same result shape, so view code does not depend on a vendor SDK response.
Development
bun install
bun test
bun run test:types
bun run lint
bun run buildLicense
MIT