@kaiord/garmin-connect 5.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -29
- package/dist/index.d.ts +64 -21
- package/dist/index.js +387 -226
- package/dist/index.js.map +1 -1
- package/package.json +9 -6
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/http/cookie-fetch.ts","../src/adapters/http/garmin-auth-fetch.ts","../src/adapters/http/urls.ts","../src/adapters/http/oauth-consumer.ts","../src/adapters/http/sso-validators.ts","../src/adapters/http/sso-login.ts","../src/adapters/http/oauth-signer.ts","../src/adapters/http/sso-oauth.ts","../src/adapters/http/garmin-sso.ts","../src/adapters/http/token-refresh.ts","../src/adapters/http/garmin-http-client.ts","../src/adapters/schemas/garmin-token.schema.ts","../src/adapters/auth/garmin-auth-provider.ts","../src/adapters/mappers/workout-summary.mapper.ts","../src/adapters/schemas/workout-response.schema.ts","../src/adapters/client/garmin-workout-service.ts","../src/adapters/client/garmin-connect-client.ts","../src/adapters/token-store/file-token-store.ts","../src/adapters/token-store/memory-token-store.ts"],"names":["createServiceAuthError","createServiceApiError","z","createConsoleLogger"],"mappings":"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","file":"index.js","sourcesContent":["import fetchCookie from \"fetch-cookie\";\n\nexport const createCookieFetch = (): typeof globalThis.fetch =>\n fetchCookie(globalThis.fetch) as typeof globalThis.fetch;\n","import { createServiceApiError } from \"@kaiord/core\";\nimport type { TokenRefreshManager } from \"./token-refresh\";\nimport type { FetchFn } from \"./types\";\n\nconst makeRequest = (\n url: string,\n init: RequestInit | undefined,\n refresh: TokenRefreshManager,\n fetchFn: FetchFn\n): Promise<Response> => {\n if (!refresh.state.oauth2Token) {\n throw createServiceApiError(\"Token unavailable after refresh\", 401);\n }\n return fetchFn(url, {\n ...init,\n headers: {\n ...init?.headers,\n Authorization: `Bearer ${refresh.state.oauth2Token.access_token}`,\n },\n });\n};\n\nexport const authFetch = async (\n url: string,\n init: RequestInit | undefined,\n refresh: TokenRefreshManager,\n fetchFn: FetchFn\n): Promise<Response> => {\n if (!refresh.state.oauth2Token) {\n throw createServiceApiError(\"Not authenticated\", 401);\n }\n if (refresh.state.oauth2Token.expires_at < Math.floor(Date.now() / 1000)) {\n await refresh.ensureFreshToken();\n }\n const res = await makeRequest(url, init, refresh, fetchFn);\n if (res.status === 401) {\n await refresh.ensureFreshToken();\n const retry = await makeRequest(url, init, refresh, fetchFn);\n if (!retry.ok) {\n throw createServiceApiError(\n `API request failed after token refresh: ${retry.statusText}`,\n retry.status\n );\n }\n return retry;\n }\n if (!res.ok) {\n throw createServiceApiError(\n `API request failed: ${res.statusText}`,\n res.status\n );\n }\n return res;\n};\n","export const GARMIN_SSO_ORIGIN = \"https://sso.garmin.com\";\nexport const GARMIN_SSO_EMBED = \"https://sso.garmin.com/sso/embed\";\nexport const SIGNIN_URL = \"https://sso.garmin.com/sso/signin\";\nexport const GC_MODERN = \"https://connect.garmin.com/modern\";\nexport const API_BASE = \"https://connectapi.garmin.com\";\nexport const OAUTH_URL = `${API_BASE}/oauth-service/oauth`;\nexport const WORKOUT_URL = `${API_BASE}/workout-service`;\n/** OAuth consumer credentials hosted by the garth project (third-party). */\nexport const OAUTH_CONSUMER_URL =\n \"https://thegarth.s3.amazonaws.com/oauth_consumer.json\";\n\nexport const USER_AGENT_MOBILE = \"com.garmin.android.apps.connectmobile\";\nexport const USER_AGENT_BROWSER =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36\";\n","import { createServiceAuthError } from \"@kaiord/core\";\nimport { OAUTH_CONSUMER_URL } from \"./urls\";\nimport type { FetchFn, OAuthConsumer } from \"./types\";\n\nexport const fetchOAuthConsumer = async (\n fetchFn: FetchFn\n): Promise<OAuthConsumer> => {\n const res = await fetchFn(OAUTH_CONSUMER_URL);\n if (!res.ok) {\n throw createServiceAuthError(\n `Failed to fetch OAuth consumer: ${res.status} ${res.statusText}`\n );\n }\n const data = (await res.json()) as {\n consumer_key: string;\n consumer_secret: string;\n };\n return { key: data.consumer_key, secret: data.consumer_secret };\n};\n","import { createServiceAuthError } from \"@kaiord/core\";\nimport type { Logger } from \"@kaiord/core\";\n\nconst ACCOUNT_LOCKED_RE = /var status\\s*=\\s*\"([^\"]*)\"/;\nconst PAGE_TITLE_RE = /<title>([^<]*)<\\/title>/;\n\nexport const checkAccountLocked = (html: string): void => {\n const match = ACCOUNT_LOCKED_RE.exec(html);\n if (match && match[1] === \"ACCOUNT_LOCKED\") {\n throw createServiceAuthError(\n `Account locked: ${match[1]}. Unlock via Garmin Connect web.`\n );\n }\n};\n\nexport const checkPageTitle = (html: string, logger: Logger): void => {\n const match = PAGE_TITLE_RE.exec(html);\n if (match?.[1]?.includes(\"Update Phone Number\")) {\n throw createServiceAuthError(\"Login failed: phone number update required.\");\n }\n if (match) {\n logger.debug(\"Login page title\", { title: match[1] });\n }\n};\n","import { createServiceAuthError } from \"@kaiord/core\";\nimport { checkAccountLocked, checkPageTitle } from \"./sso-validators\";\nimport {\n GARMIN_SSO_EMBED,\n GC_MODERN,\n GARMIN_SSO_ORIGIN,\n SIGNIN_URL,\n USER_AGENT_BROWSER,\n} from \"./urls\";\nimport type { FetchFn } from \"./types\";\nimport type { Logger } from \"@kaiord/core\";\n\nconst CSRF_RE = /name=\"_csrf\"\\s+value=\"(.+?)\"/;\nconst TICKET_RE = /ticket=([^\"]+)\"/;\n\nconst fetchCsrfToken = async (fetchFn: FetchFn): Promise<string> => {\n const signinParams = new URLSearchParams({\n id: \"gauth-widget\",\n embedWidget: \"true\",\n locale: \"en\",\n gauthHost: GARMIN_SSO_EMBED,\n });\n const csrfRes = await fetchFn(`${SIGNIN_URL}?${signinParams}`);\n if (!csrfRes.ok) {\n throw createServiceAuthError(\n `SSO login page returned ${csrfRes.status}: ${csrfRes.statusText}`\n );\n }\n const csrfHtml = await csrfRes.text();\n const csrfMatch = CSRF_RE.exec(csrfHtml);\n if (!csrfMatch) {\n throw createServiceAuthError(\"CSRF token not found on login page\");\n }\n return csrfMatch[1];\n};\n\nconst submitLogin = async (\n username: string,\n password: string,\n csrf: string,\n fetchFn: FetchFn\n): Promise<string> => {\n const loginParams = new URLSearchParams({\n id: \"gauth-widget\",\n embedWidget: \"true\",\n clientId: \"GarminConnect\",\n locale: \"en\",\n gauthHost: GARMIN_SSO_EMBED,\n service: GARMIN_SSO_EMBED,\n source: GARMIN_SSO_EMBED,\n redirectAfterAccountLoginUrl: GARMIN_SSO_EMBED,\n redirectAfterAccountCreationUrl: GARMIN_SSO_EMBED,\n });\n const body = new URLSearchParams({\n username,\n password,\n embed: \"true\",\n _csrf: csrf,\n });\n const loginRes = await fetchFn(`${SIGNIN_URL}?${loginParams}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Dnt: \"1\",\n Origin: GARMIN_SSO_ORIGIN,\n Referer: SIGNIN_URL,\n \"User-Agent\": USER_AGENT_BROWSER,\n },\n body: body.toString(),\n });\n return loginRes.text();\n};\n\nexport const getLoginTicket = async (\n username: string,\n password: string,\n fetchFn: FetchFn,\n logger: Logger\n): Promise<string> => {\n const embedParams = new URLSearchParams({\n clientId: \"GarminConnect\",\n locale: \"en\",\n service: GC_MODERN,\n });\n await fetchFn(`${GARMIN_SSO_EMBED}?${embedParams}`);\n\n const csrf = await fetchCsrfToken(fetchFn);\n const loginHtml = await submitLogin(username, password, csrf, fetchFn);\n\n checkAccountLocked(loginHtml);\n checkPageTitle(loginHtml, logger);\n\n const ticketMatch = TICKET_RE.exec(loginHtml);\n if (!ticketMatch) {\n throw createServiceAuthError(\n \"Login failed: ticket not found. Check username and password.\"\n );\n }\n return ticketMatch[1];\n};\n","import { createHmac } from \"node:crypto\";\nimport OAuth from \"oauth-1.0a\";\nimport type { OAuthConsumer } from \"./types\";\n\nexport type { OAuthConsumer } from \"./types\";\nexport type OAuthToken = { key: string; secret: string };\n\nexport type OAuthSigner = {\n toHeader: (\n request: { url: string; method: string },\n token?: OAuthToken\n ) => Record<string, string>;\n};\n\nexport const createOAuthSigner = (consumer: OAuthConsumer): OAuthSigner => {\n const oauth = new OAuth({\n consumer,\n signature_method: \"HMAC-SHA1\",\n hash_function(baseString: string, key: string) {\n return createHmac(\"sha1\", key).update(baseString).digest(\"base64\");\n },\n });\n\n return {\n toHeader: (request, token) => {\n const authorized = token\n ? oauth.authorize(request, token)\n : oauth.authorize(request);\n const header = oauth.toHeader(authorized);\n return Object.fromEntries(Object.entries(header));\n },\n };\n};\n","import { createServiceAuthError } from \"@kaiord/core\";\nimport { createOAuthSigner } from \"./oauth-signer\";\nimport { GARMIN_SSO_EMBED, OAUTH_URL, USER_AGENT_MOBILE } from \"./urls\";\nimport type { FetchFn, OAuthConsumer } from \"./types\";\nimport type { OAuth1Token, OAuth2Token } from \"./types\";\n\nexport const getOAuth1Token = async (\n ticket: string,\n consumer: OAuthConsumer,\n fetchFn: FetchFn\n): Promise<OAuth1Token> => {\n const signer = createOAuthSigner(consumer);\n const params = new URLSearchParams({\n ticket,\n \"login-url\": GARMIN_SSO_EMBED,\n \"accepts-mfa-tokens\": \"true\",\n });\n const url = `${OAUTH_URL}/preauthorized?${params}`;\n const headers = signer.toHeader({ url, method: \"GET\" });\n\n const res = await fetchFn(url, {\n headers: { ...headers, \"User-Agent\": USER_AGENT_MOBILE },\n });\n if (!res.ok) {\n throw createServiceAuthError(\n `OAuth1 token request failed: ${res.status} ${res.statusText}`\n );\n }\n const text = await res.text();\n const parsed = new URLSearchParams(text);\n\n const oauthToken = parsed.get(\"oauth_token\");\n const oauthTokenSecret = parsed.get(\"oauth_token_secret\");\n if (!oauthToken || !oauthTokenSecret) {\n throw createServiceAuthError(\"OAuth1 token exchange failed\");\n }\n\n return { oauth_token: oauthToken, oauth_token_secret: oauthTokenSecret };\n};\n\nexport const exchangeOAuth2 = async (\n oauth1: OAuth1Token,\n consumer: OAuthConsumer,\n fetchFn: FetchFn\n): Promise<OAuth2Token> => {\n const signer = createOAuthSigner(consumer);\n const baseUrl = `${OAUTH_URL}/exchange/user/2.0`;\n const token = {\n key: oauth1.oauth_token,\n secret: oauth1.oauth_token_secret,\n };\n const authHeader = signer.toHeader({ url: baseUrl, method: \"POST\" }, token);\n\n const res = await fetchFn(baseUrl, {\n method: \"POST\",\n headers: {\n ...authHeader,\n \"User-Agent\": USER_AGENT_MOBILE,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n });\n if (!res.ok) {\n throw createServiceAuthError(\n `OAuth2 exchange failed: ${res.status} ${res.statusText}`\n );\n }\n const data = (await res.json()) as OAuth2Token;\n\n return {\n ...data,\n expires_at: Math.floor(Date.now() / 1000) + data.expires_in,\n };\n};\n","import { fetchOAuthConsumer } from \"./oauth-consumer\";\nimport { getLoginTicket } from \"./sso-login\";\nimport { getOAuth1Token, exchangeOAuth2 as exchange } from \"./sso-oauth\";\nimport type { FetchFn, OAuth1Token, OAuth2Token } from \"./types\";\nimport type { Logger } from \"@kaiord/core\";\n\nexport type { OAuth1Token, OAuth2Token } from \"./types\";\nexport type SsoResult = { oauth1: OAuth1Token; oauth2: OAuth2Token };\n\n/**\n * Garmin Connect SSO login flow.\n * The fetchFn must be cookie-aware (persist cookies across requests).\n * Use fetch-cookie or similar wrapper for Node.js environments.\n */\nexport const garminSso = async (\n username: string,\n password: string,\n logger: Logger,\n fetchFn: FetchFn\n): Promise<SsoResult> => {\n logger.info(\"Starting Garmin Connect SSO login\");\n\n const consumer = await fetchOAuthConsumer(fetchFn);\n const ticket = await getLoginTicket(username, password, fetchFn, logger);\n logger.debug(\"SSO ticket obtained\");\n\n const oauth1 = await getOAuth1Token(ticket, consumer, fetchFn);\n logger.debug(\"OAuth1 token obtained\");\n\n const oauth2 = await exchange(oauth1, consumer, fetchFn);\n logger.info(\"Garmin Connect SSO login successful\");\n\n return { oauth1, oauth2 };\n};\n\nexport { exchangeOAuth2 } from \"./sso-oauth\";\n","import { createServiceApiError } from \"@kaiord/core\";\nimport { exchangeOAuth2 } from \"./garmin-sso\";\nimport { fetchOAuthConsumer } from \"./oauth-consumer\";\nimport type { FetchFn, OAuthConsumer, OAuth1Token, OAuth2Token } from \"./types\";\nimport type { Logger } from \"@kaiord/core\";\n\ntype RefreshSubscriber = {\n resolve: (token: string) => void;\n reject: (error: unknown) => void;\n};\n\nexport type TokenState = {\n oauth1Token: OAuth1Token | undefined;\n oauth2Token: OAuth2Token | undefined;\n consumer: OAuthConsumer | undefined;\n};\n\nexport type TokenRefreshManager = {\n ensureFreshToken: () => Promise<void>;\n state: TokenState;\n};\n\nconst notifyAll = (subs: RefreshSubscriber[], token: string): void => {\n subs.forEach((s) => s.resolve(token));\n};\n\nconst rejectAll = (subs: RefreshSubscriber[], error: unknown): void => {\n subs.forEach((s) => s.reject(error));\n};\n\nconst getOrFetchConsumer = async (\n state: TokenState,\n fetchFn: FetchFn\n): Promise<OAuthConsumer> => {\n if (state.consumer) return state.consumer;\n state.consumer = await fetchOAuthConsumer(fetchFn);\n return state.consumer;\n};\n\nconst doRefreshToken = async (\n state: TokenState,\n fetchFn: FetchFn,\n logger: Logger\n): Promise<void> => {\n if (!state.oauth1Token || !state.oauth2Token) {\n throw createServiceApiError(\"No tokens available for refresh\", 401);\n }\n const cons = await getOrFetchConsumer(state, fetchFn);\n state.oauth2Token = await exchangeOAuth2(state.oauth1Token, cons, fetchFn);\n logger.info(\"OAuth2 token refreshed\");\n};\n\nexport const createTokenRefreshManager = (\n fetchFn: FetchFn,\n logger: Logger\n): TokenRefreshManager => {\n const state: TokenState = {\n oauth1Token: undefined,\n oauth2Token: undefined,\n consumer: undefined,\n };\n let isRefreshing = false;\n let subscribers: RefreshSubscriber[] = [];\n\n return {\n state,\n ensureFreshToken: async (): Promise<void> => {\n if (isRefreshing) {\n await new Promise<string>((resolve, reject) => {\n subscribers.push({ resolve, reject });\n });\n return;\n }\n isRefreshing = true;\n try {\n await doRefreshToken(state, fetchFn, logger);\n if (state.oauth2Token)\n notifyAll(subscribers, state.oauth2Token.access_token);\n subscribers = [];\n } catch (error) {\n rejectAll(subscribers, error);\n subscribers = [];\n throw error;\n } finally {\n isRefreshing = false;\n }\n },\n };\n};\n","import { authFetch } from \"./garmin-auth-fetch\";\nimport { createTokenRefreshManager } from \"./token-refresh\";\nimport type {\n FetchFn,\n GarminHttpClient,\n OAuth1Token,\n OAuth2Token,\n} from \"./types\";\nimport type { Logger } from \"@kaiord/core\";\n\nexport type { GarminHttpClient } from \"./types\";\n\nexport const createGarminHttpClient = (\n logger: Logger,\n fetchFn: FetchFn = globalThis.fetch\n): GarminHttpClient => {\n const refresh = createTokenRefreshManager(fetchFn, logger);\n const fetch = (url: string, init?: RequestInit) =>\n authFetch(url, init, refresh, fetchFn);\n\n return {\n get: async <T>(url: string): Promise<T> => {\n const res = await fetch(url);\n return (await res.json()) as T;\n },\n post: async <T>(url: string, body: unknown): Promise<T> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: body !== null ? JSON.stringify(body) : undefined,\n });\n return (await res.json()) as T;\n },\n del: async <T>(url: string): Promise<T> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"X-Http-Method-Override\": \"DELETE\" },\n });\n const text = await res.text();\n return (text ? JSON.parse(text) : undefined) as T;\n },\n setTokens: (o1: OAuth1Token, o2: OAuth2Token): void => {\n refresh.state.oauth1Token = o1;\n refresh.state.oauth2Token = o2;\n },\n clearTokens: (): void => {\n refresh.state.oauth1Token = undefined;\n refresh.state.oauth2Token = undefined;\n refresh.state.consumer = undefined;\n },\n getOAuth2Token: () => refresh.state.oauth2Token,\n };\n};\n","import { z } from \"zod\";\n\nexport const oauth1TokenSchema = z.object({\n oauth_token: z.string(),\n oauth_token_secret: z.string(),\n});\n\nexport const oauth2TokenSchema = z.object({\n access_token: z.string(),\n refresh_token: z.string(),\n token_type: z.string(),\n expires_in: z.number(),\n refresh_token_expires_in: z.number(),\n expires_at: z.number(),\n});\n\nexport const garminTokensSchema = z.object({\n oauth1: oauth1TokenSchema,\n oauth2: oauth2TokenSchema,\n});\n","import { createConsoleLogger, createServiceAuthError } from \"@kaiord/core\";\nimport { createCookieFetch } from \"../http/cookie-fetch\";\nimport { createGarminHttpClient } from \"../http/garmin-http-client\";\nimport { garminSso } from \"../http/garmin-sso\";\nimport { garminTokensSchema } from \"../schemas/garmin-token.schema\";\nimport type { GarminHttpClient } from \"../http/garmin-http-client\";\nimport type { AuthProvider, Logger, TokenStore } from \"@kaiord/core\";\n\nexport type GarminAuthProviderOptions = {\n logger?: Logger;\n tokenStore?: TokenStore;\n fetchFn?: typeof globalThis.fetch;\n};\n\nexport type GarminAuthProviderResult = {\n auth: AuthProvider;\n httpClient: GarminHttpClient;\n};\n\ntype AuthState = {\n oauth1: { oauth_token: string; oauth_token_secret: string } | undefined;\n};\n\ntype AuthContext = {\n httpClient: GarminHttpClient;\n state: AuthState;\n tokenStore: TokenStore | undefined;\n logger: Logger;\n fetchFn: typeof globalThis.fetch;\n};\n\nconst buildAuthProvider = (ctx: AuthContext): AuthProvider => ({\n login: async (username, password) => {\n const result = await garminSso(username, password, ctx.logger, ctx.fetchFn);\n ctx.state.oauth1 = result.oauth1;\n ctx.httpClient.setTokens(result.oauth1, result.oauth2);\n if (ctx.tokenStore) {\n await ctx.tokenStore.save({\n oauth1: result.oauth1,\n oauth2: result.oauth2,\n });\n }\n },\n is_authenticated: () => {\n const token = ctx.httpClient.getOAuth2Token();\n if (!token) return false;\n return token.expires_at > Math.floor(Date.now() / 1000);\n },\n export_tokens: async () => {\n const token = ctx.httpClient.getOAuth2Token();\n if (!token || !ctx.state.oauth1) {\n throw createServiceAuthError(\"No tokens to export\");\n }\n return { oauth1: ctx.state.oauth1, oauth2: token };\n },\n restore_tokens: async (data) => {\n const parsed = garminTokensSchema.parse(data);\n ctx.state.oauth1 = parsed.oauth1;\n ctx.httpClient.setTokens(parsed.oauth1, parsed.oauth2);\n ctx.logger.info(\"Tokens restored from stored session\");\n },\n logout: async () => {\n ctx.state.oauth1 = undefined;\n ctx.httpClient.clearTokens();\n if (ctx.tokenStore) await ctx.tokenStore.clear();\n ctx.logger.info(\"Logged out from Garmin Connect\");\n },\n});\n\nexport const createGarminAuthProvider = (\n options?: GarminAuthProviderOptions\n): GarminAuthProviderResult => {\n const logger = options?.logger ?? createConsoleLogger();\n const tokenStore = options?.tokenStore;\n const fetchFn = options?.fetchFn ?? createCookieFetch();\n const httpClient = createGarminHttpClient(logger, fetchFn);\n const state: AuthState = { oauth1: undefined };\n const auth = buildAuthProvider({\n httpClient,\n state,\n tokenStore,\n logger,\n fetchFn,\n });\n return { auth, httpClient };\n};\n","import type { WorkoutSummary } from \"@kaiord/core\";\n\nexport const mapToWorkoutSummary = (garminWorkout: {\n workoutId?: number | string;\n workoutName?: string;\n sportType?: { sportTypeKey?: string };\n createdDate?: number | string;\n updatedDate?: number | string;\n}): WorkoutSummary => ({\n id: String(garminWorkout.workoutId ?? \"\"),\n name: garminWorkout.workoutName ?? \"Unnamed\",\n sport: garminWorkout.sportType?.sportTypeKey ?? \"unknown\",\n created_at: garminWorkout.createdDate\n ? new Date(garminWorkout.createdDate).toISOString()\n : \"\",\n updated_at: garminWorkout.updatedDate\n ? new Date(garminWorkout.updatedDate).toISOString()\n : \"\",\n});\n","import { z } from \"zod\";\n\n/** GET /workout-service/workouts?start=N&limit=N - List workout summaries */\nexport const garminWorkoutSummarySchema = z.object({\n workoutId: z.number().or(z.string()),\n workoutName: z.string().optional(),\n sportType: z.object({ sportTypeKey: z.string().optional() }).optional(),\n createdDate: z.number().or(z.string()).optional(),\n updatedDate: z.number().or(z.string()).optional(),\n});\n\n/** POST /workout-service/workout - Push a workout (returns created workout) */\nexport const garminPushResponseSchema = z.object({\n workoutId: z.number().or(z.string()),\n workoutName: z.string().optional(),\n});\n","import {\n createConsoleLogger,\n toText,\n createServiceApiError,\n} from \"@kaiord/core\";\nimport { createGarminWriter } from \"@kaiord/garmin\";\nimport { WORKOUT_URL } from \"../http/urls\";\nimport { mapToWorkoutSummary } from \"../mappers/workout-summary.mapper\";\nimport {\n garminPushResponseSchema,\n garminWorkoutSummarySchema,\n} from \"../schemas/workout-response.schema\";\nimport type { GarminHttpClient } from \"../http/garmin-http-client\";\nimport type {\n KRD,\n ListOptions,\n Logger,\n PushResult,\n WorkoutService,\n WorkoutSummary,\n} from \"@kaiord/core\";\n\nexport type GarminWorkoutClient = Pick<WorkoutService, \"push\" | \"list\">;\n\nconst pushWorkout = async (\n krd: KRD,\n httpClient: GarminHttpClient,\n garminWriter: ReturnType<typeof createGarminWriter>,\n log: Logger\n): Promise<PushResult> => {\n try {\n log.info(\"Pushing workout to Garmin Connect\");\n const gcnJson = await toText(krd, garminWriter, log);\n const payload = JSON.parse(gcnJson) as Record<string, unknown>;\n\n const raw = await httpClient.post<unknown>(\n `${WORKOUT_URL}/workout`,\n payload\n );\n const result = garminPushResponseSchema.parse(raw);\n\n return {\n id: String(result.workoutId),\n name: result.workoutName ?? \"Workout\",\n url: `https://connect.garmin.com/modern/workout/${result.workoutId}`,\n };\n } catch (error) {\n throw createServiceApiError(\"Failed to push workout\", undefined, error);\n }\n};\n\nconst listWorkouts = async (\n httpClient: GarminHttpClient,\n log: Logger,\n options?: ListOptions\n): Promise<WorkoutSummary[]> => {\n try {\n log.info(\"Listing workouts from Garmin Connect\");\n const start = options?.offset ?? 0;\n const limit = options?.limit ?? 20;\n const params = new URLSearchParams({\n start: String(start),\n limit: String(limit),\n });\n\n const raw = await httpClient.get<unknown>(\n `${WORKOUT_URL}/workouts?${params}`\n );\n const workouts = garminWorkoutSummarySchema.array().parse(raw);\n return workouts.map(mapToWorkoutSummary);\n } catch (error) {\n throw createServiceApiError(\"Failed to list workouts\", undefined, error);\n }\n};\n\nexport const createGarminWorkoutService = (\n httpClient: GarminHttpClient,\n logger?: Logger\n): GarminWorkoutClient => {\n const log = logger ?? createConsoleLogger();\n const garminWriter = createGarminWriter(log);\n\n return {\n push: (krd) => pushWorkout(krd, httpClient, garminWriter, log),\n list: (opts) => listWorkouts(httpClient, log, opts),\n };\n};\n","import { createGarminWorkoutService } from \"./garmin-workout-service\";\nimport { createGarminAuthProvider } from \"../auth/garmin-auth-provider\";\nimport type { GarminAuthProviderOptions } from \"../auth/garmin-auth-provider\";\n\nexport type GarminConnectClientOptions = GarminAuthProviderOptions;\n\nexport const createGarminConnectClient = (\n options?: GarminConnectClientOptions\n) => {\n const { auth, httpClient } = createGarminAuthProvider(options);\n const service = createGarminWorkoutService(httpClient, options?.logger);\n return { auth, service };\n};\n","import { readFile, writeFile, mkdir, unlink } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { TokenData, TokenStore } from \"@kaiord/core\";\n\nconst DEFAULT_PATH = join(homedir(), \".kaiord\", \"garmin-tokens.json\");\n\nexport const createFileTokenStore = (\n filePath: string = DEFAULT_PATH\n): TokenStore => ({\n save: async (tokens: TokenData) => {\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, JSON.stringify(tokens, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n },\n\n load: async (): Promise<TokenData | null> => {\n try {\n const content = await readFile(filePath, \"utf-8\");\n return JSON.parse(content) as TokenData;\n } catch {\n return null;\n }\n },\n\n clear: async () => {\n try {\n await unlink(filePath);\n } catch {\n // File may not exist\n }\n },\n});\n","import type { TokenData, TokenStore } from \"@kaiord/core\";\n\nexport const createMemoryTokenStore = (): TokenStore => {\n let stored: TokenData | null = null;\n\n return {\n save: async (tokens: TokenData) => {\n stored = tokens;\n },\n load: async () => stored,\n clear: async () => {\n stored = null;\n },\n };\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/adapters/http/cookie-fetch.ts","../src/adapters/http/urls.ts","../src/adapters/http/oauth-consumer.ts","../src/adapters/http/sso-html-diagnostics.ts","../src/adapters/http/sso-submit.ts","../src/adapters/http/sso-validators.ts","../src/adapters/http/sso-login.ts","../src/adapters/http/oauth-signer.ts","../src/adapters/http/sso-oauth.ts","../src/adapters/http/garmin-sso.ts","../src/adapters/schemas/garmin-token.schema.ts","../src/adapters/auth/garmin-auth-provider.ts","../src/adapters/token/token-manager.helpers.ts","../src/adapters/token/token-manager.ts","../src/adapters/http/garmin-auth-fetch.ts","../src/adapters/http/garmin-http-client.ts","../src/adapters/http/retry.ts","../src/adapters/client/build-refresh-fn.ts","../src/adapters/mappers/workout-summary.mapper.ts","../src/adapters/schemas/workout-response.schema.ts","../src/adapters/client/pull-workout.ts","../src/adapters/client/remove-workout.ts","../src/adapters/client/garmin-workout-service.ts","../src/adapters/client/garmin-connect-client.ts","../src/adapters/token-store/file-token-store.ts","../src/adapters/token-store/memory-token-store.ts"],"names":["PAGE_TITLE_RE","createServiceAuthError","createServiceApiError","z","createConsoleLogger"],"mappings":"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","file":"index.js","sourcesContent":["import fetchCookie from \"fetch-cookie\";\n\nexport const createCookieFetch = (): typeof globalThis.fetch =>\n fetchCookie(globalThis.fetch) as typeof globalThis.fetch;\n","export const GARMIN_SSO_ORIGIN = \"https://sso.garmin.com\";\nexport const GARMIN_SSO_EMBED = \"https://sso.garmin.com/sso/embed\";\nexport const SIGNIN_URL = \"https://sso.garmin.com/sso/signin\";\nexport const API_BASE = \"https://connectapi.garmin.com\";\nexport const OAUTH_URL = `${API_BASE}/oauth-service/oauth`;\nexport const WORKOUT_URL = `${API_BASE}/workout-service`;\n/** OAuth consumer credentials hosted by the garth project (third-party). */\nexport const OAUTH_CONSUMER_URL =\n \"https://thegarth.s3.amazonaws.com/oauth_consumer.json\";\n\nexport const USER_AGENT_MOBILE = \"com.garmin.android.apps.connectmobile\";\nexport const USER_AGENT_SSO = \"GCM-iOS-5.7.2.1\";\nexport const USER_AGENT_BROWSER =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36\";\n","import type { Logger } from \"@kaiord/core\";\nimport { createServiceAuthError } from \"@kaiord/core\";\n\nimport type { FetchFn, OAuthConsumer } from \"./types\";\nimport { OAUTH_CONSUMER_URL } from \"./urls\";\n\nexport const fetchOAuthConsumer = async (\n fetchFn: FetchFn,\n logger: Logger\n): Promise<OAuthConsumer> => {\n logger.debug(\"[SSO] Fetching OAuth consumer credentials\");\n const res = await fetchFn(OAUTH_CONSUMER_URL);\n if (!res.ok) {\n logger.error(\"[SSO] OAuth consumer fetch failed\", { status: res.status });\n throw createServiceAuthError(\n `Failed to fetch OAuth consumer: ${res.status} ${res.statusText}`\n );\n }\n logger.debug(\"[SSO] OAuth consumer fetch\", { status: res.status });\n const data = (await res.json()) as {\n consumer_key: string;\n consumer_secret: string;\n };\n return { key: data.consumer_key, secret: data.consumer_secret };\n};\n","import type { Logger } from \"@kaiord/core\";\n\nconst PAGE_TITLE_RE = /<title>([^<]*)<\\/title>/;\n\nconst extractTitle = (html: string): string => {\n const match = PAGE_TITLE_RE.exec(html);\n return match?.[1] ?? \"unknown\";\n};\n\nexport const logCsrfResult = (\n logger: Logger,\n status: number,\n size: number,\n found: boolean\n): void => {\n logger.debug(\"[SSO] CSRF fetch\", { status, size });\n if (!found) logger.warn(\"[SSO] CSRF token not found in response\");\n};\n\nexport const logLoginResponse = (\n logger: Logger,\n status: number,\n size: number\n): void => {\n logger.debug(\"[SSO] Login response\", { status, size });\n};\n\nexport const logLoginHtmlDiagnostics = (\n html: string,\n ticketFound: boolean,\n logger: Logger\n): void => {\n const title = extractTitle(html);\n const size = new TextEncoder().encode(html).byteLength;\n logger.debug(\"[SSO] Page title\", { title });\n if (/\\bmfa\\b/i.test(html)) logger.warn(\"[SSO] MFA detected\");\n if (/\\berror\\b/i.test(html)) logger.warn(\"[SSO] Error indicators found\");\n if (ticketFound) {\n logger.debug(\"[SSO] Ticket found in HTML\");\n } else {\n logger.warn(\"[SSO] Ticket not found in HTML\", { size, title });\n }\n};\n","import type { Logger } from \"@kaiord/core\";\n\nimport { logLoginResponse } from \"./sso-html-diagnostics\";\nimport type { FetchFn } from \"./types\";\nimport {\n GARMIN_SSO_EMBED,\n GARMIN_SSO_ORIGIN,\n SIGNIN_URL,\n USER_AGENT_SSO,\n} from \"./urls\";\n\nexport type LoginResult = { html: string; status: number };\n\ntype LoginInput = {\n username: string;\n password: string;\n csrf: string;\n fetchFn: FetchFn;\n logger: Logger;\n};\n\nconst buildLoginParams = (): URLSearchParams =>\n new URLSearchParams({\n id: \"gauth-widget\",\n embedWidget: \"true\",\n gauthHost: GARMIN_SSO_EMBED,\n service: GARMIN_SSO_EMBED,\n source: GARMIN_SSO_EMBED,\n redirectAfterAccountLoginUrl: GARMIN_SSO_EMBED,\n redirectAfterAccountCreationUrl: GARMIN_SSO_EMBED,\n });\n\nexport const submitLogin = async (input: LoginInput): Promise<LoginResult> => {\n const { username, password, csrf, fetchFn, logger } = input;\n logger.debug(\"[SSO] Submitting login\");\n const body = new URLSearchParams({\n username,\n password,\n embed: \"true\",\n _csrf: csrf,\n });\n const loginRes = await fetchFn(`${SIGNIN_URL}?${buildLoginParams()}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Origin: GARMIN_SSO_ORIGIN,\n Referer: `${SIGNIN_URL}?${buildLoginParams()}`,\n \"User-Agent\": USER_AGENT_SSO,\n },\n body: body.toString(),\n });\n const html = await loginRes.text();\n const size = new TextEncoder().encode(html).byteLength;\n logLoginResponse(logger, loginRes.status, size);\n return { html, status: loginRes.status };\n};\n","import type { Logger } from \"@kaiord/core\";\nimport { createServiceAuthError } from \"@kaiord/core\";\n\nconst ACCOUNT_LOCKED_RE = /var status\\s*=\\s*\"([^\"]*)\"/;\nconst PAGE_TITLE_RE = /<title>([^<]*)<\\/title>/;\n\nexport const checkAccountLocked = (html: string): void => {\n const match = ACCOUNT_LOCKED_RE.exec(html);\n if (match && match[1] === \"ACCOUNT_LOCKED\") {\n throw createServiceAuthError(\n `Account locked: ${match[1]}. Unlock via Garmin Connect web.`\n );\n }\n};\n\nexport const checkPageTitle = (html: string, logger: Logger): void => {\n const match = PAGE_TITLE_RE.exec(html);\n if (match?.[1]?.includes(\"Update Phone Number\")) {\n throw createServiceAuthError(\"Login failed: phone number update required.\");\n }\n if (match) {\n logger.debug(\"Login page title\", { title: match[1] });\n }\n};\n","import type { Logger } from \"@kaiord/core\";\nimport { createServiceAuthError } from \"@kaiord/core\";\n\nimport { logCsrfResult, logLoginHtmlDiagnostics } from \"./sso-html-diagnostics\";\nimport { submitLogin } from \"./sso-submit\";\nimport { checkAccountLocked, checkPageTitle } from \"./sso-validators\";\nimport type { FetchFn } from \"./types\";\nimport { GARMIN_SSO_EMBED, SIGNIN_URL, USER_AGENT_SSO } from \"./urls\";\n\nconst CSRF_RE = /name=\"_csrf\"\\s+value=\"(.+?)\"/;\nconst TICKET_RE = /ticket=([^\"]+)\"/;\n\nconst buildSigninParams = (): URLSearchParams =>\n new URLSearchParams({\n id: \"gauth-widget\",\n embedWidget: \"true\",\n gauthHost: GARMIN_SSO_EMBED,\n service: GARMIN_SSO_EMBED,\n source: GARMIN_SSO_EMBED,\n redirectAfterAccountLoginUrl: GARMIN_SSO_EMBED,\n redirectAfterAccountCreationUrl: GARMIN_SSO_EMBED,\n });\n\nconst fetchCsrfToken = async (\n fetchFn: FetchFn,\n embedUrl: string,\n logger: Logger\n): Promise<string> => {\n logger.debug(\"[SSO] Fetching CSRF token\");\n const signinParams = buildSigninParams();\n const csrfRes = await fetchFn(`${SIGNIN_URL}?${signinParams}`, {\n headers: {\n \"User-Agent\": USER_AGENT_SSO,\n Referer: embedUrl,\n },\n });\n const csrfHtml = await csrfRes.text();\n const csrfMatch = CSRF_RE.exec(csrfHtml);\n const size = new TextEncoder().encode(csrfHtml).byteLength;\n logCsrfResult(logger, csrfRes.status, size, !!csrfMatch);\n if (!csrfRes.ok) {\n throw createServiceAuthError(\n `SSO login page returned ${csrfRes.status}: ${csrfRes.statusText}`\n );\n }\n if (!csrfMatch) {\n throw createServiceAuthError(\"CSRF token not found on login page\");\n }\n return csrfMatch[1];\n};\n\nexport const getLoginTicket = async (\n username: string,\n password: string,\n fetchFn: FetchFn,\n logger: Logger\n): Promise<string> => {\n const embedParams = new URLSearchParams({\n id: \"gauth-widget\",\n embedWidget: \"true\",\n gauthHost: \"https://sso.garmin.com/sso\",\n });\n const embedUrl = `${GARMIN_SSO_EMBED}?${embedParams}`;\n const embedRes = await fetchFn(embedUrl, {\n headers: { \"User-Agent\": USER_AGENT_SSO },\n });\n logger.debug(\"[SSO] Embed bootstrap\", { status: embedRes.status });\n if (!embedRes.ok) {\n throw createServiceAuthError(\n `SSO embed bootstrap failed: ${embedRes.status} ${embedRes.statusText}`\n );\n }\n\n const csrf = await fetchCsrfToken(fetchFn, embedUrl, logger);\n const { html: loginHtml } = await submitLogin({\n username,\n password,\n csrf,\n fetchFn,\n logger,\n });\n\n checkAccountLocked(loginHtml);\n checkPageTitle(loginHtml, logger);\n\n const ticketMatch = TICKET_RE.exec(loginHtml);\n logLoginHtmlDiagnostics(loginHtml, !!ticketMatch, logger);\n if (!ticketMatch) {\n throw createServiceAuthError(\n \"Login failed: ticket not found. Check username and password.\"\n );\n }\n return ticketMatch[1];\n};\n","import { createHmac } from \"node:crypto\";\n\nimport OAuth from \"oauth-1.0a\";\n\nimport type { OAuthConsumer } from \"./types\";\n\nexport type { OAuthConsumer } from \"./types\";\nexport type OAuthToken = { key: string; secret: string };\n\nexport type OAuthSigner = {\n toHeader: (\n request: { url: string; method: string },\n token?: OAuthToken\n ) => Record<string, string>;\n};\n\nexport const createOAuthSigner = (consumer: OAuthConsumer): OAuthSigner => {\n const oauth = new OAuth({\n consumer,\n signature_method: \"HMAC-SHA1\",\n hash_function(baseString: string, key: string) {\n return createHmac(\"sha1\", key).update(baseString).digest(\"base64\");\n },\n });\n\n return {\n toHeader: (request, token) => {\n const authorized = token\n ? oauth.authorize(request, token)\n : oauth.authorize(request);\n const header = oauth.toHeader(authorized);\n return Object.fromEntries(Object.entries(header));\n },\n };\n};\n","import type { Logger } from \"@kaiord/core\";\nimport { createServiceAuthError } from \"@kaiord/core\";\n\nimport { createOAuthSigner } from \"./oauth-signer\";\nimport type { FetchFn, OAuthConsumer } from \"./types\";\nimport type { OAuth1Token, OAuth2Token } from \"./types\";\nimport { GARMIN_SSO_EMBED, OAUTH_URL, USER_AGENT_MOBILE } from \"./urls\";\n\nexport const getOAuth1Token = async (\n ticket: string,\n consumer: OAuthConsumer,\n fetchFn: FetchFn,\n logger: Logger\n): Promise<OAuth1Token> => {\n const signer = createOAuthSigner(consumer);\n const params = new URLSearchParams({\n ticket,\n \"login-url\": GARMIN_SSO_EMBED,\n \"accepts-mfa-tokens\": \"true\",\n });\n const url = `${OAUTH_URL}/preauthorized?${params}`;\n const headers = signer.toHeader({ url, method: \"GET\" });\n\n const res = await fetchFn(url, {\n headers: { ...headers, \"User-Agent\": USER_AGENT_MOBILE },\n });\n logger.debug(\"[SSO] OAuth1 token response\", { status: res.status });\n if (!res.ok) {\n throw createServiceAuthError(\n `OAuth1 token request failed: ${res.status} ${res.statusText}`\n );\n }\n const text = await res.text();\n const parsed = new URLSearchParams(text);\n\n const oauthToken = parsed.get(\"oauth_token\");\n const oauthTokenSecret = parsed.get(\"oauth_token_secret\");\n if (!oauthToken || !oauthTokenSecret) {\n throw createServiceAuthError(\"OAuth1 token exchange failed\");\n }\n\n return { oauth_token: oauthToken, oauth_token_secret: oauthTokenSecret };\n};\n\nexport const exchangeOAuth2 = async (\n oauth1: OAuth1Token,\n consumer: OAuthConsumer,\n fetchFn: FetchFn,\n logger: Logger\n): Promise<OAuth2Token> => {\n const signer = createOAuthSigner(consumer);\n const baseUrl = `${OAUTH_URL}/exchange/user/2.0`;\n const token = {\n key: oauth1.oauth_token,\n secret: oauth1.oauth_token_secret,\n };\n const authHeader = signer.toHeader({ url: baseUrl, method: \"POST\" }, token);\n\n const res = await fetchFn(baseUrl, {\n method: \"POST\",\n headers: {\n ...authHeader,\n \"User-Agent\": USER_AGENT_MOBILE,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n });\n logger.debug(\"[SSO] OAuth2 exchange response\", { status: res.status });\n if (!res.ok) {\n throw createServiceAuthError(\n `OAuth2 exchange failed: ${res.status} ${res.statusText}`\n );\n }\n const data = (await res.json()) as OAuth2Token;\n\n return {\n ...data,\n expires_at: Math.floor(Date.now() / 1000) + data.expires_in,\n };\n};\n","import type { Logger } from \"@kaiord/core\";\n\nimport { fetchOAuthConsumer } from \"./oauth-consumer\";\nimport { getLoginTicket } from \"./sso-login\";\nimport { exchangeOAuth2 as exchange, getOAuth1Token } from \"./sso-oauth\";\nimport type { FetchFn, OAuth1Token, OAuth2Token } from \"./types\";\n\nexport type { OAuth1Token, OAuth2Token } from \"./types\";\nexport type SsoResult = { oauth1: OAuth1Token; oauth2: OAuth2Token };\n\n/**\n * Garmin Connect SSO login flow.\n * The fetchFn must be cookie-aware (persist cookies across requests).\n * Use fetch-cookie or similar wrapper for Node.js environments.\n */\nexport const garminSso = async (\n username: string,\n password: string,\n logger: Logger,\n fetchFn: FetchFn\n): Promise<SsoResult> => {\n logger.info(\"Starting Garmin Connect SSO login\");\n\n logger.info(\"[SSO] Step 1/4: OAuth consumer\");\n const consumer = await fetchOAuthConsumer(fetchFn, logger);\n\n logger.info(\"[SSO] Step 2/4: Login ticket\");\n const ticket = await getLoginTicket(username, password, fetchFn, logger);\n\n logger.info(\"[SSO] Step 3/4: OAuth1 token\");\n const oauth1 = await getOAuth1Token(ticket, consumer, fetchFn, logger);\n\n logger.info(\"[SSO] Step 4/4: OAuth2 exchange\");\n const oauth2 = await exchange(oauth1, consumer, fetchFn, logger);\n\n logger.info(\"Garmin Connect SSO login successful\");\n return { oauth1, oauth2 };\n};\n\nexport { exchangeOAuth2 } from \"./sso-oauth\";\n","import { z } from \"zod\";\n\nexport const oauth1TokenSchema = z.object({\n oauth_token: z.string(),\n oauth_token_secret: z.string(),\n});\n\nexport const oauth2TokenSchema = z.object({\n access_token: z.string(),\n refresh_token: z.string(),\n token_type: z.string(),\n expires_in: z.number(),\n refresh_token_expires_in: z.number(),\n expires_at: z.number(),\n});\n\nexport const garminTokensSchema = z.object({\n oauth1: oauth1TokenSchema,\n oauth2: oauth2TokenSchema,\n});\n","import type { AuthProvider, Logger } from \"@kaiord/core\";\nimport { createConsoleLogger, createServiceAuthError } from \"@kaiord/core\";\n\nimport { createCookieFetch } from \"../http/cookie-fetch\";\nimport { garminSso } from \"../http/garmin-sso\";\nimport type { FetchFn } from \"../http/types\";\nimport { garminTokensSchema } from \"../schemas/garmin-token.schema\";\nimport type { TokenManager } from \"../token/token-manager.types\";\n\nexport type GarminAuthProviderOptions = {\n tokenManager: TokenManager;\n logger?: Logger;\n fetchFn?: FetchFn;\n};\n\nconst buildAuthProvider = (\n tm: TokenManager,\n logger: Logger,\n fetchFn: FetchFn\n): AuthProvider => ({\n login: async (username, password) => {\n const result = await garminSso(username, password, logger, fetchFn);\n await tm.setTokens(result.oauth1, result.oauth2);\n },\n is_authenticated: () => tm.isAuthenticated(),\n export_tokens: async () => {\n const oauth1 = tm.getOAuth1Token();\n const oauth2 = tm.getOAuth2Token();\n if (!oauth1 || !oauth2) {\n throw createServiceAuthError(\"No tokens to export\");\n }\n return { oauth1: { ...oauth1 }, oauth2: { ...oauth2 } };\n },\n restore_tokens: async (data) => {\n const parsed = garminTokensSchema.parse(data);\n await tm.setTokens(parsed.oauth1, parsed.oauth2);\n logger.info(\"Tokens restored from stored session\");\n },\n logout: async () => {\n await tm.clearTokens();\n logger.info(\"Logged out from Garmin Connect\");\n },\n});\n\nexport const createGarminAuthProvider = (\n options: GarminAuthProviderOptions\n): AuthProvider => {\n const logger = options.logger ?? createConsoleLogger();\n const fetchFn = options.fetchFn ?? createCookieFetch();\n return buildAuthProvider(options.tokenManager, logger, fetchFn);\n};\n","import type { Logger, TokenStore } from \"@kaiord/core\";\nimport { createServiceApiError } from \"@kaiord/core\";\n\nimport type { OAuth1Token, OAuth2Token } from \"../http/types\";\nimport { garminTokensSchema } from \"../schemas/garmin-token.schema\";\nimport type { RefreshFn } from \"./token-manager.types\";\n\nexport type TokenState = {\n oauth1: OAuth1Token | undefined;\n oauth2: OAuth2Token | undefined;\n generation: number;\n refreshPromise: Promise<void> | undefined;\n};\n\nexport const persistBestEffort = async (\n store: TokenStore | undefined,\n oauth1: OAuth1Token,\n oauth2: OAuth2Token,\n logger: Logger\n): Promise<void> => {\n if (!store) return;\n try {\n await store.save({ oauth1, oauth2 });\n } catch (error) {\n logger.warn(\"Failed to persist tokens\", {\n errorName: error instanceof Error ? error.name : typeof error,\n });\n }\n};\n\nexport const isExpired = (oauth2: OAuth2Token | undefined): boolean =>\n !oauth2 || oauth2.expires_at <= Date.now() / 1000;\n\nexport const doRefresh = (\n s: TokenState,\n refreshFn: RefreshFn,\n logger: Logger,\n tokenStore: TokenStore | undefined\n): Promise<void> => {\n if (!s.oauth1) {\n throw createServiceApiError(\"No OAuth1 token for refresh\", 401);\n }\n const currentOAuth1 = s.oauth1;\n const generationAtStart = s.generation;\n s.refreshPromise = refreshFn(currentOAuth1)\n .then(async (newOAuth2) => {\n if (s.generation !== generationAtStart) return;\n s.oauth2 = newOAuth2;\n s.generation++;\n logger.info(\"Token refreshed\", { generation: s.generation });\n await persistBestEffort(tokenStore, currentOAuth1, newOAuth2, logger);\n })\n .finally(() => {\n s.refreshPromise = undefined;\n });\n return s.refreshPromise;\n};\n\nexport const restoreFromStore = async (\n s: TokenState,\n tokenStore: TokenStore,\n logger: Logger\n): Promise<{ restored: boolean }> => {\n const data = await tokenStore.load();\n if (!data) return { restored: false };\n if (s.oauth1 && s.oauth2) return { restored: false };\n const parsed = garminTokensSchema.safeParse(data);\n if (!parsed.success) return { restored: false };\n s.oauth1 = parsed.data.oauth1;\n s.oauth2 = parsed.data.oauth2;\n s.generation++;\n if (isExpired(s.oauth2)) logger.warn(\"Restored tokens are expired\");\n logger.info(\"Tokens restored from store\", { generation: s.generation });\n return { restored: true };\n};\n","import type { Logger, TokenStore } from \"@kaiord/core\";\n\nimport type { TokenState } from \"./token-manager.helpers\";\nimport {\n doRefresh,\n isExpired,\n persistBestEffort,\n restoreFromStore,\n} from \"./token-manager.helpers\";\nimport type { RefreshFn, TokenManager } from \"./token-manager.types\";\n\ntype Options = {\n refreshFn: RefreshFn;\n logger: Logger;\n tokenStore?: TokenStore;\n};\n\nexport const createTokenManager = (options: Options): TokenManager => {\n const { refreshFn, logger, tokenStore } = options;\n const s: TokenState = {\n oauth1: undefined,\n oauth2: undefined,\n generation: 0,\n refreshPromise: undefined,\n };\n\n return {\n getAccessToken: () => s.oauth2?.access_token,\n getOAuth1Token: () => (s.oauth1 ? { ...s.oauth1 } : undefined),\n getOAuth2Token: () => (s.oauth2 ? { ...s.oauth2 } : undefined),\n getGeneration: () => s.generation,\n isAuthenticated: () => !!s.oauth2 && !isExpired(s.oauth2),\n setTokens: async (o1, o2) => {\n s.oauth1 = o1;\n s.oauth2 = o2;\n s.generation++;\n logger.info(\"Tokens set\", { generation: s.generation });\n await persistBestEffort(tokenStore, o1, o2, logger);\n },\n clearTokens: async () => {\n s.oauth1 = undefined;\n s.oauth2 = undefined;\n s.refreshPromise = undefined;\n s.generation++;\n logger.info(\"Tokens cleared\");\n if (tokenStore) await tokenStore.clear();\n },\n refresh: async () => {\n if (s.refreshPromise) return s.refreshPromise;\n return doRefresh(s, refreshFn, logger, tokenStore);\n },\n init: async () => {\n if (s.oauth1 && s.oauth2) return { restored: false };\n if (!tokenStore) return { restored: false };\n return restoreFromStore(s, tokenStore, logger);\n },\n };\n};\n","import { createServiceApiError } from \"@kaiord/core\";\n\nimport type { TokenReader } from \"../token/token-manager.types\";\nimport type { FetchFn } from \"./types\";\n\nconst sendRequest = (\n url: string,\n init: RequestInit | undefined,\n token: string,\n fetchFn: FetchFn\n): Promise<Response> =>\n fetchFn(url, {\n ...init,\n headers: { ...init?.headers, Authorization: `Bearer ${token}` },\n });\n\nconst getTokenOrThrow = (reader: TokenReader, msg: string): string => {\n const token = reader.getAccessToken();\n if (!token) throw createServiceApiError(msg, 401);\n return token;\n};\n\nconst handleNonOk = (res: Response, prefix: string): never => {\n throw createServiceApiError(`${prefix}: ${res.statusText}`, res.status);\n};\n\nexport const authFetch = async (\n url: string,\n init: RequestInit | undefined,\n reader: TokenReader,\n fetchFn: FetchFn\n): Promise<Response> => {\n if (!reader.isAuthenticated()) await reader.refresh();\n const gen = reader.getGeneration();\n const token = getTokenOrThrow(reader, \"Not authenticated\");\n const res = await sendRequest(url, init, token, fetchFn);\n\n if (res.status !== 401) {\n if (!res.ok) handleNonOk(res, \"API request failed\");\n return res;\n }\n\n if (reader.getGeneration() === gen) await reader.refresh();\n const freshToken = getTokenOrThrow(reader, \"Token unavailable after refresh\");\n const retry = await sendRequest(url, init, freshToken, fetchFn);\n if (!retry.ok) handleNonOk(retry, \"API request failed after token refresh\");\n return retry;\n};\n","import type { Logger } from \"@kaiord/core\";\n\nimport type { TokenReader } from \"../token/token-manager.types\";\nimport { authFetch } from \"./garmin-auth-fetch\";\nimport type { FetchFn, GarminHttpClient } from \"./types\";\n\nexport type { GarminHttpClient } from \"./types\";\n\nexport const createGarminHttpClient = (\n tokenReader: TokenReader,\n fetchFn: FetchFn,\n logger: Logger\n): GarminHttpClient => {\n const fetch = (url: string, init?: RequestInit) =>\n authFetch(url, init, tokenReader, fetchFn);\n\n logger.debug(\"HTTP client created\");\n\n return {\n get: async <T>(url: string): Promise<T> => {\n const res = await fetch(url);\n return (await res.json()) as T;\n },\n post: async <T>(url: string, body: unknown): Promise<T> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: body !== null ? JSON.stringify(body) : undefined,\n });\n return (await res.json()) as T;\n },\n del: async <T>(url: string): Promise<T> => {\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"X-Http-Method-Override\": \"DELETE\" },\n });\n const text = await res.text();\n return (text ? JSON.parse(text) : undefined) as T;\n },\n };\n};\n","import type { Logger } from \"@kaiord/core\";\n\nimport type { FetchFn } from \"./types\";\n\nexport type RetryOptions = {\n maxRetries?: number;\n baseDelay?: number;\n maxDelay?: number;\n randomFn?: () => number;\n logger?: Logger;\n};\n\ntype ResolvedOptions = {\n maxRetries: number;\n baseDelay: number;\n maxDelay: number;\n randomFn: () => number;\n logger?: Logger;\n};\n\nconst isRetryable = (status: number): boolean =>\n status === 429 || (status >= 500 && status <= 599);\n\nconst computeDelay = (\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n randomFn: () => number\n): number => randomFn() * Math.min(maxDelay, baseDelay * 2 ** attempt);\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst waitAndLog = (\n opts: ResolvedOptions,\n attempt: number,\n message: string,\n info: Record<string, unknown>\n): Promise<void> => {\n const delay = computeDelay(\n attempt,\n opts.baseDelay,\n opts.maxDelay,\n opts.randomFn\n );\n opts.logger?.debug(message, { ...info, delay: Math.round(delay) });\n return sleep(delay);\n};\n\nconst handleRetryableResponse = async (\n attempt: number,\n response: Response,\n opts: ResolvedOptions\n): Promise<boolean> => {\n if (attempt < opts.maxRetries && isRetryable(response.status)) {\n await waitAndLog(opts, attempt, \"Retrying request\", {\n attempt: attempt + 1,\n status: response.status,\n });\n return true;\n }\n return false;\n};\n\nconst handleRetryableError = async (\n attempt: number,\n error: unknown,\n opts: ResolvedOptions\n): Promise<boolean> => {\n if (attempt < opts.maxRetries && error instanceof TypeError) {\n await waitAndLog(opts, attempt, \"Retrying request after network error\", {\n attempt: attempt + 1,\n error: (error as Error).message,\n });\n return true;\n }\n return false;\n};\n\nexport const withRetry = (\n fetchFn: FetchFn,\n options?: RetryOptions\n): FetchFn => {\n const opts: ResolvedOptions = {\n maxRetries: options?.maxRetries ?? 3,\n baseDelay: options?.baseDelay ?? 1000,\n maxDelay: options?.maxDelay ?? 10000,\n randomFn: options?.randomFn ?? Math.random,\n logger: options?.logger,\n };\n\n return async (input, init?) => {\n for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {\n try {\n const response = await fetchFn(input, init);\n if (await handleRetryableResponse(attempt, response, opts)) continue;\n return response;\n } catch (error) {\n if (await handleRetryableError(attempt, error, opts)) continue;\n throw error;\n }\n }\n /* istanbul ignore next -- unreachable */\n throw new Error(\"Unexpected retry exhaustion\");\n };\n};\n","import type { Logger } from \"@kaiord/core\";\n\nimport { fetchOAuthConsumer } from \"../http/oauth-consumer\";\nimport { exchangeOAuth2 } from \"../http/sso-oauth\";\nimport type { FetchFn, OAuthConsumer } from \"../http/types\";\nimport type { RefreshFn } from \"../token/token-manager.types\";\n\nexport const buildRefreshFn = (fetchFn: FetchFn, logger: Logger): RefreshFn => {\n let consumer: OAuthConsumer | undefined;\n\n return async (oauth1) => {\n consumer ??= await fetchOAuthConsumer(fetchFn, logger);\n try {\n return await exchangeOAuth2(oauth1, consumer, fetchFn, logger);\n } catch {\n consumer = undefined;\n consumer = await fetchOAuthConsumer(fetchFn, logger);\n return exchangeOAuth2(oauth1, consumer, fetchFn, logger);\n }\n };\n};\n","import type { WorkoutSummary } from \"@kaiord/core\";\n\nexport const mapToWorkoutSummary = (garminWorkout: {\n workoutId?: number | string;\n workoutName?: string;\n sportType?: { sportTypeKey?: string };\n createdDate?: number | string;\n updatedDate?: number | string;\n}): WorkoutSummary => ({\n id: String(garminWorkout.workoutId ?? \"\"),\n name: garminWorkout.workoutName ?? \"Unnamed\",\n sport: garminWorkout.sportType?.sportTypeKey ?? \"unknown\",\n created_at: garminWorkout.createdDate\n ? new Date(garminWorkout.createdDate).toISOString()\n : \"\",\n updated_at: garminWorkout.updatedDate\n ? new Date(garminWorkout.updatedDate).toISOString()\n : \"\",\n});\n","import { z } from \"zod\";\n\n/** GET /workout-service/workouts?start=N&limit=N - List workout summaries */\nexport const garminWorkoutSummarySchema = z.object({\n workoutId: z.number().or(z.string()),\n workoutName: z.string().optional(),\n sportType: z.object({ sportTypeKey: z.string().optional() }).optional(),\n createdDate: z.number().or(z.string()).optional(),\n updatedDate: z.number().or(z.string()).optional(),\n});\n\n/** POST /workout-service/workout - Push a workout (returns created workout) */\nexport const garminPushResponseSchema = z.object({\n workoutId: z.number().or(z.string()),\n workoutName: z.string().optional(),\n});\n","import type { KRD, Logger } from \"@kaiord/core\";\nimport { createServiceApiError, fromText } from \"@kaiord/core\";\nimport type { createGarminReader } from \"@kaiord/garmin\";\n\nimport type { GarminHttpClient } from \"../http/types\";\nimport { WORKOUT_URL } from \"../http/urls\";\n\nexport const pullWorkout = async (\n workoutId: string,\n httpClient: GarminHttpClient,\n garminReader: ReturnType<typeof createGarminReader>,\n log: Logger\n): Promise<KRD> => {\n try {\n log.info(`Pulling workout ${workoutId} from Garmin Connect`);\n const raw = await httpClient.get<unknown>(\n `${WORKOUT_URL}/workout/${workoutId}`\n );\n const gcnJson = JSON.stringify(raw);\n return await fromText(gcnJson, garminReader, log);\n } catch (error) {\n throw createServiceApiError(\"Failed to pull workout\", undefined, error);\n }\n};\n","import type { Logger } from \"@kaiord/core\";\nimport { createServiceApiError } from \"@kaiord/core\";\n\nimport type { GarminHttpClient } from \"../http/types\";\nimport { WORKOUT_URL } from \"../http/urls\";\n\nexport const removeWorkout = async (\n workoutId: string,\n httpClient: GarminHttpClient,\n log: Logger\n): Promise<void> => {\n try {\n log.info(`Removing workout ${workoutId} from Garmin Connect`);\n await httpClient.del(`${WORKOUT_URL}/workout/${workoutId}`);\n } catch (error) {\n throw createServiceApiError(\"Failed to remove workout\", undefined, error);\n }\n};\n","import type {\n KRD,\n ListOptions,\n Logger,\n PushResult,\n WorkoutService,\n WorkoutSummary,\n} from \"@kaiord/core\";\nimport {\n createConsoleLogger,\n createServiceApiError,\n toText,\n} from \"@kaiord/core\";\nimport { createGarminReader, createGarminWriter } from \"@kaiord/garmin\";\n\nimport type { GarminHttpClient } from \"../http/types\";\nimport { WORKOUT_URL } from \"../http/urls\";\nimport { mapToWorkoutSummary } from \"../mappers/workout-summary.mapper\";\nimport {\n garminPushResponseSchema,\n garminWorkoutSummarySchema,\n} from \"../schemas/workout-response.schema\";\nimport { pullWorkout } from \"./pull-workout\";\nimport { removeWorkout } from \"./remove-workout\";\n\nexport type GarminWorkoutClient = WorkoutService;\n\nconst pushWorkout = async (\n krd: KRD,\n httpClient: GarminHttpClient,\n garminWriter: ReturnType<typeof createGarminWriter>,\n log: Logger\n): Promise<PushResult> => {\n try {\n log.info(\"Pushing workout to Garmin Connect\");\n const gcnJson = await toText(krd, garminWriter, log);\n const payload = JSON.parse(gcnJson) as Record<string, unknown>;\n const raw = await httpClient.post<unknown>(\n `${WORKOUT_URL}/workout`,\n payload\n );\n const result = garminPushResponseSchema.parse(raw);\n return {\n id: String(result.workoutId),\n name: result.workoutName ?? \"Workout\",\n url: `https://connect.garmin.com/modern/workout/${result.workoutId}`,\n };\n } catch (error) {\n throw createServiceApiError(\"Failed to push workout\", undefined, error);\n }\n};\n\nconst listWorkouts = async (\n httpClient: GarminHttpClient,\n log: Logger,\n options?: ListOptions\n): Promise<WorkoutSummary[]> => {\n try {\n log.info(\"Listing workouts from Garmin Connect\");\n const start = options?.offset ?? 0;\n const limit = options?.limit ?? 20;\n const params = new URLSearchParams({\n start: String(start),\n limit: String(limit),\n });\n const raw = await httpClient.get<unknown>(\n `${WORKOUT_URL}/workouts?${params}`\n );\n const workouts = garminWorkoutSummarySchema.array().parse(raw);\n return workouts.map(mapToWorkoutSummary);\n } catch (error) {\n throw createServiceApiError(\"Failed to list workouts\", undefined, error);\n }\n};\n\nexport const createGarminWorkoutService = (\n httpClient: GarminHttpClient,\n logger?: Logger\n): GarminWorkoutClient => {\n const log = logger ?? createConsoleLogger();\n const garminWriter = createGarminWriter(log);\n const garminReader = createGarminReader(log);\n\n return {\n push: (krd) => pushWorkout(krd, httpClient, garminWriter, log),\n pull: (id) => pullWorkout(id, httpClient, garminReader, log),\n list: (opts) => listWorkouts(httpClient, log, opts),\n remove: (id) => removeWorkout(id, httpClient, log),\n };\n};\n","import { createConsoleLogger } from \"@kaiord/core\";\n\nimport { createGarminAuthProvider } from \"../auth/garmin-auth-provider\";\nimport { createCookieFetch } from \"../http/cookie-fetch\";\nimport { createGarminHttpClient } from \"../http/garmin-http-client\";\nimport { withRetry } from \"../http/retry\";\nimport { createTokenManager } from \"../token/token-manager\";\nimport { buildRefreshFn } from \"./build-refresh-fn\";\nimport type {\n GarminConnectClient,\n GarminConnectClientOptions,\n} from \"./garmin-connect-client.types\";\nimport { createGarminWorkoutService } from \"./garmin-workout-service\";\n\nexport type {\n GarminConnectClient,\n GarminConnectClientOptions,\n InitResult,\n} from \"./garmin-connect-client.types\";\n\n/**\n * Create a Garmin Connect client with auth, workout service, and optional token auto-restore.\n *\n * @example\n * ```ts\n * const client = createGarminConnectClient({\n * tokenStore: createFileTokenStore(),\n * retry: { maxRetries: 3 },\n * });\n * const { restored } = await client.init();\n * if (!restored) await client.auth.login(email, password);\n * ```\n */\nexport const createGarminConnectClient = (\n options?: GarminConnectClientOptions\n): GarminConnectClient => {\n const logger = options?.logger ?? createConsoleLogger();\n const rawFetchFn = options?.fetchFn ?? createCookieFetch();\n const retryFetchFn = options?.retry\n ? withRetry(rawFetchFn, { ...options.retry, logger })\n : rawFetchFn;\n\n const refreshFn = buildRefreshFn(rawFetchFn, logger);\n const tokenManager = createTokenManager({\n refreshFn,\n logger,\n tokenStore: options?.tokenStore,\n });\n\n const auth = createGarminAuthProvider({\n tokenManager,\n logger,\n fetchFn: rawFetchFn,\n });\n const httpClient = createGarminHttpClient(tokenManager, retryFetchFn, logger);\n const service = createGarminWorkoutService(httpClient, logger);\n\n return {\n auth,\n service,\n init: () => tokenManager.init(),\n };\n};\n","import { mkdir, readFile, unlink, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport type { TokenData, TokenStore } from \"@kaiord/core\";\n\nconst DEFAULT_PATH = join(homedir(), \".kaiord\", \"garmin-tokens.json\");\n\nexport const createFileTokenStore = (\n filePath: string = DEFAULT_PATH\n): TokenStore => ({\n save: async (tokens: TokenData) => {\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, JSON.stringify(tokens, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n },\n\n load: async (): Promise<TokenData | null> => {\n try {\n const content = await readFile(filePath, \"utf-8\");\n return JSON.parse(content) as TokenData;\n } catch {\n return null;\n }\n },\n\n clear: async () => {\n try {\n await unlink(filePath);\n } catch {\n // File may not exist\n }\n },\n});\n","import type { TokenData, TokenStore } from \"@kaiord/core\";\n\nexport const createMemoryTokenStore = (): TokenStore => {\n let stored: TokenData | null = null;\n\n return {\n save: async (tokens: TokenData) => {\n stored = tokens;\n },\n load: async () => stored,\n clear: async () => {\n stored = null;\n },\n };\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaiord/garmin-connect",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Garmin Connect API client for the Kaiord health & fitness data framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,16 +19,16 @@
|
|
|
19
19
|
"fetch-cookie": "^3.2.0",
|
|
20
20
|
"oauth-1.0a": "^2.2.6",
|
|
21
21
|
"zod": "^4.0.0",
|
|
22
|
-
"@kaiord/
|
|
23
|
-
"@kaiord/
|
|
22
|
+
"@kaiord/core": "^7.0.0",
|
|
23
|
+
"@kaiord/garmin": "^7.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@types/node": "^25.
|
|
27
|
-
"@vitest/coverage-v8": "^4.
|
|
26
|
+
"@types/node": "^25.6.0",
|
|
27
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
28
28
|
"tsup": "^8.5.1",
|
|
29
29
|
"tsx": "^4.21.0",
|
|
30
30
|
"typescript": "^5.3.3",
|
|
31
|
-
"vitest": "^4.
|
|
31
|
+
"vitest": "^4.1.4"
|
|
32
32
|
},
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|
|
@@ -52,6 +52,9 @@
|
|
|
52
52
|
],
|
|
53
53
|
"author": "Kaiord Contributors",
|
|
54
54
|
"license": "MIT",
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=22.12.0"
|
|
57
|
+
},
|
|
55
58
|
"scripts": {
|
|
56
59
|
"build": "tsup",
|
|
57
60
|
"test": "vitest --run",
|