website/routes/api/serviceworker/precache.tsx

59 lines
1.6 KiB
TypeScript

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 versionRaw = crypto.randomUUID() + BUILD_ID
const versionBytes = new TextEncoder().encode(versionRaw)
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('*', ''),
'/',
)
}