71 lines
2.8 KiB
Text
71 lines
2.8 KiB
Text
-- main.wo — the smallest complete writeonce program.
|
|
--
|
|
-- Run it from the repo root:
|
|
--
|
|
-- cargo run --bin wo -- run docs/examples/hello (or: just hello)
|
|
-- just hello-demo -- scripted CRUD round-trip
|
|
--
|
|
-- and exercise it:
|
|
--
|
|
-- curl -X POST localhost:8080/api/notes \
|
|
-- -H "Content-Type: application/json" \
|
|
-- -d '{"title":"hello","body":"# First note"}'
|
|
-- curl localhost:8080/api/notes
|
|
-- curl localhost:8080/api/notes/1
|
|
-- curl -X PATCH localhost:8080/api/notes/1 -d '{"pinned":true}'
|
|
-- curl -X DELETE localhost:8080/api/notes/1
|
|
--
|
|
-- One type declaration is the whole app: the fields define the schema, the
|
|
-- `service` block generates the REST endpoints, and the runtime serves them
|
|
-- from a single binary — no external database, no framework.
|
|
|
|
type Note {
|
|
id: Id
|
|
title: Text
|
|
body: Markdown
|
|
pinned: Bool = false -- literal defaults populate on create
|
|
created_at: Timestamp = now() -- so does now(); computed defaults
|
|
-- like words(...) are Stage 4+
|
|
|
|
service rest "/api/notes"
|
|
expose list, get, create, update, delete, subscribe
|
|
-- list/get/create/update/delete work today (Stage 2).
|
|
-- subscribe maps to GET /api/notes/live — a documented 501 stub
|
|
-- until Stage 3 lands LIVE subscriptions over WebSocket.
|
|
}
|
|
|
|
-- A second actor that modifies Note. The closest thing to "another class" in
|
|
-- writeonce is another type with a trigger: there is no class/method model —
|
|
-- behavior attaches to data. Creating a Revision rewrites its target note's
|
|
-- title, inside the same transaction as the insert. Triggers execute from
|
|
-- Stage 4; today the block parses and is discarded.
|
|
type Revision {
|
|
id: Id
|
|
note: ref Note -- foreign key into Note
|
|
new_title: Text
|
|
at: Timestamp = now()
|
|
|
|
on create
|
|
do update Note{ id == self.note }.title = self.new_title
|
|
}
|
|
|
|
-- Procedural entry point. Stage 2 parses and discards `main` blocks
|
|
-- (see crates/rt/src/parser.rs — skip_top_level_chunk); from Phase 6 on
|
|
-- this runs once at startup, before the HTTP server binds.
|
|
main {
|
|
insert Note { title: "hello", body: "# First note" };
|
|
|
|
-- A snapshot binding would never see later changes (let n = select ...).
|
|
-- LIVE is the language's "pointer that observes stores": the handle
|
|
-- receives a delta at every commit that touches a matching row. Stage 3.
|
|
-- (Spec: docs/runtime/database/02-wo-language.md § Schema-Layer DML)
|
|
let live = LIVE select Note{ title };
|
|
|
|
-- The other actor fires: this insert runs Revision's on-create trigger,
|
|
-- the trigger updates the note, and the commit pushes one delta.
|
|
insert Revision { note: 1, new_title: "Hello World" };
|
|
|
|
for delta in live {
|
|
print(delta.kind, delta.row.title); -- update "Hello World"
|
|
}
|
|
}
|