"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DbManager = void 0;
const keyv_1 = __importDefault(require("keyv"));
const sqlite_1 = __importDefault(require("@keyv/sqlite"));
const path = __importStar(require("path"));
const tsyringe_1 = require("tsyringe");
const ipc_1 = require("../ipc");
const DbHandler_1 = require("./DbHandler");
/**
 * DbManager - Manages persistent key-value storage for Eden apps
 *
 * Provides namespace-isolated storage using SQLite backend via Keyv.
 * Each app gets its own namespace, preventing cross-app data access.
 */
let DbManager = class DbManager {
    keyv;
    handler;
    constructor(commandRegistry, appsDirectory) {
        // Initialize Keyv with SQLite backend
        const dbPath = path.join(appsDirectory, "storage.db");
        const sqlite = new sqlite_1.default(`sqlite://${dbPath}`);
        this.keyv = new keyv_1.default({ store: sqlite });
        // Handle errors
        this.keyv.on("error", (err) => {
            console.error("[DbManager] Database error:", err);
        });
        console.log(`[DbManager] Initialized storage at ${dbPath}`);
        // Create and register handler
        this.handler = new DbHandler_1.DbHandler(this);
        commandRegistry.registerManager(this.handler);
    }
    /**
     * Get the namespaced key for an app
     */
    getNamespacedKey(appId, key) {
        return `${appId}:${key}`;
    }
    /**
     * Extract app ID from a namespaced key
     */
    extractAppId(namespacedKey) {
        const colonIndex = namespacedKey.indexOf(":");
        return colonIndex > 0 ? namespacedKey.substring(0, colonIndex) : "";
    }
    /**
     * Extract the original key from a namespaced key
     */
    extractKey(namespacedKey) {
        const colonIndex = namespacedKey.indexOf(":");
        return colonIndex > 0
            ? namespacedKey.substring(colonIndex + 1)
            : namespacedKey;
    }
    /**
     * Get a value from storage for an app
     */
    async get(appId, key) {
        const namespacedKey = this.getNamespacedKey(appId, key);
        const value = await this.keyv.get(namespacedKey);
        // Runtime check: ensure we always return string or undefined
        if (value !== undefined && typeof value !== "string") {
            console.warn(`[DbManager] Non-string value found for key ${key}, converting to string`);
            return String(value);
        }
        return value;
    }
    /**
     * Set a value in storage for an app
     */
    async set(appId, key, value) {
        // Runtime check: ensure value is a string
        if (typeof value !== "string") {
            throw new Error(`[DbManager] Value must be a string, got ${typeof value}`);
        }
        const namespacedKey = this.getNamespacedKey(appId, key);
        await this.keyv.set(namespacedKey, value);
    }
    /**
     * Delete a key from storage for an app
     */
    async delete(appId, key) {
        const namespacedKey = this.getNamespacedKey(appId, key);
        return await this.keyv.delete(namespacedKey);
    }
    /**
     * Clear all keys for an app
     */
    async clear(appId) {
        const keys = await this.list(appId);
        for (const key of keys) {
            await this.delete(appId, key);
        }
    }
    /**
     * List all keys for an app
     */
    async list(appId) {
        const prefix = `${appId}:`;
        const allKeys = [];
        // Keyv's iterator requires a namespace parameter and may not be available on all stores
        try {
            if (this.keyv.iterator) {
                const iterator = this.keyv.iterator(undefined);
                for await (const [key] of iterator) {
                    if (typeof key === "string" && key.startsWith(prefix)) {
                        allKeys.push(this.extractKey(key));
                    }
                }
            }
        }
        catch (error) {
            console.warn("[DbManager] Iterator not supported or failed:", error);
        }
        return allKeys;
    }
    /**
     * Check if a key exists for an app
     */
    async has(appId, key) {
        const namespacedKey = this.getNamespacedKey(appId, key);
        const value = await this.keyv.get(namespacedKey);
        return value !== undefined;
    }
};
exports.DbManager = DbManager;
exports.DbManager = DbManager = __decorate([
    (0, tsyringe_1.singleton)(),
    (0, tsyringe_1.injectable)(),
    __param(0, (0, tsyringe_1.inject)(ipc_1.CommandRegistry)),
    __param(1, (0, tsyringe_1.inject)("appsDirectory")),
    __metadata("design:paramtypes", [ipc_1.CommandRegistry, String])
], DbManager);
//# sourceMappingURL=DbManager.js.map