Dynamic, schema-less, directive-driven GraphQL
MIT License
dynamic, schema-less, directive-driven GraphQL
npm install graphql-dynamic
import createLoader from 'graphql-dynamic'
const loader = createLoader()
const query = `
{
test @create(value: 1)
}
`
const result = await loader.load(query) // output: { errors: [], infos: [], data: { test: 1 } }
use
{
# @create use use b
a @create(b: 1, use: "{ value: b }")
}
{
testUrlString @post(url: "http://example.com/api/name?a=1&b=2")
testUrlObject
@post(
url: { host: "example.com", pathanme: "/api/name", query: { a: 1, b: 2 } }
)
}
headers [[key, value]] { [key]: value }
graphql key json
{
test
@post(
options: {
headers: [
["Content-Type", "application/json"]
["Accept", "application/json"]
]
}
)
}
post
{
test
@post(
url: "/my/api"
data: { a: 1, b: 2 }
options: {
headers: [
["Content-Type", "application/json"]
["Accept", "application/json"]
]
}
bodyType: "json"
responseType: "json"
)
}
post Promise.all
get
querystring
url ?{
test
@get(
url: "/my/api"
query: { a: 1, b: 2 }
options: {
headers: [
["Content-Type", "application/json"]
["Accept", "application/json"]
]
}
bodyType: "json"
responseType: "json"
)
}
get Promise.all
querystring
url ?fetch
{
test
@fetch(
url: "/my/api"
options: {
method: "POST"
body: { a: 1, b: 2 }
headers: [
["Content-Type", "application/json"]
["Accept", "application/json"]
]
}
bodyType: "json"
responseType: "json"
)
}
value
{
number @create(value: 1)
string @create(value: "1")
object @create(value: { a: 1, b: 2 })
array @create(value: [{ a: 1 }, { b: 2 }])
}
{
number: 1,
string: '1',
object: { a: 1, b: 2 }
array: [{ a: 1 }, {b: 2}]
}
graphql
name fieldName
{
a @create(value: 1) @variable # a
b @create(value: $a) @variable(name: "c") # a b c
c @create(value: $c) # b c
}
to js context
{
a @create(value: 1) @map(to: "a + b", b: 1) # a 2
objcet @create(value: { a: 1, b: 2 }) @map(to: "{ a: a + 1, b: b + n }", n: 1) # object { a: 2, b: 3 }
array @create(value: [{ a: 1 }, { a: 2 }]) @map(to: "{ a: a + 1 }") # array [{ a: 2 }, { a: 3 }]
}
if js context
{
a @create(value: 1) @filter(if: "a > 1") # a
b @create(value: 1) @filter(if: "b === 1") # b 1
objcet @create(value: { a: 1, b: 2 }) @filter(if: "b <= n", n: 2) # object { a: 1, b: 2 }
array @create(value: [{ a: 1 }, { a: 2 }]) @filter(if: "a < 2") # array [{ a: 1 }]
}
key
key key
{
a @create(value: { b: { c: { d: 1 } } }) @select(key: "d")
}
#
# {
# a: {
# d: 1
# }
# }
if js context
filter find
{
a @create(value: 1) @find(if: "a > 1") # a
b @create(value: 1) @find(if: "b === 1") # b 1
objcet @create(value: { a: 1, b: 2 }) @find(if: "b <= n", n: 2) # object { a: 1, b: 2 }
array @create(value: [{ a: 1 }, { a: 2 }]) @find(if: "a < 2") # array { a: 1 }
}
object
{
a @extend(b: 1, c: 2) # a { b: 1, c: 2 }
b @create(value: { b: 0, d: 3 }) @extend(b: 1, c: 2) # b { b: 1, c: 2, d: 3 }
c @create(value: [{ b: 0, d: 3 }, { b: -1, d: 4 }]) @extend(b: 1, c: 2) # c [{ b: 1, c: 2, d: 3 }, { b: 1, c: 2, d: 4 }]
}
value
{
a @prepend(value: 1)
b @prepend(value: "1")
c @prepend(value: [1, 2])
d @prepend(value: { value: 1 })
}
#
# {
# a: [1],
# b: ['1'],
# c: [1, 2],
# d: [{ value: 1 }]
# }
{
a @create(value: 0) @prepend(value: 1)
b @create(value: "0") @prepend(value: "1")
c @create(value: 0) @prepend(value: [1, 2])
d @create(value: { value: 0 }) @prepend(value: { value: 1 })
e @create(value: [0, 1, 2]) @prepend(value: [3, 4, 5])
}
#
# {
# a: [1, 0],
# b: ['1', '0'],
# c: [1, 2, 0],
# d: [{ value: 1 }, { value: 0 }],
# e: [3, 4, 5, 0, 1, 2]
# }
value @prepend
graphql-dynamic graphql-anywhere api graphql-anywhere
createLoader graphql loader
config
loader
loader.load loader.use loader.load loader.use
import createLoader from 'graphql-dynamic'
const loader = createLoader({
variableTimeout: 3000,
fetchTimeout: 3000
})
loader.use(async (ctx, next) => {
let start = Date.now()
await next()
console.log('time', Date.now() - start)
})
const result = await loader.load(`{ test @create(value: 1) }`)
// { errors: [], logs: [], data: { test: 1 }}
ctx.directive
@date
const moment = require('moment')
// @date(format, i18n) moment
loader.use((ctx, next) => {
// @date
ctx.directive('date', params => {
if (!/number|string/.test(typeof ctx.result)) {
return
}
let { format = 'YYYY/MM/DD', i18n = 'zh-cn' } = params
let local = moment(ctx.result)
if (i18n) local.locale(i18n)
ctx.result = local.format(format)
})
return next()
})
createGraphql(config) expressjs
config createLoader config graphql-playground
/graphql
import createGraphql from 'graphql-dynamic/express'
const express = require('express')
const app = express()
const playground = {
'general.betaUpdates': false,
'editor.cursorShape': 'line', // possible values: 'line', 'block', 'underline'
'editor.fontSize': 14,
'editor.fontFamily': `'Source Code Pro', 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace`,
'editor.theme': 'light', // possible values: 'dark', 'light'
'editor.reuseHeaders': true, // new tab reuses headers from last tab
'request.credentials': 'omit', // possible values: 'omit', 'include', 'same-origin'
'tracing.hideTracingResponse': true
}
const endpoint = '/graphql'
const router = createGraphql({ endpoint, playground })
app.use(endpoint, router)
// router.loader loader