import { fetch } from '@frogpond/fetch' ; import type { RawCourseType , CourseType , TermType } from './types' ; import { COURSE_DATA_PAGE , INFO_PAGE } from './urls' ; import * as storage from '../storage' ; type TermInfoType = { files : Array < TermType > ; type : string ; } ; export async function areAnyTermsCached ( ) { const localTerms = await storage . getTermInfo ( ) ; return localTerms . length === 0 ? false : true ; } export async function updateStoredCourses ( ) { const outdatedTerms = await determineOutdatedTerms ( ) ; await Promise . all ( outdatedTerms . map ( ( term ) => storeTermCoursesFromServer ( term ) ) ) ; return outdatedTerms . length === 0 ? false : true ; } async function determineOutdatedTerms ( ) { const remoteTerms = await loadCurrentTermsFromServer ( ) ; const localTerms = await storage . getTermInfo ( ) ; if ( localTerms . length === 0 ) { await storage . setTermInfo ( remoteTerms ) ; return remoteTerms ; } const outdatedTerms = localTerms . filter ( ( localTerm ) => { const match = remoteTerms . find ( ( remoteTerm ) => remoteTerm . term === localTerm . term ) ; return match ? match . hash !== localTerm . hash : true ; } ) ; if ( outdatedTerms . length !== 0 ) { storage . setTermInfo ( remoteTerms ) ; } return outdatedTerms ; } async function loadCurrentTermsFromServer ( ) { const today = new Date ( ) ; const thisYear = today . getFullYear ( ) ; const resp = await fetch ( INFO_PAGE , { cache : 'no-store' } ) . json < TermInfoType > ( ) . catch ( ( ) => ( { files : [ ] , type : 'error' , } ) ) ; const terms = resp . files . filter ( ( file ) => file . type === 'json' && file . year > thisYear - 5 ) ; return terms ; } async function storeTermCoursesFromServer ( term ) { const url = COURSE_DATA_PAGE + term . path ; const resp = await fetch ( url , { cache : 'no-store' } ) . json < Array < RawCourseType > > ( ) . catch ( ( ) => [ ] ) ; const formattedTermData = formatRawData ( resp ) ; storage . setTermCourseData ( term . term , formattedTermData ) ; } function formatRawData ( rawData ) { return rawData . map ( ( course ) => { const spaceAvailable = course . enrolled < course . max ; return { spaceAvailable : spaceAvailable , ... course } ; } ) ; }