fix(portable): harden persistence and release paths (#15)

Preserve legacy source data when portable sanitization cannot replace it, reject malformed settings without panicking, and make portable pairing regeneration durable before UI state changes.\n\nMake the packaged smoke assertion tolerate slow WebView startup and clarify AppImage storage behavior.\n\nRefs #15
This commit is contained in:
NimBold
2026-07-13 00:09:09 +03:30
parent f441c687f0
commit dad5b7bc5e
4 changed files with 65 additions and 29 deletions
+14 -10
View File
@@ -176,21 +176,25 @@ async function terminateChild() {
return waitForChildExit(5000);
}
function assertPortableStorage() {
async function assertPortableStorage() {
const portableRoot = path.dirname(executable);
const marker = path.join(portableRoot, 'portable.flag');
const database = path.join(portableRoot, 'data', 'firelink.sqlite');
const webviewData = path.join(portableRoot, 'data', 'webview');
if (!fs.statSync(marker, { throwIfNoEntry: false })?.isFile()) {
throw new Error(`Portable marker was not found at ${marker}`);
}
if (!fs.statSync(database, { throwIfNoEntry: false })?.isFile()) {
throw new Error(`Portable database was not created at ${database}`);
}
if (!fs.statSync(webviewData, { throwIfNoEntry: false })?.isDirectory()) {
throw new Error(`Portable WebView data directory was not created at ${webviewData}`);
for (let attempt = 0; attempt < 40; attempt += 1) {
const markerReady = fs.statSync(marker, { throwIfNoEntry: false })?.isFile();
const databaseReady = fs.statSync(database, { throwIfNoEntry: false })?.isFile();
const webviewReady = fs.statSync(webviewData, { throwIfNoEntry: false })?.isDirectory();
if (markerReady && databaseReady && webviewReady) {
return;
}
await sleep(250);
}
throw new Error(
`Portable storage was not ready: marker=${marker}, database=${database}, webview=${webviewData}`,
);
}
try {
@@ -212,7 +216,7 @@ try {
assertNoVisibleWindows(child.pid);
}
if (assertPortableData) {
assertPortableStorage();
await assertPortableStorage();
}
if (childExit) {