From 70ec157ff2e919daccd46c229c851b39ca0eab7c Mon Sep 17 00:00:00 2001 From: balovbohdan Date: Wed, 3 Jun 2026 10:49:30 +0300 Subject: [PATCH 1/3] id:55 feat(claude): claude symlink, nvmrc --- .claude/claude | 1 + .claude/skills/create-changelog/SKILL.md | 134 ----------------------- .nvmrc | 2 +- 3 files changed, 2 insertions(+), 135 deletions(-) create mode 120000 .claude/claude delete mode 100644 .claude/skills/create-changelog/SKILL.md diff --git a/.claude/claude b/.claude/claude new file mode 120000 index 0000000..af85e5e --- /dev/null +++ b/.claude/claude @@ -0,0 +1 @@ +../claude \ No newline at end of file diff --git a/.claude/skills/create-changelog/SKILL.md b/.claude/skills/create-changelog/SKILL.md deleted file mode 100644 index 6034feb..0000000 --- a/.claude/skills/create-changelog/SKILL.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -id: create-changelog -description: Creates a changelog entry for changes in the current branch against the main one. Use when the changelog generation is requested. ---- - -# Changelog Creation Skill - -## Context -You are a technical documentation assistant specialized in creating accurate, concise changelogs following the "Keep a Changelog" standard (https://keepachangelog.com/en/1.1.0/). - -## Task -- Analyze the code changes between the current branch and the main branch. -- Write a short changes summary during the execution to make sure you are on track. -- Based on codebase changes, recognize the changelog entry version according to the SemVer. -- Generate a changelog entry that accurately reflects ONLY the actual changes made. Use the recognized SemVer entry version, as the template below specifies. -- Write result to the [CHANGELOG.md](../../../CHANGELOG.md) extending the exisging changelog entries. - -## Instructions - -1. **Examine the git diff** between the current branch and main: - ```bash - git diff main...HEAD - ``` - -2. **Categorize changes** according to "Keep a Changelog" standard: - - **Added** - for new features - - **Changed** - for changes in existing functionality - - **Deprecated** - for soon-to-be removed features - - **Removed** - for now removed features - - **Fixed** - for any bug fixes - - **Security** - in case of vulnerabilities - -3. **Follow these strict rules**: - - Document ONLY what is explicitly visible in the code changes - - Do NOT speculate about intentions or future behavior - - Do NOT invent features that aren't clearly implemented - - Use clear, technical language - - Be concise but complete - - Focus on user-facing changes and important technical modifications - - Ignore trivial changes (whitespace, formatting, comments unless significant) - - Use uppercase first letters for titles - - **Generate the main title in the format**: `Auto-Generated Title Based on the Change Details` - - Extract the ticket ID from the current git branch name (e.g., from `feature/123-description` extract `123`) - - The auto-generated title should briefly summarize the main change - -4. **Ask for clarification** when: - - The purpose of a change is unclear - - Complex refactoring needs context - - Business logic changes lack obvious intent - - Breaking changes aren't clearly documented - -## Output Format - -```markdown -# Changelog - -## [Version according to SemVer in format ..] - Date in format yyyy-mm-dd - -### [ ](https://github.com/torqlab/torq/issues/) - -### Added -- Brief description of new feature/capability -- Another new addition - -### Changed -- Description of modified functionality -- Updated behavior or interface - -### Fixed -- Bug fix description with issue reference if available - -### Removed -- Deleted features or deprecated code removal - -### Security -- Security-related fixes or improvements -``` - -## Example Output - -For a branch named `feature/526-add-user-authentication`: - -```markdown -# Changelog - -## [1.1.0] - 2027-02-03 - -### [526 Added User Authentication with JWT based on EPAM SSO](https://github.com/torqlab/torq/issues/526) - -### Added -- User authentication system with JWT tokens -- Login and logout endpoints - -### Changed -- Updated user model to include password hashing -``` - -## Example Questions to Ask (when needed) - -- "What is the business purpose of the changes in [specific file]?" -- "Is the modification in [component] a bug fix or intentional behavior change?" -- "Should the removal of [feature] be noted as a breaking change?" -- "What user-facing impact does the refactoring of [module] have?" - -## Important Notes - -- The main title MUST follow the format: ` Auto-Generated Title Based on the Change Details`. -- Extract the ticket ID from the branch name (usually the numeric part). -- Each entry should start with a verb (Added, Removed, Fixed, etc.). -- Group related changes together. -- Order sections by importance: Security > Removed > Deprecated > Fixed > Changed > Added. -- Include issue/PR numbers when available: `Fixed #123`. -- Date entries when creating releases: `## [1.0.0] - 2024-01-15`. -- Keep entries user-focused when possible, technical when necessary. -- Avoid creating several changelog entries for the same branch. -- Avoid bumping `package.json` version several times for the same branch. -- When you face more than one changelog entry in git diff against the main branch, merge them into a single one. -- When you face inconsistent `package.json`'s versions bumps in git diff against the main branch, set the consistent version. - -## Execution Steps - -1. Get the current branch name: `git branch --show-current` -2. Extract the ticket ID from the branch name -3. Run `git diff main...HEAD` to see all changes -4. Analyze modified files for functional changes -5. Categorize each significant change -6. Generate an appropriate title based on the main changes -7. Draft changelog entries with the proper title format -8. Review for accuracy and completeness -9. Ask questions about unclear changes -10. Finalize the changelog entry in [CHANGELOG.md](../../../CHANGELOG.md) -11. Update version in the root [`package.json`](../../../package.json) - -Remember: Accuracy over completeness. It's better to have fewer, accurate entries than to include speculative or incorrect information. diff --git a/.nvmrc b/.nvmrc index 9e2934a..a45fd52 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -24.11.1 +24 From 000fa59484178fff604854d1ece2a6d214d3269c Mon Sep 17 00:00:00 2001 From: balovbohdan Date: Wed, 3 Jun 2026 16:45:38 +0300 Subject: [PATCH 2/3] feat: add fetch-athlete endpoint and configuration - Add fetch-athlete module for querying Strava athlete data - Add MCP server configuration (.mcp.json) - Add CodeMie CLI configuration - Update types to support athlete queries - Update constants and configuration - Remove claude symlink, add skills configuration Co-Authored-By: Claude Haiku 4.5 --- .claude/claude | 1 - .claude/skills | 1 + .codemie/codemie-cli.config.json | 18 ++++++++++ .gitignore | 1 + .mcp.json | 11 ++++++ CHANGELOG.md | 10 ++++++ constants.ts | 1 + fetch-athlete/fetch-athlete.ts | 58 ++++++++++++++++++++++++++++++++ fetch-athlete/index.ts | 1 + index.ts | 3 +- package.json | 2 +- types.ts | 28 +++++++++++++++ 12 files changed, 132 insertions(+), 3 deletions(-) delete mode 120000 .claude/claude create mode 120000 .claude/skills create mode 100644 .codemie/codemie-cli.config.json create mode 100644 .mcp.json create mode 100644 fetch-athlete/fetch-athlete.ts create mode 100644 fetch-athlete/index.ts diff --git a/.claude/claude b/.claude/claude deleted file mode 120000 index af85e5e..0000000 --- a/.claude/claude +++ /dev/null @@ -1 +0,0 @@ -../claude \ No newline at end of file diff --git a/.claude/skills b/.claude/skills new file mode 120000 index 0000000..e588543 --- /dev/null +++ b/.claude/skills @@ -0,0 +1 @@ +/Users/kseniiabalova/Documents/torq/.claude/skills \ No newline at end of file diff --git a/.codemie/codemie-cli.config.json b/.codemie/codemie-cli.config.json new file mode 100644 index 0000000..c12c505 --- /dev/null +++ b/.codemie/codemie-cli.config.json @@ -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" + } + } +} diff --git a/.gitignore b/.gitignore index de4d1f0..d14eab8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ dist node_modules +.env \ No newline at end of file diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..9d1f5e9 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "github": { + "type": "http", + "url": "https://api.githubcopilot.com/mcp/", + "headers": { + "Authorization": "Bearer ${GITHUB_MCP_TOKEN}" + } + } + } +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2018e2f..9b89fe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/constants.ts b/constants.ts index d2d7069..9f04f37 100644 --- a/constants.ts +++ b/constants.ts @@ -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`, /** diff --git a/fetch-athlete/fetch-athlete.ts b/fetch-athlete/fetch-athlete.ts new file mode 100644 index 0000000..30fa4dc --- /dev/null +++ b/fetch-athlete/fetch-athlete.ts @@ -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} 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 => + handleRetry({ + maxRetries: STRAVA_API_MAX_RETRIES, + initialBackoffMs: STRAVA_API_INITIAL_BACKOFF_MS, + + /** + * Fetches from Strava API. + * @returns {Promise} Promise resolving to API response. + * @throws {Error} Throws error for rate limits, unauthorized errors, or other API errors. + * @internal + */ + fn: (): Promise => client(STRAVA_API_ENDPOINTS.ATHLETE, config), + }); + +export default fetchAthlete; diff --git a/fetch-athlete/index.ts b/fetch-athlete/index.ts new file mode 100644 index 0000000..0d2c65b --- /dev/null +++ b/fetch-athlete/index.ts @@ -0,0 +1 @@ +export { default } from './fetch-athlete'; diff --git a/index.ts b/index.ts index 42f1923..575964a 100644 --- a/index.ts +++ b/index.ts @@ -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'; diff --git a/package.json b/package.json index 11ba0e9..06af6ac 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/types.ts b/types.ts index 1ebc838..798f658 100644 --- a/types.ts +++ b/types.ts @@ -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. From abbea161aaca42b79d2973b9c04a59b0eefb28ef Mon Sep 17 00:00:00 2001 From: balovbohdan Date: Wed, 3 Jun 2026 16:59:04 +0300 Subject: [PATCH 3/3] id:55 feat(query-athlete): format --- .mcp.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mcp.json b/.mcp.json index 9d1f5e9..b2ebead 100644 --- a/.mcp.json +++ b/.mcp.json @@ -8,4 +8,4 @@ } } } -} \ No newline at end of file +}