chore: moved temp script storage to idb (closes #1)
All checks were successful
Docs / build (push) Successful in 2m25s
All checks were successful
Docs / build (push) Successful in 2m25s
This commit is contained in:
parent
efbb7c0b11
commit
c2107bf01d
3 changed files with 70 additions and 22 deletions
|
@ -2,7 +2,8 @@ import { unknownToError } from '@fuman/utils'
|
|||
import { IS_SAFARI } from '../utils/env.ts'
|
||||
import { clearAvatarCache, handleAvatarRequest } from './avatar.ts'
|
||||
import { requestCache } from './cache.ts'
|
||||
import { clearCache, forgetScript, handleRuntimeRequest, uploadScript } from './runtime.ts'
|
||||
import { clearCache, handleRuntimeRequest } from './runtime.ts'
|
||||
import { forgetAllScripts, forgetScript, uploadScript } from './scripts.ts'
|
||||
|
||||
declare const self: ServiceWorkerGlobalScope
|
||||
|
||||
|
@ -70,6 +71,7 @@ function handleMessage(msg: SwMessage) {
|
|||
}
|
||||
case 'CLEAR_CACHE': {
|
||||
clearCache()
|
||||
forgetAllScripts()
|
||||
break
|
||||
}
|
||||
case 'CLEAR_AVATAR_CACHE': {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { utf8 } from '@fuman/utils'
|
||||
import { VfsStorage } from '../vfs/storage.ts'
|
||||
import { generateImportMap, generateRunnerHtml } from './iframe/html.ts'
|
||||
import { getScriptFile } from './scripts.ts'
|
||||
|
||||
const libraryCache = new Map<string, Map<string, Uint8Array>>()
|
||||
let importMapCache: Record<string, string> | undefined
|
||||
let vfs: VfsStorage | undefined
|
||||
|
||||
const scriptsStorage = new Map<string, string>()
|
||||
|
||||
async function getVfs() {
|
||||
if (!vfs) {
|
||||
vfs = await VfsStorage.create()
|
||||
|
@ -32,24 +31,8 @@ async function loadLibrary(name: string) {
|
|||
return map
|
||||
}
|
||||
|
||||
export function uploadScript(name: string, files: Record<string, string>) {
|
||||
for (const [fileName, contents] of Object.entries(files)) {
|
||||
scriptsStorage.set(`${name}/${fileName}`, contents)
|
||||
}
|
||||
}
|
||||
|
||||
export function forgetScript(name: string) {
|
||||
const folder = `${name}/`
|
||||
for (const path of scriptsStorage.keys()) {
|
||||
if (path.startsWith(folder)) {
|
||||
scriptsStorage.delete(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function clearCache() {
|
||||
libraryCache.clear()
|
||||
scriptsStorage.clear()
|
||||
importMapCache = undefined
|
||||
vfs = undefined
|
||||
}
|
||||
|
@ -80,12 +63,17 @@ export async function handleRuntimeRequest(url: URL) {
|
|||
}
|
||||
|
||||
if (path.startsWith('script/')) {
|
||||
const scriptId = path.slice('script/'.length)
|
||||
if (!scriptsStorage.has(scriptId)) {
|
||||
const scriptIdWithPath = path.slice('script/'.length)
|
||||
const idx = scriptIdWithPath.indexOf('/')
|
||||
const scriptId = scriptIdWithPath.slice(0, idx)
|
||||
const fileName = scriptIdWithPath.slice(idx + 1)
|
||||
|
||||
const file = await getScriptFile(scriptId, fileName)
|
||||
if (!file) {
|
||||
return new Response('Not found', { status: 404 })
|
||||
}
|
||||
|
||||
return new Response(scriptsStorage.get(scriptId)!, {
|
||||
return new Response(file, {
|
||||
headers: {
|
||||
'Content-Type': 'application/javascript',
|
||||
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
||||
|
|
58
packages/worker/src/sw/scripts.ts
Normal file
58
packages/worker/src/sw/scripts.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import type { DBSchema, IDBPDatabase } from 'idb'
|
||||
import { openDB } from 'idb'
|
||||
|
||||
interface Schema extends DBSchema {
|
||||
scripts: {
|
||||
key: string
|
||||
value: {
|
||||
id: string
|
||||
files: Record<string, string>
|
||||
}
|
||||
}
|
||||
}
|
||||
let db: IDBPDatabase<Schema> | undefined
|
||||
|
||||
async function getDb() {
|
||||
if (!db) {
|
||||
db = await openDB<Schema>('mtcute-repl-scripts', 1, {
|
||||
upgrade(db) {
|
||||
db.createObjectStore('scripts', { keyPath: 'id' })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
export async function uploadScript(id: string, files: Record<string, string>) {
|
||||
const db = await getDb()
|
||||
|
||||
await db.put('scripts', { id, files })
|
||||
}
|
||||
|
||||
const cachedScripts = new Map<string, Record<string, string>>()
|
||||
|
||||
export async function getScriptFile(id: string, fileName: string): Promise<string | null> {
|
||||
if (cachedScripts.has(id)) {
|
||||
return cachedScripts.get(id)![fileName]
|
||||
}
|
||||
|
||||
const db = await getDb()
|
||||
const res = await db.get('scripts', id)
|
||||
if (!res) return null
|
||||
|
||||
cachedScripts.set(id, res.files)
|
||||
return res.files[fileName]
|
||||
}
|
||||
|
||||
export async function forgetScript(id: string): Promise<void> {
|
||||
const db = await getDb()
|
||||
await db.delete('scripts', id)
|
||||
cachedScripts.delete(id)
|
||||
}
|
||||
|
||||
export async function forgetAllScripts(): Promise<void> {
|
||||
const db = await getDb()
|
||||
await db.clear('scripts')
|
||||
cachedScripts.clear()
|
||||
}
|
Loading…
Reference in a new issue