async function refreshAthlete(athlete, after = false, verbose = false) {
  // Get user document
  const athleteDoc = typeof athlete === 'number'
    ? await Athlete.findById(athlete)
    : athlete;

  // Fetch activities
  const fetchTimestamp = after
    || await getFetchTimestampFromAthlete(athleteDoc, verbose);

  console.log(`\n----\nFetching new activities for ${athleteDoc.get('athlete.firstname')} ${athleteDoc.get('athlete.lastname')} (${athleteDoc.get('_id')}) since ${timestampToISOString(fetchTimestamp)}`);

  // Get activities that *might* have laps
  const eligibleActivities = await fetchAthleteActivities(
    athleteDoc,
    fetchTimestamp,
    verbose,
  );

  if (!eligibleActivities.length) {
    console.log(`No eligible activities for user ${athleteDoc.get('_id')}`);
    return;
  }

  // Add new activities to database
  // @note Use new token refresh logic
  const activitiesWithLaps = await fetchLapsFromActivities(
    eligibleActivities,
    athleteDoc.get('access_token'),
    verbose,
  );

  if (!activitiesWithLaps.length) {
    console.log(`No new activities *with laps* for user ${athleteDoc.get('_id')}`);
    return;
  }

  // Filter for valid activities
  const filtered = activitiesWithLaps.reduce((acc, activity) => {
    const activityDoc = new Activity(activity);
    // Mongoose returns error here instead of throwing
    const err = activityDoc.validateSync();
    if (err) {
      console.warn(`Failed to validate activity ${activity.get('_id')}`);
    } else {
      acc.push(activityDoc);
    }
    return acc;
  }, []);

  await Activity.create(filtered);
  console.log(`Created ${filtered.length} new activities`);

  // Merge into user document's stats
  const stats = await compileStatsForActivities(
    filtered,
    athleteDoc.toJSON().stats,
  );
  console.log(`Found ${stats.allTime - athleteDoc.get('stats.allTime')} new laps`);

  await updateAthleteStats(athleteDoc, stats);
}
/**
 * Get athlete's laps since last_update and update their stats
 *
 * @param {Number|Document} athlete ID or Document
 * @param {Number} after Optional UTC *seconds* to override last_updated
 * @param {Boolean} verbose Defaults to false
 */
Get athlete's laps since last_update and update their stats
@param {Number|Document} athlete ID or Document
@param {Number} after Optional UTC *seconds* to override last_updated
@param {Boolean} verbose Defaults to false
Get athlete ' s laps since last_update and update their stats @param { Number|Document } athlete ID or Document @param { Number } after Optional UTC * seconds * to override last_updated @param { Boolean } verbose Defaults to false
async function refreshAthlete(athlete, after = false, verbose = false) {
  const athleteDoc = typeof athlete === 'number'
    ? await Athlete.findById(athlete)
    : athlete;
  const fetchTimestamp = after
    || await getFetchTimestampFromAthlete(athleteDoc, verbose);
  console.log(`\n----\nFetching new activities for ${athleteDoc.get('athlete.firstname')} ${athleteDoc.get('athlete.lastname')} (${athleteDoc.get('_id')}) since ${timestampToISOString(fetchTimestamp)}`);
  const eligibleActivities = await fetchAthleteActivities(
    athleteDoc,
    fetchTimestamp,
    verbose,
  );
  if (!eligibleActivities.length) {
    console.log(`No eligible activities for user ${athleteDoc.get('_id')}`);
    return;
  }
  const activitiesWithLaps = await fetchLapsFromActivities(
    eligibleActivities,
    athleteDoc.get('access_token'),
    verbose,
  );
  if (!activitiesWithLaps.length) {
    console.log(`No new activities *with laps* for user ${athleteDoc.get('_id')}`);
    return;
  }
  const filtered = activitiesWithLaps.reduce((acc, activity) => {
    const activityDoc = new Activity(activity);
    const err = activityDoc.validateSync();
    if (err) {
      console.warn(`Failed to validate activity ${activity.get('_id')}`);
    } else {
      acc.push(activityDoc);
    }
    return acc;
  }, []);
  await Activity.create(filtered);
  console.log(`Created ${filtered.length} new activities`);
  const stats = await compileStatsForActivities(
    filtered,
    athleteDoc.toJSON().stats,
  );
  console.log(`Found ${stats.allTime - athleteDoc.get('stats.allTime')} new laps`);
  await updateAthleteStats(athleteDoc, stats);
}
async function refreshAthlete ( athlete , after = false , verbose = false ) { const athleteDoc = typeof athlete === 'number' ? await Athlete . findById ( athlete ) : athlete ; const fetchTimestamp = after || await getFetchTimestampFromAthlete ( athleteDoc , verbose ) ; console . log ( ` \n \n ${ athleteDoc . get ( 'athlete.firstname' ) } ${ athleteDoc . get ( 'athlete.lastname' ) } ${ athleteDoc . get ( '_id' ) } ${ timestampToISOString ( fetchTimestamp ) } ` ) ; const eligibleActivities = await fetchAthleteActivities ( athleteDoc , fetchTimestamp , verbose , ) ; if ( ! eligibleActivities . length ) { console . log ( ` ${ athleteDoc . get ( '_id' ) } ` ) ; return ; } const activitiesWithLaps = await fetchLapsFromActivities ( eligibleActivities , athleteDoc . get ( 'access_token' ) , verbose , ) ; if ( ! activitiesWithLaps . length ) { console . log ( ` ${ athleteDoc . get ( '_id' ) } ` ) ; return ; } const filtered = activitiesWithLaps . reduce ( ( acc , activity ) => { const activityDoc = new Activity ( activity ) ; const err = activityDoc . validateSync ( ) ; if ( err ) { console . warn ( ` ${ activity . get ( '_id' ) } ` ) ; } else { acc . push ( activityDoc ) ; } return acc ; } , [ ] ) ; await Activity . create ( filtered ) ; console . log ( ` ${ filtered . length } ` ) ; const stats = await compileStatsForActivities ( filtered , athleteDoc . toJSON ( ) . stats , ) ; console . log ( ` ${ stats . allTime - athleteDoc . get ( 'stats.allTime' ) } ` ) ; await updateAthleteStats ( athleteDoc , stats ) ; }
Get athlete's laps since last_update and update their stats
 @param {Number|Document} athlete ID or Document
 @param {Number} after Optional UTC *seconds* to override last_updated
 @param {Boolean} verbose Defaults to false
Get athlete ' s laps since last_update and update their stats @param { Number|Document } athlete ID or Document @param { Number } after Optional UTC * seconds * to override last_updated @param { Boolean } verbose Defaults to false
// Get user document // Fetch activities // Get activities that *might* have laps // Add new activities to database // @note Use new token refresh logic // Filter for valid activities // Mongoose returns error here instead of throwing // Merge into user document's stats