UNPKG

evtstore

Version:

Event Sourcing with Node.JS

126 lines 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.migrate = exports.createProvider = void 0; const error_1 = require("./error"); const util_1 = require("./util"); function createProvider(opts) { const { sql, bookmarks: bms, events: evts } = opts; const onError = opts.onError || (() => { /* NOOP */ }); return { limit: opts.limit, driver: 'postgres', onError, getPosition: async (bm) => { const result = await sql `SELECT * FROM ${sql(bms)} WHERE bookmark = ${bm} LIMIT 1`; if (result[0]) return result[0].position; return 0; }, setPosition: async (bm, pos) => { const result = await sql `UPDATE ${sql(bms)} SET position = ${pos} WHERE bookmark = ${bm}`; if (result.count === 0) { await sql `INSERT INTO ${sql(bms)} (bookmark, position) VALUES (${bm}, ${pos})`; } }, getEventsFor: async (stream, aggregateId, fromPosition) => { const from = fromPosition ? sql `AND position > ${fromPosition}` : sql ``; const result = await sql `SELECT * FROM ${sql(evts)} WHERE stream = ${stream} AND aggregate_id = ${aggregateId} ${from} ORDER BY version asc`; return result.map(mapToEvent); }, getLastEventFor: async (stream, aggregateId) => { const streams = Array.isArray(stream) ? stream : [stream]; const agg = aggregateId ? sql `AND aggregate_id = ${aggregateId}` : sql ``; const result = await sql `select * from ${sql(evts)} where stream in (${sql(streams)}) ${agg} order by position desc limit 1`; return result.map(mapToEvent)[0]; }, getEventsFrom: async (stream, position, lim) => { const streams = Array.isArray(stream) ? stream : [stream]; const limit = lim !== null && lim !== void 0 ? lim : opts.limit; const limitClause = limit ? sql `LIMIT ${limit}` : sql ``; const result = await sql `SELECT * FROM ${sql(evts)} WHERE stream IN ${sql(streams)} AND position > ${position} ORDER BY position ASC ${limitClause}`; return result.map(mapToEvent); }, createEvents: (0, util_1.createEventsMapper)(0), append: async (_stream, _aggregateId, _version, newEvents) => { try { const result = await sql.begin(async (sql) => { const toInsert = toStorableEvents(newEvents); const result = await sql `insert into ${sql(evts)} ${sql(toInsert, 'stream', 'aggregate_id', 'event', 'version', 'timestamp')} returning position`; for (let i = 0; i < result.length; i++) { newEvents[i].position = Number(result[i].position); } return newEvents; }); return result; } catch (ex) { // TODO: Verify version conflict error throw new error_1.VersionError(ex.message); } }, }; } exports.createProvider = createProvider; function toStorableEvents(events) { const appendable = []; for (let i = 0; i < events.length; i++) { appendable.push({ stream: events[i].stream, aggregate_id: events[i].aggregateId, version: events[i].version, event: JSON.stringify(events[i].event), timestamp: events[i].timestamp.toISOString(), }); } return appendable; } /** Migrate using a PG.Pool object */ async function migrate(opts) { const { bookmarks, events } = opts; if (!bookmarks || !events) return; try { await opts.sql.begin(async (sql) => { await sql `CREATE TABLE ${sql(bookmarks)} ( bookmark text PRIMARY KEY, position bigint )`; await sql ` CREATE TABLE ${sql(events)} ( position BIGSERIAL PRIMARY KEY, version integer, stream text, aggregate_id text, timestamp timestamptz, event text )`; await sql `CREATE UNIQUE INDEX events_stream_position_unique ON ${sql(events)} ( stream, position )`; await sql `CREATE UNIQUE INDEX events_stream_aggregate_version_unique ON ${sql(events)} ( stream, aggregate_id, version )`; }); } catch (ex) { throw ex; } } exports.migrate = migrate; function mapToEvent(row) { return { aggregateId: row.aggregate_id, event: JSON.parse(row.event), position: row.position, stream: row.stream, timestamp: row.timestamp, version: row.version, }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9zdGdyZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwb3N0Z3Jlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxtQ0FBc0M7QUFDdEMsaUNBQTJDO0FBdUIzQyxTQUFnQixjQUFjLENBQWtCLElBQWE7SUFDM0QsTUFBTSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUE7SUFDbEQsTUFBTSxPQUFPLEdBQ1gsSUFBSSxDQUFDLE9BQU87UUFDWixDQUFDLEdBQUcsRUFBRTtZQUNKLFVBQVU7UUFDWixDQUFDLENBQUMsQ0FBQTtJQUNKLE9BQU87UUFDTCxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7UUFDakIsTUFBTSxFQUFFLFVBQVU7UUFDbEIsT0FBTztRQUNQLFdBQVcsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUU7WUFDeEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxHQUFHLENBQUEsaUJBQWlCLEdBQUcsQ0FBQyxHQUFHLENBQUMscUJBQXFCLEVBQUUsVUFBVSxDQUFBO1lBRWxGLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFBRSxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUE7WUFDeEMsT0FBTyxDQUFDLENBQUE7UUFDVixDQUFDO1FBQ0QsV0FBVyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDN0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxHQUFHLENBQUEsVUFBVSxHQUFHLENBQUMsR0FBRyxDQUFDLG1CQUFtQixHQUFHLHFCQUFxQixFQUFFLEVBQUUsQ0FBQTtZQUV6RixJQUFJLE1BQU0sQ0FBQyxLQUFLLEtBQUssQ0FBQyxFQUFFO2dCQUN0QixNQUFNLEdBQUcsQ0FBQSxlQUFlLEdBQUcsQ0FBQyxHQUFHLENBQUMsaUNBQWlDLEVBQUUsS0FBSyxHQUFHLEdBQUcsQ0FBQTthQUMvRTtR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