-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.mjs
125 lines (95 loc) · 2.39 KB
/
client.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import _debug from './debug.mjs'
import { debounceWithIndex } from './debounce.mjs'
import { FurverInvalidSchemaError } from './error.mjs'
const schemaSymbol = Symbol('schema')
const debug = _debug.extend('client')
const bulk = fetchFn => debounceWithIndex(calls => {
const [[url, options]] = calls
const payload = ['array', ...calls.map(([, { body }]) => body)]
const body = JSON.stringify(payload)
const config = {
...options,
body
}
debug(url, config)
return fetchFn(url, config)
})
const post = bulk(async (url, options) => {
const res = await fetch(url, {
credentials: 'include',
...options,
method: 'post'
})
if (!res.ok) {
throw res
}
const json = await res.json()
return json
})
const get = bulk(async (url, argOptions) => {
const { body, ...options } = argOptions || {}
const search = new URLSearchParams({ body })
const fullUrl = new URL(url)
fullUrl.search = search
const res = await fetch(fullUrl.toString(), {
credentials: 'include',
...options
})
if (!res.ok) {
throw res
}
const json = await res.json()
return json
})
client.schema = async function furverClientSchema (url) {
debug(`fetching schema from ${url}`)
const schemaRes = await fetch(url)
return await schemaRes.json()
}
const isFunction = x => typeof x === 'function'
const castFunction = x => isFunction(x) ? x : () => x
async function client ({
endpoint = 'http://localhost:3000',
fetch = post,
schema = client.schema
}) {
const api = {}
const assignMethods = (schema) => {
api[schemaSymbol] = schema
if (!Array.isArray(schema)) {
throw new FurverInvalidSchemaError('Not a valid schema')
}
return schema.reduce((api, [name]) => {
api[name] = (...args) => fetch(endpoint, {
body: [name, ...args]
})
api[name].toJSON = () => ['ref', name]
return api
}, api)
}
debug('client initialized with endpoint', endpoint)
// You can also unset the default schema fetching if you wich not to have the
// API populated.
if (schema) {
assignMethods(await castFunction(schema)(endpoint === '/'
? '/schema'
: `${endpoint}/schema`
))
}
api.call = body => fetch(endpoint, {
body
})
api.call.toJSON = () => ['ref', 'call']
return api
}
function schema (api) {
return api[schemaSymbol]
}
export default client
export {
client,
schema,
bulk,
get,
post
}