Relatude Help

Writing

Every write runs on the server as the user, through NodeStore.Execute, so the store's transaction plugins run as they do for a write from C#. A plugin that gives new pages an address gives one to a page made in TypeScript too. A write returns the node as it was stored.

const p = await store.insert(Product, { Name: 'Rain Jacket', Sku: 'RJ-1', Price: 1290, InStock: true, Parent: shopId });
await store.update<IProduct>(p.$id, { Price: 990 });
await store.upsert(Product, knownId, { Name: 'Rain Trousers', Price: 790 });
await store.delete(p.$id);                                 // or a list of ids; returns how many
Method Does
insert(type, values, { id?, ifNotExists?, draft? }) inserts a node; properties not given get the type's defaults. A draft stays hidden from readers until it is published
update(id, values, { force?, ifExists? }) writes the given properties and leaves the rest; force skips the comparison with what is stored
upsert(type, id, values) updates the node if it exists, and otherwise inserts it with this id
delete(ids, { ifExists? }) deletes the nodes and every relation they are in

Values

Values are keyed by CodeName, and the server parses them strictly by the property's type. A value that does not fit is refused with a 400.

  • null resets a property to its default.
  • A Date is sent as ISO text, and ISO text works too.
  • An enum takes its number or its name.
  • A relation end takes an id, or a list of ids for a "many" end, and is set to exactly those.
  • A reference takes an id, and a references property a list of ids.
  • A file is never a value: upload it (below).

Relations

Method Does
relate(type, id, end, to) adds related nodes at the end of the order; the other side follows
unrelate(type, id, end, to) removes related nodes
setRelation(type, id, end, to) sets the end to exactly these: one id or null for a "one" end, a list for a "many" end
clearRelation(type, id, end) removes every related node
moveRelation(type, id, end, items, to) moves related nodes within the order: 'top', 'bottom', { offset }, { before: id } or { after: id }
setRelationOrder(type, id, end, order) replaces the whole order

The type lets the compiler check the relation end's name:

await store.setRelation(Product, p.$id, 'Parent', shopId);
await store.moveRelation(Section, shopId, 'Children', p.$id, 'top');

Files

const file = input.files![0];
const stored = await store.fileUpload(articleId, 'Picture', file, file.name, {   // a FileValue, with its url
  onProgress: (sent, total) => bar.value = sent / total,
});
await store.fileCopy(otherId, 'Picture', { id: articleId, property: 'Picture' });  // the same file, there too
await store.fileDelete(articleId, 'Picture');

fileUpload takes a Blob (a File from an input is one), an ArrayBuffer or a Uint8Array. It replaces the property's file, in the revision the store's context names. Uploads larger than CmsApiOptions.MaxUploadBytes (1 GB by default) are refused. fileCopy copies another node's file without the bytes passing through the browser. fileDelete clears the property; the stored file stays until the server sweeps unreferenced files, as another revision or a copy may still hold it.

Transactions

transaction() sends several writes as one: all of them happen, or none. An insert gets its id in the browser (db.newId()), so a later action in the same transaction can use it:

const tx = store.transaction();
const outlet = tx.insert(Section, { Name: 'Outlet', Parent: shopId });
const jacket = tx.insert(Product, { Name: 'Rain Jacket 2025', Sku: 'RJ-25', Price: 690 });
tx.setRelation(Product, jacket, 'Parent', outlet);
tx.update<IProduct>(oldJacketId, { InStock: false });
const results = await tx.execute();                        // each action's answer, in order

A transaction takes insert, update, upsert, delete, resetProperty, addToProperty, relate, unrelate, setRelation, clearRelation, moveRelation and updateAddress.

The rest of the NodeStore

Method Does
resetProperty(id, property) sets a property back to its default
addToProperty(id, property, n), multiplyProperty(id, property, n) changes a number on the server, without reading it first
updateAddress(id, address) sets the node's address, its URL segment; the store makes it unique, so read it back
updateDisplayName(id, name) sets its display name
changeType(id, type) makes it a node of another type, keeping the values the two types share
updateMeta(id, meta) system data: readAccess, editAccess, editViewAccess, publishAccess (group ids), collectionId, releaseUtc, expireUtc, deleted
timestamp() the database's transaction timestamp, which moves with every write