Skip to content

Commit 74eb5c3

Browse files
jeremy-clerkwobsoriano
authored andcommitted
fix(electron): resolve storage type errors (#8792)
1 parent 1c22410 commit 74eb5c3

2 files changed

Lines changed: 18 additions & 10 deletions

File tree

‎packages/electron/src/storage/__tests__/index.test.ts‎

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ const storeGet = vi.fn();
88
const storeSet = vi.fn();
99
const storeDelete = vi.fn();
1010

11+
type AsyncSafeStorage = {
12+
encryptStringAsync: (value: string) => Promise<Buffer>;
13+
decryptStringAsync: (encrypted: Buffer) => Promise<{ result: string; shouldReEncrypt: boolean }>;
14+
isAsyncEncryptionAvailable: () => Promise<boolean>;
15+
};
16+
1117
// `safeStorage` starts empty; each test installs only the methods for the backend it exercises.
1218
// This mirrors reality: Electron < 42 has no async methods at all, so `resolveCipher` only takes the
1319
// async path when both the methods exist and `isAsyncEncryptionAvailable()` confirms it.
@@ -24,6 +30,7 @@ vi.mock('electron-store', () => ({
2430
}));
2531

2632
const ss = safeStorage as unknown as Record<string, unknown>;
33+
const asyncSafeStorage = safeStorage as typeof safeStorage & AsyncSafeStorage;
2734

2835
/** Installs the synchronous `safeStorage` API. */
2936
function installSync({ available = true }: { available?: boolean } = {}) {
@@ -134,28 +141,28 @@ describe('getItem', () => {
134141
installSync();
135142
installAsync();
136143
storeGet.mockReturnValue(`enc:${Buffer.from('cipher').toString('base64')}`);
137-
vi.mocked(safeStorage.decryptStringAsync).mockResolvedValue({ result: 'jwt', shouldReEncrypt: false });
144+
vi.mocked(asyncSafeStorage.decryptStringAsync).mockResolvedValue({ result: 'jwt', shouldReEncrypt: false });
138145

139146
await expect(storage().getItem('token-key')).resolves.toBe('jwt');
140-
expect(safeStorage.decryptStringAsync).toHaveBeenCalledWith(Buffer.from('cipher'));
147+
expect(asyncSafeStorage.decryptStringAsync).toHaveBeenCalledWith(Buffer.from('cipher'));
141148
});
142149

143150
it('re-encrypts and re-saves when the OS key has rotated (shouldReEncrypt)', async () => {
144151
installSync();
145152
installAsync();
146153
storeGet.mockReturnValue(`enc:${Buffer.from('old-cipher').toString('base64')}`);
147-
vi.mocked(safeStorage.decryptStringAsync).mockResolvedValue({ result: 'jwt', shouldReEncrypt: true });
154+
vi.mocked(asyncSafeStorage.decryptStringAsync).mockResolvedValue({ result: 'jwt', shouldReEncrypt: true });
148155

149156
await expect(storage().getItem('token-key')).resolves.toBe('jwt');
150-
expect(safeStorage.encryptStringAsync).toHaveBeenCalledWith('jwt');
157+
expect(asyncSafeStorage.encryptStringAsync).toHaveBeenCalledWith('jwt');
151158
expect(storeSet).toHaveBeenCalledWith('token-key', `enc:${Buffer.from('enc(jwt)').toString('base64')}`);
152159
});
153160

154161
it('returns null without deleting the entry when decryption rejects', async () => {
155162
installSync();
156163
installAsync();
157164
storeGet.mockReturnValue(`enc:${Buffer.from('cipher').toString('base64')}`);
158-
vi.mocked(safeStorage.decryptStringAsync).mockRejectedValue(new Error('decrypt failed'));
165+
vi.mocked(asyncSafeStorage.decryptStringAsync).mockRejectedValue(new Error('decrypt failed'));
159166

160167
await expect(storage().getItem('token-key')).resolves.toBeNull();
161168
expect(storeDelete).not.toHaveBeenCalled();
@@ -170,7 +177,7 @@ describe('getItem', () => {
170177
await expect(storage().getItem('token-key')).resolves.toBe('jwt');
171178
expect(safeStorage.decryptString).toHaveBeenCalledWith(Buffer.from('cipher'));
172179
// Critical: calling the async crypto while unavailable crashes the process on Electron 42.x.
173-
expect(safeStorage.decryptStringAsync).not.toHaveBeenCalled();
180+
expect(asyncSafeStorage.decryptStringAsync).not.toHaveBeenCalled();
174181
});
175182
});
176183
});
@@ -191,7 +198,7 @@ describe('setItem', () => {
191198

192199
await storage().setItem('token-key', 'jwt');
193200

194-
expect(safeStorage.encryptStringAsync).toHaveBeenCalledWith('jwt');
201+
expect(asyncSafeStorage.encryptStringAsync).toHaveBeenCalledWith('jwt');
195202
expect(storeSet).toHaveBeenCalledWith('token-key', `enc:${Buffer.from('enc(jwt)').toString('base64')}`);
196203
});
197204

@@ -202,7 +209,7 @@ describe('setItem', () => {
202209
await storage().setItem('token-key', 'jwt');
203210

204211
expect(safeStorage.encryptString).toHaveBeenCalledWith('jwt');
205-
expect(safeStorage.encryptStringAsync).not.toHaveBeenCalled();
212+
expect(asyncSafeStorage.encryptStringAsync).not.toHaveBeenCalled();
206213
expect(storeSet).toHaveBeenCalledWith('token-key', `enc:${Buffer.from('enc(jwt)').toString('base64')}`);
207214
});
208215

@@ -290,7 +297,7 @@ describe('setItem', () => {
290297
await storage().setItem('token-key', 'jwt');
291298

292299
expect(safeStorage.encryptString).toHaveBeenCalledWith('jwt');
293-
expect(safeStorage.encryptStringAsync).not.toHaveBeenCalled();
300+
expect(asyncSafeStorage.encryptStringAsync).not.toHaveBeenCalled();
294301
});
295302
});
296303

‎packages/electron/tsconfig.declarations.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
"declarationMap": true,
99
"sourceMap": false,
1010
"declarationDir": "./dist/types"
11-
}
11+
},
12+
"exclude": ["**/__tests__/**/*"]
1213
}

0 commit comments

Comments
 (0)