@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.
- package/LICENSE +21 -0
- package/README.md +390 -0
- package/esm/_dnt.shims.d.ts +2 -0
- package/esm/_dnt.shims.js +57 -0
- package/esm/deps/jsr.io/@cross/runtime/1.2.1/mod.d.ts +126 -0
- package/esm/deps/jsr.io/@cross/runtime/1.2.1/mod.js +480 -0
- package/esm/mod.d.ts +27 -0
- package/esm/mod.js +27 -0
- package/esm/package.json +3 -0
- package/esm/src/auth/oauth.d.ts +68 -0
- package/esm/src/auth/oauth.js +203 -0
- package/esm/src/auth/scopes.d.ts +52 -0
- package/esm/src/auth/scopes.js +71 -0
- package/esm/src/auth/token-store.d.ts +57 -0
- package/esm/src/auth/token-store.js +142 -0
- package/esm/src/client.d.ts +98 -0
- package/esm/src/client.js +235 -0
- package/esm/src/errors.d.ts +52 -0
- package/esm/src/errors.js +102 -0
- package/esm/src/http/deduplication.d.ts +33 -0
- package/esm/src/http/deduplication.js +96 -0
- package/esm/src/http/rate-limiter.d.ts +47 -0
- package/esm/src/http/rate-limiter.js +168 -0
- package/esm/src/http/request.d.ts +24 -0
- package/esm/src/http/request.js +158 -0
- package/esm/src/http/retry.d.ts +9 -0
- package/esm/src/http/retry.js +61 -0
- package/esm/src/resources/activities.d.ts +149 -0
- package/esm/src/resources/activities.js +189 -0
- package/esm/src/resources/athletes.d.ts +37 -0
- package/esm/src/resources/athletes.js +85 -0
- package/esm/src/resources/clubs.d.ts +45 -0
- package/esm/src/resources/clubs.js +71 -0
- package/esm/src/resources/gears.d.ts +17 -0
- package/esm/src/resources/gears.js +27 -0
- package/esm/src/resources/routes.d.ts +33 -0
- package/esm/src/resources/routes.js +71 -0
- package/esm/src/resources/segment-efforts.d.ts +38 -0
- package/esm/src/resources/segment-efforts.js +53 -0
- package/esm/src/resources/segments.d.ts +42 -0
- package/esm/src/resources/segments.js +67 -0
- package/esm/src/resources/streams.d.ts +44 -0
- package/esm/src/resources/streams.js +75 -0
- package/esm/src/resources/uploads.d.ts +41 -0
- package/esm/src/resources/uploads.js +79 -0
- package/esm/src/types/api.d.ts +9 -0
- package/esm/src/types/api.js +7 -0
- package/esm/src/types/common.d.ts +65 -0
- package/esm/src/types/common.js +4 -0
- package/esm/src/types/generated.d.ts +731 -0
- package/esm/src/types/generated.js +7 -0
- package/esm/src/utils/pagination.d.ts +45 -0
- package/esm/src/utils/pagination.js +112 -0
- package/esm/src/utils/transformers.d.ts +30 -0
- package/esm/src/utils/transformers.js +189 -0
- package/esm/src/utils/validators.d.ts +53 -0
- package/esm/src/utils/validators.js +84 -0
- package/package.json +40 -0
- package/script/_dnt.shims.d.ts +2 -0
- package/script/_dnt.shims.js +60 -0
- package/script/deps/jsr.io/@cross/runtime/1.2.1/mod.d.ts +126 -0
- package/script/deps/jsr.io/@cross/runtime/1.2.1/mod.js +526 -0
- package/script/mod.d.ts +27 -0
- package/script/mod.js +73 -0
- package/script/package.json +3 -0
- package/script/src/auth/oauth.d.ts +68 -0
- package/script/src/auth/oauth.js +211 -0
- package/script/src/auth/scopes.d.ts +52 -0
- package/script/src/auth/scopes.js +79 -0
- package/script/src/auth/token-store.d.ts +57 -0
- package/script/src/auth/token-store.js +182 -0
- package/script/src/client.d.ts +98 -0
- package/script/src/client.js +239 -0
- package/script/src/errors.d.ts +52 -0
- package/script/src/errors.js +111 -0
- package/script/src/http/deduplication.d.ts +33 -0
- package/script/src/http/deduplication.js +100 -0
- package/script/src/http/rate-limiter.d.ts +47 -0
- package/script/src/http/rate-limiter.js +172 -0
- package/script/src/http/request.d.ts +24 -0
- package/script/src/http/request.js +161 -0
- package/script/src/http/retry.d.ts +9 -0
- package/script/src/http/retry.js +64 -0
- package/script/src/resources/activities.d.ts +149 -0
- package/script/src/resources/activities.js +193 -0
- package/script/src/resources/athletes.d.ts +37 -0
- package/script/src/resources/athletes.js +89 -0
- package/script/src/resources/clubs.d.ts +45 -0
- package/script/src/resources/clubs.js +75 -0
- package/script/src/resources/gears.d.ts +17 -0
- package/script/src/resources/gears.js +31 -0
- package/script/src/resources/routes.d.ts +33 -0
- package/script/src/resources/routes.js +75 -0
- package/script/src/resources/segment-efforts.d.ts +38 -0
- package/script/src/resources/segment-efforts.js +57 -0
- package/script/src/resources/segments.d.ts +42 -0
- package/script/src/resources/segments.js +71 -0
- package/script/src/resources/streams.d.ts +44 -0
- package/script/src/resources/streams.js +79 -0
- package/script/src/resources/uploads.d.ts +41 -0
- package/script/src/resources/uploads.js +83 -0
- package/script/src/types/api.d.ts +9 -0
- package/script/src/types/api.js +23 -0
- package/script/src/types/common.d.ts +65 -0
- package/script/src/types/common.js +5 -0
- package/script/src/types/generated.d.ts +731 -0
- package/script/src/types/generated.js +8 -0
- package/script/src/utils/pagination.d.ts +45 -0
- package/script/src/utils/pagination.js +118 -0
- package/script/src/utils/transformers.d.ts +30 -0
- package/script/src/utils/transformers.js +196 -0
- package/script/src/utils/validators.d.ts +53 -0
- package/script/src/utils/validators.js +92 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activities resource
|
|
3
|
+
*/
|
|
4
|
+
import { buildPaginationQuery } from "../utils/pagination.js";
|
|
5
|
+
import { validatePositiveInteger } from "../utils/validators.js";
|
|
6
|
+
import { listAll } from "../utils/pagination.js";
|
|
7
|
+
/**
|
|
8
|
+
* Resource for interacting with Strava activities
|
|
9
|
+
*/
|
|
10
|
+
export class ActivitiesResource {
|
|
11
|
+
constructor(client) {
|
|
12
|
+
Object.defineProperty(this, "client", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: client
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get activity by ID
|
|
21
|
+
*/
|
|
22
|
+
async getById(id) {
|
|
23
|
+
validatePositiveInteger(id, "id");
|
|
24
|
+
return await this.client.request({
|
|
25
|
+
method: "GET",
|
|
26
|
+
path: `/activities/${id}`,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* List athlete activities
|
|
31
|
+
*/
|
|
32
|
+
async list(options) {
|
|
33
|
+
const query = {
|
|
34
|
+
...buildPaginationQuery(options),
|
|
35
|
+
};
|
|
36
|
+
if (options?.before) {
|
|
37
|
+
query.before = options.before;
|
|
38
|
+
}
|
|
39
|
+
if (options?.after) {
|
|
40
|
+
query.after = options.after;
|
|
41
|
+
}
|
|
42
|
+
return await this.client.request({
|
|
43
|
+
method: "GET",
|
|
44
|
+
path: "/athlete/activities",
|
|
45
|
+
query,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* List all activities (auto-pagination)
|
|
50
|
+
*/
|
|
51
|
+
async *listAll(options) {
|
|
52
|
+
yield* listAll((page, perPage) => {
|
|
53
|
+
return this.list({ ...options, page, perPage });
|
|
54
|
+
}, options?.perPage || 30);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create activity
|
|
58
|
+
*/
|
|
59
|
+
async create(data) {
|
|
60
|
+
return await this.client.request({
|
|
61
|
+
method: "POST",
|
|
62
|
+
path: "/activities",
|
|
63
|
+
body: data,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Update activity
|
|
68
|
+
*/
|
|
69
|
+
async update(id, data) {
|
|
70
|
+
validatePositiveInteger(id, "id");
|
|
71
|
+
return await this.client.request({
|
|
72
|
+
method: "PUT",
|
|
73
|
+
path: `/activities/${id}`,
|
|
74
|
+
body: data,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Delete activity
|
|
79
|
+
*/
|
|
80
|
+
async delete(id) {
|
|
81
|
+
validatePositiveInteger(id, "id");
|
|
82
|
+
await this.client.request({
|
|
83
|
+
method: "DELETE",
|
|
84
|
+
path: `/activities/${id}`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get activity with details (combines activity + laps + zones + comments + kudoers)
|
|
89
|
+
*/
|
|
90
|
+
async getWithDetails(id) {
|
|
91
|
+
validatePositiveInteger(id, "id");
|
|
92
|
+
const [activity, laps, zones, comments, kudoers] = await Promise.all([
|
|
93
|
+
this.getById(id),
|
|
94
|
+
this.getLaps(id),
|
|
95
|
+
this.getZones(id),
|
|
96
|
+
this.getComments(id),
|
|
97
|
+
this.getKudoers(id),
|
|
98
|
+
]);
|
|
99
|
+
return {
|
|
100
|
+
...activity,
|
|
101
|
+
laps,
|
|
102
|
+
zones,
|
|
103
|
+
comments,
|
|
104
|
+
kudoers,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get activity laps
|
|
109
|
+
*/
|
|
110
|
+
async getLaps(id) {
|
|
111
|
+
validatePositiveInteger(id, "id");
|
|
112
|
+
return await this.client.request({
|
|
113
|
+
method: "GET",
|
|
114
|
+
path: `/activities/${id}/laps`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get activity zones
|
|
119
|
+
*/
|
|
120
|
+
async getZones(id) {
|
|
121
|
+
validatePositiveInteger(id, "id");
|
|
122
|
+
return await this.client.request({
|
|
123
|
+
method: "GET",
|
|
124
|
+
path: `/activities/${id}/zones`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get activity comments
|
|
129
|
+
*/
|
|
130
|
+
async getComments(id, options) {
|
|
131
|
+
validatePositiveInteger(id, "id");
|
|
132
|
+
return await this.client.request({
|
|
133
|
+
method: "GET",
|
|
134
|
+
path: `/activities/${id}/comments`,
|
|
135
|
+
query: buildPaginationQuery(options),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get activity kudoers
|
|
140
|
+
*/
|
|
141
|
+
async getKudoers(id, options) {
|
|
142
|
+
validatePositiveInteger(id, "id");
|
|
143
|
+
return await this.client.request({
|
|
144
|
+
method: "GET",
|
|
145
|
+
path: `/activities/${id}/kudoers`,
|
|
146
|
+
query: buildPaginationQuery(options),
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Analyze activity with comprehensive data
|
|
151
|
+
* Combines activity, zones, laps, best efforts (segments), and optionally streams
|
|
152
|
+
*/
|
|
153
|
+
async analyze(id, options) {
|
|
154
|
+
validatePositiveInteger(id, "id");
|
|
155
|
+
const [activity, zones, laps] = await Promise.all([
|
|
156
|
+
this.getById(id),
|
|
157
|
+
this.getZones(id).catch(() => []),
|
|
158
|
+
this.getLaps(id).catch(() => []),
|
|
159
|
+
]);
|
|
160
|
+
const bestEfforts = activity.bestEfforts || [];
|
|
161
|
+
const analysis = {
|
|
162
|
+
hasPowerData: zones.some((z) => z.type === "power"),
|
|
163
|
+
hasHeartRateData: zones.some((z) => z.type === "heartrate"),
|
|
164
|
+
totalLaps: laps.length,
|
|
165
|
+
bestEffortCount: bestEfforts.length,
|
|
166
|
+
averageLapTime: laps.length > 0 ? laps.reduce((sum, lap) => sum + (lap.movingTime || 0), 0) / laps.length : undefined,
|
|
167
|
+
averageLapDistance: laps.length > 0 ? laps.reduce((sum, lap) => sum + (lap.distance || 0), 0) / laps.length : undefined,
|
|
168
|
+
};
|
|
169
|
+
const result = {
|
|
170
|
+
...activity,
|
|
171
|
+
zones,
|
|
172
|
+
laps,
|
|
173
|
+
bestEfforts,
|
|
174
|
+
analysis,
|
|
175
|
+
};
|
|
176
|
+
if (options?.includeStreams) {
|
|
177
|
+
try {
|
|
178
|
+
const streams = await this.client.streams.getForActivity(id, {
|
|
179
|
+
types: options.streamTypes,
|
|
180
|
+
});
|
|
181
|
+
result.streams = streams;
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// Streams may not be available for all activities
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Athletes resource
|
|
3
|
+
*/
|
|
4
|
+
import type { StravaClient } from "../client.js";
|
|
5
|
+
import type { ActivityStats, DetailedAthlete, DetailedGear, SummaryActivity } from "../types/api.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resource for interacting with Strava athletes
|
|
8
|
+
*/
|
|
9
|
+
export declare class AthletesResource {
|
|
10
|
+
private client;
|
|
11
|
+
constructor(client: StravaClient);
|
|
12
|
+
/**
|
|
13
|
+
* Get authenticated athlete
|
|
14
|
+
*/
|
|
15
|
+
get(): Promise<DetailedAthlete>;
|
|
16
|
+
/**
|
|
17
|
+
* Get athlete stats
|
|
18
|
+
*/
|
|
19
|
+
getStats(id: number): Promise<ActivityStats>;
|
|
20
|
+
/**
|
|
21
|
+
* Update authenticated athlete
|
|
22
|
+
*/
|
|
23
|
+
update(weight: number): Promise<DetailedAthlete>;
|
|
24
|
+
/**
|
|
25
|
+
* Get athlete stats with recent activities and gear
|
|
26
|
+
* Combines stats, recent activities, and gear information
|
|
27
|
+
*/
|
|
28
|
+
getStatsWithActivities(id: number, options?: {
|
|
29
|
+
recentActivitiesLimit?: number;
|
|
30
|
+
includeGear?: boolean;
|
|
31
|
+
}): Promise<DetailedAthlete & {
|
|
32
|
+
stats: ActivityStats;
|
|
33
|
+
recentActivities: SummaryActivity[];
|
|
34
|
+
gear?: DetailedGear[];
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=athletes.d.ts.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Athletes resource
|
|
3
|
+
*/
|
|
4
|
+
import { validatePositiveInteger } from "../utils/validators.js";
|
|
5
|
+
/**
|
|
6
|
+
* Resource for interacting with Strava athletes
|
|
7
|
+
*/
|
|
8
|
+
export class AthletesResource {
|
|
9
|
+
constructor(client) {
|
|
10
|
+
Object.defineProperty(this, "client", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: client
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get authenticated athlete
|
|
19
|
+
*/
|
|
20
|
+
async get() {
|
|
21
|
+
return await this.client.request({
|
|
22
|
+
method: "GET",
|
|
23
|
+
path: "/athlete",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get athlete stats
|
|
28
|
+
*/
|
|
29
|
+
async getStats(id) {
|
|
30
|
+
validatePositiveInteger(id, "id");
|
|
31
|
+
return await this.client.request({
|
|
32
|
+
method: "GET",
|
|
33
|
+
path: `/athletes/${id}/stats`,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Update authenticated athlete
|
|
38
|
+
*/
|
|
39
|
+
async update(weight) {
|
|
40
|
+
return await this.client.request({
|
|
41
|
+
method: "PUT",
|
|
42
|
+
path: "/athlete",
|
|
43
|
+
query: { weight },
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get athlete stats with recent activities and gear
|
|
48
|
+
* Combines stats, recent activities, and gear information
|
|
49
|
+
*/
|
|
50
|
+
async getStatsWithActivities(id, options) {
|
|
51
|
+
validatePositiveInteger(id, "id");
|
|
52
|
+
const [athlete, stats, recentActivities] = await Promise.all([
|
|
53
|
+
this.get(),
|
|
54
|
+
this.getStats(id),
|
|
55
|
+
this.client.activities.list({
|
|
56
|
+
perPage: options?.recentActivitiesLimit || 10,
|
|
57
|
+
}),
|
|
58
|
+
]);
|
|
59
|
+
const result = {
|
|
60
|
+
...athlete,
|
|
61
|
+
stats,
|
|
62
|
+
recentActivities,
|
|
63
|
+
};
|
|
64
|
+
if (options?.includeGear !== false) {
|
|
65
|
+
const gearIds = [];
|
|
66
|
+
if (athlete.bikes) {
|
|
67
|
+
gearIds.push(...athlete.bikes.map((bike) => bike.id).filter((id) => id !== undefined));
|
|
68
|
+
}
|
|
69
|
+
if (athlete.shoes) {
|
|
70
|
+
gearIds.push(...athlete.shoes.map((shoe) => shoe.id).filter((id) => id !== undefined));
|
|
71
|
+
}
|
|
72
|
+
if (gearIds.length > 0) {
|
|
73
|
+
try {
|
|
74
|
+
const gearPromises = gearIds.map((id) => this.client.gears.getById(id).catch(() => null));
|
|
75
|
+
const gearResults = await Promise.all(gearPromises);
|
|
76
|
+
result.gear = gearResults.filter((g) => g !== null);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Gear may not be accessible
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clubs resource
|
|
3
|
+
*/
|
|
4
|
+
import type { StravaClient } from "../client.js";
|
|
5
|
+
import type { ClubActivity, DetailedClub, SummaryAthlete, SummaryClub } from "../types/api.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resource for interacting with Strava clubs
|
|
8
|
+
*/
|
|
9
|
+
export declare class ClubsResource {
|
|
10
|
+
private client;
|
|
11
|
+
constructor(client: StravaClient);
|
|
12
|
+
/**
|
|
13
|
+
* Get club by ID
|
|
14
|
+
*/
|
|
15
|
+
getById(id: number): Promise<DetailedClub>;
|
|
16
|
+
/**
|
|
17
|
+
* List athlete clubs
|
|
18
|
+
*/
|
|
19
|
+
list(options?: {
|
|
20
|
+
page?: number;
|
|
21
|
+
perPage?: number;
|
|
22
|
+
}): Promise<SummaryClub[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Get club members
|
|
25
|
+
*/
|
|
26
|
+
getMembers(id: number, options?: {
|
|
27
|
+
page?: number;
|
|
28
|
+
perPage?: number;
|
|
29
|
+
}): Promise<SummaryAthlete[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Get club activities
|
|
32
|
+
*/
|
|
33
|
+
getActivities(id: number, options?: {
|
|
34
|
+
page?: number;
|
|
35
|
+
perPage?: number;
|
|
36
|
+
}): Promise<ClubActivity[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Get club admins
|
|
39
|
+
*/
|
|
40
|
+
getAdmins(id: number, options?: {
|
|
41
|
+
page?: number;
|
|
42
|
+
perPage?: number;
|
|
43
|
+
}): Promise<SummaryAthlete[]>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=clubs.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clubs resource
|
|
3
|
+
*/
|
|
4
|
+
import { validatePositiveInteger } from "../utils/validators.js";
|
|
5
|
+
import { buildPaginationQuery } from "../utils/pagination.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resource for interacting with Strava clubs
|
|
8
|
+
*/
|
|
9
|
+
export class ClubsResource {
|
|
10
|
+
constructor(client) {
|
|
11
|
+
Object.defineProperty(this, "client", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: client
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get club by ID
|
|
20
|
+
*/
|
|
21
|
+
async getById(id) {
|
|
22
|
+
validatePositiveInteger(id, "id");
|
|
23
|
+
return await this.client.request({
|
|
24
|
+
method: "GET",
|
|
25
|
+
path: `/clubs/${id}`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* List athlete clubs
|
|
30
|
+
*/
|
|
31
|
+
async list(options) {
|
|
32
|
+
return await this.client.request({
|
|
33
|
+
method: "GET",
|
|
34
|
+
path: "/athlete/clubs",
|
|
35
|
+
query: buildPaginationQuery(options),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get club members
|
|
40
|
+
*/
|
|
41
|
+
async getMembers(id, options) {
|
|
42
|
+
validatePositiveInteger(id, "id");
|
|
43
|
+
return await this.client.request({
|
|
44
|
+
method: "GET",
|
|
45
|
+
path: `/clubs/${id}/members`,
|
|
46
|
+
query: buildPaginationQuery(options),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get club activities
|
|
51
|
+
*/
|
|
52
|
+
async getActivities(id, options) {
|
|
53
|
+
validatePositiveInteger(id, "id");
|
|
54
|
+
return await this.client.request({
|
|
55
|
+
method: "GET",
|
|
56
|
+
path: `/clubs/${id}/activities`,
|
|
57
|
+
query: buildPaginationQuery(options),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get club admins
|
|
62
|
+
*/
|
|
63
|
+
async getAdmins(id, options) {
|
|
64
|
+
validatePositiveInteger(id, "id");
|
|
65
|
+
return await this.client.request({
|
|
66
|
+
method: "GET",
|
|
67
|
+
path: `/clubs/${id}/admins`,
|
|
68
|
+
query: buildPaginationQuery(options),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gears resource
|
|
3
|
+
*/
|
|
4
|
+
import type { StravaClient } from "../client.js";
|
|
5
|
+
import type { DetailedGear } from "../types/api.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resource for interacting with Strava gear
|
|
8
|
+
*/
|
|
9
|
+
export declare class GearsResource {
|
|
10
|
+
private client;
|
|
11
|
+
constructor(client: StravaClient);
|
|
12
|
+
/**
|
|
13
|
+
* Get gear by ID
|
|
14
|
+
*/
|
|
15
|
+
getById(id: string): Promise<DetailedGear>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=gears.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gears resource
|
|
3
|
+
*/
|
|
4
|
+
import { validateNonEmptyString } from "../utils/validators.js";
|
|
5
|
+
/**
|
|
6
|
+
* Resource for interacting with Strava gear
|
|
7
|
+
*/
|
|
8
|
+
export class GearsResource {
|
|
9
|
+
constructor(client) {
|
|
10
|
+
Object.defineProperty(this, "client", {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
value: client
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get gear by ID
|
|
19
|
+
*/
|
|
20
|
+
async getById(id) {
|
|
21
|
+
validateNonEmptyString(id, "id");
|
|
22
|
+
return await this.client.request({
|
|
23
|
+
method: "GET",
|
|
24
|
+
path: `/gear/${id}`,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routes resource
|
|
3
|
+
*/
|
|
4
|
+
import type { StravaClient } from "../client.js";
|
|
5
|
+
import type { Route } from "../types/api.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resource for interacting with Strava routes
|
|
8
|
+
*/
|
|
9
|
+
export declare class RoutesResource {
|
|
10
|
+
private client;
|
|
11
|
+
constructor(client: StravaClient);
|
|
12
|
+
/**
|
|
13
|
+
* Get route by ID
|
|
14
|
+
*/
|
|
15
|
+
getById(id: number): Promise<Route>;
|
|
16
|
+
/**
|
|
17
|
+
* List athlete routes
|
|
18
|
+
*/
|
|
19
|
+
list(options?: {
|
|
20
|
+
page?: number;
|
|
21
|
+
perPage?: number;
|
|
22
|
+
}): Promise<Route[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Download route as GPX
|
|
25
|
+
*/
|
|
26
|
+
downloadAsGPX(id: number): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Download route as TCX
|
|
29
|
+
*/
|
|
30
|
+
downloadAsTCX(id: number): Promise<string>;
|
|
31
|
+
private getAccessToken;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routes resource
|
|
3
|
+
*/
|
|
4
|
+
import { validatePositiveInteger } from "../utils/validators.js";
|
|
5
|
+
import { buildPaginationQuery } from "../utils/pagination.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resource for interacting with Strava routes
|
|
8
|
+
*/
|
|
9
|
+
export class RoutesResource {
|
|
10
|
+
constructor(client) {
|
|
11
|
+
Object.defineProperty(this, "client", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: client
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get route by ID
|
|
20
|
+
*/
|
|
21
|
+
async getById(id) {
|
|
22
|
+
validatePositiveInteger(id, "id");
|
|
23
|
+
return await this.client.request({
|
|
24
|
+
method: "GET",
|
|
25
|
+
path: `/routes/${id}`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* List athlete routes
|
|
30
|
+
*/
|
|
31
|
+
async list(options) {
|
|
32
|
+
return await this.client.request({
|
|
33
|
+
method: "GET",
|
|
34
|
+
path: "/athlete/routes",
|
|
35
|
+
query: buildPaginationQuery(options),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Download route as GPX
|
|
40
|
+
*/
|
|
41
|
+
async downloadAsGPX(id) {
|
|
42
|
+
validatePositiveInteger(id, "id");
|
|
43
|
+
const response = await fetch(`https://www.strava.com/api/v3/routes/${id}/export_gpx`, {
|
|
44
|
+
headers: {
|
|
45
|
+
"Authorization": `Bearer ${await this.getAccessToken()}`,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(`Failed to download GPX: ${response.statusText}`);
|
|
50
|
+
}
|
|
51
|
+
return response.text();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Download route as TCX
|
|
55
|
+
*/
|
|
56
|
+
async downloadAsTCX(id) {
|
|
57
|
+
validatePositiveInteger(id, "id");
|
|
58
|
+
const response = await fetch(`https://www.strava.com/api/v3/routes/${id}/export_tcx`, {
|
|
59
|
+
headers: {
|
|
60
|
+
"Authorization": `Bearer ${await this.getAccessToken()}`,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
throw new Error(`Failed to download TCX: ${response.statusText}`);
|
|
65
|
+
}
|
|
66
|
+
return response.text();
|
|
67
|
+
}
|
|
68
|
+
async getAccessToken() {
|
|
69
|
+
return await this.client.getAccessToken();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Segment efforts resource
|
|
3
|
+
*/
|
|
4
|
+
import type { StravaClient } from "../client.js";
|
|
5
|
+
import type { DetailedSegmentEffort, SummarySegmentEffort } from "../types/api.js";
|
|
6
|
+
/**
|
|
7
|
+
* Options for listing segment efforts
|
|
8
|
+
*/
|
|
9
|
+
export interface ListSegmentEffortsOptions {
|
|
10
|
+
/** Filter by segment ID */
|
|
11
|
+
segmentId?: number;
|
|
12
|
+
/** Filter by athlete ID */
|
|
13
|
+
athleteId?: number;
|
|
14
|
+
/** Start date in ISO 8601 format */
|
|
15
|
+
startDateLocal?: string;
|
|
16
|
+
/** End date in ISO 8601 format */
|
|
17
|
+
endDateLocal?: string;
|
|
18
|
+
/** Page number (default: 1) */
|
|
19
|
+
page?: number;
|
|
20
|
+
/** Number of items per page (default: 30, max: 200) */
|
|
21
|
+
perPage?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resource for interacting with Strava segment efforts
|
|
25
|
+
*/
|
|
26
|
+
export declare class SegmentEffortsResource {
|
|
27
|
+
private client;
|
|
28
|
+
constructor(client: StravaClient);
|
|
29
|
+
/**
|
|
30
|
+
* Get segment effort by ID
|
|
31
|
+
*/
|
|
32
|
+
getById(id: number): Promise<DetailedSegmentEffort>;
|
|
33
|
+
/**
|
|
34
|
+
* List segment efforts
|
|
35
|
+
*/
|
|
36
|
+
list(options?: ListSegmentEffortsOptions): Promise<SummarySegmentEffort[]>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=segment-efforts.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Segment efforts resource
|
|
3
|
+
*/
|
|
4
|
+
import { validatePositiveInteger } from "../utils/validators.js";
|
|
5
|
+
import { buildPaginationQuery } from "../utils/pagination.js";
|
|
6
|
+
/**
|
|
7
|
+
* Resource for interacting with Strava segment efforts
|
|
8
|
+
*/
|
|
9
|
+
export class SegmentEffortsResource {
|
|
10
|
+
constructor(client) {
|
|
11
|
+
Object.defineProperty(this, "client", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: client
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get segment effort by ID
|
|
20
|
+
*/
|
|
21
|
+
async getById(id) {
|
|
22
|
+
validatePositiveInteger(id, "id");
|
|
23
|
+
return await this.client.request({
|
|
24
|
+
method: "GET",
|
|
25
|
+
path: `/segment_efforts/${id}`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* List segment efforts
|
|
30
|
+
*/
|
|
31
|
+
async list(options) {
|
|
32
|
+
const query = {
|
|
33
|
+
...buildPaginationQuery(options),
|
|
34
|
+
};
|
|
35
|
+
if (options?.segmentId) {
|
|
36
|
+
query.segment_id = options.segmentId;
|
|
37
|
+
}
|
|
38
|
+
if (options?.athleteId) {
|
|
39
|
+
query.athlete_id = options.athleteId;
|
|
40
|
+
}
|
|
41
|
+
if (options?.startDateLocal) {
|
|
42
|
+
query.start_date_local = options.startDateLocal;
|
|
43
|
+
}
|
|
44
|
+
if (options?.endDateLocal) {
|
|
45
|
+
query.end_date_local = options.endDateLocal;
|
|
46
|
+
}
|
|
47
|
+
return await this.client.request({
|
|
48
|
+
method: "GET",
|
|
49
|
+
path: "/segment_efforts",
|
|
50
|
+
query,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|