UNPKG

evtstore

Version:

Event Sourcing with Node.JS

191 lines 14.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.migrateClient = exports.migratePool = exports.migrate = exports.createProvider = void 0; const error_1 = require("./error"); const util_1 = require("./util"); function createProvider(opts) { const onError = opts.onError || (() => { /* NOOP */ }); return { limit: opts.limit, driver: 'pg', onError, getPosition: async (bm) => { const result = await opts.client.query(`select * from "${opts.bookmarks}" where bookmark = $1 limit 1`, [bm]); if (result.rows[0]) return result.rows[0].position; return 0; }, setPosition: async (bm, pos) => { const result = await opts.client.query(`update "${opts.bookmarks}" set position = $1 where bookmark = $2`, [pos, bm]); if (result.rowCount === 0) { await opts.client.query(`insert into "${opts.bookmarks}" (bookmark, position) values ($1, $2)`, [bm, pos]); } }, getEventsFor: async (stream, aggregateId, fromPosition) => { let query = `select * from "${opts.events}" where stream = $1 and aggregate_id = $2`; const values = [stream, aggregateId]; if (fromPosition !== undefined) { query += ` and position > $3`; values.push(fromPosition); } query += ` order by version asc`; const result = await opts.client.query(query, values); return result.rows.map(mapToEvent); }, getLastEventFor: async (stream, aggregateId) => { const streams = Array.isArray(stream) ? stream : [stream]; const params = streams.map((_, i) => `$${i + 1}`).join(', '); let query = `select * from "${opts.events}" where stream in (${params})`; const values = [...streams]; if (aggregateId) { query += ` and aggregate_id = $${streams.length + 1}`; values.push(aggregateId); } query += ` order by position desc limit 1`; const result = await opts.client.query(query, values); return result.rows.map(mapToEvent)[0]; }, getEventsFrom: async (stream, position, lim) => { const streams = Array.isArray(stream) ? stream : [stream]; const params = streams.map((_, i) => `$${i + 1}`).join(', '); const last = `$${streams.length + 1}`; let q = `select * from "${opts.events}" where stream in (${params}) and position > ${last} order by position asc`; const values = [...streams, position]; const limit = lim !== null && lim !== void 0 ? lim : opts.limit; if (limit) { q += ` limit $${streams.length + 2}`; values.push(limit); } const result = await opts.client.query(q, values); return result.rows.map(mapToEvent); }, createEvents: (0, util_1.createEventsMapper)(0), append: async (_stream, _aggregateId, _version, newEvents) => { const trx = await opts.client.connect(); try { await trx.query('BEGIN'); const toInsert = newEvents.map((storeEvent) => [ storeEvent.stream, storeEvent.aggregateId, JSON.stringify(storeEvent.event), storeEvent.version, storeEvent.timestamp.toISOString(), ]); let index = 0; for (const insert of toInsert) { const result = await trx.query(`insert into "${opts.events}" (stream, aggregate_id, event, version, timestamp) values ( $1, $2, $3, $4, $5 ) returning position`, insert); newEvents[index].position = Number(result.rows[0].position); index++; } await trx.query('COMMIT'); return newEvents; } catch (ex) { await trx.query('ROLLBACK'); // TODO: Verify version conflict error throw new error_1.VersionError(ex.message); } finally { trx.release(); } }, }; } exports.createProvider = createProvider; /** Migrate using a PG.Pool object */ async function migrate(opts) { if (!opts.bookmarks && !opts.events) return; const trx = await opts.client.connect(); try { await trx.query('BEGIN'); await trx.query(` CREATE TABLE "${opts.bookmarks}" ( bookmark text PRIMARY KEY, position bigint ) `); await trx.query(` CREATE TABLE "${opts.events}" ( position BIGSERIAL PRIMARY KEY, version integer, stream text, aggregate_id text, timestamp timestamptz, event text ) `); await trx.query(`CREATE UNIQUE INDEX events_stream_position_unique ON "${opts.events}" ( stream, position )`); await trx.query(`CREATE UNIQUE INDEX events_stream_aggregate_version_unique ON "${opts.events}" ( stream, aggregate_id, version )`); await trx.query('COMMIT'); } catch (ex) { await trx.query('ROLLBACK'); } finally { trx.release(); } } exports.migrate = migrate; /** Migrate using a PG.Pool object */ function migratePool(opts) { return migrate(opts); } exports.migratePool = migratePool; /** Migrate using a PG.Client object */ async function migrateClient(opts) { if (!opts.bookmarks && !opts.events) return; const client = opts.client; try { await client.query('BEGIN'); await client.query(` CREATE TABLE "${opts.bookmarks}" ( bookmark text PRIMARY KEY, position bigint ) `); await client.query(` CREATE TABLE "${opts.events}" ( position BIGSERIAL PRIMARY KEY, version integer, stream text, aggregate_id text, timestamp timestamptz, event text ) `); await client.query(`CREATE UNIQUE INDEX events_stream_position_unique ON "${opts.events}" ( stream, position )`); await client.query(`CREATE UNIQUE INDEX events_stream_aggregate_version_unique ON "${opts.events}" ( stream, aggregate_id, version )`); await client.query('COMMIT'); } catch (ex) { await client.query('ROLLBACK'); throw ex; } } exports.migrateClient = migrateClient; 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxtQ0FBc0M7QUFDdEMsaUNBQTJDO0FBdUIzQyxTQUFnQixjQUFjLENBQWtCLElBQWE7SUFDM0QsTUFBTSxPQUFPLEdBQ1gsSUFBSSxDQUFDLE9BQU87UUFDWixDQUFDLEdBQUcsRUFBRTtZQUNKLFVBQVU7UUFDWixDQUFDLENBQUMsQ0FBQTtJQUNKLE9BQU87UUFDTCxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7UUFDakIsTUFBTSxFQUFFLElBQUk7UUFDWixPQUFPO1FBQ1AsV0FBVyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUN4QixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUNwQyxrQkFBa0IsSUFBSSxDQUFDLFNBQVMsK0JBQStCLEVBQy9ELENBQUMsRUFBRSxDQUFDLENBQ0wsQ0FBQTtZQUNELElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQUUsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtZQUNsRCxPQUFPLENBQUMsQ0FBQTtRQUNWLENBQUM7UUFDRCxXQUFXLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUM3QixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUNwQyxXQUFXLElBQUksQ0FBQyxTQUFTLHlDQUF5QyxFQUNsRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FDVixDQUFBO1lBQ0QsSUFBSSxNQUFNLENBQUMsUUFBUSxLQUFLLENBQUMsRUFBRTtnQkFDekIsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDckIsZ0JBQWdCLElBQUksQ0FBQyxTQUFTLHdDQUF3QyxFQUN0RSxDQUFDLEVBQUUsRUFBRSxHQUFHLENB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