@getanthill/datastore
Version:
Event-Sourced Datastore
145 lines • 6.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.publish = publish;
exports.publishEntityUpdates = publishEntityUpdates;
exports.created = created;
exports.updated = updated;
exports.patched = patched;
exports.applied = applied;
exports.restored = restored;
const omit_1 = __importDefault(require("lodash/omit"));
const utils_1 = require("../../utils");
const LAST_FRAGMENT_REGEXP = /\/[^/]+$/;
async function publish(services, topic, event) {
if (services.config.features.mqtt.isEnabled === true) {
await services.mqtt.publish(topic, event);
// Required to listen on deterministic event names:
services.mqtt.emit(topic.replace(LAST_FRAGMENT_REGEXP, ''), event);
}
if (services.config.features.amqp.isEnabled === true) {
await services.amqp.publish(topic, event);
// Required to listen on deterministic event names:
services.amqp.emit(topic.replace(LAST_FRAGMENT_REGEXP, ''), event);
}
}
async function publishEntityUpdates(services, modelName, eventName, entity) {
const topic = `${modelName}/${eventName}/success/${entity.correlationId}`.toLowerCase();
await Promise.all([
publish(services, topic, entity.state),
...entity.latestHandledEvents.map((e) => publish(services, `${modelName}/${e.type}/events/${entity.correlationId}`.toLowerCase(), e)),
]);
}
async function created(services, req, event) {
var _a;
const entity = services.models.factory(req.params.model);
const body = event;
if ((_a = req.headers) === null || _a === void 0 ? void 0 : _a['created-at']) {
body.created_at = (0, utils_1.getDate)(req.headers['created-at']);
}
await entity.create(body);
services.telemetry.logger.debug('[events#created] Entity created', {
entity: entity.state,
});
await publishEntityUpdates(services, req.params.model, 'created', entity);
return entity;
}
async function updated(services, req, event) {
var _a, _b, _c, _d;
const entity = services.models.factory(req.params.model, req.params.correlation_id);
const upsert = ((_a = req.headers) === null || _a === void 0 ? void 0 : _a['upsert']) === 'true';
const imperativeVersion = ((_b = req.headers) === null || _b === void 0 ? void 0 : _b['version']) !== undefined
? Number.parseInt((_c = req.headers) === null || _c === void 0 ? void 0 : _c['version'], 10)
: undefined;
const body = event;
if ((_d = req.headers) === null || _d === void 0 ? void 0 : _d['created-at']) {
body.created_at = (0, utils_1.getDate)(req.headers['created-at']);
}
if (upsert === true) {
await entity.upsert(body, { imperativeVersion });
}
else {
await entity.update(body, { imperativeVersion });
}
services.telemetry.logger.debug('[api/models#update] Entity updated', {
model: req.params.model,
entity: entity.state,
});
await publishEntityUpdates(services, req.params.model, 'updated', entity);
return entity;
}
async function patched(services, req, event) {
var _a, _b, _c;
const entity = services.models.factory(req.params.model, req.params.correlation_id);
const imperativeVersion = ((_a = req.headers) === null || _a === void 0 ? void 0 : _a['version'])
? Number.parseInt((_b = req.headers) === null || _b === void 0 ? void 0 : _b['version'], 10)
: undefined;
const body = event;
if ((_c = req.headers) === null || _c === void 0 ? void 0 : _c['created-at']) {
body.created_at = (0, utils_1.getDate)(req.headers['created-at']);
}
await entity.patch(body, { imperativeVersion });
services.telemetry.logger.debug('[api/models#update] Entity patched', {
model: req.params.model,
});
await publishEntityUpdates(services, req.params.model, 'patched', entity);
return entity;
}
async function applied(services, req, event) {
const entity = services.models.factory(req.params.model, req.params.correlation_id);
const imperativeVersion = req.headers['version'] !== undefined
? Number.parseInt(req.headers['version'], 10)
: undefined;
const isReplay = req.headers['replay'] === 'true';
const retryDuration = req.headers['retry-duration'] !== undefined
? Number.parseInt(req.headers['retry-duration'], 10)
: undefined;
let body = event;
if (req.headers['created-at']) {
body.created_at = (0, utils_1.getDate)(req.headers['created-at']);
}
if (isReplay === true) {
const Model = services.models.getModel(req.params.model);
const modelConfig = Model.getModelConfig();
const correlationField = modelConfig.correlation_field;
const foundEvent = await Model.getEventsCollection(Model.db(services.mongodb)).findOne({
[correlationField]: req.params.correlation_id,
type: body.type,
created_at: {
$gte: body.created_at,
$lte: body.created_at,
},
});
if (!!foundEvent === true) {
entity.state = await entity.getStateAtVersion(foundEvent.version);
return entity;
}
const originalPayload = (0, omit_1.default)(body, 'type', 'v', '_id', 'version');
body = await Model.decrypt(originalPayload);
}
await entity.apply(req.params.event_type.toUpperCase(), body, {
imperativeVersion,
retryDuration,
}, req.headers['event-version'] || req.params.event_version);
if (isReplay === false) {
await publishEntityUpdates(services, req.params.model, req.params.event_type, entity);
}
return entity;
}
async function restored(services, req, event) {
const entity = services.models.factory(req.params.model, req.params.correlation_id);
req.locals = req.locals || {};
req.locals.model = entity;
const version = Number.parseInt(req.params.version, 10);
await entity.getState();
if (entity.state === null) {
throw new Error('Not Found');
}
req.locals.currentVersion = entity.state.version;
await entity.restore(version);
await publishEntityUpdates(services, req.params.model, 'restored', entity);
return entity;
}
//# sourceMappingURL=handlers.js.map