trainingpeaks-sdk
Version:
TypeScript SDK for TrainingPeaks API integration
98 lines (97 loc) • 4.21 kB
JavaScript
import { ValidationError } from '../../domain/errors/domain-errors.js';
import { WorkoutValidationError } from '../../domain/errors/workout-errors.js';
export const calculateWorkoutDuration = (structure) => {
return structure.structure.reduce((sum, element) => {
return sum + element.length.value;
}, 0);
};
export const createWorkout = (id, name, date, duration, description, distance, activityType, structure, fileContent, fileName) => {
if (!id || id.trim().length === 0) {
throw new ValidationError('Workout ID cannot be empty', 'id');
}
if (!name || name.trim().length === 0) {
throw new ValidationError('Workout name cannot be empty', 'name');
}
if (name.trim().length > 200) {
throw new ValidationError('Workout name cannot exceed 200 characters', 'name');
}
if (duration < 0) {
throw new ValidationError('Workout duration cannot be negative', 'duration');
}
if (!isFinite(duration)) {
throw new ValidationError('Workout duration must be a finite number', 'duration');
}
if (distance !== undefined && (distance < 0 || !isFinite(distance))) {
throw new ValidationError('Workout distance must be a non-negative finite number', 'distance');
}
if (description && description.length > 1000) {
throw new ValidationError('Workout description cannot exceed 1000 characters', 'description');
}
if (activityType && activityType.trim().length > 50) {
throw new ValidationError('Activity type cannot exceed 50 characters', 'activityType');
}
if (fileName && fileName.trim().length > 255) {
throw new ValidationError('File name cannot exceed 255 characters', 'fileName');
}
const now = new Date();
return {
id: id.trim(),
name: name.trim(),
description: description?.trim() || '',
date,
duration,
distance,
activityType: activityType?.trim(),
structure,
fileContent,
fileName: fileName?.trim(),
createdAt: now,
updatedAt: now,
};
};
export const createStructuredWorkout = (id, name, date, structure, description, activityType) => {
if (!structure) {
throw new WorkoutValidationError('Workout structure is required for structured workout');
}
if (!structure.structure || structure.structure.length === 0) {
throw new WorkoutValidationError('Workout structure must contain at least one element');
}
const totalDuration = calculateWorkoutDuration(structure);
return createWorkout(id, name, date, totalDuration, description, undefined, activityType, structure);
};
export const updateWorkout = (workout, updates) => {
if (updates.name !== undefined &&
(!updates.name || updates.name.trim().length === 0)) {
throw new ValidationError('Workout name cannot be empty', 'name');
}
if (updates.name && updates.name.trim().length > 200) {
throw new ValidationError('Workout name cannot exceed 200 characters', 'name');
}
if (updates.description && updates.description.length > 1000) {
throw new ValidationError('Workout description cannot exceed 1000 characters', 'description');
}
if (updates.distance !== undefined &&
(updates.distance < 0 || !isFinite(updates.distance))) {
throw new ValidationError('Workout distance must be a non-negative finite number', 'distance');
}
if (updates.activityType && updates.activityType.trim().length > 50) {
throw new ValidationError('Activity type cannot exceed 50 characters', 'activityType');
}
return {
...workout,
...updates,
name: updates.name?.trim() || workout.name,
description: updates.description?.trim() ?? workout.description,
activityType: updates.activityType?.trim() ?? workout.activityType,
updatedAt: new Date(),
};
};
export const isStructuredWorkout = (workout) => {
return Boolean(workout.structure && workout.structure.structure.length > 0);
};
export const getWorkoutDistance = (workout) => {
if (workout.distance !== undefined) {
return workout.distance;
}
return undefined;
};