aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcolin <colin@cicadas.surf>2023-11-18 15:25:51 -0800
committercolin <colin@cicadas.surf>2023-11-18 15:25:51 -0800
commitc201a822f264041a1b9169824c0f9acbfae9cf6e (patch)
tree47ebbdfeaf4bc184a676537ec03637b3ec023c5d
parent1d3d018f01ffb71dcdeaa086b3025a00428b45c1 (diff)
version 1.0
-rw-r--r--lazybones-hunchentoot.asd10
-rw-r--r--lazybones.asd54
-rw-r--r--src/backend/hunchentoot.lisp (renamed from lazybones-hunchentoot.lisp)11
-rw-r--r--src/client/dexador.lisp205
-rw-r--r--src/client/parenscript.lisp3
-rw-r--r--src/documentation/markdown.lisp (renamed from lazybones-documentation.lisp)15
-rw-r--r--src/lazybones.lisp (renamed from lazybones.lisp)2
-rw-r--r--src/macros.lisp (renamed from macros.lisp)2
-rw-r--r--src/package.lisp (renamed from package.lisp)4
9 files changed, 274 insertions, 32 deletions
diff --git a/lazybones-hunchentoot.asd b/lazybones-hunchentoot.asd
deleted file mode 100644
index 56ae2c0..0000000
--- a/lazybones-hunchentoot.asd
+++ /dev/null
@@ -1,10 +0,0 @@
-;;;; lazybones-hunchentoot.asd
-
-(asdf:defsystem #:lazybones-hunchentoot
- :description "hunchentoot backend for lazybones"
- :author "Colin Okay <okay@toyful.space>"
- :license "AGPLv3"
- :version "0.2.1"
- :serial t
- :depends-on (#:hunchentoot #:lazybones)
- :components ((:file "lazybones-hunchentoot")))
diff --git a/lazybones.asd b/lazybones.asd
index bd56d95..cb74b04 100644
--- a/lazybones.asd
+++ b/lazybones.asd
@@ -1,19 +1,61 @@
;;;; lazybones.asd
(asdf:defsystem #:lazybones
- :description "http route handling"
- :author "Colin Okay <okay@toyful.space>"
+ :description "Multi-backend HTTP Framework with automatic client and documentation generation. "
+ :author "Colin <colin@cicadas.surf>"
:license "AGPLv3"
- :version "0.10.1"
+ :version "1.0.0"
+ :pathname "src/"
:serial t
:depends-on (#:alexandria
+ #:closer-mop
+ #:trivial-documentation
#:str
#:cl-ppcre
- #:trivial-documentation
#:jonathan
#:lisp-namespace)
:components ((:file "package")
(:file "macros")
- (:file "lazybones")
- (:file "lazybones-documentation")))
+ (:file "lazybones")))
+
+(asdf:defsystem #:lazybones/documentation
+ :description "Generate documentation for a lazybones app's endpoints."
+ :author "Colin <colin@cicadas.surf>"
+ :license "AGPLv3"
+ :depends-on (#:lazybones)
+ :pathname "src/documentation/"
+ :serial t
+ :components ((:file "markdown")))
+
+(asdf:defsystem #:lazybones/backend/hunchentoot
+ :description "hunchentoot backend for lazybones"
+ :author "Colin <colin@cicadas.surf>"
+ :license "AGPLv3"
+ :version "1.0.0"
+ :depends-on (#:hunchentoot #:lazybones)
+ :pathname "src/backend/"
+ :serial t
+ :components ((:file "hunchentoot")))
+
+
+(asdf:defsystem #:lazybones/client/parenscript
+ :description "Generate a JS module for API requests to a lazybones APP."
+ :author "Colin <colin@cicadas.surf>"
+ :license "AGPLv3"
+ :version "1.0.0"
+ :depends-on (#:parenscript #:lazybones)
+ :pathname "src/client/"
+ :serial t
+ :components ((:file "parenscript")))
+
+(asdf:defsystem #:lazybones/client/dexador
+ :description "Generates a lisp source file for API requests to a lazybones APP using Dexador."
+ :author "Colin <colin@cicadas.surf>"
+ :license "AGPLv3"
+ :version "1.0.0"
+ :depends-on (#:dexador #:lazybones)
+ :pathname "src/client/"
+ :serial t
+ :components ((:file "dexador")))
+
diff --git a/lazybones-hunchentoot.lisp b/src/backend/hunchentoot.lisp
index 2b3bf1e..acb15cb 100644
--- a/lazybones-hunchentoot.lisp
+++ b/src/backend/hunchentoot.lisp
@@ -1,4 +1,4 @@
-;; Copyright (C) 2022 Colin Okay
+;; Copyright (C) 2022 colin@cicadas.surf
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Affero General Public License as
@@ -13,16 +13,13 @@
;; You should have received a copy of the GNU Affero General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-;;;; lazybones-hunchentoot.lisp -- hunchentoot backend for lazybones
-
-(defpackage #:lazybones.backend/hunchentoot
- (:use #:cl #:lazybones.backend)
+(defpackage #:lazybones-backend.hunchentoot
+ (:use #:cl #:lazybones-backend)
(:local-nicknames (#:h #:hunchentoot)
(#:lzb #:lazybones)
(#:a #:alexandria)))
-(in-package :lazybones.backend/hunchentoot)
+(in-package :lazybones-backend.hunchentoot)
;;; Hunchentoot Acceptor Subclass
diff --git a/src/client/dexador.lisp b/src/client/dexador.lisp
new file mode 100644
index 0000000..2503b5e
--- /dev/null
+++ b/src/client/dexador.lisp
@@ -0,0 +1,205 @@
+;;;; lazybones-client.lisp -- macro to generate a set of http request functions given an APP instance
+
+;; Copyright (C) 2022 Colin Okay
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+(defpackage #:lazybones/client.dexador
+ (:use #:cl)
+ (:local-nicknames (#:a #:alexandria-2))
+ (:export #:generate))
+
+(in-package :lazybones/client.dexador)
+
+
+
+(defun endpoint-defun-name (ep)
+ "Returns the string name of a defun for making requests to
+endpoint EP."
+ (with-output-to-string (*standard-output*)
+ (princ (string-downcase (symbol-name (lazybones::endpoint-method ep))))
+ (princ "-")
+ (loop for (term . more) on (lazybones::endpoint-dispatch-pattern ep)
+ when (and (stringp term) (plusp (length term)))
+ do (princ (string-downcase term))
+ when (listp term)
+ do (princ (string-downcase (car term)))
+ when (and more (plusp (length term)))
+ do (princ "/"))))
+
+(defun endpoint-defun-route-var-names (ep)
+ "Returns a list of strings representing the names of route variables
+extracted from endpoint EP, to be used as variable names in the defun
+for making requests to that endpoint."
+ (lazybones::endpoint-route-vars ep))
+
+(defun endpoint-defun-query-var-names (ep)
+ "Returns a list of strings representing the names of query parameter
+variables extraced from the endpoint EP, to be used as variable names
+in the defun for making request to that endpoint."
+ (mapcar (a:compose #'symbol-name #'first)
+ (lazybones::endpoint-params ep)))
+
+
+(defun endpoint-accepts-body-p (ep)
+ (member (lazybones::endpoint-method ep) '(:post :put :patch)) )
+
+(defun endpoint-defun-lambda-list (ep)
+ "Returns a string representation of the lambda list of the defun
+for making requests to endpoint EP."
+ (format
+ nil
+ "(~{~a ~} %host &key ~:[~;%content-type %body ~] %headers %cookies)"
+ (append
+ (endpoint-defun-route-var-names ep)
+ (endpoint-defun-query-var-names ep))
+ (endpoint-accepts-body-p ep)))
+
+
+(defun endpoint-defun-dexador-uri-route-format-string (ep)
+ "Returns a string representing a format string, intended to be
+ embedded into the body of a defun for making requests to the
+ endpoint Ep. It is designed to be passed to FORMAT, where route
+ variables are substituted into the string."
+ (str:join "/"
+ (mapcar (lambda (x) (if (listp x) "~a" x))
+ (lazybones::endpoint-dispatch-pattern ep))))
+
+(defun endpoint-defun-dexador-uri-route-query-format-string (ep)
+ "Returns a string representing a format string, intended to be
+ embedded into the body of a defun for making requests to the
+ endpoint EP. It is desienged to be passed to FORMAT, where query
+ paramters are substituted into the string, if they exist."
+ (with-output-to-string (*standard-output*)
+ (loop
+ for first = t then nil
+ for varname in (endpoint-defun-query-var-names ep)
+ do
+ (princ "~@[")
+ (unless first (princ #\&))
+ (princ (string-upcase varname))
+ (princ "=~a~]"))))
+
+(defun endpoint-defun-dexador-request-uri (app ep)
+ "Returns a string representation of code that generates a URI for
+ passing to the dexador request function within the body of the defun
+ for making requests to the endpoint EP of the application APP."
+ (concatenate
+ 'string
+ "(format nil "
+ "\""
+ "~a"
+ (lazybones::app-prefix app)
+ (endpoint-defun-dexador-uri-route-format-string ep)
+ "?"
+ (endpoint-defun-dexador-uri-route-query-format-string ep)
+ "\" "
+ "%host "
+ (str:join " " (endpoint-defun-route-var-names ep))
+ " "
+ (str:join " " (endpoint-defun-query-var-names ep))
+ ")"))
+
+(defun endpoint-defun-body (app ep)
+ "Returns a string representation of the function body of a defun
+ for making requests to the endpoint EP in the app APP."
+ (format
+ nil
+ " (dexador:~a~% ~a~%~{ ~a~^~%~})"
+ (string-downcase (symbol-name (lazybones::endpoint-method ep)))
+ (endpoint-defun-dexador-request-uri app ep)
+ (append
+ (if (endpoint-accepts-body-p ep)
+ (list ":content %body"
+ ":cookie-jar %cookies"
+ ":headers (if %content-type (cons (cons \"Content-Type\" %content-type) %headers) %headers)")
+ (list ":cookie-jar %cookies"
+ ":headers %headers")))))
+
+(defun generate-defun-for-endpoint (app ep)
+ "Returns a string representation of a defun form for a function that
+makes a request to the endpoint EP."
+ (format nil
+ "(defun ~a~% ~a~% ~s~%~a)"
+ (endpoint-defun-name ep)
+ (endpoint-defun-lambda-list ep)
+ (lazybones::endpoint-documentation ep)
+ (endpoint-defun-body app ep)))
+
+
+(defun all-function-names (app)
+ (mapcar 'endpoint-defun-name (lazybones::app-endpoints app)))
+
+(defun app-client-package-name (app)
+ (format nil "~a-CLIENT" (lazybones::app-name app)))
+
+
+(defun generate-defsystem-for-client-of-app (app)
+ (with-output-to-string (*standard-output*)
+ (princ "(asdf:defsystem #:") (princ (app-client-package-name app))
+ (terpri)
+ (princ " :depends-on (#:dexador)")
+ (terpri)
+ (princ " :components ((:file ")
+ (princ #\")
+ (princ (string-downcase (app-client-package-name app)))
+ (princ #\")
+ (princ ")))")))
+
+
+(defun generate-defpackage-for-client-of-app (app)
+ (with-output-to-string (out)
+ (format
+ out
+ "
+;;;; DO NOT EDIT! THIS FILE HAS BEEN GENERATED BY LAZYBONES-CLIENT
+
+(defpackage #:~a
+ (:use :cl)
+ (:export ~%~{ #:~a~^~%~}))"
+ (app-client-package-name app)
+ (all-function-names app))
+ (terpri out)
+ (format out "(in-package :~a)" (app-client-package-name app))
+ (terpri out)))
+
+(defun client-asd-file-name (app)
+ (format nil "~a.asd" (string-downcase (app-client-package-name app))))
+
+(defun client-lisp-file-name (app)
+ (format nil "~a.lisp" (string-downcase (app-client-package-name app))))
+
+(defun generate-client-functions-for-app (app)
+ (loop for ep in (lazybones::app-endpoints app)
+ collect (generate-defun-for-endpoint app ep)))
+
+(defun generate (directory app)
+ "Generate "
+ (assert (uiop:directory-exists-p directory))
+
+ (alexandria:write-string-into-file
+ (generate-defsystem-for-client-of-app app)
+ (merge-pathnames (client-asd-file-name app) directory))
+
+ (alexandria:write-string-into-file
+ (with-output-to-string (*standard-output*)
+ (princ (generate-defpackage-for-client-of-app app))
+ (princ #\newline) (princ #\newline)
+ (princ #\newline) (princ #\newline)
+ (dolist (defun-string (generate-client-functions-for-app app))
+ (princ defun-string)
+ (princ #\newline) (princ #\newline)))
+ (merge-pathnames (client-lisp-file-name app) directory))
+ :ok)
diff --git a/src/client/parenscript.lisp b/src/client/parenscript.lisp
new file mode 100644
index 0000000..75afbd7
--- /dev/null
+++ b/src/client/parenscript.lisp
@@ -0,0 +1,3 @@
+(defpackage #:lazybones/client.parenscript
+ (:use #:cl)
+ (:export #:generate))
diff --git a/lazybones-documentation.lisp b/src/documentation/markdown.lisp
index 9e837d0..5f2b883 100644
--- a/lazybones-documentation.lisp
+++ b/src/documentation/markdown.lisp
@@ -1,4 +1,4 @@
-;; Copyright (C) 2022 Colin Okay
+;; Copyright (C) 2022 colin@cicadas.surf
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Affero General Public License as
@@ -14,15 +14,20 @@
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
-;;;; lazybones-documentation.lisp -- documenting APP instances
+;;;; markdown.lisp -- documenting APP instances
-(in-package :lazybones)
+(defpackage #:lazybones/documentation.markdown
+ (:use #:cl)
+ (:export #:generate))
+
+(in-package :lazybones/documentation.markdown)
(defun sorted-endpoints (endpoints)
(sort (copy-seq endpoints) #'string< :key #'endpoint-route))
-(defun generate-app-documentation (app)
- "For now, generates a single Markdown string that documents each endpoint in APP."
+(defun generate (app)
+ "For now, returns a single Markdown formatted string that documents
+each endpoint in APP."
(symbol-macrolet ((newline (progn (princ #\newline)(princ #\newline))))
(with-slots
(title
diff --git a/lazybones.lisp b/src/lazybones.lisp
index e9adc03..97c7d40 100644
--- a/lazybones.lisp
+++ b/src/lazybones.lisp
@@ -1,4 +1,4 @@
-;; Copyright (C) 2022 Colin Okay
+;; Copyright (C) 2022 colin@cicadas.surf
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Affero General Public License as
diff --git a/macros.lisp b/src/macros.lisp
index 46ac4da..0d941b6 100644
--- a/macros.lisp
+++ b/src/macros.lisp
@@ -1,4 +1,4 @@
-;; Copyright (C) 2022 Colin Okay
+;; Copyright (C) 2022 colin@cicadas.surf
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Affero General Public License as
diff --git a/package.lisp b/src/package.lisp
index 4ed5cdf..04cc5bf 100644
--- a/package.lisp
+++ b/src/package.lisp
@@ -2,7 +2,7 @@
;; any backend must implement functions for these
;; use the hunchentoot backend as a reference
-(defpackage #:lazybones.backend
+(defpackage #:lazybones-backend
(:export
;; request functions
#:request-url
@@ -39,7 +39,7 @@
;; the symbols exported here are available for end users to use in the
;; building of their apps
(defpackage #:lazybones
- (:use #:cl #:lazybones.backend)
+ (:use #:cl #:lazybones-backend)
(:local-nicknames (#:a #:alexandria)
(#:re #:cl-ppcre))
(:export