Quick reference
The SDK calls you use most, on one page. Every option, return value and type is in the API reference.
Install
npm install @dcupl/core @dcupl/loaderyarn add @dcupl/core @dcupl/loaderpnpm add @dcupl/core @dcupl/loader@dcupl/loader is only needed to load a dcupl.lc.json configuration (see Setup options).
Lifecycle
lifecycle.ts
import { Dcupl } from '@dcupl/core';
const dcupl = new Dcupl(); // options: /sdk/api/dcupl#dcuplinitoptions
dcupl.models.set({
key: 'Product',
properties: [
{ key: 'name', type: 'string' },
{ key: 'brand', type: 'string' },
{ key: 'price', type: 'int' },
],
});
dcupl.data.set(
[
{ key: 'p1', name: 'Laptop', brand: 'Acme', price: 999 },
{ key: 'p2', name: 'Mouse', brand: 'Acme', price: 29 },
{ key: 'p3', name: 'Desk', brand: 'Oak & Co', price: 299 },
],
{ model: 'Product' },
);
// Builds the indexes. Resolves false, and logs the error, if processing fails.
await dcupl.init();Load with the loader
Instead of models.set() and data.set(), load a dcupl.lc.json and the files it lists:
setup.ts
import { Dcupl } from '@dcupl/core';
import { DcuplAppLoader } from '@dcupl/loader';
const dcupl = new Dcupl();
const loader = new DcuplAppLoader();
dcupl.loaders.add(loader);
// The request url is `${baseUrl}/${loaderFileName}`.
// baseUrl must be non-empty; an empty string falls back to the dcupl CDN default.
await loader.config.fetch({
baseUrl: window.location.origin, // browser: your app's origin; in Node, pass a full URL
loaderFileName: 'dcupl.lc.json',
});
await loader.process(); // loads every resource the configuration lists
await dcupl.init();Lists and queries
query.ts
const list = dcupl.lists.create({ modelKey: 'Product' });
// Conditions on different attributes combine with AND, on the same attribute with OR
list.catalog.query.addCondition({ attribute: 'brand', operator: 'eq', value: 'Acme' });
list.catalog.query.addCondition({ attribute: 'price', operator: 'gte', value: 50 });
list.catalog.query.items(); // → Laptop
// A group with an explicit groupType ('or' or 'and')
list.catalog.query.clear();
list.catalog.query.addGroup({
groupKey: 'cheap-or-oak',
groupType: 'or',
queries: [
{ attribute: 'brand', operator: 'eq', value: 'Oak & Co' },
{ attribute: 'price', operator: 'lt', value: 50 },
],
});
list.catalog.query.items(); // → Desk, Mouse
list.catalog.query.removeGroup('cheap-or-oak');
// Sort and paginate (order is 'ASC' or 'DESC')
list.catalog.query.applyOptions({ sort: { attributes: ['price'], order: ['DESC'] }, start: 0, count: 2 });
list.catalog.query.items(); // → Laptop, Desk
list.catalog.query.first(); // → Laptop
list.catalog.query.count(); // items on the current page → 2
// Remove all conditions, sort and pagination
list.catalog.query.clear();Operators: Query Operators. Every query method: Catalog API.
Analysis functions
fn.ts
// Counts per value, for filter UIs
list.catalog.fn.facets({ attribute: 'brand' });
// → [{ value: 'Acme', size: 2, ... }, { value: 'Oak & Co', size: 1, ... }]
// sum, avg, count, min, max, distinct
list.catalog.fn.aggregate({ attribute: 'price', types: ['min', 'max', 'avg'] });
// → { attribute: 'price', min: 29, max: 999, avg: 442.3333333333333, ... }
// Items grouped by a value
list.catalog.fn.groupBy({ attribute: 'brand' });
// → { items: [{ value: 'Acme', _meta: { size: 2 }, ... }, { value: 'Oak & Co', _meta: { size: 1 }, ... }], ... }
// Autocomplete ('/…/' is a regex)
list.catalog.fn.suggest({ attribute: 'name', value: '/^la/', regexFlags: 'i' });
// → [{ value: 'Laptop', keys: ['p1'] }]
// All items matching the current query (count() is capped by the page size)
list.catalog.fn.metadata().currentSize; // → 3Options and return types: Functions API.
Global queries
Read a model without creating a list:
global-query.ts
dcupl.query.one({ modelKey: 'Product', itemKey: 'p1' });
// → { key: 'p1', name: 'Laptop', brand: 'Acme', price: 999 }
dcupl.query.execute({
modelKey: 'Product',
queries: [
{ attribute: 'brand', operator: 'eq', value: 'Acme' },
{ attribute: 'price', operator: 'gte', value: 50 },
],
sort: { attributes: ['price'], order: ['ASC'] },
count: 20,
});
// → [{ key: 'p1', name: 'Laptop', ... }]Update data
Data changes are staged until you call dcupl.update(); lists then return the new results.
update.ts
// Change existing items; properties you leave out keep their values
dcupl.data.update([{ key: 'p1', price: 899 }], { model: 'Product' });
// Add new items, or update them if they exist
dcupl.data.upsert([{ key: 'p4', name: 'Lamp', brand: 'Oak & Co', price: 40 }], { model: 'Product' });
// Remove items by key
dcupl.data.remove([{ key: 'p2' }], { model: 'Product' });
// Apply the staged changes. Resolves false, and logs the error, if the update fails.
await dcupl.update();
list.catalog.query.items(); // → Laptop (899), Desk, LampEvents
events.ts
// Every event of the instance: dcupl_initialized, dcupl_updated_manually, list_created, ...
const off = dcupl.on((message) => console.log(message.type));
// Re-render when a list's result changes, e.g. after dcupl.update()
const offList = list.onResultChange(() => render(list.catalog.query.items()));
// Unsubscribe
off();
offList();Clean up
cleanup.ts
list.destroy(); // a list you no longer need
dcupl.destroy(); // the whole instance, e.g. when your app unmountsSee also
- Quick start - Get started in 5 minutes
- Core concepts - Understand the fundamentals
- Setup options - Console + Loader, your own files, or SDK-only
- API reference - Every class, method and type