trainingpeaks-sdk
Version:
TypeScript SDK for TrainingPeaks API integration
71 lines (70 loc) • 2.6 kB
JavaScript
import { z } from 'zod';
import { ElementType, IntensityClass, IntensityMetric, IntensityTargetType, LengthMetric, LengthUnit, } from '../../types/index.js';
export const WorkoutLengthUnitSchema = z.nativeEnum(LengthUnit);
export const WorkoutIntensityClassSchema = z.nativeEnum(IntensityClass);
export const WorkoutLengthMetricSchema = z.nativeEnum(LengthMetric);
export const WorkoutIntensityMetricSchema = z.nativeEnum(IntensityMetric);
export const WorkoutIntensityTargetTypeSchema = z.nativeEnum(IntensityTargetType);
export const WorkoutLengthSchema = z.object({
value: z.number().nonnegative().finite(),
unit: WorkoutLengthUnitSchema,
});
export const WorkoutTargetSchema = z
.object({
minValue: z.number().nonnegative().finite(),
maxValue: z.number().nonnegative().finite(),
})
.refine((data) => data.minValue <= data.maxValue, {
message: 'minValue cannot be greater than maxValue',
path: ['minValue'],
});
export const WorkoutStepSchema = z
.object({
name: z.string().min(1).max(100),
length: WorkoutLengthSchema,
targets: z.array(WorkoutTargetSchema),
intensityClass: WorkoutIntensityClassSchema,
openDuration: z.boolean().default(false),
})
.refine((data) => {
if (data.intensityClass === IntensityClass.REST)
return true;
return data.targets.length > 0;
}, {
message: 'Non-rest steps must have at least one target',
path: ['targets'],
});
export const WorkoutElementTypeSchema = z.nativeEnum(ElementType);
export const WorkoutStructureElementSchema = z
.object({
type: WorkoutElementTypeSchema,
length: WorkoutLengthSchema,
steps: z.array(WorkoutStepSchema).min(1),
begin: z.number().nonnegative(),
end: z.number().nonnegative(),
})
.refine((data) => data.end > data.begin, {
message: 'end time must be greater than begin time',
path: ['end'],
});
export const WorkoutStructureSchema = z
.object({
structure: z.array(WorkoutStructureElementSchema).min(1),
polyline: z.array(z.array(z.number())),
primaryLengthMetric: WorkoutLengthMetricSchema,
primaryIntensityMetric: WorkoutIntensityMetricSchema,
primaryIntensityTargetOrRange: WorkoutIntensityTargetTypeSchema,
})
.refine((data) => {
for (let i = 0; i < data.structure.length - 1; i++) {
const current = data.structure[i];
const next = data.structure[i + 1];
if (current && next && current.end > next.begin) {
return false;
}
}
return true;
}, {
message: 'Workout structure elements cannot overlap',
path: ['structure'],
});