Module registry and composition helpers for the Wagoe shell.
This namespace provides utilities to:
For now, only the :user module is supported.
Module registry and composition helpers for the Wagoe shell. This namespace provides utilities to: - Determine which modules are enabled based on configuration. - Compose route definitions from multiple modules. - Dispatch CLI commands to module-specific runners. For now, only the `:user` module is supported.
Modules every application gets whether or not its config mentions them.
Both fall back to a working default — the logging email sender, an English-only catalogue — and the HTTP handler takes a ref to i18n's middleware unconditionally, so leaving them out is not an option an application has. They are modules rather than core components because the wiring lives in their own library, and platform depends on neither.
Modules every application gets whether or not its config mentions them. Both fall back to a working default — the logging email sender, an English-only catalogue — and the HTTP handler takes a ref to i18n's middleware unconditionally, so leaving them out is not an option an application has. They are modules rather than core components because the wiring lives in their own library, and platform depends on neither.
(compose-module-routes route-maps)Compose route definitions from multiple modules (new pattern).
Arguments: route-maps: collection of route maps from modules. Each route map has keys: :api, :web, :static.
Returns: Combined route map with merged routes: {:api [all-api-routes] :web [all-web-routes] :static [all-static-routes]}
Example: (compose-module-routes [{:api [['/users' {...}]] :web [] :static []} {:api [['/billing' {...}]] :web [] :static []}]) ;=> {:api [['/users' {...}] ['/billing' {...}]] ; :web [] ; :static []}
Compose route definitions from multiple modules (new pattern).
Arguments:
route-maps: collection of route maps from modules.
Each route map has keys: :api, :web, :static.
Returns:
Combined route map with merged routes:
{:api [all-api-routes]
:web [all-web-routes]
:static [all-static-routes]}
Example:
(compose-module-routes [{:api [['/users' {...}]] :web [] :static []}
{:api [['/billing' {...}]] :web [] :static []}])
;=> {:api [['/users' {...}] ['/billing' {...}]]
; :web []
; :static []}(discover-module-config active known-keys base-ns wiring-loadable?)(discover-module-config active known-keys base-ns wiring-loadable? resolve-var)Integrant entries for scaffolded modules named under :active.
wiring-loadable? is injected so this stays testable without a module on the
classpath; -main passes a function that requires the namespace.
Throws when a module key names a wiring namespace that will not load. The
silent skip is the whole defect: a typo in a key — :wagoe/tsaks, or the
:active/:inactive mix-up — produced no signal at all.
Integrant entries for scaffolded modules named under `:active`. `wiring-loadable?` is injected so this stays testable without a module on the classpath; `-main` passes a function that requires the namespace. Throws when a module key names a wiring namespace that will not load. The silent skip is the whole defect: a typo in a key — `:wagoe/tsaks`, or the `:active`/`:inactive` mix-up — produced no signal at all.
(discovered-route-refs active known-keys)(discovered-route-refs active known-keys built)Integrant refs to the routes of every discovered module that has any.
The HTTP handler cannot name a generated module, so it takes the routes as a
collection — this is what the application puts in :module-routes.
built is the config those modules produced, and the refs are filtered
against it. Referencing :wagoe/<name>-routes by convention alone was safe
only while every discovered module went through the scaffolder's four-key
shape, which always builds one. A module with a graph of its own need not
serve HTTP at all — a background-jobs library is exactly the kind of library
this is meant to welcome — and a ref to a component it never built is a
dangling ref, which Integrant refuses (BOU-330).
Integrant refs to the routes of every discovered module that has any. The HTTP handler cannot name a generated module, so it takes the routes as a collection — this is what the application puts in `:module-routes`. `built` is the config those modules produced, and the refs are filtered against it. Referencing `:wagoe/<name>-routes` by convention alone was safe only while every discovered module went through the scaffolder's four-key shape, which always builds one. A module with a graph of its own need not serve HTTP at all — a background-jobs library is exactly the kind of library this is meant to welcome — and a ref to a component it never built is a dangling ref, which Integrant refuses (BOU-330).
(dispatch-cli enabled-modules module->runner args)Dispatch CLI based on enabled modules.
Arguments: enabled-modules: vector of module keywords from config module->runner: map of module keyword to a function (fn [args] -> exit-code) args: raw CLI arguments vector
CLI convention: wagoe <module> <command> [options]
Dispatch CLI based on enabled modules. Arguments: enabled-modules: vector of module keywords from config module->runner: map of module keyword to a function (fn [args] -> exit-code) args: raw CLI arguments vector CLI convention: wagoe <module> <command> [options] - <module> is a keyword name like user or billing. - If <module> is omitted, and only one enabled module exists, that module is used by default. - If <module> is omitted and multiple modules are enabled, an error is reported and exit code 1 is returned. - If the selected module is not enabled or has no runner, exit code 1 is returned.
(enabled-modules config)Return the vector of enabled modules based on app config.
Looks at [:active :wagoe/settings :modules] in the configuration map. If no modules are configured, defaults to [:user] for backwards compatibility.
Return the vector of enabled modules based on app config. Looks at [:active :wagoe/settings :modules] in the configuration map. If no modules are configured, defaults to [:user] for backwards compatibility.
(framework-module-config active
{:keys [extra-modules] :as ctx}
load-wiring!
resolve-var)Integrant entries for the framework modules active switches on.
Returns {:components {…} :http {…} :routes [..]}. :components merges into
the system config and :http into :wagoe/http-handler — that is how tenant
contributes :extra-middleware. :routes is a vector of refs to modules'
route components, which reach the handler as one collection rather than as a
named slot per module (BOU-330).
ctx is what a module may need from the application and cannot know:
:config (the whole loaded map), :validation-config, and :enabled — the
set of sibling modules that are on, so user-service can take a cache ref only
when there is a cache.
load-wiring! and resolve-var are injected so this is testable without a
module on the classpath; system-config passes the real ones.
Integrant entries for the framework modules `active` switches on.
Returns `{:components {…} :http {…} :routes [..]}`. `:components` merges into
the system config and `:http` into `:wagoe/http-handler` — that is how tenant
contributes `:extra-middleware`. `:routes` is a vector of refs to modules'
route components, which reach the handler as one collection rather than as a
named slot per module (BOU-330).
`ctx` is what a module may need from the application and cannot know:
`:config` (the whole loaded map), `:validation-config`, and `:enabled` — the
set of sibling modules that are on, so user-service can take a cache ref only
when there is a cache.
`load-wiring!` and `resolve-var` are injected so this is testable without a
module on the classpath; `system-config` passes the real ones.:active key -> the library that owns it.
The wiring namespace is derived (wagoe.<lib>.shell.module-wiring) rather
than listed, so a new module is one entry. Four keys predate the convention
and cannot be derived from their own name; they are spelled out.
These are keyword-to-string pairs, not namespace loads: platform still
depends on none of these libraries, and bb check:isolation still passes.
`:active` key -> the library that owns it. The wiring namespace is derived (`wagoe.<lib>.shell.module-wiring`) rather than listed, so a new module is one entry. Four keys predate the convention and cannot be derived from their own name; they are spelled out. These are keyword-to-string pairs, not namespace loads: platform still depends on none of these libraries, and `bb check:isolation` still passes.
Modules whose library may legitimately be absent at runtime.
:wagoe/dev-error-enricher comes from wagoe-devtools, which lives in the
:repl alias — so clojure -M:run against the dev config has the key and
not the jar. A dev-only nicety must not stop the app from booting; every
other missing library is a real error and throws.
Modules whose library may legitimately be absent at runtime. `:wagoe/dev-error-enricher` comes from wagoe-devtools, which lives in the `:repl` alias — so `clojure -M:run` against the dev config has the key and not the jar. A dev-only nicety must not stop the app from booting; every other missing library is a real error and throws.
(require-wiring! wiring-ns)Load wiring-ns. Returns true when it loaded, false when it does not exist,
and rethrows anything else.
The distinction matters: a wiring namespace that exists but throws on load — freshly generated code with a compile error, or a missing transitive dep — is not a missing module, and reporting it as one buries the real error under a suggestion to check the spelling.
Load `wiring-ns`. Returns true when it loaded, false when it does not exist, and rethrows anything else. The distinction matters: a wiring namespace that exists but throws on load — freshly generated code with a compile error, or a missing transitive dep — is not a missing module, and reporting it as one buries the real error under a suggestion to check the spelling.
(scaffolded-module-keys active known-keys)The :active keys that declare a scaffolded module and are not already
wired by the caller.
A module is a :wagoe/<name> whose value carries :enabled?. Most of
:active is configuration — :wagoe/h2 names a database, :wagoe/http a
port, :wagoe/logging an adapter — and treating every key as a module made
the boot demand a wagoe.h2.shell.module-wiring. :enabled? is what
bb scaffold integrate prints, so declaring a module and being discovered as
one are the same act.
A different namespace (:wagoe.external/smtp) is a provider's settings.
The `:active` keys that declare a scaffolded module and are not already wired by the caller. A module is a `:wagoe/<name>` whose value carries `:enabled?`. Most of `:active` is configuration — `:wagoe/h2` names a database, `:wagoe/http` a port, `:wagoe/logging` an adapter — and treating every key as a module made the boot demand a `wagoe.h2.shell.module-wiring`. `:enabled?` is what `bb scaffold integrate` prints, so declaring a module and being discovered as one are the same act. A different namespace (`:wagoe.external/smtp`) is a provider's settings.
(wiring-candidates base-ns module)Where a module's wiring namespace may live, most preferred first.
An application's own code belongs under its own namespace, so
shop.product.shell.module-wiring is where bb scaffold writes it and the
first place to look (BOU-360).
wagoe.<module>.shell.module-wiring is the second: every project generated
before that change has its modules there, and the framework's own
application is one of them — its project namespace really is wagoe, so
this is not only a compatibility path. When base-ns is already "wagoe" the
two collapse to one candidate.
Where a module's wiring namespace may live, most preferred first. An application's own code belongs under its own namespace, so `shop.product.shell.module-wiring` is where `bb scaffold` writes it and the first place to look (BOU-360). `wagoe.<module>.shell.module-wiring` is the second: every project generated before that change has its modules there, and the framework's own application is one of them — its project namespace really is `wagoe`, so this is not only a compatibility path. When base-ns is already "wagoe" the two collapse to one candidate.
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 |