init
This commit is contained in:
commit
bc06ba5a1b
6 changed files with 201 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.qlot
|
53
README.md
Normal file
53
README.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
# microcms-lisp-sdk
|
||||
|
||||
microcms-lisp-sdk is a Common Lisp SDK for interacting with [microCMS](https://microcms.io) via its REST API. It provides macros to define client functions for both list and object type endpoints.
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
Before making API requests, set your API key and service domain:
|
||||
|
||||
```lisp
|
||||
(setf microcms:*api-key* "your-api-key")
|
||||
(setf microcms:*service-domain* "your-service-domain") ; e.g., "example" for example.microcms.io
|
||||
```
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
### List Type Endpoint
|
||||
|
||||
Use `define-list-client` macro to define functions for list-type content.
|
||||
|
||||
```lisp
|
||||
(microcms:define-list-client article)
|
||||
```
|
||||
This will generate the following functions:
|
||||
|
||||
| Function Name | Arguments | Description |
|
||||
|---------------|-----------|-------------|
|
||||
| `get-article-list` | (&optional `query`) | Get a list of articles. |
|
||||
| `get-article-list-detail` | (`id`, &optional `query`) | Get details of a specific article by ID. |
|
||||
| `create-article` | (`content`, &optional `query`) | Create a new article with the given content. |
|
||||
| `update-article` | (`id`, `content`) | Update an existing article by its ID with new content. |
|
||||
| `delete-article` | (`id`) | Delete an article by its ID. |
|
||||
|
||||
Note: query arguments should be provided as a property list (plist), where keys use kebab-case (e.g., `:draft-key`).
|
||||
|
||||
### Object Type Endpoint
|
||||
|
||||
Use `define-object-client` macro to define functions for object-type content.
|
||||
|
||||
```lisp
|
||||
(microcms:define-object-client profile)
|
||||
```
|
||||
|
||||
This will generate the following functions:
|
||||
|
||||
| Function Name | Arguments | Description |
|
||||
|---------------|-----------|-------------|
|
||||
| `get-profile-object` | () | Retrieve the profile object. |
|
||||
| `update-profile` | (`content`) | Update the content of the profile object. |
|
||||
|
||||
### 📄 License
|
||||
|
||||
MIT License
|
||||
© 2025 Akira Tempaku
|
8
microcms.asd
Normal file
8
microcms.asd
Normal file
|
@ -0,0 +1,8 @@
|
|||
(defsystem "microcms"
|
||||
:version "0.1.0"
|
||||
:description "microCMS Common Lisp SDK."
|
||||
:author "Akira Tempaku"
|
||||
:license "MIT"
|
||||
:class :package-inferred-system
|
||||
:pathname "src"
|
||||
:depends-on ("microcms/main"))
|
5
qlfile
Normal file
5
qlfile
Normal file
|
@ -0,0 +1,5 @@
|
|||
ql alexandria
|
||||
ql dexador
|
||||
ql jonathan
|
||||
ql quri
|
||||
ql kebab
|
24
qlfile.lock
Normal file
24
qlfile.lock
Normal file
|
@ -0,0 +1,24 @@
|
|||
("quicklisp" .
|
||||
(:class qlot/source/dist:source-dist
|
||||
:initargs (:distribution "https://beta.quicklisp.org/dist/quicklisp.txt" :%version :latest)
|
||||
:version "2024-10-12"))
|
||||
("alexandria" .
|
||||
(:class qlot/source/ql:source-ql
|
||||
:initargs (:%version :latest)
|
||||
:version "ql-2024-10-12"))
|
||||
("dexador" .
|
||||
(:class qlot/source/ql:source-ql
|
||||
:initargs (:%version :latest)
|
||||
:version "ql-2024-10-12"))
|
||||
("jonathan" .
|
||||
(:class qlot/source/ql:source-ql
|
||||
:initargs (:%version :latest)
|
||||
:version "ql-2020-09-25"))
|
||||
("quri" .
|
||||
(:class qlot/source/ql:source-ql
|
||||
:initargs (:%version :latest)
|
||||
:version "ql-2024-10-12"))
|
||||
("kebab" .
|
||||
(:class qlot/source/ql:source-ql
|
||||
:initargs (:%version :latest)
|
||||
:version "ql-2015-06-08"))
|
110
src/main.lisp
Normal file
110
src/main.lisp
Normal file
|
@ -0,0 +1,110 @@
|
|||
(defpackage #:microcms
|
||||
(:nicknames #:microcms/main)
|
||||
(:use #:cl)
|
||||
(:import-from #:alexandria
|
||||
#:alist-plist
|
||||
#:assoc-value
|
||||
#:remove-from-plist
|
||||
#:symbolicate)
|
||||
(:import-from #:jonathan
|
||||
#:to-json
|
||||
#:parse)
|
||||
(:import-from #:dexador
|
||||
#:request
|
||||
#:http-request-failed)
|
||||
(:import-from #:quri
|
||||
#:make-uri
|
||||
#:render-uri)
|
||||
(:import-from #:kebab
|
||||
#:to-camel-case)
|
||||
(:export #:*api-key*
|
||||
#:*service-domain*
|
||||
#:define-list-client
|
||||
#:define-object-client))
|
||||
(in-package #:microcms)
|
||||
|
||||
(defparameter *api-key* nil)
|
||||
(defparameter *service-domain* nil)
|
||||
|
||||
(defun %get-list (endpoint &optional query)
|
||||
(%request :get endpoint "" query))
|
||||
|
||||
(defun %get-list-detail (endpoint id &optional (query nil))
|
||||
(%request :get endpoint id query))
|
||||
|
||||
(defun %create (endpoint content &optional query)
|
||||
(let ((id (getf content :|id|))
|
||||
(pure-content (remove-from-plist content :|id|)))
|
||||
(if id
|
||||
(%put endpoint id pure-content)
|
||||
(%post endpoint pure-content query))))
|
||||
|
||||
(defun %put (endpoint id content &optional query)
|
||||
(%request :put endpoint id query content))
|
||||
|
||||
(defun %post (endpoint content &optional query)
|
||||
(%request :post endpoint "" query content))
|
||||
|
||||
(defun %update (endpoint id content)
|
||||
(%request :patch endpoint id nil content))
|
||||
|
||||
(defun %delete (endpoint id)
|
||||
(%request :delete endpoint id))
|
||||
|
||||
(defun %get-object (endpoint)
|
||||
(%request :get endpoint))
|
||||
|
||||
(defun %request (method endpoint &optional (path "") (query nil) (body nil))
|
||||
(let* ((url (%build-uri endpoint path query))
|
||||
(headers `(("X-MICROCMS-API-KEY" . ,*api-key*)
|
||||
("Content-Type" . "application/json"))))
|
||||
(format t "API request url: ~a~%" url)
|
||||
(handler-case
|
||||
(multiple-value-bind (resp-body status resp-headers)
|
||||
(request url
|
||||
:method method
|
||||
:headers headers
|
||||
:content (and body (to-json body))
|
||||
:force-binary nil)
|
||||
(format t "API response status: ~a~%" status)
|
||||
(when (and (stringp resp-body)
|
||||
(search "application/json" (gethash "content-type" resp-headers)))
|
||||
(parse resp-body)))
|
||||
(http-request-failed ()
|
||||
'(:|error| "API request failed")))))
|
||||
|
||||
(defun %build-uri (endpoint &optional (path "") (query nil))
|
||||
(let ((uri (make-uri
|
||||
:scheme "https"
|
||||
:host (format nil "~A.microcms.io" *service-domain*)
|
||||
:path (format nil "/api/v1/~A/~A" endpoint path)
|
||||
:query (%build-query query))))
|
||||
(render-uri uri)))
|
||||
|
||||
(defun %build-query (query)
|
||||
(loop :for (key val) :on query :by #'cddr
|
||||
:collect (cons (to-camel-case (symbol-name key)) val)))
|
||||
|
||||
(defmacro define-list-client (endpoint)
|
||||
(let ((str-endpoint (string-downcase (string endpoint))))
|
||||
`(progn
|
||||
(defun ,(symbolicate 'get- endpoint '-list) (&optional query)
|
||||
(%get-list ,str-endpoint query))
|
||||
(defun ,(symbolicate 'get- endpoint '-list-detail) (id &optional query)
|
||||
(%get-list-detail ,str-endpoint id query))
|
||||
(defun ,(symbolicate 'create- endpoint) (content &optional query)
|
||||
(%create ,str-endpoint content query))
|
||||
(defun ,(symbolicate 'update- endpoint) (id content)
|
||||
(%update ,str-endpoint id content))
|
||||
(defun ,(symbolicate 'delete- endpoint) (id)
|
||||
(%delete ,str-endpoint id))
|
||||
nil)))
|
||||
|
||||
(defmacro define-object-client (endpoint)
|
||||
(let ((str-endpoint (string-downcase (string endpoint))))
|
||||
`(progn
|
||||
(defun ,(symbolicate 'get- endpoint '-object) ()
|
||||
(%get-object ,str-endpoint))
|
||||
(defun ,(symbolicate 'update- endpoint) (content)
|
||||
(%update ,str-endpoint nil content))
|
||||
nil)))
|
Loading…
Add table
Reference in a new issue