@gooin/garmin-connect 1.8.5 → 1.8.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 +59 -0
- package/dist/common/FileMFASessionStorage.js +1 -1
- package/dist/common/HttpClient copy.js +1 -1
- package/dist/common/HttpClient.d.ts +1 -0
- package/dist/common/HttpClient.js +1 -1
- package/dist/common/HttpClient.js.map +1 -1
- package/dist/common/HttpClientOLD.js +1 -1
- package/dist/common/HttpClientOLDV1.js +1 -1
- package/dist/common/HttpClientV1.js +1 -1
- package/dist/common/MFAManager.js +1 -1
- package/dist/common/MFASessionStorage.js +1 -1
- package/dist/common/RedisMFASessionStorage.js +1 -1
- package/dist/garmin/GarminConnect.d.ts +17 -3
- package/dist/garmin/GarminConnect.js +1 -1
- package/dist/garmin/UrlClass.d.ts +6 -0
- package/dist/garmin/UrlClass.js +1 -1
- package/dist/garmin/UrlClass.js.map +1 -1
- package/dist/garmin/common/DateUtils.js +1 -1
- package/dist/garmin/common/HydrationUtils.js +1 -1
- package/dist/garmin/common/WeightUtils.js +1 -1
- package/dist/garmin/modules/activity/base.d.ts +4 -1
- package/dist/garmin/modules/activity/base.js +1 -1
- package/dist/garmin/modules/activity/base.js.map +1 -1
- package/dist/garmin/modules/activity/cycling.js +1 -1
- package/dist/garmin/modules/activity/running.d.ts +3 -0
- package/dist/garmin/modules/activity/running.js +1 -1
- package/dist/garmin/modules/activity/running.js.map +1 -1
- package/dist/garmin/modules/activity/training-status.d.ts +3 -0
- package/dist/garmin/modules/activity/training-status.js +1 -1
- package/dist/garmin/modules/activity/training-status.js.map +1 -1
- package/dist/garmin/modules/coach/activity-summary.d.ts +1 -0
- package/dist/garmin/modules/coach/activity-summary.js +1 -1
- package/dist/garmin/modules/coach/activity-summary.js.map +1 -1
- package/dist/garmin/modules/coach/helpers.d.ts +11 -1
- package/dist/garmin/modules/coach/helpers.js +1 -1
- package/dist/garmin/modules/coach/helpers.js.map +1 -1
- package/dist/garmin/modules/coach/sleep-analysis.d.ts +8 -0
- package/dist/garmin/modules/coach/sleep-analysis.js +1 -0
- package/dist/garmin/modules/coach/sleep-analysis.js.map +1 -0
- package/dist/garmin/modules/coach/training-overview.js +1 -1
- package/dist/garmin/modules/coach/training-overview.js.map +1 -1
- package/dist/garmin/modules/coach/wellness-overview.js +1 -1
- package/dist/garmin/modules/coach/wellness-overview.js.map +1 -1
- package/dist/garmin/modules/coach/wellness-summary.js +1 -1
- package/dist/garmin/modules/coach.d.ts +2 -1
- package/dist/garmin/modules/coach.js +1 -1
- package/dist/garmin/modules/coach.js.map +1 -1
- package/dist/garmin/modules/course.js +1 -1
- package/dist/garmin/modules/device.js +1 -1
- package/dist/garmin/modules/misc.js +1 -1
- package/dist/garmin/modules/types.js +1 -1
- package/dist/garmin/modules/user.js +1 -1
- package/dist/garmin/modules/wellness/body-battery.js +1 -1
- package/dist/garmin/modules/wellness/heart-rate.js +1 -1
- package/dist/garmin/modules/wellness/hrv.js +1 -1
- package/dist/garmin/modules/wellness/hydration.js +1 -1
- package/dist/garmin/modules/wellness/sleep.js +1 -1
- package/dist/garmin/modules/wellness/sleep.js.map +1 -1
- package/dist/garmin/modules/wellness/weight.js +1 -1
- package/dist/garmin/modules/workout.d.ts +9 -3
- package/dist/garmin/modules/workout.js +1 -1
- package/dist/garmin/modules/workout.js.map +1 -1
- package/dist/garmin/types/activity-stats.js +1 -1
- package/dist/garmin/types/activity.d.ts +30 -0
- package/dist/garmin/types/activity.js +1 -1
- package/dist/garmin/types/body-battery.js +1 -1
- package/dist/garmin/types/coach.d.ts +15 -0
- package/dist/garmin/types/coach.js +1 -1
- package/dist/garmin/types/course.js +1 -1
- package/dist/garmin/types/cycling.js +1 -1
- package/dist/garmin/types/device.js +1 -1
- package/dist/garmin/types/golf.js +1 -1
- package/dist/garmin/types/heartrate.js +1 -1
- package/dist/garmin/types/hrv.js +1 -1
- package/dist/garmin/types/hydration.js +1 -1
- package/dist/garmin/types/index.d.ts +1 -0
- package/dist/garmin/types/index.js +1 -1
- package/dist/garmin/types/index.js.map +1 -1
- package/dist/garmin/types/personal-info.js +1 -1
- package/dist/garmin/types/race-prediction.js +1 -1
- package/dist/garmin/types/sleep.d.ts +31 -0
- package/dist/garmin/types/sleep.js +1 -1
- package/dist/garmin/types/training-status.js +1 -1
- package/dist/garmin/types/weight.js +1 -1
- package/dist/garmin/types/workout.d.ts +167 -0
- package/dist/garmin/types/workout.js +1 -0
- package/dist/garmin/types/workout.js.map +1 -0
- package/dist/garmin/workouts/Running.js +1 -1
- package/dist/garmin/workouts/templates/RunningTemplate.js +1 -1
- package/dist/garmin/workouts/workout-draft.d.ts +3 -0
- package/dist/garmin/workouts/workout-draft.js +1 -0
- package/dist/garmin/workouts/workout-draft.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -547,6 +547,65 @@ GCClient.addRunningWorkout('My 5k run', 5000, 'Some description');
|
|
|
547
547
|
|
|
548
548
|
Will add a running workout of 5km called 'My 5k run' and return a JSON object representing the saved workout.
|
|
549
549
|
|
|
550
|
+
### Compile an AI coach workout draft
|
|
551
|
+
|
|
552
|
+
Use `workout_draft_v1` as a transport-neutral, metric input. The compiler
|
|
553
|
+
validates the draft and converts user-readable values to Garmin workout fields.
|
|
554
|
+
Compilation does not write to Garmin.
|
|
555
|
+
|
|
556
|
+
```ts
|
|
557
|
+
import { compileWorkoutDraft, type WorkoutDraft } from '@gooin/garmin-connect';
|
|
558
|
+
|
|
559
|
+
const draft: WorkoutDraft = {
|
|
560
|
+
schema: 'workout_draft_v1',
|
|
561
|
+
sport: 'running',
|
|
562
|
+
name: '4 x 1 km threshold',
|
|
563
|
+
estimatedDurationSec: 3600,
|
|
564
|
+
steps: [
|
|
565
|
+
{
|
|
566
|
+
type: 'step',
|
|
567
|
+
stepType: 'warmup',
|
|
568
|
+
duration: { type: 'time', seconds: 600 }
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
type: 'repeat',
|
|
572
|
+
iterations: 4,
|
|
573
|
+
steps: [
|
|
574
|
+
{
|
|
575
|
+
type: 'step',
|
|
576
|
+
stepType: 'interval',
|
|
577
|
+
duration: { type: 'distance', meters: 1000 },
|
|
578
|
+
target: {
|
|
579
|
+
type: 'pace',
|
|
580
|
+
fastestSecPerKm: 270,
|
|
581
|
+
slowestSecPerKm: 285
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
type: 'step',
|
|
586
|
+
stepType: 'recovery',
|
|
587
|
+
duration: { type: 'time', seconds: 120 }
|
|
588
|
+
}
|
|
589
|
+
]
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
type: 'step',
|
|
593
|
+
stepType: 'cooldown',
|
|
594
|
+
duration: { type: 'time', seconds: 600 }
|
|
595
|
+
}
|
|
596
|
+
]
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
const payload = compileWorkoutDraft(draft);
|
|
600
|
+
|
|
601
|
+
// Execute these write operations only after explicit user confirmation.
|
|
602
|
+
const workout = await GCClient.addWorkout(payload);
|
|
603
|
+
await GCClient.scheduleWorkout(
|
|
604
|
+
{ workoutId: String(workout.workoutId) },
|
|
605
|
+
new Date('2026-06-16')
|
|
606
|
+
);
|
|
607
|
+
```
|
|
608
|
+
|
|
550
609
|
### Schedule workout
|
|
551
610
|
|
|
552
611
|
To add a workout to your calendar, first find your workout and then add it to a specific date.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';const
|
|
1
|
+
'use strict';function a0_0x4b00(_0x46729b,_0x382ef4){_0x46729b=_0x46729b-0x65;const _0x9bde0=a0_0x9bde();let _0x4b001d=_0x9bde0[_0x46729b];return _0x4b001d;}const a0_0x4fe206=a0_0x4b00;(function(_0x49d586,_0x352705){const _0x2c157f=a0_0x4b00,_0x42bb4d=_0x49d586();while(!![]){try{const _0x1c7ce4=-parseInt(_0x2c157f(0x8a))/0x1+-parseInt(_0x2c157f(0x95))/0x2+-parseInt(_0x2c157f(0x78))/0x3*(parseInt(_0x2c157f(0x8f))/0x4)+parseInt(_0x2c157f(0x90))/0x5*(parseInt(_0x2c157f(0xa1))/0x6)+parseInt(_0x2c157f(0x84))/0x7+parseInt(_0x2c157f(0xa3))/0x8*(-parseInt(_0x2c157f(0x77))/0x9)+-parseInt(_0x2c157f(0x96))/0xa*(-parseInt(_0x2c157f(0x74))/0xb);if(_0x1c7ce4===_0x352705)break;else _0x42bb4d['push'](_0x42bb4d['shift']());}catch(_0x41165c){_0x42bb4d['push'](_0x42bb4d['shift']());}}}(a0_0x9bde,0xcfa74));var __importDefault=this&&this[a0_0x4fe206(0x8e)]||function(_0x1a6281){const _0x4c0fbd=a0_0x4fe206;return _0x1a6281&&_0x1a6281[_0x4c0fbd(0x6c)]?_0x1a6281:{'default':_0x1a6281};};Object[a0_0x4fe206(0x89)](exports,a0_0x4fe206(0x6c),{'value':!![]}),exports[a0_0x4fe206(0x6a)]=void 0x0;const fs_1=require('fs'),path_1=__importDefault(require(a0_0x4fe206(0x85)));class FileMFASessionStorage{constructor(_0x54bb95){const _0x1fe5ba=a0_0x4fe206;this[_0x1fe5ba(0x73)]=0x5*0x3c*0x3e8,this[_0x1fe5ba(0x86)]=_0x54bb95,this[_0x1fe5ba(0x9d)]();}async[a0_0x4fe206(0x9d)](){const _0x1835f9=a0_0x4fe206;try{await fs_1[_0x1835f9(0x69)][_0x1835f9(0x66)](this[_0x1835f9(0x86)],{'recursive':!![]});}catch(_0x4cf74b){console[_0x1835f9(0x83)](_0x1835f9(0x6f),_0x4cf74b);}}['getSessionFilePath'](_0x227534){const _0x25ef00=a0_0x4fe206;return path_1[_0x25ef00(0x68)][_0x25ef00(0xa0)](this[_0x25ef00(0x86)],_0x227534+_0x25ef00(0x8c));}async[a0_0x4fe206(0x7e)](_0x454e51,_0xd5647e=this['DEFAULT_TIMEOUT']){const _0x53e83f=a0_0x4fe206;await this[_0x53e83f(0x9d)](),await this[_0x53e83f(0x76)](_0x454e51);const _0x5c97f9={'sessionId':_0x454e51,'status':'waiting','createdAt':new Date()[_0x53e83f(0x88)](),'timeout':_0xd5647e},_0x3e4716=this[_0x53e83f(0x72)](_0x454e51);return await fs_1[_0x53e83f(0x69)][_0x53e83f(0x9e)](_0x3e4716,JSON[_0x53e83f(0x6e)](_0x5c97f9),_0x53e83f(0x65)),console['log']('MFA验证会话已创建:\x20'+_0x454e51),new Promise((_0x51b897,_0x1c8afa)=>{const _0x573f03=_0x53e83f,_0x1a089d=Date[_0x573f03(0x7f)](),_0x47fc86=setInterval(async()=>{const _0x7cb0d7=_0x573f03;try{if(Date[_0x7cb0d7(0x7f)]()-_0x1a089d>_0xd5647e){clearInterval(_0x47fc86),await this[_0x7cb0d7(0x76)](_0x454e51),_0x1c8afa(new Error('MFA验证超时,请重新登录'));return;}try{const _0x3885b9=await fs_1[_0x7cb0d7(0x69)][_0x7cb0d7(0x9b)](_0x3e4716,_0x7cb0d7(0x65)),_0x3b8fe5=JSON[_0x7cb0d7(0x81)](_0x3885b9);if(_0x3b8fe5[_0x7cb0d7(0x70)]===_0x7cb0d7(0x9f)&&_0x3b8fe5[_0x7cb0d7(0x91)]){clearInterval(_0x47fc86),await this[_0x7cb0d7(0x76)](_0x454e51),_0x51b897(_0x3b8fe5[_0x7cb0d7(0x91)]);return;}if(_0x3b8fe5[_0x7cb0d7(0x70)]===_0x7cb0d7(0x98)&&_0x3b8fe5[_0x7cb0d7(0x83)]){clearInterval(_0x47fc86),await this[_0x7cb0d7(0x76)](_0x454e51),_0x1c8afa(new Error(_0x3b8fe5['error']));return;}}catch(_0x447d13){}}catch(_0x688e16){clearInterval(_0x47fc86),await this[_0x7cb0d7(0x76)](_0x454e51),_0x1c8afa(_0x688e16 instanceof Error?_0x688e16:new Error(String(_0x688e16)));}},0x3e8);});}async[a0_0x4fe206(0xa2)](_0x55aa69,_0x925da1){const _0x313fad=a0_0x4fe206,_0xb349b0=this['getSessionFilePath'](_0x55aa69);try{const _0x2ec341=await fs_1['promises'][_0x313fad(0x9b)](_0xb349b0,'utf8'),_0x2fad92=JSON['parse'](_0x2ec341);if(_0x2fad92[_0x313fad(0x70)]!==_0x313fad(0x99))return console[_0x313fad(0x9a)](_0x313fad(0x71)+_0x55aa69+',\x20状态:\x20'+_0x2fad92[_0x313fad(0x70)]),![];return _0x2fad92[_0x313fad(0x70)]='resolved',_0x2fad92[_0x313fad(0x91)]=_0x925da1,_0x2fad92['resolvedAt']=new Date()[_0x313fad(0x88)](),await fs_1[_0x313fad(0x69)][_0x313fad(0x9e)](_0xb349b0,JSON['stringify'](_0x2fad92),_0x313fad(0x65)),console[_0x313fad(0x9a)]('MFA验证码已提交:\x20code\x20'+_0x925da1+_0x313fad(0x6d)+_0x55aa69),!![];}catch(_0x4e2060){return console[_0x313fad(0x9a)](_0x313fad(0x93)+_0x55aa69+_0x313fad(0x7d)+(_0x4e2060 instanceof Error?_0x4e2060['message']:String(_0x4e2060))),![];}}async['cancelMFARequest'](_0x121ed6,_0x459850='MFA验证已取消'){const _0x2db68c=a0_0x4fe206,_0x40b3b4=this[_0x2db68c(0x72)](_0x121ed6);try{const _0x5ed425=await fs_1[_0x2db68c(0x69)]['readFile'](_0x40b3b4,'utf8'),_0x54d502=JSON[_0x2db68c(0x81)](_0x5ed425);return _0x54d502[_0x2db68c(0x70)]=_0x2db68c(0x98),_0x54d502[_0x2db68c(0x83)]=_0x459850,_0x54d502[_0x2db68c(0x7b)]=new Date()[_0x2db68c(0x88)](),await fs_1[_0x2db68c(0x69)][_0x2db68c(0x9e)](_0x40b3b4,JSON['stringify'](_0x54d502),_0x2db68c(0x65)),console['log'](_0x2db68c(0x75)+_0x121ed6+_0x2db68c(0x94)+_0x459850),!![];}catch(_0x2998c1){return console[_0x2db68c(0x9a)](_0x2db68c(0x93)+_0x121ed6+_0x2db68c(0x7d)+(_0x2998c1 instanceof Error?_0x2998c1[_0x2db68c(0x82)]:String(_0x2998c1))),![];}}async[a0_0x4fe206(0x79)](_0x3a9bda){const _0x139219=a0_0x4fe206,_0x12412b=this[_0x139219(0x72)](_0x3a9bda);try{return await fs_1[_0x139219(0x69)][_0x139219(0x67)](_0x12412b),!![];}catch(_0x54c84a){return![];}}async[a0_0x4fe206(0x8b)](){const _0x57090c=a0_0x4fe206;try{await this[_0x57090c(0x9d)]();const _0xf9f7af=await fs_1[_0x57090c(0x69)][_0x57090c(0x97)](this[_0x57090c(0x86)]);return _0xf9f7af['filter'](_0x3948f2=>_0x3948f2['endsWith'](_0x57090c(0x8c)))[_0x57090c(0x92)](_0x2c9d50=>_0x2c9d50['replace'](_0x57090c(0x8c),''));}catch(_0x5983cd){return console[_0x57090c(0x83)](_0x57090c(0x87),_0x5983cd instanceof Error?_0x5983cd:String(_0x5983cd)),[];}}async[a0_0x4fe206(0x7c)](_0x4f86a7=this[a0_0x4fe206(0x73)]){const _0x54431e=a0_0x4fe206;try{await this['ensureStorageDir']();const _0x15c4e7=await fs_1['promises'][_0x54431e(0x97)](this[_0x54431e(0x86)]),_0x53ce6e=new Date();let _0x5b7927=0x0;for(const _0x5a8a69 of _0x15c4e7){if(!_0x5a8a69[_0x54431e(0x6b)]('.json'))continue;try{const _0x3f36d5=path_1[_0x54431e(0x68)][_0x54431e(0xa0)](this[_0x54431e(0x86)],_0x5a8a69),_0x4eefc9=await fs_1[_0x54431e(0x69)][_0x54431e(0x9b)](_0x3f36d5,_0x54431e(0x65)),_0x277f02=JSON['parse'](_0x4eefc9),_0x1fe5a7=new Date(_0x277f02[_0x54431e(0xa4)]);_0x53ce6e[_0x54431e(0x8d)]()-_0x1fe5a7[_0x54431e(0x8d)]()>_0x4f86a7&&(await fs_1[_0x54431e(0x69)][_0x54431e(0x80)](_0x3f36d5),_0x5b7927++);}catch(_0x385402){try{await fs_1[_0x54431e(0x69)][_0x54431e(0x80)](path_1[_0x54431e(0x68)][_0x54431e(0xa0)](this[_0x54431e(0x86)],_0x5a8a69)),_0x5b7927++;}catch(_0x155880){console[_0x54431e(0x83)](_0x54431e(0x7a)+_0x5a8a69,_0x155880 instanceof Error?_0x155880:String(_0x155880));}}}_0x5b7927>0x0&&console[_0x54431e(0x9a)]('清理了\x20'+_0x5b7927+_0x54431e(0x9c));}catch(_0x149993){console['error']('清理过期请求失败:',_0x149993 instanceof Error?_0x149993:String(_0x149993));}}async[a0_0x4fe206(0x76)](_0x4b19f9){const _0x1e0f37=a0_0x4fe206,_0x1380f4=this['getSessionFilePath'](_0x4b19f9);try{await fs_1[_0x1e0f37(0x69)][_0x1e0f37(0x80)](_0x1380f4);}catch(_0x1c9ddc){}}}exports['FileMFASessionStorage']=FileMFASessionStorage;function a0_0x9bde(){const _0x31ae1b=['7847175zfYuXC','path','storageDir','获取活跃会话失败:','toISOString','defineProperty','1245228fLqogC','getActiveSessions','.json','getTime','__importDefault','3301148ZWnpkt','442135ypzjCM','code','map','未找到MFA验证会话:\x20',',\x20原因:\x20','2965610QLKjYd','3477340PEwmWf','readdir','rejected','waiting','log','readFile','\x20个过期的MFA验证会话','ensureStorageDir','writeFile','resolved','join','12pJfzBe','submitMFACode','665672iuAKKQ','createdAt','utf8','mkdir','access','default','promises','FileMFASessionStorage','endsWith','__esModule',',\x20sessionId\x20','stringify','创建MFA存储目录失败:','status','MFA验证会话状态不正确:\x20','getSessionFilePath','DEFAULT_TIMEOUT','143pBPhHj','MFA验证已取消:\x20','cleanupRequest','153rfbvpk','3yBSZLM','hasSession','删除过期会话文件失败:\x20','rejectedAt','cleanupExpiredRequests',',\x20错误:\x20','waitForMFACode','now','unlink','parse','message','error'];a0_0x9bde=function(){return _0x31ae1b;};return a0_0x9bde();}
|