44 */
55
66const GITHUB_BASE = 'https://raw.githubusercontent.com/RaidTheory/arcraiders-data/main' ;
7- const CACHE_TTL = 300 ; // 5 minutes
7+ const CACHE_TTL = 3600 ; // 1 hour - data doesn't change often
8+ const STALE_WHILE_REVALIDATE = 86400 ; // 24 hours - serve stale data while fetching fresh
89
910// Define valid data types and their paths
1011// For directory-based collections (multiple JSON files in folders)
@@ -30,12 +31,6 @@ export default {
3031 const url = new URL ( request . url ) ;
3132 const path = url . pathname ;
3233
33- // Enforce HTTPS - redirect HTTP to HTTPS
34- if ( url . protocol === 'http:' ) {
35- const httpsUrl = url . toString ( ) . replace ( 'http://' , 'https://' ) ;
36- return Response . redirect ( httpsUrl , 301 ) ;
37- }
38-
3934 // Handle CORS preflight
4035 if ( request . method === 'OPTIONS' ) {
4136 return handleCors ( ) ;
@@ -55,7 +50,9 @@ export default {
5550
5651 // Otherwise try as a collection list
5752 if ( COLLECTION_TYPES [ type ] ) {
58- return await handleList ( type , env , ctx ) ;
53+ // Check if user wants full data via ?full=true
54+ const full = url . searchParams . get ( 'full' ) === 'true' ;
55+ return await handleList ( type , env , ctx , full ) ;
5956 }
6057
6158 return jsonResponse ( { error : `Unknown data type: ${ type } ` } , 404 ) ;
@@ -133,7 +130,7 @@ async function handleSingleFile(type, env, ctx) {
133130 status : 200 ,
134131 headers : {
135132 'Content-Type' : 'application/json' ,
136- 'Cache-Control' : `public, max-age=${ CACHE_TTL } ` ,
133+ 'Cache-Control' : `public, max-age=${ CACHE_TTL } , stale-while-revalidate= ${ STALE_WHILE_REVALIDATE } ` ,
137134 } ,
138135 } ) ;
139136
@@ -179,7 +176,7 @@ async function handleGetItem(type, id, env, ctx) {
179176 status : 200 ,
180177 headers : {
181178 'Content-Type' : 'application/json' ,
182- 'Cache-Control' : `public, max-age=${ CACHE_TTL } ` ,
179+ 'Cache-Control' : `public, max-age=${ CACHE_TTL } , stale-while-revalidate= ${ STALE_WHILE_REVALIDATE } ` ,
183180 } ,
184181 } ) ;
185182
@@ -193,22 +190,24 @@ async function handleGetItem(type, id, env, ctx) {
193190/**
194191 * List all items of a type
195192 * Uses GitHub API to dynamically list directory contents
193+ * @param {boolean } full - If true, fetch and return full data for all items
196194 */
197- async function handleList ( type , env , ctx ) {
195+ async function handleList ( type , env , ctx , full = false ) {
198196 if ( ! COLLECTION_TYPES [ type ] ) {
199197 return jsonResponse ( { error : `Unknown collection type: ${ type } ` } , 404 ) ;
200198 }
201199
202200 const dirPath = COLLECTION_TYPES [ type ] ;
203201 const githubApiUrl = `https://api.github.com/repos/RaidTheory/arcraiders-data/contents/${ dirPath } ` ;
204202
205- // Check cache first
203+ // Different cache key for full vs list-only
204+ const cacheKeySuffix = full ? '?full=true' : '' ;
206205 const cache = caches . default ;
207- const cacheKey = new Request ( githubApiUrl ) ;
206+ const cacheKey = new Request ( githubApiUrl + cacheKeySuffix ) ;
208207 let response = await cache . match ( cacheKey ) ;
209208
210209 if ( ! response ) {
211- // Fetch from GitHub API
210+ // Fetch from GitHub API to get file list
212211 const githubResponse = await fetch ( githubApiUrl , {
213212 headers : {
214213 'User-Agent' : 'ArcRaiders-API/1.0' ,
@@ -222,24 +221,52 @@ async function handleList(type, env, ctx) {
222221
223222 const files = await githubResponse . json ( ) ;
224223
225- // Filter to only .json files and extract IDs
226- const items = files
224+ // Filter to only .json files
225+ const jsonFiles = files
227226 . filter ( ( f ) => f . type === 'file' && f . name . endsWith ( '.json' ) && ! f . name . startsWith ( '_' ) )
228- . map ( ( f ) => ( {
229- id : f . name . replace ( '.json' , '' ) ,
230- url : `/v1/${ type } /${ f . name . replace ( '.json' , '' ) } ` ,
231- } ) )
232- . sort ( ( a , b ) => a . id . localeCompare ( b . id ) ) ;
233-
234- const data = {
235- type,
236- count : items . length ,
237- items,
238- } ;
227+ . map ( ( f ) => f . name . replace ( '.json' , '' ) )
228+ . sort ( ( a , b ) => a . localeCompare ( b ) ) ;
229+
230+ let data ;
231+
232+ if ( full ) {
233+ // Fetch all item data in parallel
234+ const itemPromises = jsonFiles . map ( async ( id ) => {
235+ const itemUrl = `${ GITHUB_BASE } /${ dirPath } /${ id } .json` ;
236+ const itemResponse = await fetch ( itemUrl , {
237+ headers : { 'User-Agent' : 'ArcRaiders-API/1.0' } ,
238+ } ) ;
239+
240+ if ( itemResponse . ok ) {
241+ return await itemResponse . json ( ) ;
242+ }
243+ return null ;
244+ } ) ;
245+
246+ const itemsData = await Promise . all ( itemPromises ) ;
247+
248+ data = {
249+ type,
250+ count : itemsData . filter ( Boolean ) . length ,
251+ items : itemsData . filter ( Boolean ) ,
252+ } ;
253+ } else {
254+ // Just return IDs and URLs (original behavior)
255+ const items = jsonFiles . map ( ( id ) => ( {
256+ id,
257+ url : `/v1/${ type } /${ id } ` ,
258+ } ) ) ;
259+
260+ data = {
261+ type,
262+ count : items . length ,
263+ items,
264+ } ;
265+ }
239266
240267 // Create cacheable response
241268 response = jsonResponse ( data ) ;
242- response . headers . set ( 'Cache-Control' , `public, max-age=${ CACHE_TTL } ` ) ;
269+ response . headers . set ( 'Cache-Control' , `public, max-age=${ CACHE_TTL } , stale-while-revalidate= ${ STALE_WHILE_REVALIDATE } ` ) ;
243270
244271 // Store in cache (non-blocking)
245272 ctx . waitUntil ( cache . put ( cacheKey , response . clone ( ) ) ) ;
0 commit comments