@firesystem/indexeddb
Version:
IndexedDB implementation of Virtual File System
140 lines (123 loc) • 4.21 kB
text/typescript
import type {
IReactiveFileSystem,
IFileSystemCapabilities,
} from "@firesystem/core";
// Import type-only para evitar dependência em runtime
import type { SourceProvider } from "@workspace-fs/core";
import { IndexedDBFileSystem } from "../IndexedDBFileSystem";
/**
* Provider para IndexedDBFileSystem no workspace
* Implementa o padrão de providers do VSCode
*/
export class IndexedDBWorkspaceProvider implements SourceProvider {
readonly scheme = "indexeddb";
readonly displayName = "IndexedDB File System";
/**
* Cria uma nova instância do IndexedDBFileSystem
*/
async createFileSystem(config: any): Promise<IReactiveFileSystem> {
// Configuração padrão se não fornecida
const fsConfig = {
dbName: config?.dbName || `firesystem-${Date.now()}`,
version: config?.version || 1,
storeName: config?.storeName || "files",
enableExternalSync: config?.enableExternalSync ?? true,
deepChangeDetection: config?.deepChangeDetection ?? false,
};
const fs = new IndexedDBFileSystem(fsConfig);
// IndexedDB precisa ser inicializado para conectar ao banco
await fs.initialize();
return fs;
}
/**
* Valida configuração do IndexedDB provider
*/
async validateConfiguration(
config: any,
): Promise<{ valid: boolean; errors?: string[] }> {
const errors: string[] = [];
if (config) {
// Valida dbName
if (config.dbName !== undefined) {
if (typeof config.dbName !== "string") {
errors.push("dbName must be a string");
} else if (config.dbName.length === 0) {
errors.push("dbName cannot be empty");
} else if (!/^[a-zA-Z0-9_-]+$/.test(config.dbName)) {
errors.push(
"dbName can only contain letters, numbers, hyphens and underscores",
);
}
}
// Valida version
if (config.version !== undefined) {
if (typeof config.version !== "number") {
errors.push("version must be a number");
} else if (config.version < 1) {
errors.push("version must be >= 1");
} else if (!Number.isInteger(config.version)) {
errors.push("version must be an integer");
}
}
// Valida storeName
if (config.storeName !== undefined) {
if (typeof config.storeName !== "string") {
errors.push("storeName must be a string");
} else if (config.storeName.length === 0) {
errors.push("storeName cannot be empty");
}
}
// Valida enableExternalSync
if (
config.enableExternalSync !== undefined &&
typeof config.enableExternalSync !== "boolean"
) {
errors.push("enableExternalSync must be a boolean");
}
// Valida deepChangeDetection
if (
config.deepChangeDetection !== undefined &&
typeof config.deepChangeDetection !== "boolean"
) {
errors.push("deepChangeDetection must be a boolean");
}
}
return {
valid: errors.length === 0,
errors: errors.length > 0 ? errors : undefined,
};
}
/**
* Retorna as capacidades do IndexedDB FS
*/
getCapabilities(): IFileSystemCapabilities {
return {
readonly: false,
caseSensitive: true,
atomicRename: true,
supportsWatch: true,
supportsMetadata: true,
supportsGlob: true,
supportsAtomicOperations: true,
maxFileSize: 500 * 1024 * 1024, // 500MB practical limit
maxPathLength: 1024,
description:
"Browser-based persistent storage using IndexedDB. Data survives page reloads and browser restarts.",
};
}
/**
* Limpa e destrói o file system
*/
async dispose(fs: IReactiveFileSystem): Promise<void> {
// Se for IndexedDBFileSystem, chamar dispose para limpar recursos
if ("dispose" in fs && typeof fs.dispose === "function") {
fs.dispose();
}
// Remove todos os event listeners se houver
if (fs.events && "removeAllListeners" in fs.events) {
fs.events.removeAllListeners();
}
}
}
// Exporta uma instância singleton para conveniência
export const indexedDBProvider = new IndexedDBWorkspaceProvider();