Construir una API REST
Una API CRUD completa — rutas, auth, validación, paginación, una base de datos real — en un archivo, con el servidor HTTP de producción integrado. Sin framework, sin servidor ASGI, sin requirements.txt.
Todo junto
require serve(8080)
require db("./store.db")
task check_token(req)
give header_of(req, "authorization") == "Bearer secret" -- tu chequeo real acá
serve on 8080
auth with check_token
route "GET /products"
give paged("SELECT id, name, price FROM products ORDER BY id") -- paginado + total
route "GET /products/:id"
let rows be sql("SELECT * FROM products WHERE id = ?", [params.id])
give when length(rows) == 0 then not_found("no such product") otherwise rows[0]
route "POST /products" requires auth
expect body {name: text, price: number} -- 400 automático si no coincide
let b be json of request
sql_exec("INSERT INTO products (name, price) VALUES (?, ?)", [b["name"], b["price"]])
give created(b)
route "DELETE /products/:id" requires auth
sql_exec("DELETE FROM products WHERE id = ?", [params.id])
give ok({"deleted": params.id})
Correlo: synsema serve api.syn. Eso es un servidor de producción — async, multi-core real, un único binario estático sin runtime.
Lo que obtuviste gratis
-- Doc example: the serve response contract. Helpers return {status, value}; the
-- runtime renders them. (A real `serve on` block doesn't terminate, so the doctest
-- asserts the response shapes the handlers give — see the prose for a full server.)
intent: "doc example: serve response contract"
print("ok → " + text(status of ok({"a": 1})) + ", fail(400) → " + text(status of fail(400, "bad")))
test "uniform response helpers carry a status + value"
assert_eq(status of ok({"a": 1}), 200)
assert_eq(status of created({"id": 1}), 201)
assert_eq(status of fail(400, "bad input"), 400)
assert_eq(status of not_found("missing"), 404)
assert_eq((value of fail(400, "bad input"))["error"], "bad input")
- Respuestas uniformes —
ok/created/fail/not_foundllevan el status correcto; un valor pelado se vuelve200 {json}. - Validación —
expect body {…}devuelve400con detalle cuando el body no coincide; sin chequeos manuales. - Auth —
auth with <task>+requires authpor ruta. - Paginación —
paged(...)empujaLIMIT/OFFSETal SQL y calcula un total exacto. - Seguro por defecto —
require db/serve, secretos redactados, con scope de capacidad.
vs. FastAPI
Sin framework que instalar, sin modelos Pydantic, sin Uvicorn, sin requirements.txt — un binario, un archivo. La validación y la auth son keywords del lenguaje, no decoradores que cableás a mano. Y es seguro por defecto y se despliega con un flag. Mirá Servidor HTTP para la referencia completa de rutas/SSE/CORS y Frontend para servir HTML también.