@nickchristensen/cliftin 1.3.1 → 2.1.0
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/README.md +7 -7
- package/dist/commands/exercises/list.js +6 -2
- package/dist/commands/exercises/show.js +4 -12
- package/dist/commands/programs/list.js +6 -2
- package/dist/commands/workouts/list.js +3 -2
- package/dist/commands/workouts/show.js +1 -0
- package/dist/lib/db.d.ts +1 -0
- package/dist/lib/json-weight.js +33 -11
- package/dist/lib/repositories/exercises.js +15 -9
- package/dist/lib/repositories/workouts.js +2 -0
- package/dist/lib/types.d.ts +2 -0
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ DESCRIPTION
|
|
|
73
73
|
List exercises
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
_See code: [src/commands/exercises/list.ts](https://github.com/nickchristensen/cliftin/blob/
|
|
76
|
+
_See code: [src/commands/exercises/list.ts](https://github.com/nickchristensen/cliftin/blob/v2.1.0/src/commands/exercises/list.ts)_
|
|
77
77
|
|
|
78
78
|
## `cliftin exercises show SELECTOR`
|
|
79
79
|
|
|
@@ -107,7 +107,7 @@ DESCRIPTION
|
|
|
107
107
|
Show one exercise detail and history
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
_See code: [src/commands/exercises/show.ts](https://github.com/nickchristensen/cliftin/blob/
|
|
110
|
+
_See code: [src/commands/exercises/show.ts](https://github.com/nickchristensen/cliftin/blob/v2.1.0/src/commands/exercises/show.ts)_
|
|
111
111
|
|
|
112
112
|
## `cliftin help [COMMAND]`
|
|
113
113
|
|
|
@@ -144,7 +144,7 @@ DESCRIPTION
|
|
|
144
144
|
List programs
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
_See code: [src/commands/programs/list.ts](https://github.com/nickchristensen/cliftin/blob/
|
|
147
|
+
_See code: [src/commands/programs/list.ts](https://github.com/nickchristensen/cliftin/blob/v2.1.0/src/commands/programs/list.ts)_
|
|
148
148
|
|
|
149
149
|
## `cliftin programs show [SELECTOR]`
|
|
150
150
|
|
|
@@ -164,7 +164,7 @@ DESCRIPTION
|
|
|
164
164
|
Show one program hierarchy
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
_See code: [src/commands/programs/show.ts](https://github.com/nickchristensen/cliftin/blob/
|
|
167
|
+
_See code: [src/commands/programs/show.ts](https://github.com/nickchristensen/cliftin/blob/v2.1.0/src/commands/programs/show.ts)_
|
|
168
168
|
|
|
169
169
|
## `cliftin workouts list`
|
|
170
170
|
|
|
@@ -191,7 +191,7 @@ DESCRIPTION
|
|
|
191
191
|
List workouts
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
_See code: [src/commands/workouts/list.ts](https://github.com/nickchristensen/cliftin/blob/
|
|
194
|
+
_See code: [src/commands/workouts/list.ts](https://github.com/nickchristensen/cliftin/blob/v2.1.0/src/commands/workouts/list.ts)_
|
|
195
195
|
|
|
196
196
|
## `cliftin workouts next`
|
|
197
197
|
|
|
@@ -208,7 +208,7 @@ DESCRIPTION
|
|
|
208
208
|
Show the up-next routine from the active program
|
|
209
209
|
```
|
|
210
210
|
|
|
211
|
-
_See code: [src/commands/workouts/next.ts](https://github.com/nickchristensen/cliftin/blob/
|
|
211
|
+
_See code: [src/commands/workouts/next.ts](https://github.com/nickchristensen/cliftin/blob/v2.1.0/src/commands/workouts/next.ts)_
|
|
212
212
|
|
|
213
213
|
## `cliftin workouts show [WORKOUTID]`
|
|
214
214
|
|
|
@@ -228,5 +228,5 @@ DESCRIPTION
|
|
|
228
228
|
Show one workout with exercises and sets
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
-
_See code: [src/commands/workouts/show.ts](https://github.com/nickchristensen/cliftin/blob/
|
|
231
|
+
_See code: [src/commands/workouts/show.ts](https://github.com/nickchristensen/cliftin/blob/v2.1.0/src/commands/workouts/show.ts)_
|
|
232
232
|
<!-- commandsstop -->
|
|
@@ -36,8 +36,12 @@ export default class Exercises extends Command {
|
|
|
36
36
|
name: flags.name,
|
|
37
37
|
sort: flags.sort,
|
|
38
38
|
});
|
|
39
|
-
if (this.jsonEnabled())
|
|
40
|
-
return exercises
|
|
39
|
+
if (this.jsonEnabled()) {
|
|
40
|
+
return exercises.map(({ id, ...exercise }) => ({
|
|
41
|
+
...exercise,
|
|
42
|
+
exerciseId: id,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
41
45
|
this.log(renderTable(exercises.map((exercise) => ({
|
|
42
46
|
equipment: exercise.equipment,
|
|
43
47
|
id: exercise.id,
|
|
@@ -64,20 +64,11 @@ export default class ExercisesShow extends Command {
|
|
|
64
64
|
})),
|
|
65
65
|
topWeight: withWeightUnit(row.topWeight, historyUnitPreference),
|
|
66
66
|
}));
|
|
67
|
+
const { id: detailId, ...exerciseDetail } = detail;
|
|
67
68
|
return {
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
exerciseId: detailId,
|
|
70
|
+
...exerciseDetail,
|
|
70
71
|
history,
|
|
71
|
-
id: detail.id,
|
|
72
|
-
name: detail.name,
|
|
73
|
-
perceptionScale: detail.perceptionScale,
|
|
74
|
-
primaryMuscles: detail.primaryMuscles,
|
|
75
|
-
recentRoutines: detail.recentRoutines,
|
|
76
|
-
secondaryMuscles: detail.secondaryMuscles,
|
|
77
|
-
supports1RM: detail.supports1RM,
|
|
78
|
-
timerBased: detail.timerBased,
|
|
79
|
-
totalRoutines: detail.totalRoutines,
|
|
80
|
-
totalWorkouts: detail.totalWorkouts,
|
|
81
72
|
};
|
|
82
73
|
}
|
|
83
74
|
this.log(`[${detail.id}] ${detail.name ?? '(unnamed)'}`);
|
|
@@ -103,6 +94,7 @@ export default class ExercisesShow extends Command {
|
|
|
103
94
|
this.log('');
|
|
104
95
|
this.log(renderTable(lastPerformedSnapshot.exercise.sets.map((set) => ({
|
|
105
96
|
id: set.id,
|
|
97
|
+
isWarmup: set.isWarmup,
|
|
106
98
|
reps: set.reps,
|
|
107
99
|
rpe: set.rpe,
|
|
108
100
|
timeSeconds: set.timeSeconds,
|
|
@@ -10,8 +10,12 @@ export default class Programs extends Command {
|
|
|
10
10
|
const context = openDb();
|
|
11
11
|
try {
|
|
12
12
|
const programs = await listPrograms(context.db);
|
|
13
|
-
if (this.jsonEnabled())
|
|
14
|
-
return programs
|
|
13
|
+
if (this.jsonEnabled()) {
|
|
14
|
+
return programs.map(({ id, ...program }) => ({
|
|
15
|
+
...program,
|
|
16
|
+
programId: id,
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
15
19
|
this.log(renderTable(programs.map((program) => ({
|
|
16
20
|
dateAdded: program.dateAdded,
|
|
17
21
|
id: program.id,
|
|
@@ -35,12 +35,13 @@ export default class Workouts extends Command {
|
|
|
35
35
|
to: flags.to,
|
|
36
36
|
});
|
|
37
37
|
if (this.jsonEnabled()) {
|
|
38
|
-
return workouts.map((workout) => ({
|
|
38
|
+
return workouts.map(({ duration, id, ...workout }) => ({
|
|
39
39
|
...workout,
|
|
40
40
|
duration: {
|
|
41
41
|
unit: 'seconds',
|
|
42
|
-
value:
|
|
42
|
+
value: duration,
|
|
43
43
|
},
|
|
44
|
+
workoutId: id,
|
|
44
45
|
}));
|
|
45
46
|
}
|
|
46
47
|
this.log(renderTable(workouts.map((workout) => {
|
|
@@ -61,6 +61,7 @@ export default class WorkoutsShow extends Command {
|
|
|
61
61
|
this.log(`[${exercise.exerciseId ?? exercise.exerciseResultId}] ${exercise.name ?? '(unnamed)'}`);
|
|
62
62
|
this.log(renderTable(exercise.sets.map((set) => ({
|
|
63
63
|
id: set.id,
|
|
64
|
+
isWarmup: set.isWarmup,
|
|
64
65
|
reps: set.reps,
|
|
65
66
|
rpe: set.rpe,
|
|
66
67
|
timeSeconds: set.timeSeconds,
|
package/dist/lib/db.d.ts
CHANGED
package/dist/lib/json-weight.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { withWeightUnit } from './units.js';
|
|
2
|
+
function omitId(value) {
|
|
3
|
+
return Object.fromEntries(Object.entries(value).filter(([key]) => key !== 'id'));
|
|
4
|
+
}
|
|
2
5
|
export function serializeExerciseHistoryRowsWithWeightUnits(rows, unitPreference) {
|
|
3
6
|
return rows.map((row) => ({
|
|
4
7
|
...row,
|
|
@@ -6,46 +9,62 @@ export function serializeExerciseHistoryRowsWithWeightUnits(rows, unitPreference
|
|
|
6
9
|
}));
|
|
7
10
|
}
|
|
8
11
|
export function serializeProgramDetailWithWeightUnits(detail, unitPreference) {
|
|
12
|
+
const program = omitId(detail.program);
|
|
9
13
|
return {
|
|
10
|
-
...detail,
|
|
14
|
+
program: { ...program, programId: detail.program.id },
|
|
11
15
|
weeks: detail.weeks.map((week) => ({
|
|
12
|
-
...week,
|
|
13
16
|
routines: week.routines.map((routine) => ({
|
|
14
|
-
...routine,
|
|
17
|
+
...omitId(routine),
|
|
15
18
|
exercises: routine.exercises.map((exercise) => ({
|
|
16
|
-
...exercise,
|
|
19
|
+
...omitId(exercise),
|
|
20
|
+
exerciseId: exercise.id,
|
|
17
21
|
plannedWeight: withWeightUnit(exercise.plannedWeight, unitPreference),
|
|
18
22
|
sets: exercise.sets.map((set) => ({
|
|
19
|
-
...set,
|
|
23
|
+
...omitId(set),
|
|
24
|
+
setId: set.id,
|
|
20
25
|
weight: withWeightUnit(set.weight, unitPreference),
|
|
21
26
|
})),
|
|
22
27
|
})),
|
|
28
|
+
routineId: routine.id,
|
|
23
29
|
})),
|
|
30
|
+
weekId: week.id,
|
|
24
31
|
})),
|
|
25
32
|
};
|
|
26
33
|
}
|
|
27
34
|
export function serializeNextWorkoutDetailWithWeightUnits(detail, unitPreference) {
|
|
35
|
+
const program = omitId(detail.program);
|
|
28
36
|
return {
|
|
29
|
-
...detail,
|
|
37
|
+
program: { ...program, programId: detail.program.id },
|
|
30
38
|
routine: {
|
|
31
|
-
...detail.routine,
|
|
39
|
+
...omitId(detail.routine),
|
|
32
40
|
exercises: detail.routine.exercises.map((exercise) => ({
|
|
33
|
-
...exercise,
|
|
41
|
+
...omitId(exercise),
|
|
42
|
+
exerciseId: exercise.id,
|
|
34
43
|
plannedWeight: withWeightUnit(exercise.plannedWeight, unitPreference),
|
|
35
44
|
sets: exercise.sets.map((set) => ({
|
|
36
|
-
...set,
|
|
45
|
+
...omitId(set),
|
|
46
|
+
setId: set.id,
|
|
37
47
|
weight: withWeightUnit(set.weight, unitPreference),
|
|
38
48
|
})),
|
|
39
49
|
})),
|
|
50
|
+
routineId: detail.routine.id,
|
|
51
|
+
},
|
|
52
|
+
week: {
|
|
53
|
+
number: detail.week.number,
|
|
54
|
+
weekId: detail.week.id,
|
|
40
55
|
},
|
|
41
56
|
};
|
|
42
57
|
}
|
|
43
58
|
export function serializeWorkoutDetailWithWeightUnits(detail, unitPreference) {
|
|
44
59
|
return {
|
|
45
|
-
|
|
60
|
+
date: detail.date,
|
|
61
|
+
duration: detail.duration,
|
|
46
62
|
exercises: detail.exercises.map((exercise) => ({
|
|
47
|
-
|
|
63
|
+
exerciseId: exercise.exerciseId,
|
|
64
|
+
exerciseResultId: exercise.exerciseResultId,
|
|
65
|
+
name: exercise.name,
|
|
48
66
|
sets: exercise.sets.map((set) => ({
|
|
67
|
+
isWarmup: set.isWarmup,
|
|
49
68
|
reps: set.reps,
|
|
50
69
|
rpe: set.rpe,
|
|
51
70
|
setId: set.id,
|
|
@@ -54,5 +73,8 @@ export function serializeWorkoutDetailWithWeightUnits(detail, unitPreference) {
|
|
|
54
73
|
weight: withWeightUnit(set.weight, unitPreference),
|
|
55
74
|
})),
|
|
56
75
|
})),
|
|
76
|
+
program: detail.program,
|
|
77
|
+
routine: detail.routine,
|
|
78
|
+
workoutId: detail.id,
|
|
57
79
|
};
|
|
58
80
|
}
|
|
@@ -7,6 +7,11 @@ import { getWorkoutDetail } from './workouts.js';
|
|
|
7
7
|
function asBool(value) {
|
|
8
8
|
return value === 1;
|
|
9
9
|
}
|
|
10
|
+
const workingSetCountExpr = sql `sum(case when gs.Z_PK is not null and coalesce(gs.ZWARMUPSET, 0) != 1 then 1 else 0 end)`;
|
|
11
|
+
const workingSetTotalRepsExpr = sql `coalesce(sum(case when coalesce(gs.ZWARMUPSET, 0) != 1 then gs.ZREPS else 0 end), 0)`;
|
|
12
|
+
const workingSetTopRepsExpr = sql `max(case when coalesce(gs.ZWARMUPSET, 0) != 1 then gs.ZREPS end)`;
|
|
13
|
+
const workingSetTopWeightExpr = sql `max(case when coalesce(gs.ZWARMUPSET, 0) != 1 then gs.ZWEIGHT end)`;
|
|
14
|
+
const workingSetVolumeExpr = sql `coalesce(sum(case when coalesce(gs.ZWARMUPSET, 0) != 1 then gs.ZVOLUME else 0 end), 0)`;
|
|
10
15
|
function renderSelectorCandidateList(candidates) {
|
|
11
16
|
return candidates
|
|
12
17
|
.map((candidate) => ({
|
|
@@ -142,11 +147,11 @@ export async function getExerciseHistoryRows(db, exerciseId, filters) {
|
|
|
142
147
|
'wr.ZSTARTDATE as startDate',
|
|
143
148
|
'wr.ZROUTINENAME as routineNameFromResult',
|
|
144
149
|
'r.ZNAME as routineNameFromPlan',
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
workingSetCountExpr.as('sets'),
|
|
151
|
+
workingSetTotalRepsExpr.as('totalReps'),
|
|
152
|
+
workingSetTopRepsExpr.as('topReps'),
|
|
153
|
+
workingSetTopWeightExpr.as('topWeight'),
|
|
154
|
+
workingSetVolumeExpr.as('volume'),
|
|
150
155
|
])
|
|
151
156
|
.where('ei.Z_PK', '=', exerciseId)
|
|
152
157
|
.groupBy(['wr.Z_PK', 'wr.ZSTARTDATE', 'wr.ZROUTINENAME', 'r.ZNAME'])
|
|
@@ -164,13 +169,13 @@ export async function getExerciseHistoryRows(db, exerciseId, filters) {
|
|
|
164
169
|
if (dateRange.to !== undefined)
|
|
165
170
|
query = query.where('wr.ZSTARTDATE', '<=', dateRange.to);
|
|
166
171
|
if (filters.minReps !== undefined)
|
|
167
|
-
query = query.having(
|
|
172
|
+
query = query.having(workingSetTopRepsExpr, '>=', filters.minReps);
|
|
168
173
|
if (filters.maxReps !== undefined)
|
|
169
|
-
query = query.having(
|
|
174
|
+
query = query.having(workingSetTopRepsExpr, '<=', filters.maxReps);
|
|
170
175
|
if (minWeightKg !== undefined)
|
|
171
|
-
query = query.having(
|
|
176
|
+
query = query.having(workingSetTopWeightExpr, '>=', minWeightKg);
|
|
172
177
|
if (maxWeightKg !== undefined)
|
|
173
|
-
query = query.having(
|
|
178
|
+
query = query.having(workingSetTopWeightExpr, '<=', maxWeightKg);
|
|
174
179
|
if (filters.limit !== undefined)
|
|
175
180
|
query = query.limit(filters.limit);
|
|
176
181
|
const rows = await query.execute();
|
|
@@ -199,6 +204,7 @@ export async function getExerciseHistoryWithSetsRows(db, exerciseId, filters) {
|
|
|
199
204
|
date: summary.date,
|
|
200
205
|
routine: summary.routine,
|
|
201
206
|
sets: (exercise?.sets ?? []).map((set) => ({
|
|
207
|
+
isWarmup: set.isWarmup,
|
|
202
208
|
reps: set.reps,
|
|
203
209
|
setId: set.id,
|
|
204
210
|
timeSeconds: set.timeSeconds,
|
|
@@ -136,6 +136,7 @@ export async function getWorkoutDetail(db, workoutId) {
|
|
|
136
136
|
'ZWEIGHT as weight',
|
|
137
137
|
'ZTIME as timeSeconds',
|
|
138
138
|
'ZVOLUME as volume',
|
|
139
|
+
'ZWARMUPSET as warmupSet',
|
|
139
140
|
])
|
|
140
141
|
.where('ZEXERCISE', 'in', exerciseResultIds)
|
|
141
142
|
.orderBy('Z_FOK_EXERCISE', 'asc')
|
|
@@ -148,6 +149,7 @@ export async function getWorkoutDetail(db, workoutId) {
|
|
|
148
149
|
const current = setsByExercise.get(row.exerciseResultId) ?? [];
|
|
149
150
|
current.push({
|
|
150
151
|
id: row.id,
|
|
152
|
+
isWarmup: asBool(row.warmupSet),
|
|
151
153
|
reps: row.reps,
|
|
152
154
|
rpe: normalizeRpe(row.rpe),
|
|
153
155
|
timeSeconds: row.timeSeconds,
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ export type WorkoutSummary = {
|
|
|
48
48
|
};
|
|
49
49
|
export type WorkoutSet = {
|
|
50
50
|
id: number;
|
|
51
|
+
isWarmup: boolean;
|
|
51
52
|
reps: null | number;
|
|
52
53
|
rpe: null | number;
|
|
53
54
|
timeSeconds: null | number;
|
|
@@ -98,6 +99,7 @@ export type ExerciseHistoryRow = {
|
|
|
98
99
|
workoutId: number;
|
|
99
100
|
};
|
|
100
101
|
export type ExerciseHistorySet = {
|
|
102
|
+
isWarmup: boolean;
|
|
101
103
|
reps: null | number;
|
|
102
104
|
setId: number;
|
|
103
105
|
timeSeconds: null | number;
|
package/oclif.manifest.json
CHANGED