Sync / foldkit-sync
Sixty seconds: say what is shared
Start from an ordinary application. The example keeps a todo list and a selection; only the list is shared.
ts
import { Option, Schema } from 'effect'
import { defineMessageUnion } from 'foldkit/message'
import { modifyFields } from 'foldkit/struct'
import type * as Update from 'foldkit/update'
import { MessageSet, Projection, Surface } from 'foldkit-surface'
import { DocumentId, Sync } from 'foldkit-sync'
const Model = Schema.Struct({
todos: Schema.Array(Schema.Struct({ id: Schema.String, title: Schema.String })),
selectedTodoId: Schema.Option(Schema.String),
lastError: Schema.Option(Schema.String),
})
type Model = typeof Model.Type
const Message = defineMessageUnion({
CreatedTodo: { id: Schema.String, title: Schema.String },
RenamedTodo: { id: Schema.String, title: Schema.String },
SelectedTodo: { id: Schema.String },
})
type Message = typeof Message.Type
const initial: Model = { todos: [], selectedTodoId: Option.none(), lastError: Option.none() }
type Return = Update.Return<Model, Message>
const update = (model: Model, message: Message): Return =>
Message.match<Return>(message, {
CreatedTodo: ({ id, title }) => ({
model: modifyFields(model, { todos: () => [...model.todos, { id, title }] }),
}),
RenamedTodo: ({ id, title }) => ({
model: modifyFields(model, {
todos: () => model.todos.map(todo => (todo.id === id ? { ...todo, title } : todo)),
}),
}),
SelectedTodo: ({ id }) => ({
model: modifyFields(model, { selectedTodoId: () => Option.some(id) }),
}),
})
const App = Surface.application({ Model, Message, initial, update })
const TodoSync = Sync.forApplication(App).make({
documentId: DocumentId.make('todos'),
shared: Projection.pick(App.model.todos),
durable: MessageSet.make(App, [Message.CreatedTodo, Message.RenamedTodo]),
})Read the declaration as a table:
todos shared replicated, persisted, journaled
selectedTodoId local this device only
lastError local
CreatedTodo durable recorded in the outbox, committed by the server
RenamedTodo durable
SelectedTodo local runs through update and goes nowhereFrom that, make derives the shared codec, the initial shared value, the
operation envelope, replay (your update on the shared slice), and the
server's journal contract. You write none of them.
TodoSync is a value. It has opened no storage, connected to nothing, and
rendered nothing. The next section does that.