Skip to content

Begin typing to search this documentation.

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]))
Public
(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}.

Public
(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.

Public
(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.

Experimental
(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.

Experimental
(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.

Experimental
(service definition)

Tags a definition with :hoplite/type :service. Service lifecycle integration is not yet a supported production boundary.

Experimental
(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.

Experimental
(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.

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