hevy-shared 1.0.1019 → 1.0.1021
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/index.d.ts +6 -227
- package/built/index.js +3 -7
- package/built/routineUtils.d.ts +1 -2
- package/built/tests/testUtils.d.ts +1 -2
- package/built/tests/testUtils.js +1 -1
- package/built/workout/index.d.ts +12 -0
- package/built/workout/index.js +21 -0
- package/built/{normalizedWorkoutUtils.d.ts → workout/normalizedWorkout.d.ts} +2 -2
- package/built/{normalizedWorkoutUtils.js → workout/normalizedWorkout.js} +2 -2
- package/built/workout/postWorkoutRequest.d.ts +77 -0
- package/built/workout/postWorkoutRequest.js +2 -0
- package/built/workout/publicWorkout.d.ts +93 -0
- package/built/workout/publicWorkout.js +7 -0
- package/built/workout/userWorkout.d.ts +130 -0
- package/built/workout/userWorkout.js +2 -0
- package/built/workout/workout.d.ts +120 -0
- package/built/workout/workout.js +2 -0
- package/package.json +1 -1
package/built/index.d.ts
CHANGED
|
@@ -2,12 +2,14 @@ import { InstructionsLanguage } from './exerciseLocaleUtils';
|
|
|
2
2
|
import { WorkoutDurationMinutes } from './hevyTrainer';
|
|
3
3
|
import { BugReportQuestionSchema, CreateBugReportRequestBodySchema, postEmailBackofficeSchema } from './schemas';
|
|
4
4
|
import { Language } from './translations';
|
|
5
|
-
import { Lookup
|
|
5
|
+
import { Lookup } from './typeUtils';
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
+
import { UserWorkout } from './workout';
|
|
7
8
|
export * from './schemas';
|
|
8
9
|
export * from './constants';
|
|
9
10
|
export * from './utils';
|
|
10
11
|
export * from './units';
|
|
12
|
+
export * from './workout';
|
|
11
13
|
export * from './filterExercises';
|
|
12
14
|
export * from './setIndicatorUtils';
|
|
13
15
|
export * from './workoutVolume';
|
|
@@ -18,7 +20,6 @@ export * from './cue';
|
|
|
18
20
|
export * from './muscleHeatmaps';
|
|
19
21
|
export * from './muscleSplits';
|
|
20
22
|
export * from './notifications';
|
|
21
|
-
export * from './normalizedWorkoutUtils';
|
|
22
23
|
export * from './routineUtils';
|
|
23
24
|
export * from './typeUtils';
|
|
24
25
|
export * from './async';
|
|
@@ -599,7 +600,7 @@ export interface PublicUserProfile {
|
|
|
599
600
|
following_count: number;
|
|
600
601
|
routines: RoutineMetadata[];
|
|
601
602
|
weekly_workout_durations: WeeklyWorkoutDuration[];
|
|
602
|
-
last_workout?:
|
|
603
|
+
last_workout?: UserWorkout;
|
|
603
604
|
}
|
|
604
605
|
export declare const coreMuscles: readonly ["abdominals"];
|
|
605
606
|
export declare const shoulderMuscles: readonly ["shoulders"];
|
|
@@ -745,76 +746,6 @@ export interface RepRange {
|
|
|
745
746
|
start: number | null;
|
|
746
747
|
end: number | null;
|
|
747
748
|
}
|
|
748
|
-
export interface WorkoutExerciseSet {
|
|
749
|
-
/**
|
|
750
|
-
* id can be a string or a number because we used
|
|
751
|
-
* to store it as int4 and now we store it as int8
|
|
752
|
-
* which is too big to store (accurately) in a JS
|
|
753
|
-
* number.
|
|
754
|
-
*/
|
|
755
|
-
id: number | string;
|
|
756
|
-
index: number;
|
|
757
|
-
indicator: SetType;
|
|
758
|
-
weight_kg?: number | null;
|
|
759
|
-
reps?: number | null;
|
|
760
|
-
distance_meters?: number | null;
|
|
761
|
-
duration_seconds?: number | null;
|
|
762
|
-
custom_metric?: number | null;
|
|
763
|
-
rpe?: RPE | null;
|
|
764
|
-
/**
|
|
765
|
-
* @deprecated 1.29.17 -
|
|
766
|
-
* we can only set this to `best_weight`, `best_reps`, `best_duration` or
|
|
767
|
-
* `best_distance`. sending anything else would cause older clients to crash.
|
|
768
|
-
* newer clients will ignore this field and use the `prs` field instead.
|
|
769
|
-
*/
|
|
770
|
-
personalRecords?: Array<{
|
|
771
|
-
type: 'best_weight' | 'best_reps' | 'best_duration' | 'best_distance';
|
|
772
|
-
value: number;
|
|
773
|
-
}>;
|
|
774
|
-
prs: {
|
|
775
|
-
type: SetPersonalRecordType;
|
|
776
|
-
value: number;
|
|
777
|
-
}[];
|
|
778
|
-
completed_at: string | null;
|
|
779
|
-
}
|
|
780
|
-
export interface WorkoutExercise {
|
|
781
|
-
id: string;
|
|
782
|
-
exercise_template_id: string;
|
|
783
|
-
title: string;
|
|
784
|
-
es_title?: string | null;
|
|
785
|
-
de_title?: string | null;
|
|
786
|
-
fr_title?: string | null;
|
|
787
|
-
it_title?: string | null;
|
|
788
|
-
pt_title?: string | null;
|
|
789
|
-
ko_title?: string | null;
|
|
790
|
-
ja_title?: string | null;
|
|
791
|
-
tr_title?: string | null;
|
|
792
|
-
ru_title?: string | null;
|
|
793
|
-
zh_cn_title?: string | null;
|
|
794
|
-
zh_tw_title?: string | null;
|
|
795
|
-
superset_id: number | null;
|
|
796
|
-
rest_seconds: number | null;
|
|
797
|
-
notes: string;
|
|
798
|
-
priority: number;
|
|
799
|
-
muscle_group: MuscleGroup;
|
|
800
|
-
other_muscles: MuscleGroup[];
|
|
801
|
-
exercise_type: ExerciseType;
|
|
802
|
-
equipment_category: Equipment;
|
|
803
|
-
url?: string;
|
|
804
|
-
media_type?: string;
|
|
805
|
-
custom_exercise_image_url?: string | null;
|
|
806
|
-
thumbnail_url?: string | null;
|
|
807
|
-
manual_tag?: string;
|
|
808
|
-
aka?: string;
|
|
809
|
-
/**
|
|
810
|
-
* for exercises with two dumbbells
|
|
811
|
-
*
|
|
812
|
-
* `true` if the weight of each set is the weight of _one_ dumbbell, but the
|
|
813
|
-
* exercise was performed with _two_ dumbbells of that weight
|
|
814
|
-
*/
|
|
815
|
-
volume_doubling_enabled: boolean;
|
|
816
|
-
sets: WorkoutExerciseSet[];
|
|
817
|
-
}
|
|
818
749
|
export interface WorkoutComment {
|
|
819
750
|
id: number;
|
|
820
751
|
username: string;
|
|
@@ -841,55 +772,6 @@ export type PreviewWorkoutLike = {
|
|
|
841
772
|
username: string;
|
|
842
773
|
profile_pic: string;
|
|
843
774
|
};
|
|
844
|
-
export interface Workout {
|
|
845
|
-
id: string;
|
|
846
|
-
short_id: string | null;
|
|
847
|
-
index: number;
|
|
848
|
-
name: string;
|
|
849
|
-
description?: string;
|
|
850
|
-
like_count: number;
|
|
851
|
-
/** @deprecated 2.3.4 */
|
|
852
|
-
like_images: string[];
|
|
853
|
-
preview_workout_likes: PreviewWorkoutLike[];
|
|
854
|
-
comment_count: number;
|
|
855
|
-
comments: WorkoutComment[];
|
|
856
|
-
/** @deprecated 1.28.13 */
|
|
857
|
-
image_urls?: string[];
|
|
858
|
-
media: WorkoutMedia[];
|
|
859
|
-
is_liked_by_user: boolean;
|
|
860
|
-
start_time: number;
|
|
861
|
-
end_time: number;
|
|
862
|
-
user_id: string;
|
|
863
|
-
username: string;
|
|
864
|
-
profile_image: string;
|
|
865
|
-
exercises: WorkoutExercise[];
|
|
866
|
-
routine_id?: string;
|
|
867
|
-
apple_watch: boolean;
|
|
868
|
-
wearos_watch: boolean;
|
|
869
|
-
verified: boolean;
|
|
870
|
-
created_at: string;
|
|
871
|
-
updated_at: string;
|
|
872
|
-
nth_workout: number;
|
|
873
|
-
/**
|
|
874
|
-
* See https://github.com/hevyapp/hevy-backend/pull/193 to understand
|
|
875
|
-
* why we added estimated_volume_kg
|
|
876
|
-
*/
|
|
877
|
-
estimated_volume_kg: number;
|
|
878
|
-
/**
|
|
879
|
-
* Whether to include warmup sets in various calculations.
|
|
880
|
-
* https://github.com/hevyapp/hevy-shared/pull/312
|
|
881
|
-
*/
|
|
882
|
-
include_warmup_sets: boolean;
|
|
883
|
-
is_private: boolean;
|
|
884
|
-
/**
|
|
885
|
-
* If applicable, the user ID of the coach who logged this workout
|
|
886
|
-
*/
|
|
887
|
-
logged_by_coach_id?: string;
|
|
888
|
-
biometrics?: WorkoutBiometrics;
|
|
889
|
-
is_biometrics_public: boolean;
|
|
890
|
-
trainer_program_id: string | undefined;
|
|
891
|
-
gym: TODO<Gym> | undefined;
|
|
892
|
-
}
|
|
893
775
|
export interface CustomExerciseImage {
|
|
894
776
|
type: 'image';
|
|
895
777
|
image_url: string;
|
|
@@ -900,76 +782,6 @@ export interface CustomExerciseVideo {
|
|
|
900
782
|
video_preview_image_url: string;
|
|
901
783
|
}
|
|
902
784
|
export type CustomExerciseMedia = CustomExerciseImage | CustomExerciseVideo;
|
|
903
|
-
export declare const isPublicWorkout: (x: any) => x is PublicWorkout;
|
|
904
|
-
export interface PublicWorkout {
|
|
905
|
-
type: 'public';
|
|
906
|
-
id: string;
|
|
907
|
-
short_id: string | null;
|
|
908
|
-
name: string;
|
|
909
|
-
create_at: string;
|
|
910
|
-
start_time: number;
|
|
911
|
-
end_time: number;
|
|
912
|
-
username: string;
|
|
913
|
-
profile_image: string | null;
|
|
914
|
-
preview_image: string | null;
|
|
915
|
-
is_private: boolean;
|
|
916
|
-
exercises: WorkoutExercise[];
|
|
917
|
-
/**
|
|
918
|
-
* weight_unit and distance_unit are the current unit
|
|
919
|
-
* preferences of the owner of the workout.
|
|
920
|
-
*/
|
|
921
|
-
weight_unit: WeightUnit;
|
|
922
|
-
distance_unit: DistanceUnit;
|
|
923
|
-
estimated_volume_kg: number;
|
|
924
|
-
}
|
|
925
|
-
export interface WorkoutSync {
|
|
926
|
-
updated: Workout[];
|
|
927
|
-
deleted: string[];
|
|
928
|
-
isMore: boolean;
|
|
929
|
-
updated_at?: string;
|
|
930
|
-
}
|
|
931
|
-
export interface PostWorkoutRequest {
|
|
932
|
-
workout: PostWorkoutRequestWorkout;
|
|
933
|
-
/**
|
|
934
|
-
* `source` is set by import-workout-data (currently only supports imports from Strong)
|
|
935
|
-
* and for workouts that come from the public API.
|
|
936
|
-
* This prop gives us visibility into workouts that aren't logged within Hevy. Currently,
|
|
937
|
-
* it's used to filter the feed so users aren't spammed by workouts created programmatically.
|
|
938
|
-
*/
|
|
939
|
-
source?: 'strong' | 'public-api';
|
|
940
|
-
share_to_strava?: boolean;
|
|
941
|
-
/**
|
|
942
|
-
* Fake UTC format (ISO string of user's _local_ time, but with 'Z' as the
|
|
943
|
-
* time zone), since that is what Strava expects. 🤦♂️
|
|
944
|
-
* https://developers.strava.com/docs/reference/#api-Activities-createActivity
|
|
945
|
-
*/
|
|
946
|
-
strava_activity_local_time?: string;
|
|
947
|
-
}
|
|
948
|
-
export interface PostClientsWorkoutRequest {
|
|
949
|
-
workout: PostWorkoutRequestWorkout;
|
|
950
|
-
updateRoutineValues: boolean;
|
|
951
|
-
}
|
|
952
|
-
/**
|
|
953
|
-
* PostWorkoutRequestWorkout describes the final state of a completed workout.
|
|
954
|
-
* It's used when sending a workout to the server.
|
|
955
|
-
*/
|
|
956
|
-
export interface PostWorkoutRequestWorkout {
|
|
957
|
-
title: string;
|
|
958
|
-
description: string;
|
|
959
|
-
media: WorkoutMedia[];
|
|
960
|
-
start_time: number;
|
|
961
|
-
end_time: number;
|
|
962
|
-
exercises: PostWorkoutRequestExercise[];
|
|
963
|
-
routine_id?: string;
|
|
964
|
-
apple_watch: boolean;
|
|
965
|
-
wearos_watch: boolean;
|
|
966
|
-
workout_id: string;
|
|
967
|
-
is_private: boolean;
|
|
968
|
-
biometrics?: WorkoutBiometrics;
|
|
969
|
-
is_biometrics_public: boolean;
|
|
970
|
-
trainer_program_id: string | undefined;
|
|
971
|
-
gym: TODO<Gym> | undefined;
|
|
972
|
-
}
|
|
973
785
|
export type WorkoutDataImporterReport = {
|
|
974
786
|
state: 'idle';
|
|
975
787
|
} | {
|
|
@@ -994,40 +806,6 @@ export interface HeartRateSample {
|
|
|
994
806
|
timestamp_ms: number;
|
|
995
807
|
bpm: number;
|
|
996
808
|
}
|
|
997
|
-
export interface PostWorkoutRequestExercise {
|
|
998
|
-
title: string;
|
|
999
|
-
exercise_template_id: string;
|
|
1000
|
-
superset_id?: number;
|
|
1001
|
-
rest_timer_seconds?: number;
|
|
1002
|
-
notes: string;
|
|
1003
|
-
/**
|
|
1004
|
-
* for exercises with two dumbbells
|
|
1005
|
-
*
|
|
1006
|
-
* `true` if the weight of each set is the weight of _one_ dumbbell, but the
|
|
1007
|
-
* exercise was performed with _two_ dumbbells of that weight
|
|
1008
|
-
*/
|
|
1009
|
-
volume_doubling_enabled?: boolean;
|
|
1010
|
-
sets: PostWorkoutRequestSet[];
|
|
1011
|
-
}
|
|
1012
|
-
export interface PostWorkoutRequestSet {
|
|
1013
|
-
index: number;
|
|
1014
|
-
type: SetType;
|
|
1015
|
-
weight_kg?: number;
|
|
1016
|
-
reps?: number;
|
|
1017
|
-
distance_meters?: number;
|
|
1018
|
-
duration_seconds?: number;
|
|
1019
|
-
custom_metric?: number;
|
|
1020
|
-
rpe?: RPE;
|
|
1021
|
-
completed_at?: string;
|
|
1022
|
-
}
|
|
1023
|
-
/**
|
|
1024
|
-
* Used to update an existing workout. Props that are defined will be used to
|
|
1025
|
-
* update the corresponding values of the workout in the database, and those
|
|
1026
|
-
* that are undefined will not be changed.
|
|
1027
|
-
*/
|
|
1028
|
-
export type UpdateWorkoutRequestWorkout = Partial<Pick<PostWorkoutRequestWorkout, 'title' | 'description' | 'media' | 'exercises' | 'is_private' | 'is_biometrics_public'>> & {
|
|
1029
|
-
start_and_end_time?: Required<Pick<PostWorkoutRequestWorkout, 'start_time' | 'end_time'>>;
|
|
1030
|
-
};
|
|
1031
809
|
/** Routines */
|
|
1032
810
|
export interface RoutineSet {
|
|
1033
811
|
index: number;
|
|
@@ -1627,7 +1405,8 @@ export type CommercialGym = {
|
|
|
1627
1405
|
name: string;
|
|
1628
1406
|
fullAddress: string;
|
|
1629
1407
|
city: string;
|
|
1630
|
-
|
|
1408
|
+
latitude: number;
|
|
1409
|
+
longitude: number;
|
|
1631
1410
|
};
|
|
1632
1411
|
export type HomeGym = {
|
|
1633
1412
|
type: 'home';
|
package/built/index.js
CHANGED
|
@@ -14,13 +14,14 @@ 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 = exports.isHevyTrainerRoutine = exports.isWorkoutBiometrics =
|
|
17
|
+
exports.isHeartRateSamples = exports.isSetType = exports.isRPE = exports.validRpeValues = exports.isSetPersonalRecordType = exports.weeklyTrainingFrequencies = exports.isGranularEquipment = exports.granularEquipments = exports.hevyTrainerProgramEquipments = exports.cardioPreferences = exports.restTimerLengths = 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("./schemas"), exports);
|
|
21
21
|
__exportStar(require("./constants"), exports);
|
|
22
22
|
__exportStar(require("./utils"), exports);
|
|
23
23
|
__exportStar(require("./units"), exports);
|
|
24
|
+
__exportStar(require("./workout"), exports);
|
|
24
25
|
__exportStar(require("./filterExercises"), exports);
|
|
25
26
|
__exportStar(require("./setIndicatorUtils"), exports);
|
|
26
27
|
__exportStar(require("./workoutVolume"), exports);
|
|
@@ -31,7 +32,6 @@ __exportStar(require("./cue"), exports);
|
|
|
31
32
|
__exportStar(require("./muscleHeatmaps"), exports);
|
|
32
33
|
__exportStar(require("./muscleSplits"), exports);
|
|
33
34
|
__exportStar(require("./notifications"), exports);
|
|
34
|
-
__exportStar(require("./normalizedWorkoutUtils"), exports);
|
|
35
35
|
__exportStar(require("./routineUtils"), exports);
|
|
36
36
|
__exportStar(require("./typeUtils"), exports);
|
|
37
37
|
__exportStar(require("./async"), exports);
|
|
@@ -296,10 +296,6 @@ exports.isRPE = isRPE;
|
|
|
296
296
|
const _setTypes = ['warmup', 'normal', 'failure', 'dropset'];
|
|
297
297
|
const isSetType = (x) => (0, typeUtils_1.isInArray)(x, _setTypes);
|
|
298
298
|
exports.isSetType = isSetType;
|
|
299
|
-
const isPublicWorkout = (x) => {
|
|
300
|
-
return x.type === 'public';
|
|
301
|
-
};
|
|
302
|
-
exports.isPublicWorkout = isPublicWorkout;
|
|
303
299
|
const isHeartRateSamples = (x) => {
|
|
304
300
|
if (!x || !Array.isArray(x))
|
|
305
301
|
return false;
|
package/built/routineUtils.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { BaseRoutine, HevyTrainerRoutine, RoutineUpdate } from '.';
|
|
2
|
-
import { NormalizedWorkout } from './normalizedWorkoutUtils';
|
|
1
|
+
import { BaseRoutine, HevyTrainerRoutine, NormalizedWorkout, RoutineUpdate } from '.';
|
|
3
2
|
export declare const majorRoutineUpdate: (routine: BaseRoutine, workout: NormalizedWorkout) => RoutineUpdate;
|
|
4
3
|
export declare const minorRoutineUpdate: (routine: BaseRoutine, workout: NormalizedWorkout) => RoutineUpdate;
|
|
5
4
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ExerciseType, RPE, RepRange, Routine, RoutineExercise, RoutineUpdate, RoutineUpdateExercise, SetType } from '..';
|
|
2
|
-
import { NormalizedExercise, NormalizedWorkout } from '../normalizedWorkoutUtils';
|
|
1
|
+
import { ExerciseType, NormalizedExercise, NormalizedWorkout, RPE, RepRange, Routine, RoutineExercise, RoutineUpdate, RoutineUpdateExercise, SetType } from '..';
|
|
3
2
|
interface RoutineBuilderScope {
|
|
4
3
|
nextExerciseId: () => string;
|
|
5
4
|
}
|
package/built/tests/testUtils.js
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Workout } from './workout';
|
|
2
|
+
export * from './workout';
|
|
3
|
+
export * from './userWorkout';
|
|
4
|
+
export * from './publicWorkout';
|
|
5
|
+
export * from './normalizedWorkout';
|
|
6
|
+
export * from './postWorkoutRequest';
|
|
7
|
+
export interface WorkoutSync {
|
|
8
|
+
updated: Workout[];
|
|
9
|
+
deleted: string[];
|
|
10
|
+
isMore: boolean;
|
|
11
|
+
updated_at?: string;
|
|
12
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./workout"), exports);
|
|
18
|
+
__exportStar(require("./userWorkout"), exports);
|
|
19
|
+
__exportStar(require("./publicWorkout"), exports);
|
|
20
|
+
__exportStar(require("./normalizedWorkout"), exports);
|
|
21
|
+
__exportStar(require("./postWorkoutRequest"), exports);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExerciseType,
|
|
1
|
+
import { ExerciseType, RPE, SetType, ShareToPlatform, WorkoutBiometrics, WorkoutMedia, WorkoutVisibility } from '..';
|
|
2
2
|
/**
|
|
3
3
|
* Events are used to determine the start time, end time and duration of a
|
|
4
4
|
* `NormalizedWorkout`, in a way that can be persisted to disk.
|
|
@@ -36,7 +36,7 @@ export interface NormalizedWorkout {
|
|
|
36
36
|
clientId: string;
|
|
37
37
|
biometrics?: WorkoutBiometrics;
|
|
38
38
|
trainerProgramId: string | undefined;
|
|
39
|
-
|
|
39
|
+
gymId: string | undefined;
|
|
40
40
|
}
|
|
41
41
|
export interface NormalizedSet {
|
|
42
42
|
index: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.trimWorkout = exports.isWorkoutCurrentlyPaused = exports.generateWorkoutTimeEvents = exports.calculateEndTime = exports.calculateDuration = void 0;
|
|
4
|
-
const
|
|
4
|
+
const __1 = require("..");
|
|
5
5
|
const calculateDuration = (normalizedWorkout, nowUnix) => {
|
|
6
6
|
const { startTime, timeEvents } = normalizedWorkout;
|
|
7
7
|
if (!timeEvents.length)
|
|
@@ -31,7 +31,7 @@ const calculateEndTime = (normalizedWorkout, nowUnix) => {
|
|
|
31
31
|
exports.calculateEndTime = calculateEndTime;
|
|
32
32
|
const generateWorkoutTimeEvents = ({ startTimeUnix, durationSeconds, nowUnix, isPaused = false, }) => {
|
|
33
33
|
const maxPossibleDuration = nowUnix - startTimeUnix;
|
|
34
|
-
const safeRequestedDuration = (0,
|
|
34
|
+
const safeRequestedDuration = (0, __1.clampNumber)(durationSeconds, {
|
|
35
35
|
min: 0,
|
|
36
36
|
max: maxPossibleDuration,
|
|
37
37
|
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { RPE, SetType, WorkoutBiometrics, WorkoutMedia } from '..';
|
|
2
|
+
export interface PostWorkoutRequest {
|
|
3
|
+
workout: PostWorkoutRequestWorkout;
|
|
4
|
+
/**
|
|
5
|
+
* `source` is set by import-workout-data (currently only supports imports from Strong)
|
|
6
|
+
* and for workouts that come from the public API.
|
|
7
|
+
* This prop gives us visibility into workouts that aren't logged within Hevy. Currently,
|
|
8
|
+
* it's used to filter the feed so users aren't spammed by workouts created programmatically.
|
|
9
|
+
*/
|
|
10
|
+
source?: 'strong' | 'public-api';
|
|
11
|
+
share_to_strava?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Fake UTC format (ISO string of user's _local_ time, but with 'Z' as the
|
|
14
|
+
* time zone), since that is what Strava expects. 🤦♂️
|
|
15
|
+
* https://developers.strava.com/docs/reference/#api-Activities-createActivity
|
|
16
|
+
*/
|
|
17
|
+
strava_activity_local_time?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface PostClientsWorkoutRequest {
|
|
20
|
+
workout: PostWorkoutRequestWorkout;
|
|
21
|
+
updateRoutineValues: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* PostWorkoutRequestWorkout describes the final state of a completed workout.
|
|
25
|
+
* It's used when sending a workout to the server.
|
|
26
|
+
*/
|
|
27
|
+
export interface PostWorkoutRequestWorkout {
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
media: WorkoutMedia[];
|
|
31
|
+
start_time: number;
|
|
32
|
+
end_time: number;
|
|
33
|
+
exercises: PostWorkoutRequestExercise[];
|
|
34
|
+
routine_id?: string;
|
|
35
|
+
apple_watch: boolean;
|
|
36
|
+
wearos_watch: boolean;
|
|
37
|
+
workout_id: string;
|
|
38
|
+
is_private: boolean;
|
|
39
|
+
biometrics?: WorkoutBiometrics;
|
|
40
|
+
is_biometrics_public: boolean;
|
|
41
|
+
trainer_program_id: string | undefined;
|
|
42
|
+
gymId: string | undefined;
|
|
43
|
+
}
|
|
44
|
+
export interface PostWorkoutRequestExercise {
|
|
45
|
+
title: string;
|
|
46
|
+
exercise_template_id: string;
|
|
47
|
+
superset_id?: number;
|
|
48
|
+
rest_timer_seconds?: number;
|
|
49
|
+
notes: string;
|
|
50
|
+
/**
|
|
51
|
+
* for exercises with two dumbbells
|
|
52
|
+
*
|
|
53
|
+
* `true` if the weight of each set is the weight of _one_ dumbbell, but the
|
|
54
|
+
* exercise was performed with _two_ dumbbells of that weight
|
|
55
|
+
*/
|
|
56
|
+
volume_doubling_enabled?: boolean;
|
|
57
|
+
sets: PostWorkoutRequestSet[];
|
|
58
|
+
}
|
|
59
|
+
export interface PostWorkoutRequestSet {
|
|
60
|
+
index: number;
|
|
61
|
+
type: SetType;
|
|
62
|
+
weight_kg?: number;
|
|
63
|
+
reps?: number;
|
|
64
|
+
distance_meters?: number;
|
|
65
|
+
duration_seconds?: number;
|
|
66
|
+
custom_metric?: number;
|
|
67
|
+
rpe?: RPE;
|
|
68
|
+
completed_at?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Used to update an existing workout. Props that are defined will be used to
|
|
72
|
+
* update the corresponding values of the workout in the database, and those
|
|
73
|
+
* that are undefined will not be changed.
|
|
74
|
+
*/
|
|
75
|
+
export type UpdateWorkoutRequestWorkout = Partial<Pick<PostWorkoutRequestWorkout, 'title' | 'description' | 'media' | 'exercises' | 'is_private' | 'is_biometrics_public'>> & {
|
|
76
|
+
start_and_end_time?: Required<Pick<PostWorkoutRequestWorkout, 'start_time' | 'end_time'>>;
|
|
77
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { DistanceUnit, Equipment, ExerciseType, MuscleGroup, RPE, SetPersonalRecordType, SetType, WeightUnit } from '..';
|
|
2
|
+
export declare const isPublicWorkout: (x: any) => x is PublicWorkout;
|
|
3
|
+
export interface PublicWorkout {
|
|
4
|
+
type: 'public';
|
|
5
|
+
id: string;
|
|
6
|
+
short_id: string | null;
|
|
7
|
+
name: string;
|
|
8
|
+
create_at: string;
|
|
9
|
+
start_time: number;
|
|
10
|
+
end_time: number;
|
|
11
|
+
username: string;
|
|
12
|
+
profile_image: string | null;
|
|
13
|
+
preview_image: string | null;
|
|
14
|
+
is_private: boolean;
|
|
15
|
+
exercises: PublicWorkoutExercise[];
|
|
16
|
+
/**
|
|
17
|
+
* weight_unit and distance_unit are the current unit
|
|
18
|
+
* preferences of the owner of the workout.
|
|
19
|
+
*/
|
|
20
|
+
weight_unit: WeightUnit;
|
|
21
|
+
distance_unit: DistanceUnit;
|
|
22
|
+
estimated_volume_kg: number;
|
|
23
|
+
}
|
|
24
|
+
export interface PublicWorkoutExercise {
|
|
25
|
+
id: string;
|
|
26
|
+
exercise_template_id: string;
|
|
27
|
+
title: string;
|
|
28
|
+
es_title?: string | null;
|
|
29
|
+
de_title?: string | null;
|
|
30
|
+
fr_title?: string | null;
|
|
31
|
+
it_title?: string | null;
|
|
32
|
+
pt_title?: string | null;
|
|
33
|
+
ko_title?: string | null;
|
|
34
|
+
ja_title?: string | null;
|
|
35
|
+
tr_title?: string | null;
|
|
36
|
+
ru_title?: string | null;
|
|
37
|
+
zh_cn_title?: string | null;
|
|
38
|
+
zh_tw_title?: string | null;
|
|
39
|
+
superset_id: number | null;
|
|
40
|
+
rest_seconds: number | null;
|
|
41
|
+
notes: string;
|
|
42
|
+
priority: number;
|
|
43
|
+
muscle_group: MuscleGroup;
|
|
44
|
+
other_muscles: MuscleGroup[];
|
|
45
|
+
exercise_type: ExerciseType;
|
|
46
|
+
equipment_category: Equipment;
|
|
47
|
+
url?: string;
|
|
48
|
+
media_type?: string;
|
|
49
|
+
custom_exercise_image_url?: string | null;
|
|
50
|
+
thumbnail_url?: string | null;
|
|
51
|
+
manual_tag?: string;
|
|
52
|
+
aka?: string;
|
|
53
|
+
/**
|
|
54
|
+
* for exercises with two dumbbells
|
|
55
|
+
*
|
|
56
|
+
* `true` if the weight of each set is the weight of _one_ dumbbell, but the
|
|
57
|
+
* exercise was performed with _two_ dumbbells of that weight
|
|
58
|
+
*/
|
|
59
|
+
volume_doubling_enabled: boolean;
|
|
60
|
+
sets: PublicWorkoutExerciseSet[];
|
|
61
|
+
}
|
|
62
|
+
export interface PublicWorkoutExerciseSet {
|
|
63
|
+
/**
|
|
64
|
+
* id can be a string or a number because we used
|
|
65
|
+
* to store it as int4 and now we store it as int8
|
|
66
|
+
* which is too big to store (accurately) in a JS
|
|
67
|
+
* number.
|
|
68
|
+
*/
|
|
69
|
+
id: number | string;
|
|
70
|
+
index: number;
|
|
71
|
+
indicator: SetType;
|
|
72
|
+
weight_kg?: number | null;
|
|
73
|
+
reps?: number | null;
|
|
74
|
+
distance_meters?: number | null;
|
|
75
|
+
duration_seconds?: number | null;
|
|
76
|
+
custom_metric?: number | null;
|
|
77
|
+
rpe?: RPE | null;
|
|
78
|
+
/**
|
|
79
|
+
* @deprecated 1.29.17 -
|
|
80
|
+
* we can only set this to `best_weight`, `best_reps`, `best_duration` or
|
|
81
|
+
* `best_distance`. sending anything else would cause older clients to crash.
|
|
82
|
+
* newer clients will ignore this field and use the `prs` field instead.
|
|
83
|
+
*/
|
|
84
|
+
personalRecords?: Array<{
|
|
85
|
+
type: 'best_weight' | 'best_reps' | 'best_duration' | 'best_distance';
|
|
86
|
+
value: number;
|
|
87
|
+
}>;
|
|
88
|
+
prs: {
|
|
89
|
+
type: SetPersonalRecordType;
|
|
90
|
+
value: number;
|
|
91
|
+
}[];
|
|
92
|
+
completed_at: string | null;
|
|
93
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Equipment, ExerciseType, MuscleGroup, PreviewWorkoutLike, RPE, SetPersonalRecordType, SetType, WorkoutBiometrics, WorkoutComment, WorkoutMedia } from '..';
|
|
2
|
+
export interface UserWorkout {
|
|
3
|
+
id: string;
|
|
4
|
+
short_id: string | null;
|
|
5
|
+
index: number;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
like_count: number;
|
|
9
|
+
/** @deprecated 2.3.4 */
|
|
10
|
+
like_images: string[];
|
|
11
|
+
preview_workout_likes: PreviewWorkoutLike[];
|
|
12
|
+
comment_count: number;
|
|
13
|
+
comments: WorkoutComment[];
|
|
14
|
+
/** @deprecated 1.28.13 */
|
|
15
|
+
image_urls?: string[];
|
|
16
|
+
media: WorkoutMedia[];
|
|
17
|
+
is_liked_by_user: boolean;
|
|
18
|
+
start_time: number;
|
|
19
|
+
end_time: number;
|
|
20
|
+
user_id: string;
|
|
21
|
+
username: string;
|
|
22
|
+
profile_image: string;
|
|
23
|
+
exercises: UserWorkoutExercise[];
|
|
24
|
+
routine_id?: string;
|
|
25
|
+
apple_watch: boolean;
|
|
26
|
+
wearos_watch: boolean;
|
|
27
|
+
verified: boolean;
|
|
28
|
+
created_at: string;
|
|
29
|
+
updated_at: string;
|
|
30
|
+
nth_workout: number;
|
|
31
|
+
/**
|
|
32
|
+
* See https://github.com/hevyapp/hevy-backend/pull/193 to understand
|
|
33
|
+
* why we added estimated_volume_kg
|
|
34
|
+
*/
|
|
35
|
+
estimated_volume_kg: number;
|
|
36
|
+
/**
|
|
37
|
+
* Whether to include warmup sets in various calculations.
|
|
38
|
+
* https://github.com/hevyapp/hevy-shared/pull/312
|
|
39
|
+
*/
|
|
40
|
+
include_warmup_sets: boolean;
|
|
41
|
+
is_private: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* If applicable, the user ID of the coach who logged this workout
|
|
44
|
+
*/
|
|
45
|
+
logged_by_coach_id?: string;
|
|
46
|
+
biometrics?: WorkoutBiometrics;
|
|
47
|
+
is_biometrics_public: boolean;
|
|
48
|
+
trainer_program_id: string | undefined;
|
|
49
|
+
gym: UserWorkoutGym | undefined;
|
|
50
|
+
}
|
|
51
|
+
export interface UserWorkoutExercise {
|
|
52
|
+
id: string;
|
|
53
|
+
exercise_template_id: string;
|
|
54
|
+
title: string;
|
|
55
|
+
es_title?: string | null;
|
|
56
|
+
de_title?: string | null;
|
|
57
|
+
fr_title?: string | null;
|
|
58
|
+
it_title?: string | null;
|
|
59
|
+
pt_title?: string | null;
|
|
60
|
+
ko_title?: string | null;
|
|
61
|
+
ja_title?: string | null;
|
|
62
|
+
tr_title?: string | null;
|
|
63
|
+
ru_title?: string | null;
|
|
64
|
+
zh_cn_title?: string | null;
|
|
65
|
+
zh_tw_title?: string | null;
|
|
66
|
+
superset_id: number | null;
|
|
67
|
+
rest_seconds: number | null;
|
|
68
|
+
notes: string;
|
|
69
|
+
priority: number;
|
|
70
|
+
muscle_group: MuscleGroup;
|
|
71
|
+
other_muscles: MuscleGroup[];
|
|
72
|
+
exercise_type: ExerciseType;
|
|
73
|
+
equipment_category: Equipment;
|
|
74
|
+
url?: string;
|
|
75
|
+
media_type?: string;
|
|
76
|
+
custom_exercise_image_url?: string | null;
|
|
77
|
+
thumbnail_url?: string | null;
|
|
78
|
+
manual_tag?: string;
|
|
79
|
+
aka?: string;
|
|
80
|
+
/**
|
|
81
|
+
* for exercises with two dumbbells
|
|
82
|
+
*
|
|
83
|
+
* `true` if the weight of each set is the weight of _one_ dumbbell, but the
|
|
84
|
+
* exercise was performed with _two_ dumbbells of that weight
|
|
85
|
+
*/
|
|
86
|
+
volume_doubling_enabled: boolean;
|
|
87
|
+
sets: UserWorkoutExerciseSet[];
|
|
88
|
+
}
|
|
89
|
+
export interface UserWorkoutExerciseSet {
|
|
90
|
+
/**
|
|
91
|
+
* id can be a string or a number because we used
|
|
92
|
+
* to store it as int4 and now we store it as int8
|
|
93
|
+
* which is too big to store (accurately) in a JS
|
|
94
|
+
* number.
|
|
95
|
+
*/
|
|
96
|
+
id: number | string;
|
|
97
|
+
index: number;
|
|
98
|
+
indicator: SetType;
|
|
99
|
+
weight_kg?: number | null;
|
|
100
|
+
reps?: number | null;
|
|
101
|
+
distance_meters?: number | null;
|
|
102
|
+
duration_seconds?: number | null;
|
|
103
|
+
custom_metric?: number | null;
|
|
104
|
+
rpe?: RPE | null;
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated 1.29.17 -
|
|
107
|
+
* we can only set this to `best_weight`, `best_reps`, `best_duration` or
|
|
108
|
+
* `best_distance`. sending anything else would cause older clients to crash.
|
|
109
|
+
* newer clients will ignore this field and use the `prs` field instead.
|
|
110
|
+
*/
|
|
111
|
+
personalRecords?: Array<{
|
|
112
|
+
type: 'best_weight' | 'best_reps' | 'best_duration' | 'best_distance';
|
|
113
|
+
value: number;
|
|
114
|
+
}>;
|
|
115
|
+
prs: {
|
|
116
|
+
type: SetPersonalRecordType;
|
|
117
|
+
value: number;
|
|
118
|
+
}[];
|
|
119
|
+
completed_at: string | null;
|
|
120
|
+
}
|
|
121
|
+
type CommercialGym = {
|
|
122
|
+
type: 'commercial';
|
|
123
|
+
name: string;
|
|
124
|
+
city: string;
|
|
125
|
+
};
|
|
126
|
+
type HomeGym = {
|
|
127
|
+
type: 'home';
|
|
128
|
+
};
|
|
129
|
+
export type UserWorkoutGym = CommercialGym | HomeGym;
|
|
130
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Equipment, ExerciseType, MuscleGroup, PreviewWorkoutLike, RPE, SetPersonalRecordType, SetType, WorkoutBiometrics, WorkoutComment, WorkoutMedia } from '..';
|
|
2
|
+
export interface Workout {
|
|
3
|
+
id: string;
|
|
4
|
+
short_id: string | null;
|
|
5
|
+
index: number;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
like_count: number;
|
|
9
|
+
/** @deprecated 2.3.4 */
|
|
10
|
+
like_images: string[];
|
|
11
|
+
preview_workout_likes: PreviewWorkoutLike[];
|
|
12
|
+
comment_count: number;
|
|
13
|
+
comments: WorkoutComment[];
|
|
14
|
+
/** @deprecated 1.28.13 */
|
|
15
|
+
image_urls?: string[];
|
|
16
|
+
media: WorkoutMedia[];
|
|
17
|
+
is_liked_by_user: boolean;
|
|
18
|
+
start_time: number;
|
|
19
|
+
end_time: number;
|
|
20
|
+
user_id: string;
|
|
21
|
+
username: string;
|
|
22
|
+
profile_image: string;
|
|
23
|
+
exercises: WorkoutExercise[];
|
|
24
|
+
routine_id?: string;
|
|
25
|
+
apple_watch: boolean;
|
|
26
|
+
wearos_watch: boolean;
|
|
27
|
+
verified: boolean;
|
|
28
|
+
created_at: string;
|
|
29
|
+
updated_at: string;
|
|
30
|
+
nth_workout: number;
|
|
31
|
+
/**
|
|
32
|
+
* See https://github.com/hevyapp/hevy-backend/pull/193 to understand
|
|
33
|
+
* why we added estimated_volume_kg
|
|
34
|
+
*/
|
|
35
|
+
estimated_volume_kg: number;
|
|
36
|
+
/**
|
|
37
|
+
* Whether to include warmup sets in various calculations.
|
|
38
|
+
* https://github.com/hevyapp/hevy-shared/pull/312
|
|
39
|
+
*/
|
|
40
|
+
include_warmup_sets: boolean;
|
|
41
|
+
is_private: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* If applicable, the user ID of the coach who logged this workout
|
|
44
|
+
*/
|
|
45
|
+
logged_by_coach_id?: string;
|
|
46
|
+
biometrics?: WorkoutBiometrics;
|
|
47
|
+
is_biometrics_public: boolean;
|
|
48
|
+
trainer_program_id: string | undefined;
|
|
49
|
+
gymId: string | undefined;
|
|
50
|
+
}
|
|
51
|
+
export interface WorkoutExercise {
|
|
52
|
+
id: string;
|
|
53
|
+
exercise_template_id: string;
|
|
54
|
+
title: string;
|
|
55
|
+
es_title?: string | null;
|
|
56
|
+
de_title?: string | null;
|
|
57
|
+
fr_title?: string | null;
|
|
58
|
+
it_title?: string | null;
|
|
59
|
+
pt_title?: string | null;
|
|
60
|
+
ko_title?: string | null;
|
|
61
|
+
ja_title?: string | null;
|
|
62
|
+
tr_title?: string | null;
|
|
63
|
+
ru_title?: string | null;
|
|
64
|
+
zh_cn_title?: string | null;
|
|
65
|
+
zh_tw_title?: string | null;
|
|
66
|
+
superset_id: number | null;
|
|
67
|
+
rest_seconds: number | null;
|
|
68
|
+
notes: string;
|
|
69
|
+
priority: number;
|
|
70
|
+
muscle_group: MuscleGroup;
|
|
71
|
+
other_muscles: MuscleGroup[];
|
|
72
|
+
exercise_type: ExerciseType;
|
|
73
|
+
equipment_category: Equipment;
|
|
74
|
+
url?: string;
|
|
75
|
+
media_type?: string;
|
|
76
|
+
custom_exercise_image_url?: string | null;
|
|
77
|
+
thumbnail_url?: string | null;
|
|
78
|
+
manual_tag?: string;
|
|
79
|
+
aka?: string;
|
|
80
|
+
/**
|
|
81
|
+
* for exercises with two dumbbells
|
|
82
|
+
*
|
|
83
|
+
* `true` if the weight of each set is the weight of _one_ dumbbell, but the
|
|
84
|
+
* exercise was performed with _two_ dumbbells of that weight
|
|
85
|
+
*/
|
|
86
|
+
volume_doubling_enabled: boolean;
|
|
87
|
+
sets: WorkoutExerciseSet[];
|
|
88
|
+
}
|
|
89
|
+
export interface WorkoutExerciseSet {
|
|
90
|
+
/**
|
|
91
|
+
* id can be a string or a number because we used
|
|
92
|
+
* to store it as int4 and now we store it as int8
|
|
93
|
+
* which is too big to store (accurately) in a JS
|
|
94
|
+
* number.
|
|
95
|
+
*/
|
|
96
|
+
id: number | string;
|
|
97
|
+
index: number;
|
|
98
|
+
indicator: SetType;
|
|
99
|
+
weight_kg?: number | null;
|
|
100
|
+
reps?: number | null;
|
|
101
|
+
distance_meters?: number | null;
|
|
102
|
+
duration_seconds?: number | null;
|
|
103
|
+
custom_metric?: number | null;
|
|
104
|
+
rpe?: RPE | null;
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated 1.29.17 -
|
|
107
|
+
* we can only set this to `best_weight`, `best_reps`, `best_duration` or
|
|
108
|
+
* `best_distance`. sending anything else would cause older clients to crash.
|
|
109
|
+
* newer clients will ignore this field and use the `prs` field instead.
|
|
110
|
+
*/
|
|
111
|
+
personalRecords?: Array<{
|
|
112
|
+
type: 'best_weight' | 'best_reps' | 'best_duration' | 'best_distance';
|
|
113
|
+
value: number;
|
|
114
|
+
}>;
|
|
115
|
+
prs: {
|
|
116
|
+
type: SetPersonalRecordType;
|
|
117
|
+
value: number;
|
|
118
|
+
}[];
|
|
119
|
+
completed_at: string | null;
|
|
120
|
+
}
|