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.Meta
Sprites.Library.Store.Media
- Media.Read
- Media.Write
- Media.Delete
- Media.Binding
- Media.Filter
- Media.Count
- Media.List
- Media.Rename
- Media.Replace
- Media.metaOf
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);
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 };
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.
| Input | Type | Description |
|---|---|---|
id | String | The fresh id for the new document, from Id. |
template | Object | Carries 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);
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);
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);
Meta.Delete Command
Sprites.Library.Store.Meta.Delete(id)
Delete one meta row by id.
Sprites.Library.Store.Meta.Delete(id);
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);
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);
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');
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');
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);
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);
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.
| Input | Type | Description |
|---|---|---|
result | Sprites.Reactive.Value | The sink the document reads into and writes back from. |
id | Sprites.Reactive.Value or String | The document id to open. Reactive or constant. |
optionalSeed | Object | The 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');
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);
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);
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.
| Field | Type | Description |
|---|---|---|
query.media | String | The media type to list. Equality, optional. |
query.platform | String | Limit to one platform. Equality, optional. |
query.search | String | Keep documents whose name contains this text. Optional. |
query.start | Number | Skip this many, for paging. Optional. |
query.count | Number | Return at most this many. Optional. |
query.sort | String | '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);
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);
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);
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);
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');
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);
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);
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);
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);
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');