-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClient.js
105 lines (97 loc) · 3.26 KB
/
Client.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
'use strict'
const attach = require('farnsworth-attach')
const aws4 = require('aws4')
const request = require('request')
/**
* @typedef CallResult
*
* Map of CallResultArrays for the associated calls
*/
/**
* @typedef CallResultArray
* @property 0 {object} Error object
* @property 1 {object} Data object
*/
/**
* @typedef CallStructure
*
* A structure with method names and their associated parameters.
*
* Each result is an CallResultArray for the associated call key.
*/
/**
* Client for JSON/REST/RPC over http with AWS4 signatures
*
* Traditionally making calls to JSON based servers involves way to much syntax. This client reduces the syntax to the
* bare minimum. You get a method name, parameter object, and a result or error structure. Servers where the http body
* is processed as a JSON object are supported.
* <p>
* If desired you can sign your requests by including AWS keys.
*
* @example
*
* const client = new Client('api.moarhealth.com')
* client.call({
* greeting: "Mark"
* initialize: { "some": "stuff" }
* }).then(results => {
* console.log(`Result for greeting was ${results.greeting}`)
* console.log(`Result for initialize was ${results.initialize}`)
* })
*/
class Client {
/**
* Create client for a host
*
* @example
* const client = new Client('api.moarhealth.com', {
* "accessKeyId": "XXXXXXXXXXXXXXXXXXXX",
* "secretAccessKey": "XXXXXXXX/XXXXXXXXXXXXXXXXXXXX"
* })
*
* @param host {string} Host name
* @param keys {Credentials} Optional credentials for AWS4 signing
*/
constructor(host, keys) { client(this, host, keys) }
/**
* Call one or more methods
*
* @param structures {CallStructure} Structure for the calls the client will make.
* @returns A promise to produce {CallResult}
*/
call(structures) {}
}
module.exports = Client
function client(T, host, keys) {
attach(T, function call(structures) {
return new Promise((resolve, reject) => {
const results = {}, methods = Object.keys(structures)
let errorCount = 0, resultCount = 0
for(let method of methods) {
const params = structures[method]
const signingFn = keys
? aws4.sign
: (o, k) => { return o}
const baseUrl = host === 'localhost'
? `http://${host}:3000`
: `https://${host}`
const options = signingFn({
method: 'POST', service: 'execute-api',
headers: {'content-type': 'application/json', Host: host},
path: method, url: `${baseUrl}/${method}`, json: true,
body: JSON.stringify(params)
}, keys)
options.body = params
request(options, (err, res, result) => {
if(err) {
errorCount++
}
results[method] = { err: err, data: result }
if(++resultCount == methods.length) {
return (errorCount ? reject : resolve)(results)
}
})
}
})
})
}