← Files RivetARCHIVED FILE

node_modules/rivet-design/dist/services/ProjectMetadataStore.js

6 KB · Nov 7, 2026 · 13:16 UTC

↓ Download file

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectMetadataStore = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const ProjectStorage_1 = require("./ProjectStorage");
const logger_1 = require("../utils/logger");
const ProjectMetadataRecords_1 = require("../storage/project-metadata/ProjectMetadataRecords");
const migrations_1 = require("../storage/project-metadata/migrations");
const log = (0, logger_1.createLogger)('ProjectMetadataStore');
const DATABASE_FILENAME = 'rivet.db';
const DATABASE_SIBLING_SUFFIXES = ['-wal', '-shm'];
const VARIANT_INDEX_STATE_KEY = 'variant_index_state';
const VARIANT_INDEX_READY = 'ready';
const VARIANT_INDEX_STALE = 'stale';
const VARIANTS_UI_STATE_KEY = 'variants_ui_state';
class ProjectMetadataStore {
    storage;
    handles = new Map();
    staleOverrides = new Set();
    migrations;
    constructor(migrations = migrations_1.PROJECT_METADATA_MIGRATIONS, storage = new ProjectStorage_1.ProjectStorage()) {
        this.storage = storage;
        this.migrations = migrations;
    }
    databasePath(projectPath) {
        return path_1.default.join(this.storage.resolve(projectPath).dataDirectory, DATABASE_FILENAME);
    }
    hasDatabase(projectPath) {
        return fs_1.default.existsSync(this.databasePath(projectPath));
    }
    async initialize(projectPath) {
        await this.openDatabase(projectPath);
    }
    async upsertVariantFromManifest(args) {
        const db = await this.openDatabase(args.projectPath);
        db.upsert(args);
    }
    async rebuildVariantIndex(args) {
        const db = await this.openDatabase(args.projectPath);
        db.transaction(() => {
            db.clearVariants();
            for (const entry of args.entries)
                db.upsert(entry);
            db.writeState(VARIANT_INDEX_STATE_KEY, VARIANT_INDEX_READY);
        });
        this.staleOverrides.delete(path_1.default.resolve(args.projectPath));
    }
    async isVariantIndexReady(projectPath) {
        if (this.staleOverrides.has(path_1.default.resolve(projectPath)))
            return false;
        if (!this.handles.has(path_1.default.resolve(projectPath))) {
            if (!this.hasDatabase(projectPath))
                return false;
        }
        const db = await this.openDatabase(projectPath);
        return db.readState(VARIANT_INDEX_STATE_KEY) === VARIANT_INDEX_READY;
    }
    async markVariantIndexStale(projectPath) {
        this.staleOverrides.add(path_1.default.resolve(projectPath));
        try {
            const db = await this.openDatabase(projectPath);
            db.writeState(VARIANT_INDEX_STATE_KEY, VARIANT_INDEX_STALE);
        }
        catch (err) {
            log.warn(`markVariantIndexStale: durable stale flag failed for ${projectPath} — the in-memory override still forces a rebuild in this process`, err);
        }
    }
    async listVariants(args) {
        const db = await this.openDatabase(args.projectPath);
        return db.list({ status: args.status, limit: args.limit });
    }
    async searchVariants(args) {
        const db = await this.openDatabase(args.projectPath);
        return db.search({ query: args.query, limit: args.limit });
    }
    async readVariantsUiState(projectPath) {
        if (!this.hasDatabase(projectPath))
            return null;
        const db = await this.openDatabase(projectPath);
        return db.readState(VARIANTS_UI_STATE_KEY);
    }
    async writeVariantsUiState(projectPath, json) {
        const db = await this.openDatabase(projectPath);
        db.writeState(VARIANTS_UI_STATE_KEY, json);
    }
    closeAll() {
        for (const [key, db] of this.handles) {
            try {
                db.close();
            }
            catch (err) {
                log.warn(`closeAll: failed to close database for ${key}`, err);
            }
        }
        this.handles.clear();
    }
    async openDatabase(projectPath) {
        const key = path_1.default.resolve(projectPath);
        const dbPath = this.databasePath(key);
        const existing = this.handles.get(key);
        if (existing) {
            if (fs_1.default.existsSync(dbPath))
                return existing;
            try {
                existing.close();
            }
            catch (err) {
                log.warn(`openDatabase: failed to close stale handle for ${key}`, err);
            }
            this.handles.delete(key);
        }
        fs_1.default.mkdirSync(path_1.default.dirname(dbPath), { recursive: true });
        let db;
        try {
            db = await ProjectMetadataRecords_1.ProjectMetadataRecords.open(dbPath, this.migrations);
        }
        catch (err) {
            if (err instanceof migrations_1.UnsupportedSchemaVersionError)
                throw err;
            log.warn(`openDatabase: ${dbPath} is unreadable — recreating the projection`, err);
            this.deleteDatabaseFiles(dbPath);
            db = await ProjectMetadataRecords_1.ProjectMetadataRecords.open(dbPath, this.migrations);
        }
        if (db.wasUpgraded) {
            this.staleOverrides.add(key);
            try {
                db.writeState(VARIANT_INDEX_STATE_KEY, VARIANT_INDEX_STALE);
            }
            catch (err) {
                log.warn(`openDatabase: durable stale flag failed after upgrading ${dbPath}`, err);
            }
        }
        this.handles.set(key, db);
        return db;
    }
    deleteDatabaseFiles(dbPath) {
        for (const target of [
            dbPath,
            ...DATABASE_SIBLING_SUFFIXES.map((suffix) => `${dbPath}${suffix}`),
        ]) {
            try {
                fs_1.default.rmSync(target, { force: true });
            }
            catch (err) {
                log.warn(`deleteDatabaseFiles: failed to remove ${target}`, err);
            }
        }
    }
}
exports.ProjectMetadataStore = ProjectMetadataStore;
//# sourceMappingURL=ProjectMetadataStore.js.map

SHA-256: 80d07dbea0f8ca935283aae7d87c0b57efa2848edae9a99194985822b2ca47d7