-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
131 lines (107 loc) · 3.37 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
130
131
'use strict';
var JSONScript = require('jsonscript-js')
, request = require('request')
, Ajv = require('ajv')
, defineKeywords = require('ajv-keywords')
, _ = require('lodash')
, optionsSchema = require('./config_schema.json')
, validateOptions = getValidator();
module.exports = jsonscriptProxy;
var METHODS = ['get', 'post', 'put', 'delete'];
function jsonscriptProxy(options, js) {
if (!validateOptions(options)) {
console.log('Invalid options:\n', validateOptions.errors);
throw new Error('Invalid options');
}
js = js || new JSONScript(options.jsonscript || { strict: true });
for (var name in options.services)
js.addExecutor(name, getExecutor(name, options.services[name]));
evaluator.js = js;
return evaluator;
function evaluator(req, res) {
var script = req.body.script;
var data = req.body.data;
var valid = js.validate(script);
if (valid) {
js.evaluate(script, data)
.then(function (value) {
res.json(value);
}, function (err) {
res.status(err.errors ? 400 : err.statusCode || 500)
.send({
error: err.message,
errors: err.errors
});
});
} else {
res.status(400)
.send({
error: 'script is invalid',
errors: js.validate.errors
});
}
}
function getExecutor(serviceName, service) {
var processResponse = processResponseFunc(service.processResponse || options.processResponse);
addExecutorMethods();
var serviceInfo = {
name: serviceName,
basePath: service.basePath
};
return execRouter;
function execRouter(args) {
var opts = {
uri: service.basePath + args.path,
headers: args.headers,
json: args.body || true
};
return new (options.Promise || Promise)(function (resolve, reject) {
request[args.method](opts, function (err, resp) {
if (err) return reject(err);
try { resolve(processResponse(resp, args, serviceInfo)); }
catch(e) { reject(e); }
});
});
}
function addExecutorMethods() {
METHODS.forEach(function (method) {
execRouter[method] = function(args) {
if (args.method && args.method != method) {
console.warn('method specified in args (' + args.method +
') is different from $method in instruction (' + method + '), used ' + method);
}
args.method = method;
return execRouter(args);
};
});
}
}
}
function getValidator() {
var ajv = Ajv({ allErrors: true });
defineKeywords(ajv, 'typeof');
return ajv.compile(optionsSchema);
}
function processResponseFunc(processResponse) {
return processResponse == 'body'
? bodyProcessResponse
: typeof processResponse == 'function'
? processResponse
: defaultProcessResponse;
}
function bodyProcessResponse(resp) {
if (resp.statusCode < 300) return resp.body;
throw new HttpError(resp);
}
function defaultProcessResponse(resp, args, service) {
resp = _.pick(resp, 'statusCode', 'headers', 'body');
resp.service = service;
resp.request = args;
return resp;
}
function HttpError(resp) {
this.message = resp.body ? JSON.stringify(resp.body) : 'Error';
this.statusCode = resp.statusCode;
}
HttpError.prototype = Object.create(Error.prototype);
HttpError.prototype.constructor = HttpError;