@gooin/garmin-connect 1.6.5 → 1.6.7
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/README.md +243 -49
- package/dist/common/HttpClient.d.ts +1 -0
- package/dist/common/HttpClient.js +271 -421
- package/dist/common/HttpClient.js.map +1 -1
- package/dist/garmin/GarminConnect copy.d.ts +76 -0
- package/dist/garmin/GarminConnect copy.js +397 -0
- package/dist/garmin/GarminConnect copy.js.map +1 -0
- package/dist/garmin/GarminConnect.d.ts +35 -5
- package/dist/garmin/GarminConnect.js +404 -322
- package/dist/garmin/GarminConnect.js.map +1 -1
- package/dist/garmin/GarminConnect_new.d.ts +76 -0
- package/dist/garmin/GarminConnect_new.js +397 -0
- package/dist/garmin/GarminConnect_new.js.map +1 -0
- package/dist/garmin/GarminConnect_old.d.ts +75 -0
- package/dist/garmin/GarminConnect_old.js +386 -0
- package/dist/garmin/GarminConnect_old.js.map +1 -0
- package/dist/garmin/UrlClass.d.ts +16 -1
- package/dist/garmin/UrlClass.js +114 -139
- package/dist/garmin/UrlClass.js.map +1 -1
- package/dist/garmin/Urls copy.d.ts +66 -0
- package/dist/garmin/Urls copy.js +109 -0
- package/dist/garmin/Urls copy.js.map +1 -0
- package/dist/garmin/common/DateUtils.d.ts +6 -0
- package/dist/garmin/common/DateUtils.js +38 -0
- package/dist/garmin/common/DateUtils.js.map +1 -0
- package/dist/garmin/common/HydrationUtils.d.ts +2 -0
- package/dist/garmin/common/HydrationUtils.js +16 -0
- package/dist/garmin/common/HydrationUtils.js.map +1 -0
- package/dist/garmin/common/WeightUtils.d.ts +1 -0
- package/dist/garmin/common/WeightUtils.js +9 -0
- package/dist/garmin/common/WeightUtils.js.map +1 -0
- package/dist/garmin/types/activity.d.ts +408 -0
- package/dist/garmin/types/activity.js +27 -0
- package/dist/garmin/types/activity.js.map +1 -0
- package/dist/garmin/types/course.d.ts +146 -0
- package/dist/garmin/types/course.js +3 -0
- package/dist/garmin/types/course.js.map +1 -0
- package/dist/garmin/types/golf.d.ts +67 -0
- package/dist/garmin/types/golf.js +3 -0
- package/dist/garmin/types/golf.js.map +1 -0
- package/dist/garmin/types/heartrate.d.ts +22 -0
- package/dist/garmin/types/heartrate.js +2 -0
- package/dist/garmin/types/heartrate.js.map +1 -0
- package/dist/garmin/types/hydration.d.ts +28 -0
- package/dist/garmin/types/hydration.js +2 -0
- package/dist/garmin/types/hydration.js.map +1 -0
- package/dist/garmin/types/index.d.ts +541 -0
- package/dist/garmin/types/index.js +17 -0
- package/dist/garmin/types/index.js.map +1 -0
- package/dist/garmin/types/sleep.d.ts +120 -0
- package/dist/garmin/types/sleep.js +3 -0
- package/dist/garmin/types/sleep.js.map +1 -0
- package/dist/garmin/types/weight.d.ts +42 -0
- package/dist/garmin/types/weight.js +3 -0
- package/dist/garmin/types/weight.js.map +1 -0
- package/dist/garmin/types.d.ts +107 -0
- package/dist/garmin/workouts/Running.js +36 -53
- package/dist/garmin/workouts/Running.js.map +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +27 -36
- package/dist/utils.js.map +1 -1
- package/examples/example.js +1 -1
- package/package.json +1 -1
|
@@ -1,106 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
-
}
|
|
19
|
-
Object.defineProperty(o, k2, desc);
|
|
20
|
-
}) : (function(o, m, k, k2) {
|
|
21
|
-
if (k2 === undefined) k2 = k;
|
|
22
|
-
o[k2] = m[k];
|
|
23
|
-
}));
|
|
24
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
-
}) : function(o, v) {
|
|
27
|
-
o["default"] = v;
|
|
28
|
-
});
|
|
29
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
-
if (mod && mod.__esModule) return mod;
|
|
31
|
-
var result = {};
|
|
32
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
-
__setModuleDefault(result, mod);
|
|
34
|
-
return result;
|
|
35
|
-
};
|
|
36
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
-
});
|
|
44
|
-
};
|
|
45
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
46
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
47
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
48
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49
|
-
function step(op) {
|
|
50
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
51
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
52
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
53
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
54
|
-
switch (op[0]) {
|
|
55
|
-
case 0: case 1: t = op; break;
|
|
56
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
57
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
58
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
59
|
-
default:
|
|
60
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
61
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
62
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
63
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
64
|
-
if (t[2]) _.ops.pop();
|
|
65
|
-
_.trys.pop(); continue;
|
|
66
|
-
}
|
|
67
|
-
op = body.call(thisArg, _);
|
|
68
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
69
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
73
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
74
4
|
};
|
|
75
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76
6
|
exports.Event = void 0;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
config = app_root_path_1.default.require('/garmin.config.json');
|
|
91
|
-
}
|
|
92
|
-
catch (e) {
|
|
93
|
-
// Do nothing
|
|
94
|
-
}
|
|
7
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
8
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
9
|
+
const luxon_1 = require("luxon");
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const HttpClient_1 = require("../common/HttpClient");
|
|
13
|
+
const utils_1 = require("../utils");
|
|
14
|
+
const UrlClass_1 = require("./UrlClass");
|
|
15
|
+
const DateUtils_1 = require("./common/DateUtils");
|
|
16
|
+
const HydrationUtils_1 = require("./common/HydrationUtils");
|
|
17
|
+
const WeightUtils_1 = require("./common/WeightUtils");
|
|
18
|
+
const types_1 = require("./types");
|
|
19
|
+
const Running_1 = __importDefault(require("./workouts/Running"));
|
|
95
20
|
var Event;
|
|
96
21
|
(function (Event) {
|
|
97
22
|
Event["sessionChange"] = "sessionChange";
|
|
98
23
|
})(Event = exports.Event || (exports.Event = {}));
|
|
99
|
-
|
|
24
|
+
class GarminConnect {
|
|
100
25
|
// private oauth1: OAuth;
|
|
101
|
-
|
|
102
|
-
if (credentials === void 0) { credentials = config; }
|
|
103
|
-
if (domain === void 0) { domain = 'garmin.com'; }
|
|
26
|
+
constructor(credentials, domain = 'garmin.com') {
|
|
104
27
|
if (!credentials) {
|
|
105
28
|
throw new Error('Missing credentials');
|
|
106
29
|
}
|
|
@@ -110,47 +33,46 @@ var GarminConnect = /** @class */ (function () {
|
|
|
110
33
|
this._userHash = undefined;
|
|
111
34
|
this.listeners = {};
|
|
112
35
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return [2 /*return*/, this];
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
GarminConnect.prototype.exportTokenToFile = function (dirPath) {
|
|
131
|
-
if (!(0, utils_1.checkIsDirectory)(dirPath)) {
|
|
132
|
-
(0, utils_1.createDirectory)(dirPath);
|
|
36
|
+
async login(username, password) {
|
|
37
|
+
if (username && password) {
|
|
38
|
+
this.credentials.username = username;
|
|
39
|
+
this.credentials.password = password;
|
|
40
|
+
}
|
|
41
|
+
await this.client.login(this.credentials.username, this.credentials.password);
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
async exportTokenToFile(dirPath) {
|
|
45
|
+
const isDir = await (0, utils_1.checkIsDirectory)(dirPath);
|
|
46
|
+
if (!isDir) {
|
|
47
|
+
await (0, utils_1.createDirectory)(dirPath);
|
|
133
48
|
}
|
|
134
49
|
// save oauth1 to json
|
|
135
50
|
if (this.client.oauth1Token) {
|
|
136
|
-
(0, utils_1.writeToFile)(
|
|
51
|
+
await (0, utils_1.writeToFile)(node_path_1.default.join(dirPath, 'oauth1_token.json'), JSON.stringify(this.client.oauth1Token));
|
|
137
52
|
}
|
|
138
53
|
if (this.client.oauth2Token) {
|
|
139
|
-
(0, utils_1.writeToFile)(
|
|
54
|
+
await (0, utils_1.writeToFile)(node_path_1.default.join(dirPath, 'oauth2_token.json'), JSON.stringify(this.client.oauth2Token));
|
|
140
55
|
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
56
|
+
}
|
|
57
|
+
async loadTokenByFile(dirPath) {
|
|
58
|
+
const isDir = await (0, utils_1.checkIsDirectory)(dirPath);
|
|
59
|
+
if (!isDir) {
|
|
144
60
|
throw new Error('loadTokenByFile: Directory not found: ' + dirPath);
|
|
145
61
|
}
|
|
146
|
-
|
|
147
|
-
|
|
62
|
+
let oauth1Data = await node_fs_1.promises.readFile(node_path_1.default.join(dirPath, 'oauth1_token.json'), 'utf-8');
|
|
63
|
+
// console.log('loadTokenByFile - oauth1Data:', oauth1Data);
|
|
64
|
+
const oauth1 = JSON.parse(oauth1Data);
|
|
65
|
+
// console.log('loadTokenByFile - oauth1:', oauth1);
|
|
148
66
|
this.client.oauth1Token = oauth1;
|
|
149
|
-
|
|
150
|
-
|
|
67
|
+
let oauth2Data = await node_fs_1.promises.readFile(node_path_1.default.join(dirPath, 'oauth2_token.json'), 'utf-8');
|
|
68
|
+
// console.log('loadTokenByFile - oauth2Data:', oauth2Data);
|
|
69
|
+
const oauth2 = JSON.parse(oauth2Data);
|
|
70
|
+
// console.log('loadTokenByFile - oauth2:', oauth2);
|
|
151
71
|
this.client.oauth2Token = oauth2;
|
|
152
|
-
|
|
153
|
-
|
|
72
|
+
// console.log('loadTokenByFile - oauth2Token:', this);
|
|
73
|
+
// console.log('loadTokenByFile - oauth2Token:', this.client.oauth2Token);
|
|
74
|
+
}
|
|
75
|
+
exportToken() {
|
|
154
76
|
if (!this.client.oauth1Token || !this.client.oauth2Token) {
|
|
155
77
|
throw new Error('exportToken: Token not found');
|
|
156
78
|
}
|
|
@@ -158,218 +80,378 @@ var GarminConnect = /** @class */ (function () {
|
|
|
158
80
|
oauth1: this.client.oauth1Token,
|
|
159
81
|
oauth2: this.client.oauth2Token
|
|
160
82
|
};
|
|
161
|
-
}
|
|
83
|
+
}
|
|
162
84
|
// from db or localstorage etc
|
|
163
|
-
|
|
85
|
+
loadToken(oauth1, oauth2) {
|
|
164
86
|
this.client.oauth1Token = oauth1;
|
|
165
87
|
this.client.oauth2Token = oauth2;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return __generator(this, function (_a) {
|
|
177
|
-
return [2 /*return*/, this.client.get(this.url.USER_PROFILE)];
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
};
|
|
181
|
-
GarminConnect.prototype.getActivities = function (start, limit) {
|
|
182
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
183
|
-
return __generator(this, function (_a) {
|
|
184
|
-
return [2 /*return*/, this.client.get(this.url.ACTIVITIES, {
|
|
185
|
-
params: { start: start, limit: limit }
|
|
186
|
-
})];
|
|
187
|
-
});
|
|
88
|
+
}
|
|
89
|
+
async getUserSettings() {
|
|
90
|
+
return this.client.get(this.url.USER_SETTINGS);
|
|
91
|
+
}
|
|
92
|
+
async getUserProfile() {
|
|
93
|
+
return this.client.get(this.url.USER_PROFILE);
|
|
94
|
+
}
|
|
95
|
+
async getActivities(start, limit, activityType, subActivityType) {
|
|
96
|
+
return this.client.get(this.url.ACTIVITIES, {
|
|
97
|
+
params: { start, limit, activityType, subActivityType }
|
|
188
98
|
});
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
99
|
+
}
|
|
100
|
+
async getActivity(activity) {
|
|
101
|
+
if (!activity.activityId)
|
|
102
|
+
throw new Error('Missing activityId');
|
|
103
|
+
return this.client.get(this.url.ACTIVITY + activity.activityId);
|
|
104
|
+
}
|
|
105
|
+
async countActivities() {
|
|
106
|
+
return this.client.get(this.url.STAT_ACTIVITIES, {
|
|
107
|
+
params: {
|
|
108
|
+
aggregation: 'lifetime',
|
|
109
|
+
startDate: '1970-01-01',
|
|
110
|
+
endDate: luxon_1.DateTime.now().toFormat('yyyy-MM-dd'),
|
|
111
|
+
metric: 'duration'
|
|
112
|
+
}
|
|
197
113
|
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
metric: 'duration'
|
|
208
|
-
}
|
|
209
|
-
})];
|
|
210
|
-
});
|
|
114
|
+
}
|
|
115
|
+
async downloadWellnessData(date, dir) {
|
|
116
|
+
const dateStr = (0, DateUtils_1.toDateString)(date);
|
|
117
|
+
const isDir = await (0, utils_1.checkIsDirectory)(dir);
|
|
118
|
+
if (!isDir) {
|
|
119
|
+
await (0, utils_1.createDirectory)(dir);
|
|
120
|
+
}
|
|
121
|
+
let fileBuffer = await this.client.get(this.url.DOWNLOAD_WELLNESS + dateStr, {
|
|
122
|
+
responseType: 'arraybuffer'
|
|
211
123
|
});
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
fileBuffer = _a.sent();
|
|
235
|
-
return [3 /*break*/, 9];
|
|
236
|
-
case 4:
|
|
237
|
-
if (!(type === 'kml')) return [3 /*break*/, 6];
|
|
238
|
-
return [4 /*yield*/, this.client.get(this.url.DOWNLOAD_KML + activity.activityId)];
|
|
239
|
-
case 5:
|
|
240
|
-
fileBuffer = _a.sent();
|
|
241
|
-
return [3 /*break*/, 9];
|
|
242
|
-
case 6:
|
|
243
|
-
if (!(type === 'zip')) return [3 /*break*/, 8];
|
|
244
|
-
return [4 /*yield*/, this.client.get(this.url.DOWNLOAD_ZIP + activity.activityId, {
|
|
245
|
-
responseType: 'arraybuffer'
|
|
246
|
-
})];
|
|
247
|
-
case 7:
|
|
248
|
-
fileBuffer = _a.sent();
|
|
249
|
-
return [3 /*break*/, 9];
|
|
250
|
-
case 8: throw new Error('downloadOriginalActivityData - Invalid type: ' + type);
|
|
251
|
-
case 9:
|
|
252
|
-
(0, utils_1.writeToFile)(path.join(dir, "".concat(activity.activityId, ".").concat(type)), fileBuffer);
|
|
253
|
-
return [2 /*return*/];
|
|
254
|
-
}
|
|
124
|
+
await (0, utils_1.writeToFile)(node_path_1.default.join(dir, `${dateStr}.zip`), fileBuffer);
|
|
125
|
+
}
|
|
126
|
+
async downloadOriginalActivityData(activity, dir, type = 'zip') {
|
|
127
|
+
if (!activity.activityId)
|
|
128
|
+
throw new Error('Missing activityId');
|
|
129
|
+
const isDir = await (0, utils_1.checkIsDirectory)(dir);
|
|
130
|
+
if (!isDir) {
|
|
131
|
+
await (0, utils_1.createDirectory)(dir);
|
|
132
|
+
}
|
|
133
|
+
let fileBuffer;
|
|
134
|
+
if (type === 'tcx') {
|
|
135
|
+
fileBuffer = await this.client.get(this.url.DOWNLOAD_TCX + activity.activityId);
|
|
136
|
+
}
|
|
137
|
+
else if (type === 'gpx') {
|
|
138
|
+
fileBuffer = await this.client.get(this.url.DOWNLOAD_GPX + activity.activityId);
|
|
139
|
+
}
|
|
140
|
+
else if (type === 'kml') {
|
|
141
|
+
fileBuffer = await this.client.get(this.url.DOWNLOAD_KML + activity.activityId);
|
|
142
|
+
}
|
|
143
|
+
else if (type === 'zip') {
|
|
144
|
+
fileBuffer = await this.client.get(this.url.DOWNLOAD_ZIP + activity.activityId, {
|
|
145
|
+
responseType: 'arraybuffer'
|
|
255
146
|
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
throw new Error('downloadOriginalActivityData - Invalid type: ' + type);
|
|
150
|
+
}
|
|
151
|
+
await (0, utils_1.writeToFile)(node_path_1.default.join(dir, `${activity.activityId}.${type}`), fileBuffer);
|
|
152
|
+
}
|
|
153
|
+
async uploadActivity(file, format = 'fit') {
|
|
259
154
|
var _a;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
return [4 /*yield*/, this.client.post(this.url.UPLOAD + '.' + format, form, {
|
|
274
|
-
headers: {
|
|
275
|
-
'Content-Type': form.getHeaders()['content-type']
|
|
276
|
-
}
|
|
277
|
-
})];
|
|
278
|
-
case 1:
|
|
279
|
-
response = _b.sent();
|
|
280
|
-
return [2 /*return*/, response];
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
};
|
|
285
|
-
GarminConnect.prototype.deleteActivity = function (activity) {
|
|
286
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
287
|
-
return __generator(this, function (_a) {
|
|
288
|
-
switch (_a.label) {
|
|
289
|
-
case 0:
|
|
290
|
-
if (!activity.activityId)
|
|
291
|
-
throw new Error('Missing activityId');
|
|
292
|
-
return [4 /*yield*/, this.client.delete(this.url.ACTIVITY + activity.activityId)];
|
|
293
|
-
case 1:
|
|
294
|
-
_a.sent();
|
|
295
|
-
return [2 /*return*/];
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
};
|
|
300
|
-
GarminConnect.prototype.getWorkouts = function (start, limit) {
|
|
301
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
302
|
-
return __generator(this, function (_a) {
|
|
303
|
-
return [2 /*return*/, this.client.get(this.url.WORKOUTS, {
|
|
304
|
-
params: {
|
|
305
|
-
start: start,
|
|
306
|
-
limit: limit
|
|
307
|
-
}
|
|
308
|
-
})];
|
|
309
|
-
});
|
|
155
|
+
const detectedFormat = (_a = (format || node_path_1.default.extname(file))) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
156
|
+
if (!lodash_1.default.includes(types_1.UploadFileType, detectedFormat)) {
|
|
157
|
+
throw new Error('uploadActivity - Invalid format: ' + format);
|
|
158
|
+
}
|
|
159
|
+
// const fh = await fs.open(file);
|
|
160
|
+
const fileBuffer = (0, node_fs_1.createReadStream)(file);
|
|
161
|
+
// console.log('fileBuffer:', fileBuffer);
|
|
162
|
+
const form = new form_data_1.default();
|
|
163
|
+
form.append('userfile', fileBuffer);
|
|
164
|
+
const response = await this.client.post(this.url.UPLOAD + '.' + format, form, {
|
|
165
|
+
headers: {
|
|
166
|
+
'Content-Type': form.getHeaders()['content-type']
|
|
167
|
+
}
|
|
310
168
|
});
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
169
|
+
return response;
|
|
170
|
+
}
|
|
171
|
+
async deleteActivity(activity) {
|
|
172
|
+
if (!activity.activityId)
|
|
173
|
+
throw new Error('Missing activityId');
|
|
174
|
+
await this.client.delete(this.url.ACTIVITY + activity.activityId);
|
|
175
|
+
}
|
|
176
|
+
async getWorkouts(start, limit) {
|
|
177
|
+
return this.client.get(this.url.WORKOUTS, {
|
|
178
|
+
params: {
|
|
179
|
+
start,
|
|
180
|
+
limit
|
|
181
|
+
}
|
|
319
182
|
});
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
newWorkout = lodash_1.default.omit(workout, [
|
|
337
|
-
'workoutId',
|
|
338
|
-
'ownerId',
|
|
339
|
-
'updatedDate',
|
|
340
|
-
'createdDate',
|
|
341
|
-
'author'
|
|
342
|
-
]);
|
|
343
|
-
if (!newWorkout.description) {
|
|
344
|
-
newWorkout.description = 'Added by garmin-connect for Node.js';
|
|
183
|
+
}
|
|
184
|
+
async getWorkoutDetail(workout) {
|
|
185
|
+
if (!workout.workoutId)
|
|
186
|
+
throw new Error('Missing workoutId');
|
|
187
|
+
return this.client.get(this.url.WORKOUT(workout.workoutId));
|
|
188
|
+
}
|
|
189
|
+
async addWorkout(workout) {
|
|
190
|
+
if (!workout)
|
|
191
|
+
throw new Error('Missing workout');
|
|
192
|
+
if (workout instanceof Running_1.default) {
|
|
193
|
+
if (workout.isValid()) {
|
|
194
|
+
const data = { ...workout.toJson() };
|
|
195
|
+
if (!data.description) {
|
|
196
|
+
data.description = 'Added by garmin-connect for Node.js';
|
|
345
197
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
198
|
+
return this.client.post(this.url.WORKOUT(), data);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!workout.workoutSegments)
|
|
202
|
+
throw new Error('Missing workoutSegments, please use WorkoutDetail, not Workout.');
|
|
203
|
+
const newWorkout = lodash_1.default.omit(workout, [
|
|
204
|
+
'workoutId',
|
|
205
|
+
'ownerId',
|
|
206
|
+
'updatedDate',
|
|
207
|
+
'createdDate',
|
|
208
|
+
'author'
|
|
209
|
+
]);
|
|
210
|
+
if (!newWorkout.description) {
|
|
211
|
+
newWorkout.description = 'Added by garmin-connect for Node.js';
|
|
212
|
+
}
|
|
213
|
+
// console.log('addWorkout - newWorkout:', newWorkout)
|
|
214
|
+
return this.client.post(this.url.WORKOUT(), newWorkout);
|
|
215
|
+
}
|
|
216
|
+
async addRunningWorkout(name, meters, description) {
|
|
217
|
+
const running = new Running_1.default();
|
|
218
|
+
running.name = name;
|
|
219
|
+
running.distance = meters;
|
|
220
|
+
running.description = description;
|
|
221
|
+
return this.addWorkout(running);
|
|
222
|
+
}
|
|
223
|
+
async deleteWorkout(workout) {
|
|
224
|
+
if (!workout.workoutId)
|
|
225
|
+
throw new Error('Missing workout');
|
|
226
|
+
return this.client.delete(this.url.WORKOUT(workout.workoutId));
|
|
227
|
+
}
|
|
228
|
+
async scheduleWorkout(workout, date = new Date()) {
|
|
229
|
+
if (!workout.workoutId)
|
|
230
|
+
throw new Error('Missing workoutId');
|
|
231
|
+
const formatedDate = luxon_1.DateTime.fromJSDate(date).toFormat('yyyy-MM-dd');
|
|
232
|
+
return this.client.post(`${this.url.SCHEDULE_WORKOUTS}${workout.workoutId}`, {
|
|
233
|
+
date: formatedDate
|
|
349
234
|
});
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
235
|
+
}
|
|
236
|
+
// Garmin use month 0-11, not real month.
|
|
237
|
+
async getCalendar(year = new Date().getFullYear(), month = new Date().getMonth()) {
|
|
238
|
+
return this.client.get(this.url.CALENDAR(year, month));
|
|
239
|
+
}
|
|
240
|
+
async getSteps(date = new Date()) {
|
|
241
|
+
const dateString = (0, DateUtils_1.toDateString)(date);
|
|
242
|
+
const days = await this.client.get(`${this.url.DAILY_STEPS}${dateString}/${dateString}`);
|
|
243
|
+
const dayStats = days.find(({ calendarDate }) => calendarDate === dateString);
|
|
244
|
+
if (!dayStats) {
|
|
245
|
+
throw new Error("Can't find daily steps for this date.");
|
|
246
|
+
}
|
|
247
|
+
return dayStats.totalSteps;
|
|
248
|
+
}
|
|
249
|
+
async getSleepData(date = new Date()) {
|
|
250
|
+
try {
|
|
251
|
+
const dateString = (0, DateUtils_1.toDateString)(date);
|
|
252
|
+
const sleepData = await this.client.get(`${this.url.DAILY_SLEEP}`, { params: { date: dateString } });
|
|
253
|
+
if (!sleepData) {
|
|
254
|
+
throw new Error('Invalid or empty sleep data response.');
|
|
255
|
+
}
|
|
256
|
+
return sleepData;
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
throw new Error(`Error in getSleepData: ${error.message}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
async getSleepDuration(date = new Date()) {
|
|
263
|
+
try {
|
|
264
|
+
const sleepData = await this.getSleepData(date);
|
|
265
|
+
if (!sleepData ||
|
|
266
|
+
!sleepData.dailySleepDTO ||
|
|
267
|
+
sleepData.dailySleepDTO.sleepStartTimestampGMT === undefined ||
|
|
268
|
+
sleepData.dailySleepDTO.sleepEndTimestampGMT === undefined) {
|
|
269
|
+
throw new Error('Invalid or missing sleep data for the specified date.');
|
|
270
|
+
}
|
|
271
|
+
const sleepStartTimestampGMT = sleepData.dailySleepDTO.sleepStartTimestampGMT;
|
|
272
|
+
const sleepEndTimestampGMT = sleepData.dailySleepDTO.sleepEndTimestampGMT;
|
|
273
|
+
const { hours, minutes } = (0, DateUtils_1.calculateTimeDifference)(sleepStartTimestampGMT, sleepEndTimestampGMT);
|
|
274
|
+
return {
|
|
275
|
+
hours,
|
|
276
|
+
minutes
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
throw new Error(`Error in getSleepDuration: ${error.message}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async getDailyWeightData(date = new Date()) {
|
|
284
|
+
try {
|
|
285
|
+
const dateString = (0, DateUtils_1.toDateString)(date);
|
|
286
|
+
const weightData = await this.client.get(`${this.url.DAILY_WEIGHT}/${dateString}`);
|
|
287
|
+
if (!weightData) {
|
|
288
|
+
throw new Error('Invalid or empty weight data response.');
|
|
289
|
+
}
|
|
290
|
+
return weightData;
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
throw new Error(`Error in getDailyWeightData: ${error.message}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async getDailyWeightInPounds(date = new Date()) {
|
|
297
|
+
const weightData = await this.getDailyWeightData(date);
|
|
298
|
+
if (weightData.totalAverage &&
|
|
299
|
+
typeof weightData.totalAverage.weight === 'number') {
|
|
300
|
+
return (0, WeightUtils_1.gramsToPounds)(weightData.totalAverage.weight);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
throw new Error("Can't find valid daily weight for this date.");
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
async getDailyHydration(date = new Date()) {
|
|
307
|
+
try {
|
|
308
|
+
const dateString = (0, DateUtils_1.toDateString)(date);
|
|
309
|
+
const hydrationData = await this.client.get(`${this.url.DAILY_HYDRATION}/${dateString}`);
|
|
310
|
+
if (!hydrationData || !hydrationData.valueInML) {
|
|
311
|
+
throw new Error('Invalid or empty hydration data response.');
|
|
312
|
+
}
|
|
313
|
+
return (0, HydrationUtils_1.convertMLToOunces)(hydrationData.valueInML);
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
throw new Error(`Error in getDailyHydration: ${error.message}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async updateWeight(date = new Date(), lbs, timezone) {
|
|
320
|
+
try {
|
|
321
|
+
const weightData = await this.client.post(`${this.url.UPDATE_WEIGHT}`, {
|
|
322
|
+
dateTimestamp: (0, DateUtils_1.getLocalTimestamp)(date, timezone),
|
|
323
|
+
gmtTimestamp: date.toISOString().substring(0, 23),
|
|
324
|
+
unitKey: 'lbs',
|
|
325
|
+
value: lbs
|
|
360
326
|
});
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
327
|
+
return weightData;
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
throw new Error(`Error in updateWeight: ${error.message}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
async updateHydrationLogOunces(date = new Date(), valueInOz) {
|
|
334
|
+
try {
|
|
335
|
+
const dateString = (0, DateUtils_1.toDateString)(date);
|
|
336
|
+
const hydrationData = await this.client.put(`${this.url.HYDRATION_LOG}`, {
|
|
337
|
+
calendarDate: dateString,
|
|
338
|
+
valueInML: (0, HydrationUtils_1.convertOuncesToML)(valueInOz),
|
|
339
|
+
userProfileId: (await this.getUserProfile()).profileId,
|
|
340
|
+
timestampLocal: date.toISOString().substring(0, 23)
|
|
369
341
|
});
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
342
|
+
return hydrationData;
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
throw new Error(`Error in updateHydrationLogOunces: ${error.message}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
async getGolfSummary() {
|
|
349
|
+
try {
|
|
350
|
+
const golfSummary = await this.client.get(`${this.url.GOLF_SCORECARD_SUMMARY}`);
|
|
351
|
+
if (!golfSummary) {
|
|
352
|
+
throw new Error('Invalid or empty golf summary data response.');
|
|
353
|
+
}
|
|
354
|
+
return golfSummary;
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
throw new Error(`Error in getGolfSummary: ${error.message}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
async getGolfScorecard(scorecardId) {
|
|
361
|
+
try {
|
|
362
|
+
const golfScorecard = await this.client.get(`${this.url.GOLF_SCORECARD_DETAIL}`, { params: { 'scorecard-ids': scorecardId } });
|
|
363
|
+
if (!golfScorecard) {
|
|
364
|
+
throw new Error('Invalid or empty golf scorecard data response.');
|
|
365
|
+
}
|
|
366
|
+
return golfScorecard;
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
throw new Error(`Error in getGolfScorecard: ${error.message}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async getHeartRate(date = new Date()) {
|
|
373
|
+
try {
|
|
374
|
+
const dateString = (0, DateUtils_1.toDateString)(date);
|
|
375
|
+
const heartRate = await this.client.get(`${this.url.DAILY_HEART_RATE}`, { params: { date: dateString } });
|
|
376
|
+
return heartRate;
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
throw new Error(`Error in getHeartRate: ${error.message}`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async getCourses() {
|
|
383
|
+
try {
|
|
384
|
+
const coursesForUser = await this.client.get(`${this.url.COURSE_OWNER}`);
|
|
385
|
+
const courses_favorite = await this.client.get(`${this.url.COURSE_FAVORITE}`);
|
|
386
|
+
const course = [
|
|
387
|
+
...coursesForUser.coursesForUser,
|
|
388
|
+
...courses_favorite
|
|
389
|
+
];
|
|
390
|
+
const uniqCourse = lodash_1.default.uniqBy(course, 'courseId');
|
|
391
|
+
return uniqCourse;
|
|
392
|
+
}
|
|
393
|
+
catch (error) {
|
|
394
|
+
throw new Error(`Error in getHeartRate: ${error.message}`);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
async getCourse(course) {
|
|
398
|
+
try {
|
|
399
|
+
if (!course.courseId) {
|
|
400
|
+
throw new Error('Missing courseId');
|
|
401
|
+
}
|
|
402
|
+
const courseDetail = await this.client.get(`${this.url.COURSE(course.courseId)}`);
|
|
403
|
+
return courseDetail;
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
throw new Error(`Error in getHeartRate: ${error.message}`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
async createCourse(course) {
|
|
410
|
+
try {
|
|
411
|
+
const createdCourse = await this.client.post(`${this.url.COURSE()}`, lodash_1.default.omit(course, [
|
|
412
|
+
'courseId',
|
|
413
|
+
// 'description',
|
|
414
|
+
'matchedToSegments',
|
|
415
|
+
'userProfilePk',
|
|
416
|
+
'userGroupPk',
|
|
417
|
+
'firstName',
|
|
418
|
+
'lastName',
|
|
419
|
+
'displayName',
|
|
420
|
+
'geoRoutePk',
|
|
421
|
+
'sourcePk',
|
|
422
|
+
'hasShareableEvent',
|
|
423
|
+
'virtualPartnerId',
|
|
424
|
+
'includeLaps',
|
|
425
|
+
'speedMeterPerSecond',
|
|
426
|
+
'createDate',
|
|
427
|
+
'updateDate',
|
|
428
|
+
'targetCoordinateSystem',
|
|
429
|
+
'originalCoordinateSystem',
|
|
430
|
+
'consumer',
|
|
431
|
+
'elevationSource',
|
|
432
|
+
'hasPaceBand',
|
|
433
|
+
'hasPowerGuide',
|
|
434
|
+
'favorite',
|
|
435
|
+
'curatedCoursePk'
|
|
436
|
+
]));
|
|
437
|
+
return createdCourse;
|
|
438
|
+
}
|
|
439
|
+
catch (error) {
|
|
440
|
+
throw new Error(`Error in getHeartRate: ${error.message}`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async get(url, data) {
|
|
444
|
+
const response = await this.client.get(url, data);
|
|
445
|
+
return response;
|
|
446
|
+
}
|
|
447
|
+
async post(url, data) {
|
|
448
|
+
const response = await this.client.post(url, data, {});
|
|
449
|
+
return response;
|
|
450
|
+
}
|
|
451
|
+
async put(url, data) {
|
|
452
|
+
const response = await this.client.put(url, data, {});
|
|
453
|
+
return response;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
374
456
|
exports.default = GarminConnect;
|
|
375
457
|
//# sourceMappingURL=GarminConnect.js.map
|