Fork me on GitHub

So… you’d either want a way to specify additional items for the compilation classpath, or a way to exclude JAR files (currently the regex-based exclude operates only at the file level, not on the JAR or its contents)…


Open an issue on the depstar GH and I’ll have a think about it…

🙌 3

@seancorfield will do. Thanks for the great tool and your answer.


I suspect a reasonable way to approach it is to provide an option to specify :compile-aliases so you can tell depstar to calculate a different basis for AOT compilation than for the JAR building part. Then you could have a :storm alias that adds that JAR via :extra-deps (and you’d have to use it for developing with). But “additive” is better.


Is there a way to share what goes in :deps with :storm and :compile-alias in your example? Say I have 20 libs in :deps that are used in :test and others, except one that I want to be excluded. The additive approach would need to have :deps referring to the union of what is needed in compilation and uberjar. Otherwise, I'd have to duplicate the dependencies, split between two alias that are used by uberjar.


My suggestion was: add a :storm alias that has just that storm-client dependency — and remove it from your “normal” list of dependencies. Then you use that alias (along with whatever you normally use) for dev/test — and if I add a :compile-aliases option you would also pass it to that, since it’s needed for the compile part but not the main JAR-build part.


At work, we have a somewhat similar situation where we have a process that needs the standard root-level :deps alias (as in tools.deps.alpha) for a couple of actions but we don’t want it in the JAR version of that process, so we just specify -M:deps:other:aliases when we run those particular actions and -M:other:aliases when we run other stuff or build the JAR. That code doesn’t need it statically for compilation, only dynamically to run certain actions. Hence, I haven’t needed the :compile-aliases option at work yet.


And to be clear :compile-aliases would be a new exec arg that you pass to depstar — a variant of the existing :aliases exec arg.


@seancorfield yeah that would work great


@U01RKE3LQ73 A first cut of the implementation can be tested via

seancorfield/depstar {:git/url "" :sha "39d234b9bce94ff8f51e0660f9db8bf475618e23"}
Needs tests and documentation but I figured you might be able to take it for a spin and let me know it works for you? (edited to update the SHA)


@seancorfield thank you so much. I’ll report back tomorrow morning


@U01RKE3LQ73 FYI -- once I added tests, I found a bug, so I updated the SHA above to reflect the correction.

🙌 3

works perfectly!


thank you so much


I haven't figured out how to make cursive resolve linter dependencies from aliases. But that's ok for storm since it can't resolve a lot of things from storm.


I released it as com.github.seancorfield/depstar {:mvn/version "2.0.211"}.

🚀 3

Is there a way to share what goes in :deps with :storm and :compile-alias in your example? Say I have 20 libs in :deps that are used in :test and others, except one that I want to be excluded. The additive approach would need to have :deps referring to the union of what is needed in compilation and uberjar. Otherwise, I'd have to duplicate the dependencies, split between two alias that are used by uberjar.


Does anyone know about a generic OAuth client, which supports the PKCE flow (as defined in I'm not even sure what should I use as a generic OAuth client...


I forgot to search clojars. There are a few libs there which have oauth in their name. I've also looked into specifically Xero API related libs and I found that the project for example is using the fork of Then there is from the prolific r0man or from the very official-sounding oauth clojars org. So my question more precisely is: which one of these libraries have you used and what was your experience like?


@onetom Sometimes I feel like the only clojure dev that uses

👍 3

thx for the link. i will probably use it to see how they named certain things, but i definitely won't unleash such a monstrous class hierarchy on my colleagues. imean, we are using clojure to avoid things like: OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter() (i've found this on


we have a ~200 LoC implementation, using http-kit, and a hint of buddy-core for the sake of convenience. it's not super generic and some of the names are a bit quirky, but it's rather straightforward...


I have not even considered that Spring Security could be used effectively from Clojure :thinking_face:


@UGTAV6LR2 Yeah, the one thing I use it for consistently is DelegatingPasswordEncoder

👍 3

is there a compelling reason to use Sping Sec? leaving aside its provenance, depending on a monolithic (?) solution doesn't seem very aligned with clojure ideals.


@U3JH98J4R im curious too! have u been already familiar with spring sec before u learnt clojure? @U45T93RA6 let's not forget that one of clojure's core ideas is to allow leveraging existing jvm solutions.


I'm not going to pretend to have a real scientific justification but in general for stuff like passwords and hashing i'd rather have stuff that is more well audited. Its a comfort blanket sort of thing.


I tend to program in clojure as if everyone involved in the language other than me is going to die suddenly one day choking on the dust that was once a river


JDBC stuff is stable, http stack is stable, libraries that work with just data I can alter if needed


"Security" just feels like something that would require frequent/crucial updates from domain experts. I trust the spring community for that more


Which is hypocritical, since I do use buddy for stuff


IDK, a crypto fn is essentially a mathematical function and I don't expect math to change much over time :) FWIW I'm not java-allergic (in fact the opposite) but if I can pick a lib instead of a framework, that seems a win to me auditing is also a delicate topic. A framework (even more so one written in java) seems hard to audit; often surprisingly few people know the guts of the stuff


it's not all kittens and unicorns in clojure land of course, but a smaller lib in my language of choice seems vastly easier to assess (especially for code coverage)


> a crypto fn is essentially a mathematical function Yeah, but the time taken to compute that function is an important consideration. I remember reading this a while back and it i think influences my opinion


There is this offhand comment in there "a scheme isn't secure until it has been extensively attacked."

🙂 3

and at this point i'm arguing with vibes and impressions, but it does make sense to me


at least in the manner I use spring security it is a library - it has compile time dependencies on spring but I don't think much at runtime, and I just call the java classes directly without any of that factory/bean nonsense

👍 3

(def ^PasswordEncoder password-encoder

(defn create!
  "Creates and returns a user record."
  [db email password]
  (sql/insert! db "\"user\"" {:email (string/lower-case email)
                              :password_hash (.encode password-encoder password)}))

(defn confirm-password
  "Takes a user and a password to check to see if it is the password for the user."
  [user password]
  (let [password-hash (:user/password_hash user)]
    (.matches password-encoder password password-hash)))


(side project, not work project so I can share code)


I respect all of that :) probably the world would be a safer place if there more lang-independent test suites around for crypto, csrf, etc. Like but for this domain Else our security boils down to trust. There isn't a categorical difference between trusting Spring or trusting a high-quality clj lib


Yeah, which - there is a categorical difference between stuff like buddy and


no offense to jcf or his code. I can't think of any obvious things he would get wrong or can even justify oauth being an issue


but it is marked as "This project is under active development, and has yet to reach 1.0. As such the API may change." in the readme, has 4 releases, hasn't been updated in 5 years, and has 17000 downloads on clojars


thanks for the extensive discussion!


Is there a way to profile namespace loading in Clojure and figure out which namespaces are taking the longest to load? I have a test suite that takes a minute or two just to load all the requisite namespaces before the assertions start happening, and am curious where that time is going and what code / dependencies I should try to get rid of.


the ones with the macros

thinking-face 3

what version of clojure?


somewhere around 1.10 there was a change to how user.clj is loaded, where loading code from user.clj could take a long time


(the change fixed it)


basically if you had a user.clj, and it loaded any core.async code it could take minutes


1.10.1 was the fix


this quick and dirty might be good enough

(cmd)user=> (alter-var-root #'require #(fn [& args] (println "require" args) (time (apply % args))))
#object[user$eval3$fn__4$fn__140 0x320494b6 "user$eval3$fn__4$fn__140@320494b6"]
(cmd)user=> (require 'clojure.set)
require (clojure.set)
"Elapsed time: 4.618158 msecs"
(ins)user=> (require 'clojure.string)
require (clojure.string)
"Elapsed time: 0.074134 msecs"


isn't there a dynamic var that does essentially that?


IIRC there's a dynamic var to make it verbose, I didn't recall it printing timings and I am failing to recall the name



Alex Miller (Clojure team)20:03:49

^^ or you can put :verbose flag in the first require (which sets that)

👍 3

oh I didn't know that one, thanks

Alex Miller (Clojure team)20:03:55

then you can usually just eyeball it


oh - it does print the timing, nice


what prints the timing?


require prints the timing if you set *loading-verbosely*

(ins)user=> (require 'clojure.walk :verbose)
require (clojure.walk :verbose)
"Elapsed time: 0.068989 msecs"


no, that's just the side effect of your alter var root

😹 6

oooh awesome

Alex Miller (Clojure team)20:03:31

but the answer is: clojure.core.async

😂 9
💯 3
ghadi20:03:42 😉


yet another alternative: use


topo-sort the namespaces then load them one at a time with a timer

😂 3

tbc — not saying issue individual require commands. Do it in a doseq.


But you can just time each require in the standard way once they’re topo-sorted.


Hi all, I am a bit stuck on this. How do I tell the compiler that I want the first arity of the following Paths/get? I tried: (Paths/get #^"[S" (into-array [(:path image)])) I might have syntax error - I googled a bunch of stuff...


Sean saved my chickens, thank you! For posterity the correct call is:

(Paths/get (:path image) ^"[Ljava.lang.String;" (into-array String []))


@richiardiandrea Only the ... part maps to an array, so you want a String followed by an array of String.


oh man, that's silly 😄

Alex Miller (Clojure team)21:03:34

#^ is old school now, just ^ is preferred

👍 3

@richiardiandrea you do not need the type hint

user=> (set! *warn-on-reflection* true)
user=> (Paths/get "/usr" (into-array ["local"]))
#object[sun.nio.fs.UnixPath 0x1a411233 "/usr/local"]


I am basically parsing only one string though, sorry it was not clear maybe from the example


👌:skin-tone-3: that makes sense


Still haven't solved though, cause this fails

(Paths/get "/home" ^"[S" (into-array ^String []))


ah, ok found out - no type hint in into-array


(Paths/get (:path image) ^"[S" (into-array String [])) works


[S is not a valid type hint


should be [Ljava.lang.String;


also into-array takes a class directly -- not a type hinted arg:

(into-array String [.....])
(into-array ^String [.....])


user=> (-> (make-array String 0) class .getName)


isn't [S an array of shorts?


user=> (type (make-array Short/TYPE 0))


only the primitives have single letter abbrevs


Completely misread that S here lol "Oh it's an S - same as the first letter of String" 😅


(because the signatures of Paths/get have distinct # of args)


@richiardiandrea if you're interested in a library around java.nio.file which makes this stuff easier from clojure, check out


yeah just discovered that thank you


the array stuff is what bugged me most ;)


it took me 30 mins + asking here -> I have just replaced everything we mentioned above with babashka.fs functions now 🤷


here is a more recent URL for this lib: which further points to:

❤️ 1