evtstore
Version:
Event Sourcing with Node.JS
191 lines • 14.6 kB
JavaScript
;
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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