@pinta365/strava 0.0.1

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.
Files changed (113) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +390 -0
  3. package/esm/_dnt.shims.d.ts +2 -0
  4. package/esm/_dnt.shims.js +57 -0
  5. package/esm/deps/jsr.io/@cross/runtime/1.2.1/mod.d.ts +126 -0
  6. package/esm/deps/jsr.io/@cross/runtime/1.2.1/mod.js +480 -0
  7. package/esm/mod.d.ts +27 -0
  8. package/esm/mod.js +27 -0
  9. package/esm/package.json +3 -0
  10. package/esm/src/auth/oauth.d.ts +68 -0
  11. package/esm/src/auth/oauth.js +203 -0
  12. package/esm/src/auth/scopes.d.ts +52 -0
  13. package/esm/src/auth/scopes.js +71 -0
  14. package/esm/src/auth/token-store.d.ts +57 -0
  15. package/esm/src/auth/token-store.js +142 -0
  16. package/esm/src/client.d.ts +98 -0
  17. package/esm/src/client.js +235 -0
  18. package/esm/src/errors.d.ts +52 -0
  19. package/esm/src/errors.js +102 -0
  20. package/esm/src/http/deduplication.d.ts +33 -0
  21. package/esm/src/http/deduplication.js +96 -0
  22. package/esm/src/http/rate-limiter.d.ts +47 -0
  23. package/esm/src/http/rate-limiter.js +168 -0
  24. package/esm/src/http/request.d.ts +24 -0
  25. package/esm/src/http/request.js +158 -0
  26. package/esm/src/http/retry.d.ts +9 -0
  27. package/esm/src/http/retry.js +61 -0
  28. package/esm/src/resources/activities.d.ts +149 -0
  29. package/esm/src/resources/activities.js +189 -0
  30. package/esm/src/resources/athletes.d.ts +37 -0
  31. package/esm/src/resources/athletes.js +85 -0
  32. package/esm/src/resources/clubs.d.ts +45 -0
  33. package/esm/src/resources/clubs.js +71 -0
  34. package/esm/src/resources/gears.d.ts +17 -0
  35. package/esm/src/resources/gears.js +27 -0
  36. package/esm/src/resources/routes.d.ts +33 -0
  37. package/esm/src/resources/routes.js +71 -0
  38. package/esm/src/resources/segment-efforts.d.ts +38 -0
  39. package/esm/src/resources/segment-efforts.js +53 -0
  40. package/esm/src/resources/segments.d.ts +42 -0
  41. package/esm/src/resources/segments.js +67 -0
  42. package/esm/src/resources/streams.d.ts +44 -0
  43. package/esm/src/resources/streams.js +75 -0
  44. package/esm/src/resources/uploads.d.ts +41 -0
  45. package/esm/src/resources/uploads.js +79 -0
  46. package/esm/src/types/api.d.ts +9 -0
  47. package/esm/src/types/api.js +7 -0
  48. package/esm/src/types/common.d.ts +65 -0
  49. package/esm/src/types/common.js +4 -0
  50. package/esm/src/types/generated.d.ts +731 -0
  51. package/esm/src/types/generated.js +7 -0
  52. package/esm/src/utils/pagination.d.ts +45 -0
  53. package/esm/src/utils/pagination.js +112 -0
  54. package/esm/src/utils/transformers.d.ts +30 -0
  55. package/esm/src/utils/transformers.js +189 -0
  56. package/esm/src/utils/validators.d.ts +53 -0
  57. package/esm/src/utils/validators.js +84 -0
  58. package/package.json +40 -0
  59. package/script/_dnt.shims.d.ts +2 -0
  60. package/script/_dnt.shims.js +60 -0
  61. package/script/deps/jsr.io/@cross/runtime/1.2.1/mod.d.ts +126 -0
  62. package/script/deps/jsr.io/@cross/runtime/1.2.1/mod.js +526 -0
  63. package/script/mod.d.ts +27 -0
  64. package/script/mod.js +73 -0
  65. package/script/package.json +3 -0
  66. package/script/src/auth/oauth.d.ts +68 -0
  67. package/script/src/auth/oauth.js +211 -0
  68. package/script/src/auth/scopes.d.ts +52 -0
  69. package/script/src/auth/scopes.js +79 -0
  70. package/script/src/auth/token-store.d.ts +57 -0
  71. package/script/src/auth/token-store.js +182 -0
  72. package/script/src/client.d.ts +98 -0
  73. package/script/src/client.js +239 -0
  74. package/script/src/errors.d.ts +52 -0
  75. package/script/src/errors.js +111 -0
  76. package/script/src/http/deduplication.d.ts +33 -0
  77. package/script/src/http/deduplication.js +100 -0
  78. package/script/src/http/rate-limiter.d.ts +47 -0
  79. package/script/src/http/rate-limiter.js +172 -0
  80. package/script/src/http/request.d.ts +24 -0
  81. package/script/src/http/request.js +161 -0
  82. package/script/src/http/retry.d.ts +9 -0
  83. package/script/src/http/retry.js +64 -0
  84. package/script/src/resources/activities.d.ts +149 -0
  85. package/script/src/resources/activities.js +193 -0
  86. package/script/src/resources/athletes.d.ts +37 -0
  87. package/script/src/resources/athletes.js +89 -0
  88. package/script/src/resources/clubs.d.ts +45 -0
  89. package/script/src/resources/clubs.js +75 -0
  90. package/script/src/resources/gears.d.ts +17 -0
  91. package/script/src/resources/gears.js +31 -0
  92. package/script/src/resources/routes.d.ts +33 -0
  93. package/script/src/resources/routes.js +75 -0
  94. package/script/src/resources/segment-efforts.d.ts +38 -0
  95. package/script/src/resources/segment-efforts.js +57 -0
  96. package/script/src/resources/segments.d.ts +42 -0
  97. package/script/src/resources/segments.js +71 -0
  98. package/script/src/resources/streams.d.ts +44 -0
  99. package/script/src/resources/streams.js +79 -0
  100. package/script/src/resources/uploads.d.ts +41 -0
  101. package/script/src/resources/uploads.js +83 -0
  102. package/script/src/types/api.d.ts +9 -0
  103. package/script/src/types/api.js +23 -0
  104. package/script/src/types/common.d.ts +65 -0
  105. package/script/src/types/common.js +5 -0
  106. package/script/src/types/generated.d.ts +731 -0
  107. package/script/src/types/generated.js +8 -0
  108. package/script/src/utils/pagination.d.ts +45 -0
  109. package/script/src/utils/pagination.js +118 -0
  110. package/script/src/utils/transformers.d.ts +30 -0
  111. package/script/src/utils/transformers.js +196 -0
  112. package/script/src/utils/validators.d.ts +53 -0
  113. package/script/src/utils/validators.js +92 -0
@@ -0,0 +1,203 @@
1
+ /**
2
+ * OAuth 2.0 authentication flow for Strava API
3
+ */
4
+ import { StravaAuthError } from "../errors.js";
5
+ import { formatScopes, parseScopes } from "./scopes.js";
6
+ const OAUTH_BASE_URL = "https://www.strava.com/api/v3/oauth";
7
+ /**
8
+ * Generate authorization URL
9
+ */
10
+ export function getAuthorizationUrl(options) {
11
+ const { clientId, redirectUri, scope, state, approvalPrompt = "auto" } = options;
12
+ const params = new URLSearchParams({
13
+ client_id: clientId,
14
+ redirect_uri: redirectUri,
15
+ response_type: "code",
16
+ scope: formatScopes(scope),
17
+ approval_prompt: approvalPrompt,
18
+ });
19
+ if (state) {
20
+ params.append("state", state);
21
+ }
22
+ return `${OAUTH_BASE_URL}/authorize?${params.toString()}`;
23
+ }
24
+ /**
25
+ * Exchange authorization code for tokens
26
+ * @param code - Authorization code from OAuth callback
27
+ * @param clientId - Strava client ID
28
+ * @param clientSecret - Strava client secret
29
+ * @param redirectUri - Redirect URI used in authorization (optional)
30
+ * @returns Token data
31
+ */
32
+ export async function exchangeCode(code, clientId, clientSecret, redirectUri) {
33
+ const params = new URLSearchParams({
34
+ client_id: clientId,
35
+ client_secret: clientSecret,
36
+ code,
37
+ grant_type: "authorization_code",
38
+ });
39
+ if (redirectUri) {
40
+ params.append("redirect_uri", redirectUri);
41
+ }
42
+ const response = await fetch(`${OAUTH_BASE_URL}/token`, {
43
+ method: "POST",
44
+ headers: {
45
+ "Content-Type": "application/x-www-form-urlencoded",
46
+ },
47
+ body: params.toString(),
48
+ });
49
+ if (!response.ok) {
50
+ const error = await response.json().catch(() => ({ message: response.statusText }));
51
+ throw new StravaAuthError(`Failed to exchange code: ${error.message || response.statusText}`, response.status, error);
52
+ }
53
+ const data = await response.json();
54
+ return {
55
+ accessToken: data.access_token,
56
+ refreshToken: data.refresh_token,
57
+ expiresAt: data.expires_at,
58
+ tokenType: data.token_type,
59
+ athleteId: data.athlete?.id,
60
+ };
61
+ }
62
+ /**
63
+ * Refresh access token using refresh token
64
+ */
65
+ export async function refreshAccessToken(refreshToken, clientId, clientSecret) {
66
+ const params = new URLSearchParams({
67
+ client_id: clientId,
68
+ client_secret: clientSecret,
69
+ refresh_token: refreshToken,
70
+ grant_type: "refresh_token",
71
+ });
72
+ const response = await fetch(`${OAUTH_BASE_URL}/token`, {
73
+ method: "POST",
74
+ headers: {
75
+ "Content-Type": "application/x-www-form-urlencoded",
76
+ },
77
+ body: params.toString(),
78
+ });
79
+ if (!response.ok) {
80
+ const error = await response.json().catch(() => ({ message: response.statusText }));
81
+ throw new StravaAuthError(`Failed to refresh token: ${error.message || response.statusText}`, response.status, error);
82
+ }
83
+ const data = await response.json();
84
+ return {
85
+ accessToken: data.access_token,
86
+ refreshToken: data.refresh_token,
87
+ expiresAt: data.expires_at,
88
+ tokenType: data.token_type,
89
+ athleteId: data.athlete?.id,
90
+ };
91
+ }
92
+ /**
93
+ * Check if token is expired or about to expire
94
+ */
95
+ export function isTokenExpired(token, bufferSeconds = 300) {
96
+ const now = Math.floor(Date.now() / 1000);
97
+ return token.expiresAt <= (now + bufferSeconds);
98
+ }
99
+ /**
100
+ * OAuth manager for handling authentication and token refresh
101
+ */
102
+ export class OAuthManager {
103
+ constructor(clientId, clientSecret, tokenStore) {
104
+ Object.defineProperty(this, "tokenStore", {
105
+ enumerable: true,
106
+ configurable: true,
107
+ writable: true,
108
+ value: void 0
109
+ });
110
+ Object.defineProperty(this, "clientId", {
111
+ enumerable: true,
112
+ configurable: true,
113
+ writable: true,
114
+ value: void 0
115
+ });
116
+ Object.defineProperty(this, "clientSecret", {
117
+ enumerable: true,
118
+ configurable: true,
119
+ writable: true,
120
+ value: void 0
121
+ });
122
+ this.clientId = clientId;
123
+ this.clientSecret = clientSecret;
124
+ this.tokenStore = tokenStore;
125
+ }
126
+ /**
127
+ * Get authorization URL
128
+ */
129
+ getAuthorizationUrl(options) {
130
+ return getAuthorizationUrl({
131
+ ...options,
132
+ clientId: this.clientId,
133
+ });
134
+ }
135
+ /**
136
+ * Exchange code and store tokens
137
+ */
138
+ async authenticate(code, redirectUri) {
139
+ const token = await exchangeCode(code, this.clientId, this.clientSecret, redirectUri);
140
+ await this.tokenStore.set(token);
141
+ return token;
142
+ }
143
+ /**
144
+ * Get current token, refreshing if needed
145
+ */
146
+ async getToken() {
147
+ const token = await this.tokenStore.get();
148
+ if (!token) {
149
+ return null;
150
+ }
151
+ // Refresh if expired or about to expire
152
+ if (isTokenExpired(token)) {
153
+ try {
154
+ const newToken = await refreshAccessToken(token.refreshToken, this.clientId, this.clientSecret);
155
+ const refreshedToken = {
156
+ ...newToken,
157
+ scope: token.scope,
158
+ athleteId: token.athleteId || newToken.athleteId,
159
+ };
160
+ await this.tokenStore.set(refreshedToken);
161
+ return refreshedToken;
162
+ }
163
+ catch (error) {
164
+ await this.tokenStore.clear();
165
+ throw error;
166
+ }
167
+ }
168
+ return token;
169
+ }
170
+ /**
171
+ * Manually refresh token
172
+ */
173
+ async refreshToken() {
174
+ const token = await this.tokenStore.get();
175
+ if (!token) {
176
+ throw new StravaAuthError("No token available to refresh");
177
+ }
178
+ const newToken = await refreshAccessToken(token.refreshToken, this.clientId, this.clientSecret);
179
+ const refreshedToken = {
180
+ ...newToken,
181
+ scope: token.scope,
182
+ athleteId: token.athleteId || newToken.athleteId,
183
+ };
184
+ await this.tokenStore.set(refreshedToken);
185
+ return refreshedToken;
186
+ }
187
+ /**
188
+ * Get current scopes
189
+ */
190
+ async getScopes() {
191
+ const token = await this.tokenStore.get();
192
+ if (!token || !token.scope) {
193
+ return [];
194
+ }
195
+ return parseScopes(token.scope);
196
+ }
197
+ /**
198
+ * Clear stored tokens
199
+ */
200
+ async clearTokens() {
201
+ await this.tokenStore.clear();
202
+ }
203
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * OAuth 2.0 scope definitions for Strava API
3
+ */
4
+ /**
5
+ * Available OAuth scopes
6
+ */
7
+ export declare enum StravaScope {
8
+ Read = "read",
9
+ ReadAll = "read_all",
10
+ ProfileReadAll = "profile:read_all",
11
+ ProfileWrite = "profile:write",
12
+ ActivityRead = "activity:read",
13
+ ActivityReadAll = "activity:read_all",
14
+ ActivityWrite = "activity:write"
15
+ }
16
+ /**
17
+ * Scope descriptions
18
+ */
19
+ export declare const SCOPE_DESCRIPTIONS: Record<StravaScope, string>;
20
+ /**
21
+ * Parse scope string into array
22
+ * @param scopeString - Comma-separated scope string
23
+ * @returns Array of scope enums
24
+ */
25
+ export declare function parseScopes(scopeString: string): StravaScope[];
26
+ /**
27
+ * Format scopes array into string
28
+ * @param scopes - Array of scope enums
29
+ * @returns Comma-separated scope string
30
+ */
31
+ export declare function formatScopes(scopes: StravaScope[]): string;
32
+ /**
33
+ * Check if a scope is included in the provided scopes
34
+ * @param required - Required scope
35
+ * @param available - Available scopes
36
+ * @returns True if the required scope is available
37
+ */
38
+ export declare function hasScope(required: StravaScope, available: StravaScope[]): boolean;
39
+ /**
40
+ * Check if all required scopes are available
41
+ * @param required - Required scopes
42
+ * @param available - Available scopes
43
+ * @returns True if all required scopes are available
44
+ */
45
+ export declare function hasAllScopes(required: StravaScope[], available: StravaScope[]): boolean;
46
+ /**
47
+ * Validate scopes
48
+ * @param scopes - Scopes to validate
49
+ * @returns True if all scopes are valid
50
+ */
51
+ export declare function validateScopes(scopes: StravaScope[]): boolean;
52
+ //# sourceMappingURL=scopes.d.ts.map
@@ -0,0 +1,71 @@
1
+ /**
2
+ * OAuth 2.0 scope definitions for Strava API
3
+ */
4
+ /**
5
+ * Available OAuth scopes
6
+ */
7
+ export var StravaScope;
8
+ (function (StravaScope) {
9
+ StravaScope["Read"] = "read";
10
+ StravaScope["ReadAll"] = "read_all";
11
+ StravaScope["ProfileReadAll"] = "profile:read_all";
12
+ StravaScope["ProfileWrite"] = "profile:write";
13
+ StravaScope["ActivityRead"] = "activity:read";
14
+ StravaScope["ActivityReadAll"] = "activity:read_all";
15
+ StravaScope["ActivityWrite"] = "activity:write";
16
+ })(StravaScope || (StravaScope = {}));
17
+ /**
18
+ * Scope descriptions
19
+ */
20
+ export const SCOPE_DESCRIPTIONS = {
21
+ [StravaScope.Read]: "Read public segments, public routes, public profile data, public posts, public events, club feeds, and leaderboards",
22
+ [StravaScope.ReadAll]: "Read private routes, private segments, and private events for the user",
23
+ [StravaScope.ProfileReadAll]: "Read all profile information even if the user has set their profile visibility to Followers or Only You",
24
+ [StravaScope.ProfileWrite]: "Update the user's weight and Functional Threshold Power (FTP), and access to star or unstar segments on their behalf",
25
+ [StravaScope.ActivityRead]: "Read the user's activity data for activities that are visible to Everyone and Followers, excluding privacy zone data",
26
+ [StravaScope.ActivityReadAll]: "The same access as activity:read, plus privacy zone data and access to read the user's activities with visibility set to Only You",
27
+ [StravaScope.ActivityWrite]: "Access to create manual activities and uploads, and access to edit any activities that are visible to the app, based on activity read access level",
28
+ };
29
+ /**
30
+ * Parse scope string into array
31
+ * @param scopeString - Comma-separated scope string
32
+ * @returns Array of scope enums
33
+ */
34
+ export function parseScopes(scopeString) {
35
+ return scopeString.split(",").map((s) => s.trim()).filter(Boolean);
36
+ }
37
+ /**
38
+ * Format scopes array into string
39
+ * @param scopes - Array of scope enums
40
+ * @returns Comma-separated scope string
41
+ */
42
+ export function formatScopes(scopes) {
43
+ return scopes.join(",");
44
+ }
45
+ /**
46
+ * Check if a scope is included in the provided scopes
47
+ * @param required - Required scope
48
+ * @param available - Available scopes
49
+ * @returns True if the required scope is available
50
+ */
51
+ export function hasScope(required, available) {
52
+ return available.includes(required);
53
+ }
54
+ /**
55
+ * Check if all required scopes are available
56
+ * @param required - Required scopes
57
+ * @param available - Available scopes
58
+ * @returns True if all required scopes are available
59
+ */
60
+ export function hasAllScopes(required, available) {
61
+ return required.every((scope) => available.includes(scope));
62
+ }
63
+ /**
64
+ * Validate scopes
65
+ * @param scopes - Scopes to validate
66
+ * @returns True if all scopes are valid
67
+ */
68
+ export function validateScopes(scopes) {
69
+ const validScopes = Object.values(StravaScope);
70
+ return scopes.every((scope) => validScopes.includes(scope));
71
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Token storage interface and implementations
3
+ */
4
+ /**
5
+ * Token data structure
6
+ */
7
+ export interface TokenData {
8
+ accessToken: string;
9
+ refreshToken: string;
10
+ expiresAt: number;
11
+ tokenType: string;
12
+ scope?: string;
13
+ athleteId?: number;
14
+ }
15
+ /**
16
+ * Token storage interface
17
+ */
18
+ export interface TokenStore {
19
+ get(): Promise<TokenData | null>;
20
+ set(token: TokenData): Promise<void>;
21
+ clear(): Promise<void>;
22
+ }
23
+ /**
24
+ * In-memory token store (default)
25
+ */
26
+ export declare class MemoryTokenStore implements TokenStore {
27
+ private token;
28
+ get(): Promise<TokenData | null>;
29
+ set(token: TokenData): Promise<void>;
30
+ clear(): Promise<void>;
31
+ }
32
+ /**
33
+ * Browser localStorage token store
34
+ */
35
+ export declare class LocalStorageTokenStore implements TokenStore {
36
+ private readonly key;
37
+ constructor(key?: string);
38
+ get(): Promise<TokenData | null>;
39
+ set(token: TokenData): Promise<void>;
40
+ clear(): Promise<void>;
41
+ }
42
+ /**
43
+ * File system token store (Node.js/Deno)
44
+ */
45
+ export declare class FileSystemTokenStore implements TokenStore {
46
+ private readonly path;
47
+ constructor(path?: string);
48
+ get(): Promise<TokenData | null>;
49
+ set(token: TokenData): Promise<void>;
50
+ clear(): Promise<void>;
51
+ }
52
+ /**
53
+ * Get default token store based on runtime environment
54
+ * @returns TokenStore appropriate for the current runtime (browser, Node.js, Deno, Bun)
55
+ */
56
+ export declare function getDefaultTokenStore(): TokenStore;
57
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Token storage interface and implementations
3
+ */
4
+ import { CurrentRuntime, Runtime } from "../../deps/jsr.io/@cross/runtime/1.2.1/mod.js";
5
+ /**
6
+ * In-memory token store (default)
7
+ */
8
+ export class MemoryTokenStore {
9
+ constructor() {
10
+ Object.defineProperty(this, "token", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: null
15
+ });
16
+ }
17
+ get() {
18
+ return Promise.resolve(this.token);
19
+ }
20
+ set(token) {
21
+ this.token = token;
22
+ return Promise.resolve();
23
+ }
24
+ clear() {
25
+ this.token = null;
26
+ return Promise.resolve();
27
+ }
28
+ }
29
+ /**
30
+ * Browser localStorage token store
31
+ */
32
+ export class LocalStorageTokenStore {
33
+ constructor(key = "strava_tokens") {
34
+ Object.defineProperty(this, "key", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: void 0
39
+ });
40
+ this.key = key;
41
+ }
42
+ get() {
43
+ if (CurrentRuntime !== Runtime.Browser) {
44
+ throw new Error("LocalStorageTokenStore can only be used in browser environment");
45
+ }
46
+ try {
47
+ const stored = localStorage.getItem(this.key);
48
+ if (!stored)
49
+ return Promise.resolve(null);
50
+ return Promise.resolve(JSON.parse(stored));
51
+ }
52
+ catch {
53
+ return Promise.resolve(null);
54
+ }
55
+ }
56
+ set(token) {
57
+ if (CurrentRuntime !== Runtime.Browser) {
58
+ throw new Error("LocalStorageTokenStore can only be used in browser environment");
59
+ }
60
+ localStorage.setItem(this.key, JSON.stringify(token));
61
+ return Promise.resolve();
62
+ }
63
+ clear() {
64
+ if (CurrentRuntime !== Runtime.Browser) {
65
+ throw new Error("LocalStorageTokenStore can only be used in browser environment");
66
+ }
67
+ localStorage.removeItem(this.key);
68
+ return Promise.resolve();
69
+ }
70
+ }
71
+ /**
72
+ * File system token store (Node.js/Deno)
73
+ */
74
+ export class FileSystemTokenStore {
75
+ constructor(path = "./.strava-tokens.json") {
76
+ Object.defineProperty(this, "path", {
77
+ enumerable: true,
78
+ configurable: true,
79
+ writable: true,
80
+ value: void 0
81
+ });
82
+ this.path = path;
83
+ }
84
+ async get() {
85
+ try {
86
+ let content;
87
+ if (CurrentRuntime === Runtime.Node || CurrentRuntime === Runtime.Bun) {
88
+ const { readFile } = await import("node:fs/promises");
89
+ content = await readFile(this.path, "utf-8");
90
+ }
91
+ else {
92
+ // Deno
93
+ content = await Deno.readTextFile(this.path);
94
+ }
95
+ return JSON.parse(content);
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ }
101
+ async set(token) {
102
+ const content = JSON.stringify(token, null, 2);
103
+ if (CurrentRuntime === Runtime.Node || CurrentRuntime === Runtime.Bun) {
104
+ const { writeFile } = await import("node:fs/promises");
105
+ await writeFile(this.path, content, "utf-8");
106
+ }
107
+ else {
108
+ // Deno
109
+ await Deno.writeTextFile(this.path, content);
110
+ }
111
+ }
112
+ async clear() {
113
+ try {
114
+ if (CurrentRuntime === Runtime.Node || CurrentRuntime === Runtime.Bun) {
115
+ const { unlink } = await import("node:fs/promises");
116
+ await unlink(this.path);
117
+ }
118
+ else {
119
+ // Deno
120
+ await Deno.remove(this.path);
121
+ }
122
+ }
123
+ catch {
124
+ // File doesn't exist, ignore
125
+ }
126
+ }
127
+ }
128
+ /**
129
+ * Get default token store based on runtime environment
130
+ * @returns TokenStore appropriate for the current runtime (browser, Node.js, Deno, Bun)
131
+ */
132
+ export function getDefaultTokenStore() {
133
+ if (CurrentRuntime === Runtime.Browser) {
134
+ return new LocalStorageTokenStore();
135
+ }
136
+ else if (CurrentRuntime === Runtime.Node || CurrentRuntime === Runtime.Deno || CurrentRuntime === Runtime.Bun) {
137
+ return new FileSystemTokenStore();
138
+ }
139
+ else {
140
+ return new MemoryTokenStore();
141
+ }
142
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Main Strava API client
3
+ */
4
+ import { type TokenStore } from "./auth/token-store.js";
5
+ import type { RateLimitStrategy, RequestConfig, RetryConfig } from "./types/common.js";
6
+ /**
7
+ * Client configuration options
8
+ */
9
+ export interface ClientOptions {
10
+ clientId: string;
11
+ clientSecret: string;
12
+ redirectUri?: string;
13
+ tokenStore?: TokenStore;
14
+ baseUrl?: string;
15
+ timeout?: number;
16
+ retries?: RetryConfig;
17
+ rateLimitStrategy?: RateLimitStrategy;
18
+ deduplicationWindow?: number;
19
+ normalizeKeys?: boolean;
20
+ transformDates?: boolean;
21
+ flattenResponses?: boolean;
22
+ addComputedFields?: boolean;
23
+ }
24
+ /**
25
+ * Authentication credentials
26
+ */
27
+ export interface AuthCredentials {
28
+ code: string;
29
+ redirectUri?: string;
30
+ }
31
+ /**
32
+ * Main Strava API client class
33
+ */
34
+ export declare class StravaClient {
35
+ private readonly options;
36
+ private readonly oauthManager;
37
+ private readonly rateLimiter;
38
+ private readonly deduplicator;
39
+ private _athletes?;
40
+ private _activities?;
41
+ private _segments?;
42
+ private _segmentEfforts?;
43
+ private _clubs?;
44
+ private _gears?;
45
+ private _routes?;
46
+ private _uploads?;
47
+ private _streams?;
48
+ constructor(options: ClientOptions);
49
+ /**
50
+ * Authenticate with authorization code
51
+ */
52
+ authenticate(credentials: AuthCredentials): Promise<void>;
53
+ /**
54
+ * Refresh access token
55
+ */
56
+ refreshToken(): Promise<void>;
57
+ /**
58
+ * Get authorization URL
59
+ */
60
+ getAuthorizationUrl(options: {
61
+ redirectUri?: string;
62
+ scope: string[];
63
+ state?: string;
64
+ approvalPrompt?: "force" | "auto";
65
+ }): string;
66
+ /**
67
+ * Get current access token (for direct fetch calls)
68
+ */
69
+ getAccessToken(): Promise<string>;
70
+ /**
71
+ * Low-level request method
72
+ */
73
+ request<T>(config: RequestConfig): Promise<T>;
74
+ get athletes(): AthletesResource;
75
+ get activities(): ActivitiesResource;
76
+ get segments(): SegmentsResource;
77
+ get segmentEfforts(): SegmentEffortsResource;
78
+ get clubs(): ClubsResource;
79
+ get gears(): GearsResource;
80
+ get routes(): RoutesResource;
81
+ get uploads(): UploadsResource;
82
+ get streams(): StreamsResource;
83
+ /**
84
+ * Clean up resources (stop timers, clear caches)
85
+ * Call this when you're done with the client to allow the process to exit
86
+ */
87
+ destroy(): void;
88
+ }
89
+ import { AthletesResource } from "./resources/athletes.js";
90
+ import { ActivitiesResource } from "./resources/activities.js";
91
+ import { SegmentsResource } from "./resources/segments.js";
92
+ import { SegmentEffortsResource } from "./resources/segment-efforts.js";
93
+ import { ClubsResource } from "./resources/clubs.js";
94
+ import { GearsResource } from "./resources/gears.js";
95
+ import { RoutesResource } from "./resources/routes.js";
96
+ import { UploadsResource } from "./resources/uploads.js";
97
+ import { StreamsResource } from "./resources/streams.js";
98
+ //# sourceMappingURL=client.d.ts.map