MY MONSTER IT LIVES!
This commit is contained in:
		
							parent
							
								
									7c9f7f91b4
								
							
						
					
					
						commit
						b69bcaa020
					
				|  | @ -44,7 +44,7 @@ | |||
|     (.exists (java.io.File. (first args))) | ||||
|     (let [application (x/parse (first args))] | ||||
|       (h/to-hugsql-queries application) | ||||
|       ;; (j/to-json-routes application) | ||||
|       (j/to-json-routes application) | ||||
|       (s/to-selmer-routes application) | ||||
|       (t/to-selmer-templates application)))) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,11 +1,14 @@ | |||
| (ns ^{:doc "Application Description Language: generate RING routes for REST requests." | ||||
|       :author "Simon Brooke"} | ||||
|   adl.to-json-routes | ||||
|   (:require [clojure.java.io :refer [file]] | ||||
|   (:require [clojure.java.io :refer [file make-parents writer]] | ||||
|             [clojure.pprint :refer [pprint]] | ||||
|             [clojure.string :as s] | ||||
|             [clojure.xml :as x] | ||||
|             [clj-time.core :as t] | ||||
|             [clj-time.format :as f] | ||||
|             [adl.utils :refer :all])) | ||||
|             [adl.utils :refer :all] | ||||
|             [adl.to-hugsql-queries :refer [queries]])) | ||||
| 
 | ||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||
| ;;;; | ||||
|  | @ -34,11 +37,12 @@ | |||
| ;;; to-hugsql-queries, because essentially we need one JSON entry point to wrap | ||||
| ;;; each query. | ||||
| 
 | ||||
| (defn file-header [parent-name this-name] | ||||
| 
 | ||||
| (defn file-header [application] | ||||
|   (list | ||||
|     'ns | ||||
|     (symbol (str parent-name ".routes." this-name)) | ||||
|     (str "JSON routes for " parent-name | ||||
|     (symbol (str (safe-name (:name (:attrs application))) ".routes.auto-json")) | ||||
|     (str "JSON routes for " (:name (:attrs application)) | ||||
|          " auto-generated by [Application Description Language framework](https://github.com/simon-brooke/adl) at " | ||||
|          (f/unparse (f/formatters :basic-date-time) (t/now))) | ||||
|     (list | ||||
|  | @ -49,15 +53,11 @@ | |||
|       '[ring.util.http-response :as response] | ||||
|       '[clojure.java.io :as io] | ||||
|       '[hugsql.core :as hugsql] | ||||
|       (vector (symbol (str parent-name ".db.core")) :as 'db)))) | ||||
| 
 | ||||
| 
 | ||||
| (defn make-safe-name [string] | ||||
|   (s/replace string #"[^a-zA-Z0-9-]" "")) | ||||
|       (vector (symbol (str (safe-name (:name (:attrs application))) ".db.core")) :as 'db)))) | ||||
| 
 | ||||
| 
 | ||||
| (defn declarations [handlers-map] | ||||
|   (cons 'declare (sort (map #(symbol (make-safe-name (name %))) (keys handlers-map))))) | ||||
|   (cons 'declare (sort (map #(symbol (name %)) (keys handlers-map))))) | ||||
| 
 | ||||
| 
 | ||||
| (defn generate-handler-src | ||||
|  | @ -81,12 +81,12 @@ | |||
| 
 | ||||
| 
 | ||||
| (defn handler | ||||
|   "Generate declarations for handlers from query with this `query-key` in this `queries-map` taken from within | ||||
|   this `entities-map`. This method must follow the structure of | ||||
|   "Generate declarations for handlers from query with this `query-key` in this `queries-map` | ||||
|   taken from within this `application`. This method must follow the structure of | ||||
|   `to-hugsql-queries/queries` quite closely, because we must generate the same names." | ||||
|   [query-key queries-map entities-map] | ||||
|   [query-key queries-map application] | ||||
|   (let [query (query-key queries-map) | ||||
|         handler-name (symbol (make-safe-name (name query-key)))] | ||||
|         handler-name (symbol (name query-key))] | ||||
|     (hash-map | ||||
|       (keyword handler-name) | ||||
|       (merge | ||||
|  | @ -182,6 +182,7 @@ | |||
| 
 | ||||
| 
 | ||||
| (defn defroutes [handlers-map] | ||||
|   "Generate JSON routes for all queries implied by this ADL `application` spec." | ||||
|   (cons | ||||
|     'defroutes | ||||
|     (cons | ||||
|  | @ -190,7 +191,7 @@ | |||
|         #(let [handler (handlers-map %)] | ||||
|            (list | ||||
|              (symbol (s/upper-case (name (:method handler)))) | ||||
|              (str "/json/auto/" (:name handler)) | ||||
|              (str "/json/auto/" (safe-name (:name handler))) | ||||
|              'request | ||||
|               (list | ||||
|                 'route/restricted | ||||
|  | @ -199,39 +200,46 @@ | |||
|           (keys handlers-map)))))) | ||||
| 
 | ||||
| 
 | ||||
| ;; (defn migrations-to-json-routes | ||||
| ;;   ([migrations-path parent-namespace-name] | ||||
| ;;    (migrations-to-json-routes migrations-path parent-namespace-name "auto-json-routes")) | ||||
| ;;   ([migrations-path parent-namespace-name namespace-name] | ||||
| ;;    (let [output (str (s/replace namespace-name #"-" "_") ".clj") | ||||
| ;;          adl-struct (migrations-to-xml migrations-path "Ignored") | ||||
| ;;          q (reduce | ||||
| ;;              merge | ||||
| ;;              {} | ||||
| ;;              (map | ||||
| ;;                #(queries % adl-struct) | ||||
| ;;                (vals adl-struct))) | ||||
| ;;          h (reduce | ||||
| ;;              merge | ||||
| ;;              {} | ||||
| ;;              (map | ||||
| ;;                #(handler % q adl-struct) | ||||
| ;;                (keys q))) | ||||
| ;;          f (cons | ||||
| ;;              (file-header parent-namespace-name namespace-name) | ||||
| ;;              ;;                          (pre-declare | ||||
| ;;              (cons | ||||
| ;;                (declarations h) | ||||
| ;;                (cons | ||||
| ;;                  (defroutes h) | ||||
| ;;                  (map #(:src (h %)) (sort (keys h))))))] | ||||
| ;;      (spit | ||||
| ;;        output | ||||
| ;;        (with-out-str | ||||
| ;;          (doall | ||||
| ;;            (for [expr f] | ||||
| ;;              (do | ||||
| ;;                (pprint expr) | ||||
| ;;                (print "\n\n")))))) | ||||
| ;;      f | ||||
| ;;      ))) | ||||
| (defn make-handlers-map | ||||
|   [application] | ||||
|   (reduce | ||||
|     merge | ||||
|     {} | ||||
|     (map | ||||
|       (fn [e] | ||||
|         (let [qmap (queries application e)] | ||||
|           (reduce | ||||
|             merge | ||||
|             {} | ||||
|             (map | ||||
|               (fn [k] | ||||
|                 (handler k qmap application)) | ||||
|               (keys qmap))))) | ||||
|       (children-with-tag application :entity)))) | ||||
| 
 | ||||
| 
 | ||||
| (defn to-json-routes | ||||
|   [application] | ||||
|   (let [handlers-map (make-handlers-map application) | ||||
|         filepath (str *output-path* (:name (:attrs application)) "/routes/auto_json.clj")] | ||||
|     (make-parents filepath) | ||||
|     (with-open [output (writer filepath)] | ||||
|       (binding [*out* output] | ||||
|         (doall | ||||
|           (map | ||||
|             (fn [f] | ||||
|               (pprint f) | ||||
|               (println "\n")) | ||||
|             (list | ||||
|               (file-header application) | ||||
|               (declarations handlers-map) | ||||
|               (defroutes handlers-map)))) | ||||
|         (doall | ||||
|           (map | ||||
|             (fn [h] | ||||
|               (pprint (:src (handlers-map h))) | ||||
|               (println) | ||||
|               h) | ||||
|             (sort (keys handlers-map)))))))) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ | |||
|       '[ring.util.http-response :as response] | ||||
|       '[clojure.java.io :as io] | ||||
|       '[hugsql.core :as hugsql] | ||||
|       (vector (symbol (str (:name (:attrs application)) ".layout")) :as 'l) | ||||
|       (vector (symbol (str (:name (:attrs application)) ".db.core")) :as 'db) | ||||
|       (vector (symbol (str (:name (:attrs application)) ".routes.manual")) :as 'm)))) | ||||
| 
 | ||||
|  | @ -62,7 +63,7 @@ | |||
|       (vector 'r) | ||||
|       (list 'let (vector 'p (list :form-params 'r)) | ||||
|             (list | ||||
|               'layout/render | ||||
|               'l/render | ||||
|               (list 'resolve-template (str n ".html")) | ||||
|               (merge | ||||
|                 {:title (capitalise (:name (:attrs f))) | ||||
|  | @ -79,7 +80,7 @@ | |||
|                    (list | ||||
|                      (symbol | ||||
|                        (str | ||||
|                          "db/search-" | ||||
|                          "db/search-strings-" | ||||
|                          (singularise (:name (:attrs e))))) | ||||
|                      'p)}))))))) | ||||
| 
 | ||||
|  | @ -111,13 +112,38 @@ | |||
|       'defroutes | ||||
|       (cons | ||||
|         'auto-selmer-routes | ||||
|         (interleave | ||||
|           (map | ||||
|             (fn [r] (make-route 'GET r)) | ||||
|             (sort routes)) | ||||
|         (map | ||||
|           (fn [r] (make-route 'POST r)) | ||||
|           (sort routes))))))) | ||||
|         (cons | ||||
|           '(GET | ||||
|              "/index" | ||||
|              request | ||||
|              (route/restricted | ||||
|                (apply (resolve-handler "index") (list request)))) | ||||
|           (interleave | ||||
|             (map | ||||
|               (fn [r] (make-route 'GET r)) | ||||
|               (sort routes)) | ||||
|             (map | ||||
|               (fn [r] (make-route 'POST r)) | ||||
|               (sort routes)))))))) | ||||
| 
 | ||||
| 
 | ||||
| (defn generate-handler-resolver | ||||
|   "Dodgy, dodgy, dodgy. Generate code which will look up functions in the | ||||
|   manual and in this namespace. I'm sure someone who really knew what they | ||||
|   were doing could write this more elegantly." | ||||
|   [application] | ||||
|   (list | ||||
|     'defn | ||||
|     'raw-resolve-handler | ||||
|     "Prefer the manually-written version of the handler with name `n`, if it exists, to the automatically generated one" | ||||
|     (vector 'n) | ||||
|     (list 'try | ||||
|           (list 'eval (list 'symbol (list 'str (:name (:attrs application)) ".routes.manual/" 'n))) | ||||
|           (list 'catch | ||||
|                 'Exception '_ | ||||
|                 (list 'eval | ||||
|                       (list 'symbol | ||||
|                             (list 'str (:name (:attrs application)) ".routes.auto/" 'n))))))) | ||||
| 
 | ||||
| 
 | ||||
| (defn to-selmer-routes | ||||
|  | @ -134,13 +160,13 @@ | |||
|                      n | ||||
|                      (str "auto/" n)))) | ||||
|         (println) | ||||
|         (pprint '(def resolve-template (memoise raw-resolve-template))) | ||||
|         (pprint '(def resolve-template (memoize raw-resolve-template))) | ||||
|         (println) | ||||
|         (pprint '(defn index | ||||
|                    [r] | ||||
|                    (layout/render | ||||
|                    (l/render | ||||
|                      (resolve-template | ||||
|                        "application-index") | ||||
|                        "application-index.html") | ||||
|                      {:title "Administrative menu"}))) | ||||
|         (println) | ||||
|         (doall | ||||
|  | @ -153,14 +179,8 @@ | |||
|                     (println)) | ||||
|                   (filter (fn [c] (#{:form :list :page} (:tag c))) (children e))))) | ||||
|             (children-with-tag application :entity))) | ||||
|         (pprint '(defn raw-resolve-handler | ||||
|                    "Prefer the manually-written version of the handler with name `n`, if it exists, to the automatically generated one" | ||||
|                    [n] | ||||
|                    (let [s (symbol (str "m." n))] | ||||
|                      (if | ||||
|                        (bound? s) | ||||
|                        (eval s) | ||||
|                        (eval (symbol n)))))) | ||||
|         (pprint | ||||
|           (generate-handler-resolver application)) | ||||
|         (println) | ||||
|         (pprint '(def resolve-handler | ||||
|                    (memoize raw-resolve-handler))) | ||||
|  |  | |||
|  | @ -90,7 +90,7 @@ | |||
|      "\n" | ||||
|      (flatten | ||||
|        (list | ||||
|          "{% extends \"templates/base.html\" %}" | ||||
|          "{% extends \"base.html\" %}" | ||||
|          (str "<!-- File " | ||||
|               filename | ||||
|               " generated " | ||||
|  |  | |||
|  | @ -181,6 +181,19 @@ | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| (defn safe-name | ||||
|   ([string] | ||||
|     (s/replace string #"[^a-zA-Z0-9-]" "")) | ||||
|   ([string convention] | ||||
|    (case convention | ||||
|      (:sql :c) (s/replace string #"[^a-zA-Z0-9_]" "_") | ||||
|      :c-sharp (s/replace (capitalise string) #"[^a-zA-Z0-9]" "") | ||||
|      :java (let | ||||
|              [camel (s/replace (capitalise string) #"[^a-zA-Z0-9]" "")] | ||||
|              (apply str (cons (Character/toUpperCase (first camel)) (rest camel)))) | ||||
|      (safe-name string)))) | ||||
| 
 | ||||
| 
 | ||||
| (defn link-table? | ||||
|   "Return true if this `entity` represents a link table." | ||||
|   [entity] | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue