aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Okay <okay@toyful.space>2022-02-08 08:24:27 -0600
committerColin Okay <okay@toyful.space>2022-02-08 08:24:27 -0600
commitf37b6e61cbebab71424ae9561cd5932776c952d9 (patch)
treebae7064f68458133d8a35a9480eaa0f303095c6b
parent4a10c2df8ba3097af9bf34f19c12186d63ca831a (diff)
added support for basic documentation of apps
-rw-r--r--lazybones-documentation.lisp43
-rw-r--r--lazybones.asd3
-rw-r--r--lazybones.lisp33
-rw-r--r--package.lisp1
4 files changed, 72 insertions, 8 deletions
diff --git a/lazybones-documentation.lisp b/lazybones-documentation.lisp
new file mode 100644
index 0000000..bb94515
--- /dev/null
+++ b/lazybones-documentation.lisp
@@ -0,0 +1,43 @@
+;;;; lazybones-documentation.lisp -- documenting APP instances
+
+(in-package :lazybones)
+
+(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."
+ (symbol-macrolet ((newline (progn (princ #\newline)(princ #\newline))))
+ (with-slots
+ (title
+ version
+ endpoints
+ (default-authorizer authorizer)
+ default-content-type
+ app-error-response-contents
+ description)
+ app
+ (with-output-to-string (*standard-output*)
+ (princ "# ") (princ title) (princ " - ") (princ "v") (princ version)
+ newline
+ (princ description)
+ newline
+ (princ "## Endpoints")
+ (dolist (ep (sorted-endpoints endpoints))
+ (with-slots (method route authorizer endpoint-documentation) ep
+ newline
+ (princ "### ") (princ method) (princ " ") (princ route)
+ newline
+ (when authorizer
+ (princ "Authorization Required: ")
+ (cond ((function-or-function-name-p authorizer)
+ (princ (documentation authorizer 'function)))
+ ((function-or-function-name-p default-authorizer)
+ (princ (documentation default-authorizer 'function))))
+ newline)
+
+ (princ endpoint-documentation) ))))))
+
+(defun function-or-function-name-p (thing)
+ (or (functionp thing)
+ (and (symbolp thing) (fboundp thing))))
diff --git a/lazybones.asd b/lazybones.asd
index 3a1326c..7ed7adf 100644
--- a/lazybones.asd
+++ b/lazybones.asd
@@ -13,5 +13,6 @@
#:jonathan
#:lisp-namespace)
:components ((:file "package")
- (:file "lazybones")))
+ (:file "lazybones")
+ (:file "lazybones-documentation")))
diff --git a/lazybones.lisp b/lazybones.lisp
index 45da60b..8e1228b 100644
--- a/lazybones.lisp
+++ b/lazybones.lisp
@@ -30,6 +30,18 @@
:initarg :name
:initform (error "Appname is required")
:type symbol)
+ (title
+ :accessor app-title
+ :initarg :title
+ :initform ""
+ :type string
+ :documentation "A string title")
+ (description
+ :accessor app-description
+ :initarg :description
+ :initform ""
+ :type string
+ :documentation "A string describing the app")
(version
:reader app-version
:initarg :vsn :initarg :version
@@ -65,8 +77,13 @@
(defmethod initialize-instance :after ((app app) &key)
(setf (symbol-lazybones (app-name app)) app))
-(defun app (name)
- (symbol-lazybones name nil))
+(defun app (&optional name)
+ "Get the APP instance named by the symbol NAME. If NAME is not
+supplied, get the default app. Every package has at most one default
+app, named with the package name."
+ (symbol-lazybones (or name
+ (intern (package-name *package*) *package*))
+ nil))
(defclass endpoint ()
((method
@@ -237,8 +254,9 @@ applying HANDLER-FUNCTION slot of ENDPOINT to the ARGS list."
(let ((*request* request)
(*response* response)
(*app* app))
- (when (request-authorized-p endpoint)
- (apply (endpoint-request-handler endpoint) args))))
+ (if (request-authorized-p endpoint)
+ (apply (endpoint-request-handler endpoint) args)
+ (http-err 404))))
(defun request-authorized-p (endpoint)
"Attempts to authorize an endpoint.
@@ -254,9 +272,10 @@ authorizer is used.
Hence, if the endpoint authorizer is T and the app doesn't have an
authorizer, then, the endpoint wants to be authorized but there isn't
any way to do it, hence NIL is returned."
- (a:if-let (specific-authorizer (request-authorizer endpoint))
- (if (functionp specific-authorizer)
- (funcall specific-authorizer)
+ (a:if-let (auth (request-authorizer endpoint))
+ (if (or (functionp auth)
+ (and (symbolp auth) (fboundp auth)))
+ (funcall auth)
(when (request-authorizer *app*) ; perhaps this should be an if, and
(funcall (request-authorizer *app*))))
t))
diff --git a/package.lisp b/package.lisp
index 6c90b5b..126c046 100644
--- a/package.lisp
+++ b/package.lisp
@@ -39,6 +39,7 @@
#:*app*
#:*request*
#:*response*
+ #:generate-app-documentation
#:app
#:create-server
#:defendpoint