hevy-shared 1.0.706 → 1.0.708

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.
@@ -0,0 +1,126 @@
1
+ import { WeeklyTrainingFrequency, TrainingGoal, TrainingLevel, Equipment, SimplifiedMuscleGroup, MuscleGroup, LibraryExercise } from '.';
2
+ export type HevyTrainerExerciseCategory = typeof hevyTrainerExerciseCategories[number];
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 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"];
7
+ export type exerciseId = string;
8
+ export declare const frequencyMap: Record<WeeklyTrainingFrequency, string>;
9
+ export declare const programSplits: Record<WeeklyTrainingFrequency, HevyTrainerRoutineName[]>;
10
+ export type SetsPerGoal = {
11
+ [key in TrainingGoal]: number;
12
+ };
13
+ export type Sets = {
14
+ [key in string]: SetsPerGoal;
15
+ };
16
+ export interface RepRange {
17
+ rep_range_start: number;
18
+ rep_range_end: number;
19
+ }
20
+ export type RepRangesPerCategory = {
21
+ [key in HevyTrainerExerciseCategory]: RepRange;
22
+ };
23
+ export type RepRanges = {
24
+ [key in TrainingGoal]: RepRangesPerCategory;
25
+ };
26
+ export type RestTimersPerCategory = {
27
+ [key in HevyTrainerExerciseCategory]: number;
28
+ };
29
+ export type RestTimers = {
30
+ [key in TrainingGoal]: RestTimersPerCategory;
31
+ };
32
+ export type ExercisePriorities = {
33
+ [key in MuscleGroup]: exerciseId[];
34
+ };
35
+ export type ExerciseNotes = {
36
+ [key in exerciseId]: string;
37
+ };
38
+ export interface ExercisePrescription {
39
+ muscle_group: MuscleGroup | 'focus_muscle';
40
+ category: HevyTrainerExerciseCategory;
41
+ warmup_set_count?: number;
42
+ }
43
+ export interface WorkoutTemplate {
44
+ exercises: ExercisePrescription[];
45
+ notes?: string;
46
+ }
47
+ export type Templates = {
48
+ [key in HevyTrainerRoutineName]: WorkoutTemplate;
49
+ };
50
+ export interface TrainerPreset {
51
+ id?: number;
52
+ username: string;
53
+ title?: string;
54
+ is_default?: boolean;
55
+ updated_at?: string;
56
+ settings: TrainerPresetSettings;
57
+ workout_tab_ai_insight_prompt?: string;
58
+ }
59
+ export interface TrainerPresetSettings {
60
+ sets: Sets;
61
+ rep_ranges: RepRanges;
62
+ rest_timers: RestTimers;
63
+ templates: Templates;
64
+ exercise_priorities: ExercisePriorities;
65
+ exercise_notes: ExerciseNotes;
66
+ }
67
+ export interface TrainerProgramExercise {
68
+ exerciseTemplate: HevyTrainerLibraryExercise;
69
+ muscleGroup: MuscleGroup | 'focus_muscle';
70
+ category: HevyTrainerExerciseCategory;
71
+ sets: number;
72
+ warmupSetCount?: number;
73
+ repRangeStart: number;
74
+ repRangeEnd: number;
75
+ restTimerSeconds: number;
76
+ notes?: string;
77
+ }
78
+ export interface TrainerProgramRoutine {
79
+ name: HevyTrainerRoutineName;
80
+ exercises: TrainerProgramExercise[];
81
+ notes?: string;
82
+ }
83
+ export interface TrainerProgram {
84
+ name: WeeklyTrainingFrequency;
85
+ routines: TrainerProgramRoutine[];
86
+ }
87
+ export type HevyTrainerLibraryExercise = Pick<LibraryExercise, 'id' | 'title' | 'priority' | 'muscle_group' | 'other_muscles' | 'exercise_type' | 'equipment_category' | 'category' | 'level' | 'goal'>;
88
+ export interface ExercisePrescriptionError {
89
+ type: 'exercise_not_found';
90
+ prescription: ExercisePrescription;
91
+ muscleGroup: MuscleGroup;
92
+ context: {
93
+ goal: TrainingGoal;
94
+ level: TrainingLevel;
95
+ equipments: HevyTrainerProgramEquipment[];
96
+ focusMuscle?: SimplifiedMuscleGroup;
97
+ };
98
+ }
99
+ export interface TrainerProgramExerciseResult {
100
+ success: true;
101
+ exercise: TrainerProgramExercise;
102
+ }
103
+ export interface TrainerProgramExerciseError {
104
+ success: false;
105
+ error: ExercisePrescriptionError;
106
+ }
107
+ export type TrainerProgramExerciseAttempt = TrainerProgramExerciseResult | TrainerProgramExerciseError;
108
+ export interface TrainerProgramResult {
109
+ success: true;
110
+ program: TrainerProgram;
111
+ }
112
+ export interface TrainerProgramError {
113
+ success: false;
114
+ errors: ExercisePrescriptionError[];
115
+ partialProgram?: TrainerProgram;
116
+ }
117
+ export type TrainerProgramAttempt = TrainerProgramResult | TrainerProgramError;
118
+ export declare const generateProgram: ({ trainerPreset, selectedDays, selectedGoal, selectedLevel, selectedEquipments, exerciseStore, focusMuscle, }: {
119
+ trainerPreset: TrainerPreset;
120
+ selectedDays: WeeklyTrainingFrequency;
121
+ selectedGoal: TrainingGoal;
122
+ selectedLevel: TrainingLevel;
123
+ selectedEquipments: HevyTrainerProgramEquipment[];
124
+ exerciseStore: HevyTrainerLibraryExercise[];
125
+ focusMuscle?: SimplifiedMuscleGroup;
126
+ }) => TrainerProgramAttempt;
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateProgram = exports.programSplits = exports.frequencyMap = exports.routineNames = exports.hevyTrainerExerciseCategories = void 0;
4
+ const _1 = require(".");
5
+ exports.hevyTrainerExerciseCategories = ['compound', 'isolation'];
6
+ exports.routineNames = [
7
+ // Full body 1x
8
+ 'full_body_1',
9
+ // Full body 2x
10
+ 'full_body_2_a',
11
+ 'full_body_2_b',
12
+ // Full body 3x
13
+ 'full_body_3_a',
14
+ 'full_body_3_b',
15
+ 'full_body_3_c',
16
+ // Upper body x4 per week
17
+ 'upper_1_a',
18
+ 'lower_1_a',
19
+ 'upper_1_b',
20
+ 'lower_1_b',
21
+ // Push Pull Legs Upper Lower 5x per week
22
+ 'push_1',
23
+ 'pull_1',
24
+ 'legs_1',
25
+ 'upper_2',
26
+ 'lower_2',
27
+ // Push Pull Legs x6 per week
28
+ 'push_2_a',
29
+ 'pull_2_a',
30
+ 'legs_2_a',
31
+ 'push_2_b',
32
+ 'pull_2_b',
33
+ 'legs_2_b',
34
+ ];
35
+ exports.frequencyMap = {
36
+ 1: 'one_day',
37
+ 2: 'two_days',
38
+ 3: 'three_days',
39
+ 4: 'four_days',
40
+ 5: 'five_days',
41
+ 6: 'six_days',
42
+ };
43
+ exports.programSplits = {
44
+ 1: ['full_body_1'],
45
+ 2: ['full_body_2_a', 'full_body_2_b'],
46
+ 3: ['full_body_3_a', 'full_body_3_b', 'full_body_3_c'],
47
+ 4: ['upper_1_a', 'lower_1_a', 'upper_1_b', 'lower_1_b'],
48
+ 5: ['push_1', 'pull_1', 'legs_1', 'upper_2', 'lower_2'],
49
+ 6: ['push_2_a', 'pull_2_a', 'legs_2_a', 'push_2_b', 'pull_2_b', 'legs_2_b'],
50
+ };
51
+ const isolationExerciseAlternatives = {
52
+ chest: ['B74A95BB', '392887AA', '39C99849'],
53
+ triceps: ['6575F52D', 'CD6DC8E5'],
54
+ quadriceps: ['32HKJ34K', 'A733CC5B', '9694DA61'],
55
+ hamstrings: ['F6948F17', '487B3755', 'CDA23948'],
56
+ glutes: [],
57
+ lats: [],
58
+ lower_back: [],
59
+ upper_back: [],
60
+ shoulders: [],
61
+ biceps: [],
62
+ adductors: [],
63
+ abductors: [],
64
+ calves: [],
65
+ forearms: [],
66
+ abdominals: [],
67
+ other: [],
68
+ cardio: [],
69
+ traps: [],
70
+ neck: [],
71
+ full_body: [],
72
+ };
73
+ const getMuscleGroup = ({ muscleGroupPrescription, programFocusMuscleExerciseCount, focusMuscle, }) => {
74
+ if (muscleGroupPrescription === 'focus_muscle') {
75
+ if (!!focusMuscle) {
76
+ const n = _1.simplifiedMuscleGroupToMuscleGroups[focusMuscle].length;
77
+ return _1.simplifiedMuscleGroupToMuscleGroups[focusMuscle][programFocusMuscleExerciseCount % n];
78
+ }
79
+ // User has not selected a focus muscle, so we skip this extra exercise for the focus muscle
80
+ return undefined;
81
+ }
82
+ return muscleGroupPrescription;
83
+ };
84
+ const isExerciseMatch = ({ exercisePrescription, exercise, equipments, routineBarbellExerciseCount, level, goal, }) => {
85
+ var _a, _b;
86
+ return ((exercise.category === exercisePrescription.category ||
87
+ (exercise.category === 'assistance-compound' && // Airtable also has `assistance-compound` as another category
88
+ exercisePrescription.category === 'compound')) && // but we are not differentiating between them and using `compound` instead
89
+ ((_a = exercise.level) === null || _a === void 0 ? void 0 : _a.includes(level)) &&
90
+ ((_b = exercise.goal) === null || _b === void 0 ? void 0 : _b.includes(goal)) &&
91
+ (equipments.includes(exercise.equipment_category) ||
92
+ exercise.equipment_category === 'none' ||
93
+ exercise.equipment_category === 'other') &&
94
+ // Up to 2 barbell exercises per routine, unless there is only one equipment category selected
95
+ (exercise.equipment_category !== 'barbell' ||
96
+ routineBarbellExerciseCount < 2 ||
97
+ equipments.length === 1));
98
+ };
99
+ const isAlternativeIsolationExerciseMatch = ({ exercise, exercisePrescription, equipments, level, muscleGroup, }) => {
100
+ var _a;
101
+ return (exercisePrescription.category === 'isolation' &&
102
+ isolationExerciseAlternatives[muscleGroup].includes(exercise.id) &&
103
+ (equipments.includes(exercise.equipment_category) ||
104
+ exercise.equipment_category === 'none' ||
105
+ exercise.equipment_category === 'other') &&
106
+ ((_a = exercise.level) === null || _a === void 0 ? void 0 : _a.includes(level)));
107
+ };
108
+ const generateProgram = ({ trainerPreset, selectedDays, selectedGoal, selectedLevel, selectedEquipments, exerciseStore, focusMuscle, }) => {
109
+ var _a;
110
+ const routines = exports.programSplits[selectedDays];
111
+ const program = {
112
+ name: selectedDays,
113
+ routines: [],
114
+ };
115
+ // Have a map of muscle group to exercises sorted by exercise priority
116
+ const sortedExercises = Object.entries(trainerPreset.settings.exercise_priorities).reduce((acc, [muscleGroup, exercises]) => {
117
+ acc[muscleGroup] = exercises.map((exercise) => exerciseStore.find((e) => e.id === exercise));
118
+ return acc;
119
+ }, {});
120
+ // Then add remaining exercises to the map
121
+ Object.keys(sortedExercises).forEach((muscleGroup) => {
122
+ const remainingExercises = exerciseStore
123
+ .filter((e) => e.muscle_group === muscleGroup &&
124
+ !sortedExercises[muscleGroup].includes(e))
125
+ .sort((a, b) => b.priority - a.priority);
126
+ sortedExercises[muscleGroup].push(...remainingExercises);
127
+ });
128
+ const programUsedExercises = new Set();
129
+ let programFocusMuscleExerciseCount = 0;
130
+ const allErrors = [];
131
+ for (const routine of routines) {
132
+ const routineTemplate = trainerPreset.settings.templates[routine];
133
+ let routineBarbellExerciseCount = 0;
134
+ const routineUsedExercises = new Set();
135
+ const routineExercises = [];
136
+ for (const exercisePrescription of routineTemplate.exercises) {
137
+ const muscleGroup = getMuscleGroup({
138
+ muscleGroupPrescription: exercisePrescription.muscle_group,
139
+ programFocusMuscleExerciseCount,
140
+ focusMuscle,
141
+ });
142
+ // If the muscle group is not found, skip the exercise
143
+ if (!muscleGroup) {
144
+ continue;
145
+ }
146
+ // First pass: Try to find an exact match for the exercise that is not used in the program
147
+ let exercise = sortedExercises[muscleGroup].find((e) => isExerciseMatch({
148
+ exercisePrescription,
149
+ exercise: e,
150
+ equipments: selectedEquipments,
151
+ routineBarbellExerciseCount,
152
+ level: selectedLevel,
153
+ goal: selectedGoal,
154
+ }) && !programUsedExercises.has(e.title));
155
+ if (exercise === undefined) {
156
+ // Second pass
157
+ // By allowing the same exercise to be assigned in the same program more than once
158
+ const extendedMatchingExercise = sortedExercises[muscleGroup].find((e) => isExerciseMatch({
159
+ exercisePrescription,
160
+ exercise: e,
161
+ equipments: selectedEquipments,
162
+ routineBarbellExerciseCount,
163
+ level: selectedLevel,
164
+ goal: selectedGoal,
165
+ }) && !routineUsedExercises.has(e.title));
166
+ exercise = extendedMatchingExercise;
167
+ }
168
+ if (exercise === undefined) {
169
+ // Third pass
170
+ // Check if isolation exercise alternatives are available and not used in the program
171
+ const alternativeIsolationExercise = sortedExercises[muscleGroup].find((e) => isAlternativeIsolationExerciseMatch({
172
+ exercise: e,
173
+ exercisePrescription,
174
+ equipments: selectedEquipments,
175
+ level: selectedLevel,
176
+ muscleGroup,
177
+ }) && !programUsedExercises.has(e.title));
178
+ exercise = alternativeIsolationExercise;
179
+ }
180
+ if (exercise === undefined) {
181
+ // Fourth pass
182
+ // Check if isolation exercise alternatives are available and not used in the workout
183
+ const extendedIsolationExercise = sortedExercises[muscleGroup].find((e) => isAlternativeIsolationExerciseMatch({
184
+ exercise: e,
185
+ exercisePrescription,
186
+ equipments: selectedEquipments,
187
+ level: selectedLevel,
188
+ muscleGroup,
189
+ }) && !routineUsedExercises.has(e.title));
190
+ exercise = extendedIsolationExercise;
191
+ }
192
+ if (!!exercise) {
193
+ programUsedExercises.add(exercise.title);
194
+ routineUsedExercises.add(exercise.title);
195
+ if (exercise.equipment_category === 'barbell')
196
+ routineBarbellExerciseCount++;
197
+ if (exercisePrescription.muscle_group === 'focus_muscle')
198
+ programFocusMuscleExerciseCount++;
199
+ routineExercises.push({
200
+ exerciseTemplate: exercise,
201
+ muscleGroup: exercisePrescription.muscle_group,
202
+ category: exercisePrescription.category,
203
+ sets: trainerPreset.settings.sets[exports.frequencyMap[selectedDays]][selectedGoal],
204
+ warmupSetCount: exercisePrescription.warmup_set_count,
205
+ repRangeStart: trainerPreset.settings.rep_ranges[selectedGoal][exercisePrescription.category].rep_range_start,
206
+ repRangeEnd: trainerPreset.settings.rep_ranges[selectedGoal][exercisePrescription.category].rep_range_end,
207
+ restTimerSeconds: trainerPreset.settings.rest_timers[selectedGoal][exercisePrescription.category],
208
+ notes: (_a = trainerPreset.settings.exercise_notes[exercise.id]) !== null && _a !== void 0 ? _a : '',
209
+ });
210
+ }
211
+ else {
212
+ // Collect error instead of throwing
213
+ allErrors.push({
214
+ type: 'exercise_not_found',
215
+ prescription: exercisePrescription,
216
+ muscleGroup,
217
+ context: {
218
+ goal: selectedGoal,
219
+ level: selectedLevel,
220
+ equipments: selectedEquipments,
221
+ focusMuscle,
222
+ },
223
+ });
224
+ }
225
+ }
226
+ program.routines.push({
227
+ name: routine,
228
+ notes: routineTemplate.notes,
229
+ exercises: routineExercises,
230
+ });
231
+ }
232
+ // Return result based on whether there were errors
233
+ if (allErrors.length > 0) {
234
+ return {
235
+ success: false,
236
+ errors: allErrors,
237
+ partialProgram: program.routines.length > 0 ? program : undefined,
238
+ };
239
+ }
240
+ return {
241
+ success: true,
242
+ program,
243
+ };
244
+ };
245
+ exports.generateProgram = generateProgram;
package/built/index.d.ts CHANGED
@@ -17,7 +17,7 @@ export * from './routineUtils';
17
17
  export * from './typeUtils';
18
18
  export * from './async';
19
19
  export * from './adminPermissions';
20
- export * from './adjustEventTokens';
20
+ export * from './hevyTrainer';
21
21
  export declare const supportedLanguages: readonly ["en", "es", "de", "fr", "it", "pt", "tr", "zh_CN", "zh_TW", "ru", "ja", "ko"];
22
22
  export type Language = Lookup<typeof supportedLanguages>;
23
23
  export declare const isLanguage: (x: string) => x is Language;
@@ -73,6 +73,7 @@ export interface AccountResponse {
73
73
  is_coached: boolean;
74
74
  birthday?: string;
75
75
  sex?: Sex;
76
+ height_cm?: number;
76
77
  }
77
78
  export interface UserAccountResponse {
78
79
  id: string;
@@ -107,6 +108,7 @@ export interface UserAccountResponse {
107
108
  sex?: Sex;
108
109
  email_consent: boolean;
109
110
  email_verified: boolean;
111
+ height_cm?: number;
110
112
  }
111
113
  export interface CoachAppPushTarget {
112
114
  type: 'android' | 'ios';
@@ -161,6 +163,7 @@ export interface AccountUpdate {
161
163
  accepted_terms_and_conditions?: boolean;
162
164
  sex?: Sex;
163
165
  birthday?: string;
166
+ height_cm?: number;
164
167
  }
165
168
  export interface AppleSignUpRequest {
166
169
  email?: string;
@@ -556,18 +559,19 @@ export declare const coreMuscles: readonly ["abdominals"];
556
559
  export declare const shoulderMuscles: readonly ["shoulders"];
557
560
  export declare const armMuscles: readonly ["biceps", "triceps", "forearms"];
558
561
  export declare const legMuscles: readonly ["quadriceps", "hamstrings", "calves", "glutes", "abductors", "adductors"];
559
- export declare const backMuscles: readonly ["lats", "traps", "lower_back", "upper_back"];
562
+ export declare const backMuscles: readonly ["lats", "upper_back", "traps", "lower_back"];
560
563
  export declare const chestMuscles: readonly ["chest"];
561
564
  export declare const miscellaneousMuscles: readonly ["cardio", "neck", "full_body", "other"];
562
565
  export declare const simplifiedMuscleGroups: readonly ["core", "shoulders", "arms", "legs", "back", "chest"];
563
566
  export type SimplifiedMuscleGroup = Lookup<typeof simplifiedMuscleGroups>;
564
567
  export declare const isSimplifiedMuscleGroup: (x: string) => x is SimplifiedMuscleGroup;
565
- export declare const muscleGroups: readonly ["abdominals", "shoulders", "biceps", "triceps", "forearms", "quadriceps", "hamstrings", "calves", "glutes", "abductors", "adductors", "lats", "traps", "lower_back", "upper_back", "chest", "cardio", "neck", "full_body", "other"];
568
+ export declare const muscleGroups: readonly ["abdominals", "shoulders", "biceps", "triceps", "forearms", "quadriceps", "hamstrings", "calves", "glutes", "abductors", "adductors", "lats", "upper_back", "traps", "lower_back", "chest", "cardio", "neck", "full_body", "other"];
566
569
  export type MuscleGroup = Lookup<typeof muscleGroups>;
567
570
  export declare const isMuscleGroup: (x: string) => x is MuscleGroup;
568
- export declare const muscleGroupFilters: readonly ["all_muscles", "abdominals", "shoulders", "biceps", "triceps", "forearms", "quadriceps", "hamstrings", "calves", "glutes", "abductors", "adductors", "lats", "traps", "lower_back", "upper_back", "chest", "cardio", "neck", "full_body", "other"];
571
+ export declare const muscleGroupFilters: readonly ["all_muscles", "abdominals", "shoulders", "biceps", "triceps", "forearms", "quadriceps", "hamstrings", "calves", "glutes", "abductors", "adductors", "lats", "upper_back", "traps", "lower_back", "chest", "cardio", "neck", "full_body", "other"];
569
572
  export type MuscleGroupFilter = Lookup<typeof muscleGroupFilters>;
570
573
  export declare const isMuscleGroupFilter: (x: string) => x is MuscleGroupFilter;
574
+ export declare const simplifiedMuscleGroupToMuscleGroups: Record<SimplifiedMuscleGroup, readonly MuscleGroup[]>;
571
575
  /**
572
576
  * Equipment
573
577
  */
@@ -1194,6 +1198,8 @@ export interface OutstandingInvitesForCoachTeamResponse {
1194
1198
  invites: CoachTeamInvite[];
1195
1199
  }
1196
1200
  export interface HevyTrainerProgram {
1201
+ created_at: string;
1202
+ updated_at: string;
1197
1203
  title: string;
1198
1204
  level: TrainingLevel;
1199
1205
  goal: TrainingGoal;
@@ -1439,9 +1445,6 @@ export interface UserMetadataRequest {
1439
1445
  platformVersion: string;
1440
1446
  appVersion: string;
1441
1447
  securityId?: string;
1442
- googleAdId?: string;
1443
- appleIdfv?: string;
1444
- adjustAdId?: string;
1445
1448
  }
1446
1449
  export type NetworkType = 'wifi' | 'cellular' | 'unknown';
1447
1450
  export interface UserMetadataResponse {
@@ -1455,10 +1458,6 @@ export interface UserMetadataResponse {
1455
1458
  geoip_city: string | null;
1456
1459
  geoip_timezone: string | null;
1457
1460
  security_id: string | null;
1458
- adjust_adid: string | null;
1459
- google_adid: string | null;
1460
- apple_idfv: string | null;
1461
- last_ip: string | null;
1462
1461
  }
1463
1462
  export interface NetworkInfoRequest {
1464
1463
  networkType: NetworkType;
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.measurementsList = exports.isWorkoutBiometrics = exports.isHeartRateSamples = exports.isPublicWorkout = exports.isSetType = exports.isRPE = exports.validRpeValues = exports.isSetPersonalRecordType = exports.supportedInstructionsLanguages = exports.weeklyTrainingFrequencies = 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.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.isCoachRole = exports.isErrorResponse = exports.isLivePRVolumeOption = exports.isTimerVolumeOption = exports.isWeekday = exports.orderedWeekdays = exports.isBodyMeasurementUnit = exports.isDistanceUnitShort = exports.isDistanceUnit = exports.isWeightUnit = exports.isLanguage = exports.supportedLanguages = void 0;
18
- exports.isSuggestedUserSource = exports.isValidUserWorkoutMetricsType = exports.isBodyMeasurementKey = void 0;
17
+ exports.isWorkoutBiometrics = exports.isHeartRateSamples = exports.isPublicWorkout = exports.isSetType = exports.isRPE = exports.validRpeValues = exports.isSetPersonalRecordType = exports.supportedInstructionsLanguages = exports.weeklyTrainingFrequencies = 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.isCoachRole = exports.isErrorResponse = exports.isLivePRVolumeOption = exports.isTimerVolumeOption = exports.isWeekday = exports.orderedWeekdays = exports.isBodyMeasurementUnit = exports.isDistanceUnitShort = exports.isDistanceUnit = exports.isWeightUnit = exports.isLanguage = exports.supportedLanguages = void 0;
18
+ exports.isSuggestedUserSource = exports.isValidUserWorkoutMetricsType = exports.isBodyMeasurementKey = exports.measurementsList = void 0;
19
19
  const typeUtils_1 = require("./typeUtils");
20
20
  __exportStar(require("./constants"), exports);
21
21
  __exportStar(require("./utils"), exports);
@@ -35,7 +35,7 @@ __exportStar(require("./routineUtils"), exports);
35
35
  __exportStar(require("./typeUtils"), exports);
36
36
  __exportStar(require("./async"), exports);
37
37
  __exportStar(require("./adminPermissions"), exports);
38
- __exportStar(require("./adjustEventTokens"), exports);
38
+ __exportStar(require("./hevyTrainer"), exports);
39
39
  exports.supportedLanguages = [
40
40
  'en',
41
41
  'es',
@@ -119,9 +119,9 @@ exports.legMuscles = [
119
119
  ];
120
120
  exports.backMuscles = [
121
121
  'lats',
122
+ 'upper_back',
122
123
  'traps',
123
124
  'lower_back',
124
- 'upper_back',
125
125
  ];
126
126
  exports.chestMuscles = ['chest'];
127
127
  exports.miscellaneousMuscles = [
@@ -154,6 +154,14 @@ exports.isMuscleGroup = isMuscleGroup;
154
154
  exports.muscleGroupFilters = ['all_muscles', ...exports.muscleGroups];
155
155
  const isMuscleGroupFilter = (x) => (0, typeUtils_1.isInArray)(x, exports.muscleGroupFilters);
156
156
  exports.isMuscleGroupFilter = isMuscleGroupFilter;
157
+ exports.simplifiedMuscleGroupToMuscleGroups = {
158
+ chest: exports.chestMuscles,
159
+ shoulders: exports.shoulderMuscles,
160
+ back: exports.backMuscles,
161
+ arms: exports.armMuscles,
162
+ legs: exports.legMuscles,
163
+ core: exports.coreMuscles,
164
+ };
157
165
  /**
158
166
  * Equipment
159
167
  */
@@ -30,3 +30,8 @@ export type Some<T> = {
30
30
  * ```
31
31
  */
32
32
  export declare const dangerousUncheckedTypeCast: <T = void, U extends T = T>(value: unknown) => U;
33
+ /**
34
+ * Same as `array[index]`, but adds `undefined` to the return type. Maybe some
35
+ * fine day we will enable `noUncheckedIndexedAccess` in all our projects. 🤞
36
+ */
37
+ export declare const typeSafeIndex: <T>(array: T[], index: number) => T | undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dangerousUncheckedTypeCast = exports.exhaustiveTypeException = exports.exhaustiveTypeCheck = exports.isInArray = void 0;
3
+ exports.typeSafeIndex = exports.dangerousUncheckedTypeCast = exports.exhaustiveTypeException = exports.exhaustiveTypeCheck = exports.isInArray = void 0;
4
4
  const isInArray = (value, array) => array.includes(value);
5
5
  exports.isInArray = isInArray;
6
6
  const exhaustiveTypeCheck = (_) => void _;
@@ -30,3 +30,9 @@ exports.exhaustiveTypeException = exhaustiveTypeException;
30
30
  */
31
31
  const dangerousUncheckedTypeCast = (value) => value;
32
32
  exports.dangerousUncheckedTypeCast = dangerousUncheckedTypeCast;
33
+ /**
34
+ * Same as `array[index]`, but adds `undefined` to the return type. Maybe some
35
+ * fine day we will enable `noUncheckedIndexedAccess` in all our projects. 🤞
36
+ */
37
+ const typeSafeIndex = (array, index) => array[index];
38
+ exports.typeSafeIndex = typeSafeIndex;
package/built/utils.d.ts CHANGED
@@ -14,6 +14,11 @@ export declare const roundToTwoDecimal: (value: number) => number;
14
14
  export declare const roundToOneDecimal: (value: number) => number;
15
15
  export declare const roundToWholeNumber: (value: number) => number;
16
16
  export declare const isValidUsername: (username: string) => boolean;
17
+ export declare const secondsToClockParts: (totalSeconds: number) => {
18
+ hours: number;
19
+ minutes: number;
20
+ seconds: number;
21
+ };
17
22
  /**
18
23
  * 01:25
19
24
  * 02:25:36
package/built/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getYoutubeVideoId = exports.validateYoutubeUrl = exports.splitAtUsernamesAndLinks = exports.isVersionAGreaterOrEqualToVersionB = exports.generateUserGroupValue = exports.generateUserGroup = exports.isBaseExerciseTemplate = exports.getStrengthLevelFromPercentile = exports.numberToLocaleString = exports.numberWithCommas = exports.setVolume = exports.oneRepMax = exports.oneRepMaxPercentageMap = exports.workoutSetCount = exports.userExerciseSetWeight = exports.workoutDistanceMeters = exports.workoutReps = exports.workoutDurationSeconds = exports.removeAccents = exports.getClosestDataPointAroundTargetDate = exports.getClosestDataPointBeforeTargetDate = exports.findMapped = exports.stringToNumber = exports.forceStringToNumber = exports.formatDurationInput = exports.isValidFormattedTime = exports.isWholeNumber = exports.isNumber = exports.isValidUuid = exports.isValidPhoneNumber = exports.isValidWebUrl = exports.URL_REGEX = exports.isValidEmail = exports.secondsToWordFormatMinutes = exports.secondsToWordFormat = exports.secondsToClockFormat = exports.isValidUsername = exports.roundToWholeNumber = exports.roundToOneDecimal = exports.roundToTwoDecimal = exports.divide = exports.clampNumber = exports.num = void 0;
3
+ exports.getYoutubeVideoId = exports.validateYoutubeUrl = exports.splitAtUsernamesAndLinks = exports.isVersionAGreaterOrEqualToVersionB = exports.generateUserGroupValue = exports.generateUserGroup = exports.isBaseExerciseTemplate = exports.getStrengthLevelFromPercentile = exports.numberToLocaleString = exports.numberWithCommas = exports.setVolume = exports.oneRepMax = exports.oneRepMaxPercentageMap = exports.workoutSetCount = exports.userExerciseSetWeight = exports.workoutDistanceMeters = exports.workoutReps = exports.workoutDurationSeconds = exports.removeAccents = exports.getClosestDataPointAroundTargetDate = exports.getClosestDataPointBeforeTargetDate = exports.findMapped = exports.stringToNumber = exports.forceStringToNumber = exports.formatDurationInput = exports.isValidFormattedTime = exports.isWholeNumber = exports.isNumber = exports.isValidUuid = exports.isValidPhoneNumber = exports.isValidWebUrl = exports.URL_REGEX = exports.isValidEmail = exports.secondsToWordFormatMinutes = exports.secondsToWordFormat = exports.secondsToClockFormat = exports.secondsToClockParts = exports.isValidUsername = exports.roundToWholeNumber = exports.roundToOneDecimal = exports.roundToTwoDecimal = exports.divide = exports.clampNumber = exports.num = void 0;
4
4
  /**
5
5
  * Doesn't matter what you throw in the function it'll
6
6
  * always return a number. Non number values will return
@@ -47,6 +47,13 @@ const isValidUsername = (username) => {
47
47
  return re.test(username);
48
48
  };
49
49
  exports.isValidUsername = isValidUsername;
50
+ const secondsToClockParts = (totalSeconds) => {
51
+ const hours = Math.floor(totalSeconds / 3600);
52
+ const minutes = Math.floor((totalSeconds - hours * 3600) / 60);
53
+ const seconds = totalSeconds - hours * 3600 - minutes * 60;
54
+ return { hours, minutes, seconds };
55
+ };
56
+ exports.secondsToClockParts = secondsToClockParts;
50
57
  /**
51
58
  * 01:25
52
59
  * 02:25:36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hevy-shared",
3
- "version": "1.0.706",
3
+ "version": "1.0.708",
4
4
  "description": "",
5
5
  "main": "built/index.js",
6
6
  "types": "built/index.d.ts",
@@ -1,15 +0,0 @@
1
- /**
2
- * Manage adjust events at https://suite.adjust.com/apps/na3q7q6avq4g/events
3
- */
4
- export declare const ADJUST_EVENT_TOKENS: {
5
- logWorkout: string;
6
- purchase: string;
7
- signupComplete: string;
8
- updateSexMale: string;
9
- updateSexFemale: string;
10
- updateSexOther: string;
11
- updateAge18Through28: string;
12
- updateAge29Through44: string;
13
- updateAge45AndUp: string;
14
- };
15
- export type AdjustEventToken = typeof ADJUST_EVENT_TOKENS[keyof typeof ADJUST_EVENT_TOKENS];
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ADJUST_EVENT_TOKENS = void 0;
4
- /**
5
- * Manage adjust events at https://suite.adjust.com/apps/na3q7q6avq4g/events
6
- */
7
- exports.ADJUST_EVENT_TOKENS = {
8
- logWorkout: 'e3xe9l',
9
- purchase: 'qf1l8r',
10
- signupComplete: 'n46d1z',
11
- updateSexMale: 'kbdp5b',
12
- updateSexFemale: 'jkkjka',
13
- updateSexOther: 'z4awr3',
14
- updateAge18Through28: 'o5f1gc',
15
- updateAge29Through44: 'vvhb17',
16
- updateAge45AndUp: '3meyo6',
17
- };