fitbit-api-client
Version:
## ⚠️ This SDK is not ready for production
288 lines • 11.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FitbitClient = void 0;
const apis_1 = require("./apis");
const constants_1 = require("./constants");
const oauth_utils_1 = require("./utils/oauth.utils");
class FitbitClient {
constructor({ clientId, clientSecret, token, session }) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.token = token;
this.session = session;
// 関数にbindを行い、thisを固定する
this.auth = {
setToken: this.setToken.bind(this),
getAccessToken: this.getAccessToken.bind(this),
refreshAccessToken: this.refreshAccessToken.bind(this),
isAccessTokenExpired: this.isAccessTokenExpired.bind(this),
};
this.oauth = {
createSession: this.createSession.bind(this),
getAuthorizationUrl: this.getAuthorizationUrl.bind(this),
setSession: this.setSession.bind(this),
handleOAuthCallback: this.handleOAuthCallback.bind(this),
};
this.profile = {
getProfileRaw: this.getProfileRaw.bind(this),
getProfile: this.getProfile.bind(this),
};
this.heartRate = {
getHeartRateIntraday: this.getHeartRateIntraday.bind(this),
getHeartRateIntradayRaw: this.getHeartRateIntradayRaw.bind(this),
};
this.activity = {
getStepsIntraday: this.getStepsIntraday.bind(this),
getStepsIntradayRaw: this.getStepsIntradayRaw.bind(this),
getCaloriesIntraday: this.getCaloriesIntraday.bind(this),
getCaloriesIntradayRaw: this.getCaloriesIntradayRaw.bind(this),
getDistanceIntradayRaw: this.getDistanceIntradayRaw.bind(this),
getElevationIntradayRaw: this.getElevationIntradayRaw.bind(this),
getFloorsIntradayRaw: this.getFloorsIntradayRaw.bind(this),
getSwimmingStrokesRaw: this.getSwimmingStrokesRaw.bind(this),
};
this.sleep = {
getSleepLog: this.getSleepLog.bind(this),
getSleepLogRaw: this.getSleepLogRaw.bind(this),
};
this.temperature = {
getTemperatureCoreSummaryRaw: this.getTemperatureCoreSummaryRaw.bind(this),
};
this.spO2 = {
getSpO2Intraday: this.getSpO2Intraday.bind(this),
getSpO2IntradayRaw: this.getSpO2IntradayRaw.bind(this),
};
this.body = {
getWeightLog: this.getWeightLog.bind(this),
getWeightLogRaw: this.getWeightLogRaw.bind(this),
};
}
/**
* セッションを作成する
*/
createSession(redirectUrl, usePkce = true) {
const state = (0, oauth_utils_1.generateState)();
const codeVerifier = (0, oauth_utils_1.generateCodeVerifier)();
this.session = {
state,
codeVerifier,
codeChallenge: usePkce ? (0, oauth_utils_1.generateCodeChallenge)(codeVerifier) : undefined,
challengeMethod: usePkce ? constants_1.CODE_CHALLENGE_METHOD : undefined,
redirectUrl: redirectUrl ?? undefined,
};
return this.session;
}
/**
* セッションを設定する
*/
setSession(session) {
this.session = session;
}
/**
* 認証URLを取得する
*/
getAuthorizationUrl(scopes) {
if (!this.session) {
throw new Error('createSession or setSession must be called before getAuthorizationUrl');
}
const { state, codeChallenge, challengeMethod, redirectUrl } = this.session;
const scope = scopes.join('+');
return `${constants_1.FITBIT_AUTH_URL}?response_type=code&client_id=${this.clientId}&scope=${scope}&code_challenge=${codeChallenge}&code_challenge_method=${challengeMethod}&state=${state}&redirect_uri=${redirectUrl}`;
}
/**
* OAuth2.0のコールバックを処理する
* @throws {Error} sessionが設定されていない場合
*/
async handleOAuthCallback(code, state) {
if (!this.session) {
throw new Error('session is required.');
}
if (this.session.state !== state) {
throw new Error('state is invalid.');
}
const token = await apis_1.oauthApi.postAuthorization({
clientId: this.clientId,
clientSecret: this.clientSecret,
redirectUrl: this.session.redirectUrl,
codeVerifier: this.session.codeVerifier,
code,
});
this.setToken(token);
return token;
}
/**
* トークンを設定するメソッド
*/
setToken(token) {
this.token = token;
}
validateToken() {
if (!this.token) {
throw new Error('token is required.');
}
if (!this.token.accessToken || !this.token.expiresAt) {
throw new Error('accessToken and expiresAt is required. Please call a refreshAccessToken().');
}
return {
expiresAt: this.token.expiresAt,
accessToken: this.token.accessToken,
};
}
/**
* アクセストークンが期限切れまたはnullの場合にtrueを返す
*/
isAccessTokenExpired() {
const token = this.validateToken();
return token.expiresAt < new Date();
}
/**
* アクセストークンを取得する
* @throws {Error} アクセストークンが有効切れ
*/
async getAccessToken() {
const token = this.validateToken();
if (this.isAccessTokenExpired()) {
throw new Error('Access token is expired.');
}
return token.accessToken;
}
/**
* リフレッシュトークンを使用してアクセストークンを再取得する
* ※リフレッシュトークンは一度使用したら無効になる為、返却されたトークンを保存するようにお願いします。
* @throws {Error} リフレッシュトークンが設定されていない場合
*/
async refreshAccessToken() {
if (!this.token) {
throw new Error('refreshToken is required.');
}
const newToken = await apis_1.oauthApi.postTokenRefresh({
refreshToken: this.token.refreshToken,
clientId: this.clientId,
clientSecret: this.clientSecret,
});
this.setToken(newToken);
return newToken;
}
async getProfileRaw() {
const accessToken = await this.auth.getAccessToken();
return await apis_1.profileAPi.getProfileRaw({ accessToken });
}
async getProfile() {
const accessToken = await this.auth.getAccessToken();
return await apis_1.profileAPi.getProfile({ accessToken });
}
async getHeartRateIntraday(localDate, offsetFromUTCMillis, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.heartRateApi.getHeartRateIntradayByDate({
localDate,
detailLevel,
}, offsetFromUTCMillis, { accessToken });
}
async getHeartRateIntradayRaw(localDate, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.heartRateApi.getHeartRateIntradayByDateRaw({
localDate,
detailLevel,
}, { accessToken });
}
async getStepsIntraday(localDate, offsetFromUTCMillis, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getStepsIntradayByDate({
localDate,
detailLevel,
}, offsetFromUTCMillis, { accessToken });
}
async getStepsIntradayRaw(localDate, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getStepsIntradayByDateRaw({
localDate,
detailLevel,
}, { accessToken });
}
async getCaloriesIntraday(localDate, offsetFromUTCMillis, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getCaloriesIntradayByDate({
localDate,
detailLevel,
}, offsetFromUTCMillis, { accessToken });
}
async getCaloriesIntradayRaw(localDate, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getCaloriesIntradayByDateRaw({
localDate,
detailLevel,
}, { accessToken });
}
async getDistanceIntradayRaw(localDate, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getDistanceIntradayByDateRaw({
localDate,
detailLevel,
}, { accessToken });
}
async getElevationIntradayRaw(localDate, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getElevationIntradayByDateRaw({
localDate,
detailLevel,
}, { accessToken });
}
async getFloorsIntradayRaw(localDate, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getFloorsIntradayByDateRaw({
localDate,
detailLevel,
}, { accessToken });
}
async getSwimmingStrokesRaw(localDate, detailLevel) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.activityApi.getSwimmingStrokesByDateRaw({
localDate,
detailLevel,
}, { accessToken });
}
async getSleepLog(localDate, offsetFromUTCMillis) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.sleepApi.getSleepLogByDate({
localDate,
}, offsetFromUTCMillis, { accessToken });
}
async getTemperatureCoreSummaryRaw(localDate) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.temperatureApi.getTemperatureCoreSummaryByDateRaw({
localDate,
}, { accessToken });
}
async getSleepLogRaw(localDate) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.sleepApi.getSleepLogByDateRaw({
localDate,
}, { accessToken });
}
async getSpO2Intraday(localDate, offsetFromUTCMillis) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.spO2Api.getSpo2IntradayByDate({
localDate,
}, offsetFromUTCMillis, { accessToken });
}
async getSpO2IntradayRaw(localDate) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.spO2Api.getSpO2IntradayByDateRaw({
localDate,
}, { accessToken });
}
async getWeightLog(localDate, offsetFromUTCMillis) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.bodyApi.getWeightLogByDate({
localDate,
}, offsetFromUTCMillis, { accessToken });
}
async getWeightLogRaw(localDate) {
const accessToken = await this.auth.getAccessToken();
return await apis_1.bodyApi.getWeightLogByDateRaw({
localDate,
}, { accessToken });
}
}
exports.FitbitClient = FitbitClient;
//# sourceMappingURL=fitbit-client.js.map