hevy-shared 1.0.960 → 1.0.962

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +21 -0
  3. package/.github/workflows/ci.yml +15 -0
  4. package/.github/workflows/npm-publish.yml +59 -0
  5. package/.github/workflows/pr-auto-assign.yml +15 -0
  6. package/.prettierrc.js +5 -0
  7. package/README.md +2 -17
  8. package/built/chat.d.ts +23 -25
  9. package/built/coachPlans.d.ts +1 -2
  10. package/built/coachPlans.js +2 -2
  11. package/built/filterExercises.d.ts +3 -19
  12. package/built/filterExercises.js +60 -72
  13. package/built/index.d.ts +304 -1140
  14. package/built/index.js +75 -269
  15. package/built/setIndicatorUtils.d.ts +3 -4
  16. package/built/setIndicatorUtils.js +1 -15
  17. package/built/tests/utils.test.js +0 -748
  18. package/built/tests/workoutVolume.test.js +49 -165
  19. package/built/units.d.ts +7 -14
  20. package/built/units.js +14 -24
  21. package/built/utils.d.ts +5 -192
  22. package/built/utils.js +85 -598
  23. package/built/websocket.d.ts +2 -14
  24. package/built/workoutVolume.d.ts +5 -24
  25. package/built/workoutVolume.js +34 -25
  26. package/jest.config.js +4 -0
  27. package/package.json +10 -32
  28. package/src/chat.ts +130 -0
  29. package/src/coachPlans.ts +57 -0
  30. package/src/constants.ts +14 -0
  31. package/src/filterExercises.ts +222 -0
  32. package/src/index.ts +1576 -0
  33. package/src/setIndicatorUtils.ts +137 -0
  34. package/src/tests/utils.test.ts +156 -0
  35. package/src/tests/workoutVolume.test.ts +93 -0
  36. package/src/units.ts +41 -0
  37. package/src/utils.ts +516 -0
  38. package/src/websocket.ts +36 -0
  39. package/src/workoutVolume.ts +175 -0
  40. package/tsconfig.json +70 -0
  41. package/built/API/APIClient.d.ts +0 -157
  42. package/built/API/APIClient.js +0 -381
  43. package/built/API/index.d.ts +0 -2
  44. package/built/API/index.js +0 -18
  45. package/built/API/types.d.ts +0 -38
  46. package/built/API/types.js +0 -18
  47. package/built/adjustEventTokens.d.ts +0 -16
  48. package/built/adjustEventTokens.js +0 -18
  49. package/built/adminPermissions.d.ts +0 -4
  50. package/built/adminPermissions.js +0 -22
  51. package/built/async.d.ts +0 -50
  52. package/built/async.js +0 -170
  53. package/built/cue.d.ts +0 -12
  54. package/built/cue.js +0 -22
  55. package/built/exerciseLocaleUtils.d.ts +0 -17
  56. package/built/exerciseLocaleUtils.js +0 -62
  57. package/built/hevyTrainer.d.ts +0 -250
  58. package/built/hevyTrainer.js +0 -676
  59. package/built/muscleHeatmaps.d.ts +0 -31
  60. package/built/muscleHeatmaps.js +0 -68
  61. package/built/muscleSplits.d.ts +0 -36
  62. package/built/muscleSplits.js +0 -100
  63. package/built/normalizedWorkoutUtils.d.ts +0 -88
  64. package/built/normalizedWorkoutUtils.js +0 -112
  65. package/built/notifications.d.ts +0 -215
  66. package/built/notifications.js +0 -9
  67. package/built/routineUtils.d.ts +0 -14
  68. package/built/routineUtils.js +0 -186
  69. package/built/schemas.d.ts +0 -6
  70. package/built/schemas.js +0 -12
  71. package/built/tests/async.test.d.ts +0 -1
  72. package/built/tests/async.test.js +0 -49
  73. package/built/tests/hevyTrainer.test.d.ts +0 -1
  74. package/built/tests/hevyTrainer.test.js +0 -1199
  75. package/built/tests/muscleSplit.test.d.ts +0 -1
  76. package/built/tests/muscleSplit.test.js +0 -153
  77. package/built/tests/routineUtils.test.d.ts +0 -1
  78. package/built/tests/routineUtils.test.js +0 -745
  79. package/built/tests/testUtils.d.ts +0 -85
  80. package/built/tests/testUtils.js +0 -319
  81. package/built/translations/index.d.ts +0 -2
  82. package/built/translations/index.js +0 -18
  83. package/built/translations/translationUtils.d.ts +0 -2
  84. package/built/translations/translationUtils.js +0 -61
  85. package/built/translations/types.d.ts +0 -8
  86. package/built/translations/types.js +0 -20
  87. package/built/typeUtils.d.ts +0 -70
  88. package/built/typeUtils.js +0 -55
@@ -1,31 +0,0 @@
1
- import { MuscleGroup } from '.';
2
- import { Lookup } from './typeUtils';
3
- declare const _muscleHeatmapKeys: readonly ["abdominals", "shoulders", "chest", "lower_back", "biceps", "triceps", "upper_back", "quadriceps", "calves", "lats", "hamstrings", "glutes", "abductors", "adductors", "traps", "forearms", "neck"];
4
- export type MuscleHeatmapKey = Lookup<typeof _muscleHeatmapKeys>;
5
- export declare const isMuscleHeatmapKey: (x: string) => x is MuscleHeatmapKey;
6
- export type MuscleHeatmapData = {
7
- [key in MuscleHeatmapKey]?: number;
8
- };
9
- /**
10
- * Calculates muscle group opacity from exercise data: primary muscle groups are 1.0, secondary are 0.5
11
- */
12
- export declare const getMuscleHeatmapDataForExercises: (exercises: ({
13
- muscle_group: MuscleGroup;
14
- other_muscles: MuscleGroup[];
15
- } | undefined)[]) => MuscleHeatmapData;
16
- /**
17
- *
18
- * @param workoutsOrRoutines An array of objects with an array of exercises
19
- * @param getExerciseTemplateWithId A function that returns an ExerciseTemplate (or undefined) given an ID
20
- * @returns MuscleHeatmapData with a value that represents how much a muscle group was used in the workouts or routines:
21
- * A primary muscle counts as 1.0 per workout/routine, and a secondary muscle counts as 0.5 per workout/routine
22
- */
23
- export declare const getMuscleHeatmapDataForWorkoutsOrRoutines: ({ workoutsOrRoutines, }: {
24
- workoutsOrRoutines: {
25
- exercises: {
26
- muscle_group: MuscleGroup;
27
- other_muscles: MuscleGroup[];
28
- }[];
29
- }[];
30
- }) => MuscleHeatmapData;
31
- export {};
@@ -1,68 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getMuscleHeatmapDataForWorkoutsOrRoutines = exports.getMuscleHeatmapDataForExercises = exports.isMuscleHeatmapKey = void 0;
4
- const typeUtils_1 = require("./typeUtils");
5
- const _muscleHeatmapKeys = [
6
- 'abdominals',
7
- 'shoulders',
8
- 'chest',
9
- 'lower_back',
10
- 'biceps',
11
- 'triceps',
12
- 'upper_back',
13
- 'quadriceps',
14
- 'calves',
15
- 'lats',
16
- 'hamstrings',
17
- 'glutes',
18
- 'abductors',
19
- 'adductors',
20
- 'traps',
21
- 'forearms',
22
- 'neck',
23
- ];
24
- const isMuscleHeatmapKey = (x) => (0, typeUtils_1.isInArray)(x, _muscleHeatmapKeys);
25
- exports.isMuscleHeatmapKey = isMuscleHeatmapKey;
26
- /**
27
- * Calculates muscle group opacity from exercise data: primary muscle groups are 1.0, secondary are 0.5
28
- */
29
- const getMuscleHeatmapDataForExercises = (exercises) => {
30
- var _a;
31
- // initialise all keys to 0
32
- const data = _muscleHeatmapKeys.reduce((prev, curr) => (Object.assign(Object.assign({}, prev), { [curr]: 0 })), {});
33
- for (const e of exercises) {
34
- if (!e)
35
- continue;
36
- if ((0, exports.isMuscleHeatmapKey)(e.muscle_group)) {
37
- data[e.muscle_group] = 1;
38
- }
39
- for (const m of e.other_muscles) {
40
- if ((0, exports.isMuscleHeatmapKey)(m)) {
41
- data[m] = Math.max((_a = data[m]) !== null && _a !== void 0 ? _a : 0, 0.5);
42
- }
43
- }
44
- }
45
- return data;
46
- };
47
- exports.getMuscleHeatmapDataForExercises = getMuscleHeatmapDataForExercises;
48
- /**
49
- *
50
- * @param workoutsOrRoutines An array of objects with an array of exercises
51
- * @param getExerciseTemplateWithId A function that returns an ExerciseTemplate (or undefined) given an ID
52
- * @returns MuscleHeatmapData with a value that represents how much a muscle group was used in the workouts or routines:
53
- * A primary muscle counts as 1.0 per workout/routine, and a secondary muscle counts as 0.5 per workout/routine
54
- */
55
- const getMuscleHeatmapDataForWorkoutsOrRoutines = ({ workoutsOrRoutines, }) => {
56
- // initialise all keys to 0
57
- const data = _muscleHeatmapKeys.reduce((prev, curr) => (Object.assign(Object.assign({}, prev), { [curr]: 0 })), {});
58
- workoutsOrRoutines.forEach((workoutOrRoutine) => {
59
- const muscleData = (0, exports.getMuscleHeatmapDataForExercises)(workoutOrRoutine.exercises);
60
- Object.keys(muscleData).forEach((muscle) => {
61
- data[muscle] =
62
- (data[muscle] || 0) +
63
- (muscleData[muscle] || 0);
64
- });
65
- });
66
- return data;
67
- };
68
- exports.getMuscleHeatmapDataForWorkoutsOrRoutines = getMuscleHeatmapDataForWorkoutsOrRoutines;
@@ -1,36 +0,0 @@
1
- import { MuscleGroup, SetType, SimplifiedMuscleGroup } from '.';
2
- interface SetCountableSet {
3
- indicator: SetType;
4
- }
5
- interface SetCountableExercise {
6
- muscle_group: MuscleGroup;
7
- other_muscles: MuscleGroup[];
8
- sets: SetCountableSet[];
9
- }
10
- export interface SetCountableWorkoutOrRoutine {
11
- exercises: SetCountableExercise[];
12
- }
13
- export declare const calculateSetContributionsForSimplifiedMuscleGroups: ({ muscle_group, other_muscles, }: {
14
- muscle_group: MuscleGroup;
15
- other_muscles: MuscleGroup[];
16
- }) => {
17
- core: number;
18
- shoulders: number;
19
- arms: number;
20
- legs: number;
21
- back: number;
22
- chest: number;
23
- };
24
- export declare const calculateSimplifiedMuscleSplit: ({ workoutsOrRoutines, includeWarmupSets, }: {
25
- workoutsOrRoutines: SetCountableWorkoutOrRoutine[];
26
- includeWarmupSets: boolean;
27
- }) => Record<SimplifiedMuscleGroup, number>;
28
- export declare const calculateSetContributionsForMuscleGroups: ({ muscleGroup, otherMuscles, }: {
29
- muscleGroup: MuscleGroup;
30
- otherMuscles: MuscleGroup[];
31
- }) => Record<MuscleGroup, number>;
32
- export declare const calculateSetCountPerMuscleGroups: ({ workoutsOrRoutines, includeWarmupSets, }: {
33
- workoutsOrRoutines: SetCountableWorkoutOrRoutine[];
34
- includeWarmupSets: boolean;
35
- }) => Record<MuscleGroup, number>;
36
- export {};
@@ -1,100 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.calculateSetCountPerMuscleGroups = exports.calculateSetContributionsForMuscleGroups = exports.calculateSimplifiedMuscleSplit = exports.calculateSetContributionsForSimplifiedMuscleGroups = void 0;
7
- const intersection_1 = __importDefault(require("lodash/intersection"));
8
- const _1 = require(".");
9
- const calculateSetContributionsForSimplifiedMuscleGroups = ({ muscle_group, other_muscles, }) => {
10
- const getContribution = (mg) => {
11
- if (mg.includes(muscle_group)) {
12
- return 1;
13
- }
14
- else if ((0, intersection_1.default)(mg, other_muscles).length) {
15
- return 0.5;
16
- }
17
- else if (muscle_group === 'full_body') {
18
- return 1 / 6;
19
- }
20
- return 0;
21
- };
22
- return {
23
- core: getContribution(_1.coreMuscles),
24
- shoulders: getContribution(_1.shoulderMuscles),
25
- arms: getContribution(_1.armMuscles),
26
- legs: getContribution(_1.legMuscles),
27
- back: getContribution(_1.backMuscles),
28
- chest: getContribution(_1.chestMuscles),
29
- };
30
- };
31
- exports.calculateSetContributionsForSimplifiedMuscleGroups = calculateSetContributionsForSimplifiedMuscleGroups;
32
- const calculateSimplifiedMuscleSplit = ({ workoutsOrRoutines, includeWarmupSets, }) => {
33
- const totals = {
34
- core: 0,
35
- shoulders: 0,
36
- arms: 0,
37
- legs: 0,
38
- back: 0,
39
- chest: 0,
40
- };
41
- for (const workoutOrRoutine of workoutsOrRoutines) {
42
- for (const exercise of workoutOrRoutine.exercises) {
43
- const trimmedSets = includeWarmupSets
44
- ? exercise.sets
45
- : exercise.sets.filter((s) => s.indicator !== 'warmup');
46
- const setCount = trimmedSets.length;
47
- const contributions = (0, exports.calculateSetContributionsForSimplifiedMuscleGroups)({
48
- muscle_group: exercise.muscle_group,
49
- other_muscles: exercise.other_muscles,
50
- });
51
- totals.core += contributions.core * setCount;
52
- totals.shoulders += contributions.shoulders * setCount;
53
- totals.arms += contributions.arms * setCount;
54
- totals.legs += contributions.legs * setCount;
55
- totals.back += contributions.back * setCount;
56
- totals.chest += contributions.chest * setCount;
57
- }
58
- }
59
- return totals;
60
- };
61
- exports.calculateSimplifiedMuscleSplit = calculateSimplifiedMuscleSplit;
62
- const calculateSetContributionsForMuscleGroups = ({ muscleGroup, otherMuscles, }) => {
63
- const getContribution = (mg) => {
64
- if (mg === muscleGroup) {
65
- return 1;
66
- }
67
- else if (otherMuscles.includes(mg)) {
68
- return 0.5;
69
- }
70
- return 0;
71
- };
72
- return _1.muscleGroups.reduce((acc, mg) => {
73
- acc[mg] = getContribution(mg);
74
- return acc;
75
- }, {});
76
- };
77
- exports.calculateSetContributionsForMuscleGroups = calculateSetContributionsForMuscleGroups;
78
- const calculateSetCountPerMuscleGroups = ({ workoutsOrRoutines, includeWarmupSets, }) => {
79
- const totals = _1.muscleGroups.reduce((acc, muscleGroup) => {
80
- acc[muscleGroup] = 0;
81
- return acc;
82
- }, {});
83
- for (const workoutOrRoutine of workoutsOrRoutines) {
84
- for (const exercise of workoutOrRoutine.exercises) {
85
- const trimmedSets = includeWarmupSets
86
- ? exercise.sets
87
- : exercise.sets.filter((s) => s.indicator !== 'warmup');
88
- const setCount = trimmedSets.length;
89
- const contributions = (0, exports.calculateSetContributionsForMuscleGroups)({
90
- muscleGroup: exercise.muscle_group,
91
- otherMuscles: exercise.other_muscles,
92
- });
93
- for (const muscleGroup of _1.muscleGroups) {
94
- totals[muscleGroup] += contributions[muscleGroup] * setCount;
95
- }
96
- }
97
- }
98
- return totals;
99
- };
100
- exports.calculateSetCountPerMuscleGroups = calculateSetCountPerMuscleGroups;
@@ -1,88 +0,0 @@
1
- import { ExerciseType, RPE, SetType, ShareToPlatform, WorkoutBiometrics, WorkoutMedia, WorkoutVisibility } from '.';
2
- /**
3
- * Events are used to determine the start time, end time and duration of a
4
- * `NormalizedWorkout`, in a way that can be persisted to disk.
5
- */
6
- export interface NormalizedWorkoutEvent {
7
- type: 'resume' | 'pause';
8
- unixTimestamp: number;
9
- }
10
- /**
11
- * NormalizedWorkout describes the state of a workout. It's used when
12
- * persisting an ongoing workout to disk, or calculating shareables after
13
- * completing the workout.
14
- *
15
- * The duration of a `NormalizedWorkout` is _derived_ from the `timeEvents`
16
- * array. There is no single "duration" variable, because that would require
17
- * pausing to be a complex stateful operation.
18
- */
19
- export interface NormalizedWorkout {
20
- name: string;
21
- description: string;
22
- media: WorkoutMedia[];
23
- startTime: number;
24
- timeEvents: NormalizedWorkoutEvent[];
25
- exercises: NormalizedExercise[];
26
- routineId?: string;
27
- trackWorkoutAsRoutine: boolean;
28
- updateRoutineFromWorkout?: boolean;
29
- appleWatch: boolean;
30
- wearosWatch: boolean;
31
- workoutVisibility: WorkoutVisibility;
32
- isWorkoutBiometricsPublic: boolean;
33
- shareTo: {
34
- [key in ShareToPlatform]: boolean;
35
- };
36
- clientId: string;
37
- biometrics?: WorkoutBiometrics;
38
- trainerProgramId: string | undefined;
39
- }
40
- export interface NormalizedSet {
41
- index: number;
42
- indicator: SetType;
43
- weight?: number;
44
- reps?: number;
45
- distance?: number;
46
- duration?: number;
47
- customMetric?: number;
48
- rpe?: RPE;
49
- targetRpe?: RPE;
50
- completed: boolean;
51
- completedAt?: string;
52
- }
53
- export interface NormalizedExercise {
54
- title: string;
55
- exerciseTemplateId: string;
56
- supersetId?: number;
57
- autoRestTimerSeconds?: number;
58
- routineNotes: string;
59
- notes: string;
60
- volumeDoublingEnabled: boolean;
61
- sets: NormalizedSet[];
62
- }
63
- export declare const calculateDuration: (normalizedWorkout: Pick<NormalizedWorkout, "startTime" | "timeEvents">, nowUnix: number) => number;
64
- export declare const calculateEndTime: (normalizedWorkout: Pick<NormalizedWorkout, "startTime" | "timeEvents">, nowUnix: number) => number;
65
- interface GenerateWorkoutTimeEventsArgs {
66
- startTimeUnix: number;
67
- durationSeconds: number;
68
- nowUnix: number;
69
- /**
70
- * if this is `true`, generate a pause event at the current timestamp
71
- */
72
- isPaused?: boolean;
73
- }
74
- export declare const generateWorkoutTimeEvents: ({ startTimeUnix, durationSeconds, nowUnix, isPaused, }: GenerateWorkoutTimeEventsArgs) => NormalizedWorkoutEvent[];
75
- export declare const isWorkoutCurrentlyPaused: (normalizedWorkout: NormalizedWorkout) => boolean;
76
- /**
77
- * When logging a workout, we can't just use the `completed` state of a set to
78
- * determine if the user meant for the set to be included in the workout. This
79
- * is because a lot of users never mark sets as completed, and forcing them to
80
- * do that wouldn't add anything to the app. For that reason, we count a set as
81
- * completed if it contains inputted valid values based on its exercise type.
82
- * This function filters out all sets in a `NormalizedWorkout` that are
83
- * incomplete based on the values inputted.
84
- */
85
- export declare const trimWorkout: (workout: NormalizedWorkout, exerciseTypeMap: {
86
- [key: string]: ExerciseType;
87
- }) => NormalizedWorkout;
88
- export {};
@@ -1,112 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.trimWorkout = exports.isWorkoutCurrentlyPaused = exports.generateWorkoutTimeEvents = exports.calculateEndTime = exports.calculateDuration = void 0;
4
- const _1 = require(".");
5
- const calculateDuration = (normalizedWorkout, nowUnix) => {
6
- const { startTime, timeEvents } = normalizedWorkout;
7
- if (!timeEvents.length)
8
- return nowUnix - startTime;
9
- const timeBeforeFirstEvent = timeEvents[0].unixTimestamp - startTime;
10
- const duration = timeEvents.reduce((prev, curr, index, array) => {
11
- var _a;
12
- const nextEvent = (_a = array[index + 1]) !== null && _a !== void 0 ? _a : {
13
- type: 'resume',
14
- unixTimestamp: nowUnix,
15
- };
16
- if (curr.type === 'pause') {
17
- return prev;
18
- }
19
- else {
20
- return prev + nextEvent.unixTimestamp - curr.unixTimestamp;
21
- }
22
- }, timeBeforeFirstEvent);
23
- return duration;
24
- };
25
- exports.calculateDuration = calculateDuration;
26
- const calculateEndTime = (normalizedWorkout, nowUnix) => {
27
- const { startTime } = normalizedWorkout;
28
- const durationSeconds = (0, exports.calculateDuration)(normalizedWorkout, nowUnix);
29
- return startTime + durationSeconds;
30
- };
31
- exports.calculateEndTime = calculateEndTime;
32
- const generateWorkoutTimeEvents = ({ startTimeUnix, durationSeconds, nowUnix, isPaused = false, }) => {
33
- const maxPossibleDuration = nowUnix - startTimeUnix;
34
- const safeRequestedDuration = (0, _1.clampNumber)(durationSeconds, {
35
- min: 0,
36
- max: maxPossibleDuration,
37
- });
38
- const pausePaddingSeconds = maxPossibleDuration - safeRequestedDuration;
39
- const timeEvents = [];
40
- if (pausePaddingSeconds > 0) {
41
- /**
42
- * The duration is shorter than (endTime - startTime). Add a pause event at
43
- * the start of the workout for padding, and a resume event at the correct
44
- * time to make the duration match.
45
- */
46
- timeEvents.push(...[
47
- { type: 'pause', unixTimestamp: startTimeUnix },
48
- { type: 'resume', unixTimestamp: startTimeUnix + pausePaddingSeconds },
49
- ]);
50
- }
51
- if (isPaused) {
52
- timeEvents.push({
53
- type: 'pause',
54
- unixTimestamp: startTimeUnix + maxPossibleDuration,
55
- });
56
- }
57
- return timeEvents;
58
- };
59
- exports.generateWorkoutTimeEvents = generateWorkoutTimeEvents;
60
- const isWorkoutCurrentlyPaused = (normalizedWorkout) => {
61
- var _a;
62
- return ((_a = normalizedWorkout.timeEvents.slice(-1)[0]) === null || _a === void 0 ? void 0 : _a.type) === 'pause';
63
- };
64
- exports.isWorkoutCurrentlyPaused = isWorkoutCurrentlyPaused;
65
- /**
66
- * When logging a workout, we can't just use the `completed` state of a set to
67
- * determine if the user meant for the set to be included in the workout. This
68
- * is because a lot of users never mark sets as completed, and forcing them to
69
- * do that wouldn't add anything to the app. For that reason, we count a set as
70
- * completed if it contains inputted valid values based on its exercise type.
71
- * This function filters out all sets in a `NormalizedWorkout` that are
72
- * incomplete based on the values inputted.
73
- */
74
- const trimWorkout = (workout, exerciseTypeMap) => {
75
- // Filter out empty sets.
76
- const filteredSetsWorkout = Object.assign(Object.assign({}, workout), { exercises: workout.exercises.map((e) => {
77
- return Object.assign(Object.assign({}, e), { sets: e.sets.filter((s) => {
78
- const exerciseType = exerciseTypeMap[e.exerciseTemplateId];
79
- if (!exerciseType) {
80
- /**
81
- * if we don't know the exercise type, we can't tell if the set is
82
- * empty or not, so we'll just assume that it's not.
83
- */
84
- return true;
85
- }
86
- return !isEmptySet(s, exerciseType);
87
- }) });
88
- }) });
89
- // Filter out exercises that contain 0 sets.
90
- const filteredWorkout = Object.assign(Object.assign({}, filteredSetsWorkout), { exercises: filteredSetsWorkout.exercises.filter((e) => !!e.sets.length) });
91
- return filteredWorkout;
92
- };
93
- exports.trimWorkout = trimWorkout;
94
- const isEmptySet = (set, exerciseType) => {
95
- switch (exerciseType) {
96
- case 'weight_reps':
97
- case 'bodyweight_reps':
98
- case 'bodyweight_assisted_reps':
99
- case 'reps_only':
100
- return !set.reps && !set.weight;
101
- case 'distance_duration':
102
- case 'duration':
103
- return !set.duration && !set.distance;
104
- case 'short_distance_weight':
105
- return !set.distance && !set.weight;
106
- case 'weight_duration':
107
- return !set.weight && !set.duration;
108
- case 'floors_duration':
109
- case 'steps_duration':
110
- return !set.duration;
111
- }
112
- };
@@ -1,215 +0,0 @@
1
- /**
2
- * Notifications and Mobile pushes
3
- *
4
- * Notifications are types used for the in-app notification feed
5
- *
6
- * Mobile pushes are payloads delivered to mobile apps
7
- */
8
- import { ClientsCoachData, Program } from '.';
9
- import { HevyChatUpdateMobilePushData } from './chat';
10
- export type Notification = WorkoutCompleteNotification | WorkoutMentionNotification | WorkoutCommentNotification | WorkoutCommentMentionNotification | WorkoutCommentReplyNotification | WorkoutCommentDiscussionNotification | WorkoutLikeNotification | WorkoutCommentLikeNotification | FollowNotification | FollowRequestNotification | AcceptFollowRequestNotification | CoachClientInviteNotification | ContactOnHevyNotification;
11
- export type NotificationType = 'workout-complete' | 'workout-mention' | 'workout-comment' | 'workout-comment-mention' | 'workout-comment-reply' | 'workout-comment-reply-v2' | 'workout-like' | 'workout-comment-like' | 'follow' | 'follow-request' | 'accept-follow-request' | 'coach-client-invite' | 'contact-on-hevy';
12
- export interface BaseNotification {
13
- id: number;
14
- type: NotificationType;
15
- from_username: string;
16
- profile_pic?: string;
17
- date: string;
18
- }
19
- export interface BaseMobilePushData {
20
- type: MobilePushDataType;
21
- deeplink?: string;
22
- profilePic?: string;
23
- cue_notification_group_identifier?: string;
24
- additionalHevyData?: any;
25
- }
26
- export interface WorkoutCompleteNotification extends BaseNotification {
27
- type: 'workout-complete';
28
- workout_id: string;
29
- workout_title: string;
30
- }
31
- export interface WorkoutCompleteMobilePushData extends BaseMobilePushData {
32
- type: 'workout-complete';
33
- }
34
- export interface WorkoutMentionNotification extends BaseNotification {
35
- type: 'workout-mention';
36
- workout_id: string;
37
- workout_title: string;
38
- }
39
- export interface WorkoutMentionMobilePushData extends BaseMobilePushData {
40
- type: 'workout-mention';
41
- }
42
- export interface WorkoutCommentNotification extends BaseNotification {
43
- type: 'workout-comment';
44
- workout_id: string;
45
- workout_title: string;
46
- comment: string;
47
- }
48
- export interface WorkoutCommentMobilePushData extends BaseMobilePushData {
49
- type: 'workout-comment';
50
- }
51
- export interface WorkoutCommentDiscussionNotification extends BaseNotification {
52
- type: 'workout-comment-reply';
53
- workout_id: string;
54
- workout_title: string;
55
- comment: string;
56
- }
57
- export interface WorkoutCommentDiscussionMobilePushData extends BaseMobilePushData {
58
- type: 'workout-comment-reply';
59
- }
60
- export interface WorkoutCommentMentionNotification extends BaseNotification {
61
- type: 'workout-comment-mention';
62
- workout_id: string;
63
- workout_title: string;
64
- comment: string;
65
- }
66
- export interface WorkoutCommentMentionMobilePushData extends BaseMobilePushData {
67
- type: 'workout-comment-mention';
68
- }
69
- export interface WorkoutCommentReplyNotification extends BaseNotification {
70
- type: 'workout-comment-reply-v2';
71
- workout_id: string;
72
- workout_title: string;
73
- comment: string;
74
- }
75
- export interface WorkoutCommentReplyMobilePushData extends BaseMobilePushData {
76
- type: 'workout-comment-reply-v2';
77
- }
78
- export interface WorkoutLikeNotification extends BaseNotification {
79
- type: 'workout-like';
80
- workout_id: string;
81
- workout_title: string;
82
- }
83
- export interface WorkoutLikeMobilePushData extends BaseMobilePushData {
84
- type: 'workout-like';
85
- }
86
- export interface WorkoutCommentLikeNotification extends BaseNotification {
87
- type: 'workout-comment-like';
88
- workout_id: string;
89
- workout_title: string;
90
- comment_id: number;
91
- comment: string;
92
- }
93
- export interface WorkoutCommentLikeMobilePushData extends BaseMobilePushData {
94
- type: 'workout-comment-like';
95
- }
96
- export interface FollowNotification extends BaseNotification {
97
- type: 'follow';
98
- }
99
- export interface FollowMobilePushData extends BaseMobilePushData {
100
- type: 'follow';
101
- }
102
- export interface FollowRequestNotification extends BaseNotification {
103
- type: 'follow-request';
104
- }
105
- export interface FollowRequestMobilePushData extends BaseMobilePushData {
106
- type: 'follow-request';
107
- }
108
- export interface AcceptFollowRequestNotification extends BaseNotification {
109
- type: 'accept-follow-request';
110
- }
111
- export interface AcceptFollowRequestMobilePushData extends BaseMobilePushData {
112
- type: 'accept-follow-request';
113
- }
114
- export interface CoachClientInviteNotification extends BaseNotification {
115
- type: 'coach-client-invite';
116
- from_full_name?: string;
117
- }
118
- export interface CoachClientInviteMobilePushData extends BaseMobilePushData {
119
- type: 'coach-client-invite';
120
- }
121
- export interface ContactOnHevyNotification extends BaseNotification {
122
- type: 'contact-on-hevy';
123
- contact_name: string;
124
- }
125
- export interface ContactOnHevyMobilePushData extends BaseMobilePushData {
126
- type: 'contact-on-hevy';
127
- }
128
- /**
129
- * "Pushes": a push is basically a remote notification, NOT to be confused with a "notification", which is
130
- * a data type in the Hevy database
131
- */
132
- export type MobilePushDataType = NotificationMobilePushDataType | DataOnlyMobilePushDataType;
133
- /**
134
- * These types will have an alert/title, and will only be delivered if the user has given the notification
135
- * permission to the App
136
- */
137
- export type NotificationMobilePushDataType = NotificationType | 'chat-update' | 'coach-program-finishes-next-week' | 'coach-program-starts-today' | 'coach-logged-your-workout' | 'coach-logged-your-measurements' | 'monthly-report' | 'grace-period-enter' | 'grace-period-resolve';
138
- /**
139
- * These types CAN NOT have an alert/title, but may be delivered even if the user has not given the notification
140
- * permission and even if Hevy isn't running, although these should be treated as best effort
141
- * For iOS/Apple see https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app
142
- * For Android see https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages
143
- */
144
- export type DataOnlyMobilePushDataType = 'coach-data-changed' | 'coach-program-changed' | 'sync-workouts' | 'sync-routines' | 'sync-routine-folders' | 'sync-exercise-templates-and-customizations' | 'sync-account' | 'hevy-pro-status-changed' | 'hevy-pro-subscription-renewed' | 'new-notification' | never;
145
- export interface CoachDataChangedMobilePushData extends BaseMobilePushData {
146
- type: 'coach-data-changed';
147
- additionalHevyData: ClientsCoachData;
148
- }
149
- export interface CoachProgramChangedMobilePushData extends BaseMobilePushData {
150
- type: 'coach-program-changed';
151
- additionalHevyData: {
152
- program: Program | undefined;
153
- };
154
- }
155
- export interface HevyProSubscriptionRenewedMobilePushData extends BaseMobilePushData {
156
- type: 'hevy-pro-subscription-renewed';
157
- }
158
- export interface ProStatusChangedPushMobilePushData extends BaseMobilePushData {
159
- type: 'hevy-pro-status-changed';
160
- }
161
- export interface SyncWorkoutsMobilePushData extends BaseMobilePushData {
162
- type: 'sync-workouts';
163
- }
164
- export interface SyncRoutinesMobilePushData extends BaseMobilePushData {
165
- type: 'sync-routines';
166
- }
167
- export interface SyncRoutineFoldersMobilePushData extends BaseMobilePushData {
168
- type: 'sync-routine-folders';
169
- }
170
- export interface SyncCustomExercisesAndCoachCustomizationsMobilePushData extends BaseMobilePushData {
171
- type: 'sync-exercise-templates-and-customizations';
172
- }
173
- export interface SyncAccountMobilePushData extends BaseMobilePushData {
174
- type: 'sync-account';
175
- }
176
- export interface CoachProgramFinishesNextWeekMobilePushData extends BaseMobilePushData {
177
- type: 'coach-program-finishes-next-week';
178
- }
179
- export interface CoachProgramStartsTodayMobilePushData extends BaseMobilePushData {
180
- type: 'coach-program-starts-today';
181
- }
182
- export interface ChatUpdateMobilePushData extends BaseMobilePushData {
183
- type: 'chat-update';
184
- additionalHevyData: HevyChatUpdateMobilePushData;
185
- }
186
- export interface CoachLoggedYourWorkoutMobilePushData extends BaseMobilePushData {
187
- type: 'coach-logged-your-workout';
188
- additionalHevyData: {
189
- workoutId: string;
190
- };
191
- deeplink: string;
192
- }
193
- export interface CoachLoggedYourMeasurementsMobilePushData extends BaseMobilePushData {
194
- type: 'coach-logged-your-measurements';
195
- deeplink: string;
196
- }
197
- export interface MonthlyReportMobilePushData extends BaseMobilePushData {
198
- type: 'monthly-report';
199
- deeplink: string;
200
- }
201
- export interface GracePeriodEnterMobilePushData extends BaseMobilePushData {
202
- type: 'grace-period-enter';
203
- deeplink: string;
204
- }
205
- export interface GracePeriodResolveMobilePushData extends BaseMobilePushData {
206
- type: 'grace-period-resolve';
207
- deeplink: string;
208
- }
209
- export interface NewNotificationMobilePushData extends BaseMobilePushData {
210
- type: 'new-notification';
211
- additionalHevyData: {
212
- notificationDateISO: string;
213
- };
214
- }
215
- export type MobilePushData = ChatUpdateMobilePushData | SyncCustomExercisesAndCoachCustomizationsMobilePushData | SyncWorkoutsMobilePushData | SyncRoutineFoldersMobilePushData | SyncRoutinesMobilePushData | SyncAccountMobilePushData | ProStatusChangedPushMobilePushData | HevyProSubscriptionRenewedMobilePushData | CoachProgramChangedMobilePushData | CoachDataChangedMobilePushData | ContactOnHevyMobilePushData | CoachClientInviteMobilePushData | AcceptFollowRequestMobilePushData | FollowRequestMobilePushData | FollowMobilePushData | WorkoutLikeMobilePushData | WorkoutCommentLikeMobilePushData | WorkoutCommentMentionMobilePushData | WorkoutCommentDiscussionMobilePushData | WorkoutCommentReplyMobilePushData | WorkoutCommentMobilePushData | WorkoutMentionMobilePushData | WorkoutCompleteMobilePushData | CoachProgramFinishesNextWeekMobilePushData | CoachProgramStartsTodayMobilePushData | CoachLoggedYourWorkoutMobilePushData | CoachLoggedYourMeasurementsMobilePushData | MonthlyReportMobilePushData | GracePeriodEnterMobilePushData | GracePeriodResolveMobilePushData | NewNotificationMobilePushData;
@@ -1,9 +0,0 @@
1
- "use strict";
2
- /**
3
- * Notifications and Mobile pushes
4
- *
5
- * Notifications are types used for the in-app notification feed
6
- *
7
- * Mobile pushes are payloads delivered to mobile apps
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,14 +0,0 @@
1
- import { BaseRoutine, HevyTrainerRoutine, RoutineUpdate } from '.';
2
- import { NormalizedWorkout } from './normalizedWorkoutUtils';
3
- export declare const majorRoutineUpdate: (routine: BaseRoutine, workout: NormalizedWorkout) => RoutineUpdate;
4
- export declare const minorRoutineUpdate: (routine: BaseRoutine, workout: NormalizedWorkout) => RoutineUpdate;
5
- /**
6
- * Updates a Hevy Trainer routine with the workout data.
7
- * @param routine - The Hevy Trainer routine to update.
8
- * @param workout - The workout data to update the routine with.
9
- * @returns The updated routine.
10
- *
11
- * Only the rest timer seconds are updated for now.
12
- */
13
- export declare const trainerRoutineUpdate: (routine: HevyTrainerRoutine, workout: NormalizedWorkout) => RoutineUpdate;
14
- export type ViewRoutineSetValueType = 'weight' | 'reps' | 'rpe' | 'repRangeStart' | 'repRangeEnd' | 'distance' | 'duration' | 'short_distance' | 'custom_metric';