;; ========================================================================== ;; boundary.sx — SX language boundary contract ;; ;; Declares the core I/O primitives that any SX host must provide. ;; This is the LANGUAGE contract — not deployment-specific. ;; ;; Pure primitives (Tier 1) are declared in primitives.sx. ;; Deployment-specific I/O (layout contexts) lives in boundary-app.sx. ;; Per-service page helpers live in {service}/sx/boundary.sx. ;; ;; Format: ;; (define-io-primitive "name" ;; :params (param1 param2 &key ...) ;; :returns "type" ;; :async true ;; :doc "description" ;; :context :request) ;; ;; ========================================================================== ;; -------------------------------------------------------------------------- ;; Tier 1: Pure primitives — declared in primitives.sx ;; -------------------------------------------------------------------------- (declare-tier :pure :source "primitives.sx") ;; -------------------------------------------------------------------------- ;; Tier 2: Core I/O primitives — async, side-effectful, need host context ;; -------------------------------------------------------------------------- ;; Cross-service communication (define-io-primitive "frag" :params (service frag-type &key) :returns "string" :async true :doc "Fetch cross-service HTML fragment." :context :request) (define-io-primitive "query" :params (service query-name &key) :returns "any" :async true :doc "Fetch data from another service via internal HTTP." :context :request) (define-io-primitive "action" :params (service action-name &key) :returns "any" :async true :doc "Call an action on another service via internal HTTP." :context :request) (define-io-primitive "service" :params (service-or-method &rest args &key) :returns "any" :async true :doc "Call a domain service method. Two-arg: (service svc method). One-arg: (service method) uses bound handler service." :context :request) ;; Request context (define-io-primitive "current-user" :params () :returns "dict?" :async true :doc "Current authenticated user dict, or nil." :context :request) (define-io-primitive "htmx-request?" :params () :returns "boolean" :async true :doc "True if current request has HX-Request header." :context :request) (define-io-primitive "request-arg" :params (name &rest default) :returns "any" :async true :doc "Read a query string argument from the current request." :context :request) (define-io-primitive "request-path" :params () :returns "string" :async true :doc "Current request path." :context :request) (define-io-primitive "request-view-args" :params (key) :returns "any" :async true :doc "Read a URL view argument from the current request." :context :request) (define-io-primitive "g" :params (key) :returns "any" :async true :doc "Read a value from the Quart request-local g object." :context :request) (define-io-primitive "csrf-token" :params () :returns "string" :async true :doc "Current CSRF token string." :context :request) (define-io-primitive "abort" :params (status &rest message) :returns "nil" :async true :doc "Raise HTTP error from SX." :context :request) ;; Routing (define-io-primitive "url-for" :params (endpoint &key) :returns "string" :async true :doc "Generate URL for a named endpoint." :context :request) (define-io-primitive "route-prefix" :params () :returns "string" :async true :doc "Service URL prefix for dev/prod routing." :context :request) ;; Navigation and relations (define-io-primitive "nav-tree" :params () :returns "list" :async true :doc "Navigation tree as list of node dicts." :context :request) (define-io-primitive "get-children" :params (&key parent-type parent-id) :returns "list" :async true :doc "Fetch child entities for a parent." :context :request) ;; Config and host context (sync — no await needed) (define-io-primitive "app-url" :params (service &rest path) :returns "string" :async false :doc "Full URL for a service: (app-url \"blog\" \"/my-post/\")." :context :config) (define-io-primitive "asset-url" :params (&rest path) :returns "string" :async false :doc "Versioned static asset URL." :context :config) (define-io-primitive "config" :params (key) :returns "any" :async false :doc "Read a value from app-config.yaml." :context :config) (define-io-primitive "jinja-global" :params (key &rest default) :returns "any" :async false :doc "Read a Jinja environment global." :context :request) (define-io-primitive "relations-from" :params (entity-type) :returns "list" :async false :doc "List of RelationDef dicts for an entity type." :context :config) ;; -------------------------------------------------------------------------- ;; Boundary types — what's allowed to cross the host-SX boundary ;; -------------------------------------------------------------------------- (define-boundary-types (list "number" "string" "boolean" "nil" "keyword" "list" "dict" "sx-source" "style-value"))