- docs/examples/web-app: Product (@unique name, backlink orders) / Order (ref Product) as @table classes; handlers as Handler classes — ListProducts (ordered query -> JSON array), ShowProduct (unique-index probe, 404), CreateProduct (checked json.decode -> 400; @unique trap -> 409), CreateOrder (FK insert), DeleteProduct (FK restrict trap -> 409); Auth middleware reads WA_TOKEN. Entry validates port + token honestly. - The [deps] KEY is the module name `use` imports: hyphens are not identifier characters, so the app keys the dep `framework` while the repository keeps its long name (recorded in the manifest comment). - driver fix (real gap the chain exposed): a dependency's INTERNAL `use` paths are written against its own root (`use http` inside the framework) but compile under `<depname>/...` — compile_image now prefixes dep files' use paths with the dep name (stdlib namespaces stay bare; a path already starting with the dep name is untouched). Verified end to end through the full chain (temp git remote of the framework, file:// substituted, fetch -> lock -> build -> serve): 401 without the token; [] empty list; 201 create; 409 duplicate (@unique); 400 malformed json; list/show payloads exact; 404 unknown product; 201 order; 409 delete-while-referenced (FK restrict) with the server still serving; SIGTERM clean; the product survives a process restart (WAL replay). Gates: woc-test 540/0, oop-e2e 88/0, deps-accept 8/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| main.wo | ||
| README.md | ||
| types.wo | ||
| wo.toml | ||
web-app — the storefront sample
A small store: Product/Order as @table classes, JSON routes, one auth
middleware — built on writeonce-framework, which
it imports through [deps] (iteration 15). This app is iteration 16's
acceptance workload: just web-app runs the whole chain — fetch → lock →
build → serve → curl matrix → restart persistence → SIGTERM.
Routes
| Route | What |
|---|---|
GET /products |
list (JSON array) |
GET /products/:id |
one product or 404 |
POST /products |
create from a JSON body (name, price, stock); 400 on malformed JSON; 409 on a duplicate name (@unique) |
POST /orders |
create (product, qty); FK checked |
DELETE /products/:id |
409 while orders reference it (FK restrict), 200 after |
Every request needs authorization: Bearer <token> (the auth middleware);
the token comes from the WA_TOKEN env var.
Run
woc . # fetches deps, builds target/web-app
WA_TOKEN=secret WO_DATA=./data ./target/web-app 8080
TLS / HTTP2
None here, deliberately: deploy behind nginx/caddy — the proxy terminates TLS+ALPN and speaks h2 to browsers while this backend serves HTTP/1.1 keep-alive. Sketch:
server {
listen 443 ssl;
http2 on;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}