镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Typing full namespaces for keywords in config.edn is tedious #71

Open

Description

@dkarvik

It might be worth creating some sugar for this, or maybe it's not so bad :).

Activity

  1. dkarvik commented on Apr 7, 2019

    @dkarvik
    ContributorAuthor

    A patch to add support for aliases into the config, there's 3 kinds:

    • Direct alias (:foo becomes :foo.bar.baz/bosh)
    • NS alias (expand xyz in :xyz/foo to com.myproj.xyz/foo)
    • NS prefix (expand proj in :proj.xyz/foo to com.myproj.xyz/foo)

    Aliases and prefixes have overlapping functionality. Alias functionality can be replicated with prefixes. This patch needs more work to specify an internally consistent format for the aliases.

    From 980ad65006f6e45acaa33313c0b6fd557c6ca09f Mon Sep 17 00:00:00 2001
    From: Dominic Monroe <dmc@juxt.pro>
    Date: Sun, 7 Apr 2019 08:05:11 +0100
    Subject: [PATCH] Add aliases to config
    
    ---
     lib/edge.system/src/edge/system.clj | 113 +++++++++++++++++++++++++++-
     1 file changed, 112 insertions(+), 1 deletion(-)
    
    diff --git a/lib/edge.system/src/edge/system.clj b/lib/edge.system/src/edge/system.clj
    index bff5043..d2af043 100644
    --- a/lib/edge.system/src/edge/system.clj
    +++ b/lib/edge.system/src/edge/system.clj
    @@ -5,6 +5,8 @@
       (:require
        [aero.core :as aero]
        [clojure.java.io :as io]
    +   [clojure.walk :as walk]
    +   [clojure.string :as string]
        [integrant.core :as ig]))
     
     ;; There will be integrant tags in our Aero configuration. We need to
    @@ -18,12 +20,121 @@
         (locking lock
           (ig/load-namespaces system-config))))
     
    +(defprotocol EdgeNamed
    +  (get-namespace [this])
    +  (set-namespace [this ns]))
    +
    +(extend-protocol EdgeNamed
    +  clojure.lang.Keyword
    +  (get-namespace [k] (namespace k))
    +  (set-namespace [k ns] (keyword ns (name k)))
    +
    +  clojure.lang.Symbol
    +  (get-namespace [s] (namespace s))
    +  (set-namespace [s ns] (symbol ns (name s))))
    +
    +(defn- split-ns
    +  [ns]
    +  (string/split ns #"\."))
    +
    +(defn- join-ns-segments
    +  [ns-segments]
    +  (string/join "." ns-segments))
    +
    +(defn- ns-prefixes
    +  [ns]
    +  (->> ns
    +       split-ns
    +       (iterate butlast)
    +       (take-while some?)
    +       (map join-ns-segments)))
    +
    +(defn- expand-named
    +  [context named]
    +  (try
    +    (let [named-ns (get-namespace named)]
    +      (cond
    +        ;; There's a named alias for this key
    +        (get-in context [:alias named])
    +        (get-in context [:alias named])
    +
    +        ;; There's an alias for the namespace
    +        (get-in context [:require-as (keyword named-ns)])
    +        (set-namespace named
    +                       (name (get-in context [:require-as (keyword named-ns)])))
    +
    +        ;; There's a prefix for the namespace
    +        (some->> named-ns ns-prefixes (map keyword) (some (:ns-prefix context {})))
    +        (let [[prefix replacement]
    +              (some #(find (:ns-prefix context) %)
    +                    (map keyword (ns-prefixes named-ns)))]
    +          (set-namespace
    +            named
    +            (string/replace-first named-ns
    +                                  (name prefix)
    +                                  (name replacement))))
    +        :else named))
    +    (catch Exception e
    +      (prn {:context context
    +            :named named})
    +      (prn (some->> (get-namespace named) ns-prefixes (map keyword)))
    +      (throw (ex-info "Error during expansion"
    +                      {:context context
    +                       :named named}
    +                      e)))))
    +
    +(comment
    +  (def ctx {:alias {:foo :edge.system/foo}
    +            :require-as {:foo :edge.system.foo}
    +            :ns-prefix {:foo :edge.system.bar}})
    +
    +  (expand-named ctx :foo.baz/abc) ; => :edge.system.bar.baz/abc
    +  (expand-named ctx :foo) ; => :edge.system/foo
    +  (expand-named ctx :foo/bar) ; => :edge.system.foo/bar
    +  )
    +
    +(defn- expand-config
    +  [config]
    +  (let [context (::context config)]
    +    (walk/postwalk
    +      (fn [x]
    +        (if (satisfies? EdgeNamed x)
    +          (expand-named context x)
    +          x))
    +      config)))
    +
    +(comment
    +  (expand-config
    +    {::context
    +     {:ns-prefix {:f :falcon
    +                  :fn :falcon.fakenews}}
    +
    +     :ig/system
    +     {:f.pg/embedded nil
    +      :fn.foo/article-route {:fn.http.section/article-page 10}}})
    +  ;; =>
    +  ;{:ig/system {:falcon.pg/embedded nil
    +  ;             :falcon.fakenews.foo/article-route
    +  ;             {:falcon.fakenews.http.section/article-page 10}}}                                
    +  )
    +
    +(defn- read-config
    +  [source given-opts]
    +  (let [opts (merge aero/default-opts given-opts {:source source})
    +        tag-fn (partial aero/reader opts)
    +        wrapped-config (aero/read-config-into-tag-wrapper source)]
    +    (-> wrapped-config
    +        expand-config
    +        (aero/resolve-refs tag-fn)
    +        (#'aero/resolve-tag-wrappers tag-fn)
    +        (#'aero/realize-deferreds))))
    +
     (defn config
       "Read EDN config, with the given aero options. See Aero docs at
       https://github.com/juxt/aero for details."
       [opts]
       (-> (io/resource "config.edn") ;; <1>
    -      (aero/read-config opts)) ;; <2>
    +      (read-config opts)) ;; <2>
       )
     
     (defn system-config
    -- 
    2.21.0
    
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions