xadecimal / expose-api

A Clojure library to automatically generate public API namespaces by wrapping and exposing functions and macros from implementation namespaces.
MIT License
13 stars 0 forks source link

Support partial code generation (and maybe copy function) #2

Open ikitommi opened 2 months ago

ikitommi commented 2 months ago

We seem to be using potemkin in https://github.com/metosin/ring-http-response. There is a code generation step that creates code to pull extra functions from ring.util.response using potemkin (yes, the code is 10y old 🙈). Would like to drop this in favour of expose-api and all the code in the library is generated already using mustache templates.

Problem using expose-api

  1. expose-api wants to create the full file, I just need a code fragment, see this => would it be possible to optionally generate just the defn-fragments, no comments or ns definitions? would be easier to pull in just the defn-parts as part of the overall code generation.

Enhancement requests

  1. Actually, it would be nice to be able to optionally inline the full source code to the target namespace instead of generating a proxy to forward the calls. With ring-http-response this would make sense as over time, there are new functions being added to ring.util.response and if we generate the proxies using the latest version ring and a user would use an older version of ring, the proxy can point to a defn that doesn't exist in that version of ring. For this, there is a runtime guard in ring-http-response (potemkin import fails silently with missing Vars):
;; charset
(if-not (ns-resolve 'ring.util.response 'charset)
  (println "Can't import ring.util.response/charset, try updating to Ring 1.6.0+"))
(p/import-vars [ring.util.response charset])

... looking back how ring-http-response is implemented, I think the whole idea of "drop-in replacement" was bad. But, I don't want to break it now, 5M downloads and lot's of active users, just want drop the potemkin away. Cheers.

ikitommi commented 2 months ago

great work with the lib :)

didibus commented 2 months ago

I've been hammocking a little how to support exposing some APIs in an existing namespace.

My current thought are it would append to the end, and put it between comment blocks that let me find the part of the file that's auto-generated. So it would leave the rest of the file intact. That way you can mix and match generated code and not generated code in the same file.

Another idea I had was to be more granular even, and actually use a special comment in an existing file. Something like:

;;; --EXPOSE [#'com.my_lib/foo]

;;; EXPOSE--

And I would append between the comments but only for the given Vars.

That way you can do a mixed namespace, where in some places you can selectively expose things, but also have other code mixed in.

The comments wouldn't disappear after the code-gen, so when reruning code-gen it would replace things between them again to update.

didibus commented 2 months ago

Specifically in your case, since you have a mustache template already, I think I can probably provide an expose-str that takes the impl var and returns a wrapped defn or defmacro just for it as a string. So you could call it from within the template.