Announcing: https://github.com/potetm/lightweaver: Topological namespace sorting for making Clojure components with a simple reduce.
• a.k.a. Yet Another Component Lib
• a.k.a. You don't need this library but you do need to read the https://github.com/potetm/lightweaver?tab=readme-ov-file#rationale to discover how to do components the Right Way
• a.k.a. The first library to come out as a direct result of Clojure Conj 2025
• Major shoutout to @foo, who rightly chooses to not use this library, but who tipped me off the the pattern of using a simple reduce to initialize Clojure components.
• v0.0.1: Alpha release, but I'm eager to hear some feedback so here you go.
> There is one shortcoming of this approach: It requires manual ordering of your components. ... ... Lightweaver will find and sort your component start and stop functions using your namespace dependencies to properly order startup/shutdown. i am confused
> • a.k.a. Yet Another Component Lib Lisp Curse is the most apparent in Clojure when it comes to Component alternatives ;-)
so you are reading the Clojure ns-decl :require graph and using that to solve for the order of initialization?
@dustingetz correct
it's very interesting, i need to think about it
caveat emptor: https://github.com/potetm/lightweaver?tab=readme-ov-file#gotchas
or as I like to think of it, the Lisp Blessing!
so you're searching for start functions across all loaded namespaces
correct, (or a subset of namespaces if you supply it) (or any symbol of your choosing, not just start)
for a second, i was wondering when you'd show how to use this with Component, lol, but then it clicked. This is a really interesting approach
is this similar to mount wrt. starting/stopping the components in the order they were required?
yes exactly. except it doesn't have a special macro, and it doesn't manage state for you. it just examines the dependency graph and forms a logical ordering for start/stop functions.
the order is implied by graph formed by the ns-decl :require directives
the limit of the approach therefore would seem to be the point at which the ns-decl :require graph diverges from the actual system component dependency topology, particularly because clojure being dynamic has many shenanigans. Inevitable in the large, but for a small team I dont see why it wouldn't work
yeah exactly. although the upshot of this approach is it pushes you to be disciplined in how you define and declare your components, with the hope being that you don't pull any weird shenanigans in the first place.
a faint hope, but a hope nonetheless
requiring-resolve, for example. I use it all the time
yeah so, using that in the right spot is totally fine. requiring-resolve -> lw/start works great. just gotta do it before you examine the dep graph.
i do believe you used the word "just", sir
lol
Announcing Oreo - a layer on top of Component and Aero which allows you to define your systems declaratively and integrated with your application's configuration. It solves a bunch ofproblems I kept running into when working with Component in the last ten years: • it's hard to see the "shape" of the system • there's a lot of boilerplate that goes into injecting configuration • building application systems so that some components conditionally added or removed - e.g. deploying HTTP-only variant https://github.com/lukaszkorecki/oreo/ While I use it in production. it's not 1.0.0 quality so any feedback is welcomed.
there is no. way.
lol
lol
this has gone Too Far!
Aentegrant
(comp aero integrant) - that’s the name
Comp AI That would attract a lot of new developers
I had to check the date lol.
I did a hand-rolled starter-stopper thingy I dubbed... systom https://gist.github.com/adityaathalye/960845ad75d1c93ac60542a4031cfe50
> "Why do we need a whole library to start/stop our Clojure web app "system" (libraries like integrant / component / mount)?"
(defonce system ; a system in an atom = systom (I'll show myself out)
(atom {:profile {:requires-component :profile
:starter [identity]
:state nil}
:config {:requires-component :profile
:starter [cc/get-config]
:state nil}
:db {:requires-component :config
:starter [cc/db-connection-config
identity] ; cats.db.core/connect-db
:stopper identity ; cats.db.core/disconnect-db
:state nil}
:server {:requires-component :config
:starter [cc/server-config
cats.server/start-server]
:stopper cats.server/stop-server
:state nil}
:futures {:stopper shutdown-agents}}))
(def start-sequence
[:profile :config :db :server :futures])
(def stop-sequence
(reverse start-sequence))
which caused me to do a talk, because that idea was just one of the seven stages of grief, uh, library selection
Grokking Libraries in Clojure-land (feat. component and mount)
https://github.com/adityaathalye/slideware/blob/master/Grokking%20Libraries%20in%20Clojureland.pdf
Usually it begins with denial / atoms (same thing)...> one of the seven stages of grief, uh, library selection haha, this hit too close
After what just happened in the channel, I'm honestly tempted to announce a new component library that uses AI to find your dependencies.
Purely as a joke.
Do it.