Files
makelore/electron/services/cloud-agent-journal.ts

43 lines
1.9 KiB
TypeScript

import type { CloudPendingOperation, CloudRecoveryState, CloudRecent } from '../../shared/cloud-agents';
interface JournalStore {
get(key: string, fallback: CloudRecoveryState): CloudRecoveryState;
set(key: string, value: CloudRecoveryState): void;
}
let storePromise: Promise<JournalStore> | undefined;
const loadStore = () => storePromise ??= import('electron-store').then(({ default: Store }) =>
new Store<Record<string, CloudRecoveryState>>({ name: 'makelore-cloud-recovery' }));
/** Main 保存当前账号的未确认业务输入;不保存凭据,也不自动重放。 */
export class CloudAgentJournal {
constructor(private readonly store = loadStore) {}
async read(accountKey: string): Promise<CloudRecoveryState> {
return (await this.store()).get(accountKey, { recent: null, pending: [] });
}
private async update(accountKey: string, validate: () => void, change: (value: CloudRecoveryState) => CloudRecoveryState) {
const store = await this.store();
validate();
store.set(accountKey, change(store.get(accountKey, { recent: null, pending: [] })));
}
remember(accountKey: string, recent: CloudRecent | null, validate: () => void) {
return this.update(accountKey, validate, value => ({ ...value, recent }));
}
put(accountKey: string, entry: CloudPendingOperation, validate: () => void) {
return this.update(accountKey, validate, value => {
const existing = value.pending.find(item => item.id === entry.id);
if (existing && JSON.stringify(existing.input) !== JSON.stringify(entry.input)) {
throw new Error('同一次待确认操作不能更改输入');
}
return { ...value, pending: existing ? value.pending : [...value.pending, entry] };
});
}
remove(accountKey: string, id: string, validate: () => void) {
return this.update(accountKey, validate, value => ({ ...value, pending: value.pending.filter(item => item.id !== id) }));
}
}