Sprites.Library.Store

The user's saved documents, built on the generic Sprites.Store. Meta is the light listing projection, Media the whole document with its meta kept in step, and Refs the reference edges between documents. Every sub-module presents the same six functions — Read, Write, Delete, Binding, Filter, Count — over its table, plus a few conveniences.

Sprites.Library.Store

Sprites.Library.Store.Meta

Sprites.Library.Store.Media

Sprites.Library.Store.Refs

Sprites.Library.Store

Id String

Sprites.Library.Store.Id()

A fresh unique id for a new document. Every saved document keeps its id for life, so a reference to it stays stable across edits.

Returns the id string.

const id = Sprites.Library.Store.Id();
const template = { media: 'sprite', platform: 'freeform' };
const seed = Sprites.Library.Store.blank(id, template);
A fresh id starts a new document, seeded and saved on its first edit.

now Number

Sprites.Library.Store.now()

The current time in milliseconds, for the created and modified stamps a new document carries.

Returns the millisecond timestamp.

const stamp = Sprites.Library.Store.now();
const record = { id: id, created: stamp, modified: stamp };
Stamp a new document's created and modified fields with one time.

blank Object

Sprites.Library.Store.blank(id, template)

A blank envelope seed for a new document, the seed a page passes to Media.Binding so a fresh id renders and edits from it and saves on the first change. The template carries the media, platform and a fresh data buffer; media and platform are required, so a missing one is a bug, not a default. Its data is read to a plain snapshot, and info defaults to the buffer's dimensions and mode.

InputTypeDescription
idStringThe fresh id for the new document, from Id.
templateObjectCarries media, platform and a fresh data buffer. media and platform are required.

Returns a plain envelope record with the light fields and the data snapshot.

const id = Sprites.Library.Store.Id();
const fresh = Sprites.Grid.Two.Blank(8, 8, 0);
const template = { media: 'sprite', platform: 'freeform', data: fresh };
const seed = Sprites.Library.Store.blank(id, template);
const name = Sprites.Object.Field(seed, 'name');
const info = Sprites.Object.Field(seed, 'info');
Sprites.Ui.Dom.Text('name: ', name, ' · info: ', info);
A blank 8×8 sprite envelope, ready to render and save on the first edit.

Sprites.Library.Store.Meta

The meta table: the light projection, the envelope minus the data payload, so a listing or a count never pulls the heavy data.

Meta.Read Read

Sprites.Library.Store.Meta.Read(result, id)

Read one meta row into result, by id: the light envelope without its data payload.

const result = Sprites.Reactive.Pending();
Sprites.Library.Store.Meta.Read(result, id);
const name = Sprites.Object.Field(result, 'name');
Sprites.Ui.Dom.Text(name);
Read the light row into a sink; the data payload never loads.

Meta.Write Write

Sprites.Library.Store.Meta.Write(id, meta)

Write one meta row under its id, the light envelope for the listings.

const meta = { id: id, media: 'sprite', platform: 'freeform', name: 'Hero' };
Sprites.Library.Store.Meta.Write(id, meta);
Save one light row to the meta table.

Meta.Delete Command

Sprites.Library.Store.Meta.Delete(id)

Delete one meta row by id.

Sprites.Library.Store.Meta.Delete(id);
Remove the light row.

Meta.Binding Binding

Sprites.Library.Store.Meta.Binding(result, id)

A two way meta value: read one row into result and write edits back, for an inline rename without loading the document's data.

const result = Sprites.Reactive.Pending();
Sprites.Library.Store.Meta.Binding(result, id);
const name = Sprites.Object.Field(result, 'name');
Sprites.Ui.Input.Text(name);
Edit the light row in place; the data payload stays untouched.

Meta.Filter Live, array

Sprites.Library.Store.Meta.Filter(rows, filter, start, limit)

A filtered, paged read into rows. filter holds the equality fields, for example { media, platform }; a listing never pulls the heavy data.

const rows = Sprites.Reactive.Pending();
const filter = { media: 'sprite', platform: 'freeform' };
Sprites.Library.Store.Meta.Filter(rows, filter, 0, 50);
A live page of light rows for one media and platform.

Meta.Count Live, number

Sprites.Library.Store.Meta.Count(total, filter)

The number of meta rows matching filter, into total; a count never pulls the heavy data.

const total = Sprites.Reactive.Pending();
const filter = { media: 'sprite' };
Sprites.Library.Store.Meta.Count(total, filter);
Sprites.Ui.Dom.Text(total, ' sprites');
How many sprites are saved.

Sprites.Library.Store.Media

The whole document: the data table plus the meta projection kept in step. Read gives the whole record; Write and Delete keep the projection in step; Filter and Count run over the light meta rows.

Media.Read Read

Sprites.Library.Store.Media.Read(result, id)

Read the whole media record into result, by id: the light fields and the data payload together.

const result = Sprites.Reactive.Pending();
Sprites.Library.Store.Media.Read(result, id);
const data = Sprites.Object.Field(result, 'data');
Load the whole document in one read.

Media.Write Write

Sprites.Library.Store.Media.Write(id, record)

Write the whole record plus its light meta projection. If record is reactive the write follows it, so this is the save side; a plain record is one write.

Sprites.Library.Store.Media.Write(id, record);
Save the document; its meta projection follows.

Media.Delete Command

Sprites.Library.Store.Media.Delete(id)

Delete the record, its meta, and every reference edge it owns, the edges from it, so a deleted document leaves no dangling outgoing edges.

Sprites.Library.Store.Media.Delete(id);
Remove the document and the edges it owns.

Media.Binding Binding

Sprites.Library.Store.Media.Binding(result, id, optionalSeed)

A two way document: read the whole record into result, write it back as it changes, and keep the meta projection in step. optionalSeed is the blank the caller seeded result with, so a new id opens on a fresh document and saves on the first edit, while an existing id loads over the seed.

InputTypeDescription
resultSprites.Reactive.ValueThe sink the document reads into and writes back from.
idSprites.Reactive.Value or StringThe document id to open. Reactive or constant.
optionalSeedObjectThe blank from Sprites.Library.Store.blank, so a new id opens a fresh document.
const fresh = Sprites.Grid.Two.Blank(16, 16, 0);
const template = { media: 'sprite', platform: 'freeform', data: fresh };
const seed = Sprites.Library.Store.blank(id, template);
const result = Sprites.Reactive.Value(seed);
Sprites.Library.Store.Media.Binding(result, id, seed);
const data = Sprites.Object.Field(result, 'data');
An editor document that opens a blank at once, loads over it, and autosaves.

Media.Filter Live, array

Sprites.Library.Store.Media.Filter(rows, filter, start, limit)

A filtered, paged listing into rows, over the light meta projection, since a listing wants the light rows, not the payloads.

const rows = Sprites.Reactive.Pending();
const filter = { media: 'sprite' };
Sprites.Library.Store.Media.Filter(rows, filter, 0, 50);
A live page of light rows for a media page.

Media.Count Live, number

Sprites.Library.Store.Media.Count(total, filter)

The number of media matching filter, into total, off the light meta projection.

const total = Sprites.Reactive.Pending();
const filter = { media: 'sprite', platform: 'freeform' };
Sprites.Library.Store.Media.Count(total, filter);
How many documents match, counted off the light rows.

Media.List Live, array

Sprites.Library.Store.Media.List(rows, query)

The listing a media page wants, into rows: the meta rows matching a query, searched, sorted and paged. query is one reactive object of the search fields. media and platform are equality, an unset one is no constraint; search is a substring over the name; sort is 'name' for name ascending or otherwise the most recently modified first. The rows stay live as writes land here or in another tab.

FieldTypeDescription
query.mediaStringThe media type to list. Equality, optional.
query.platformStringLimit to one platform. Equality, optional.
query.searchStringKeep documents whose name contains this text. Optional.
query.startNumberSkip this many, for paging. Optional.
query.countNumberReturn at most this many. Optional.
query.sortString'name' for name ascending, otherwise most recently modified first.
const rows = Sprites.Reactive.Pending();
const search = Sprites.Reactive.Value('');
const query = Sprites.Reactive.ReadOnly({ media: 'sprite', search: search, sort: 'recent' });
Sprites.Library.Store.Media.List(rows, query);
Sprites.Ui.Input.Text(search);
Typing in the search box refilters the live listing.

Media.Rename Command

Sprites.Library.Store.Media.Rename(id, name)

Rename without loading the data: patch the name onto both the record and its meta, so the listing and the document stay in step.

const name = Sprites.Reactive.Value('Hero');
Sprites.Library.Store.Media.Rename(id, name);
Patch the name onto the record and its meta without a data load.

Media.Replace Command

Sprites.Library.Store.Media.Replace(targetId, replacementId)

Delete targetId but first repoint every edge that used it at replacementId, so nothing is left pointing at a gone item. The referential integrity delete.

Sprites.Library.Store.Media.Replace(targetId, replacementId);
Redirect the usages, then delete the target.

Media.metaOf Object

Sprites.Library.Store.Media.metaOf(result)

The light meta projection of a record: the envelope fields without the data payload. It is identity stable, so a payload-only edit does not rewrite the meta row.

const record = Sprites.Reactive.Pending();
Sprites.Library.Store.Media.Read(record, id);
const meta = Sprites.Library.Store.Media.metaOf(record);
const name = Sprites.Object.Field(meta, 'name');
Sprites.Ui.Dom.Text(name);
Project the light row off a whole record without rewriting it on payload edits.

Sprites.Library.Store.Refs

The refs table: the reference edges. An edge is plain data { id, from, to, kind, slot, label }. Editors maintain their own edges with these normal reads and writes. The usage list is Filter with { to: target }; an owner's edges are Filter with { from: owner }; the usage count is Count with { to: target }.

Refs.Read Read

Sprites.Library.Store.Refs.Read(result, id)

Read one edge into result, by id.

const result = Sprites.Reactive.Pending();
Sprites.Library.Store.Refs.Read(result, id);
const to = Sprites.Object.Field(result, 'to');
Load one edge by its id.

Refs.Write Write

Sprites.Library.Store.Refs.Write(id, edge)

Write one edge under its id, when an editor sets the reference it stands for.

const edge = { id: edgeId, from: owner, to: target, kind: 'tile', slot: 3, label: 'Wall' };
Sprites.Library.Store.Refs.Write(edgeId, edge);
Save an edge when a reference is set.

Refs.Delete Command

Sprites.Library.Store.Refs.Delete(id)

Delete one edge by id, when an editor clears the reference it stood for.

Sprites.Library.Store.Refs.Delete(edgeId);
Remove an edge when a reference is cleared.

Refs.Binding Binding

Sprites.Library.Store.Refs.Binding(result, id)

A two way edge value: read one edge into result and write edits back.

const result = Sprites.Reactive.Pending();
Sprites.Library.Store.Refs.Binding(result, edgeId);
const label = Sprites.Object.Field(result, 'label');
Sprites.Ui.Input.Text(label);
Edit an edge in place.

Refs.Filter Live, array

Sprites.Library.Store.Refs.Filter(rows, filter, start, limit)

A filtered, paged read of edges into rows. The usage list is Filter with { to: target }; an owner's edges are Filter with { from: owner }.

const rows = Sprites.Reactive.Pending();
const filter = { to: target };
Sprites.Library.Store.Refs.Filter(rows, filter, 0, 50);
The usages of a target: the edges whose to is it.

Refs.Count Live, number

Sprites.Library.Store.Refs.Count(total, filter)

The number of edges matching filter, into total. The usage count is Count with { to: target }.

const total = Sprites.Reactive.Pending();
const filter = { to: target };
Sprites.Library.Store.Refs.Count(total, filter);
Sprites.Ui.Dom.Text('Used in ', total, ' places');
How many edges point at a target.