import { open } from 'node:fs/promises';
export const ACCOUNT_ID = /^acct_[A-Za-z0-9_-]{43}$/;
const MAX_ACCOUNTS = 16;
const MAX_BYTES = 1024 * 1024;
export async function readStore(path) {
const file = await open(path, 'r');
try {
const info = await file.stat();
if (!info.isFile() || info.mode & 0o077) throw new Error('not private');
if (info.size > MAX_BYTES) throw new Error('too large');
const buffer = Buffer.alloc(MAX_BYTES + 1);
let bytesRead = 0;
while (bytesRead < buffer.length) {
const chunk = await file.read(buffer, bytesRead, buffer.length - bytesRead, bytesRead);
if (chunk.bytesRead === 0) break;
bytesRead += chunk.bytesRead;
}
if (bytesRead > MAX_BYTES) throw new Error('too large');
const store = JSON.parse(buffer.subarray(0, bytesRead).toString());
if (
store.version !== 1 ||
!Array.isArray(store.accounts) ||
store.accounts.length > MAX_ACCOUNTS
)
throw new Error('invalid store');
const ids = new Set();
for (const account of store.accounts) {
if (
!ACCOUNT_ID.test(account.account_id) ||
ids.has(account.account_id) ||
['client_id', 'client_secret', 'refresh_token'].some(
(key) => typeof account[key] !== 'string' || !account[key],
)
)
throw new Error('invalid record');
ids.add(account.account_id);
}
return store.accounts;
} finally {
await file.close();
}
}