patchrelay 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +3 -3
- package/dist/preflight.js +39 -0
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
package/dist/preflight.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { accessSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { runPatchRelayMigrations } from "./db/migrations.js";
|
|
4
|
+
import { SqliteConnection } from "./db/shared.js";
|
|
3
5
|
import { execCommand } from "./utils.js";
|
|
4
6
|
export async function runPreflight(config) {
|
|
5
7
|
const checks = [];
|
|
@@ -62,6 +64,7 @@ export async function runPreflight(config) {
|
|
|
62
64
|
checks.push(...checkPublicBaseUrl(config));
|
|
63
65
|
checks.push(...checkOAuthRedirectUri(config));
|
|
64
66
|
checks.push(...checkPath("database", path.dirname(config.database.path), "directory", { createIfMissing: true, writable: true }));
|
|
67
|
+
checks.push(checkDatabaseSchema(config));
|
|
65
68
|
checks.push(...checkPath("logging", path.dirname(config.logging.filePath), "directory", { createIfMissing: true, writable: true }));
|
|
66
69
|
if (config.logging.webhookArchiveDir) {
|
|
67
70
|
checks.push(...checkPath("archive", config.logging.webhookArchiveDir, "directory", { createIfMissing: true, writable: true }));
|
|
@@ -86,6 +89,42 @@ export async function runPreflight(config) {
|
|
|
86
89
|
ok: checks.every((check) => check.status !== "fail"),
|
|
87
90
|
};
|
|
88
91
|
}
|
|
92
|
+
function checkDatabaseSchema(config) {
|
|
93
|
+
let connection;
|
|
94
|
+
try {
|
|
95
|
+
connection = new SqliteConnection(config.database.path);
|
|
96
|
+
connection.pragma("foreign_keys = ON");
|
|
97
|
+
if (config.database.wal) {
|
|
98
|
+
connection.pragma("journal_mode = WAL");
|
|
99
|
+
}
|
|
100
|
+
runPatchRelayMigrations(connection);
|
|
101
|
+
const quickCheck = connection.prepare("PRAGMA quick_check").get();
|
|
102
|
+
const quickCheckResult = quickCheck ? Object.values(quickCheck)[0] : undefined;
|
|
103
|
+
if (quickCheckResult !== "ok") {
|
|
104
|
+
return fail("database_schema", `SQLite quick_check failed: ${String(quickCheckResult ?? "unknown result")}`);
|
|
105
|
+
}
|
|
106
|
+
const schemaStats = connection
|
|
107
|
+
.prepare(`
|
|
108
|
+
SELECT
|
|
109
|
+
COUNT(*) AS object_count
|
|
110
|
+
FROM sqlite_master
|
|
111
|
+
WHERE type IN ('table', 'index', 'view', 'trigger')
|
|
112
|
+
AND name NOT LIKE 'sqlite_%'
|
|
113
|
+
`)
|
|
114
|
+
.get();
|
|
115
|
+
const objectCount = Number(schemaStats?.object_count ?? 0);
|
|
116
|
+
if (objectCount < 1) {
|
|
117
|
+
return fail("database_schema", "Database schema is empty after migrations");
|
|
118
|
+
}
|
|
119
|
+
return pass("database_schema", `Database opened, migrations applied, and schema is readable (${objectCount} objects)`);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
return fail("database_schema", `Unable to open or validate database schema at ${config.database.path}: ${formatError(error)}`);
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
connection?.close();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
89
128
|
function checkPath(scope, targetPath, expectedType, options) {
|
|
90
129
|
const checks = [];
|
|
91
130
|
if (!existsSync(targetPath)) {
|