ts-watches 0.1.2 → 0.1.3
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 +1 -0
- package/dist/bin/cli.js +1 -1
- package/dist/src/cloud/garmin-connect.d.ts +12 -1
- package/dist/src/cloud/index.d.ts +2 -0
- package/dist/src/index.js +18 -18
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -172,6 +172,7 @@ const userId = await garmin.getUserId(tokens.accessToken) // the key push notifi
|
|
|
172
172
|
const legacy = new GarminConnectClient()
|
|
173
173
|
await legacy.login('email@example.com', 'password')
|
|
174
174
|
const activities = await legacy.getActivities(new Date('2024-01-01'))
|
|
175
|
+
const { bytes, filename } = await legacy.downloadOriginalActivity(activityId) // "Export Original" zip, in memory
|
|
175
176
|
|
|
176
177
|
// Strava
|
|
177
178
|
const strava = new StravaClient({
|
package/dist/bin/cli.js
CHANGED
|
@@ -28,7 +28,7 @@ Received ${i}, cleaning up...`),e)try{await e()}catch(s){console.error("Error du
|
|
|
28
28
|
✗ Command "${e}" not found.
|
|
29
29
|
`)),this.enableDidYouMean){let t=[];for(let s of this.commands){if(s.displayName)t.push(s.displayName);if(s.aliasNames)t.push(...s.aliasNames)}let i=K(e,t);if(i.length>0)console.log(S.yellow("Did you mean one of these?")),i.forEach((s)=>console.log(` ${S.dim("•")} ${this.name} ${s}`)),console.log("")}console.log(S.dim("Run"),`${this.name} --help`,S.dim("to see all available commands")),w.exit(1)}async parse(e=H,t={}){let{run:i=!0,exitOnError:s=!1}=t;if(s)try{return await this.parse(e,{run:i})}catch(r){throw this.handleUsageError(r),r}if(this.rawArgs=e,!this.name)this.name=e[1]?oe(e[1]):"cli";let n=!0,o=e.slice(2),c=o[0];if(c&&!c.startsWith("-")){for(let r of this.commands)if(r.isMatched(c)){let u=this.mri(o,r);n=!1;let h={...u,args:u.args.slice(1)};this.setParsedInfo(h,r,c),this.emit(`command:${c}`,r);break}}if(n){for(let r of this.commands)if(r.name===""){n=!1;let u=this.mri(o,r);this.setParsedInfo(u,r),this.emit("command:!",r);break}}if(n){let r=this.mri(e.slice(2));this.setParsedInfo(r)}if(this.options.verbose)this.isVerbose=!0;if(this.options.quiet)this.isQuiet=!0;if(this.options.debug)this.isDebug=!0;if(this.options.noInteraction)this.isNoInteraction=!0;if(this.options.env)this.environment=String(this.options.env);if(this.options.dryRun)this.isDryRun=!0;if(this.options.force)this.isForce=!0;if(this.options.noEmoji!==void 0)this.useEmoji=!this.options.noEmoji;if(this.options.theme)this.theme=String(this.options.theme);if(this.options.noCache!==void 0)this.isNoCache=Boolean(this.options.noCache);if(this.options.help&&this.showHelpOnExit)this.outputHelp(),i=!1,this.unsetMatchedCommand();if(this.options.version&&this.showVersionOnExit&&this.matchedCommandName==null)this.outputVersion(),i=!1,this.unsetMatchedCommand();let a={args:this.args,options:this.options};if(i)await this.runMatchedCommand();if(!this.matchedCommand&&this.args[0]){if(this.emit("command:*"),!(this.listenerCount("command:*")>0))this.showCommandNotFound(this.args[0])}return a}mri(e,t){let i=[...this.globalCommand.options,...t?t.options:[]],s=se(i),n=[],o=e.indexOf("--");if(o>-1)n=e.slice(o+1),e=e.slice(0,o);let c=ee(e,s),a={_:c._};for(let m of Object.keys(c))if(m!=="_")a[U(m)]=c[m];let r=a._,u={"--":n},h=t&&t.config.ignoreOptionDefaultValue?t.config.ignoreOptionDefaultValue:this.globalCommand.config.ignoreOptionDefaultValue,d=Object.create(null);for(let m of i){if(!h&&m.config.default!==void 0)for(let f of m.names)u[f]=m.config.default;if(Array.isArray(m.config.type)){if(d[m.name]===void 0)d[m.name]={shouldTransform:!0,transformFunction:m.config.type[0]}}}for(let m of Object.keys(a))if(m!=="_"){let f=m.split(".");ne(u,f,a[m]),re(u,d)}return{args:r,options:u}}async run(e=H){return this.parse(e,{run:!0,exitOnError:!0})}handleUsageError(e){if(!(!!e&&typeof e==="object"&&e.name==="ClappError"&&e.isUsageError!==!1))return;let s=e,n=s.message??"command-line error",o=this.name?`${this.name}: `:"",c=/--help/.test(n)?"":`
|
|
30
30
|
Run \`${this.name??"cli"} --help\` for usage.`;w.stderr.write(`${o}${n}${c}
|
|
31
|
-
`),w.exit(s.exitCode??2)}async runMatchedCommand(){let{args:e,options:t,matchedCommand:i}=this;if(!i||!i.commandAction)return;i.checkUnknownOptions(),i.checkOptionValue(),i.checkRequiredArgs();let s=[];i.args.forEach((a,r)=>{if(a.variadic)s.push(e.slice(r));else s.push(e[r])}),s.push(t);let n={command:i,args:s,options:t};for(let a of i.beforeHooks)await a(n);let o,c=async()=>{let a=i.commandAction.apply(this,s);if(a instanceof Promise)o=await a;else o=a;return o};if(i.middleware.length>0){let a=0,r=async()=>{if(a<i.middleware.length){let u=i.middleware[a++];await u({...n,next:r})}else await c()};await r()}else await c();for(let a of i.afterHooks)await a(n);return o}removeSignalHandlers(){if(!this.signalHandlersSet)return this;return w.removeAllListeners("SIGINT"),w.removeAllListeners("SIGTERM"),this.signalHandlersSet=!1,this}destroy(){this.removeSignalHandlers(),this.commands=[],this.rawArgs=[],this.args=[],this.options={},this.matchedCommand=void 0,this.matchedCommandName=void 0,this.removeAllListeners()}}class Y{cache;enabled;cleanupInterval=null;hits=0;misses=0;constructor(){this.cache=new Map,this.enabled=!0,this.startCleanupInterval()}startCleanupInterval(){if(this.cleanupInterval)return;this.cleanupInterval=setInterval(()=>{this.cleanup()},30000),this.cleanupInterval.unref()}stopCleanup(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isEnabled(){return this.enabled}get(e){if(!this.enabled){this.misses++;return}let t=this.cache.get(e);if(!t){this.misses++;return}if(Date.now()-t.timestamp>t.ttl){this.cache.delete(e),this.misses++;return}return this.hits++,t.value}set(e,t,i=5000){if(!this.enabled)return;this.cache.set(e,{value:t,timestamp:Date.now(),ttl:i})}has(e){if(!this.enabled)return!1;let t=this.cache.get(e);if(!t)return!1;if(Date.now()-t.timestamp>t.ttl)return this.cache.delete(e),!1;return!0}delete(e){this.cache.delete(e)}clear(){this.cache.clear()}disable(){this.enabled=!1,this.clear()}enable(){this.enabled=!0}stats(){return{size:this.cache.size,enabled:this.enabled,hits:this.hits,misses:this.misses}}resetStats(){this.hits=0,this.misses=0}keys(){return Array.from(this.cache.keys())}cleanup(){let e=Date.now();for(let[t,i]of this.cache.entries())if(e-i.timestamp>i.ttl)this.cache.delete(t)}destroy(){this.stopCleanup(),this.clear(),this.resetStats()}}var at=new Y;function fe(){if("FORCE_COLOR"in O.env)return O.env.FORCE_COLOR!=="0";if("NO_COLOR"in O.env||O.env.TERM==="dumb")return!1;if(O.platform==="win32")return!0;return z.isatty(1)&&z.isatty(2)}var J=fe();function g(e,t){if(!J)return(i)=>i;return(i)=>e+i+t}var pe=g("\x1B[0m","\x1B[0m"),ge=g("\x1B[31m","\x1B[39m"),$e=g("\x1B[32m","\x1B[39m"),ve=g("\x1B[33m","\x1B[39m"),we=g("\x1B[34m","\x1B[39m"),be=g("\x1B[35m","\x1B[39m"),ye=g("\x1B[36m","\x1B[39m"),xe=g("\x1B[37m","\x1B[39m"),Ce=g("\x1B[90m","\x1B[39m"),Se=g("\x1B[1m","\x1B[22m"),Oe=g("\x1B[3m","\x1B[23m"),Ie=g("\x1B[4m","\x1B[24m"),_e=g("\x1B[2m","\x1B[22m"),Ee=g("\x1B[7m","\x1B[27m"),Be=g("\x1B[8m","\x1B[28m"),ke=g("\x1B[9m","\x1B[29m"),Te=g("\x1B[41m","\x1B[49m"),Me=g("\x1B[42m","\x1B[49m"),Ae=g("\x1B[43m","\x1B[49m"),je=g("\x1B[44m","\x1B[49m"),Re=g("\x1B[45m","\x1B[49m"),Ve=g("\x1B[46m","\x1B[49m"),De=g("\x1B[47m","\x1B[49m"),Ne=J,Le={reset:pe,red:ge,green:$e,yellow:ve,blue:we,magenta:be,cyan:ye,white:xe,gray:Ce,bold:Se,italic:Oe,underline:Ie,dim:_e,inverse:Ee,hidden:Be,strikethrough:ke,bgRed:Te,bgGreen:Me,bgYellow:Ae,bgBlue:je,bgMagenta:Re,bgCyan:Ve,bgWhite:De,isColorSupported:Ne},Pe=Le,Fe=["up","down","left","right","space","enter","cancel"],mt={actions:new Set(Fe),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]]),messages:{cancel:"Canceled",error:"Something went wrong"}};var ft=We.platform.startsWith("win"),pt=Symbol("clapp:cancel");var He=ae();var p=(e,t)=>He?e:t,gt=p("◆","*"),$t=p("■","x"),vt=p("▲","x"),wt=p("◇","o"),bt=p("┌","T"),ze=p("│","|"),yt=p("└","—"),xt=p("●",">"),Ct=p("○"," "),St=p("◻","[•]"),Ot=p("◼","[+]"),It=p("◻","[ ]"),_t=p("▪","•"),Et=p("─","-"),Bt=p("╮","+"),kt=p("├","+"),Tt=p("╯","+"),Mt=p("●","•"),At=p("◆","*"),jt=p("▲","!"),Rt=p("■","x");var Vt={light:p("─","-"),heavy:p("━","="),block:p("█","#")};function Ge(){return`${Pe.gray(ze)} `}var Dt=Ge();var D="0.1.
|
|
31
|
+
`),w.exit(s.exitCode??2)}async runMatchedCommand(){let{args:e,options:t,matchedCommand:i}=this;if(!i||!i.commandAction)return;i.checkUnknownOptions(),i.checkOptionValue(),i.checkRequiredArgs();let s=[];i.args.forEach((a,r)=>{if(a.variadic)s.push(e.slice(r));else s.push(e[r])}),s.push(t);let n={command:i,args:s,options:t};for(let a of i.beforeHooks)await a(n);let o,c=async()=>{let a=i.commandAction.apply(this,s);if(a instanceof Promise)o=await a;else o=a;return o};if(i.middleware.length>0){let a=0,r=async()=>{if(a<i.middleware.length){let u=i.middleware[a++];await u({...n,next:r})}else await c()};await r()}else await c();for(let a of i.afterHooks)await a(n);return o}removeSignalHandlers(){if(!this.signalHandlersSet)return this;return w.removeAllListeners("SIGINT"),w.removeAllListeners("SIGTERM"),this.signalHandlersSet=!1,this}destroy(){this.removeSignalHandlers(),this.commands=[],this.rawArgs=[],this.args=[],this.options={},this.matchedCommand=void 0,this.matchedCommandName=void 0,this.removeAllListeners()}}class Y{cache;enabled;cleanupInterval=null;hits=0;misses=0;constructor(){this.cache=new Map,this.enabled=!0,this.startCleanupInterval()}startCleanupInterval(){if(this.cleanupInterval)return;this.cleanupInterval=setInterval(()=>{this.cleanup()},30000),this.cleanupInterval.unref()}stopCleanup(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}isEnabled(){return this.enabled}get(e){if(!this.enabled){this.misses++;return}let t=this.cache.get(e);if(!t){this.misses++;return}if(Date.now()-t.timestamp>t.ttl){this.cache.delete(e),this.misses++;return}return this.hits++,t.value}set(e,t,i=5000){if(!this.enabled)return;this.cache.set(e,{value:t,timestamp:Date.now(),ttl:i})}has(e){if(!this.enabled)return!1;let t=this.cache.get(e);if(!t)return!1;if(Date.now()-t.timestamp>t.ttl)return this.cache.delete(e),!1;return!0}delete(e){this.cache.delete(e)}clear(){this.cache.clear()}disable(){this.enabled=!1,this.clear()}enable(){this.enabled=!0}stats(){return{size:this.cache.size,enabled:this.enabled,hits:this.hits,misses:this.misses}}resetStats(){this.hits=0,this.misses=0}keys(){return Array.from(this.cache.keys())}cleanup(){let e=Date.now();for(let[t,i]of this.cache.entries())if(e-i.timestamp>i.ttl)this.cache.delete(t)}destroy(){this.stopCleanup(),this.clear(),this.resetStats()}}var at=new Y;function fe(){if("FORCE_COLOR"in O.env)return O.env.FORCE_COLOR!=="0";if("NO_COLOR"in O.env||O.env.TERM==="dumb")return!1;if(O.platform==="win32")return!0;return z.isatty(1)&&z.isatty(2)}var J=fe();function g(e,t){if(!J)return(i)=>i;return(i)=>e+i+t}var pe=g("\x1B[0m","\x1B[0m"),ge=g("\x1B[31m","\x1B[39m"),$e=g("\x1B[32m","\x1B[39m"),ve=g("\x1B[33m","\x1B[39m"),we=g("\x1B[34m","\x1B[39m"),be=g("\x1B[35m","\x1B[39m"),ye=g("\x1B[36m","\x1B[39m"),xe=g("\x1B[37m","\x1B[39m"),Ce=g("\x1B[90m","\x1B[39m"),Se=g("\x1B[1m","\x1B[22m"),Oe=g("\x1B[3m","\x1B[23m"),Ie=g("\x1B[4m","\x1B[24m"),_e=g("\x1B[2m","\x1B[22m"),Ee=g("\x1B[7m","\x1B[27m"),Be=g("\x1B[8m","\x1B[28m"),ke=g("\x1B[9m","\x1B[29m"),Te=g("\x1B[41m","\x1B[49m"),Me=g("\x1B[42m","\x1B[49m"),Ae=g("\x1B[43m","\x1B[49m"),je=g("\x1B[44m","\x1B[49m"),Re=g("\x1B[45m","\x1B[49m"),Ve=g("\x1B[46m","\x1B[49m"),De=g("\x1B[47m","\x1B[49m"),Ne=J,Le={reset:pe,red:ge,green:$e,yellow:ve,blue:we,magenta:be,cyan:ye,white:xe,gray:Ce,bold:Se,italic:Oe,underline:Ie,dim:_e,inverse:Ee,hidden:Be,strikethrough:ke,bgRed:Te,bgGreen:Me,bgYellow:Ae,bgBlue:je,bgMagenta:Re,bgCyan:Ve,bgWhite:De,isColorSupported:Ne},Pe=Le,Fe=["up","down","left","right","space","enter","cancel"],mt={actions:new Set(Fe),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["\x03","cancel"],["escape","cancel"]]),messages:{cancel:"Canceled",error:"Something went wrong"}};var ft=We.platform.startsWith("win"),pt=Symbol("clapp:cancel");var He=ae();var p=(e,t)=>He?e:t,gt=p("◆","*"),$t=p("■","x"),vt=p("▲","x"),wt=p("◇","o"),bt=p("┌","T"),ze=p("│","|"),yt=p("└","—"),xt=p("●",">"),Ct=p("○"," "),St=p("◻","[•]"),Ot=p("◼","[+]"),It=p("◻","[ ]"),_t=p("▪","•"),Et=p("─","-"),Bt=p("╮","+"),kt=p("├","+"),Tt=p("╯","+"),Mt=p("●","•"),At=p("◆","*"),jt=p("▲","!"),Rt=p("■","x");var Vt={light:p("─","-"),heavy:p("━","="),block:p("█","#")};function Ge(){return`${Pe.gray(ze)} `}var Dt=Ge();var D="0.1.3";var y=new V("watch");y.command("detect","Detect connected watch devices").option("--verbose","Enable verbose output").action(async(e)=>{let t=l();if(e.verbose)console.log(`Searching for connected watch devices...
|
|
32
32
|
`);let i=await t.detectDevices();if(i.length===0){console.log("No watch devices found."),console.log(`
|
|
33
33
|
Make sure your watch is:`),console.log(" 1. Connected via USB, or"),console.log(" 2. Synced via Garmin Express (data will be read from cache)");return}console.log(`Found ${i.length} device(s):
|
|
34
34
|
`);for(let s of i){if(console.log(` ${s.name}`),console.log(` Type: ${s.type}`),s.isGarminExpress)console.log(" Source: Garmin Express cache");else console.log(` Path: ${s.path}`);if(s.model)console.log(` Model: ${s.model}`);if(s.serial)console.log(` Serial: ${s.serial}`);if(s.firmware)console.log(` Firmware: ${s.firmware}`);console.log()}});y.command("download","Download data from connected watch").option("-o, --output <dir>","Output directory",{default:"./watch-data"}).option("--since <date>","Only download data after this date (YYYY-MM-DD)").option("--until <date>","Only download data before this date (YYYY-MM-DD)").option("--activities","Download activity data only").option("--monitoring","Download monitoring data only").option("--no-raw","Do not copy raw FIT files").option("--verbose","Enable verbose output").action(async(e)=>{let t=l();console.log("Detecting devices...");let i=await t.detectDevices();if(i.length===0)console.error("No watch devices found."),console.error(`
|
|
@@ -12,6 +12,11 @@ export declare interface GarminConnectConfig {
|
|
|
12
12
|
username: string
|
|
13
13
|
password: string
|
|
14
14
|
}
|
|
15
|
+
/** A downloaded activity file, held in memory. */
|
|
16
|
+
export declare interface OriginalActivityFile {
|
|
17
|
+
bytes: Uint8Array
|
|
18
|
+
filename: string
|
|
19
|
+
}
|
|
15
20
|
export declare interface GarminActivitySummary {
|
|
16
21
|
activityId: number
|
|
17
22
|
activityName: string
|
|
@@ -64,6 +69,11 @@ export declare interface ActivityDetailSample {
|
|
|
64
69
|
power: number | null
|
|
65
70
|
speed: number | null
|
|
66
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* What Connect can export an activity as. `zip` is "Export Original", the
|
|
74
|
+
* device's own recording; the rest are Garmin's conversions.
|
|
75
|
+
*/
|
|
76
|
+
export type GarminExportFormat = 'zip' | 'tcx' | 'gpx' | 'kml';
|
|
67
77
|
export declare class GarminConnectClient {
|
|
68
78
|
constructor(config?: GarminConnectConfig);
|
|
69
79
|
login(username?: string, password?: string): Promise<void>;
|
|
@@ -71,7 +81,8 @@ export declare class GarminConnectClient {
|
|
|
71
81
|
getActivities(start?: number, limit?: number): Promise<GarminActivitySummary[]>;
|
|
72
82
|
getActivity(activityId: number): Promise<Activity>;
|
|
73
83
|
getActivityDetails(activityId: number, maxSamples?: number): Promise<ActivityDetailSample[]>;
|
|
74
|
-
|
|
84
|
+
downloadOriginalActivity(activityId: number, format?: GarminExportFormat): Promise<OriginalActivityFile>;
|
|
85
|
+
downloadActivityFit(activityId: number, outputDir: string): Promise<string>;
|
|
75
86
|
getDailySummary(date: Date): Promise<DailySummary>;
|
|
76
87
|
getHeartRateData(date: Date): Promise<DailyHeartRate | undefined>;
|
|
77
88
|
getSleepData(date: Date): Promise<SleepData | undefined>;
|
|
@@ -8,6 +8,8 @@ export {
|
|
|
8
8
|
type DailySummary,
|
|
9
9
|
type GarminActivitySummary as GarminConnectActivitySummary,
|
|
10
10
|
type GarminConnectConfig,
|
|
11
|
+
type GarminExportFormat,
|
|
12
|
+
type OriginalActivityFile,
|
|
11
13
|
} from './garmin-connect';
|
|
12
14
|
export * from './strava';
|
|
13
15
|
export * from './trainingpeaks';
|