forked from nordsimon/graphql-client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
129 lines (105 loc) · 3.05 KB
/
index.js
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
126
127
128
129
/* global fetch, Headers */
require('isomorphic-fetch')
function Client (options) {
var self = this
if (!options.url) throw new Error('Missing url parameter')
self.options = options
self.url = options.url
// A stack of registered listeners
self.listeners = []
}
// to reduce file size
var proto = Client.prototype
/**
* Send a query and get a Promise
* @param {String} query
* @param {Object} variables
* @param {Function} beforeRequest hook
* @returns {Promise}
*/
proto.query = function (query, variables, beforeRequest) {
var self = this
var req = self.options.request || {}
req.method || (req.method = 'POST')
if (!req.headers) {
req.headers = new Headers()
req.headers.set('content-type', 'application/json')
}
req.body = JSON.stringify({
query: query,
variables: variables
})
// 'beforeRequest' is a top priority per-query hook, it should forcibly
// override response even from other hooks.
var result = beforeRequest && beforeRequest(req)
if (typeof result === 'undefined') {
result = self.emit('request', req)
// No 'response' hook here, reserve it for real responses only.
// 'data' hook is only triggered if there are any data
if (typeof result !== 'undefined') {
var data = self.emit('data', result, true) // `true` for fake data
if (typeof data !== 'undefined') result = data
}
}
if (typeof result !== 'undefined') {
result = Promise.resolve(result)
}
return result || self.fetch(req)
}
/**
* For making requests
* @param {Object} req
* @returns Promise
*/
proto.fetch = function (req) {
var self = this
return fetch(self.url, req).then(function (res) {
// 'response' hook can redefine `res`
var _res = self.emit('response', res)
if (typeof _res !== 'undefined') res = _res
return res.json()
}).then(function (data) {
// 'data' hook can redefine `data`
var _data = self.emit('data', data)
if (typeof _data !== 'undefined') data = _data
return data
})
}
/**
* Register a listener.
* @param {String} eventName - 'request', 'response', 'data'
* @param {Function} callback
* @returns Client instance
*/
proto.on = function (eventName, callback) {
var allowedNames = ['request', 'response', 'data']
if (~allowedNames.indexOf(eventName)) {
this.listeners.push([ eventName, callback ])
}
return this
}
/**
* Emit an event.
* @param {String} eventName - 'request', 'response', 'data'
* @param {mixed} ...args
* @returns {Array} array of results received from each listener respectively
*/
proto.emit = function (eventName) {
var args = Array.prototype.slice.call(arguments, 1)
var listeners = this.listeners
var result
// Triggering listeners and gettings latest result
for (var i = 0; i < listeners.length; i++) {
if (listeners[i][0] === eventName) {
var r = listeners[i][1].apply(this, args)
if (typeof r !== 'undefined') {
result = r
}
}
}
return result
}
module.exports = function (options) {
return new Client(options)
}
module.exports.Client = Client