84 lines
2.2 KiB
JavaScript
Executable File
84 lines
2.2 KiB
JavaScript
Executable File
const fs = require("fs");
|
|
const path = require("path");
|
|
const Database = require("better-sqlite3");
|
|
const { DATA_DIR, DB_PATH } = require("./config");
|
|
|
|
const SQLITE_EXTENSIONS = new Set([".sqlite", ".sqlite3", ".db"]);
|
|
const REQUIRED_SCHEMA_TABLES = ["packages", "regions"];
|
|
|
|
function isSqliteFile(fileName) {
|
|
const extension = path.extname(fileName).toLowerCase();
|
|
return SQLITE_EXTENSIONS.has(extension);
|
|
}
|
|
|
|
function listExistingSqliteFiles(directoryPath) {
|
|
if (!fs.existsSync(directoryPath)) {
|
|
return [];
|
|
}
|
|
|
|
return fs
|
|
.readdirSync(directoryPath, { withFileTypes: true })
|
|
.filter((entry) => entry.isFile() && isSqliteFile(entry.name))
|
|
.map((entry) => path.resolve(directoryPath, entry.name))
|
|
.sort((left, right) => left.localeCompare(right));
|
|
}
|
|
|
|
function hasApplicationSchema(filePath) {
|
|
let db;
|
|
|
|
try {
|
|
db = new Database(filePath, { readonly: true, fileMustExist: true });
|
|
|
|
return REQUIRED_SCHEMA_TABLES.every((tableName) =>
|
|
db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(tableName)
|
|
);
|
|
} catch {
|
|
return false;
|
|
} finally {
|
|
if (db) {
|
|
db.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
function resolveRuntimeDbPath() {
|
|
const configuredPath = path.resolve(DB_PATH);
|
|
const configuredFileName = path.basename(configuredPath).toLowerCase();
|
|
const existingDatabases = listExistingSqliteFiles(DATA_DIR);
|
|
|
|
if (!existingDatabases.length) {
|
|
return configuredPath;
|
|
}
|
|
|
|
const schemaDatabases = existingDatabases.filter(hasApplicationSchema);
|
|
const preferredDatabases = schemaDatabases.length ? schemaDatabases : existingDatabases;
|
|
const configuredMatch = preferredDatabases.find(
|
|
(filePath) => path.basename(filePath).toLowerCase() === configuredFileName
|
|
);
|
|
|
|
return configuredMatch || preferredDatabases[0];
|
|
}
|
|
|
|
function ensureDataDirectory() {
|
|
fs.mkdirSync(DATA_DIR, { recursive: true });
|
|
}
|
|
|
|
function openDatabase() {
|
|
ensureDataDirectory();
|
|
const runtimeDbPath = resolveRuntimeDbPath();
|
|
|
|
const db = new Database(runtimeDbPath);
|
|
db.pragma("journal_mode = WAL");
|
|
db.pragma("foreign_keys = ON");
|
|
|
|
return db;
|
|
}
|
|
|
|
module.exports = {
|
|
DB_PATH,
|
|
hasApplicationSchema,
|
|
listExistingSqliteFiles,
|
|
openDatabase,
|
|
resolveRuntimeDbPath,
|
|
};
|