hoplite.core
hoplite.core contains the public HAL constructors used to describe an
application and its logical responses. Constructors return ordinary immutable
values; they do not start Nginx or perform transport I/O.
(ns example.app (:require [hoplite.core :as h]))(app definition)Defines one immutable resource application. A map is tagged with
:hoplite/type :application; any other value becomes the catch-all handler.
(defn hello [_request] {:status 200 :headers {"content-type" "text/plain; charset=utf-8"} :body "hello\n"})
(def app (h/app {:name "example" :handler hello}))
;; => {:name "example";; :handler #<function hello>;; :hoplite/type :application}The definition map is otherwise preserved, so routes, channels, peers, and
package-owned fields remain inspectable application data. Passing hello
directly produces {:hoplite/type :application :handler hello}.
response
Section titled “response”(response definition)(response status body)Constructs a logical response value. Response maps may also be returned directly.
(h/response 201 {:id 42});; => {:hoplite/type :response :status 201 :body {:id 42}}
(h/response {:status 204 :headers {"x-example" "created"}});; => {:status 204 :headers {"x-example" "created"};; :hoplite/type :response}The two-argument form sets only :status and :body. Use the one-argument form,
or return a response map directly, when headers or other response fields are
needed.
stream
Section titled “stream”(stream source)Constructs a backpressured HTTP body from an IStream or a finite iterable.
An existing IStream is retained directly. A finite iterable is converted to an
iterator-backed generated stream, and that iterator is closed in a finally
boundary when production completes or fails.
(h/stream ["first\n" "second\n"]);; => {:hoplite/type :stream;; :source #<stream>}An unsupported or non-finite source fails synchronously with structured
:stream/invalid-source data. Streaming response production then follows the
same request cancellation and slow-client backpressure lifecycle as other
native response bodies.
channel
Section titled “channel”(channel definition)hoplite.core/channel remains a compatibility constructor that tags the map
with :hoplite/type :channel. New applications should activate the
:hoplite/nchan package export and use
hoplite.nchan/channel directly.
(h/channel {:name "signals" :path "/signals/:channel" :profile :ephemeral :authorize #'authorize-subscriber :admit #'admit-publisher :transports [:websocket :sse] :message-buffer 8 :message-timeout-seconds 30 :max-channel-id-bytes 128 :max-subscribers 4})The consuming application validator applies a closed schema. The path must be a
safe absolute path ending in /:channel; the profile is only :ephemeral; and
transports are a non-empty subset of :websocket and :sse. Raw Nginx
directives, Redis coordinates, arbitrary upstreams, and unknown fields are
rejected.
Nchan supplies bounded fan-out and signalling, not durable state or application identity. Both hook handlers remain application-owned authorization boundaries. See Realtime channels and WebRTC for limits and a complete application declaration.
Experimental(peer definition)Declares one WebRTC peer handler bound to a channel in the same application and
tags the map with :hoplite/type :peer.
(h/peer {:name "sync" :channel "signals" :handler #'handle-peer :label "sync" :max-message-bytes 65536 :idle-timeout-seconds 120})Peer names must be unique, channel references must resolve, message limits are
bounded from 1 byte through 1 MiB, and idle timeouts are bounded from 5 seconds
through 1 hour. The declaration selects application policy; actual session
negotiation and stream Duplex composition are provided by
hoplite.rtc.
middleware
Section titled “middleware”(middleware definition)Tags a lifecycle middleware definition with :hoplite/type :middleware. The
documented phases are request, response, error, and close, but complete host
integration remains pre-release.
service
Section titled “service”(service definition)Tags a definition with :hoplite/type :service. Service lifecycle integration
is not yet a supported production boundary.
module, adapter, and store
Section titled “module, adapter, and store”(module definition)(adapter definition)(store definition)Define composable behaviour entirely in HAL. A module owns behaviour and its
contracts; an adapter implements a contract; a store is an adapter expressed
through logical atomic operations rather than database tables. SQLite, PGlite
and other persistence engines are addon implementations of that store boundary.
These constructors currently validate no schema; each adds the corresponding
:hoplite/type tag to the supplied map.
package-ref
Section titled “package-ref”(package-ref coordinate version export alias config)Constructs the activation selected by project.edn. For example:
(package-ref "gh:example:service-package" "0.1.0" :example/service :service {});; => {:hoplite/type :package-ref;; :module/id "gh:example:service-package";; :module/version "0.1.0";; :module/export :example/service;; :module/as :service;; :module/config {}}The version is exact, the export is package-owned, and the alias is unique in the composed application.
Failure behavior
Section titled “Failure behavior”The small map constructors use ordinary map operations, so callers should pass
maps where documented. stream performs its own source validation. Runtime
validation of applications, routes, channels, peers, packages, and other
experimental definitions happens at the build or host boundary that consumes
them; invalid data fails before a serving runtime is published.
Source: core/lib/src/hoplite/core.hal