From 57afcdd8b437b3ca9b66126db966d07ed751ed15 Mon Sep 17 00:00:00 2001 From: colin Date: Sat, 4 May 2024 22:09:46 -0700 Subject: dropped defendpoint; added example --- src/defendpoint.lisp | 205 ++++++++++++++++++++++++++++++++++++++++++++++++ src/endpoint.lisp | 215 ++------------------------------------------------- 2 files changed, 212 insertions(+), 208 deletions(-) create mode 100644 src/defendpoint.lisp (limited to 'src') diff --git a/src/defendpoint.lisp b/src/defendpoint.lisp new file mode 100644 index 0000000..2e87874 --- /dev/null +++ b/src/defendpoint.lisp @@ -0,0 +1,205 @@ +;;; DEFENDPOINT + +(defun path-part-p (part) + "Returns T if PART is a a valid route path part. + +PART is either + STRING + (KEYWORD STRING) + (KEYWORD STRING FUNCTION-NAME)" + (or (stringp part) + (and (listp part) + (or (and (= 2 (length part)) + (do> + (key str) :match= part + :when (keywordp key) + :when (stringp str))) + (and (= 3 (length part)) + (do> + (key str parser) :match= part + :when (keywordp key) + :when (string str) + :when (symbolp parser) + (fboundp parser))))))) + +(defun parameter-spec-p (spec) + "Returns T if SPEC is a valid parameter spec for a DEFENDPOINT form. + +(NAME TYPE &OPTIONAL DOC)" + (and (listp spec) + (symbolp (first spec)) + (symbolp (second spec)) + (or (not (third spec)) + (stringp (third spec))))) + +(defun property-spec-p (spec) + "Returns T if SPEC is a valid property spec for a DEFENDPOINT form. + +(NAME TYPE &KEY DEFAULT DOC)" + (and (listp spec) + (symbolp (first spec)) + (symbolp (second spec)))) + +(defun params-to-slotdefs (specs) + (loop :for (name type . doc) :in specs + :collect `(,name + :accessor ,name + :initarg ,(a:make-keyword name) + :type ,type + :documentation ,(or (first doc) "")))) + +(defun props-to-slotdefs (specs) + (loop :for (name type . kwargs) :in specs + :collect `(,name + :accessor ,name + :initform ,(getf kwargs :default) + :type (or null ,type) + :documentation ,(or (getf kwargs :doc "") + (getf kwargs :documentation ""))))) + +(defun expand-endpoint-class + (name method pathspec handle return + &key + supers + parameters + properties + metaclass + var + documentation + authenticate + authorize) + (setf var (or var (gensym "REQ-"))) + (setf metaclass (or metaclass 'endpoint)) + (let* ((slot-defs + (nconc (params-to-slotdefs parameters) + (props-to-slotdefs properties))) + (all-slots + (nconc (mapcar #'first slot-defs) + (reduce #'union supers :key #'class-slot-names :initial-value nil))) + (route-parts + (loop :for part :in pathspec + :when (stringp part) + :collect part + :else + :collect (second part))) + (extractors + (loop :for part :in pathspec + :when (listp part) + :collect (if (third part) + (list (first part) (third part)) + (first part)))) + (class-options + (nconc + (list (list :metaclass metaclass)) + (list (cons :method method)) + (list (list* :route-parts route-parts)) + (list (cons :content-type return)) + (when extractors + (list (list* :extractors extractors))) + (when documentation + (list (list :documentation documentation)))))) + `(progn + (defclass ,name ,supers + ,slot-defs + ,@class-options) + + (defmethod handle ((,var ,name)) + (with-slots ,all-slots ,var + ,handle)) + + ,@(when authenticate + (list + `(defmethod authenticate ((,var ,name)) + (with-slots ,all-slots ,var + ,authenticate)))) + + ,@(when authorize + (list + `(defmethod authorize ((,var ,name)) + (with-slots ,all-slots ,var + ,authorize))))))) + +(argot:deflanguage defendpoint () + ( + :match (:seq (:@ name (:item)) + (:@ supers (:? )) + (:@ method ) + (:@ pathspec ) + (:@ return ) + (:@ params (:? )) + (:@ props (:? )) + (:@ options (:*