A Common Lisp client library for the Pantry JSON storage service.
Pantry, stores JSON data in objects which it calls baskets
.
You can store JSON data in them like so:
CL-USER> (pantry:create-basket *client* "user-settings"
'(("theme" . "dark")
("language" . "en")
("notifications" . t)
("user-id" . 12345)))
"Your Pantry was updated with basket: user-settings!"
Or get the data out:
(pantry:get-basket *client* "user-settings")
;; => a hash-table
You can also update your basket:
(pantry:update-basket *client* "user-settings"
'(("theme" . "light")
("last-login" . "2023-12-01")))
;; => merged basket contents as a hash-table
which merges your existing data with the new data.
Or you can delete it:
(pantry:delete-basket *client* "user-settings")
;; Returns: "user-settings was removed from your Pantry!"
The place where all these baskets sit within Pantry, the service, is called pantry, the object, which you can look up:
(pantry:get-pantry-details *client*)
To make it easier to work with data, You can pass many Common Lisp data structures and they’ll be converted to JSON automatically. Basket payloads must be JSON objects and you pass a non-object (like a list or vector), it is wrapped as {"value": ...} to satisfy the API.
(ql:quickload '(:dexador :com.inuoe.jzon))
Option A: Using ASDF (recommended)
;; Add the pantry directory to ASDF's search path
(push #P"/path/to/pantry/" asdf:*central-registry*)
;; Load the system
(asdf:load-system :pantry)
Option B: Manual loading
;; Single-file system: just load pantry.lisp
(load "/path/to/pantry/pantry.lisp")
Visit getpantry.cloud to get your free pantry ID.
(defparameter *client* (pantry:make-pantry-client "your-pantry-id-here"))
Get information about your pantry, including available baskets:
(pantry:get-pantry-details *client*)
;; => a hash-table mapping string keys to values
;; Example access:
(let ((details (pantry:get-pantry-details *client*)))
(gethash "baskets" details))
(let ((ht (make-hash-table :test 'equal)))
(setf (gethash :theme ht) :dark
(gethash "language" ht) "en"
(gethash 'notifications ht) t)
(pantry:create-basket *client* "ht-basket" ht))
(pantry:create-basket *client* "plist-basket"
'(:theme :dark :language "en" :notifications t))
(pantry:create-basket *client* "array-basket" #(1 2 3 4))
;; Sends {"value": [1,2,3,4]}
(pantry:create-basket *client* "list-basket" '(:a :b :c))
;; Sends {"value": ["a","b","c"]}
(pantry:create-basket *client* "pair-basket" '(foo . 42))
(pantry:create-basket *client* "nested"
'((user . ((id . 1) (name . "Ada")))
(prefs . (:theme :dark :langs #("en" "fr")))))
The library defines custom conditions for error handling:
;; Catch all pantry errors
(handler-case
(pantry:get-basket *client* "non-existent-basket")
(pantry:pantry-error (e)
(format t "Error: ~A~%" (pantry:pantry-error-message e))))
;; Catch HTTP-specific errors
(handler-case
(pantry:create-basket *client* "test" invalid-data)
(pantry:pantry-http-error (e)
(format t "HTTP ~A: ~A~%"
(pantry:pantry-http-error-status-code e)
(pantry:pantry-error-message e))))
pantry-client
- Main client structure containing pantry-id and base-url
make-pantry-client (pantry-id)
- Create a new client instanceget-pantry-details (client)
- Get pantry informationupdate-pantry-details (client &key name description)
- Update pantry metadatacreate-basket (client basket-name data)
- Create or replace a basketget-basket (client basket-name)
- Get basket contentsupdate-basket (client basket-name data)
- Update basket (merge)delete-basket (client basket-name)
- Delete a basket
BSD License