JSON store (Tier 1)
Key-value storage for simple state — preferences, flags, counters, cached values.
Access via sdk.json.
Methods
Section titled “Methods”get<T>(key: string): Promise<T | null>getEntry<T>(key: string): Promise<{ key: string; value: T; updatedAt: string } | null>set<T>(key: string, value: T, options?: { ifMatch?: string; // only write if current updatedAt matches ifNoneMatch?: '*'; // only create if key is absent}): Promise<{ key: string; created: boolean; updatedAt: string }>update<T>(key: string, fn: (prev: T | null) => T, options?: { retries?: number; // default 8}): Promise<T>delete(key: string): Promise<boolean>exists(key: string): Promise<boolean>list(): Promise<string[]>clear(): Promise<void>Examples
Section titled “Examples”await sdk.json.set('prefs', { theme: 'dark', fontSize: 14 });const prefs = await sdk.json.get('prefs');
// Atomic increment — safe under concurrent viewers/editorsconst next = await sdk.json.update('counter', n => (n || 0) + 1);
// Manual compare-and-swapconst entry = await sdk.json.getEntry('prefs');if (entry) { await sdk.json.set('prefs', { ...entry.value, theme: 'light' }, { ifMatch: entry.updatedAt, });}
const keys = await sdk.json.list();Atomic update()
Section titled “Atomic update()”update() does a read → transform → conditional write loop:
getEntryreads the current value andupdatedAtversion token- Your function computes the next value
setsendsIf-Match: <updatedAt>(orIf-None-Match: *for first create)- On
409 VERSION_CONFLICT, it re-reads and retries (default 8 times)
Use this for counters, toggles, and any read-modify-write. A plain
get + set can lose updates under concurrent writers.
REST equivalents:
| Header | Meaning |
|---|---|
If-Match: <updatedAt> |
Update only if the stored version matches |
If-None-Match: * |
Create only if the key does not exist |
Mismatch → 409 VERSION_CONFLICT.
Manifest
Section titled “Manifest”Declare every key you use:
<script type="shareout/manifest">{ "version": "2.0", "sources": { "json": { "prefs": { "default": { "theme": "light" } }, "counter": { "default": 0 } } }}</script>Reach for tables when you need many structured records with filtering instead of a single value.
