Lets app/api/foo.prg keep its idiomatic `FUNCTION Main()` shape while
multiple such files compile into one binary. fnode auto-renames each
library file's Main into a unique symbol derived from the basename:
app/api/hello.prg -> HELLO__MAIN
app/api/admin-stats.prg -> ADMIN_STATS__MAIN (hyphen -> underscore)
Three moving parts:
cmd/fnode/main.go
parseOne for every PRG, then rename Main on every file except
the first (the entry). crossFile map updated so the analyzer
treats the renamed symbol as declared.
hbrtl_ext/dispatch/dispatch.go
New HB_FUNC FNODE_CALL(cFuncName) that does VM.FindSymbol +
PushSymbol/Function dance and discards the return value. Same
pattern pgserver's callPRG helper uses internally.
app/bridge_server.prg
BridgeDispatch now derives the symbol name from hReq["path"]
( /api/foo[.prg] -> FOO__MAIN ), invokes FNODE_CALL, and
maps "not found" errors to HTTP 404 (other errors -> 500).
Hardcoded /api/hello and /api/echo handlers replaced by the
path-driven model.
Verified end-to-end with app/api/hello.prg and app/api/admin-stats.prg:
GET /api/hello.prg -> 200 + JSON from HELLO__MAIN
GET /api/hello -> 200 (extension optional)
GET /api/admin-stats.prg?from=2026 -> 200 from ADMIN_STATS__MAIN
with query string echoed
GET /api/nope -> 404 "function not found"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Seven HB_FUNCs that fivenode's bridge_*.prg layer relies on:
_CTX_SET_JSON / _CTX_GET_JSON — per-request context payload
_OUT_APPEND / _OUT_GET / _OUT_CLEAR — response body buffer
_BRIDGE_SET_RESULT / _BRIDGE_GET_RESULT — fast-path response
Crucially per-thread, not process-global like the original C
implementation. fivenode runs single-threaded under N-API so a static
buffer per process was fine; fivenode_go runs one *hbrt.Thread per
HTTP request goroutine, so the state is keyed by *hbrt.Thread in a
sync.Map. The HTTP dispatcher will call CleanupThread once per
request to keep the map bounded (sub-phase 1a.3-3).
Also exposes Go-side helpers (OutputBytes, Result, SetContextJSON,
CleanupThread) so the dispatcher can seed the context and harvest
the response without bouncing back through PRG.
Verified with app/capi_test.prg: all seven functions behave as
expected; combined with the Five hb_jsonDecode byref fix, ctx_get()
now correctly returns hash values rather than the fallback default.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>