Skip to content

Commit 85f6f54

Browse files
committed
Preserve storage save probe failures
(cherry picked from commit dedb342)
1 parent fb3861f commit 85f6f54

File tree

2 files changed

+90
-13
lines changed

2 files changed

+90
-13
lines changed

lib/storage/account-save.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,13 @@ export async function saveAccountsToDisk(
3737
await params.ensureGitignore();
3838

3939
if (params.looksLikeSyntheticFixtureStorage(storage)) {
40-
try {
41-
const existing = await params.loadExistingStorage();
42-
if (
43-
existing &&
44-
existing.accounts.length > 0 &&
45-
!params.looksLikeSyntheticFixtureStorage(existing)
46-
) {
47-
throw params.createSyntheticFixtureError();
48-
}
49-
} catch (error) {
50-
if (error instanceof Error && error.message.includes("synthetic")) {
51-
throw error;
52-
}
40+
const existing = await params.loadExistingStorage();
41+
if (
42+
existing &&
43+
existing.accounts.length > 0 &&
44+
!params.looksLikeSyntheticFixtureStorage(existing)
45+
) {
46+
throw params.createSyntheticFixtureError();
5347
}
5448
}
5549

test/account-save.test.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
import { saveAccountsToDisk } from "../lib/storage/account-save.js";
3+
4+
function createStorage(): {
5+
version: 3;
6+
accounts: Array<{ refreshToken: string }>;
7+
activeIndex: number;
8+
activeIndexByFamily: Record<string, number>;
9+
} {
10+
return {
11+
version: 3,
12+
accounts: [{ refreshToken: "rt-1" }],
13+
activeIndex: 0,
14+
activeIndexByFamily: {},
15+
};
16+
}
17+
18+
function createParams(overrides?: Partial<Parameters<typeof saveAccountsToDisk>[1]>) {
19+
return {
20+
path: "/tmp/accounts.json",
21+
resetMarkerPath: "/tmp/accounts.reset",
22+
walPath: "/tmp/accounts.wal",
23+
storageBackupEnabled: false,
24+
ensureDirectory: vi.fn(async () => undefined),
25+
ensureGitignore: vi.fn(async () => undefined),
26+
looksLikeSyntheticFixtureStorage: vi.fn(() => true),
27+
loadExistingStorage: vi.fn(async () => null),
28+
createSyntheticFixtureError: vi.fn(() => new Error("synthetic fixture refusal")),
29+
createRotatingAccountsBackup: vi.fn(async () => undefined),
30+
computeSha256: vi.fn(() => "hash"),
31+
writeJournal: vi.fn(async () => undefined),
32+
writeTemp: vi.fn(async () => undefined),
33+
statTemp: vi.fn(async () => ({ size: 10 })),
34+
renameTempToPath: vi.fn(async () => undefined),
35+
cleanupResetMarker: vi.fn(async () => undefined),
36+
cleanupWal: vi.fn(async () => undefined),
37+
cleanupTemp: vi.fn(async () => undefined),
38+
onSaved: vi.fn(() => undefined),
39+
logWarn: vi.fn(() => undefined),
40+
logError: vi.fn(() => undefined),
41+
createStorageError: vi.fn((error) => error as Error),
42+
backupPath: "/tmp/accounts.backup",
43+
createTempPath: vi.fn(() => "/tmp/accounts.tmp"),
44+
...overrides,
45+
};
46+
}
47+
48+
describe("account save helper", () => {
49+
it("rethrows probe failures through createStorageError", async () => {
50+
const probeError = new Error("Failed to read storage file");
51+
const params = createParams({
52+
loadExistingStorage: vi.fn(async () => {
53+
throw probeError;
54+
}),
55+
});
56+
57+
await expect(saveAccountsToDisk(createStorage() as never, params)).rejects.toBe(
58+
probeError,
59+
);
60+
expect(params.createSyntheticFixtureError).not.toHaveBeenCalled();
61+
expect(params.createStorageError).toHaveBeenCalledWith(probeError);
62+
expect(params.writeJournal).not.toHaveBeenCalled();
63+
});
64+
65+
it("refuses to overwrite live storage with a synthetic fixture payload", async () => {
66+
const refusalError = new Error("synthetic fixture refusal");
67+
const params = createParams({
68+
loadExistingStorage: vi.fn(async () => createStorage() as never),
69+
looksLikeSyntheticFixtureStorage: vi
70+
.fn()
71+
.mockReturnValueOnce(true)
72+
.mockReturnValueOnce(false),
73+
createSyntheticFixtureError: vi.fn(() => refusalError),
74+
});
75+
76+
await expect(saveAccountsToDisk(createStorage() as never, params)).rejects.toBe(
77+
refusalError,
78+
);
79+
expect(params.createSyntheticFixtureError).toHaveBeenCalledOnce();
80+
expect(params.createStorageError).toHaveBeenCalledWith(refusalError);
81+
expect(params.writeJournal).not.toHaveBeenCalled();
82+
});
83+
});

0 commit comments

Comments
 (0)