@dlwiest/ts-tonal-client 0.0.1 → 0.1.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.
Files changed (48) hide show
  1. package/README.md +413 -37
  2. package/dist/examples/create-workout.d.ts +1 -0
  3. package/dist/examples/debug-daily-lifts.d.ts +1 -0
  4. package/dist/examples/delete-workout.d.ts +1 -0
  5. package/dist/examples/edit-workout.d.ts +1 -0
  6. package/dist/examples/estimate-workout.d.ts +1 -0
  7. package/dist/examples/get-achievement-stats.d.ts +2 -0
  8. package/dist/examples/get-achievements.d.ts +2 -0
  9. package/dist/examples/get-activity-summaries.d.ts +2 -0
  10. package/dist/examples/get-current-streak.d.ts +1 -0
  11. package/dist/examples/get-daily-lifts.d.ts +1 -0
  12. package/dist/examples/get-daily-metrics.d.ts +1 -0
  13. package/dist/examples/get-goal-metrics.d.ts +1 -0
  14. package/dist/examples/get-goals.d.ts +1 -0
  15. package/dist/examples/get-home-calendar.d.ts +2 -0
  16. package/dist/examples/get-metric-scores.d.ts +1 -0
  17. package/dist/examples/get-movements.d.ts +1 -0
  18. package/dist/examples/get-muscle-readiness.d.ts +1 -0
  19. package/dist/examples/get-program-by-id.d.ts +1 -0
  20. package/dist/examples/get-target-scores.d.ts +1 -0
  21. package/dist/examples/get-training-effect-goals.d.ts +1 -0
  22. package/dist/examples/get-training-types.d.ts +1 -0
  23. package/dist/examples/get-user-info.d.ts +1 -0
  24. package/dist/examples/get-user-settings.d.ts +1 -0
  25. package/dist/examples/get-user-statistics.d.ts +2 -0
  26. package/dist/examples/get-user-workouts.d.ts +1 -0
  27. package/dist/examples/get-workout-by-id.d.ts +1 -0
  28. package/dist/examples/get-workout-by-share-url.d.ts +1 -0
  29. package/dist/examples/raw-daily-lifts-test.d.ts +1 -0
  30. package/dist/index.d.ts +573 -29
  31. package/dist/index.esm.js +510 -118
  32. package/dist/index.js +514 -118
  33. package/dist/src/auth/auth-manager.d.ts +15 -0
  34. package/dist/src/client.d.ts +39 -0
  35. package/dist/src/http/http-client.d.ts +12 -0
  36. package/dist/src/index.d.ts +4 -0
  37. package/dist/src/services/movement-service.d.ts +7 -0
  38. package/dist/src/services/user-service.d.ts +51 -0
  39. package/dist/src/services/workout-service.d.ts +14 -0
  40. package/dist/src/types/auth.d.ts +18 -0
  41. package/dist/src/types/common.d.ts +1 -0
  42. package/dist/src/types/index.d.ts +6 -0
  43. package/dist/src/types/movements.d.ts +30 -0
  44. package/dist/src/types/programs.d.ts +46 -0
  45. package/dist/src/types/users.d.ts +418 -0
  46. package/dist/src/types/workouts.d.ts +120 -0
  47. package/dist/src/types.d.ts +125 -0
  48. package/package.json +54 -4
package/README.md CHANGED
@@ -1,76 +1,452 @@
1
- # Tonal Client
1
+ # TypeScript Tonal Client
2
2
 
3
- This repository contains a TypeScript client for accessing Tonal data. It is designed to interact with Tonal's systems to retrieve various types of workout-related data.
3
+ [![npm version](https://badge.fury.io/js/@dlwiest%2Fts-tonal-client.svg)](https://badge.fury.io/js/@dlwiest%2Fts-tonal-client)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@dlwiest/ts-tonal-client.svg)](https://www.npmjs.com/package/@dlwiest/ts-tonal-client)
4
5
 
6
+ A comprehensive TypeScript client for accessing Tonal's API. This library provides a robust interface to retrieve workout data, user information, movements, and more from your Tonal account.
5
7
 
6
8
  ## Features
7
9
 
8
- - Retrieve detailed workout data by ID.
9
- - Access shared workouts through share URLs.
10
- - Fetch movements and other related workout data.
10
+ - 🏋️ **Complete Workout Management** - Get, create, estimate, and share workouts including daily lifts
11
+ - 👤 **User Management** - Access user info, goals, and preferences
12
+ - 💪 **Movement Database** - Browse all available Tonal movements
13
+ - 🎯 **Muscle Readiness Tracking** - Monitor recovery status for all muscle groups
14
+ - 📋 **Program Details** - Get comprehensive information about training programs
15
+ - 🎯 **Target Score Tracking** - Get weekly fitness targets and progress ranges for all metrics
16
+ - 📈 **Metric Score Analysis** - Track actual performance vs targets with comprehensive analytics
17
+ - 🛡️ **Enterprise-Grade Reliability** - Built-in error handling, retries, and timeouts
18
+ - 📝 **Full TypeScript Support** - Comprehensive types for all API responses
19
+ - 🔄 **Smart Token Management** - Automatic authentication and token refresh
11
20
 
12
21
  ## Installation
13
22
 
14
- To use this client, clone the repository and install the necessary dependencies:
23
+ ### Option 1: Install from npm (Recommended)
24
+
25
+ ```bash
26
+ npm install @dlwiest/ts-tonal-client
27
+ ```
28
+
29
+ ### Option 2: Clone and build from source
15
30
 
16
31
  ```bash
17
32
  git clone https://github.com/dlwiest/ts-tonal-client.git
18
33
  cd ts-tonal-client
19
34
  npm install
35
+ npm run build
20
36
  ```
21
37
 
22
- In order to test with the example scripts in `/src/examples` you will need to create a `.env` file based on the formatting described in `.env.sample`.
23
- Note that your Tonal username is most likely an email address.
38
+ ## Quick Start
39
+
40
+ Basic usage:
24
41
 
25
- ## Usage
42
+ ```typescript
43
+ import TonalClient from '@dlwiest/ts-tonal-client'
26
44
 
27
- The client can be used in scripts or applications that require data from Tonal. Here are some examples of how to use the client:
45
+ const client = await TonalClient.create({
46
+ username: 'your_email@example.com',
47
+ password: 'your_password',
48
+ })
28
49
 
29
- ### Get Movements
50
+ // Get your workouts
51
+ const workouts = await client.getUserWorkouts()
52
+ console.log(`You have ${workouts.length} workouts`)
53
+ ```
30
54
 
31
- ```typescript
32
- // Example: Fetching movements
33
- import { TonalClient } from './src/client';
55
+ ## Examples
34
56
 
35
- async function fetchMovements() {
36
- const client = await TonalClient.create({ username: 'your_username', password: 'your_password' });
37
- const movements = await client.getMovements();
38
- console.log(movements);
39
- }
57
+ To run the example scripts, first create a `.env` file:
40
58
 
41
- fetchMovements();
59
+ ```bash
60
+ cp .env.sample .env
61
+ # Edit .env with your Tonal username (email) and password
42
62
  ```
43
63
 
44
- ### Get Workout by ID
64
+ Then try the examples:
65
+
66
+ ```bash
67
+ # See all your workouts
68
+ npm run example:user-workouts
69
+
70
+ # Get your user info
71
+ npm run example:user
72
+
73
+ # Browse available movements
74
+ npm run example:movements
75
+
76
+ # See fitness goals
77
+ npm run example:goals
78
+
79
+ # Estimate workout duration
80
+ npm run example:estimate
81
+
82
+ # Create a new workout
83
+ npm run example:create-workout
84
+
85
+ # Edit an existing workout
86
+ npm run example:edit-workout
87
+
88
+ # Delete a workout
89
+ npm run example:delete-workout
90
+
91
+ # Get daily lifts
92
+ npm run example:daily-lifts
93
+
94
+ # Get training effect goals
95
+ npm run example:training-effect-goals
96
+
97
+ # Get training types
98
+ npm run example:training-types
99
+
100
+ # Get user settings
101
+ npm run example:user-settings
102
+
103
+ # Get daily metrics
104
+ npm run example:daily-metrics
105
+
106
+ # Get current workout streak
107
+ npm run example:current-streak
108
+
109
+ # Get workout activity history
110
+ npm run example:activity-summaries
111
+
112
+ # Get lifetime user statistics
113
+ npm run example:user-statistics
114
+
115
+ # Get achievement stats and milestones
116
+ npm run example:achievement-stats
117
+
118
+ # Get earned achievement history
119
+ npm run example:achievements
120
+
121
+ # Get home calendar and workout recommendations
122
+ npm run example:home-calendar
123
+
124
+ # Get muscle readiness and recovery status
125
+ npm run example:muscle-readiness
126
+
127
+ # Get detailed program information by ID
128
+ npm run example:program-by-id
129
+
130
+ # Get weekly fitness targets and progress tracking
131
+ npm run example:target-scores
132
+
133
+ # Get actual performance scores vs targets with comprehensive analytics
134
+ npm run example:metric-scores
135
+ ```
136
+
137
+ ## API Reference
138
+
139
+ ### Workouts
45
140
 
46
141
  ```typescript
47
- // Example: Fetching a workout by ID
48
- import { TonalClient } from './src/client';
142
+ // Get your workouts (with pagination)
143
+ const workouts = await client.getUserWorkouts(0, 10)
144
+ console.log(`You have ${workouts.length} workouts`)
49
145
 
50
- async function fetchWorkoutById(workoutId: string) {
51
- const client = await TonalClient.create({ username: 'your_username', password: 'your_password' });
52
- const workout = await client.getWorkoutById(workoutId);
53
- console.log(workout);
54
- }
146
+ // Get daily lifts (auto-detects timezone)
147
+ const dailyLifts = await client.getDailyLifts()
148
+ console.log(`You have ${dailyLifts.length} daily lifts`)
149
+
150
+ // Get daily lifts with specific timezone
151
+ const dailyLiftsEST = await client.getDailyLifts('America/New_York')
55
152
 
56
- fetchWorkoutById('workout_id_here');
153
+ // Get specific workout details
154
+ const workout = await client.getWorkoutById('workout-uuid')
155
+
156
+ // Get shared workout
157
+ const sharedWorkout = await client.getWorkoutByShareUrl('https://share.tonal.com/workout/...')
158
+
159
+ // Estimate workout duration
160
+ const sets = [/* workout sets */]
161
+ const estimate = await client.estimateWorkoutDuration(sets)
162
+ console.log(`Estimated duration: ${estimate.duration} seconds`)
163
+
164
+ // Create a new workout
165
+ const newWorkout = await client.createWorkout({
166
+ title: 'My Custom Workout',
167
+ sets: sets,
168
+ createdSource: 'WorkoutBuilder',
169
+ description: 'A great workout!'
170
+ })
171
+
172
+ // Edit an existing workout
173
+ const updatedWorkout = await client.updateWorkout({
174
+ id: 'workout-uuid',
175
+ title: 'My Updated Workout Title',
176
+ description: 'Updated description with changes',
177
+ coachId: '00000000-0000-0000-0000-000000000000',
178
+ sets: modifiedSets,
179
+ assetId: 'asset-uuid',
180
+ createdSource: 'WorkoutBuilder'
181
+ })
182
+
183
+ // Delete a workout
184
+ await client.deleteWorkout('workout-uuid')
57
185
  ```
58
186
 
59
- ### Get Workout by Share URL
187
+ ### User Information
60
188
 
61
189
  ```typescript
62
- // Example: Fetching a workout by its share URL
63
- import { TonalClient } from './src/client';
190
+ // Get your profile information
191
+ const userInfo = await client.getUserInfo()
192
+ console.log(`Welcome ${userInfo.firstName}!`)
193
+ console.log(`Level: ${userInfo.level}`)
194
+ console.log(`Location: ${userInfo.location}`)
195
+
196
+ // Get available fitness goals
197
+ const goals = await client.getGoals()
198
+ goals.forEach(goal => {
199
+ console.log(`${goal.name}: ${goal.description}`)
200
+ })
201
+
202
+ // Get training effect goals with relationships
203
+ const trainingGoals = await client.getTrainingEffectGoals()
204
+ console.log(`${trainingGoals.goals.length} training goals available`)
205
+ trainingGoals.relations.forEach(relation => {
206
+ console.log(`Primary goal relationships found`)
207
+ })
208
+
209
+ // Get all training types
210
+ const trainingTypes = await client.getTrainingTypes()
211
+ console.log(`${trainingTypes.length} training types available`)
212
+ trainingTypes.forEach(type => {
213
+ console.log(`${type.name}: ${type.description}`)
214
+ })
215
+
216
+ // Get goal metrics
217
+ const goalMetrics = await client.getGoalMetrics()
218
+ console.log(`${goalMetrics.length} goal metrics available`)
219
+ goalMetrics.forEach(metric => {
220
+ console.log(`${metric.name}: ${metric.description}`)
221
+ })
222
+
223
+ // Get comprehensive user settings
224
+ const userSettings = await client.getUserSettings()
225
+ console.log(`Audio settings: ${userSettings.overallVolume * 100}% volume`)
226
+ console.log(`Preferred music service: ${userSettings.preferredMusicService}`)
227
+ console.log(`Time zone: ${userSettings.timeZone}`)
228
+ console.log(`Total settings tracked: ${Object.keys(userSettings).length}`)
64
229
 
65
- async function fetchWorkoutByShareUrl(shareUrl: string) {
66
- const client = await TonalClient.create({ username: 'your_username', password: 'your_password' });
67
- const workout = await client.getWorkoutByShareUrl(shareUrl);
68
- console.log(workout);
230
+ // Get daily fitness metrics (analyzes 60 days, shows recent 10 workouts)
231
+ const dailyMetrics = await client.getDailyMetrics(60)
232
+ const activeDays = dailyMetrics.filter(day => day.totalWorkouts > 0)
233
+ console.log(`Workout frequency over 60 days: ${(activeDays.length / dailyMetrics.length * 100).toFixed(1)}%`)
234
+ console.log(`Total volume (all workouts): ${activeDays.reduce((sum, day) => sum + day.totalVolume, 0).toLocaleString()} lbs`)
235
+ console.log(`Average workout duration: ${Math.round(activeDays.reduce((sum, day) => sum + day.totalDuration, 0) / activeDays.length / 60)} minutes`)
236
+
237
+ // Get current workout streak
238
+ const streak = await client.getCurrentStreak()
239
+ console.log(`Current streak: ${streak.currentStreak} workouts`)
240
+ console.log(`Personal best: ${streak.maxStreak} workouts`)
241
+ console.log(`Progress to personal best: ${Math.round((streak.currentStreak / streak.maxStreak) * 100)}%`)
242
+
243
+ // Get comprehensive workout activity history
244
+ const activities = await client.getActivitySummaries()
245
+ console.log(`Total workouts completed: ${activities.length}`)
246
+ const totalVolume = activities.reduce((sum, activity) => sum + activity.totalVolume, 0)
247
+ console.log(`Total volume lifted: ${totalVolume.toLocaleString()} lbs`)
248
+ const guidedWorkouts = activities.filter(a => a.isGuidedWorkout).length
249
+ console.log(`Guided vs Free Lift: ${guidedWorkouts}/${activities.length - guidedWorkouts}`)
250
+
251
+ // Get lifetime statistics and achievements
252
+ const stats = await client.getUserStatistics()
253
+ console.log(`Total volume: ${stats.volume.total.toLocaleString()} lbs over ${stats.workouts.total} workouts`)
254
+ console.log(`Average per workout: ${stats.volume.avgVolumePerWorkout.toLocaleString()} lbs`)
255
+ console.log(`Total workout time: ${Math.round(stats.workouts.totalDuration / 3600)} hours`)
256
+ console.log(`Movement diversity: ${stats.movements.total} unique movements performed`)
257
+
258
+ // Get achievement progress and upcoming milestones
259
+ const achievementStats = await client.getAchievementStats()
260
+ console.log(`Achievements earned: ${achievementStats.totalAchievements}`)
261
+ console.log(`Upcoming milestones: ${achievementStats.nextMilestones.length}`)
262
+ achievementStats.nextMilestones.forEach(milestone => {
263
+ console.log(`Next goal: ${milestone.name} (${milestone.value.toLocaleString()})`)
264
+ })
265
+
266
+ // Get complete earned achievement history
267
+ const earnedAchievements = await client.getAchievements()
268
+ console.log(`Total achievements earned: ${earnedAchievements.length}`)
269
+ const recentAchievement = earnedAchievements[0]
270
+ console.log(`Most recent: ${recentAchievement.name} (${new Date(recentAchievement.createdAt).toLocaleDateString()})`)
271
+ const categories = [...new Set(earnedAchievements.map(a => a.achievement.achievementCategory.name))]
272
+ console.log(`Achievement categories: ${categories.join(', ')}`)
273
+
274
+ // Get home calendar with workout history and recommendations
275
+ const homeCalendar = await client.getHomeCalendar()
276
+ const completedWorkouts = homeCalendar.dailySchedules.filter(day =>
277
+ day.tiles.some(tile => tile.completed)
278
+ ).length
279
+ const recommendationCategories = [...new Set(
280
+ homeCalendar.dailySchedules.map(day => day.recommendationType).filter(Boolean)
281
+ )]
282
+ console.log(`Completed workout days: ${completedWorkouts}`)
283
+ console.log(`Recommendation categories: ${recommendationCategories.join(', ')}`)
284
+
285
+ // Get muscle readiness for all muscle groups
286
+ const readiness = await client.getMuscleReadiness()
287
+ console.log(`Muscle Readiness Status:`)
288
+ console.log(` Chest: ${readiness.Chest}%`)
289
+ console.log(` Shoulders: ${readiness.Shoulders}%`)
290
+ console.log(` Back: ${readiness.Back}%`)
291
+ console.log(` Triceps: ${readiness.Triceps}%`)
292
+ console.log(` Biceps: ${readiness.Biceps}%`)
293
+ console.log(` Abs: ${readiness.Abs}%`)
294
+ console.log(` Obliques: ${readiness.Obliques}%`)
295
+ console.log(` Quads: ${readiness.Quads}%`)
296
+ console.log(` Glutes: ${readiness.Glutes}%`)
297
+ console.log(` Hamstrings: ${readiness.Hamstrings}%`)
298
+ console.log(` Calves: ${readiness.Calves}%`)
299
+
300
+ // Calculate average readiness
301
+ const allMuscles = Object.values(readiness)
302
+ const averageReadiness = Math.round(allMuscles.reduce((sum, val) => sum + val, 0) / allMuscles.length)
303
+ console.log(`Average readiness: ${averageReadiness}%`)
304
+
305
+ // Find muscles that need recovery (< 60%)
306
+ const needsRecovery = Object.entries(readiness)
307
+ .filter(([_, percentage]) => percentage < 60)
308
+ .map(([muscle]) => muscle)
309
+ if (needsRecovery.length > 0) {
310
+ console.log(`Muscles needing recovery: ${needsRecovery.join(', ')}`)
69
311
  }
70
312
 
71
- fetchWorkoutByShareUrl('https://link.tonal.com/custom-workout/your_workout_id');
313
+ // Get detailed program information
314
+ const programId = 'f243be64-76f2-4073-8ce7-8adb37657e9f' // Example: House of Volume
315
+ const program = await client.getProgramById(programId)
316
+ console.log(`Program: ${program.name}`)
317
+ console.log(`Level: ${program.level}`)
318
+ console.log(`Duration: ${program.weeks} weeks`)
319
+ console.log(`Workouts per week: ${program.workoutsPerWeek}`)
320
+ console.log(`Total workouts: ${program.workouts.length}`)
321
+ console.log(`Description: ${program.description}`)
322
+
323
+ // Analyze program structure
324
+ const targetAreas = program.workouts.map(w => w.targetArea)
325
+ const targetAreaCounts = targetAreas.reduce((acc, area) => {
326
+ acc[area] = (acc[area] || 0) + 1
327
+ return acc
328
+ }, {} as Record<string, number>)
329
+ console.log(`Target area distribution:`, targetAreaCounts)
330
+
331
+ // Show weekly schedule
332
+ const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
333
+ const schedule = program.cadence.map((isWorkout, i) =>
334
+ isWorkout ? `${days[i]}: Workout` : `${days[i]}: Rest`
335
+ )
336
+ console.log(`Weekly schedule: ${schedule.join(', ')}`)
337
+
338
+ // Get weekly fitness targets for all metrics
339
+ const targetScores = await client.getTargetScores()
340
+ console.log('Weekly Fitness Targets:')
341
+
342
+ Object.entries(targetScores).forEach(([metricId, weeklyTargets]) => {
343
+ // Get the most recent week target
344
+ const currentTarget = weeklyTargets.sort((a, b) => b.weekNumber - a.weekNumber)[0]
345
+ const year = Math.floor(currentTarget.weekNumber / 100)
346
+ const week = currentTarget.weekNumber % 100
347
+
348
+ console.log(`Metric ${metricId}:`)
349
+ console.log(` Target: ${currentTarget.target}`)
350
+ console.log(` Range: ${currentTarget.lowRange} - ${currentTarget.highRange}`)
351
+ console.log(` Week: ${week}/${year}`)
352
+ })
353
+
354
+ // Analyze target trends
355
+ const volumeTargets = targetScores['2a2f499e-ae13-45d1-b501-aa1d25ff6a4a'] // Volume metric
356
+ if (volumeTargets && volumeTargets.length >= 2) {
357
+ const sorted = volumeTargets.sort((a, b) => a.weekNumber - b.weekNumber)
358
+ const firstTarget = sorted[0].target
359
+ const lastTarget = sorted[sorted.length - 1].target
360
+ const change = Math.round(((lastTarget - firstTarget) / firstTarget) * 100)
361
+ console.log(`Volume trend: ${change > 0 ? '+' : ''}${change}% over ${sorted.length} weeks`)
362
+ }
363
+
364
+ // Get actual performance scores vs targets with comprehensive analytics
365
+ const metricScores = await client.getMetricScores()
366
+ // Optional: get scores starting from a specific week
367
+ // const metricScores = await client.getMetricScores(202440) // Start from week 40 of 2024
368
+
369
+ console.log('Performance vs Targets Analysis:')
370
+
371
+ Object.entries(metricScores).forEach(([metricId, weeklyScores]) => {
372
+ // Get the most recent week score
373
+ const currentScore = weeklyScores.sort((a, b) => b.weekNumber - a.weekNumber)[0]
374
+ const year = Math.floor(currentScore.weekNumber / 100)
375
+ const week = currentScore.weekNumber % 100
376
+
377
+ console.log(`Metric ${metricId}:`)
378
+ console.log(` Actual Score: ${currentScore.score}`)
379
+ console.log(` Week: ${week}/${year}`)
380
+ })
381
+
382
+ // Compare against targets to see goal achievement
383
+ const volumeScores = metricScores['2a2f499e-ae13-45d1-b501-aa1d25ff6a4a'] // Volume metric
384
+ const volumeTargets = targetScores['2a2f499e-ae13-45d1-b501-aa1d25ff6a4a']
385
+ if (volumeScores && volumeTargets) {
386
+ const latestScore = volumeScores.sort((a, b) => b.weekNumber - a.weekNumber)[0]
387
+ const matchingTarget = volumeTargets.find(t => t.weekNumber === latestScore.weekNumber)
388
+
389
+ if (matchingTarget) {
390
+ const achievementPercent = Math.round((latestScore.score / matchingTarget.target) * 100)
391
+ const inRange = latestScore.score >= matchingTarget.lowRange && latestScore.score <= matchingTarget.highRange
392
+ console.log(`Volume Achievement: ${achievementPercent}% of target (${inRange ? 'In Range' : 'Out of Range'})`)
393
+ }
394
+ }
395
+
396
+ // Calculate performance trends
397
+ if (volumeScores && volumeScores.length >= 2) {
398
+ const sorted = volumeScores.sort((a, b) => a.weekNumber - b.weekNumber)
399
+ const firstScore = sorted[0].score
400
+ const lastScore = sorted[sorted.length - 1].score
401
+ const change = Math.round(((lastScore - firstScore) / firstScore) * 100)
402
+ console.log(`Volume performance trend: ${change > 0 ? '+' : ''}${change}% over ${sorted.length} weeks`)
403
+ }
72
404
  ```
73
405
 
406
+ ### Movements
407
+
408
+ ```typescript
409
+ // Get all available movements
410
+ const movements = await client.getMovements()
411
+ console.log(`${movements.length} movements available`)
412
+
413
+ // Filter by muscle group
414
+ const chestMovements = movements.filter(m =>
415
+ m.muscleGroups.includes('Chest')
416
+ )
417
+ ```
418
+
419
+ ## Available Scripts
420
+
421
+ - `npm run build` - Build the TypeScript client
422
+ - `npm run typecheck` - Run TypeScript type checking
423
+ - `npm run example:movements` - List all movements
424
+ - `npm run example:user` - Show user information
425
+ - `npm run example:goals` - Show available goals
426
+ - `npm run example:user-workouts` - List your workouts
427
+ - `npm run example:workout:id <id>` - Get specific workout
428
+ - `npm run example:workout:share <url>` - Get shared workout
429
+ - `npm run example:estimate` - Estimate workout duration
430
+ - `npm run example:create-workout` - Create a new workout
431
+ - `npm run example:edit-workout` - Create and edit a workout
432
+ - `npm run example:delete-workout` - Create and delete a workout
433
+ - `npm run example:daily-lifts` - Get daily lifts with auto-detected timezone
434
+ - `npm run example:training-effect-goals` - Get training effect goals and relationships
435
+ - `npm run example:training-types` - Get all available training types
436
+ - `npm run example:goal-metrics` - Get goal metrics and relationships
437
+ - `npm run example:user-settings` - Get comprehensive user settings and preferences
438
+ - `npm run example:daily-metrics` - Get daily fitness metrics with workout analytics
439
+ - `npm run example:current-streak` - Get current workout streak and personal best
440
+ - `npm run example:activity-summaries` - Get comprehensive workout activity history and analytics
441
+ - `npm run example:user-statistics` - Get lifetime user statistics and achievement milestones
442
+ - `npm run example:achievement-stats` - Get achievement progress and upcoming milestone targets
443
+ - `npm run example:achievements` - Get complete earned achievement history with timeline analytics
444
+ - `npm run example:home-calendar` - Get home calendar with workout history and personalized recommendations
445
+ - `npm run example:muscle-readiness` - Get muscle readiness percentages and recovery recommendations
446
+ - `npm run example:program-by-id` - Get comprehensive program details including all workouts and structure
447
+ - `npm run example:target-scores` - Get weekly fitness targets with ranges and trend analysis for all metrics
448
+ - `npm run example:metric-scores` - Get actual performance scores vs targets with comprehensive goal achievement analytics
449
+
74
450
  ## Contributing
75
451
 
76
452
  Contributions to this project are welcome, especially in the areas of error handling, expanding functionality, and improving the robustness of the client.
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env tsx
2
+ import 'dotenv/config';
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env tsx
2
+ import 'dotenv/config';
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env tsx
2
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env tsx
2
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env tsx
2
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1 @@
1
+ import 'dotenv/config';