writeonce/reference/rest/blog.rest
shoney.arickathil 9279175f26 scaffold sibling crates, multi-app ecommerce, REST + concurrency docs
- scaffold 14 placeholder crates (app, db, engine, gen, http, logic,
  policy, ql, service, sub, txn, ui, value, wal) — empty Cargo.toml +
  src/lib.rs to receive code phase-by-phase from `rt`
- restructure docs/examples/ecommerce into multi-app layout: apps/admin
  and apps/storefront, with shared/ types/logic/components, per-app
  app.wo + wo.toml, and reusable .htmlx components (layout, money,
  order-row)
- add reference/rest/{blog,ecommerce}.rest — VS Code/JetBrains HTTP
  request files driving the running prototype, including 501/404/405
  expectations for stubbed endpoints
- add docs/plan/09-concurrency-scaleout.md and docs/plan/ui/00-overview.md;
  refine docs/plan/assembly/02-writeonce-stance.md
- refresh templates (about, article, header/footer, home, layout, styles)
  and add static favicon/logo
- add infra/sync.sh and tighten .gitignore for reference/ symlinks
2026-05-04 13:39:58 +02:00

181 lines
5.9 KiB
ReStructuredText

###############################################################################
# blog.rest — exercise the `.wo` runtime against docs/examples/blog/
#
# Start the server first:
# cargo run --bin wo -- run docs/examples/blog
#
# Then in VS Code (REST Client extension) or JetBrains (HTTP Client):
# click "Send Request" on each block, top to bottom
#
# Response back-references (# @name foo → {{foo.response.body.id}}) are
# supported by both clients — later blocks pick up ids minted by earlier
# blocks automatically. For `curl` equivalents, see reference/rest/README.md.
###############################################################################
@host = http://127.0.0.1:8080
### Runtime info — expected 200
GET {{host}}/
### Liveness probe — expected 200 "ok"
GET {{host}}/healthz
###############################################################################
# Author — exposes: list, get, me, subscribe
###############################################################################
### List authors (empty on fresh boot) — expected 200 []
GET {{host}}/api/authors
### Author create is NOT exposed in the blog sample (expose list, get, me, subscribe)
# Expected 405 — method not allowed. The sample expects authors seeded by
# `on startup do: seed_admin()` in app.wo. Stage 2 doesn't run startup hooks
# yet, so the list above will be empty.
POST {{host}}/api/authors
Content-Type: application/json
{ "email": "alice@example.com", "handle": "alice", "display": "Alice" }
### /me — Stage 3 session layer; expected 501
GET {{host}}/api/authors/me
### LIVE subscribe — Stage 3; expected 501
GET {{host}}/api/authors/live
###############################################################################
# Article — exposes: list, get, create, update, delete, subscribe
###############################################################################
### Create an article — expected 201
# @name createArticle
POST {{host}}/api/articles
Content-Type: application/json
{
"slug": "hello-writeonce",
"title": "Hello, writeonce",
"author": 1,
"published": true,
"meta": {
"excerpt": "First post on the new runtime.",
"body_md": "# Hi\n\nHello from the `.wo` runtime. The server, the database, and this HTTP API are all one binary.\n"
}
}
### Create a second article (draft) — expected 201
# @name createDraft
POST {{host}}/api/articles
Content-Type: application/json
{
"slug": "second-draft",
"title": "Second Post (draft)",
"author": 1,
"published": false,
"meta": { "excerpt": "", "body_md": "WIP." }
}
### List articles — expected 200 with 2 rows
GET {{host}}/api/articles
### Get one article by id — expected 200
GET {{host}}/api/articles/{{createArticle.response.body.id}}
### Partial update (PATCH) — change just the title — expected 200
PATCH {{host}}/api/articles/{{createArticle.response.body.id}}
Content-Type: application/json
{ "title": "Hi, writeonce!" }
### Partial update of an embedded-document field — expected 200
# Note: Stage 2's PATCH does a shallow merge at the top level.
# To change `meta.excerpt` alone you re-send the whole `meta` object.
PATCH {{host}}/api/articles/{{createArticle.response.body.id}}
Content-Type: application/json
{
"meta": { "excerpt": "Updated excerpt.", "body_md": "# Hi\n\nUpdated body." }
}
### Publish the draft — expected 200 (`on update` trigger that sets
### `published_at` is Stage 3+; Stage 2 just records the bool change).
PATCH {{host}}/api/articles/{{createDraft.response.body.id}}
Content-Type: application/json
{ "published": true }
### Delete the draft — expected 204 No Content
DELETE {{host}}/api/articles/{{createDraft.response.body.id}}
### Get the deleted id — expected 404
GET {{host}}/api/articles/{{createDraft.response.body.id}}
### LIVE subscribe (Article) — Stage 3; expected 501
GET {{host}}/api/articles/live
###############################################################################
# Tag — exposes: list, get, subscribe
###############################################################################
### List tags — expected 200 [] (create is not exposed)
GET {{host}}/api/tags
### Tag create NOT exposed (expose list, get, subscribe) — expected 405
POST {{host}}/api/tags
Content-Type: application/json
{ "slug": "rust", "label": "Rust" }
### LIVE subscribe (Tag) — Stage 3; expected 501
GET {{host}}/api/tags/live
###############################################################################
# Comment — exposes: list, get, create, update, delete, subscribe
###############################################################################
### Create a comment — expected 201
# @name createComment
POST {{host}}/api/comments
Content-Type: application/json
{
"article": {{createArticle.response.body.id}},
"author": 1,
"body": "Nice post. Runs on one binary which is still weird to me."
}
### List comments — expected 200 with 1 row
GET {{host}}/api/comments
### Get one comment — expected 200
GET {{host}}/api/comments/{{createComment.response.body.id}}
### Update comment body — expected 200 (the `on update when old.body != new.body
### do set self.edited_at = now()` trigger is Stage 3+; edited_at stays unset)
PATCH {{host}}/api/comments/{{createComment.response.body.id}}
Content-Type: application/json
{ "body": "Edited: really, one binary? Neat." }
### Delete comment — expected 204
DELETE {{host}}/api/comments/{{createComment.response.body.id}}
### LIVE subscribe (Comment) — Stage 3; expected 501
GET {{host}}/api/comments/live
###############################################################################
# Final state — should show the updated article still there, no drafts,
# no comments (all deleted above).
###############################################################################
### Final article list — expected 200 with 1 row
GET {{host}}/api/articles
### Final comment list — expected 200 []
GET {{host}}/api/comments