From 537a302c922050b84a82ffc84460e2a544b87868 Mon Sep 17 00:00:00 2001 From: CharlesKWON Date: Mon, 15 Jun 2026 14:49:07 +0900 Subject: [PATCH] docs(rag): adopt endpoint helpers + no-inline-semicolon style Update idioms skeleton to use REQUIRE_PG/REQUIRE_JSON_BODY/API_OK/API_ERR, and add the style rule banning inline ';' multi-statements (visual-review readability) to idioms + gotchas. Co-Authored-By: Claude Opus 4.8 (1M context) --- rag/04-idioms.md | 39 ++++++++++++++++++++++++++------------- rag/05-gotchas.md | 17 ++++++++++++++++- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/rag/04-idioms.md b/rag/04-idioms.md index b347faf..1f6e0ec 100644 --- a/rag/04-idioms.md +++ b/rag/04-idioms.md @@ -9,36 +9,49 @@ summary: Battle-tested patterns from the production solmade app for building HTT All snippets are from the real `solmade` app (`/Users/charleskwon/solmade`). -## 1. HTTP endpoint skeleton +## 1. HTTP endpoint skeleton (use the shared helpers) -One `FUNCTION Main()` per `.prg` file under `app/api/`. +One `FUNCTION Main()` per `.prg` file under `app/api/`. Use the helpers in +`app/lib/api.prg` instead of repeating PG/JSON/error boilerplate: + +- `REQUIRE_PG() → nPG` — PG handle; on failure emits a 500 JSON error and returns -1. +- `REQUIRE_JSON_BODY() → hBody | NIL` — parsed JSON body; on failure emits 400, returns NIL. +- `API_OK( [hPayload] ) → NIL` — sends `{"ok":true, ...payload}`. +- `API_ERR( nStatus, cMsg [, hExtra] ) → NIL` — sends `{"ok":false,"error":cMsg, ...}`. + +xBase can't force the caller to return, so the convention is "helper sets the response, +caller returns immediately." `API_OK`/`API_ERR` return NIL so you can write +`RETURN API_ERR( 400, "…" )` on one line. ```five // POST /api/press-save.prg FUNCTION Main() - LOCAL nPG := LABDB_GET_PG() - LOCAL hBody, nUser, aRows + LOCAL nPG := REQUIRE_PG() + LOCAL hBody, nUser IF nPG < 0 - ctx_set( "status", 500 ) - AP_JSONRESPONSE( { "ok" => .f., "error" => "PG not connected" } ) RETURN NIL ENDIF - hBody := hb_jsonDecode( AP_BODY() ) // parse JSON request body - IF ! HB_ISHASH( hBody ) - ctx_set( "status", 400 ) - AP_JSONRESPONSE( { "ok" => .f., "error" => "body must be JSON object" } ) + hBody := REQUIRE_JSON_BODY() + IF hBody == NIL RETURN NIL ENDIF nUser := Val( ctx_get( "auth_user_id", "0" ) ) // authed user (string → int) + IF Empty( nUser ) + RETURN API_ERR( 401, "login required" ) + ENDIF - AP_JSONRESPONSE( { "ok" => .t. } ) - RETURN NIL + RETURN API_OK( { "id" => 123 } ) ``` -Core verbs: +> STYLE: always write `IF`/`FOR`/`WHILE` bodies on their own indented lines. Do NOT use +> inline `;` to pack multiple statements on one line (`IF nPG < 0 ; RETURN NIL ; ENDIF` +> is banned — it hurts visual review). The trailing-`;` line *continuation* (for long +> strings/SQL/args) is a different, allowed use. + +Core verbs (used by/inside the helpers): - `AP_BODY()` → raw request body (decode with `hb_jsonDecode`). - `AP_GETPAIRS( .t. )` → hash of query-string params (GET). - `AP_JSONRESPONSE( hHash )` → serialize + send JSON response. diff --git a/rag/05-gotchas.md b/rag/05-gotchas.md index f0cdd3a..a93c4f9 100644 --- a/rag/05-gotchas.md +++ b/rag/05-gotchas.md @@ -79,7 +79,22 @@ about; they still resolve at runtime via the registry. To silence, add the name known-function set in `compiler/analyzer/analyzer.go` (e.g. `HB_GETCHARSET` etc. were added there). A warning is not an error. -## 10. Density is a double-edged sword when debugging +## 10. STYLE: no inline `;` multi-statements (banned) + +Five aims to be easy for a human to verify by eye. Do **not** pack multiple statements +onto one line with `;`: `IF nPG < 0 ; RETURN NIL ; ENDIF`, `IF Empty(x) ; x:="y" ; ENDIF` +are banned — they hurt visual review. Always expand: + +```five +IF nPG < 0 + RETURN NIL +ENDIF +``` + +(The *trailing* `;` for line continuation — joining a long string/SQL/arg list across +lines — is a different, allowed feature. The ban is only on `;` as a statement separator.) + +## 11. Density is a double-edged sword when debugging One line doing a lot means one line failing does a lot. When a dense statement misbehaves, expand it (split the chained `hb_*`/`PG_*`/`LLM_CHAT` calls into temporaries) to localize