;; ========================================================================== ;; boundary.sx — SX boundary contract ;; ;; Declares everything allowed to cross the host-SX boundary: ;; I/O primitives (Tier 2) and page helpers (Tier 3). ;; ;; Pure primitives (Tier 1) are declared in primitives.sx. ;; This file declares what primitives.sx does NOT cover: ;; async/side-effectful host functions that need request context. ;; ;; Format: ;; (define-io-primitive "name" ;; :params (param1 param2 &key ...) ;; :returns "type" ;; :async true ;; :doc "description" ;; :context :request) ;; ;; (define-page-helper "name" ;; :params (param1 param2) ;; :returns "type" ;; :service "service-name") ;; ;; Bootstrappers read this file and emit frozen sets + validation ;; functions for the target language. ;; ========================================================================== ;; -------------------------------------------------------------------------- ;; Tier 1: Pure primitives — declared in primitives.sx ;; -------------------------------------------------------------------------- (declare-tier :pure :source "primitives.sx") ;; -------------------------------------------------------------------------- ;; Tier 2: I/O primitives — async, side-effectful, need host context ;; -------------------------------------------------------------------------- (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 "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 "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) (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 "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) (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) (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) (define-io-primitive "root-header-ctx" :params () :returns "dict" :async true :doc "Dict with root header values (cart-mini, auth-menu, nav-tree, etc.)." :context :request) (define-io-primitive "post-header-ctx" :params () :returns "dict" :async true :doc "Dict with post-level header values." :context :request) (define-io-primitive "select-colours" :params () :returns "string" :async true :doc "Shared select/hover CSS class string." :context :request) (define-io-primitive "account-nav-ctx" :params () :returns "any" :async true :doc "Account nav fragments, or nil." :context :request) (define-io-primitive "app-rights" :params () :returns "dict" :async true :doc "User rights dict from g.rights." :context :request) (define-io-primitive "federation-actor-ctx" :params () :returns "dict?" :async true :doc "Serialized ActivityPub actor dict or nil." :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 "cart-page-ctx" :params () :returns "dict" :async true :doc "Dict with cart page header values." :context :request) (define-io-primitive "events-calendar-ctx" :params () :returns "dict" :async true :doc "Dict with events calendar header values." :context :request) (define-io-primitive "events-day-ctx" :params () :returns "dict" :async true :doc "Dict with events day header values." :context :request) (define-io-primitive "events-entry-ctx" :params () :returns "dict" :async true :doc "Dict with events entry header values." :context :request) (define-io-primitive "events-slot-ctx" :params () :returns "dict" :async true :doc "Dict with events slot header values." :context :request) (define-io-primitive "events-ticket-type-ctx" :params () :returns "dict" :async true :doc "Dict with ticket type header values." :context :request) (define-io-primitive "market-header-ctx" :params () :returns "dict" :async true :doc "Dict with market header data." :context :request) ;; Moved from primitives.py — these need host context (infra/config/Quart) (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) ;; -------------------------------------------------------------------------- ;; Tier 3: Page helpers — service-scoped, registered per app ;; -------------------------------------------------------------------------- ;; SX docs service (define-page-helper "highlight" :params (code lang) :returns "sx-source" :service "sx") (define-page-helper "primitives-data" :params () :returns "dict" :service "sx") (define-page-helper "special-forms-data" :params () :returns "dict" :service "sx") (define-page-helper "reference-data" :params (slug) :returns "dict" :service "sx") (define-page-helper "attr-detail-data" :params (slug) :returns "dict" :service "sx") (define-page-helper "header-detail-data" :params (slug) :returns "dict" :service "sx") (define-page-helper "event-detail-data" :params (slug) :returns "dict" :service "sx") (define-page-helper "read-spec-file" :params (filename) :returns "string" :service "sx") (define-page-helper "bootstrapper-data" :params (target) :returns "dict" :service "sx") ;; Blog service (define-page-helper "editor-data" :params (&key) :returns "dict" :service "blog") (define-page-helper "editor-page-data" :params (&key) :returns "dict" :service "blog") (define-page-helper "post-admin-data" :params (&key slug) :returns "dict" :service "blog") (define-page-helper "post-data-data" :params (&key slug) :returns "dict" :service "blog") (define-page-helper "post-preview-data" :params (&key slug) :returns "dict" :service "blog") (define-page-helper "post-entries-data" :params (&key slug) :returns "dict" :service "blog") (define-page-helper "post-settings-data" :params (&key slug) :returns "dict" :service "blog") (define-page-helper "post-edit-data" :params (&key slug) :returns "dict" :service "blog") ;; Events service (define-page-helper "calendar-admin-data" :params (&key calendar-slug) :returns "dict" :service "events") (define-page-helper "day-admin-data" :params (&key calendar-slug year month day) :returns "dict" :service "events") (define-page-helper "slots-data" :params (&key calendar-slug) :returns "dict" :service "events") (define-page-helper "slot-data" :params (&key calendar-slug slot-id) :returns "dict" :service "events") (define-page-helper "entry-data" :params (&key calendar-slug entry-id) :returns "dict" :service "events") (define-page-helper "entry-admin-data" :params (&key calendar-slug entry-id year month day) :returns "dict" :service "events") (define-page-helper "ticket-types-data" :params (&key calendar-slug entry-id year month day) :returns "dict" :service "events") (define-page-helper "ticket-type-data" :params (&key calendar-slug entry-id ticket-type-id year month day) :returns "dict" :service "events") (define-page-helper "tickets-data" :params (&key) :returns "dict" :service "events") (define-page-helper "ticket-detail-data" :params (&key code) :returns "dict" :service "events") (define-page-helper "ticket-admin-data" :params (&key) :returns "dict" :service "events") (define-page-helper "markets-data" :params (&key) :returns "dict" :service "events") ;; Market service (define-page-helper "all-markets-data" :params (&key) :returns "dict" :service "market") (define-page-helper "page-markets-data" :params (&key slug) :returns "dict" :service "market") (define-page-helper "page-admin-data" :params (&key slug) :returns "dict" :service "market") (define-page-helper "market-home-data" :params (&key page-slug market-slug) :returns "dict" :service "market") ;; -------------------------------------------------------------------------- ;; 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"))