node-hue-api
Version:
Philips Hue API Library for Node.js
99 lines (98 loc) • 4.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transport = void 0;
const ApiError_1 = require("../../ApiError");
const util_1 = require("../../util");
const HueError_1 = require("../../HueError");
const HueRateLimiter_1 = require("../HueRateLimiter");
class Transport {
constructor(client, rateLimiterConfig, username) {
this._username = username;
this._client = client;
this._limiter = new HueRateLimiter_1.HueRateLimiter('', 'transport', rateLimiterConfig);
}
get limiter() {
return this._limiter;
}
/**
* Executes an API Endpoint Request.
* @param api The Api endpoint to perform a request against.
* @param parameters Any parameters specific to the request.
* @returns {Promise<any>} The promise for making the specified API request.
*/
execute(api, parameters) {
let self = this, limiter = this.limiter, client = self._client, requestParameters = Object.assign({ username: self._username }, parameters), promise;
if (!api) {
throw new Error('An API must be provided');
}
// @ts-ignore
promise = limiter.schedule(() => {
return client.request(api.getRequest(requestParameters));
})
.catch((err) => {
// @ts-ignore
throw extractError(err, err.response);
})
.then((res) => {
// Errors can be contained in the object payload from a successful response code.
const errors = (0, util_1.parseErrors)(res.data);
if (errors) {
throw new ApiError_1.ApiError(errors[0]);
}
return res.data;
});
if (api.getErrorHandler()) {
// @ts-ignore
promise = promise.catch(api.getErrorHandler());
}
const postProcessing = api.getPostProcessing();
if (postProcessing) {
// Inject the request parameters into the post processing function
promise = promise.then((result) => {
return postProcessing(result, requestParameters);
});
}
return promise;
}
refreshAuthorizationHeader(token) {
// Update the default common authorization header with the new bearer token
this._client.refreshAuthorizationHeader(`Bearer ${token}`);
}
}
exports.Transport = Transport;
/**
* Extracts an appropriate error from the provided details.
*
* @param {Error} err The captured Error.
* @param {Object} response The underlying transport HTTP response object.
* @returns {ApiError | HueError} The error extracted from the data provided
*/
function extractError(err, response) {
var _a, _b;
if (!response) {
//TODO fetch leaks the API key in the URL, need to redact it
const error = new ApiError_1.ApiError(err.message);
// Set the original stack trace here as the one for the error created is pretty much useless and obscures the real problem
error.stack = err.stack;
throw error;
}
const headers = response.headers, authenticateHeader = headers ? headers['www-authenticate'] : null;
let hueError;
if (authenticateHeader) {
const errorMatch = /error="(.*?)"/.exec(authenticateHeader), errorDescriptionMatch = /error_description="(.*?)"/.exec(authenticateHeader);
hueError = new HueError_1.HueError({
type: response.status,
message: (errorMatch ? errorMatch[1] : response.data) || 'Error',
description: errorDescriptionMatch ? errorDescriptionMatch[1] : undefined,
address: (_a = response.config) === null || _a === void 0 ? void 0 : _a.url,
});
}
else {
hueError = new HueError_1.HueError({
type: response.status,
message: response.data || 'Error',
address: (_b = response.config) === null || _b === void 0 ? void 0 : _b.url,
});
}
return new ApiError_1.ApiError(hueError);
}