Quick start
Build a filterable product list in 5 minutes.
What you'll build: A query that filters products by category and returns matching items instantly — no backend required.
Prerequisites
- A supported Node.js version, see Compatibility (
node -vto check) - A TypeScript/JavaScript project (or use
npx tsxto run standalone)
Install
npm install @dcupl/coreyarn add @dcupl/corepnpm add @dcupl/coreTypeScript types are included; type names such as ModelDefinition come from @dcupl/common, which you install (npm install @dcupl/common) only when you import them in your own code.
Create your first query
Create a new file and paste this complete example:
import { Dcupl } from '@dcupl/core';
async function main() {
// 1. Create a dcupl instance
const dcupl = new Dcupl();
// 2. Define a model with filterable properties
dcupl.models.set({
key: 'Product',
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'int' },
{ key: 'category', type: 'string' },
],
});
// 3. Load data (inline or from external API)
dcupl.data.set(
[
{ key: 'p1', name: 'Laptop', price: 999, category: 'Electronics' },
{ key: 'p2', name: 'Mouse', price: 29, category: 'Electronics' },
{ key: 'p3', name: 'Desk', price: 299, category: 'Furniture' },
],
{ model: 'Product' },
);
// 4. Initialize (builds indexes). Resolves false, and logs the error,
// if processing fails; it doesn't throw.
await dcupl.init();
// 5. Create a list to query the model
const list = dcupl.lists.create({ modelKey: 'Product' });
// 6. Add filter conditions
list.catalog.query.addCondition({
attribute: 'category',
operator: 'eq',
value: 'Electronics',
});
// 7. Get results
const results = list.catalog.query.items();
console.log('Filtered results:', results);
// → [
// { key: 'p1', name: 'Laptop', price: 999, category: 'Electronics' },
// { key: 'p2', name: 'Mouse', price: 29, category: 'Electronics' }
// ]
}
main();Run it with
npx tsx demo.tsor your preferred TypeScript runner.
Want to skip setup? → Try it in the Playground — experiment with filters, sorting, and facets live.
Common operations
// Conditions on different attributes combine with AND (with step 6: Electronics and price >= 50)
list.catalog.query.addCondition({ attribute: 'price', operator: 'gte', value: 50 });
list.catalog.query.items(); // → Laptop
// Conditions on the same attribute combine with OR
list.catalog.query.clear(); // removes all conditions and sort/pagination options
list.catalog.query.addCondition([
{ attribute: 'category', operator: 'eq', value: 'Electronics' },
{ attribute: 'category', operator: 'eq', value: 'Furniture' },
]); // → Laptop, Mouse, Desk
// OR across attributes: a group with an explicit groupType
list.catalog.query.clear();
list.catalog.query.addGroup({
groupKey: 'cheap-or-furniture',
groupType: 'or',
queries: [
{ attribute: 'category', operator: 'eq', value: 'Furniture' },
{ attribute: 'price', operator: 'lt', value: 50 },
],
}); // → Desk, Mouse
// Sort ('ASC' or 'DESC', uppercase) and paginate
list.catalog.query.clear();
list.catalog.query.applyOptions({ sort: { attributes: ['price'], order: ['ASC'] }, start: 0, count: 2 });
list.catalog.query.items(); // → Mouse, DeskEvery other common call (facets, metadata, aggregations) is on one page: Quick reference.
Update data
Data changes after init() are staged. Apply them with dcupl.update(); lists then return the new results.
dcupl.data.upsert([{ key: 'p4', name: 'Monitor', price: 199, category: 'Electronics' }], { model: 'Product' });
await dcupl.update(); // resolves false, and logs the error, if the update fails
list.catalog.query.items(); // → Mouse, Monitor (still sorted by price, 2 per page)