From 2f87231b45f6339307bf443dfb7529b05010cce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cchrisshank=E2=80=9D?= Date: Thu, 2 Jan 2025 12:49:04 -0800 Subject: [PATCH] move stuff --- bun.lockb | Bin 44088 -> 44495 bytes .../persistence/file.ts | 98 +----------------- lib/index.ts | 2 + lib/indexeddb.ts | 78 ++++++++++++++ package.json | 1 + tsconfig.json | 2 +- 6 files changed, 87 insertions(+), 94 deletions(-) rename website/canvas/src/file-system.ts => labs/persistence/file.ts (51%) create mode 100644 lib/indexeddb.ts diff --git a/bun.lockb b/bun.lockb index 8ccf0b20fe4b9026316aac168064f7fb04c681e0..bcac7398356c76bcf7d552a79b5c32963db9eec5 100755 GIT binary patch delta 5562 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 Promise; - var showOpenFilePicker: (args: any) => Promise; - - interface FileSystemHandle { - queryPermission: (args: any) => Promise; - requestPermission: (args: any) => Promise; - } -} - -class KeyValueStore { - #db: Promise; - #storeName; - - constructor(name = 'keyval-store') { - this.#storeName = name; - const request = indexedDB.open(name); - request.onupgradeneeded = () => request.result.createObjectStore(name); - - this.#db = this.#promisifyRequest(request); - } - - #promisifyRequest(transaction: IDBRequest) { - return new Promise((resolve, reject) => { - transaction.onsuccess = () => resolve(transaction.result); - transaction.onerror = () => reject(transaction.error); - }); - } - - #promisifyTransaction(transaction: IDBTransaction) { - return new Promise((resolve, reject) => { - transaction.oncomplete = () => resolve(); - transaction.onabort = transaction.onerror = () => reject(transaction.error); - }); - } - - #getStore(mode: 'readonly' | 'readwrite') { - return this.#db.then((db) => db.transaction(this.#storeName, mode).objectStore(this.#storeName)); - } - - get(key: IDBValidKey): Promise { - return this.#getStore('readonly').then((store) => this.#promisifyRequest(store.get(key))); - } - - set(key: IDBValidKey, value: Data) { - return this.#getStore('readwrite').then((store) => { - store.put(value, key); - return this.#promisifyTransaction(store.transaction); - }); - } - - setMany(entries: [IDBValidKey, Data][]) { - return this.#getStore('readwrite').then((store) => { - entries.forEach((entry) => store.put(entry[1], entry[0])); - return this.#promisifyTransaction(store.transaction); - }); - } - - delete(key: IDBValidKey) { - return this.#getStore('readwrite').then((store) => { - store.delete(key); - return this.#promisifyTransaction(store.transaction); - }); - } - - clear() { - return this.#getStore('readwrite').then((store) => { - store.clear(); - return this.#promisifyTransaction(store.transaction); - }); - } - - keys() { - return this.#getStore('readwrite').then((store) => this.#promisifyRequest(store.getAllKeys())); - } - - values(): Promise { - return this.#getStore('readwrite').then((store) => this.#promisifyRequest(store.getAll())); - } - - entries(): Promise<[IDBValidKey, Data][]> { - return this.#getStore('readwrite').then((store) => - Promise.all([this.#promisifyRequest(store.getAllKeys()), this.#promisifyRequest(store.getAll())]).then( - ([keys, values]) => keys.map((key, i) => [key, values[i]]) - ) - ); - } -} diff --git a/lib/index.ts b/lib/index.ts index 494b92a..deed108 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -29,5 +29,7 @@ export * from './EffectIntegrator'; // WebGL utilities export * from './webgl'; +export * from './indexeddb'; + // Experimental features export * from './Experimental'; diff --git a/lib/indexeddb.ts b/lib/indexeddb.ts new file mode 100644 index 0000000..bf5e389 --- /dev/null +++ b/lib/indexeddb.ts @@ -0,0 +1,78 @@ +export class KeyValueStore { + #db: Promise; + #storeName; + + constructor(name = 'keyval-store') { + this.#storeName = name; + const request = indexedDB.open(name); + request.onupgradeneeded = () => request.result.createObjectStore(name); + + this.#db = this.#promisifyRequest(request); + } + + #promisifyRequest(transaction: IDBRequest) { + return new Promise((resolve, reject) => { + transaction.onsuccess = () => resolve(transaction.result); + transaction.onerror = () => reject(transaction.error); + }); + } + + #promisifyTransaction(transaction: IDBTransaction) { + return new Promise((resolve, reject) => { + transaction.oncomplete = () => resolve(); + transaction.onabort = transaction.onerror = () => reject(transaction.error); + }); + } + + #getStore(mode: 'readonly' | 'readwrite') { + return this.#db.then((db) => db.transaction(this.#storeName, mode).objectStore(this.#storeName)); + } + + get(key: IDBValidKey): Promise { + return this.#getStore('readonly').then((store) => this.#promisifyRequest(store.get(key))); + } + + set(key: IDBValidKey, value: Data) { + return this.#getStore('readwrite').then((store) => { + store.put(value, key); + return this.#promisifyTransaction(store.transaction); + }); + } + + setMany(entries: [IDBValidKey, Data][]) { + return this.#getStore('readwrite').then((store) => { + entries.forEach((entry) => store.put(entry[1], entry[0])); + return this.#promisifyTransaction(store.transaction); + }); + } + + delete(key: IDBValidKey) { + return this.#getStore('readwrite').then((store) => { + store.delete(key); + return this.#promisifyTransaction(store.transaction); + }); + } + + clear() { + return this.#getStore('readwrite').then((store) => { + store.clear(); + return this.#promisifyTransaction(store.transaction); + }); + } + + keys() { + return this.#getStore('readwrite').then((store) => this.#promisifyRequest(store.getAllKeys())); + } + + values(): Promise { + return this.#getStore('readwrite').then((store) => this.#promisifyRequest(store.getAll())); + } + + entries(): Promise<[IDBValidKey, Data][]> { + return this.#getStore('readwrite').then((store) => + Promise.all([this.#promisifyRequest(store.getAllKeys()), this.#promisifyRequest(store.getAll())]).then( + ([keys, values]) => keys.map((key, i) => [key, values[i]]), + ), + ); + } +} diff --git a/package.json b/package.json index 18f5732..e7a9266 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "devDependencies": { "@types/leaflet": "^1.9.14", "@types/node": "^22.10.1", + "@types/wicg-file-system-access": "^2023.10.5", "@webgpu/types": "^0.1.51", "bun-types": "^1.1.38", "mitata": "^1.0.20", diff --git a/tsconfig.json b/tsconfig.json index 8e3085c..d48a893 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,7 @@ "skipLibCheck": true, "noUnusedLocals": false, "lib": ["DOM", "DOM.Iterable", "ESNext", "WebWorker"], - "types": ["@webgpu/types", "@types/node", "bun-types"], + "types": ["@webgpu/types", "@types/node", "@types/wicg-file-system-access", "bun-types"], "baseUrl": ".", "paths": { "@lib": ["lib"],