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.
nullresets a property to its default.- A
Dateis 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 orderA 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 |