Skip to main content

Work with encrypted JSON

Use named content resources to organize your application's data. The examples below assume an open catalog, as shown in the Quick Start.

Create a resource​

Add a name that does not already exist in the catalog:

await ulda.add('profile', {
displayName: 'Ada',
preferences: { theme: 'light' },
tags: ['personal', 'work'],
});

Each content resource has its own encryption secrets and chain. The master stores its name and credentials inside the encrypted catalog.

add() defaults to mode X. You can select S with the third argument, ulda.add(name, value, 'S'); the mode is fixed when the resource is created.

Adding content first reserves a resource ID, then commits the content and master together. Those are two separate commits. An interrupted add can leave an unreferenced resource; do not repeat it automatically after UNKNOWN_OUTCOME.

Read a local copy​

const profile = ulda.value('profile');
const theme = ulda.value('profile', ['preferences', 'theme']);
const catalog = ulda.snapshot();

These calls return independent copies of the last verified local state. They make no network request. Changing a returned object does not change the SDK or server.

Use await ulda.refresh() to fetch and verify the current server snapshot when no competing local operation is active. Local reads can remain available while disconnected, so they are not evidence of freshness.

Update a field or a resource​

await ulda.set('profile', ['preferences', 'theme'], 'dark');
await ulda.data.profile.displayName.update('Grace');

Both calls explicitly save a change. An object field at the final path component may be new, but its parent objects must exist. Arrays support replacement at existing indices:

await ulda.set('profile', ['tags', 0], 'home');

To replace the entire resource:

await ulda.update('profile', {
displayName: 'Grace',
preferences: { theme: 'dark' },
tags: ['home', 'work'],
});

A field change re-encrypts the whole content resource. Writes are queued per resource; await the returned promise before treating that particular write as confirmed.

Use references​

A reference addresses a resource or a nested value:

const profileRef = ulda.ref('profile');
const currentName = profileRef.displayName.get();
await profileRef.preferences.theme.update('light');

References are objects, even when their underlying value is a boolean or string. Use .get() to read the value.

Use .field() for dynamic keys or keys that collide with reference methods:

await ulda.add('settings', { update: 'manual' });
const updateMode = ulda.ref('settings').field('update').get();

The reserved reference members are get, update, delete, field, toJSON and then. Direct assignment, the JavaScript delete operator and Object.defineProperty are not supported on references.

A reference belongs to one content ID and session. After deletion, recovery or reopening, obtain a new reference. Reusing the same name does not revive the old one; stale references fail with STALE_REFERENCE.

Remove data​

Remove a nested field or array element:

await ulda.remove('profile', ['preferences', 'theme']);
await ulda.remove('profile', ['tags', 0]);

Array removal shifts later elements left. An empty path is not accepted by remove().

Use await ulda.delete('profile') to delete the whole content resource and remove its catalog entry. This operation refreshes required state and commits the deletion and master update atomically. It can return BUSY if another local operation is active.

await ulda.superDelete() deletes the verified catalog and its listed contents in one atomic batch, then closes the SDK. Missing or damaged required content can prevent deletion. Other catalogs that reference the same resource ID are affected by its physical deletion.

Supported values and sizes​

Data may contain null, booleans, finite numbers, strings, dense arrays and plain objects. Convert dates explicitly to strings; Date, bigint, functions, undefined, accessors, sparse arrays and cycles are rejected.

Application JSON is limited to 1 MiB per content, depth 48 and 40,000 visited nodes. Content names are 1–256 UTF-16 code units. Resource IDs are decimal strings, never JavaScript numbers.

A catalog has no fixed content-entry count cap, but all content is loaded eagerly. Byte, memory, queue and server budgets still apply. See the capacity reference for larger workloads.

Continue with events and synchronization or conflicts and recovery.