Here's a 34 line implementation I use on a node production system. It writes struct-like JavaScript objects that represents events to disk. When reading it back I do a fold (or .reduce) to build the state.
And yes –– it could be way smarter (writing to memory and disk), but YAGNI has been working out pretty well so far.
class EventStore {
constructor(file) {
this.file = file;
this.cache = null;
}
async appendEvent(event) {
// Purge the cache for entries since we mutated the store.
this.cache = null;
return new Promise((resolve, reject) => {
createWriteStream(this.file, { flags: 'a' })
.on('error', reject)
.on('close', resolve)
.end(`${JSON.stringify(event)}\n`);
});
}
async readEvents() {
if (this.cache !== null) {
return this.cache;
}
try {
const data = await readFile(this.file, 'utf-8');
const lines = data.split('\n').filter(line => line);
const events = lines.map(line => JSON.parse(line));
this.cache = events;
return events;
} catch (error) {
return [];
}
}
}