openmates 0.12.0-alpha.24 → 0.12.0-alpha.26
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/{chunk-YQL7OKLK.js → chunk-KYTZNUYQ.js} +31 -4
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -9605,6 +9605,24 @@ function writeChecksums(rootDir) {
|
|
|
9605
9605
|
writeFileSync3(join3(rootDir, "checksums.sha256"), `${lines.sort().join("\n")}
|
|
9606
9606
|
`);
|
|
9607
9607
|
}
|
|
9608
|
+
function verifyChecksums(rootDir) {
|
|
9609
|
+
const checksumsPath = join3(rootDir, "checksums.sha256");
|
|
9610
|
+
if (!existsSync5(checksumsPath)) throw new Error("Backup archive is missing checksums.sha256.");
|
|
9611
|
+
for (const line of readFileSync5(checksumsPath, "utf-8").split("\n")) {
|
|
9612
|
+
const trimmed = line.trim();
|
|
9613
|
+
if (!trimmed) continue;
|
|
9614
|
+
const match = trimmed.match(/^([a-f0-9]{64}) {2}(.+)$/);
|
|
9615
|
+
if (!match) throw new Error(`Invalid checksum entry: ${trimmed}`);
|
|
9616
|
+
const relative2 = match[2];
|
|
9617
|
+
if (relative2.startsWith("/") || relative2.split(/[\\/]/).includes("..")) {
|
|
9618
|
+
throw new Error(`Unsafe checksum path in backup archive: ${relative2}`);
|
|
9619
|
+
}
|
|
9620
|
+
const filePath = join3(rootDir, relative2);
|
|
9621
|
+
if (!existsSync5(filePath)) throw new Error(`Backup archive is missing checksummed file: ${relative2}`);
|
|
9622
|
+
const actual = createHash5("sha256").update(readFileSync5(filePath)).digest("hex");
|
|
9623
|
+
if (actual !== match[1]) throw new Error(`Backup checksum mismatch for ${relative2}.`);
|
|
9624
|
+
}
|
|
9625
|
+
}
|
|
9608
9626
|
function createServerBackup(installPath, role, options = {}) {
|
|
9609
9627
|
const plan = planBackup({ role, includeObservability: options.includeObservability });
|
|
9610
9628
|
const backupDir = roleBackupDir(installPath, role);
|
|
@@ -9629,7 +9647,10 @@ function createServerBackup(installPath, role, options = {}) {
|
|
|
9629
9647
|
const databaseUser = env.DATABASE_USERNAME || "directus";
|
|
9630
9648
|
const databaseName = env.DATABASE_NAME || "directus";
|
|
9631
9649
|
try {
|
|
9632
|
-
const dump = execSync(
|
|
9650
|
+
const dump = execSync(
|
|
9651
|
+
`docker exec cms-database pg_dump --clean --if-exists --no-owner --no-privileges -U ${shellQuote(databaseUser)} ${shellQuote(databaseName)}`,
|
|
9652
|
+
{ encoding: "utf-8", maxBuffer: 256 * 1024 * 1024 }
|
|
9653
|
+
);
|
|
9633
9654
|
writeFileSync3(join3(tempDir, "postgres.sql"), dump);
|
|
9634
9655
|
} catch (error) {
|
|
9635
9656
|
throw new Error(`Postgres backup failed. Is cms-database running? ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -9658,6 +9679,7 @@ function restoreServerBackup(installPath, role, file) {
|
|
|
9658
9679
|
const env = readEnvMap(installPath);
|
|
9659
9680
|
try {
|
|
9660
9681
|
execSync(`tar -xzf ${shellQuote(archivePath)} -C ${shellQuote(tempDir)}`, { stdio: "pipe" });
|
|
9682
|
+
verifyChecksums(tempDir);
|
|
9661
9683
|
const manifestPath = join3(tempDir, "manifest.json");
|
|
9662
9684
|
if (!existsSync5(manifestPath)) throw new Error("Backup archive is missing manifest.json.");
|
|
9663
9685
|
const manifest = JSON.parse(readFileSync5(manifestPath, "utf-8"));
|
|
@@ -9668,7 +9690,7 @@ function restoreServerBackup(installPath, role, file) {
|
|
|
9668
9690
|
if (role === "core" && existsSync5(postgresDump)) {
|
|
9669
9691
|
const databaseUser = env.DATABASE_USERNAME || "directus";
|
|
9670
9692
|
const databaseName = env.DATABASE_NAME || "directus";
|
|
9671
|
-
execSync(`docker exec -i cms-database psql -U ${shellQuote(databaseUser)} ${shellQuote(databaseName)}`, {
|
|
9693
|
+
execSync(`docker exec -i cms-database psql -v ON_ERROR_STOP=1 -U ${shellQuote(databaseUser)} ${shellQuote(databaseName)}`, {
|
|
9672
9694
|
input: readFileSync5(postgresDump),
|
|
9673
9695
|
stdio: ["pipe", "pipe", "pipe"]
|
|
9674
9696
|
});
|
|
@@ -9677,6 +9699,10 @@ function restoreServerBackup(installPath, role, file) {
|
|
|
9677
9699
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
9678
9700
|
}
|
|
9679
9701
|
}
|
|
9702
|
+
function restoreStopServices(role) {
|
|
9703
|
+
if (role !== "core") return [];
|
|
9704
|
+
return resolveServiceSelection("core", { exclude: "cms-database" });
|
|
9705
|
+
}
|
|
9680
9706
|
async function promptText(question, defaultValue = "") {
|
|
9681
9707
|
const rl = createPromptInterface({ input: process.stdin, output: process.stderr });
|
|
9682
9708
|
try {
|
|
@@ -10631,7 +10657,8 @@ WARNING: This will restore ${role} data from ${file}.`);
|
|
|
10631
10657
|
}
|
|
10632
10658
|
const withOverrides = config?.composeProfile === "full";
|
|
10633
10659
|
const installMode = getInstallMode(installPath, config);
|
|
10634
|
-
|
|
10660
|
+
const stopArgs = [...composeArgs(installPath, withOverrides, installMode, role), "stop", ...restoreStopServices(role)];
|
|
10661
|
+
let code = await runInteractive("docker", stopArgs, installPath);
|
|
10635
10662
|
if (code !== 0) process.exit(code);
|
|
10636
10663
|
restoreServerBackup(installPath, role, file);
|
|
10637
10664
|
code = await runInteractive("docker", [...composeArgs(installPath, withOverrides, installMode, role), "up", "-d"], installPath);
|
|
@@ -27698,7 +27725,7 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
|
|
|
27698
27725
|
text: "Private local personalization"
|
|
27699
27726
|
},
|
|
27700
27727
|
title: {
|
|
27701
|
-
text: "
|
|
27728
|
+
text: "What are you interested in?"
|
|
27702
27729
|
},
|
|
27703
27730
|
continue: {
|
|
27704
27731
|
text: "Continue"
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED