Mirror / foldkit-mirror

One list per application with wiring

The hand-wiring above — fold or reduce, restore at startup, spread the Subscriptions — is one value when the application uses foldkit-bundle:

ts
import { Bundle } from 'foldkit-bundle'

const Page = Bundle.parent({ Model, Message })
const wiring = Page.assemble(Filters.wiring('UrlChanged'), Prefs.wiring())
const update = wiring.update(model => ({ model }))
const subscriptions = wiring.subscriptions()
const url = wiring.url(url => Message.UrlChanged({ url }))

Filters.wiring('UrlChanged') routes the application's URL Message into Filters.reduce and reads the URL at startup; Prefs.wiring() routes its own MirrorRestored into Prefs.reduce and runs Prefs.restore at startup. Both tags are shared: two key-value mirrors each read only their own MirrorRestored, several URL mirrors each read their keys from one UrlChanged, and the application's own update sees UrlChanged after them, so it can route on the URL over the slices they have already read.

Slice = field refs or a writable Projection

A mirror accepts either field refs directly:

ts
fields: [
  App.model.filter,
  App.model.page,
]

or a writable Projection:

ts
fields: Projection.pick(
  App.model.sidebar,
  App.model.draft,
)

That is the same structural vocabulary used elsewhere in Foldkit Plus. The projection tells Mirror what it may observe and write back; it does not transfer ownership away from the application.