[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/graphql b0bd6c5fd8 02/56: Create DSL and basic encoder
From: |
ELPA Syncer |
Subject: |
[elpa] externals/graphql b0bd6c5fd8 02/56: Create DSL and basic encoder |
Date: |
Sat, 29 Oct 2022 13:57:51 -0400 (EDT) |
branch: externals/graphql
commit b0bd6c5fd85eb78bf3d95cf0b22907e56f769720
Author: Sean Allred <code@seanallred.com>
Commit: Sean Allred <code@seanallred.com>
Create DSL and basic encoder
---
.gitignore | 1 +
examples.el | 27 ++++++++++++
graphql.el | 106 ++++++++++++++++++++++++++++++++++++++++++++++++
test/graphql.el-test.el | 41 +++++++++++++++++++
4 files changed, 175 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..28f0a7dc05
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.cask/
diff --git a/examples.el b/examples.el
new file mode 100644
index 0000000000..5c48e8ca4b
--- /dev/null
+++ b/examples.el
@@ -0,0 +1,27 @@
+(require 'json)
+(require 'ghub)
+(require 'graphql)
+
+;;; The following functions create
+
+(defun ghubp--graphql-submit (type object)
+ (thread-last (graphql-encode object)
+ (cons type)
+ (list)
+ (json-encode)
+ (ghub-post "/graphql" nil)))
+(defun ghubp-graphql-query (query)
+ (ghubp--graphql-submit "query" (cons 'query query)))
+(defun ghubp-graphql-mutation (mutation)
+ (ghubp--graphql-submit "mutation" (cons 'mutation mutation)))
+
+;;; Begin examples
+
+(ghubp-graphql-query
+ ;; Get the first hundred issues from vermiculus/magithub
+ '((repository
+ :arguments ((owner . "vermiculus")
+ (name . "magithub"))
+ (issues :arguments ((first . 100))
+ (edges
+ (node number title url id))))))
diff --git a/graphql.el b/graphql.el
new file mode 100644
index 0000000000..ba1995139a
--- /dev/null
+++ b/graphql.el
@@ -0,0 +1,106 @@
+;;; graphql.el --- GraphQL utilities -*- lexical-binding: t;
-*-
+
+;; Copyright (C) 2017 Sean Allred
+
+;; Author: Sean Allred <code@seanallred.com>
+;; Keywords: hypermedia, tools, lisp
+;; Package-Version: 0
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Graphql.el provides a generally-applicable domain-specific language
+;; for creating and executing GraphQL queries against your favorite
+;; web services.
+
+;;; Code:
+
+(require 'pcase)
+
+(defun graphql--encode-atom (g)
+ (cond
+ ((stringp g)
+ g)
+ ((symbolp g)
+ (symbol-name g))
+ ((numberp g)
+ (number-to-string g))
+ ((and (consp g)
+ (not (consp (cdr g))))
+ (symbol-name (car g)))))
+(defun graphql--encode-list (l)
+ (when (and (consp l) (consp (car l)))
+ (mapconcat #'graphql--encode l " ")))
+(defun graphql--encode-parameter-pair (pair)
+ (graphql--encode-parameter (car pair) (cdr pair)))
+(defun graphql--encode-parameter (key value)
+ (format "%s:%s"
+ key
+ (cond
+ ((symbolp value)
+ (symbol-name value))
+ ((listp value)
+ (format "{%s}" (mapconcat #'graphql--encode-parameter-pair value
",")))
+ ((stringp value)
+ (format "\"%s\"" value))
+ ((numberp value)
+ value)
+ (t
+ (graphql--encode value)))))
+
+(defun graphql--get-keys (g)
+ (let (graph keys)
+ (while g
+ (if (keywordp (car g))
+ (let* ((param (pop g))
+ (value (pop g)))
+ (push (cons param value) keys))
+ (push (pop g) graph)))
+ (list keys (nreverse graph))))
+
+(defun graphql--encode (g)
+ "Encode G as a GraphQL string."
+ (or (graphql--encode-atom g)
+ (graphql--encode-list g)
+ (pcase (graphql--get-keys g)
+ (`(,keys ,graph)
+ (let ((root (car graph))
+ (name (alist-get :name keys))
+ (arguments (alist-get :arguments keys))
+ (rest (cdr graph)))
+ (concat
+ (symbol-name root)
+ (when arguments
+ ;; Format arguments "key:value, ..."
+ (format "(%s)"
+ (mapconcat #'graphql--encode-parameter-pair arguments
",")))
+ (when (or name rest) " ")
+ (when name
+ (format "%S ") name)
+ (when rest
+ (format "{ %s }"
+ (if (listp rest)
+ (mapconcat #'graphql--encode rest " ")
+ (graphql--encode rest))))))))))
+
+(defun graphql-encode (g)
+ "Encode G as a GraphQL string."
+ (let ((s (graphql--encode g)))
+ ;; clean up
+ (set-text-properties 0 (length s) nil s)
+ s))
+
+(provide 'graphql)
+;;; graphql.el ends here
diff --git a/test/graphql.el-test.el b/test/graphql.el-test.el
new file mode 100644
index 0000000000..31158630a1
--- /dev/null
+++ b/test/graphql.el-test.el
@@ -0,0 +1,41 @@
+;;; graphql.el-test.el --- Tests for graphql.el
+
+(ert-deftest encode-basic ()
+ (should (string= (graphql-encode
+ '(query
+ hello-world))
+ "query { hello-world }"))
+
+ (should (string= (graphql-encode
+ '(query
+ :arguments ((one . "1")
+ (two . "2"))
+ hello-world))
+ "query(one:\"1\",two:\"2\") { hello-world }")))
+
+(ert-deftest encode-recursive ()
+ (should (string= (graphql-encode
+ '(query
+ (repository
+ :arguments ((owner . "my-owner")
+ (name . "my-repo-name")))))
+ "query {
repository(owner:\"my-owner\",name:\"my-repo-name\") }"))
+
+ (should (string= (graphql-encode
+ '(query
+ (repository
+ :arguments ((owner . "my-owner")
+ (name . "my-repo-name"))
+ (issues
+ :arguments ((first . 20))
+ (edges (node number title url))))))
+ (concat
+ "query {
repository(owner:\"my-owner\",name:\"my-repo-name\") "
+ "{ issues(first:20) { edges { node { number title url } }
} } }")))
+
+ (should (string= (graphql-encode
+ '(addReaction :arguments ((input . ((subjectId .
"MDU6SXNzdWUxNzc2MzA3Mjk=")
+ (content . HOORAY))))))
+
"addReaction(input:{subjectId:\"MDU6SXNzdWUxNzc2MzA3Mjk=\",content:HOORAY})")))
+
+;;; graphql.el-test.el ends here
- [elpa] branch externals/graphql created (now 5ca5f50b5e), ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 1026c76d30 01/56: Initial commit, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 9d4179cd4a 04/56: Simplify handling of fields, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 335ec3a9c5 08/56: More appropriate function names for argument encoding, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql a8067839b6 10/56: Rename `graphql--encode-argument-pair' to `*-spec', ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 1f4f1a61c9 11/56: Remove graphql-encode and replace it with graphql--encode, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql adf95c1d92 16/56: Compress output, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql f9dc451ae6 18/56: Simplify object encoding, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 0756399fc9 22/56: Test unnamed query, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql b0bd6c5fd8 02/56: Create DSL and basic encoder,
ELPA Syncer <=
- [elpa] externals/graphql fcc32d3d71 03/56: Simplify handling of spacing optional elements, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 3bf43e2ad1 05/56: Use real names of things, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 24d278dd43 06/56: Add support for variables in object parameters, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 4d2837ddbe 07/56: Fix format bug for :name, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 210fed6a12 09/56: More appropriate name for `:name', ELPA Syncer, 2022/10/29
- [elpa] externals/graphql d299be77da 12/56: Tweak handling for numbers when encoding argument values., ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 08fb4fcf12 13/56: Add support for operation parameters via `:op-params', ELPA Syncer, 2022/10/29
- [elpa] externals/graphql da47d83cef 14/56: Add `graphql-{query, mutation}' macros, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql 22a84b1b08 15/56: Fix issue if `:op-name' and `:arguments' are given to one object, ELPA Syncer, 2022/10/29
- [elpa] externals/graphql f43b1da554 17/56: Fix *-parameter-spec behavior when REQUIRED is omitted, ELPA Syncer, 2022/10/29