garminclimb 1.2.1 → 1.2.2

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.
@@ -22,7 +22,8 @@
22
22
  "Bash(grep -r \"Cycling\" /Users/johnottenlips/garminclimb/node_modules/garmin-connect/dist/garmin/types/activity* 2>/dev/null | head -20)",
23
23
  "Bash(node -e \"const { ActivityType } = require\\('garmin-connect/dist/garmin/types/activity'\\); console.log\\('ActivityType.Cycling =', ActivityType.Cycling\\); console.log\\('All types:', JSON.stringify\\(ActivityType, null, 2\\)\\);\")",
24
24
  "Bash(ls:*)",
25
- "Bash(npm run:*)"
25
+ "Bash(npm run:*)",
26
+ "Bash(python3 -c ':*)"
26
27
  ]
27
28
  }
28
29
  }
package/bin/download.js CHANGED
@@ -48,15 +48,39 @@ const fs = __importStar(require("fs"));
48
48
  const garmin_connect_1 = require("garmin-connect");
49
49
  const _1 = require(".");
50
50
  const activity_1 = require("garmin-connect/dist/garmin/types/activity");
51
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
52
+ const DELAY = 3000; // 3s between bulk requests
53
+ function withRetry(fn_1) {
54
+ return __awaiter(this, arguments, void 0, function* (fn, retries = 3) {
55
+ var _a, _b;
56
+ for (let i = 0; i < retries; i++) {
57
+ try {
58
+ return yield fn();
59
+ }
60
+ catch (e) {
61
+ const is429 = ((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.includes("429")) || ((_b = e === null || e === void 0 ? void 0 : e.message) === null || _b === void 0 ? void 0 : _b.includes("Rate"));
62
+ if (is429 && i < retries - 1) {
63
+ const wait = DELAY * (i + 2);
64
+ console.log(`Rate limited, retrying in ${wait / 1000}s...`);
65
+ yield sleep(wait);
66
+ }
67
+ else {
68
+ throw e;
69
+ }
70
+ }
71
+ }
72
+ throw new Error("Unreachable");
73
+ });
74
+ }
51
75
  const download = (username, password) => __awaiter(void 0, void 0, void 0, function* () {
52
76
  const GCClient = new garmin_connect_1.GarminConnect({
53
77
  username,
54
78
  password,
55
79
  });
56
80
  yield GCClient.login(username, password);
57
- const activities = yield GCClient.getActivities(0, 6000, activity_1.ActivityType.FitnessEquipment,
81
+ const activities = yield withRetry(() => GCClient.getActivities(0, 6000, activity_1.ActivityType.FitnessEquipment,
58
82
  // @ts-ignore
59
- "indoor_climbing");
83
+ "indoor_climbing"));
60
84
  const indoorClimbingActivities = activities === null || activities === void 0 ? void 0 : activities.filter((activity) => { var _a; return ((_a = activity === null || activity === void 0 ? void 0 : activity.activityType) === null || _a === void 0 ? void 0 : _a.typeKey) === "indoor_climbing"; });
61
85
  if (!fs.existsSync(_1.garminDataFolder)) {
62
86
  fs.mkdirSync(_1.garminDataFolder);
@@ -66,16 +90,18 @@ const download = (username, password) => __awaiter(void 0, void 0, void 0, funct
66
90
  fs.writeFileSync(`${_1.garminDataFolder}/boulderingActivities.json`, JSON.stringify(boulderingActivities, null, 2));
67
91
  console.log("Downloaded climbing activities from Garmin Connect");
68
92
  // Download strength training activities
69
- const strengthActivities = yield GCClient.getActivities(0, 6000, activity_1.ActivityType.FitnessEquipment,
93
+ yield sleep(DELAY);
94
+ const strengthActivities = yield withRetry(() => GCClient.getActivities(0, 6000, activity_1.ActivityType.FitnessEquipment,
70
95
  // @ts-ignore
71
- "strength_training");
96
+ "strength_training"));
72
97
  const strengthTrainingActivities = strengthActivities === null || strengthActivities === void 0 ? void 0 : strengthActivities.filter((activity) => { var _a; return ((_a = activity === null || activity === void 0 ? void 0 : activity.activityType) === null || _a === void 0 ? void 0 : _a.typeKey) === "strength_training"; });
73
98
  // Fetch detailed data for each strength activity to get exercise sets
74
99
  console.log(`Found ${(strengthTrainingActivities === null || strengthTrainingActivities === void 0 ? void 0 : strengthTrainingActivities.length) || 0} strength training activities, fetching details...`);
75
100
  const detailedActivities = [];
76
101
  for (const activity of strengthTrainingActivities || []) {
77
102
  try {
78
- const detail = yield GCClient.getActivity({ activityId: activity.activityId });
103
+ yield sleep(1000);
104
+ const detail = yield withRetry(() => GCClient.getActivity({ activityId: activity.activityId }));
79
105
  detailedActivities.push(Object.assign(Object.assign({}, activity), { exerciseSets: (detail === null || detail === void 0 ? void 0 : detail.exerciseSets) || (detail === null || detail === void 0 ? void 0 : detail.summarizedExerciseSets) || (activity === null || activity === void 0 ? void 0 : activity.summarizedExerciseSets) || [], fullSummarizedExerciseSets: (detail === null || detail === void 0 ? void 0 : detail.summarizedExerciseSets) || (activity === null || activity === void 0 ? void 0 : activity.summarizedExerciseSets) || [] }));
80
106
  }
81
107
  catch (e) {
@@ -86,9 +112,10 @@ const download = (username, password) => __awaiter(void 0, void 0, void 0, funct
86
112
  fs.writeFileSync(`${_1.garminDataFolder}/strengthTrainingActivities.json`, JSON.stringify(detailedActivities, null, 2));
87
113
  console.log("Downloaded strength training activities from Garmin Connect");
88
114
  // Download running activities (street_running gets all running subtypes)
89
- const runningActivities = yield GCClient.getActivities(0, 6000,
115
+ yield sleep(DELAY);
116
+ const runningActivities = yield withRetry(() => GCClient.getActivities(0, 6000,
90
117
  // @ts-ignore
91
- "running");
118
+ "running"));
92
119
  const filteredRunning = (runningActivities || []).filter((a) => {
93
120
  var _a;
94
121
  const key = ((_a = a === null || a === void 0 ? void 0 : a.activityType) === null || _a === void 0 ? void 0 : _a.typeKey) || "";
@@ -97,13 +124,15 @@ const download = (username, password) => __awaiter(void 0, void 0, void 0, funct
97
124
  fs.writeFileSync(`${_1.garminDataFolder}/runningActivities.json`, JSON.stringify(filteredRunning, null, 2));
98
125
  console.log(`Downloaded ${filteredRunning.length} running activities from Garmin Connect`);
99
126
  // Download cycling activities
100
- const cyclingActivities = yield GCClient.getActivities(0, 6000,
127
+ yield sleep(DELAY);
128
+ const cyclingActivities = yield withRetry(() => GCClient.getActivities(0, 6000,
101
129
  // @ts-ignore
102
- "cycling");
130
+ "cycling"));
103
131
  // Download mountain biking activities using correct subtype
104
- const mtbActivities = yield GCClient.getActivities(0, 6000,
132
+ yield sleep(DELAY);
133
+ const mtbActivities = yield withRetry(() => GCClient.getActivities(0, 6000,
105
134
  // @ts-ignore
106
- "cycling", "mountain_biking");
135
+ "cycling", "mountain_biking"));
107
136
  const allCycling = [...(cyclingActivities || []), ...(mtbActivities || [])];
108
137
  const seen = new Set();
109
138
  const filteredCycling = allCycling.filter((a) => {
@@ -1 +1 @@
1
- {"version":3,"file":"download.js","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"download.js","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "garminclimb",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/download.ts CHANGED
@@ -6,6 +6,28 @@ import {
6
6
  ActivitySubType,
7
7
  ActivityType,
8
8
  } from "garmin-connect/dist/garmin/types/activity";
9
+
10
+ const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
11
+ const DELAY = 3000; // 3s between bulk requests
12
+
13
+ async function withRetry<T>(fn: () => Promise<T>, retries = 3): Promise<T> {
14
+ for (let i = 0; i < retries; i++) {
15
+ try {
16
+ return await fn();
17
+ } catch (e: any) {
18
+ const is429 = e?.message?.includes("429") || e?.message?.includes("Rate");
19
+ if (is429 && i < retries - 1) {
20
+ const wait = DELAY * (i + 2);
21
+ console.log(`Rate limited, retrying in ${wait / 1000}s...`);
22
+ await sleep(wait);
23
+ } else {
24
+ throw e;
25
+ }
26
+ }
27
+ }
28
+ throw new Error("Unreachable");
29
+ }
30
+
9
31
  export const download = async (
10
32
  username: string,
11
33
  password: string
@@ -17,13 +39,13 @@ export const download = async (
17
39
 
18
40
  await GCClient.login(username, password);
19
41
 
20
- const activities = await GCClient.getActivities(
42
+ const activities = await withRetry(() => GCClient.getActivities(
21
43
  0,
22
44
  6000,
23
45
  ActivityType.FitnessEquipment,
24
46
  // @ts-ignore
25
47
  "indoor_climbing"
26
- );
48
+ ));
27
49
 
28
50
  const indoorClimbingActivities = activities?.filter(
29
51
  (activity) => activity?.activityType?.typeKey === "indoor_climbing"
@@ -48,13 +70,14 @@ export const download = async (
48
70
  console.log("Downloaded climbing activities from Garmin Connect");
49
71
 
50
72
  // Download strength training activities
51
- const strengthActivities = await GCClient.getActivities(
73
+ await sleep(DELAY);
74
+ const strengthActivities = await withRetry(() => GCClient.getActivities(
52
75
  0,
53
76
  6000,
54
77
  ActivityType.FitnessEquipment,
55
78
  // @ts-ignore
56
79
  "strength_training"
57
- );
80
+ ));
58
81
 
59
82
  const strengthTrainingActivities = strengthActivities?.filter(
60
83
  (activity: any) => activity?.activityType?.typeKey === "strength_training"
@@ -65,7 +88,8 @@ export const download = async (
65
88
  const detailedActivities: any[] = [];
66
89
  for (const activity of strengthTrainingActivities || []) {
67
90
  try {
68
- const detail: any = await GCClient.getActivity({ activityId: activity.activityId });
91
+ await sleep(1000);
92
+ const detail: any = await withRetry(() => GCClient.getActivity({ activityId: activity.activityId }));
69
93
  detailedActivities.push({
70
94
  ...activity,
71
95
  exerciseSets: detail?.exerciseSets || detail?.summarizedExerciseSets || (activity as any)?.summarizedExerciseSets || [],
@@ -84,12 +108,13 @@ export const download = async (
84
108
  console.log("Downloaded strength training activities from Garmin Connect");
85
109
 
86
110
  // Download running activities (street_running gets all running subtypes)
87
- const runningActivities = await GCClient.getActivities(
111
+ await sleep(DELAY);
112
+ const runningActivities = await withRetry(() => GCClient.getActivities(
88
113
  0,
89
114
  6000,
90
115
  // @ts-ignore
91
116
  "running",
92
- );
117
+ ));
93
118
 
94
119
  const filteredRunning = (runningActivities || []).filter(
95
120
  (a: any) => {
@@ -105,21 +130,23 @@ export const download = async (
105
130
  console.log(`Downloaded ${filteredRunning.length} running activities from Garmin Connect`);
106
131
 
107
132
  // Download cycling activities
108
- const cyclingActivities = await GCClient.getActivities(
133
+ await sleep(DELAY);
134
+ const cyclingActivities = await withRetry(() => GCClient.getActivities(
109
135
  0,
110
136
  6000,
111
137
  // @ts-ignore
112
138
  "cycling",
113
- );
139
+ ));
114
140
 
115
141
  // Download mountain biking activities using correct subtype
116
- const mtbActivities = await GCClient.getActivities(
142
+ await sleep(DELAY);
143
+ const mtbActivities = await withRetry(() => GCClient.getActivities(
117
144
  0,
118
145
  6000,
119
146
  // @ts-ignore
120
147
  "cycling",
121
148
  "mountain_biking",
122
- );
149
+ ));
123
150
 
124
151
  const allCycling = [...(cyclingActivities || []), ...(mtbActivities || [])];
125
152
  const seen = new Set<number>();