Dynamic IO proxy: derive proxied primitives from component io_refs

Replace hardcoded IO primitive lists on both client and server with
data-driven registration. Page registry entries carry :io-deps (list
of IO primitive names) instead of :has-io boolean. Client registers
proxied IO on demand per page via registerIoDeps(). Server builds
allowlist from component analysis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 09:13:53 +00:00
parent c2a85ed026
commit cb0990feb3
7 changed files with 61 additions and 38 deletions

View File

@@ -41,7 +41,7 @@
(div :class "rounded-lg border border-stone-200 bg-white p-5 space-y-3"
(h3 :class "text-sm font-medium text-stone-500 uppercase tracking-wide" "SX async rendering spec")
(~doc-code :code
(highlight ";; try-client-route dispatches on has-io flag\n(if has-io\n ;; Async render: IO primitives proxied via /sx/io/<name>\n (do\n (try-async-eval-content content-src env\n (fn (rendered)\n (when rendered\n (swap-rendered-content target rendered pathname))))\n true)\n ;; Sync render: pure components, no IO\n (let ((rendered (try-eval-content content-src env)))\n (swap-rendered-content target rendered pathname)))" "lisp"))))
(highlight ";; try-client-route reads io-deps from page registry\n(let ((io-deps (get match \"io-deps\"))\n (has-io (and io-deps (not (empty? io-deps)))))\n ;; Register IO deps as proxied primitives on demand\n (when has-io (register-io-deps io-deps))\n (if has-io\n ;; Async render: IO primitives proxied via /sx/io/<name>\n (do\n (try-async-eval-content content-src env\n (fn (rendered)\n (when rendered\n (swap-rendered-content target rendered pathname))))\n true)\n ;; Sync render: pure components, no IO\n (let ((rendered (try-eval-content content-src env)))\n (swap-rendered-content target rendered pathname))))" "lisp"))))
;; Architecture explanation
(div :class "rounded-lg border border-blue-200 bg-blue-50 p-5 space-y-3"
@@ -49,8 +49,8 @@
(ol :class "list-decimal list-inside text-blue-800 space-y-2 text-sm"
(li "Server renders the page — " (code "highlight") " runs Python directly")
(li "Client receives component definitions including " (code "~async-io-demo-content"))
(li "On client navigation, " (code "has-io") " flag routes to async renderer")
(li "Async renderer encounters " (code "(highlight ...)") " — checks " (code "IO_PRIMITIVES"))
(li "On client navigation, " (code "io-deps") " list routes to async renderer")
(li (code "register-io-deps") " ensures each IO name is proxied via " (code "registerProxiedIo"))
(li "Proxied call: " (code "fetch(\"/sx/io/highlight?_arg0=...&_arg1=lisp\")"))
(li "Server runs highlight, returns SX source (colored span elements)")
(li "Client parses SX → AST, async renderer recursively renders to DOM")))