(defpackage #:weekend.client.ps (:use #:cl) (:import-from #:flatbind #:do>) (:local-nicknames (#:wknd #:weekend) (#:a #:alexandria-2)) (:export #:generate)) (in-package #:weekend.client.ps) ;; this function largely mirrors the implementation of construct-route-builder (defun generate (class &optional alt-name) (when (symbolp class) (setf class (find-class class))) (let* ((args (mapcar (a:compose #'intern #'string) (wknd:class-initargs class))) (parts (loop :for part :in (wknd:route-builder-parts class) :when (or (stringp part) (characterp part)) :collect part :else :collect (intern (string part)))) (method (wknd:request-method class)) (body (when (wknd:body-expected-p method) `(ps:chain -J-S-O-N (stringify (ps:create ,@(loop :for arg :in args :collect arg :collect arg)))))) (url-param-names (unless (wknd:body-expected-p method) (set-difference args parts :test 'eq))) (url-params (when url-param-names (cons "?" (loop :for (param . more) :on url-param-names :collect (string param) :collect "=" :collect param :when more :collect "&"))))) `(defun ,(or alt-name (class-name class)) ,args (ps:chain (fetch (+ "" ,@parts ,@url-params) (ps:create method ,(string method) cache "no-cache" ,@(when (wknd:body-expected-p method) `(headers (ps:create "Content-Type" "application/json"))) redirect "follow" ,@(when body (list 'body body)))) (then (lambda (resp) (and resp (= 200 (ps:@ resp status)) (ps:chain resp (json)))))))))