fitbit-oauth2-client
Version:
Fitbit client API for OAuth2
1 lines • 36.9 kB
Source Map (JSON)
{"version":3,"sources":["../src/Fitbit.ts","../src/FileTokenManager.ts","../src/LogManager.ts","../src/FitbitApi.ts"],"sourcesContent":["import axios, { AxiosResponse } from 'axios';\nimport { stringify } from 'qs';\nimport FileTokenManager from './FileTokenManager';\nimport { LogManager } from './LogManager';\nimport TokenManager, { TokenData } from './TokenManager';\nimport { AuthorizationCode } from 'simple-oauth2';\n\nconst _request = axios.request;\nconst post = axios.post;\n\nconst PROCENTAGE_TO_DECIMAL_DIVIDER = 100;\nconst SUBSTRACT_MILLIS = 60000; // 1 minute\n\nlet _logger = LogManager.getLogger();\n\ninterface DefaultFitbitConfig {\n timeout: number;\n tokenExpiresFactorProcentage: number;\n uris: {\n authorizationUri: string;\n authorizationPath: string;\n tokenUri: string;\n tokenPath: string;\n };\n authorizationUri: {\n scope: string;\n state: string;\n };\n}\n\ninterface QueuedRequest<T> {\n promise: Promise<AxiosResponse<T>>;\n handler: () => void;\n}\n\nconst FITBIT_CONFIG_DEFAULTS: DefaultFitbitConfig = {\n timeout: 60000,\n tokenExpiresFactorProcentage: 80,\n uris: {\n authorizationUri: 'https://www.fitbit.com',\n authorizationPath: '/oauth2/authorize',\n tokenUri: 'https://api.fitbit.com',\n tokenPath: '/oauth2/token',\n },\n authorizationUri: {\n scope: 'location activity nutrition social settings profile sleep heartrate weight',\n state: '3(#0/!~',\n },\n};\n\ninterface CompleteFitbitConfig extends DefaultFitbitConfig {\n timeout: number;\n tokenExpiresFactorProcentage: number;\n creds: {\n clientId: string;\n clientSecret: string;\n };\n tokenFilePath?: string;\n uris: {\n authorizationUri: string;\n authorizationPath: string;\n tokenUri: string;\n tokenPath: string;\n };\n authorizationUri: {\n redirectUri: string;\n scope: string;\n state: string;\n };\n}\n\nexport interface FitbitConfig {\n timeout?: number;\n tokenExpiresFactorProcentage?: number;\n creds: {\n clientId: string;\n clientSecret: string;\n };\n tokenFilePath?: string;\n uris?: {\n authorizationUri?: string;\n authorizationPath?: string;\n tokenUri?: string;\n tokenPath?: string;\n };\n authorizationUri: {\n redirectUri: string;\n scope?: string;\n state: string;\n };\n}\n\nexport interface RequestOptions {\n method: 'GET' | 'POST';\n data?: any;\n timeout?: number;\n headers?: Record<string, string>;\n url: string;\n}\n\nexport interface LegacyRequestOptions {\n method: 'GET' | 'POST';\n data?: any;\n timeout?: number;\n headers?: Record<string, string>;\n uri: string;\n url?: string;\n}\n\nexport const createDefaultFitbitConfig = (\n clientId: string,\n clientSecret: string,\n redirectUri: string,\n): FitbitConfig => {\n return {\n ...FITBIT_CONFIG_DEFAULTS,\n creds: { clientId, clientSecret },\n authorizationUri: { ...FITBIT_CONFIG_DEFAULTS.authorizationUri, redirectUri },\n };\n};\n\nexport const createDefaultFitbitConfigFromEnvironment = (): FitbitConfig => {\n if (!process.env.env_clientID) {\n throw new Error('Missing env variable env_clientID');\n }\n if (!process.env.env_clientSecret) {\n throw new Error('Missing env variable env_clientSecret');\n }\n if (!process.env.env_redirect_uri) {\n throw new Error('Missing env variable env_redirect_uri');\n }\n return createDefaultFitbitConfig(\n process.env.env_clientID,\n process.env.env_clientSecret,\n process.env.env_redirect_uri,\n );\n};\n\nclass FitbitBase {\n public static setLogger(logger: any) {\n _logger = LogManager.getLogger(logger);\n }\n\n protected static addExpiresAt(token: TokenData, tokenExpiresFactor: number, requestDateTime?: Date): TokenData {\n const now = requestDateTime || new Date();\n now.setSeconds(now.getSeconds() + Math.round(token.expires_in * tokenExpiresFactor));\n if (!requestDateTime) {\n now.setSeconds(now.getSeconds() - SUBSTRACT_MILLIS);\n }\n const expires_at = now.toISOString();\n const expires_at_timestamp = now.getTime();\n return { ...token, expires_at, expires_at_timestamp };\n }\n\n protected static createQueuedRequest<T>(\n options: RequestOptions | LegacyRequestOptions,\n fitbit: Fitbit,\n ): QueuedRequest<T> {\n // eslint-disable-next-line no-unused-vars\n const promiseInspector: { resolve: (data: AxiosResponse<T>) => void; reject: (error?: any) => void } = {\n // eslint-disable-next-line no-unused-vars\n resolve: (data: AxiosResponse<T>) => {\n console.log(data);\n },\n // eslint-disable-next-line no-unused-vars\n reject: (error?: any) => {\n console.log(error);\n },\n };\n const queuedRequest = {\n promise: new Promise<AxiosResponse<T>>((resolve, reject) => {\n promiseInspector.reject = reject;\n promiseInspector.resolve = resolve;\n }),\n handler: () => {\n _logger.trace(`request[dequeued] ${options.url}:`, options);\n fitbit\n .request<T>(options)\n .then((response: AxiosResponse<T>) => promiseInspector.resolve(response))\n .catch((error?: any) => promiseInspector.reject(error));\n },\n };\n\n return queuedRequest;\n }\n\n protected static hasTokenExpired(token: TokenData): boolean {\n if (!token.expires_at) {\n return true;\n }\n const now = new Date();\n if (token.expires_at_timestamp) {\n return now.getTime() >= token.expires_at_timestamp;\n }\n const then = new Date(token.expires_at);\n console.log('then:', then);\n return now.getTime() >= then.getTime();\n }\n\n public static createData(data: any): string {\n return stringify(data);\n }\n\n protected static normalizeOptions(\n options: RequestOptions | LegacyRequestOptions,\n config: CompleteFitbitConfig,\n ): RequestOptions {\n const newOptions: RequestOptions = { ...options, url: options.url || (options as any).uri };\n if (!newOptions.url) {\n throw new Error(`Parameter url is missing in: ${JSON.stringify(newOptions)}`);\n }\n if ((newOptions as any).uri) {\n delete (options as any).uri;\n }\n\n if (!newOptions.timeout) {\n newOptions.timeout = config.timeout;\n }\n\n if (!options.headers) {\n options.headers = {};\n }\n\n return newOptions;\n }\n}\n\nexport class TestFitbitBase extends FitbitBase {\n public static addExpiresAt(token: TokenData, tokenExpiresFactor: number, requestDateTime?: Date): TokenData {\n return super.addExpiresAt(token, tokenExpiresFactor, requestDateTime);\n }\n\n public static hasTokenExpired(token: TokenData): boolean {\n return super.hasTokenExpired(token);\n }\n}\n\nexport class Fitbit extends FitbitBase {\n private _config: CompleteFitbitConfig;\n private _tokenManager: TokenManager;\n private _tokenData: TokenData | null = null;\n private _isTokenRefreshingOrInitiating: boolean = false;\n private _tokenExpiresFactor: number;\n private _requestQueue: any[] = [];\n private _limits?: {\n limit: string;\n remaining: string;\n reset: string;\n };\n\n constructor(config: FitbitConfig, tokenManager?: TokenManager) {\n super();\n if (!config) {\n throw new Error('Config expected');\n }\n\n this._config = {\n ...FITBIT_CONFIG_DEFAULTS,\n ...config,\n authorizationUri: { ...FITBIT_CONFIG_DEFAULTS.authorizationUri, ...config.authorizationUri },\n uris: { ...FITBIT_CONFIG_DEFAULTS.uris, ...config.uris },\n };\n this._tokenManager = tokenManager\n ? tokenManager\n : (() => {\n if (!config.tokenFilePath) {\n throw new Error(\"Make sure config has property 'tokenFilePath' defined or provide a token persist manager\");\n }\n return new FileTokenManager(config.tokenFilePath);\n })();\n\n this._tokenExpiresFactor =\n this._config.tokenExpiresFactorProcentage > 1\n ? this._config.tokenExpiresFactorProcentage / PROCENTAGE_TO_DECIMAL_DIVIDER\n : this._config.tokenExpiresFactorProcentage;\n if (this._tokenExpiresFactor > 1) {\n this._tokenExpiresFactor = this._tokenExpiresFactor / PROCENTAGE_TO_DECIMAL_DIVIDER;\n }\n }\n\n authorizeURL() {\n const config = {\n client: {\n id: this._config.creds.clientId,\n secret: this._config.creds.clientSecret,\n },\n auth: {\n tokenHost: this._config.uris.authorizationUri,\n tokenPath: this._config.uris.tokenPath,\n authorizePath: this._config.uris.authorizationPath,\n },\n };\n const client = new AuthorizationCode(config);\n return client.authorizeURL(this._config.authorizationUri);\n }\n\n public fetchToken(code: string) {\n return this.internalFetchToken('', code);\n }\n\n private internalFetchToken(refreshToken: string, code?: string) {\n _logger.debug(`fetchToken: refreshToken=${refreshToken}, code=${code}`);\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n const url = self._config.uris.tokenUri + self._config.uris.tokenPath;\n const data = stringify(\n code\n ? {\n code: code,\n redirect_uri: self._config.authorizationUri.redirectUri,\n grant_type: 'authorization_code',\n client_id: self._config.creds.clientId,\n client_secret: self._config.creds.clientSecret,\n }\n : {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n },\n );\n const config = {\n headers: {\n Authorization:\n 'Basic ' +\n Buffer.from(self._config.creds.clientId + ':' + self._config.creds.clientSecret).toString('base64'),\n Accept: 'application/json, text/plain, */*',\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n timeout: self._config.timeout,\n };\n const requestDateTime = new Date();\n _logger.trace(`fetchToken[axios.post]: ${url}`, { data, config });\n return post(url, data, config)\n .then((response) => {\n const token = Fitbit.addExpiresAt(response.data, self._tokenExpiresFactor, requestDateTime);\n self._tokenData = token;\n _logger.trace('fetchToken[axios.post][response]:', token);\n return token;\n })\n .then((token: TokenData) => {\n return self._tokenManager.write(token);\n });\n }\n\n private refresh(refreshToken: string) {\n _logger.debug('refresh');\n return this.internalFetchToken(refreshToken);\n }\n\n public request<T>(options: RequestOptions | LegacyRequestOptions): Promise<AxiosResponse<T>> {\n return this.internalRequest<T>(Fitbit.normalizeOptions(options, this._config));\n }\n\n protected internalRequest<T>(options: RequestOptions): Promise<AxiosResponse<T>> {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const self = this;\n\n if (self._isTokenRefreshingOrInitiating) {\n _logger.debug('request[enqueued]:', options);\n const queuedRequest = Fitbit.createQueuedRequest<T>(options, self);\n self._requestQueue.push(queuedRequest.handler);\n return queuedRequest.promise;\n }\n\n _logger.debug('request:', options);\n\n const performRequest = (): Promise<AxiosResponse<T>> => {\n if (!self._tokenData || !self._tokenData.access_token) {\n return new Promise<AxiosResponse<T>>((resolve, reject) => {\n const error = new Error('token appears corrupt:' + JSON.stringify(self._tokenData));\n reject(error);\n });\n }\n if (!options.headers) {\n options.headers = {};\n }\n if (!options?.headers?.Authorization) {\n options.headers.Authorization = 'Bearer ' + self._tokenData.access_token;\n }\n _logger.trace('request.performRequest[axios.request]:', options);\n return _request(options).then((response: AxiosResponse<T>) => {\n _logger.trace(\n `Request ${options.url}:`,\n response.toString ? response.toString() : response.data ? response.data : '...',\n );\n if (response.headers) {\n self._limits = {\n limit: response.headers['fitbit-rate-limit-limit'],\n remaining: response.headers['fitbit-rate-limit-remaining'],\n reset: response.headers['fitbit-rate-limit-reset'],\n };\n }\n return response;\n });\n };\n\n const processQueuedRequests = () => {\n setTimeout(() => {\n const noqr = self._requestQueue.length;\n _logger.debug(`request.processQueuedRequests: Processing ${noqr} queued requests...`);\n while (self._requestQueue.length > 0) {\n const qr = self._requestQueue.shift();\n if (!qr) {\n break;\n }\n qr();\n }\n }, 0);\n };\n\n if (!self._tokenData) {\n self._isTokenRefreshingOrInitiating = true;\n return self._tokenManager\n .read()\n .then((token) => {\n _logger.trace('request[tokenManager.read]:', token);\n if (!token.expires_at_timestamp) {\n token = Fitbit.addExpiresAt(token, self._tokenExpiresFactor);\n self._tokenData = token;\n _logger.trace('request[tokenManager.read] Expire info added:', token);\n return self._tokenManager.write(token);\n }\n self._tokenData = token;\n return token;\n })\n .then((token: TokenData) => {\n if (Fitbit.hasTokenExpired(token)) {\n _logger.trace('request[tokenManager.read] Token expired:', token);\n return self.refresh(token.refresh_token);\n }\n\n return token;\n })\n .then(() => {\n if (self._isTokenRefreshingOrInitiating) {\n self._isTokenRefreshingOrInitiating = false;\n processQueuedRequests();\n }\n return performRequest();\n });\n } else if (Fitbit.hasTokenExpired(self._tokenData)) {\n this._isTokenRefreshingOrInitiating = true;\n _logger.trace('request[Token Expired]:', self._tokenData);\n return self.refresh(self._tokenData.refresh_token).then(() => {\n if (self._isTokenRefreshingOrInitiating) {\n self._isTokenRefreshingOrInitiating = false;\n processQueuedRequests();\n }\n return performRequest();\n });\n }\n\n return performRequest();\n }\n\n public getLimits() {\n return this._limits;\n }\n}\n\nexport default Fitbit;\n","import { readFile, writeFile } from 'fs';\nimport { LogManager } from './LogManager';\nimport TokenManager, { TokenData } from './TokenManager';\n\nlet _logger = LogManager.getLogger();\n\nexport class FileTokenManager implements TokenManager {\n // eslint-disable-next-line no-unused-vars\n constructor(private tokenFilePath: string) {}\n\n static setLogger(logger: any) {\n _logger = LogManager.getLogger(logger);\n }\n\n public read(): Promise<TokenData> {\n return new Promise<TokenData>((resolve, reject) => {\n try {\n _logger.debug('Reading token file [' + this.tokenFilePath + ']');\n readFile(this.tokenFilePath, { encoding: 'utf8', flag: 'r' }, function (err, data) {\n if (err) {\n _logger.error('Read failed:', err);\n return reject(err);\n }\n try {\n const token = JSON.parse(data) as TokenData;\n _logger.trace('Read token:', token);\n resolve(token);\n } catch (error) {\n _logger.error('Read failed<2>:', error);\n reject(error);\n }\n });\n } catch (error) {\n _logger.error('Read failed<2>:', error);\n reject(error);\n }\n });\n }\n\n public write(token: TokenData): Promise<TokenData> {\n return new Promise<TokenData>((resolve, reject) => {\n try {\n _logger.debug('Writing token file [' + this.tokenFilePath + ']:', token);\n writeFile(this.tokenFilePath, JSON.stringify(token), { encoding: 'utf8', flag: 'w' }, (err) => {\n if (err) {\n _logger.error('Write failed:', err);\n reject(err);\n } else {\n _logger.trace('Wrote token:', token);\n resolve(token);\n }\n });\n } catch (error) {\n _logger.error('Write failed<2>:', error);\n reject(error);\n }\n });\n }\n}\n\nexport default FileTokenManager;\n","const DEFAULT_JSON_IDENT = 3;\n\ntype Level = 'trace' | 'debug' | 'info' | 'warn' | 'error';\n\nexport class Logger {\n constructor(\n // eslint-disable-next-line no-unused-vars\n private logger: any = null,\n // eslint-disable-next-line no-unused-vars\n private jsonIdent: number = DEFAULT_JSON_IDENT,\n ) {}\n\n log(level: Level, msg: string, data?: any) {\n if (!this.logger) {\n return;\n }\n\n if (typeof this.logger === 'function') {\n data ? this.logger(msg, JSON.stringify(data, undefined, this.jsonIdent)) : this.logger(msg);\n return;\n }\n\n if (this.logger[level]) {\n data ? this.logger[level](msg, JSON.stringify(data, undefined, this.jsonIdent)) : this.logger[level](msg);\n return;\n }\n\n if (level === 'trace' && this.logger['silly']) {\n data ? this.logger['silly'](msg, JSON.stringify(data, undefined, this.jsonIdent)) : this.logger['silly'](msg);\n return;\n }\n }\n\n trace(msg: string, data?: any) {\n this.log('trace', msg, data);\n }\n\n debug(msg: string, data?: any) {\n this.log('debug', msg, data);\n }\n\n info(msg: string, data?: any) {\n this.log('info', msg, data);\n }\n\n warn(msg: string, data?: any) {\n this.log('warn', msg, data);\n }\n\n error(msg: string, data?: any) {\n this.log('error', msg, data);\n }\n}\n\nexport class LogManager {\n static getLogger(logger = null) {\n return new Logger(logger);\n }\n}\n\nexport default LogManager;\n","import dayjs, { extend, Dayjs } from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport timezone from 'dayjs/plugin/timezone';\nimport Fitbit, { LegacyRequestOptions, RequestOptions } from './Fitbit';\nimport { AxiosResponse } from 'axios';\n\nextend(utc);\nextend(timezone);\n\nconst THOUSAND_FACTOR = 1000;\n\nconst handleResponse = <T>(response: AxiosResponse<T>) => response.data;\n\nconst getDayjsInstance = (dayjsDateOrTimestamp?: Dayjs | number): Dayjs => {\n const at: Dayjs = dayjsDateOrTimestamp\n ? (dayjsDateOrTimestamp as any).isValid\n ? (dayjsDateOrTimestamp as Dayjs)\n : dayjs(dayjsDateOrTimestamp)\n : dayjs();\n\n if (!at.isValid()) {\n throw new Error('Invalid instance: ' + at);\n }\n\n return at;\n};\n\nconst handleRequest = <T>(\n options: RequestOptions,\n fitbitClient: Fitbit,\n apiCallInterceptor?: (config: RequestOptions | LegacyRequestOptions) => boolean,\n): Promise<T> => {\n if (apiCallInterceptor) {\n if (apiCallInterceptor(options)) {\n return new Promise((resolve, reject) => {\n reject();\n });\n }\n }\n\n return fitbitClient.request<T>(options).then(handleResponse);\n};\n\nexport interface WeightResponse {\n weight: {\n bmi: number;\n date: string;\n fat: number;\n logId: number;\n source: string;\n time: string;\n weight: number;\n }[];\n}\n\nexport interface BodyFatResponse {\n fat: {\n date: string;\n fat: number;\n logId: number;\n source: string;\n time: string;\n }[];\n}\n\nexport interface ProfileResponse {\n user: {\n age: number;\n ambassador: boolean;\n avatar: string;\n avatar150: string;\n avatar640: string;\n averageDailySteps: number;\n challengesBeta: boolean;\n clockTimeDisplayFormat: string;\n corporate: boolean;\n corporateAdmin: boolean;\n country: string;\n dateOfBirth: string;\n displayName: string;\n displayNameSetting: string;\n distanceUnit: string;\n encodedId: string;\n features: { exerciseGoal: boolean };\n firstName: string;\n foodsLocale: string;\n fullName: string;\n gender: string;\n glucoseUnit: string;\n height: number;\n heightUnit: string;\n isBugReportEnabled: boolean;\n isChild: boolean;\n isCoach: boolean;\n languageLocale: string;\n lastName: string;\n legalTermsAcceptRequired: boolean;\n locale: string;\n memberSince: string;\n mfaEnabled: boolean;\n offsetFromUTCMillis: number;\n sdkDeveloper: boolean;\n sleepTracking: string;\n startDayOfWeek: string;\n strideLengthRunning: number;\n strideLengthRunningType: string;\n strideLengthWalking: number;\n strideLengthWalkingType: string;\n swimUnit: string;\n temperatureUnit: string;\n timezone: string;\n topBadges: any[];\n visibleUser: boolean;\n waterUnit: string;\n waterUnitName: string;\n weight: number;\n weightUnit: string;\n };\n}\n\nexport interface LifetimeStatsResponse {\n lifetime: {\n total: { activeScore: number; caloriesOut: number; distance: number; steps: number };\n tracker: { activeScore: number; caloriesOut: number; distance: number; steps: number };\n };\n}\n\nexport class FitbitApi {\n constructor(\n private fitbitClient: Fitbit,\n private apiCallInterceptor?: (config: RequestOptions | LegacyRequestOptions) => boolean,\n ) {}\n\n static fromUTC = (timestamp: number, tz?: string) => {\n return tz ? dayjs.utc(timestamp).tz(tz) : dayjs.utc(timestamp);\n };\n\n static getDateTime = (dayjsDateOrTimestamp?: Dayjs | number) => {\n const at = getDayjsInstance(dayjsDateOrTimestamp);\n\n return {\n date: at.format('YYYY-MM-DD'),\n time: at.format('HH:mm:ss'),\n };\n };\n\n static getDate = (dayjsDateOrTimestamp?: Dayjs | number) => {\n const at = getDayjsInstance(dayjsDateOrTimestamp);\n return at.format('YYYY-MM-DD');\n };\n\n static getLifetimeStatsUrl = (userId = '-') => {\n return `https://api.fitbit.com/1/user/${userId}/activities.json`;\n };\n\n static getProfileUrl = (userId = '-') => {\n return `https://api.fitbit.com/1/user/${userId}/profile.json`;\n };\n\n static getBodyFatUrl = (dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => {\n const dateStr = FitbitApi.getDate(dayjsDateOrTimestamp);\n return `https://api.fitbit.com/1/user/${userId || '-'}/body/log/fat/date/${dateStr}.json`;\n };\n\n static getLogBodyFatUrl = (userId = '-') => {\n return `https://api.fitbit.com/1/user/${userId}/body/log/fat.json`;\n };\n\n static getLogWeightUrl = (userId?: string) => {\n return `https://api.fitbit.com/1/user/${userId || '-'}/body/log/weight.json`;\n };\n\n static getWeightUrl = (dayjsDateOrTimestamp?: Dayjs | number, userId?: string) => {\n const dateStr = FitbitApi.getDate(dayjsDateOrTimestamp);\n return `https://api.fitbit.com/1/user/${userId || '-'}/body/log/weight/date/${dateStr}.json`;\n };\n\n getLifetimeStats = (userId?: string): Promise<LifetimeStatsResponse> => {\n const url = FitbitApi.getLifetimeStatsUrl(userId);\n const options: RequestOptions = {\n url,\n method: 'GET',\n };\n return handleRequest<LifetimeStatsResponse>(options, this.fitbitClient, this.apiCallInterceptor);\n };\n\n getProfile = (userId?: string): Promise<ProfileResponse> => {\n const url = FitbitApi.getProfileUrl(userId);\n const options: RequestOptions = {\n url,\n method: 'GET',\n };\n return handleRequest<ProfileResponse>(options, this.fitbitClient, this.apiCallInterceptor);\n };\n\n getBodyFat = (dayjsDateOrTimestamp?: Dayjs | number, userId?: string): Promise<BodyFatResponse> => {\n const url = FitbitApi.getBodyFatUrl(dayjsDateOrTimestamp, userId);\n const options: RequestOptions = {\n url,\n method: 'GET',\n };\n return handleRequest<BodyFatResponse>(options, this.fitbitClient, this.apiCallInterceptor);\n };\n\n logBodyFat = (fat: any, dayjsDateOrTimestamp?: Dayjs | number, userId?: string): Promise<any> => {\n const dateTime = FitbitApi.getDateTime(dayjsDateOrTimestamp);\n const url = FitbitApi.getLogBodyFatUrl(userId);\n const options: RequestOptions = {\n url,\n method: 'POST',\n data: Fitbit.createData({\n fat,\n date: dateTime.date,\n time: dateTime.time,\n }),\n };\n return handleRequest<any>(options, this.fitbitClient, this.apiCallInterceptor);\n };\n\n logWeight = (weight: any, dayjsDateOrTimestamp?: Dayjs | number, userId?: string): Promise<any> => {\n const dateTime = FitbitApi.getDateTime(dayjsDateOrTimestamp);\n const url = FitbitApi.getLogWeightUrl(userId);\n const verifiedWeight = weight > THOUSAND_FACTOR ? weight / THOUSAND_FACTOR : weight;\n const options: RequestOptions = {\n url,\n method: 'POST',\n data: Fitbit.createData({\n weight: verifiedWeight,\n date: dateTime.date,\n time: dateTime.time,\n }),\n };\n return handleRequest<any>(options, this.fitbitClient, this.apiCallInterceptor);\n };\n\n getWeight = (dayjsDateOrTimestamp?: Dayjs | number, userId?: string): Promise<WeightResponse> => {\n const url = FitbitApi.getWeightUrl(dayjsDateOrTimestamp, userId);\n const options: RequestOptions = {\n url,\n method: 'GET',\n };\n return handleRequest<WeightResponse>(options, this.fitbitClient, this.apiCallInterceptor);\n };\n}\n\nexport default FitbitApi;\n"],"mappings":"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","names":["_logger","_logger","_logger"]}