This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.7 KiB
167 lines
5.7 KiB
'use strict'; |
|
|
|
var errors = require('./errors.js'), |
|
isFunction = require('lodash/isFunction'), |
|
isObjectLike = require('lodash/isObjectLike'), |
|
isString = require('lodash/isString'), |
|
isUndefined = require('lodash/isUndefined'); |
|
|
|
|
|
module.exports = function (options) { |
|
|
|
var errorText = 'Please verify options'; // For better minification because this string is repeating |
|
|
|
if (!isObjectLike(options)) { |
|
throw new TypeError(errorText); |
|
} |
|
|
|
if (!isFunction(options.PromiseImpl)) { |
|
throw new TypeError(errorText + '.PromiseImpl'); |
|
} |
|
|
|
if (!isUndefined(options.constructorMixin) && !isFunction(options.constructorMixin)) { |
|
throw new TypeError(errorText + '.PromiseImpl'); |
|
} |
|
|
|
var PromiseImpl = options.PromiseImpl; |
|
var constructorMixin = options.constructorMixin; |
|
|
|
|
|
var plumbing = {}; |
|
|
|
plumbing.init = function (requestOptions) { |
|
|
|
var self = this; |
|
|
|
self._rp_promise = new PromiseImpl(function (resolve, reject) { |
|
self._rp_resolve = resolve; |
|
self._rp_reject = reject; |
|
if (constructorMixin) { |
|
constructorMixin.apply(self, arguments); // Using arguments since specific Promise libraries may pass additional parameters |
|
} |
|
}); |
|
|
|
self._rp_callbackOrig = requestOptions.callback; |
|
requestOptions.callback = self.callback = function RP$callback(err, response, body) { |
|
plumbing.callback.call(self, err, response, body); |
|
}; |
|
|
|
if (isString(requestOptions.method)) { |
|
requestOptions.method = requestOptions.method.toUpperCase(); |
|
} |
|
|
|
requestOptions.transform = requestOptions.transform || plumbing.defaultTransformations[requestOptions.method]; |
|
|
|
self._rp_options = requestOptions; |
|
self._rp_options.simple = requestOptions.simple !== false; |
|
self._rp_options.resolveWithFullResponse = requestOptions.resolveWithFullResponse === true; |
|
self._rp_options.transform2xxOnly = requestOptions.transform2xxOnly === true; |
|
|
|
}; |
|
|
|
plumbing.defaultTransformations = { |
|
HEAD: function (body, response, resolveWithFullResponse) { |
|
return resolveWithFullResponse ? response : response.headers; |
|
} |
|
}; |
|
|
|
plumbing.callback = function (err, response, body) { |
|
|
|
var self = this; |
|
|
|
var origCallbackThrewException = false, thrownException = null; |
|
|
|
if (isFunction(self._rp_callbackOrig)) { |
|
try { |
|
self._rp_callbackOrig.apply(self, arguments); // TODO: Apply to self mimics behavior of request@2. Is that also right for request@next? |
|
} catch (e) { |
|
origCallbackThrewException = true; |
|
thrownException = e; |
|
} |
|
} |
|
|
|
var is2xx = !err && /^2/.test('' + response.statusCode); |
|
|
|
if (err) { |
|
|
|
self._rp_reject(new errors.RequestError(err, self._rp_options, response)); |
|
|
|
} else if (self._rp_options.simple && !is2xx) { |
|
|
|
if (isFunction(self._rp_options.transform) && self._rp_options.transform2xxOnly === false) { |
|
|
|
(new PromiseImpl(function (resolve) { |
|
resolve(self._rp_options.transform(body, response, self._rp_options.resolveWithFullResponse)); // transform may return a Promise |
|
})) |
|
.then(function (transformedResponse) { |
|
self._rp_reject(new errors.StatusCodeError(response.statusCode, body, self._rp_options, transformedResponse)); |
|
}) |
|
.catch(function (transformErr) { |
|
self._rp_reject(new errors.TransformError(transformErr, self._rp_options, response)); |
|
}); |
|
|
|
} else { |
|
self._rp_reject(new errors.StatusCodeError(response.statusCode, body, self._rp_options, response)); |
|
} |
|
|
|
} else { |
|
|
|
if (isFunction(self._rp_options.transform) && (is2xx || self._rp_options.transform2xxOnly === false)) { |
|
|
|
(new PromiseImpl(function (resolve) { |
|
resolve(self._rp_options.transform(body, response, self._rp_options.resolveWithFullResponse)); // transform may return a Promise |
|
})) |
|
.then(function (transformedResponse) { |
|
self._rp_resolve(transformedResponse); |
|
}) |
|
.catch(function (transformErr) { |
|
self._rp_reject(new errors.TransformError(transformErr, self._rp_options, response)); |
|
}); |
|
|
|
} else if (self._rp_options.resolveWithFullResponse) { |
|
self._rp_resolve(response); |
|
} else { |
|
self._rp_resolve(body); |
|
} |
|
|
|
} |
|
|
|
if (origCallbackThrewException) { |
|
throw thrownException; |
|
} |
|
|
|
}; |
|
|
|
plumbing.exposePromiseMethod = function (exposeTo, bindTo, promisePropertyKey, methodToExpose, exposeAs) { |
|
|
|
exposeAs = exposeAs || methodToExpose; |
|
|
|
if (exposeAs in exposeTo) { |
|
throw new Error('Unable to expose method "' + exposeAs + '"'); |
|
} |
|
|
|
exposeTo[exposeAs] = function RP$exposed() { |
|
var self = bindTo || this; |
|
return self[promisePropertyKey][methodToExpose].apply(self[promisePropertyKey], arguments); |
|
}; |
|
|
|
}; |
|
|
|
plumbing.exposePromise = function (exposeTo, bindTo, promisePropertyKey, exposeAs) { |
|
|
|
exposeAs = exposeAs || 'promise'; |
|
|
|
if (exposeAs in exposeTo) { |
|
throw new Error('Unable to expose method "' + exposeAs + '"'); |
|
} |
|
|
|
exposeTo[exposeAs] = function RP$promise() { |
|
var self = bindTo || this; |
|
return self[promisePropertyKey]; |
|
}; |
|
|
|
}; |
|
|
|
return plumbing; |
|
|
|
};
|
|
|