expose-api is a Clojure library designed to simplify the process of creating public-facing API namespaces. In Clojure, it's common to define a namespace as your "public" interface and have implementation namespaces with the actual code. Manually writing the public namespace can be tedious. This library automates that process by generating a Clojure namespace that wraps implementation vars and exposes a public API.
Add the following dependency to your project.clj:
[com.xadecimal/expose-api "0.3.0"]
Add the following dependency to your deps.edn:
{:deps {com.xadecimal/expose-api {:mvn/version "0.3.0"}}}
Here's a quick example of how to use expose-api to generate a public API namespace:
(ns your.namespace
(:require [com.xadecimal.expose-api :as api]))
(api/expose-api
:file-path "./src/com/xadecimal/my_lib.clj"
:ns-code `(~'ns ~'com.xadecimal.my-lib
"A very cool library which lets you do cool things.
To use it, require it and call its cool functions."
(:refer-clojure :exclude ~'[defn])
(:require ~'[com.xadecimal.my-lib.impl :as impl]))
:vars [#'impl/defn #'impl/cool])
This will create a file ./src/com/xadecimal/my_lib.clj containing Clojure source code of the specified namespace form, and with a function named cool which calls the impl/cool function, with the same doc and arities as that of the impl/cool function, as well as a macro named defn which calls the impl/defn macro, with the same doc and arities as that of the impl/defn macro.
file-path - A string pointing to the path where you want the generated .clj namespace source file to be created. This should match the ns-code namespace path. It's relative to where you are executing from.ns-code - An ns code form, which will become the ns directive in the generated namespace source code. Ensure that you require the implementation namespaces that the vars use.vars - A sequence of vars that you want to wrap and expose publicly in the generated namespace. Vars are assumed to come from implementation namespaces.Potemkin's import-vars is another tool that facilitates the creation of public APIs by importing vars from other namespaces. Here's a comparison of expose-api and Potemkin's import-vars:
import-vars is used directly in the namespace definition to import vars from other namespaces.(ns your.namespace
(:require [potemkin :refer [import-vars]]
[some.other.namespace :as other]))
(import-vars other/foo other/bar)
expose-api generates a new namespace file with the specified public API, wrapping implementation vars.(api/expose-api
:file-path "./src/com/xadecimal/my_lib.clj"
:ns-code `(~'ns ~'com.xadecimal.my-lib
"A very cool library which lets you do cool things."
(:refer-clojure :exclude ~'[defn])
(:require ~'[com.xadecimal.my-lib.impl :as impl]))
:vars [#'impl/defn #'impl/cool])
It is recommended to use expose-api from a build step. Here’s an example of how you can add such a build step using tools.build:
Create a build script (e.g., build.clj):
(ns build
(:require [clojure.tools.build.api :as b]
[com.xadecimal.expose-api :as api]))
(defn generate-api [m]
(api/expose-api
:file-path "./src/com/xadecimal/my_lib.clj"
:ns-code `(~'ns ~'com.xadecimal.my-lib
"A very cool library which lets you do cool things."
(:refer-clojure :exclude ~'[defn])
(:require ~'[com.xadecimal.my-lib.impl :as impl]))
:vars [#'impl/defn #'impl/cool]))
Add a build alias to your deps.edn
:build {:extra-deps {io.github.clojure/tools.build {:git/tag "v0.10.4" :git/sha "31388ff"}}
:extra-paths ["."]
:ns-default build}
You need it to include your project's source whose vars are getting exposed. This is why we use :extra-deps and :extra-paths, because we will run it with -X and not as a tool.
Run the build script:
clojure -X:build generate-api
This will generate the specified public API namespace as part of your build process, ensuring that your API is always up to date with the latest implementation changes.
This project is licensed under the MIT License - see the LICENSE file for details.
Thanks to the Clojure community for their support and contributions to the ecosystem.
Can you improve this documentation?Edit on GitHub
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 |