hevy-shared 1.0.917 → 1.0.918
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/built/adminPermissions.d.ts +1 -1
- package/built/adminPermissions.js +0 -1
- package/built/hevyTrainer.d.ts +25 -8
- package/built/hevyTrainer.js +159 -14
- package/built/index.d.ts +55 -2
- package/built/index.js +38 -2
- package/built/tests/hevyTrainer.test.d.ts +1 -0
- package/built/tests/hevyTrainer.test.js +118 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Lookup } from './typeUtils';
|
|
2
|
-
export declare const AdminPermissions: readonly ["become_user", "ip_blacklists", "featured_users", "feature_flags", "hevy_trainer", "user_account_management", "import_strong_csv", "community_management", "user_app_logs"
|
|
2
|
+
export declare const AdminPermissions: readonly ["become_user", "ip_blacklists", "featured_users", "feature_flags", "hevy_trainer", "user_account_management", "import_strong_csv", "community_management", "user_app_logs"];
|
|
3
3
|
export type AdminPermission = Lookup<typeof AdminPermissions>;
|
|
4
4
|
export declare const isAdminPermission: (permission?: any) => permission is AdminPermission;
|
package/built/hevyTrainer.d.ts
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import { WeeklyTrainingFrequency, TrainingGoal, TrainingLevel,
|
|
1
|
+
import { WeeklyTrainingFrequency, TrainingGoal, TrainingLevel, SimplifiedMuscleGroup, MuscleGroup, LibraryExercise, ExerciseCategory, GranularEquipment, HevyTrainerProgramEquipment } from '.';
|
|
2
2
|
export type HevyTrainerExerciseCategory = typeof hevyTrainerExerciseCategories[number];
|
|
3
3
|
export type HevyTrainerRoutineName = typeof routineNames[number];
|
|
4
|
-
export type HevyTrainerProgramEquipment = Extract<Equipment, 'barbell' | 'dumbbell' | 'machine'>;
|
|
5
|
-
export declare const hevyTrainerExerciseCategories: readonly ["compound", "isolation"];
|
|
6
|
-
export type WorkoutDurationMinutes = typeof workoutDurationOptions[number];
|
|
7
4
|
export declare const workoutDurationOptions: readonly [40, 60, 80];
|
|
5
|
+
export type WorkoutDurationMinutes = typeof workoutDurationOptions[number];
|
|
6
|
+
export declare const trainerGymTypes: readonly ["home_gym", "garage_gym", "commercial_gym", "full_gym"];
|
|
7
|
+
export type TrainerGymType = typeof trainerGymTypes[number];
|
|
8
|
+
export declare const granularEquipmentDefaults: {
|
|
9
|
+
[key in TrainerGymType]: GranularEquipment[];
|
|
10
|
+
};
|
|
11
|
+
export declare const trainerEquipmentToGranularEquipments: (equipments: HevyTrainerProgramEquipment[]) => GranularEquipment[];
|
|
12
|
+
/**
|
|
13
|
+
* Converts granular equipment values back to the old HevyTrainerProgramEquipment
|
|
14
|
+
* types for backwards compatibility with old mobile clients.
|
|
15
|
+
*/
|
|
16
|
+
export declare const granularEquipmentsToTrainerEquipments: (granularEquipments: GranularEquipment[]) => HevyTrainerProgramEquipment[];
|
|
17
|
+
export declare const hevyTrainerExerciseCategories: readonly ["compound", "isolation"];
|
|
8
18
|
export declare const defaultDurationPerFrequency: Record<WeeklyTrainingFrequency, WorkoutDurationMinutes>;
|
|
9
19
|
export declare const routineNames: readonly ["full_body_1", "full_body_2_a", "full_body_2_b", "full_body_3_a", "full_body_3_b", "full_body_3_c", "upper_1_a", "lower_1_a", "upper_1_b", "lower_1_b", "push_1", "pull_1", "legs_1", "upper_2", "lower_2", "push_2_a", "pull_2_a", "legs_2_a", "push_2_b", "pull_2_b", "legs_2_b"];
|
|
10
20
|
export type exerciseId = string;
|
|
11
21
|
export interface ExerciseSelectionCriteria {
|
|
12
22
|
exerciseCategory: HevyTrainerExerciseCategory | 'all';
|
|
13
|
-
equipments:
|
|
23
|
+
equipments: GranularEquipment[];
|
|
14
24
|
routineBarbellExerciseCount: number;
|
|
15
25
|
level: TrainingLevel;
|
|
16
26
|
goal: TrainingGoal;
|
|
@@ -32,7 +42,7 @@ export interface ProgramGenerationParams<T extends HevyTrainerLibraryExercise> {
|
|
|
32
42
|
selectedDays: WeeklyTrainingFrequency;
|
|
33
43
|
selectedGoal: TrainingGoal;
|
|
34
44
|
selectedLevel: TrainingLevel;
|
|
35
|
-
selectedEquipments:
|
|
45
|
+
selectedEquipments: GranularEquipment[];
|
|
36
46
|
selectedWorkoutDurationMinutes?: WorkoutDurationMinutes;
|
|
37
47
|
exerciseStore: T[];
|
|
38
48
|
focusMuscle?: SimplifiedMuscleGroup;
|
|
@@ -137,6 +147,13 @@ export declare const normalizeExerciseCategory: (exercise: {
|
|
|
137
147
|
is_custom: boolean;
|
|
138
148
|
category?: ExerciseCategory;
|
|
139
149
|
}) => HevyTrainerExerciseCategory;
|
|
150
|
+
/**
|
|
151
|
+
* Checks if an exercise is compatible with the user's selected granular equipments
|
|
152
|
+
*
|
|
153
|
+
* - If the exercise has no granular equipments, it is compatible no matter what the user has selected
|
|
154
|
+
* - Otherwise, the exercise is only allowed if the user has all the granular equipments
|
|
155
|
+
*/
|
|
156
|
+
export declare const isEquipmentCompatible: (exercise: HevyTrainerLibraryExercise, userSelectedGranularEquipments: GranularEquipment[]) => boolean;
|
|
140
157
|
/**
|
|
141
158
|
* Sorts exercises by priority for each muscle group based on the provided priorities
|
|
142
159
|
* and adds any remaining exercises from the store that weren't in the priorities.
|
|
@@ -150,7 +167,7 @@ export declare const getPrioritySortedExercises: <T extends HevyTrainerLibraryEx
|
|
|
150
167
|
* Selects the best exercise for a given prescription using a multi-pass strategy
|
|
151
168
|
*/
|
|
152
169
|
export declare const pickExerciseForPrescription: <T extends HevyTrainerLibraryExercise>(params: ExerciseSelectionParams<T>) => T | undefined;
|
|
153
|
-
export type HevyTrainerLibraryExercise = Pick<LibraryExercise, 'id' | 'title' | 'priority' | 'muscle_group' | 'other_muscles' | 'exercise_type' | 'equipment_category' | 'category' | 'level' | 'goal'>;
|
|
170
|
+
export type HevyTrainerLibraryExercise = Pick<LibraryExercise, 'id' | 'title' | 'priority' | 'muscle_group' | 'other_muscles' | 'exercise_type' | 'equipment_category' | 'category' | 'level' | 'goal' | 'granular_equipments'>;
|
|
154
171
|
export interface ExercisePrescriptionError {
|
|
155
172
|
type: 'exercise_not_found';
|
|
156
173
|
prescription: ExercisePrescription;
|
|
@@ -158,7 +175,7 @@ export interface ExercisePrescriptionError {
|
|
|
158
175
|
context: {
|
|
159
176
|
goal: TrainingGoal;
|
|
160
177
|
level: TrainingLevel;
|
|
161
|
-
equipments:
|
|
178
|
+
equipments: GranularEquipment[];
|
|
162
179
|
focusMuscle?: SimplifiedMuscleGroup;
|
|
163
180
|
};
|
|
164
181
|
}
|
package/built/hevyTrainer.js
CHANGED
|
@@ -1,10 +1,146 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateProgram = exports.pickExerciseForPrescription = exports.getPrioritySortedExercises = exports.normalizeExerciseCategory = exports.getTrainerRestTimerSeconds = exports.getTrainerRepRange = exports.getTrainerSetCount = exports.programSplits = exports.frequencyMap = exports.routineNames = exports.defaultDurationPerFrequency = exports.
|
|
3
|
+
exports.generateProgram = exports.pickExerciseForPrescription = exports.getPrioritySortedExercises = exports.isEquipmentCompatible = exports.normalizeExerciseCategory = exports.getTrainerRestTimerSeconds = exports.getTrainerRepRange = exports.getTrainerSetCount = exports.programSplits = exports.frequencyMap = exports.routineNames = exports.defaultDurationPerFrequency = exports.hevyTrainerExerciseCategories = exports.granularEquipmentsToTrainerEquipments = exports.trainerEquipmentToGranularEquipments = exports.granularEquipmentDefaults = exports.trainerGymTypes = exports.workoutDurationOptions = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
5
|
const MAX_BARBELL_EXERCISES_PER_ROUTINE = 2;
|
|
6
|
-
exports.hevyTrainerExerciseCategories = ['compound', 'isolation'];
|
|
7
6
|
exports.workoutDurationOptions = [40, 60, 80];
|
|
7
|
+
exports.trainerGymTypes = [
|
|
8
|
+
'home_gym',
|
|
9
|
+
'garage_gym',
|
|
10
|
+
'commercial_gym',
|
|
11
|
+
'full_gym',
|
|
12
|
+
];
|
|
13
|
+
exports.granularEquipmentDefaults = {
|
|
14
|
+
home_gym: ['dumbbell', 'pullup_bar', 'adjustable_bench'],
|
|
15
|
+
garage_gym: [
|
|
16
|
+
'dumbbell',
|
|
17
|
+
'kettlebell',
|
|
18
|
+
'barbell',
|
|
19
|
+
'plate',
|
|
20
|
+
'pullup_bar',
|
|
21
|
+
'dip_bar',
|
|
22
|
+
'squat_rack',
|
|
23
|
+
'adjustable_bench',
|
|
24
|
+
'spinning',
|
|
25
|
+
],
|
|
26
|
+
commercial_gym: [
|
|
27
|
+
'dumbbell',
|
|
28
|
+
'barbell',
|
|
29
|
+
'plate',
|
|
30
|
+
'ez_bar',
|
|
31
|
+
'pullup_bar',
|
|
32
|
+
'dip_bar',
|
|
33
|
+
'squat_rack',
|
|
34
|
+
'adjustable_bench',
|
|
35
|
+
'single_cable_machine',
|
|
36
|
+
'lat_pulldown_cable',
|
|
37
|
+
'leg_press_machine',
|
|
38
|
+
'smith_machine',
|
|
39
|
+
'stack_machines',
|
|
40
|
+
'treadmill',
|
|
41
|
+
'elliptical_trainer',
|
|
42
|
+
'spinning',
|
|
43
|
+
],
|
|
44
|
+
// All equipment is available in a full gym
|
|
45
|
+
full_gym: [
|
|
46
|
+
'barbell',
|
|
47
|
+
'dumbbell',
|
|
48
|
+
'kettlebell',
|
|
49
|
+
'plate',
|
|
50
|
+
'medicine_ball',
|
|
51
|
+
'ez_bar',
|
|
52
|
+
'landmine',
|
|
53
|
+
'trap_bar',
|
|
54
|
+
'pullup_bar',
|
|
55
|
+
'dip_bar',
|
|
56
|
+
'squat_rack',
|
|
57
|
+
'flat_bench',
|
|
58
|
+
'adjustable_bench',
|
|
59
|
+
'dual_cable_machine',
|
|
60
|
+
'single_cable_machine',
|
|
61
|
+
'lat_pulldown_cable',
|
|
62
|
+
'leg_press_machine',
|
|
63
|
+
'smith_machine',
|
|
64
|
+
't_bar',
|
|
65
|
+
'plate_machines',
|
|
66
|
+
'stack_machines',
|
|
67
|
+
'treadmill',
|
|
68
|
+
'elliptical_trainer',
|
|
69
|
+
'rowing_machine',
|
|
70
|
+
'spinning',
|
|
71
|
+
'stair_machine',
|
|
72
|
+
'air_bike',
|
|
73
|
+
'suspension_band',
|
|
74
|
+
'battle_rope',
|
|
75
|
+
'rings',
|
|
76
|
+
'jump_rope',
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
const trainerEquipmentToGranularEquipmentsMap = {
|
|
80
|
+
barbell: [
|
|
81
|
+
'adjustable_bench',
|
|
82
|
+
'barbell',
|
|
83
|
+
'ez_bar',
|
|
84
|
+
'flat_bench',
|
|
85
|
+
'landmine',
|
|
86
|
+
'plate',
|
|
87
|
+
'squat_rack',
|
|
88
|
+
't_bar',
|
|
89
|
+
],
|
|
90
|
+
dumbbell: ['adjustable_bench', 'dumbbell', 'flat_bench'],
|
|
91
|
+
machine: [
|
|
92
|
+
'adjustable_bench',
|
|
93
|
+
'dip_bar',
|
|
94
|
+
'dual_cable_machine',
|
|
95
|
+
'flat_bench',
|
|
96
|
+
'lat_pulldown_cable',
|
|
97
|
+
'leg_press_machine',
|
|
98
|
+
'plate',
|
|
99
|
+
'plate_machines',
|
|
100
|
+
'pullup_bar',
|
|
101
|
+
'single_cable_machine',
|
|
102
|
+
'smith_machine',
|
|
103
|
+
'stack_machines',
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
const trainerEquipmentToGranularEquipments = (equipments) => {
|
|
107
|
+
const granularEquipments = [];
|
|
108
|
+
equipments.forEach((equipment) => {
|
|
109
|
+
granularEquipments.push(...trainerEquipmentToGranularEquipmentsMap[equipment]);
|
|
110
|
+
});
|
|
111
|
+
return Array.from(new Set(granularEquipments));
|
|
112
|
+
};
|
|
113
|
+
exports.trainerEquipmentToGranularEquipments = trainerEquipmentToGranularEquipments;
|
|
114
|
+
const MACHINE_SPECIFIC_GRANULAR_EQUIPMENTS = [
|
|
115
|
+
'smith_machine',
|
|
116
|
+
'leg_press_machine',
|
|
117
|
+
'dual_cable_machine',
|
|
118
|
+
'single_cable_machine',
|
|
119
|
+
'lat_pulldown_cable',
|
|
120
|
+
'plate_machines',
|
|
121
|
+
'stack_machines',
|
|
122
|
+
'dip_bar',
|
|
123
|
+
'pullup_bar',
|
|
124
|
+
];
|
|
125
|
+
/**
|
|
126
|
+
* Converts granular equipment values back to the old HevyTrainerProgramEquipment
|
|
127
|
+
* types for backwards compatibility with old mobile clients.
|
|
128
|
+
*/
|
|
129
|
+
const granularEquipmentsToTrainerEquipments = (granularEquipments) => {
|
|
130
|
+
const result = [];
|
|
131
|
+
if (granularEquipments.includes('barbell')) {
|
|
132
|
+
result.push('barbell');
|
|
133
|
+
}
|
|
134
|
+
if (granularEquipments.includes('dumbbell')) {
|
|
135
|
+
result.push('dumbbell');
|
|
136
|
+
}
|
|
137
|
+
if (granularEquipments.some((eq) => MACHINE_SPECIFIC_GRANULAR_EQUIPMENTS.includes(eq))) {
|
|
138
|
+
result.push('machine');
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
};
|
|
142
|
+
exports.granularEquipmentsToTrainerEquipments = granularEquipmentsToTrainerEquipments;
|
|
143
|
+
exports.hevyTrainerExerciseCategories = ['compound', 'isolation'];
|
|
8
144
|
// These are the values that Philip decided for the default duration per frequency
|
|
9
145
|
exports.defaultDurationPerFrequency = {
|
|
10
146
|
1: 80,
|
|
@@ -120,19 +256,28 @@ const isFocusMuscleExtraExerciseAllowed = (templateName, focusMuscle) => {
|
|
|
120
256
|
}
|
|
121
257
|
};
|
|
122
258
|
/**
|
|
123
|
-
* Checks if an exercise is compatible with the user's equipments
|
|
259
|
+
* Checks if an exercise is compatible with the user's selected granular equipments
|
|
124
260
|
*
|
|
125
|
-
* -
|
|
126
|
-
* -
|
|
127
|
-
* - Otherwise, the exercise is only allowed if the user has that equipment
|
|
261
|
+
* - If the exercise has no granular equipments, it is compatible no matter what the user has selected
|
|
262
|
+
* - Otherwise, the exercise is only allowed if the user has all the granular equipments
|
|
128
263
|
*/
|
|
129
|
-
const isEquipmentCompatible = (exercise,
|
|
130
|
-
|
|
131
|
-
exercise.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
264
|
+
const isEquipmentCompatible = (exercise, userSelectedGranularEquipments) => {
|
|
265
|
+
if (!exercise.granular_equipments ||
|
|
266
|
+
exercise.granular_equipments.length === 0) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
const allowedEquipments = [...userSelectedGranularEquipments];
|
|
270
|
+
// Special case: adjustable bench can substitute for flat bench
|
|
271
|
+
if (userSelectedGranularEquipments.includes('adjustable_bench')) {
|
|
272
|
+
allowedEquipments.push('flat_bench');
|
|
273
|
+
}
|
|
274
|
+
// Special case: dual cable machine can substitute for single cable machine
|
|
275
|
+
if (userSelectedGranularEquipments.includes('dual_cable_machine')) {
|
|
276
|
+
allowedEquipments.push('single_cable_machine');
|
|
277
|
+
}
|
|
278
|
+
return exercise.granular_equipments.every((granularEquipment) => allowedEquipments.includes(granularEquipment));
|
|
135
279
|
};
|
|
280
|
+
exports.isEquipmentCompatible = isEquipmentCompatible;
|
|
136
281
|
/**
|
|
137
282
|
* Checks if the routine barbell exercise limit is exceeded
|
|
138
283
|
*
|
|
@@ -232,7 +377,7 @@ const isExerciseMatch = (exercise, criteria) => {
|
|
|
232
377
|
criteria.exerciseCategory === 'compound');
|
|
233
378
|
const levelMatch = (_b = (_a = exercise.level) === null || _a === void 0 ? void 0 : _a.includes(criteria.level)) !== null && _b !== void 0 ? _b : false;
|
|
234
379
|
const goalMatch = (_d = (_c = exercise.goal) === null || _c === void 0 ? void 0 : _c.includes(criteria.goal)) !== null && _d !== void 0 ? _d : false;
|
|
235
|
-
const equipmentMatch = isEquipmentCompatible(exercise, criteria.equipments);
|
|
380
|
+
const equipmentMatch = (0, exports.isEquipmentCompatible)(exercise, criteria.equipments);
|
|
236
381
|
const barbellLimitOk = !isBarbellLimitExceeded(exercise, criteria.routineBarbellExerciseCount, criteria.equipments);
|
|
237
382
|
return (categoryMatch && levelMatch && goalMatch && equipmentMatch && barbellLimitOk);
|
|
238
383
|
};
|
|
@@ -243,7 +388,7 @@ const isAlternativeIsolationExerciseMatch = (exercise, criteria) => {
|
|
|
243
388
|
var _a, _b;
|
|
244
389
|
const isIsolationCategory = criteria.exerciseCategory === 'isolation';
|
|
245
390
|
const isAlternativeExercise = isolationExerciseAlternatives[criteria.muscleGroup].includes(exercise.id);
|
|
246
|
-
const equipmentMatch = isEquipmentCompatible(exercise, criteria.equipments);
|
|
391
|
+
const equipmentMatch = (0, exports.isEquipmentCompatible)(exercise, criteria.equipments);
|
|
247
392
|
const levelMatch = (_b = (_a = exercise.level) === null || _a === void 0 ? void 0 : _a.includes(criteria.level)) !== null && _b !== void 0 ? _b : false;
|
|
248
393
|
return (isIsolationCategory && isAlternativeExercise && equipmentMatch && levelMatch);
|
|
249
394
|
};
|
package/built/index.d.ts
CHANGED
|
@@ -647,6 +647,9 @@ export type TrainingLevel = Lookup<typeof trainingLevels>;
|
|
|
647
647
|
export type ExerciseCategory = Lookup<typeof exerciseCategories>;
|
|
648
648
|
export type HevyTrainerProgramEquipment = Extract<Equipment, 'barbell' | 'dumbbell' | 'machine'>;
|
|
649
649
|
export declare const hevyTrainerProgramEquipments: readonly ["barbell", "dumbbell", "machine"];
|
|
650
|
+
export declare const granularEquipments: readonly ["barbell", "dumbbell", "kettlebell", "plate", "medicine_ball", "ez_bar", "landmine", "trap_bar", "pullup_bar", "dip_bar", "squat_rack", "flat_bench", "adjustable_bench", "dual_cable_machine", "single_cable_machine", "lat_pulldown_cable", "leg_press_machine", "smith_machine", "t_bar", "plate_machines", "stack_machines", "treadmill", "elliptical_trainer", "rowing_machine", "spinning", "stair_machine", "air_bike", "suspension_band", "resistance_band", "battle_rope", "rings", "jump_rope"];
|
|
651
|
+
export type GranularEquipment = Lookup<typeof granularEquipments>;
|
|
652
|
+
export declare const isGranularEquipment: (x: string) => x is GranularEquipment;
|
|
650
653
|
export declare const weeklyTrainingFrequencies: readonly [1, 2, 3, 4, 5, 6];
|
|
651
654
|
export type WeeklyTrainingFrequency = Lookup<typeof weeklyTrainingFrequencies>;
|
|
652
655
|
/**
|
|
@@ -698,6 +701,7 @@ export interface LibraryExercise extends BaseExerciseTemplate {
|
|
|
698
701
|
goal: TrainingGoal[] | undefined;
|
|
699
702
|
level: TrainingLevel[] | undefined;
|
|
700
703
|
category: ExerciseCategory | undefined;
|
|
704
|
+
granular_equipments: GranularEquipment[] | undefined;
|
|
701
705
|
url_female?: string;
|
|
702
706
|
thumbnail_url_female?: string;
|
|
703
707
|
}
|
|
@@ -1251,7 +1255,7 @@ export interface HevyTrainerProgram {
|
|
|
1251
1255
|
title: string;
|
|
1252
1256
|
level: TrainingLevel;
|
|
1253
1257
|
goal: TrainingGoal;
|
|
1254
|
-
equipments:
|
|
1258
|
+
equipments: GranularEquipment[];
|
|
1255
1259
|
weekly_frequency: WeeklyTrainingFrequency;
|
|
1256
1260
|
routines: HevyTrainerRoutine[];
|
|
1257
1261
|
focus_muscle?: SimplifiedMuscleGroup;
|
|
@@ -1263,7 +1267,7 @@ export interface PostHevyTrainerProgramRequestBody {
|
|
|
1263
1267
|
title: string;
|
|
1264
1268
|
level: TrainingLevel;
|
|
1265
1269
|
goal: TrainingGoal;
|
|
1266
|
-
equipments:
|
|
1270
|
+
equipments: GranularEquipment[];
|
|
1267
1271
|
weekly_frequency: WeeklyTrainingFrequency;
|
|
1268
1272
|
focus_muscle?: SimplifiedMuscleGroup;
|
|
1269
1273
|
routines: RoutineUpdate[];
|
|
@@ -1272,6 +1276,55 @@ export interface PostHevyTrainerProgramRequestBody {
|
|
|
1272
1276
|
};
|
|
1273
1277
|
}
|
|
1274
1278
|
export interface UpdateHevyTrainerProgramRequestBody {
|
|
1279
|
+
program: {
|
|
1280
|
+
programId: string;
|
|
1281
|
+
title: string;
|
|
1282
|
+
level: TrainingLevel;
|
|
1283
|
+
goal: TrainingGoal;
|
|
1284
|
+
equipments: GranularEquipment[];
|
|
1285
|
+
weekly_frequency: WeeklyTrainingFrequency;
|
|
1286
|
+
focus_muscle?: SimplifiedMuscleGroup;
|
|
1287
|
+
next_workout_index?: number;
|
|
1288
|
+
workout_duration_minutes?: WorkoutDurationMinutes;
|
|
1289
|
+
routines: {
|
|
1290
|
+
id: string;
|
|
1291
|
+
title: string;
|
|
1292
|
+
notes: string | null;
|
|
1293
|
+
exercises: RoutineUpdateExercise[];
|
|
1294
|
+
}[];
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
/** @deprecated Use HevyTrainerProgram instead */
|
|
1298
|
+
export interface HevyTrainerProgramOld {
|
|
1299
|
+
id: string;
|
|
1300
|
+
created_at: string;
|
|
1301
|
+
updated_at: string;
|
|
1302
|
+
title: string;
|
|
1303
|
+
level: TrainingLevel;
|
|
1304
|
+
goal: TrainingGoal;
|
|
1305
|
+
equipments: HevyTrainerProgramEquipment[];
|
|
1306
|
+
weekly_frequency: WeeklyTrainingFrequency;
|
|
1307
|
+
routines: HevyTrainerRoutine[];
|
|
1308
|
+
focus_muscle?: SimplifiedMuscleGroup;
|
|
1309
|
+
next_workout_index: number;
|
|
1310
|
+
workout_duration_minutes?: WorkoutDurationMinutes;
|
|
1311
|
+
}
|
|
1312
|
+
/** @deprecated Use PostHevyTrainerProgramRequestBody instead */
|
|
1313
|
+
export interface PostHevyTrainerProgramOldRequestBody {
|
|
1314
|
+
program: {
|
|
1315
|
+
title: string;
|
|
1316
|
+
level: TrainingLevel;
|
|
1317
|
+
goal: TrainingGoal;
|
|
1318
|
+
equipments: HevyTrainerProgramEquipment[];
|
|
1319
|
+
weekly_frequency: WeeklyTrainingFrequency;
|
|
1320
|
+
focus_muscle?: SimplifiedMuscleGroup;
|
|
1321
|
+
routines: RoutineUpdate[];
|
|
1322
|
+
next_workout_index?: number;
|
|
1323
|
+
workout_duration_minutes?: WorkoutDurationMinutes;
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
/** @deprecated Use UpdateHevyTrainerProgramRequestBody instead */
|
|
1327
|
+
export interface UpdateHevyTrainerProgramOldRequestBody {
|
|
1275
1328
|
program: {
|
|
1276
1329
|
programId: string;
|
|
1277
1330
|
title: string;
|
package/built/index.js
CHANGED
|
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
18
|
-
exports.isOAuthScope = exports.supportedScopes = exports.isSuggestedUserSource = exports.isValidUserWorkoutMetricsType = exports.isBodyMeasurementKey = exports.measurementsList = void 0;
|
|
17
|
+
exports.isHeartRateSamples = exports.isPublicWorkout = exports.isSetType = exports.isRPE = exports.validRpeValues = exports.isSetPersonalRecordType = exports.supportedInstructionsLanguages = exports.weeklyTrainingFrequencies = exports.isGranularEquipment = exports.granularEquipments = exports.hevyTrainerProgramEquipments = exports.exerciseCategories = exports.trainingLevels = exports.trainingGoals = exports.isCustomExerciseType = exports.customExericseTypes = exports.isExerciseType = exports.exerciseTypes = exports.isExerciseRepType = exports.exerciseRepTypes = exports.isEquipmentFilter = exports.equipmentFilters = exports.isEquipment = exports.equipments = exports.simplifiedMuscleGroupToMuscleGroups = exports.isMuscleGroupFilter = exports.muscleGroupFilters = exports.isMuscleGroup = exports.muscleGroups = exports.isSimplifiedMuscleGroup = exports.simplifiedMuscleGroups = exports.miscellaneousMuscles = exports.chestMuscles = exports.backMuscles = exports.legMuscles = exports.armMuscles = exports.shoulderMuscles = exports.coreMuscles = exports.DefaultClientConfiguration = exports.parseClientAuthTokenResponse = exports.isCoachRole = exports.isErrorResponse = exports.isLivePRVolumeOption = exports.isTimerVolumeOption = exports.isWeekday = exports.orderedWeekdays = exports.isBodyMeasurementUnit = exports.isDistanceUnitShort = exports.isDistanceUnit = exports.isWeightUnit = void 0;
|
|
18
|
+
exports.isOAuthScope = exports.supportedScopes = exports.isSuggestedUserSource = exports.isValidUserWorkoutMetricsType = exports.isBodyMeasurementKey = exports.measurementsList = exports.isHevyTrainerRoutine = exports.isWorkoutBiometrics = void 0;
|
|
19
19
|
const typeUtils_1 = require("./typeUtils");
|
|
20
20
|
__exportStar(require("./constants"), exports);
|
|
21
21
|
__exportStar(require("./utils"), exports);
|
|
@@ -232,6 +232,42 @@ exports.hevyTrainerProgramEquipments = [
|
|
|
232
232
|
'dumbbell',
|
|
233
233
|
'machine',
|
|
234
234
|
];
|
|
235
|
+
exports.granularEquipments = [
|
|
236
|
+
'barbell',
|
|
237
|
+
'dumbbell',
|
|
238
|
+
'kettlebell',
|
|
239
|
+
'plate',
|
|
240
|
+
'medicine_ball',
|
|
241
|
+
'ez_bar',
|
|
242
|
+
'landmine',
|
|
243
|
+
'trap_bar',
|
|
244
|
+
'pullup_bar',
|
|
245
|
+
'dip_bar',
|
|
246
|
+
'squat_rack',
|
|
247
|
+
'flat_bench',
|
|
248
|
+
'adjustable_bench',
|
|
249
|
+
'dual_cable_machine',
|
|
250
|
+
'single_cable_machine',
|
|
251
|
+
'lat_pulldown_cable',
|
|
252
|
+
'leg_press_machine',
|
|
253
|
+
'smith_machine',
|
|
254
|
+
't_bar',
|
|
255
|
+
'plate_machines',
|
|
256
|
+
'stack_machines',
|
|
257
|
+
'treadmill',
|
|
258
|
+
'elliptical_trainer',
|
|
259
|
+
'rowing_machine',
|
|
260
|
+
'spinning',
|
|
261
|
+
'stair_machine',
|
|
262
|
+
'air_bike',
|
|
263
|
+
'suspension_band',
|
|
264
|
+
'resistance_band',
|
|
265
|
+
'battle_rope',
|
|
266
|
+
'rings',
|
|
267
|
+
'jump_rope',
|
|
268
|
+
];
|
|
269
|
+
const isGranularEquipment = (x) => (0, typeUtils_1.isInArray)(x, exports.granularEquipments);
|
|
270
|
+
exports.isGranularEquipment = isGranularEquipment;
|
|
235
271
|
exports.weeklyTrainingFrequencies = [1, 2, 3, 4, 5, 6];
|
|
236
272
|
exports.supportedInstructionsLanguages = [
|
|
237
273
|
'en',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const hevyTrainer_1 = require("../hevyTrainer");
|
|
4
|
+
const sortGranular = (arr) => [...arr].sort();
|
|
5
|
+
describe('trainerEquipmentToGranularEquipments', () => {
|
|
6
|
+
it('returns empty array when no equipments are provided', () => {
|
|
7
|
+
expect((0, hevyTrainer_1.trainerEquipmentToGranularEquipments)([])).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
it('returns expected granular equipments for barbell only', () => {
|
|
10
|
+
const result = (0, hevyTrainer_1.trainerEquipmentToGranularEquipments)(['barbell']);
|
|
11
|
+
expect(sortGranular(result)).toEqual(sortGranular([
|
|
12
|
+
'adjustable_bench',
|
|
13
|
+
'barbell',
|
|
14
|
+
'ez_bar',
|
|
15
|
+
'flat_bench',
|
|
16
|
+
'landmine',
|
|
17
|
+
'plate',
|
|
18
|
+
'squat_rack',
|
|
19
|
+
't_bar',
|
|
20
|
+
]));
|
|
21
|
+
});
|
|
22
|
+
it('returns expected granular equipments for dumbbell only', () => {
|
|
23
|
+
const result = (0, hevyTrainer_1.trainerEquipmentToGranularEquipments)(['dumbbell']);
|
|
24
|
+
expect(sortGranular(result)).toEqual(sortGranular(['adjustable_bench', 'dumbbell', 'flat_bench']));
|
|
25
|
+
});
|
|
26
|
+
it('returns expected granular equipments for machine only', () => {
|
|
27
|
+
const result = (0, hevyTrainer_1.trainerEquipmentToGranularEquipments)(['machine']);
|
|
28
|
+
expect(sortGranular(result)).toEqual(sortGranular([
|
|
29
|
+
'adjustable_bench',
|
|
30
|
+
'dip_bar',
|
|
31
|
+
'dual_cable_machine',
|
|
32
|
+
'flat_bench',
|
|
33
|
+
'lat_pulldown_cable',
|
|
34
|
+
'leg_press_machine',
|
|
35
|
+
'plate',
|
|
36
|
+
'plate_machines',
|
|
37
|
+
'pullup_bar',
|
|
38
|
+
'single_cable_machine',
|
|
39
|
+
'smith_machine',
|
|
40
|
+
'stack_machines',
|
|
41
|
+
]));
|
|
42
|
+
});
|
|
43
|
+
it('returns deduped union for multiple equipments', () => {
|
|
44
|
+
const equipments = ['barbell', 'dumbbell'];
|
|
45
|
+
const result = (0, hevyTrainer_1.trainerEquipmentToGranularEquipments)(equipments);
|
|
46
|
+
const barbellOnly = (0, hevyTrainer_1.trainerEquipmentToGranularEquipments)(['barbell']);
|
|
47
|
+
const dumbbellOnly = (0, hevyTrainer_1.trainerEquipmentToGranularEquipments)(['dumbbell']);
|
|
48
|
+
const combined = sortGranular(Array.from(new Set([...barbellOnly, ...dumbbellOnly])));
|
|
49
|
+
expect(sortGranular(result)).toEqual(combined);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
const createExercise = (granularEquipments) => ({
|
|
53
|
+
id: 'test-exercise',
|
|
54
|
+
title: 'Test Exercise',
|
|
55
|
+
granular_equipments: granularEquipments,
|
|
56
|
+
});
|
|
57
|
+
describe('isEquipmentCompatible', () => {
|
|
58
|
+
it('returns true when exercise has no granular equipments', () => {
|
|
59
|
+
const exercise = createExercise(undefined);
|
|
60
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['barbell'])).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
it('returns true when exercise has empty granular equipments', () => {
|
|
63
|
+
const exercise = createExercise([]);
|
|
64
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['barbell'])).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
it('returns true when user has all required equipments', () => {
|
|
67
|
+
const exercise = createExercise(['barbell', 'squat_rack']);
|
|
68
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['barbell', 'squat_rack'])).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
it('returns false when user is missing required equipment', () => {
|
|
71
|
+
const exercise = createExercise(['barbell', 'squat_rack']);
|
|
72
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['barbell'])).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
it('returns true when user has more equipment than required', () => {
|
|
75
|
+
const exercise = createExercise(['barbell']);
|
|
76
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['barbell', 'squat_rack', 'dumbbell'])).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
describe('special case: adjustable_bench / flat_bench substitution', () => {
|
|
79
|
+
it('allows adjustable_bench to substitute for flat_bench when exercise requires flat_bench', () => {
|
|
80
|
+
const exercise = createExercise(['flat_bench']);
|
|
81
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['adjustable_bench'])).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
it('does NOT allow flat_bench to substitute for adjustable_bench when exercise requires adjustable_bench', () => {
|
|
84
|
+
const exercise = createExercise(['adjustable_bench']);
|
|
85
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['flat_bench'])).toBe(false);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('special case: dual_cable_machine / single_cable_machine substitution', () => {
|
|
89
|
+
it('allows dual_cable_machine to substitute for single_cable_machine when exercise requires single_cable_machine', () => {
|
|
90
|
+
const exercise = createExercise(['single_cable_machine']);
|
|
91
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['dual_cable_machine'])).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
it('does NOT allow single_cable_machine to substitute for dual_cable_machine when exercise requires dual_cable_machine', () => {
|
|
94
|
+
const exercise = createExercise(['dual_cable_machine']);
|
|
95
|
+
expect((0, hevyTrainer_1.isEquipmentCompatible)(exercise, ['single_cable_machine'])).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
const __1 = require("..");
|
|
100
|
+
describe('hevyTrainer gym types and defaults', () => {
|
|
101
|
+
it('defines granular equipment defaults for every trainer gym type', () => {
|
|
102
|
+
__1.trainerGymTypes.forEach((gymType) => {
|
|
103
|
+
const defaults = __1.granularEquipmentDefaults[gymType];
|
|
104
|
+
expect(Array.isArray(defaults)).toBe(true);
|
|
105
|
+
expect(defaults.length).toBeGreaterThan(0);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
it('granular equipment defaults only contain granular equipment values', () => {
|
|
109
|
+
Object.keys(__1.granularEquipmentDefaults).forEach((gymType) => {
|
|
110
|
+
const defaults = __1.granularEquipmentDefaults[gymType];
|
|
111
|
+
defaults.forEach((equipment) => {
|
|
112
|
+
// Type assertion ensures the mapping stays within the GranularEquipment union.
|
|
113
|
+
const typed = equipment;
|
|
114
|
+
expect(typeof typed).toBe('string');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|