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 { IS_SAFARI } from '../utils/env.ts'
|
||||||
import { clearAvatarCache, handleAvatarRequest } from './avatar.ts'
|
import { clearAvatarCache, handleAvatarRequest } from './avatar.ts'
|
||||||
import { requestCache } from './cache.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
|
declare const self: ServiceWorkerGlobalScope
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ function handleMessage(msg: SwMessage) {
|
||||||
}
|
}
|
||||||
case 'CLEAR_CACHE': {
|
case 'CLEAR_CACHE': {
|
||||||
clearCache()
|
clearCache()
|
||||||
|
forgetAllScripts()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'CLEAR_AVATAR_CACHE': {
|
case 'CLEAR_AVATAR_CACHE': {
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import { utf8 } from '@fuman/utils'
|
import { utf8 } from '@fuman/utils'
|
||||||
import { VfsStorage } from '../vfs/storage.ts'
|
import { VfsStorage } from '../vfs/storage.ts'
|
||||||
import { generateImportMap, generateRunnerHtml } from './iframe/html.ts'
|
import { generateImportMap, generateRunnerHtml } from './iframe/html.ts'
|
||||||
|
import { getScriptFile } from './scripts.ts'
|
||||||
|
|
||||||
const libraryCache = new Map<string, Map<string, Uint8Array>>()
|
const libraryCache = new Map<string, Map<string, Uint8Array>>()
|
||||||
let importMapCache: Record<string, string> | undefined
|
let importMapCache: Record<string, string> | undefined
|
||||||
let vfs: VfsStorage | undefined
|
let vfs: VfsStorage | undefined
|
||||||
|
|
||||||
const scriptsStorage = new Map<string, string>()
|
|
||||||
|
|
||||||
async function getVfs() {
|
async function getVfs() {
|
||||||
if (!vfs) {
|
if (!vfs) {
|
||||||
vfs = await VfsStorage.create()
|
vfs = await VfsStorage.create()
|
||||||
|
@ -32,24 +31,8 @@ async function loadLibrary(name: string) {
|
||||||
return map
|
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() {
|
export function clearCache() {
|
||||||
libraryCache.clear()
|
libraryCache.clear()
|
||||||
scriptsStorage.clear()
|
|
||||||
importMapCache = undefined
|
importMapCache = undefined
|
||||||
vfs = undefined
|
vfs = undefined
|
||||||
}
|
}
|
||||||
|
@ -80,12 +63,17 @@ export async function handleRuntimeRequest(url: URL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.startsWith('script/')) {
|
if (path.startsWith('script/')) {
|
||||||
const scriptId = path.slice('script/'.length)
|
const scriptIdWithPath = path.slice('script/'.length)
|
||||||
if (!scriptsStorage.has(scriptId)) {
|
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('Not found', { status: 404 })
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response(scriptsStorage.get(scriptId)!, {
|
return new Response(file, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/javascript',
|
'Content-Type': 'application/javascript',
|
||||||
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
'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