Remote / foldkit-remote

Routing Remote's Messages

The first run folds Remote's Messages under one variant of the application's union, the shape Foldkit gives a Submodel. The fold's fetch, mutate, and subscriptions yield that variant too, with the lift recorded so a Story resolves a fetch or a mutation by Remote's own answer.

The shorter path, for an update that only reduces, spreads Remote's cases into the union and narrows by tag; the rest of update is then a partial match over tags the application never handles:

ts
const Message = defineMessageUnion({ ...Remote.messages })

function update(model: Model, message: Message): Update.Return<Model, Message, RemoteClient> {
  if (Remote.reduces(message)) return { model: Data.reduce(model, message) }
  return { model }
}

The rest of this guide uses the fold. With the spread, read Data.subscriptions for foldData.subscriptions and Data.mutate for foldData.mutate.

One value with foldkit-bundle: Data.wiring

The integration steps above — fold or reduce, derive the Subscriptions, provide the client — are one value when the application uses foldkit-bundle:

ts
import { Bundle } from 'foldkit-bundle'

const Page = Bundle.parent({ Model, Message })
const wiring = Page.assemble(
  Data.wiring({
    project: Surface.at(ProjectPage, model =>
      model.route._tag === 'project'
        ? Option.some({ projectId: model.route.projectId })
        : Option.none(),
    ),
  }),
)
const update = wiring.update(model => ({ model }))

Data.wiring routes Remote's Messages into Data.reduce, brings the active Surfaces' Subscriptions and the domain's contract, and requires RemoteClient from the runtime's resources — the same client layer from above. One assembly holds at most one Remote domain: every domain claims the same Message tags, and the assembly refuses a second claimant at startup, naming both.