Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/skills
134 changes: 0 additions & 134 deletions .claude/skills/create-changelog/SKILL.md

This file was deleted.

18 changes: 18 additions & 0 deletions .codemie/codemie-cli.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": 2,
"activeProfile": "codemie-sso",
"profiles": {
"codemie-sso": {
"codeMieProject": "bohdan_balov@epam.com",
"provider": "ai-run-sso",
"codeMieUrl": "https://codemie.lab.epam.com",
"apiKey": "sso-provided",
"baseUrl": "https://codemie.lab.epam.com/code-assistant-api",
"model": "claude-haiku-4-5-20251001",
"haikuModel": "claude-haiku-4-5-20251001",
"sonnetModel": "claude-haiku-4-5-20251001",
"opusModel": "claude-opus-4-8",
"name": "codemie-sso"
}
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dist
node_modules
.env
11 changes: 11 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer ${GITHUB_MCP_TOKEN}"
}
}
}
}
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24.11.1
24
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ Please, document here only changes visible to the client app.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0] - 2026-06-03

### [55 Query Athlete](https://github.com/torqlab/torq/issues/55)

### Added

- Fetch athlete module with `fetchStravaAthlete` function to retrieve authenticated athlete profile data
- `StravaAthlete` TypeScript type definition for athlete response validation
- New API endpoint constant for athlete endpoint

## [1.1.1] - 2026-03-03

### [47 Better Error Handling](https://github.com/torqlab/torq/issues/47)
Expand Down
1 change: 1 addition & 0 deletions constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const STRAVA_API_BASE_URL = 'https://www.strava.com/api/v3';
export const STRAVA_API_ENDPOINTS = {
TOKEN: `${STRAVA_OAUTH_BASE_URL}/token`,
AUTH: `${STRAVA_OAUTH_BASE_URL}/authorize`,
ATHLETE: `${STRAVA_API_BASE_URL}/athlete`,
ACTIVITIES: `${STRAVA_API_BASE_URL}/athlete/activities`,

/**
Expand Down
58 changes: 58 additions & 0 deletions fetch-athlete/fetch-athlete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import client, { handleRetry } from '../client';
import {
STRAVA_API_MAX_RETRIES,
STRAVA_API_INITIAL_BACKOFF_MS,
STRAVA_API_ENDPOINTS,
} from '../constants';
import type { StravaApiConfig, StravaAthlete } from '../types';

/**
* Fetches the authenticated athlete from Strava API.
*
* Main entry point for fetching authenticated athlete data. Orchestrates the complete flow:
* fetches data from Strava API with retry logic, handles rate limiting and token refresh,
* and returns the raw Strava API response format.
*
* This function is typically called to retrieve the current user's athlete profile
* for display or processing purposes.
*
* The function implements the following flow:
* 1. Fetches from API with automatic retry on retryable errors
* 2. Handles rate limiting by waiting before retry
* 3. Attempts token refresh on 401 errors (if refresh token available)
* 4. Returns raw API response
*
* @param {StravaApiConfig} config - Strava API configuration including OAuth tokens.
* @returns {Promise<StravaAthlete>} Promise resolving to authenticated athlete in raw Strava API format.
* @throws {Error} Throws an error with StravaApiError structure for various failure scenarios:
* - 'UNAUTHORIZED' (not retryable): Authentication failed (after refresh attempt if applicable)
* - 'FORBIDDEN' (not retryable): Insufficient permissions
* - 'RATE_LIMITED' (retryable): Rate limit exceeded (handled with retry)
* - 'SERVER_ERROR' (retryable): Strava API server error (handled with retry)
* - 'NETWORK_ERROR' (retryable): Network connection failure (handled with retry)
* - 'MALFORMED_RESPONSE' (not retryable): Invalid API response format
*
* @see {@link https://developers.strava.com/docs/reference/#api-Athletes-getLoggedInAthlete | Strava Get Logged In Athlete API}
*
* @example
* ```typescript
* const athlete = await fetchAthlete({
* accessToken: 'abc123',
* });
* ```
*/
const fetchAthlete = async (config: StravaApiConfig): Promise<StravaAthlete> =>
handleRetry({
maxRetries: STRAVA_API_MAX_RETRIES,
initialBackoffMs: STRAVA_API_INITIAL_BACKOFF_MS,

/**
* Fetches from Strava API.
* @returns {Promise<StravaAthlete>} Promise resolving to API response.
* @throws {Error} Throws error for rate limits, unauthorized errors, or other API errors.
* @internal
*/
fn: (): Promise<StravaAthlete> => client<StravaAthlete>(STRAVA_API_ENDPOINTS.ATHLETE, config),
});

export default fetchAthlete;
1 change: 1 addition & 0 deletions fetch-athlete/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './fetch-athlete';
3 changes: 2 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { default as fetchStravaActivity } from './fetch-activity';
export { default as fetchStravaActivities } from './fetch-activities';
export { default as fetchStravaAthlete } from './fetch-athlete';
export { default as getStravaAuthUrl } from './get-auth-url';
export { default as exchangeStravaAuthToken } from './exchange-token';
export { default as refreshStravaAuthToken } from './refresh-token';
export type { StravaApiConfig, StravaActivity } from './types';
export type { StravaApiConfig, StravaActivity, StravaAthlete } from './types';
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@torqlab/strava-api",
"version": "1.1.1",
"version": "1.2.0",
"description": "Strava API client with automatic rate limiting, retry handling, and comprehensive type safety.",
"license": "MIT",
"author": {
Expand Down
28 changes: 28 additions & 0 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,34 @@ export interface StravaApiTokenRefreshResponse {
refresh_token?: string;
}

/**
* Strava Athlete type.
* The type is dictated by the Strava API and used internally by the system.
* @see {@link https://developers.strava.com/docs/reference/#api-Athletes-getLoggedInAthlete | Strava Get Logged In Athlete Response Format}
*/
export interface StravaAthlete {
id: number;
resource_state?: number;
firstname?: string;
lastname?: string;
city?: string;
state?: string;
country?: string;
sex?: string;
summit?: boolean;
premium?: boolean;
created_at?: string;
updated_at?: string;
badge_type_id?: number;
weight?: number;
profile_medium?: string;
profile?: string;
friend?: unknown;
follower?: unknown;
username?: string;
bio?: string;
}

/**
* Strava Activity type.
* The type is dictated by the Strava API and used internally by the system.
Expand Down
Loading