homebridge-hatch-baby-rest
Version:
Homebridge plugin for Hatch Rest/Restore WiFi sound machines
104 lines (103 loc) • 3.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RestClient = void 0;
exports.apiPath = apiPath;
exports.requestWithRetry = requestWithRetry;
const util_1 = require("../shared/util");
const apiBaseUrl = 'https://prod-sleep.hatchbaby.com/', defaultRequestOptions = {
method: 'GET',
}, defaultHeaders = {
USER_AGENT: 'hatch_rest_api',
'content-type': 'application/json',
};
function apiPath(path) {
return apiBaseUrl + path;
}
async function requestWithRetry(options) {
try {
const optionsWithDefaults = {
...defaultRequestOptions,
...options,
headers: {
...defaultHeaders,
...options.headers,
},
};
if (options.json) {
optionsWithDefaults.body = JSON.stringify(options.json);
}
const response = await fetch(new Request(options.url, optionsWithDefaults));
if (!response.ok) {
const errorWithResponse = new Error(`Failed to fetch ${options.url}. Response: ${response.status} ${response.statusText}. ${await response.text()}`);
errorWithResponse.response = response;
throw errorWithResponse;
}
const responseJson = await response.json();
return responseJson;
}
catch (e) {
if (!e.response) {
(0, util_1.logError)(`Failed to reach Hatch Baby server at ${options.url}. ${e.message}. Trying again in 5 seconds...`);
await (0, util_1.delay)(5000);
return requestWithRetry(options);
}
throw e;
}
}
class RestClient {
constructor(authOptions) {
this.authOptions = authOptions;
this.loginPromise = this.logIn();
}
async logIn() {
try {
const resp = await requestWithRetry({
url: apiPath('public/v1/login'),
json: {
email: this.authOptions.email,
password: this.authOptions.password,
},
method: 'POST',
});
return resp;
}
catch (requestError) {
const errorMessage = 'Failed to fetch oauth token from Hatch Baby. Verify that your email and password are correct.';
(0, util_1.logError)(requestError.response || requestError);
(0, util_1.logError)(errorMessage);
throw new Error(errorMessage);
}
}
refreshAuth() {
this.loginPromise = this.logIn();
}
async request(options) {
try {
const loginResponse = await this.loginPromise, headers = {
...options.headers,
'X-HatchBaby-Auth': loginResponse.token,
}, response = await requestWithRetry({
...options,
headers,
});
return response.payload;
}
catch (e) {
const response = e.response || {}, { url } = options;
if (response.status === 401) {
this.refreshAuth();
return this.request(options);
}
if (response.status === 404 && url.startsWith(apiBaseUrl)) {
(0, util_1.logError)('404 from endpoint ' + url);
throw new Error('Not found with response: ' + JSON.stringify(response.data));
}
(0, util_1.logError)(`Request to ${url} failed`);
throw e;
}
}
getAccount() {
return this.loginPromise.then((l) => l.payload);
}
}
exports.RestClient = RestClient;