mac: bundle web chat assets
This commit is contained in:
27
apps/macos/Sources/Clawdis/Resources/WebChat/storage/backends/indexeddb-storage-backend.d.ts
vendored
Normal file
27
apps/macos/Sources/Clawdis/Resources/WebChat/storage/backends/indexeddb-storage-backend.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { IndexedDBConfig, StorageBackend, StorageTransaction } from "../types.js";
|
||||
/**
|
||||
* IndexedDB implementation of StorageBackend.
|
||||
* Provides multi-store key-value storage with transactions and quota management.
|
||||
*/
|
||||
export declare class IndexedDBStorageBackend implements StorageBackend {
|
||||
private config;
|
||||
private dbPromise;
|
||||
constructor(config: IndexedDBConfig);
|
||||
private getDB;
|
||||
private promisifyRequest;
|
||||
get<T = unknown>(storeName: string, key: string): Promise<T | null>;
|
||||
set<T = unknown>(storeName: string, key: string, value: T): Promise<void>;
|
||||
delete(storeName: string, key: string): Promise<void>;
|
||||
keys(storeName: string, prefix?: string): Promise<string[]>;
|
||||
getAllFromIndex<T = unknown>(storeName: string, indexName: string, direction?: "asc" | "desc"): Promise<T[]>;
|
||||
clear(storeName: string): Promise<void>;
|
||||
has(storeName: string, key: string): Promise<boolean>;
|
||||
transaction<T>(storeNames: string[], mode: "readonly" | "readwrite", operation: (tx: StorageTransaction) => Promise<T>): Promise<T>;
|
||||
getQuotaInfo(): Promise<{
|
||||
usage: number;
|
||||
quota: number;
|
||||
percent: number;
|
||||
}>;
|
||||
requestPersistence(): Promise<boolean>;
|
||||
}
|
||||
//# sourceMappingURL=indexeddb-storage-backend.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"indexeddb-storage-backend.d.ts","sourceRoot":"","sources":["../../../src/storage/backends/indexeddb-storage-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvF;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,cAAc;IAGjD,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,SAAS,CAAqC;gBAElC,MAAM,EAAE,eAAe;YAE7B,KAAK;IAoCnB,OAAO,CAAC,gBAAgB;IAOlB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAQnE,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAazE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrD,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAgB3D,eAAe,CAAC,CAAC,GAAG,OAAO,EAChC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,GAAE,KAAK,GAAG,MAAc,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC;IAwBT,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrD,WAAW,CAAC,CAAC,EAClB,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,EAAE,UAAU,GAAG,WAAW,EAC9B,SAAS,EAAE,CAAC,EAAE,EAAE,kBAAkB,KAAK,OAAO,CAAC,CAAC,CAAC,GAC/C,OAAO,CAAC,CAAC,CAAC;IA6BP,YAAY,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAY1E,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC;CAM5C"}
|
||||
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* IndexedDB implementation of StorageBackend.
|
||||
* Provides multi-store key-value storage with transactions and quota management.
|
||||
*/
|
||||
export class IndexedDBStorageBackend {
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
this.dbPromise = null;
|
||||
}
|
||||
async getDB() {
|
||||
if (!this.dbPromise) {
|
||||
this.dbPromise = new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open(this.config.dbName, this.config.version);
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
request.onupgradeneeded = (_event) => {
|
||||
const db = request.result;
|
||||
// Create object stores from config
|
||||
for (const storeConfig of this.config.stores) {
|
||||
if (!db.objectStoreNames.contains(storeConfig.name)) {
|
||||
const store = db.createObjectStore(storeConfig.name, {
|
||||
keyPath: storeConfig.keyPath,
|
||||
autoIncrement: storeConfig.autoIncrement,
|
||||
});
|
||||
// Create indices
|
||||
if (storeConfig.indices) {
|
||||
for (const indexConfig of storeConfig.indices) {
|
||||
store.createIndex(indexConfig.name, indexConfig.keyPath, {
|
||||
unique: indexConfig.unique,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
return this.dbPromise;
|
||||
}
|
||||
promisifyRequest(request) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
}
|
||||
async get(storeName, key) {
|
||||
const db = await this.getDB();
|
||||
const tx = db.transaction(storeName, "readonly");
|
||||
const store = tx.objectStore(storeName);
|
||||
const result = await this.promisifyRequest(store.get(key));
|
||||
return result ?? null;
|
||||
}
|
||||
async set(storeName, key, value) {
|
||||
const db = await this.getDB();
|
||||
const tx = db.transaction(storeName, "readwrite");
|
||||
const store = tx.objectStore(storeName);
|
||||
// If store has keyPath, only pass value (in-line key)
|
||||
// Otherwise pass both value and key (out-of-line key)
|
||||
if (store.keyPath) {
|
||||
await this.promisifyRequest(store.put(value));
|
||||
}
|
||||
else {
|
||||
await this.promisifyRequest(store.put(value, key));
|
||||
}
|
||||
}
|
||||
async delete(storeName, key) {
|
||||
const db = await this.getDB();
|
||||
const tx = db.transaction(storeName, "readwrite");
|
||||
const store = tx.objectStore(storeName);
|
||||
await this.promisifyRequest(store.delete(key));
|
||||
}
|
||||
async keys(storeName, prefix) {
|
||||
const db = await this.getDB();
|
||||
const tx = db.transaction(storeName, "readonly");
|
||||
const store = tx.objectStore(storeName);
|
||||
if (prefix) {
|
||||
// Use IDBKeyRange for efficient prefix filtering
|
||||
const range = IDBKeyRange.bound(prefix, prefix + "\uffff", false, false);
|
||||
const keys = await this.promisifyRequest(store.getAllKeys(range));
|
||||
return keys.map((k) => String(k));
|
||||
}
|
||||
else {
|
||||
const keys = await this.promisifyRequest(store.getAllKeys());
|
||||
return keys.map((k) => String(k));
|
||||
}
|
||||
}
|
||||
async getAllFromIndex(storeName, indexName, direction = "asc") {
|
||||
const db = await this.getDB();
|
||||
const tx = db.transaction(storeName, "readonly");
|
||||
const store = tx.objectStore(storeName);
|
||||
const index = store.index(indexName);
|
||||
return new Promise((resolve, reject) => {
|
||||
const results = [];
|
||||
const request = index.openCursor(null, direction === "desc" ? "prev" : "next");
|
||||
request.onsuccess = () => {
|
||||
const cursor = request.result;
|
||||
if (cursor) {
|
||||
results.push(cursor.value);
|
||||
cursor.continue();
|
||||
}
|
||||
else {
|
||||
resolve(results);
|
||||
}
|
||||
};
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
}
|
||||
async clear(storeName) {
|
||||
const db = await this.getDB();
|
||||
const tx = db.transaction(storeName, "readwrite");
|
||||
const store = tx.objectStore(storeName);
|
||||
await this.promisifyRequest(store.clear());
|
||||
}
|
||||
async has(storeName, key) {
|
||||
const db = await this.getDB();
|
||||
const tx = db.transaction(storeName, "readonly");
|
||||
const store = tx.objectStore(storeName);
|
||||
const result = await this.promisifyRequest(store.getKey(key));
|
||||
return result !== undefined;
|
||||
}
|
||||
async transaction(storeNames, mode, operation) {
|
||||
const db = await this.getDB();
|
||||
const idbTx = db.transaction(storeNames, mode);
|
||||
const storageTx = {
|
||||
get: async (storeName, key) => {
|
||||
const store = idbTx.objectStore(storeName);
|
||||
const result = await this.promisifyRequest(store.get(key));
|
||||
return (result ?? null);
|
||||
},
|
||||
set: async (storeName, key, value) => {
|
||||
const store = idbTx.objectStore(storeName);
|
||||
// If store has keyPath, only pass value (in-line key)
|
||||
// Otherwise pass both value and key (out-of-line key)
|
||||
if (store.keyPath) {
|
||||
await this.promisifyRequest(store.put(value));
|
||||
}
|
||||
else {
|
||||
await this.promisifyRequest(store.put(value, key));
|
||||
}
|
||||
},
|
||||
delete: async (storeName, key) => {
|
||||
const store = idbTx.objectStore(storeName);
|
||||
await this.promisifyRequest(store.delete(key));
|
||||
},
|
||||
};
|
||||
return operation(storageTx);
|
||||
}
|
||||
async getQuotaInfo() {
|
||||
if (navigator.storage?.estimate) {
|
||||
const estimate = await navigator.storage.estimate();
|
||||
return {
|
||||
usage: estimate.usage || 0,
|
||||
quota: estimate.quota || 0,
|
||||
percent: estimate.quota ? ((estimate.usage || 0) / estimate.quota) * 100 : 0,
|
||||
};
|
||||
}
|
||||
return { usage: 0, quota: 0, percent: 0 };
|
||||
}
|
||||
async requestPersistence() {
|
||||
if (navigator.storage?.persist) {
|
||||
return await navigator.storage.persist();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=indexeddb-storage-backend.js.map
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user