@dgpholdings/greatoak-shared 1.2.86 → 1.2.88

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 (106) hide show
  1. package/README.md +148 -148
  2. package/dist/__mocks__/catalog.fixture.d.ts +2 -0
  3. package/dist/__mocks__/catalog.fixture.js +208 -0
  4. package/dist/__mocks__/exercises.mock.d.ts +4 -11
  5. package/dist/__mocks__/exercises.mock.js +82 -41
  6. package/dist/__mocks__/sessions.mock.d.ts +28 -0
  7. package/dist/__mocks__/sessions.mock.js +394 -0
  8. package/dist/__mocks__/testIds.d.ts +9 -0
  9. package/dist/__mocks__/testIds.js +13 -0
  10. package/dist/__mocks__/user.mock.js +3 -1
  11. package/dist/constants/goalJourney.d.ts +108 -0
  12. package/dist/constants/goalJourney.js +443 -0
  13. package/dist/constants/index.d.ts +1 -0
  14. package/dist/constants/index.js +1 -0
  15. package/dist/types/TApiAiExerciseAnalysis.d.ts +2 -1
  16. package/dist/types/TApiClientConstellation.d.ts +33 -0
  17. package/dist/types/TApiClientConstellation.js +13 -0
  18. package/dist/types/TApiExercise.d.ts +5 -3
  19. package/dist/types/TApiUser.d.ts +2 -0
  20. package/dist/types/index.d.ts +1 -0
  21. package/dist/utils/adoptionEngine/scaleProPlan.util.js +9 -4
  22. package/dist/utils/constellation/computeNormalisedLoad.d.ts +48 -0
  23. package/dist/utils/constellation/computeNormalisedLoad.js +150 -0
  24. package/dist/utils/constellation/computeNormalisedLoad.test.d.ts +1 -0
  25. package/dist/utils/constellation/computeNormalisedLoad.test.js +218 -0
  26. package/dist/utils/constellation/evaluateConstellation.d.ts +27 -0
  27. package/dist/utils/constellation/evaluateConstellation.js +135 -0
  28. package/dist/utils/constellation/evaluateConstellation.test.d.ts +1 -0
  29. package/dist/utils/constellation/evaluateConstellation.test.js +93 -0
  30. package/dist/utils/constellation/index.d.ts +18 -0
  31. package/dist/utils/constellation/index.js +29 -0
  32. package/dist/utils/constellation/levelThresholds.d.ts +99 -0
  33. package/dist/utils/constellation/levelThresholds.js +123 -0
  34. package/dist/utils/constellation/starFoundation.d.ts +25 -0
  35. package/dist/utils/constellation/starFoundation.js +54 -0
  36. package/dist/utils/constellation/starFoundation.test.d.ts +1 -0
  37. package/dist/utils/constellation/starFoundation.test.js +75 -0
  38. package/dist/utils/constellation/stars/consistency.d.ts +29 -0
  39. package/dist/utils/constellation/stars/consistency.js +142 -0
  40. package/dist/utils/constellation/stars/consistency.test.d.ts +1 -0
  41. package/dist/utils/constellation/stars/consistency.test.js +94 -0
  42. package/dist/utils/constellation/stars/lowerBody.d.ts +17 -0
  43. package/dist/utils/constellation/stars/lowerBody.js +30 -0
  44. package/dist/utils/constellation/stars/pull.d.ts +11 -0
  45. package/dist/utils/constellation/stars/pull.js +24 -0
  46. package/dist/utils/constellation/stars/push.d.ts +11 -0
  47. package/dist/utils/constellation/stars/push.js +24 -0
  48. package/dist/utils/constellation/stars/quality.d.ts +19 -0
  49. package/dist/utils/constellation/stars/quality.js +98 -0
  50. package/dist/utils/constellation/stars/quality.test.d.ts +1 -0
  51. package/dist/utils/constellation/stars/quality.test.js +113 -0
  52. package/dist/utils/constellation/stars/recovery.d.ts +29 -0
  53. package/dist/utils/constellation/stars/recovery.js +169 -0
  54. package/dist/utils/constellation/stars/recovery.test.d.ts +1 -0
  55. package/dist/utils/constellation/stars/recovery.test.js +131 -0
  56. package/dist/utils/constellation/strengthStar.test.d.ts +1 -0
  57. package/dist/utils/constellation/strengthStar.test.js +190 -0
  58. package/dist/utils/constellation/strengthStarHelpers.d.ts +41 -0
  59. package/dist/utils/constellation/strengthStarHelpers.js +104 -0
  60. package/dist/utils/constellation/types.d.ts +124 -0
  61. package/dist/utils/constellation/types.js +18 -0
  62. package/dist/utils/exerciseRecord/recordValidator.integration.test.js +1 -1
  63. package/dist/utils/exerciseRecord/recordValidator.js +1 -1
  64. package/dist/utils/exerciseRecord/recordValidator.test.js +8 -8
  65. package/dist/utils/index.d.ts +5 -3
  66. package/dist/utils/index.js +1 -0
  67. package/dist/utils/scoringWorkout/calculateQualityScore.d.ts +59 -36
  68. package/dist/utils/scoringWorkout/calculateQualityScore.js +234 -233
  69. package/dist/utils/scoringWorkout/computeMuscleFatigueMap.d.ts +8 -5
  70. package/dist/utils/scoringWorkout/computeMuscleFatigueMap.js +72 -88
  71. package/dist/utils/scoringWorkout/constants.d.ts +20 -6
  72. package/dist/utils/scoringWorkout/constants.js +23 -9
  73. package/dist/utils/scoringWorkout/helpers.d.ts +7 -0
  74. package/dist/utils/scoringWorkout/helpers.js +24 -18
  75. package/dist/utils/scoringWorkout/index.d.ts +12 -8
  76. package/dist/utils/scoringWorkout/index.js +23 -15
  77. package/dist/utils/scoringWorkout/parseRecords.js +4 -3
  78. package/dist/utils/scoringWorkout/scoringWorkout.integration.test.js +223 -185
  79. package/dist/utils/scoringWorkout/types.d.ts +34 -14
  80. package/package.json +31 -31
  81. package/dist/utils/exerciseRecord/__mocks__/exercises.mock.d.ts +0 -30
  82. package/dist/utils/exerciseRecord/__mocks__/exercises.mock.js +0 -138
  83. package/dist/utils/scaleProPlan.util.d.ts +0 -9
  84. package/dist/utils/scaleProPlan.util.js +0 -139
  85. package/dist/utils/scoring/calculateCalories.d.ts +0 -67
  86. package/dist/utils/scoring/calculateCalories.js +0 -345
  87. package/dist/utils/scoring/calculateMuscleFatiue.d.ts +0 -67
  88. package/dist/utils/scoring/calculateMuscleFatiue.js +0 -310
  89. package/dist/utils/scoring/calculateQualityScore.d.ts +0 -71
  90. package/dist/utils/scoring/calculateQualityScore.js +0 -334
  91. package/dist/utils/scoring/calculateTotalVolume.d.ts +0 -15
  92. package/dist/utils/scoring/calculateTotalVolume.js +0 -73
  93. package/dist/utils/scoring/constants.d.ts +0 -211
  94. package/dist/utils/scoring/constants.js +0 -247
  95. package/dist/utils/scoring/helpers.d.ts +0 -119
  96. package/dist/utils/scoring/helpers.js +0 -229
  97. package/dist/utils/scoring/index.d.ts +0 -28
  98. package/dist/utils/scoring/index.js +0 -47
  99. package/dist/utils/scoring/parseRecords.d.ts +0 -98
  100. package/dist/utils/scoring/parseRecords.js +0 -284
  101. package/dist/utils/scoring/types.d.ts +0 -86
  102. package/dist/utils/scoring/types.js +0 -11
  103. package/dist/utils/scoring.utils.d.ts +0 -14
  104. package/dist/utils/scoring.utils.js +0 -243
  105. /package/dist/utils/scoringWorkout/{calculateMuscleFatiue.d.ts → calculateMuscleFatigue.d.ts} +0 -0
  106. /package/dist/utils/scoringWorkout/{calculateMuscleFatiue.js → calculateMuscleFatigue.js} +0 -0
@@ -40,11 +40,7 @@ exports.mockExerciseWeightReps = {
40
40
  maximum: 300,
41
41
  optimalRange: [90, 180],
42
42
  },
43
- singleRep: {
44
- min: 2.0,
45
- max: 5.0,
46
- typical: 3.5,
47
- },
43
+ singleRep: { min: 2.0, max: 5.0, typical: 3.5 },
48
44
  },
49
45
  youtubeVideoUrl: ["https://youtube.com/watch?v=mock1"],
50
46
  modelVideoUrl: "https://example.com/mock-video.mp4",
@@ -52,12 +48,30 @@ exports.mockExerciseWeightReps = {
52
48
  instructionsHtml: "<ul><li>Mock instruction 1</li></ul>",
53
49
  importantTipsHtml: "<ul><li>Mock tip 1</li></ul>",
54
50
  popularityIndex: 90,
51
+ // Fields previously missing (the @ts-ignore):
52
+ movementPattern: "squat",
53
+ exerciseType: "compound",
54
+ stabilityDemand: "moderate",
55
+ progressionTier: "beginner",
55
56
  };
56
57
  /**
57
- * MOCK EXERCISE: Reps-Only
58
- * Simulates a bodyweight movement (e.g., Push-up).
58
+ * MOCK EXERCISE: Reps-Only (bodyweight push)
59
59
  */
60
- exports.mockExerciseRepsOnly = Object.assign(Object.assign({}, exports.mockExerciseWeightReps), { exerciseId: "mock-exercise-reps-only-456", name: "Generic Push-Up", status: "active", bodyPart: ["Chest", "Core"], recordType: "reps-only", primaryMuscles: ["pectoralis-major"], secondaryMuscles: ["tricep-brachii-lateral", "abs-lower"], trainingTypes: ["body-weight"], timingGuardrails: {
60
+ exports.mockExerciseRepsOnly = {
61
+ ...exports.mockExerciseWeightReps,
62
+ exerciseId: "mock-exercise-reps-only-456",
63
+ name: "Generic Push-Up",
64
+ status: "active",
65
+ bodyPart: ["Chest", "Core"],
66
+ recordType: "reps-only",
67
+ primaryMuscles: ["pectoralis-major"],
68
+ secondaryMuscles: ["tricep-brachii-lateral", "abs-lower"],
69
+ trainingTypes: ["body-weight"],
70
+ movementPattern: "push_horizontal",
71
+ exerciseType: "bodyweight",
72
+ bodyweightDependency: "high",
73
+ weightMultiplier: { male: 0.65, female: 0.6, default: 0.62 },
74
+ timingGuardrails: {
61
75
  type: "reps-only",
62
76
  stressRestBonus: 2,
63
77
  fatigueMultiplier: 1.05,
@@ -68,17 +82,25 @@ exports.mockExerciseRepsOnly = Object.assign(Object.assign({}, exports.mockExerc
68
82
  maximum: 180,
69
83
  optimalRange: [45, 90],
70
84
  },
71
- singleRep: {
72
- min: 1.0,
73
- max: 3.0,
74
- typical: 1.8,
75
- },
76
- } });
85
+ singleRep: { min: 1.0, max: 3.0, typical: 1.8 },
86
+ },
87
+ };
77
88
  /**
78
- * MOCK EXERCISE: Duration
79
- * Simulates an isometric hold (e.g., Plank).
89
+ * MOCK EXERCISE: Duration (isometric hold)
80
90
  */
81
- exports.mockExerciseDuration = Object.assign(Object.assign({}, exports.mockExerciseWeightReps), { exerciseId: "mock-exercise-duration-789", name: "Generic Forearm Plank", status: "active", bodyPart: ["Core"], recordType: "duration", primaryMuscles: ["abs-lower", "abs-upper"], secondaryMuscles: ["lower-back"], trainingTypes: ["body-weight", "isometric"], timingGuardrails: {
91
+ exports.mockExerciseDuration = {
92
+ ...exports.mockExerciseWeightReps,
93
+ exerciseId: "mock-exercise-duration-789",
94
+ name: "Generic Forearm Plank",
95
+ status: "active",
96
+ bodyPart: ["Core"],
97
+ recordType: "duration",
98
+ primaryMuscles: ["abs-lower", "abs-upper"],
99
+ secondaryMuscles: ["lower-back"],
100
+ trainingTypes: ["body-weight", "isometric"],
101
+ movementPattern: "core_stability",
102
+ exerciseType: "isometric",
103
+ timingGuardrails: {
82
104
  type: "duration",
83
105
  stressRestBonus: 3,
84
106
  fatigueMultiplier: 1.1,
@@ -89,17 +111,25 @@ exports.mockExerciseDuration = Object.assign(Object.assign({}, exports.mockExerc
89
111
  maximum: 120,
90
112
  optimalRange: [45, 60],
91
113
  },
92
- setDuration: {
93
- min: 15,
94
- max: 300,
95
- typical: 60,
96
- },
97
- } });
114
+ setDuration: { min: 15, max: 300, typical: 60 },
115
+ },
116
+ };
98
117
  /**
99
118
  * MOCK EXERCISE: Cardio-Machine
100
- * Simulates a machine cardio session (e.g., Treadmill).
101
119
  */
102
- exports.mockExerciseCardioMachine = Object.assign(Object.assign({}, exports.mockExerciseWeightReps), { exerciseId: "mock-exercise-cardio-machine-101", name: "Generic Treadmill Run", status: "active", bodyPart: ["Legs"], recordType: "cardio-machine", primaryMuscles: ["quadriceps", "hamstrings", "calves"], secondaryMuscles: ["glutes-maximus"], trainingTypes: ["cardio"], timingGuardrails: {
120
+ exports.mockExerciseCardioMachine = {
121
+ ...exports.mockExerciseWeightReps,
122
+ exerciseId: "mock-exercise-cardio-machine-101",
123
+ name: "Generic Treadmill Run",
124
+ status: "active",
125
+ bodyPart: ["Legs"],
126
+ recordType: "cardio-machine",
127
+ primaryMuscles: ["quadriceps", "hamstrings", "calves"],
128
+ secondaryMuscles: ["glutes-maximus"],
129
+ trainingTypes: ["cardio"],
130
+ movementPattern: "cardio",
131
+ exerciseType: "cardio",
132
+ timingGuardrails: {
103
133
  type: "cardio-machine",
104
134
  stressRestBonus: 0,
105
135
  fatigueMultiplier: 1.0,
@@ -110,31 +140,42 @@ exports.mockExerciseCardioMachine = Object.assign(Object.assign({}, exports.mock
110
140
  maximum: 300,
111
141
  optimalRange: [0, 60],
112
142
  },
113
- } });
143
+ },
144
+ };
114
145
  /**
115
146
  * MOCK EXERCISE: Cardio-Free
116
- * Simulates an outdoor/untracked cardio session (e.g., Outdoor Run).
117
147
  */
118
- exports.mockExerciseCardioFree = Object.assign(Object.assign({}, exports.mockExerciseWeightReps), { exerciseId: "mock-exercise-cardio-free-202", name: "Generic Outdoor Jog", status: "active", bodyPart: ["Legs"], recordType: "cardio-free", primaryMuscles: ["quadriceps", "hamstrings", "calves"], secondaryMuscles: ["glutes-maximus"], trainingTypes: ["cardio"], timingGuardrails: {
148
+ exports.mockExerciseCardioFree = {
149
+ ...exports.mockExerciseWeightReps,
150
+ exerciseId: "mock-exercise-cardio-free-202",
151
+ name: "Generic Outdoor Jog",
152
+ status: "active",
153
+ bodyPart: ["Legs"],
154
+ recordType: "cardio-free",
155
+ primaryMuscles: ["quadriceps", "hamstrings", "calves"],
156
+ secondaryMuscles: ["glutes-maximus"],
157
+ trainingTypes: ["cardio"],
158
+ movementPattern: "cardio",
159
+ exerciseType: "cardio",
160
+ timingGuardrails: {
119
161
  type: "cardio-free",
120
162
  stressRestBonus: 0,
121
163
  fatigueMultiplier: 1.0,
122
164
  setupTypicalSecs: 0,
123
- restPeriods: {
124
- minimum: 0,
125
- typical: 0,
126
- maximum: 300,
127
- optimalRange: [0, 0],
128
- },
129
- } });
130
- /**
131
- * MOCK EXERCISE: No Guardrails
132
- * Simulates an older DB entry or custom exercise missing guardrails.
133
- */
134
- exports.mockExerciseNoGuardrails = Object.assign(Object.assign({}, exports.mockExerciseWeightReps), { exerciseId: "mock-exercise-no-guardrails-303", name: "Legacy Exercise", status: "active", timingGuardrails: undefined });
165
+ restPeriods: { minimum: 0, typical: 0, maximum: 300, optimalRange: [0, 0] },
166
+ },
167
+ };
135
168
  /**
136
- * Helper dictionary containing all mock exercises mapped by their ID.
169
+ * MOCK EXERCISE: No Guardrails (legacy/custom entry)
137
170
  */
171
+ exports.mockExerciseNoGuardrails = {
172
+ ...exports.mockExerciseWeightReps,
173
+ exerciseId: "mock-exercise-no-guardrails-303",
174
+ name: "Legacy Exercise",
175
+ status: "active",
176
+ timingGuardrails: undefined,
177
+ };
178
+ /** All mock exercises mapped by id. */
138
179
  exports.mockExercisesDictionary = {
139
180
  [exports.mockExerciseWeightReps.exerciseId]: exports.mockExerciseWeightReps,
140
181
  [exports.mockExerciseRepsOnly.exerciseId]: exports.mockExerciseRepsOnly,
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Real workout-session records (verbatim shape as stored in CLIENT_WORKOUTS_TABLE),
3
+ * used to test the session loader's mapping and the constellation end-to-end
4
+ * against the real exercise catalog. clientId is rewired to MOCK_USER_ID.
5
+ *
6
+ * These reference real exercise IDs that exist in the production exercise
7
+ * snapshot, with real movement patterns (push_horizontal, squat, lunge, etc.).
8
+ */
9
+ export interface IStoredWorkoutSession {
10
+ pk: string;
11
+ sk: string;
12
+ clientId: string;
13
+ createdAt: string;
14
+ sessionId: string;
15
+ sessionRecord: {
16
+ exerciseId: string;
17
+ records: Record<string, unknown>[];
18
+ }[];
19
+ userDuration?: number;
20
+ expirationTime?: number;
21
+ }
22
+ /** Upper/push + accessory session (bench-pattern, triceps, shoulders). */
23
+ export declare const mockSessionPush: IStoredWorkoutSession;
24
+ /** Lower-body session (squat, lunge, plyo) — note several sets isDone:false. */
25
+ export declare const mockSessionLegs: IStoredWorkoutSession;
26
+ /** Short mixed session (abs, cardio-machine, duration) — recent. */
27
+ export declare const mockSessionMixed: IStoredWorkoutSession;
28
+ export declare const mockStoredSessions: IStoredWorkoutSession[];
@@ -0,0 +1,394 @@
1
+ "use strict";
2
+ // shared/src/__mocks__/sessions.mock.ts
3
+ /**
4
+ * Real workout-session records (verbatim shape as stored in CLIENT_WORKOUTS_TABLE),
5
+ * used to test the session loader's mapping and the constellation end-to-end
6
+ * against the real exercise catalog. clientId is rewired to MOCK_USER_ID.
7
+ *
8
+ * These reference real exercise IDs that exist in the production exercise
9
+ * snapshot, with real movement patterns (push_horizontal, squat, lunge, etc.).
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.mockStoredSessions = exports.mockSessionMixed = exports.mockSessionLegs = exports.mockSessionPush = void 0;
13
+ const testIds_1 = require("./testIds");
14
+ /** Upper/push + accessory session (bench-pattern, triceps, shoulders). */
15
+ exports.mockSessionPush = {
16
+ pk: testIds_1.MOCK_CLIENT_PK,
17
+ sk: "SESSION#2026-05-19T09:05:38.286Z#PERSONAL",
18
+ clientId: testIds_1.MOCK_USER_ID,
19
+ createdAt: "2026-05-19T09:47:09.418Z",
20
+ expirationTime: 1794736029,
21
+ sessionId: "QKB0lDAN_2sB3RbumAZ1O",
22
+ userDuration: 2491,
23
+ sessionRecord: [
24
+ {
25
+ exerciseId: "2tprDDd4_BsnK6gbMVWTQ",
26
+ records: [
27
+ {
28
+ auxWeightKg: "0",
29
+ durationMmSs: "00:30",
30
+ isDone: true,
31
+ isStrictMode: false,
32
+ type: "duration",
33
+ },
34
+ ],
35
+ },
36
+ {
37
+ exerciseId: "-SR_ogujWtdkH6EtCe2OQ",
38
+ records: [
39
+ {
40
+ auxWeightKg: "0",
41
+ isDone: true,
42
+ isStrictMode: false,
43
+ reps: "8",
44
+ type: "reps-only",
45
+ },
46
+ {
47
+ auxWeightKg: "0",
48
+ isDone: true,
49
+ isStrictMode: false,
50
+ reps: "8",
51
+ restDurationSecs: 90,
52
+ type: "reps-only",
53
+ },
54
+ {
55
+ auxWeightKg: "0",
56
+ isDone: true,
57
+ isStrictMode: false,
58
+ reps: "6",
59
+ type: "reps-only",
60
+ },
61
+ ],
62
+ },
63
+ {
64
+ exerciseId: "EA9B8p_H60pQPRBevjRj6",
65
+ records: [
66
+ {
67
+ auxWeightKg: "0",
68
+ isDone: true,
69
+ isStrictMode: false,
70
+ reps: "10",
71
+ type: "reps-only",
72
+ },
73
+ {
74
+ auxWeightKg: "0",
75
+ isDone: true,
76
+ isStrictMode: false,
77
+ reps: "9",
78
+ restDurationSecs: 90,
79
+ type: "reps-only",
80
+ },
81
+ {
82
+ auxWeightKg: "0",
83
+ isDone: true,
84
+ isStrictMode: false,
85
+ reps: "8",
86
+ restDurationSecs: 90,
87
+ type: "reps-only",
88
+ },
89
+ ],
90
+ },
91
+ {
92
+ exerciseId: "5LyI0el3TUJta6xLYdoua",
93
+ records: [
94
+ {
95
+ isDone: true,
96
+ isStrictMode: false,
97
+ kg: "20",
98
+ reps: "10",
99
+ type: "weight-reps",
100
+ },
101
+ {
102
+ isDone: true,
103
+ isStrictMode: false,
104
+ kg: "20",
105
+ reps: "9",
106
+ restDurationSecs: 90,
107
+ type: "weight-reps",
108
+ },
109
+ {
110
+ isDone: true,
111
+ isStrictMode: false,
112
+ kg: "20",
113
+ reps: "7",
114
+ restDurationSecs: 90,
115
+ type: "weight-reps",
116
+ },
117
+ ],
118
+ },
119
+ {
120
+ exerciseId: "RQCNQi0sw8icSqyhzytyS",
121
+ records: [
122
+ {
123
+ isDone: true,
124
+ isStrictMode: false,
125
+ kg: "26",
126
+ reps: "10",
127
+ type: "weight-reps",
128
+ },
129
+ {
130
+ isDone: true,
131
+ isStrictMode: false,
132
+ kg: "26",
133
+ reps: "10",
134
+ restDurationSecs: 60,
135
+ type: "weight-reps",
136
+ },
137
+ {
138
+ isDone: true,
139
+ isStrictMode: false,
140
+ kg: "26",
141
+ reps: "8",
142
+ restDurationSecs: 60,
143
+ type: "weight-reps",
144
+ },
145
+ ],
146
+ },
147
+ {
148
+ exerciseId: "cICiD8ldTl3TVKl_SZV4y",
149
+ records: [
150
+ {
151
+ isDone: true,
152
+ isStrictMode: false,
153
+ kg: "50",
154
+ reps: "8",
155
+ type: "weight-reps",
156
+ },
157
+ {
158
+ isDone: true,
159
+ isStrictMode: false,
160
+ kg: "50",
161
+ reps: "7",
162
+ restDurationSecs: 60,
163
+ type: "weight-reps",
164
+ },
165
+ {
166
+ isDone: true,
167
+ isStrictMode: false,
168
+ kg: "45",
169
+ reps: "7",
170
+ restDurationSecs: 60,
171
+ type: "weight-reps",
172
+ },
173
+ ],
174
+ },
175
+ {
176
+ exerciseId: "9W7Yon0FWh1Eqd52yjHV9",
177
+ records: [
178
+ {
179
+ auxWeightKg: "0",
180
+ durationMmSs: "01:13",
181
+ isDone: true,
182
+ isStrictMode: false,
183
+ type: "duration",
184
+ },
185
+ ],
186
+ },
187
+ ],
188
+ };
189
+ /** Lower-body session (squat, lunge, plyo) — note several sets isDone:false. */
190
+ exports.mockSessionLegs = {
191
+ pk: testIds_1.MOCK_CLIENT_PK,
192
+ sk: "SESSION#2026-04-29T07:47:53.111Z#PERSONAL",
193
+ clientId: testIds_1.MOCK_USER_ID,
194
+ createdAt: "2026-04-29T07:52:24.207Z",
195
+ expirationTime: 1793001144,
196
+ sessionId: "EASmO9MwSnNHKtCWseQzz",
197
+ userDuration: 271,
198
+ sessionRecord: [
199
+ {
200
+ exerciseId: "xNvol6-lFnHQUMCfxFMBD",
201
+ records: [
202
+ {
203
+ auxWeightKg: "0",
204
+ isDone: false,
205
+ isStrictMode: false,
206
+ reps: "15",
207
+ type: "reps-only",
208
+ },
209
+ {
210
+ auxWeightKg: "0",
211
+ isDone: false,
212
+ isStrictMode: false,
213
+ reps: "15",
214
+ type: "reps-only",
215
+ },
216
+ {
217
+ auxWeightKg: "0",
218
+ isDone: false,
219
+ isStrictMode: false,
220
+ reps: "15",
221
+ type: "reps-only",
222
+ },
223
+ ],
224
+ },
225
+ {
226
+ exerciseId: "D3XVV-ypHfraYO52eH9ur",
227
+ records: [
228
+ {
229
+ auxWeightKg: "0",
230
+ isDone: true,
231
+ isStrictMode: false,
232
+ reps: "10",
233
+ restDurationSecs: 60,
234
+ type: "reps-only",
235
+ },
236
+ {
237
+ auxWeightKg: "0",
238
+ isDone: false,
239
+ isStrictMode: false,
240
+ reps: "10",
241
+ restDurationSecs: 45,
242
+ type: "reps-only",
243
+ },
244
+ {
245
+ auxWeightKg: "0",
246
+ isDone: false,
247
+ isStrictMode: false,
248
+ reps: "10",
249
+ type: "reps-only",
250
+ },
251
+ ],
252
+ },
253
+ {
254
+ exerciseId: "cXExEzqEAF8YrFN2kAnIq",
255
+ records: [
256
+ {
257
+ auxWeightKg: "0",
258
+ isDone: true,
259
+ isStrictMode: false,
260
+ reps: "10",
261
+ rir: "0",
262
+ type: "reps-only",
263
+ },
264
+ {
265
+ auxWeightKg: "0",
266
+ isDone: true,
267
+ isStrictMode: false,
268
+ reps: "12",
269
+ restDurationSecs: 30,
270
+ rir: "0",
271
+ type: "reps-only",
272
+ },
273
+ {
274
+ auxWeightKg: "0",
275
+ isDone: true,
276
+ isStrictMode: false,
277
+ reps: "12",
278
+ rir: "0",
279
+ type: "reps-only",
280
+ },
281
+ ],
282
+ },
283
+ {
284
+ exerciseId: "3CkW5o5VQbCodRFmByeMc",
285
+ records: [
286
+ {
287
+ auxWeightKg: "0",
288
+ isDone: true,
289
+ isStrictMode: false,
290
+ reps: "10",
291
+ type: "reps-only",
292
+ },
293
+ {
294
+ auxWeightKg: "0",
295
+ isDone: false,
296
+ isStrictMode: false,
297
+ reps: "12",
298
+ type: "reps-only",
299
+ },
300
+ {
301
+ auxWeightKg: "0",
302
+ isDone: false,
303
+ isStrictMode: false,
304
+ reps: "12",
305
+ type: "reps-only",
306
+ },
307
+ ],
308
+ },
309
+ ],
310
+ };
311
+ /** Short mixed session (abs, cardio-machine, duration) — recent. */
312
+ exports.mockSessionMixed = {
313
+ pk: testIds_1.MOCK_CLIENT_PK,
314
+ sk: "SESSION#2026-06-05T19:39:08.048Z#PERSONAL",
315
+ clientId: testIds_1.MOCK_USER_ID,
316
+ createdAt: "2026-06-05T19:40:04.918Z",
317
+ expirationTime: 1796240404,
318
+ sessionId: "HauSJHH0Eo3clVrSmR9z7",
319
+ userDuration: 56,
320
+ sessionRecord: [
321
+ {
322
+ exerciseId: "S7Edj-DnCvOgYNv_0SlzP",
323
+ records: [
324
+ {
325
+ auxWeightKg: "0",
326
+ isDone: true,
327
+ isStrictMode: false,
328
+ reps: "10",
329
+ type: "reps-only",
330
+ },
331
+ {
332
+ auxWeightKg: "0",
333
+ isDone: true,
334
+ isStrictMode: false,
335
+ reps: "10",
336
+ type: "reps-only",
337
+ },
338
+ {
339
+ auxWeightKg: "0",
340
+ isDone: true,
341
+ isStrictMode: false,
342
+ reps: "10",
343
+ type: "reps-only",
344
+ },
345
+ ],
346
+ },
347
+ {
348
+ exerciseId: "_pz6syBDTeH36DFmg2VRy",
349
+ records: [
350
+ {
351
+ distance: "2",
352
+ durationMmSs: "15:00",
353
+ isDone: true,
354
+ isStrictMode: false,
355
+ speed: "8",
356
+ type: "cardio-machine",
357
+ },
358
+ {
359
+ distance: "2",
360
+ durationMmSs: "13:00",
361
+ isDone: true,
362
+ isStrictMode: false,
363
+ speed: "8",
364
+ type: "cardio-machine",
365
+ },
366
+ ],
367
+ },
368
+ {
369
+ exerciseId: "9W7Yon0FWh1Eqd52yjHV9",
370
+ records: [
371
+ {
372
+ auxWeightKg: "0",
373
+ durationMmSs: "00:00",
374
+ isDone: true,
375
+ isStrictMode: false,
376
+ type: "duration",
377
+ },
378
+ {
379
+ auxWeightKg: "0",
380
+ durationMmSs: "00:00",
381
+ isDone: true,
382
+ isStrictMode: false,
383
+ restDurationSecs: 10,
384
+ type: "duration",
385
+ },
386
+ ],
387
+ },
388
+ ],
389
+ };
390
+ exports.mockStoredSessions = [
391
+ exports.mockSessionPush,
392
+ exports.mockSessionLegs,
393
+ exports.mockSessionMixed,
394
+ ];
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Common identifiers for tests and fixtures. Keeping them here means a mock
3
+ * user, their session records, and any controller test all agree on the same
4
+ * id without magic strings scattered around.
5
+ */
6
+ /** The canonical test user. Used as both userId and the CLIENT#<id> partition. */
7
+ export declare const MOCK_USER_ID = "mock-user-123";
8
+ /** The DynamoDB partition key for that user's workout sessions. */
9
+ export declare const MOCK_CLIENT_PK = "CLIENT#mock-user-123";
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ // shared/src/__mocks__/testIds.ts
3
+ /**
4
+ * Common identifiers for tests and fixtures. Keeping them here means a mock
5
+ * user, their session records, and any controller test all agree on the same
6
+ * id without magic strings scattered around.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MOCK_CLIENT_PK = exports.MOCK_USER_ID = void 0;
10
+ /** The canonical test user. Used as both userId and the CLIENT#<id> partition. */
11
+ exports.MOCK_USER_ID = "mock-user-123";
12
+ /** The DynamoDB partition key for that user's workout sessions. */
13
+ exports.MOCK_CLIENT_PK = `CLIENT#${exports.MOCK_USER_ID}`;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mockUser = void 0;
4
+ const testIds_1 = require("./testIds");
4
5
  exports.mockUser = {
5
6
  // TUserPreferences fields (flat in TUserMetric)
6
7
  preferredDurationMinutes: 45,
@@ -18,8 +19,9 @@ exports.mockUser = {
18
19
  appLanguage: "en",
19
20
  preferencesUpdatedAt: new Date("2023-01-01").toISOString(),
20
21
  femaleHealth: null, // Male user
22
+ constellationLevel: 1,
21
23
  // TUserMetric-specific fields
22
- userId: "mock-user-123",
24
+ userId: testIds_1.MOCK_USER_ID,
23
25
  userCode: "MOCK123",
24
26
  userType: "regular",
25
27
  fullName: "Mock User",