;; Reference API endpoints — live demos for hypermedia attribute docs ;; ;; These replace the Python endpoints in bp/pages/routes.py. ;; Each defhandler with :path registers as a public route automatically. ;; --- sx-get demo: server time --- (defhandler ref-time :path "/sx/(geography.(hypermedia.(reference.(api.time))))" :method :get :returns "element" (&key) (let ((now (helper "now" "%H:%M:%S"))) (<> (span (~tw :tokens "text-stone-800 text-sm") "Server time: " (strong now)) (~docs/oob-code :target-id "ref-wire-sx-get" :text (str "(span :class \"text-stone-800 text-sm\" \"Server time: \" (strong \"" now "\"))"))))) ;; --- sx-post demo: greet --- (defhandler ref-greet :path "/sx/(geography.(hypermedia.(reference.(api.greet))))" :method :post :csrf false :returns "element" (&key) (let ((name (helper "request-form" "name" "stranger"))) (<> (span (~tw :tokens "text-stone-800 text-sm") "Hello, " (strong name) "!") (~docs/oob-code :target-id "ref-wire-sx-post" :text (str "(span :class \"text-stone-800 text-sm\" \"Hello, \" (strong \"" name "\") \"!\")"))))) ;; --- sx-put demo: status update --- (defhandler ref-status :path "/sx/(geography.(hypermedia.(reference.(api.status))))" :method :put :csrf false :returns "element" (&key) (let ((status (helper "request-form" "status" "unknown"))) (<> (span (~tw :tokens "text-stone-700 text-sm") "Status: " (strong status) " — updated via PUT") (~docs/oob-code :target-id "ref-wire-sx-put" :text (str "(span :class \"text-stone-700 text-sm\" \"Status: \" (strong \"" status "\") \" — updated via PUT\")"))))) ;; --- sx-patch demo: theme --- (defhandler ref-theme :path "/sx/(geography.(hypermedia.(reference.(api.theme))))" :method :patch :csrf false :returns "element" (&key) (let ((theme (helper "request-form" "theme" "unknown"))) (<> theme (~docs/oob-code :target-id "ref-wire-sx-patch" :text (str "\"" theme "\""))))) ;; --- sx-delete demo --- (defhandler ref-delete-item :path "/sx/(geography.(hypermedia.(reference.(api.(item.)))))" :method :delete :csrf false :returns "element" (&key) (<> (~docs/oob-code :target-id "ref-wire-sx-delete" :text "\"\""))) ;; --- sx-trigger demo: search --- (defhandler ref-trigger-search :path "/sx/(geography.(hypermedia.(reference.(api.trigger-search))))" :method :get :returns "element" (&key) (let ((q (helper "request-arg" "q" ""))) (let ((sx-text (if (= q "") "(span :class \"text-stone-400 text-sm\" \"Start typing to trigger a search.\")" (str "(span :class \"text-stone-800 text-sm\" \"Results for: \" (strong \"" q "\"))")))) (<> (if (= q "") (span (~tw :tokens "text-stone-400 text-sm") "Start typing to trigger a search.") (span (~tw :tokens "text-stone-800 text-sm") "Results for: " (strong q))) (~docs/oob-code :target-id "ref-wire-sx-trigger" :text sx-text))))) ;; --- sx-swap demo --- (defhandler ref-swap-item :path "/sx/(geography.(hypermedia.(reference.(api.swap-item))))" :method :get :returns "element" (&key) (let ((now (helper "now" "%H:%M:%S"))) (<> (div (~tw :tokens "text-sm text-violet-700") (str "New item (" now ")")) (~docs/oob-code :target-id "ref-wire-sx-swap" :text (str "(div :class \"text-sm text-violet-700\" \"New item (" now ")\")"))))) ;; --- sx-swap-oob demo --- (defhandler ref-oob :path "/sx/(geography.(hypermedia.(reference.(api.oob))))" :method :get :returns "element" (&key) (let ((now (helper "now" "%H:%M:%S"))) (<> (span (~tw :tokens "text-emerald-700 text-sm") "Main updated at " now) (div :id "ref-oob-side" :sx-swap-oob "innerHTML" (span (~tw :tokens "text-violet-700 text-sm") "OOB updated at " now)) (~docs/oob-code :target-id "ref-wire-sx-swap-oob" :text (str "(<> (span ... \"" now "\") (div :id \"ref-oob-side\" :sx-swap-oob \"innerHTML\" ...))"))))) ;; --- sx-select demo --- (defhandler ref-select-page :path "/sx/(geography.(hypermedia.(reference.(api.select-page))))" :method :get :returns "element" (&key) (let ((now (helper "now" "%H:%M:%S"))) (<> (div :id "the-header" (h3 "Page header — not selected")) (div :id "the-content" (span (~tw :tokens "text-emerald-700 text-sm") "This fragment was selected from a larger response. Time: " now)) (div :id "the-footer" (p "Page footer — not selected")) (~docs/oob-code :target-id "ref-wire-sx-select" :text (str "(<> (div :id \"the-header\" ...) (div :id \"the-content\" ... \"" now "\") (div :id \"the-footer\" ...))"))))) ;; --- sx-sync demo: slow echo --- (defhandler ref-slow-echo :path "/sx/(geography.(hypermedia.(reference.(api.slow-echo))))" :method :get :returns "element" (&key) (let ((q (helper "request-arg" "q" ""))) (sleep 800) (<> (span (~tw :tokens "text-stone-800 text-sm") "Echo: " (strong q)) (~docs/oob-code :target-id "ref-wire-sx-sync" :text (str "(span :class \"text-stone-800 text-sm\" \"Echo: \" (strong \"" q "\"))"))))) ;; --- sx-prompt demo --- (defhandler ref-prompt-echo :path "/sx/(geography.(hypermedia.(reference.(api.prompt-echo))))" :method :get :returns "element" (&key) (let ((name (helper "request-header" "SX-Prompt" "anonymous"))) (<> (span (~tw :tokens "text-stone-800 text-sm") "Hello, " (strong name) "!") (~docs/oob-code :target-id "ref-wire-sx-prompt" :text (str "(span :class \"text-stone-800 text-sm\" \"Hello, \" (strong \"" name "\") \"!\")"))))) ;; --- Error demo --- (defhandler ref-error-500 :path "/sx/(geography.(hypermedia.(reference.(api.error-500))))" :method :get :returns "nil" (&key) (abort 500 "Server error")) ;; ========================================================================== ;; Remaining reference endpoints — migrated from Python ;; ========================================================================== ;; --- sx-encoding demo: file upload name --- (defhandler ref-upload-name :path "/sx/(geography.(hypermedia.(reference.(api.upload-name))))" :method :post :csrf false :returns "element" (&key) (let ((name (helper "request-file-name" "file"))) (let ((display (if (nil? name) "(no file)" name))) (let ((sx-text (str "(span :class \"text-stone-800 text-sm\" \"Received: \" (strong \"" display "\"))"))) (<> (span (~tw :tokens "text-stone-800 text-sm") "Received: " (strong display)) (~docs/oob-code :target-id "ref-wire-sx-encoding" :text sx-text)))))) ;; --- sx-headers demo: echo custom headers --- (defhandler ref-echo-headers :path "/sx/(geography.(hypermedia.(reference.(api.echo-headers))))" :method :get :returns "element" (&key) (let ((all-headers (into (list) (helper "request-headers-all")))) (let ((custom (filter (fn (pair) (starts-with? (first pair) "x-")) all-headers))) (let ((sx-text (if (empty? custom) "(span :class \"text-stone-400 text-sm\" \"No custom headers received.\")" (str "(ul :class \"text-sm text-stone-700 space-y-1\" " (join " " (map (fn (pair) (str "(li (strong \"" (first pair) "\") \": \" \"" (nth pair 1) "\")")) custom)) ")")))) (<> (if (empty? custom) (span (~tw :tokens "text-stone-400 text-sm") "No custom headers received.") (ul (~tw :tokens "text-sm text-stone-700 space-y-1") (map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) custom))) (~docs/oob-code :target-id "ref-wire-sx-headers" :text sx-text)))))) ;; --- sx-include demo: echo GET query params --- (defhandler ref-echo-vals-get :path "/sx/(geography.(hypermedia.(reference.(api.echo-vals))))" :method :get :returns "element" (&key) (let ((vals (into (list) (helper "request-args-all")))) (let ((sx-text (if (empty? vals) "(span :class \"text-stone-400 text-sm\" \"No values received.\")" (str "(ul :class \"text-sm text-stone-700 space-y-1\" " (join " " (map (fn (pair) (str "(li (strong \"" (first pair) "\") \": \" \"" (nth pair 1) "\")")) vals)) ")")))) (<> (if (empty? vals) (span (~tw :tokens "text-stone-400 text-sm") "No values received.") (ul (~tw :tokens "text-sm text-stone-700 space-y-1") (map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) vals))) (~docs/oob-code :target-id "ref-wire-sx-include" :text sx-text))))) ;; --- sx-vals demo: echo POST form values --- (defhandler ref-echo-vals-post :path "/sx/(geography.(hypermedia.(reference.(api.echo-vals))))" :method :post :csrf false :returns "element" (&key) (let ((vals (into (list) (helper "request-form-all")))) (let ((sx-text (if (empty? vals) "(span :class \"text-stone-400 text-sm\" \"No values received.\")" (str "(ul :class \"text-sm text-stone-700 space-y-1\" " (join " " (map (fn (pair) (str "(li (strong \"" (first pair) "\") \": \" \"" (nth pair 1) "\")")) vals)) ")")))) (<> (if (empty? vals) (span (~tw :tokens "text-stone-400 text-sm") "No values received.") (ul (~tw :tokens "text-sm text-stone-700 space-y-1") (map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) vals))) (~docs/oob-code :target-id "ref-wire-sx-vals" :text sx-text))))) ;; --- sx-retry demo: flaky endpoint (fails 2/3 times) --- (defhandler ref-flaky :path "/sx/(geography.(hypermedia.(reference.(api.flaky))))" :method :get :returns "element" (&key) (let ((prev (helper "state-get" "ref-flaky-n" 0))) (let ((n (+ prev 1))) (helper "state-set!" "ref-flaky-n" n) (if (not (= (mod n 3) 0)) (do (set-response-status 503) "") (let ((sx-text (str "(span :class \"text-emerald-700 text-sm\" \"Success on attempt \" \"" n "\" \"!\")"))) (<> (span (~tw :tokens "text-emerald-700 text-sm") "Success on attempt " (str n) "!") (~docs/oob-code :target-id "ref-wire-sx-retry" :text sx-text))))))) ;; --- sx-trigger-event demo: response header triggers --- (defhandler ref-trigger-event :path "/sx/(geography.(hypermedia.(reference.(api.trigger-event))))" :method :get :returns "element" (&key) (let ((now (helper "now" "%H:%M:%S"))) (set-response-header "SX-Trigger" "showNotice") (<> (span (~tw :tokens "text-stone-800 text-sm") "Loaded at " (strong now) " — check the border!")))) ;; --- sx-retarget demo: response header retargets --- (defhandler ref-retarget :path "/sx/(geography.(hypermedia.(reference.(api.retarget))))" :method :get :returns "element" (&key) (let ((now (helper "now" "%H:%M:%S"))) (set-response-header "SX-Retarget" "#ref-hdr-retarget-alt") (<> (span (~tw :tokens "text-violet-700 text-sm") "Retargeted at " (strong now)))))