import { expandGlob } from '$std/fs/mod.ts' import { SessionHandlers } from ':src/session/mod.ts' import { respondApi } from ':src/utils.ts' import { BUILD_ID } from '$fresh/src/server/build_id.ts' import { encodeBase64 } from '@std/encoding' export type PrecacheResponse = { version: string; preCachedUrls: string[] } async function getVersion() { const versionBytes = new TextEncoder().encode(BUILD_ID) const versionHash = await crypto.subtle.digest('SHA-256', versionBytes) return encodeBase64(versionHash) } export const handler: SessionHandlers = { async GET() { try { const preCachedUrls: string[] = ['/', '/imports/markdown_css'] const paths = ['/static/**', '/_fresh/static/**'] const routes = '/routes/*/index.tsx' const version = await getVersion() //Pre-cache routes for await (const route of expandGlob(routes, { root: '.' })) { if (!route.isFile) continue //@ts-expect-error parentPath is missing from type definition preCachedUrls.push(strip(routes, route.parentPath)) } // Pre-cache files for (const path of paths) { for await (const entry of expandGlob(path, { root: '.' })) { if (!entry.isFile) continue preCachedUrls.push(strip(path, entry.path)) } } return respondApi<'success', PrecacheResponse>('success', { version, preCachedUrls, }) } catch (error) { return respondApi('error', error) } }, } function strip(root: string, path: string) { return path // Force unix/web separator .replaceAll('\\', '/') .replace( // Remove root slash and glob * root.slice(1).replaceAll('*', ''), '/', ) }