import { normalizeDatabaseFile } from '../lib/normalize-database-file.js';
import { parseDatabasePath } from '../lib/parse-database-path.js';
import { SQLiteMemoryDriver } from './sqlite-memory-driver.js';
export class SQLiteOpfsDriver extends SQLiteMemoryDriver {
    constructor(sqlite3InitModule) {
        super(sqlite3InitModule);
        Object.defineProperty(this, "storageType", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: 'opfs'
        });
    }
    async init(config) {
        const { databasePath } = config;
        const flags = this.getFlags(config);
        if (!databasePath) {
            throw new Error('No databasePath specified');
        }
        if (!this.sqlite3InitModule) {
            const { default: sqlite3InitModule } = await import('@sqlite.org/sqlite-wasm');
            this.sqlite3InitModule = sqlite3InitModule;
        }
        if (!this.sqlite3) {
            this.sqlite3 = await this.sqlite3InitModule();
        }
        if (!('opfs' in this.sqlite3)) {
            throw new Error('OPFS not available');
        }
        if (this.db) {
            await this.destroy();
        }
        this.db = new this.sqlite3.oo1.OpfsDb(databasePath, flags);
        this.config = config;
        this.initWriteHook();
    }
    async isDatabasePersisted() {
        return navigator.storage?.persisted();
    }
    async import(database) {
        if (!this.sqlite3 || !this.config?.databasePath) {
            throw new Error('Driver not initialized');
        }
        await this.destroy();
        const data = await normalizeDatabaseFile(database, 'callback');
        await this.sqlite3.oo1.OpfsDb.importDb(this.config.databasePath, data);
    }
    async export() {
        if (!this.db || !this.config?.databasePath) {
            throw new Error('Driver not initialized');
        }
        let name, data;
        const path = parseDatabasePath(this.config.databasePath);
        const { directories, getDirectoryHandle } = path;
        name = path.fileName;
        const tempFileName = `backup-${Date.now()}--${name}`;
        const tempFilePath = `${directories.join('/')}/${tempFileName}`;
        this.db.exec({ sql: 'VACUUM INTO ?', bind: [tempFilePath] });
        const dirHandle = await getDirectoryHandle();
        const fileHandle = await dirHandle.getFileHandle(tempFileName);
        const file = await fileHandle.getFile();
        data = await file.arrayBuffer();
        await dirHandle.removeEntry(tempFileName);
        return { name, data };
    }
    async clear() {
        if (!this.config?.databasePath)
            throw new Error('Driver not initialized');
        await this.destroy();
        const { getDirectoryHandle, fileName, tempFileNames } = parseDatabasePath(this.config.databasePath);
        const dirHandle = await getDirectoryHandle();
        const fileNames = [fileName, ...tempFileNames];
        await Promise.all(fileNames.map(async (name) => {
            return dirHandle.removeEntry(name).catch((err) => {
                if (!(err instanceof DOMException && err.name === 'NotFoundError')) {
                    throw err;
                }
            });
        }));
    }
    async destroy() {
        this.closeDb();
        this.writeCallbacks.clear();
    }
}
//# sourceMappingURL=sqlite-opfs-driver.js.map