@dlwiest/ts-tonal-client 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Derrick Wiest
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # Tonal Client
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.
4
+
5
+
6
+ ## Features
7
+
8
+ - Retrieve detailed workout data by ID.
9
+ - Access shared workouts through share URLs.
10
+ - Fetch movements and other related workout data.
11
+
12
+ ## Installation
13
+
14
+ To use this client, clone the repository and install the necessary dependencies:
15
+
16
+ ```bash
17
+ git clone https://github.com/dlwiest/ts-tonal-client.git
18
+ cd ts-tonal-client
19
+ npm install
20
+ ```
21
+
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.
24
+
25
+ ## Usage
26
+
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:
28
+
29
+ ### Get Movements
30
+
31
+ ```typescript
32
+ // Example: Fetching movements
33
+ import { TonalClient } from './src/client';
34
+
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
+ }
40
+
41
+ fetchMovements();
42
+ ```
43
+
44
+ ### Get Workout by ID
45
+
46
+ ```typescript
47
+ // Example: Fetching a workout by ID
48
+ import { TonalClient } from './src/client';
49
+
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
+ }
55
+
56
+ fetchWorkoutById('workout_id_here');
57
+ ```
58
+
59
+ ### Get Workout by Share URL
60
+
61
+ ```typescript
62
+ // Example: Fetching a workout by its share URL
63
+ import { TonalClient } from './src/client';
64
+
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);
69
+ }
70
+
71
+ fetchWorkoutByShareUrl('https://link.tonal.com/custom-workout/your_workout_id');
72
+ ```
73
+
74
+ ## Contributing
75
+
76
+ Contributions to this project are welcome, especially in the areas of error handling, expanding functionality, and improving the robustness of the client.
77
+
78
+ ## License
79
+
80
+ This project is open-sourced under the MIT License. See the [LICENSE](LICENSE) file for more details.
81
+
82
+ ## Contact
83
+
84
+ For any queries or further assistance, please contact [Derrick Wiest](mailto:me@dlwiest.com).
@@ -0,0 +1,16 @@
1
+ import { TonalMovement, TonalSharedWorkout, TonalWorkout } from './types';
2
+ export declare class TonalClient {
3
+ private username;
4
+ private password;
5
+ private idToken;
6
+ private tokenExpiresAt;
7
+ private constructor();
8
+ static create({ username, password }: {
9
+ username: string;
10
+ password: string;
11
+ }): Promise<TonalClient>;
12
+ private refreshToken;
13
+ getMovements(): Promise<TonalMovement[]>;
14
+ getWorkoutById(id: string): Promise<TonalWorkout>;
15
+ getWorkoutByShareUrl(shareUrl: string): Promise<TonalSharedWorkout>;
16
+ }
@@ -0,0 +1,132 @@
1
+ interface OAuthTokenResponse {
2
+ access_token: string;
3
+ id_token: string;
4
+ refresh_token: string;
5
+ scope: string;
6
+ token_type: string;
7
+ expires_in: number;
8
+ }
9
+ type MuscleGroup = 'Obliques' | 'Abs' | 'Shoulders' | 'Glutes' | 'Back' | 'Biceps' | 'Quads' | 'Triceps' | 'Chest' | 'Hamstrings' | 'Calves' | 'Forearms';
10
+ interface TonalMovement {
11
+ id: string;
12
+ createdAt: string;
13
+ updatedAt: string;
14
+ name: string;
15
+ shortName: string;
16
+ muscleGroups: MuscleGroup[];
17
+ bodyRegion: string;
18
+ bodyRegionDisplay: string;
19
+ baseOfSupport: string;
20
+ pushPull: string;
21
+ family: string;
22
+ familyDisplay: string;
23
+ inFreeLift: boolean;
24
+ onMachine: boolean;
25
+ countReps: boolean;
26
+ isTwoSided: boolean;
27
+ isBilateral: boolean;
28
+ isAlternating: boolean;
29
+ offMachineAccessory: string;
30
+ descriptionHow: string;
31
+ descriptionWhy: string;
32
+ sortOrder: number;
33
+ imageAssetId: string;
34
+ skillLevel: number;
35
+ active: boolean;
36
+ featureGroupIds: null | string[];
37
+ isGeneric: boolean;
38
+ }
39
+ interface TonalWorkout {
40
+ id: string;
41
+ createdAt: string;
42
+ title: string;
43
+ shortDescription: string;
44
+ description: string;
45
+ productionCode: string;
46
+ assetId: string;
47
+ coachId: string;
48
+ sets: WorkoutSet[];
49
+ duration: number;
50
+ publishState: string;
51
+ programId: string | null;
52
+ level: string;
53
+ groupIds: string[];
54
+ targetArea: string;
55
+ tags: string[] | null;
56
+ bodyRegions: MuscleGroup[];
57
+ goalIds: string[] | null;
58
+ trainingEffectGoals: string[];
59
+ disableModification: boolean;
60
+ publishedAt: string;
61
+ localPublishedAt: string;
62
+ type: string;
63
+ userId: string;
64
+ style: string;
65
+ trainingType: string;
66
+ trainingTypeIds: string[] | null;
67
+ mobileFriendly: boolean;
68
+ live: boolean;
69
+ recoveryWeight: boolean;
70
+ supportedDevices: string[] | null;
71
+ featureGroupIds: string[] | null;
72
+ movementIds: string[];
73
+ muscleGroupsForExclusion: MuscleGroup[] | null;
74
+ playbackType: string;
75
+ isImported: boolean;
76
+ }
77
+ interface WorkoutSet {
78
+ id: string;
79
+ workoutId: string;
80
+ blockStart: boolean;
81
+ movementId: string;
82
+ prescribedReps: number;
83
+ repetition: number;
84
+ repetitionTotal: number;
85
+ blockNumber: number;
86
+ burnout: boolean;
87
+ spotter: boolean;
88
+ eccentric: boolean;
89
+ chains: boolean;
90
+ skipSetup: boolean;
91
+ skipDemo: boolean;
92
+ finalSet: boolean;
93
+ calibration: boolean;
94
+ practice: boolean;
95
+ flex: boolean;
96
+ progressive: boolean;
97
+ weightPercentage: number;
98
+ warmUp: boolean;
99
+ durationBasedRepGoal: number;
100
+ setGroup: number;
101
+ round: number;
102
+ description: string;
103
+ dropSet: boolean;
104
+ omitempty: null | any;
105
+ }
106
+ interface TonalSharedWorkout {
107
+ id: string;
108
+ sharerUserId: string;
109
+ parentWorkoutId: string;
110
+ workoutSnapshotId: string;
111
+ workoutSnapshotHash: string;
112
+ deepLinkUrl: string;
113
+ workoutSnapshot: TonalWorkout;
114
+ }
115
+
116
+ declare class TonalClient {
117
+ private username;
118
+ private password;
119
+ private idToken;
120
+ private tokenExpiresAt;
121
+ private constructor();
122
+ static create({ username, password }: {
123
+ username: string;
124
+ password: string;
125
+ }): Promise<TonalClient>;
126
+ private refreshToken;
127
+ getMovements(): Promise<TonalMovement[]>;
128
+ getWorkoutById(id: string): Promise<TonalWorkout>;
129
+ getWorkoutByShareUrl(shareUrl: string): Promise<TonalSharedWorkout>;
130
+ }
131
+
132
+ export { MuscleGroup, OAuthTokenResponse, TonalMovement, TonalSharedWorkout, TonalWorkout, TonalClient as default };
@@ -0,0 +1,147 @@
1
+ /******************************************************************************
2
+ Copyright (c) Microsoft Corporation.
3
+
4
+ Permission to use, copy, modify, and/or distribute this software for any
5
+ purpose with or without fee is hereby granted.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
+ PERFORMANCE OF THIS SOFTWARE.
14
+ ***************************************************************************** */
15
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
16
+
17
+
18
+ function __awaiter(thisArg, _arguments, P, generator) {
19
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
20
+ return new (P || (P = Promise))(function (resolve, reject) {
21
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
23
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
24
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
25
+ });
26
+ }
27
+
28
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
29
+ var e = new Error(message);
30
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
31
+ };
32
+
33
+ class TonalClient {
34
+ constructor({ username, password }) {
35
+ this.username = username;
36
+ this.password = password;
37
+ this.idToken = '';
38
+ this.tokenExpiresAt = 0;
39
+ }
40
+ // TonalClient factory
41
+ static create(_a) {
42
+ return __awaiter(this, arguments, void 0, function* ({ username, password }) {
43
+ const client = new TonalClient({ username, password });
44
+ yield client.refreshToken();
45
+ return client;
46
+ });
47
+ }
48
+ // Request a new ID token from Auth0
49
+ refreshToken() {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ const data = {
52
+ username: this.username,
53
+ password: this.password,
54
+ client_id: 'ERCyexW-xoVG_Yy3RDe-eV4xsOnRHP6L',
55
+ grant_type: 'password',
56
+ scope: 'offline_access',
57
+ };
58
+ try {
59
+ const response = yield fetch('https://tonal.auth0.com/oauth/token', {
60
+ method: 'POST',
61
+ headers: {
62
+ 'Content-Type': 'application/json',
63
+ },
64
+ body: JSON.stringify(data),
65
+ });
66
+ if (response.status === 403) {
67
+ throw new Error('Invalid username or password');
68
+ }
69
+ const json = (yield response.json());
70
+ this.idToken = json.id_token;
71
+ this.tokenExpiresAt = Date.now() + json.expires_in * 1000;
72
+ }
73
+ catch (e) {
74
+ console.error(e);
75
+ throw new Error('Failed to retrieve access token');
76
+ }
77
+ });
78
+ }
79
+ // Get all movements available on Tonal
80
+ getMovements() {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ try {
83
+ if (this.tokenExpiresAt < Date.now()) {
84
+ yield this.refreshToken();
85
+ }
86
+ const response = yield fetch('https://api.tonal.com/v6/movements', {
87
+ headers: {
88
+ Authorization: `Bearer ${this.idToken}`,
89
+ },
90
+ });
91
+ return (yield response.json());
92
+ }
93
+ catch (e) {
94
+ console.error(e);
95
+ throw new Error('Failed to retrieve movements');
96
+ }
97
+ });
98
+ }
99
+ // Get a workout by its ID
100
+ getWorkoutById(id) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ try {
103
+ if (this.tokenExpiresAt < Date.now()) {
104
+ yield this.refreshToken();
105
+ }
106
+ const response = yield fetch(`https://api.tonal.com/v6/workouts/${id}`, {
107
+ headers: {
108
+ Authorization: `Bearer ${this.idToken}`,
109
+ },
110
+ });
111
+ const json = (yield response.json());
112
+ return json;
113
+ }
114
+ catch (e) {
115
+ console.error(e);
116
+ throw new Error('Failed to retrieve workout');
117
+ }
118
+ });
119
+ }
120
+ // Get a workout by its share URL
121
+ getWorkoutByShareUrl(shareUrl) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ if (!shareUrl) {
124
+ throw new Error('Share URL is required');
125
+ }
126
+ const shareId = shareUrl.split('/').pop();
127
+ try {
128
+ if (this.tokenExpiresAt < Date.now()) {
129
+ yield this.refreshToken();
130
+ }
131
+ const response = yield fetch(`https://api.tonal.com/v6/user-workouts/sharing-records/${shareId}`, {
132
+ headers: {
133
+ Authorization: `Bearer ${this.idToken}`,
134
+ },
135
+ });
136
+ const json = (yield response.json());
137
+ return json;
138
+ }
139
+ catch (e) {
140
+ console.error(e);
141
+ throw new Error('Failed to retrieve workout');
142
+ }
143
+ });
144
+ }
145
+ }
146
+
147
+ export { TonalClient as default };
package/dist/index.js ADDED
@@ -0,0 +1,149 @@
1
+ 'use strict';
2
+
3
+ /******************************************************************************
4
+ Copyright (c) Microsoft Corporation.
5
+
6
+ Permission to use, copy, modify, and/or distribute this software for any
7
+ purpose with or without fee is hereby granted.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
16
+ ***************************************************************************** */
17
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
18
+
19
+
20
+ function __awaiter(thisArg, _arguments, P, generator) {
21
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
22
+ return new (P || (P = Promise))(function (resolve, reject) {
23
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
24
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
25
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
26
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
27
+ });
28
+ }
29
+
30
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
31
+ var e = new Error(message);
32
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
33
+ };
34
+
35
+ class TonalClient {
36
+ constructor({ username, password }) {
37
+ this.username = username;
38
+ this.password = password;
39
+ this.idToken = '';
40
+ this.tokenExpiresAt = 0;
41
+ }
42
+ // TonalClient factory
43
+ static create(_a) {
44
+ return __awaiter(this, arguments, void 0, function* ({ username, password }) {
45
+ const client = new TonalClient({ username, password });
46
+ yield client.refreshToken();
47
+ return client;
48
+ });
49
+ }
50
+ // Request a new ID token from Auth0
51
+ refreshToken() {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ const data = {
54
+ username: this.username,
55
+ password: this.password,
56
+ client_id: 'ERCyexW-xoVG_Yy3RDe-eV4xsOnRHP6L',
57
+ grant_type: 'password',
58
+ scope: 'offline_access',
59
+ };
60
+ try {
61
+ const response = yield fetch('https://tonal.auth0.com/oauth/token', {
62
+ method: 'POST',
63
+ headers: {
64
+ 'Content-Type': 'application/json',
65
+ },
66
+ body: JSON.stringify(data),
67
+ });
68
+ if (response.status === 403) {
69
+ throw new Error('Invalid username or password');
70
+ }
71
+ const json = (yield response.json());
72
+ this.idToken = json.id_token;
73
+ this.tokenExpiresAt = Date.now() + json.expires_in * 1000;
74
+ }
75
+ catch (e) {
76
+ console.error(e);
77
+ throw new Error('Failed to retrieve access token');
78
+ }
79
+ });
80
+ }
81
+ // Get all movements available on Tonal
82
+ getMovements() {
83
+ return __awaiter(this, void 0, void 0, function* () {
84
+ try {
85
+ if (this.tokenExpiresAt < Date.now()) {
86
+ yield this.refreshToken();
87
+ }
88
+ const response = yield fetch('https://api.tonal.com/v6/movements', {
89
+ headers: {
90
+ Authorization: `Bearer ${this.idToken}`,
91
+ },
92
+ });
93
+ return (yield response.json());
94
+ }
95
+ catch (e) {
96
+ console.error(e);
97
+ throw new Error('Failed to retrieve movements');
98
+ }
99
+ });
100
+ }
101
+ // Get a workout by its ID
102
+ getWorkoutById(id) {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ try {
105
+ if (this.tokenExpiresAt < Date.now()) {
106
+ yield this.refreshToken();
107
+ }
108
+ const response = yield fetch(`https://api.tonal.com/v6/workouts/${id}`, {
109
+ headers: {
110
+ Authorization: `Bearer ${this.idToken}`,
111
+ },
112
+ });
113
+ const json = (yield response.json());
114
+ return json;
115
+ }
116
+ catch (e) {
117
+ console.error(e);
118
+ throw new Error('Failed to retrieve workout');
119
+ }
120
+ });
121
+ }
122
+ // Get a workout by its share URL
123
+ getWorkoutByShareUrl(shareUrl) {
124
+ return __awaiter(this, void 0, void 0, function* () {
125
+ if (!shareUrl) {
126
+ throw new Error('Share URL is required');
127
+ }
128
+ const shareId = shareUrl.split('/').pop();
129
+ try {
130
+ if (this.tokenExpiresAt < Date.now()) {
131
+ yield this.refreshToken();
132
+ }
133
+ const response = yield fetch(`https://api.tonal.com/v6/user-workouts/sharing-records/${shareId}`, {
134
+ headers: {
135
+ Authorization: `Bearer ${this.idToken}`,
136
+ },
137
+ });
138
+ const json = (yield response.json());
139
+ return json;
140
+ }
141
+ catch (e) {
142
+ console.error(e);
143
+ throw new Error('Failed to retrieve workout');
144
+ }
145
+ });
146
+ }
147
+ }
148
+
149
+ module.exports = TonalClient;
@@ -0,0 +1,115 @@
1
+ export interface OAuthTokenResponse {
2
+ access_token: string;
3
+ id_token: string;
4
+ refresh_token: string;
5
+ scope: string;
6
+ token_type: string;
7
+ expires_in: number;
8
+ }
9
+ export type MuscleGroup = 'Obliques' | 'Abs' | 'Shoulders' | 'Glutes' | 'Back' | 'Biceps' | 'Quads' | 'Triceps' | 'Chest' | 'Hamstrings' | 'Calves' | 'Forearms';
10
+ export interface TonalMovement {
11
+ id: string;
12
+ createdAt: string;
13
+ updatedAt: string;
14
+ name: string;
15
+ shortName: string;
16
+ muscleGroups: MuscleGroup[];
17
+ bodyRegion: string;
18
+ bodyRegionDisplay: string;
19
+ baseOfSupport: string;
20
+ pushPull: string;
21
+ family: string;
22
+ familyDisplay: string;
23
+ inFreeLift: boolean;
24
+ onMachine: boolean;
25
+ countReps: boolean;
26
+ isTwoSided: boolean;
27
+ isBilateral: boolean;
28
+ isAlternating: boolean;
29
+ offMachineAccessory: string;
30
+ descriptionHow: string;
31
+ descriptionWhy: string;
32
+ sortOrder: number;
33
+ imageAssetId: string;
34
+ skillLevel: number;
35
+ active: boolean;
36
+ featureGroupIds: null | string[];
37
+ isGeneric: boolean;
38
+ }
39
+ export interface TonalWorkout {
40
+ id: string;
41
+ createdAt: string;
42
+ title: string;
43
+ shortDescription: string;
44
+ description: string;
45
+ productionCode: string;
46
+ assetId: string;
47
+ coachId: string;
48
+ sets: WorkoutSet[];
49
+ duration: number;
50
+ publishState: string;
51
+ programId: string | null;
52
+ level: string;
53
+ groupIds: string[];
54
+ targetArea: string;
55
+ tags: string[] | null;
56
+ bodyRegions: MuscleGroup[];
57
+ goalIds: string[] | null;
58
+ trainingEffectGoals: string[];
59
+ disableModification: boolean;
60
+ publishedAt: string;
61
+ localPublishedAt: string;
62
+ type: string;
63
+ userId: string;
64
+ style: string;
65
+ trainingType: string;
66
+ trainingTypeIds: string[] | null;
67
+ mobileFriendly: boolean;
68
+ live: boolean;
69
+ recoveryWeight: boolean;
70
+ supportedDevices: string[] | null;
71
+ featureGroupIds: string[] | null;
72
+ movementIds: string[];
73
+ muscleGroupsForExclusion: MuscleGroup[] | null;
74
+ playbackType: string;
75
+ isImported: boolean;
76
+ }
77
+ interface WorkoutSet {
78
+ id: string;
79
+ workoutId: string;
80
+ blockStart: boolean;
81
+ movementId: string;
82
+ prescribedReps: number;
83
+ repetition: number;
84
+ repetitionTotal: number;
85
+ blockNumber: number;
86
+ burnout: boolean;
87
+ spotter: boolean;
88
+ eccentric: boolean;
89
+ chains: boolean;
90
+ skipSetup: boolean;
91
+ skipDemo: boolean;
92
+ finalSet: boolean;
93
+ calibration: boolean;
94
+ practice: boolean;
95
+ flex: boolean;
96
+ progressive: boolean;
97
+ weightPercentage: number;
98
+ warmUp: boolean;
99
+ durationBasedRepGoal: number;
100
+ setGroup: number;
101
+ round: number;
102
+ description: string;
103
+ dropSet: boolean;
104
+ omitempty: null | any;
105
+ }
106
+ export interface TonalSharedWorkout {
107
+ id: string;
108
+ sharerUserId: string;
109
+ parentWorkoutId: string;
110
+ workoutSnapshotId: string;
111
+ workoutSnapshotHash: string;
112
+ deepLinkUrl: string;
113
+ workoutSnapshot: TonalWorkout;
114
+ }
115
+ export {};
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@dlwiest/ts-tonal-client",
3
+ "version": "0.0.1",
4
+ "description": "TypeScript client for Tonal API",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "type": "module",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "rollup -c --bundleConfigAsCjs"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/dlwiest/ts-tonal-client.git"
18
+ },
19
+ "keywords": [],
20
+ "author": "",
21
+ "license": "ISC",
22
+ "bugs": {
23
+ "url": "https://github.com/dlwiest/ts-tonal-client/issues"
24
+ },
25
+ "homepage": "https://github.com/dlwiest/ts-tonal-client#readme",
26
+ "devDependencies": {
27
+ "@rollup/plugin-typescript": "^11.1.0",
28
+ "@types/node": "^20.14.8",
29
+ "rollup": "^3.20.2",
30
+ "rollup-plugin-dts": "^5.3.1",
31
+ "ts-node": "^10.9.2",
32
+ "tslib": "^2.7.0",
33
+ "typescript": "^5.5.4"
34
+ }
35
+ }