Idiomatic Clojure authoring for URPX entities. Output of every builder is
a coerced (typed) entity ready for urpx.price/resolve-prices,
urpx.emit/write-*, or any other consumer of urpx.schema-shaped data.
(require '[urpx.dsl :as dsl])
(dsl/dsl-scope (dsl/season ::summer :name "Summer" :month [5 6 7 8 9 10]) (dsl/season ::winter :name "Winter" :month [11 12 1 2 3 4]) (dsl/price-definition ::pd-summer :name "Commodity Summer" :applies-in-season ::summer :references-ledger ::ledger-commodity))
dsl-scope macro establishing a local-symbol-ref scopemake-builder generator: schema → constructor functionentity-type introspect a schema for its @type literalurpx.schema
(season, metric-input, price-definition,
rate-plan, urpx-document, …)Every builder:
:jsonld/type automatically from the schema (no boilerplate).:urpx/* keys (:urpx/seasonName) or auto-derived kebab-case short
forms (:season-name); both can be mixed in one call.:decode/urpx-jsonld
decoders: number → BigDecimal, ISO string → LocalDate /
LocalDateTime / LocalTime, --MM xsd:gMonth → int month-of-year,
ISO 8601 string → Duration / Period.nil-valued kwargs (so (builder :foo (when … x)) cleanly
omits the field). Explicit false is preserved.ex-info with the Malli explanation on failure.Inside a dsl-scope, builders additionally:
@id (e.g. (season ::summer …) registers ::summer in the
scope and sets :jsonld/id "summer").{:jsonld/id …} Ref maps. Vector-typed kwargs walk
element-wise.Resolution is eager (declare-before-reference): an unknown ref or a
duplicate declaration throws. Each dsl-scope has its own registry —
scopes don't leak.
Idiomatic Clojure authoring for URPX entities. Output of every builder is
a coerced (typed) entity ready for `urpx.price/resolve-prices`,
`urpx.emit/write-*`, or any other consumer of `urpx.schema`-shaped data.
## At a glance
(require '[urpx.dsl :as dsl])
(dsl/dsl-scope
(dsl/season ::summer :name "Summer" :month [5 6 7 8 9 10])
(dsl/season ::winter :name "Winter" :month [11 12 1 2 3 4])
(dsl/price-definition ::pd-summer
:name "Commodity Summer"
:applies-in-season ::summer
:references-ledger ::ledger-commodity))
## Public API
- `dsl-scope` macro establishing a local-symbol-ref scope
- `make-builder` generator: schema → constructor function
- `entity-type` introspect a schema for its @type literal
- 37 named builders one per entity-type schema in `urpx.schema`
(`season`, `metric-input`, `price-definition`,
`rate-plan`, `urpx-document`, …)
## Builder semantics
Every builder:
- Sets `:jsonld/type` automatically from the schema (no boilerplate).
- Accepts kwargs (or a Clojure 1.11+ trailing map) of either canonical
`:urpx/*` keys (`:urpx/seasonName`) or auto-derived kebab-case short
forms (`:season-name`); both can be mixed in one call.
- Auto-coerces raw inputs through the schema's `:decode/urpx-jsonld`
decoders: number → `BigDecimal`, ISO string → `LocalDate` /
`LocalDateTime` / `LocalTime`, `--MM` xsd:gMonth → int month-of-year,
ISO 8601 string → `Duration` / `Period`.
- Drops `nil`-valued kwargs (so `(builder :foo (when … x))` cleanly
omits the field). Explicit `false` is preserved.
- Validates the assembled entity against the schema and throws
`ex-info` with the Malli explanation on failure.
Inside a `dsl-scope`, builders additionally:
- Accept an optional leading qualified-keyword arg as the entity's
local `@id` (e.g. `(season ::summer …)` registers `::summer` in the
scope and sets `:jsonld/id "summer"`).
- Resolve qualified-keyword kwarg values against the scope's registry
to produce `{:jsonld/id …}` Ref maps. Vector-typed kwargs walk
element-wise.
Resolution is eager (declare-before-reference): an unknown ref or a
duplicate declaration throws. Each `dsl-scope` has its own registry —
scopes don't leak.(dsl-scope & body)Establish a local-symbol-ref scope. Inside the body, builders accept an optional leading qualified-keyword argument as the entity's local @id (registered in the scope), and qualified-keyword values in kwarg positions resolve to {:jsonld/id ...} maps via the registry.
Resolution is eager (declare-before-reference): a reference to an undeclared keyword throws ex-info. Multiple declarations of the same keyword also throw.
Implementation: the scope binds *local-refs* to a fresh volatile!
holding a persistent map. Builders mutate it via vswap! during the
scope's evaluation; nothing outside the body's dynamic extent ever
sees the volatile, and the scope returns a regular immutable result.
Establish a local-symbol-ref scope. Inside the body, builders accept an
optional leading qualified-keyword argument as the entity's local @id
(registered in the scope), and qualified-keyword values in kwarg
positions resolve to {:jsonld/id ...} maps via the registry.
Resolution is eager (declare-before-reference): a reference to an
undeclared keyword throws ex-info. Multiple declarations of the same
keyword also throw.
Implementation: the scope binds `*local-refs*` to a fresh `volatile!`
holding a persistent map. Builders mutate it via `vswap!` during the
scope's evaluation; nothing outside the body's dynamic extent ever
sees the volatile, and the scope returns a regular immutable result.(entity-type schema)Extract the @type literal (e.g. "urpx:Season") from a Malli entity
schema by introspecting its :jsonld/type entry — which must have the
form [:= "urpx:X"]. Schemas wrapped in [:schema {:registry ...} <inner>] (e.g. ConditionExpression) are unwrapped via m/deref first.
Returns nil if the schema doesn't carry a :jsonld/type entry shaped
that way.
Extract the @type literal (e.g. "urpx:Season") from a Malli entity
schema by introspecting its :jsonld/type entry — which must have the
form `[:= "urpx:X"]`. Schemas wrapped in `[:schema {:registry ...}
<inner>]` (e.g. ConditionExpression) are unwrapped via `m/deref` first.
Returns nil if the schema doesn't carry a :jsonld/type entry shaped
that way.(make-builder schema)Given a urpx.schema entity schema, return a constructor function. The constructor:
dsl-scope (URPX-8fo), accepts an optional leading
qualified-keyword as the entity's local @id (registered in the scope's
registry); qualified-keyword values in kwarg positions resolve to
Ref maps via the same registry.The schema must carry a :jsonld/type entry with shape [:= "urpx:X"]
so the @type can be inferred.
Given a urpx.schema entity schema, return a constructor function. The
constructor:
- Accepts kwargs (or a trailing map per Clojure 1.11+ unification) of
canonical :urpx/* keys; the entity's :jsonld/type is set automatically
from the schema.
- Inside a `dsl-scope` (URPX-8fo), accepts an optional leading
qualified-keyword as the entity's local @id (registered in the scope's
registry); qualified-keyword values in kwarg positions resolve to
Ref maps via the same registry.
- Drops kwargs whose value is nil so optional fields can be supplied
conditionally without producing present-but-nil entries.
- Runs urpx.coerce/coerce against the schema — already-typed values pass
through; raw values (numbers, strings, gMonth strings, …) are decoded
per the schema's :decode/urpx-jsonld decoders.
- Validates the assembled entity against the schema; throws ex-info
(with the Malli explanation attached) on validation failure.
The schema must carry a :jsonld/type entry with shape `[:= "urpx:X"]`
so the @type can be inferred.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |