@othree.io/chisel
Version:
Event sourcing made easy
105 lines • 5.1 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateNewState = exports.loadState = void 0;
const optional_1 = require("@othree.io/optional");
const cerillo_1 = require("@othree.io/cerillo");
const loadState = (configuration) => (getEvents) => (getInitialState) => (reduce) => (contextId) => __awaiter(void 0, void 0, void 0, function* () {
return (0, optional_1.TryAsync)(() => __awaiter(void 0, void 0, void 0, function* () {
if (contextId.isEmpty) {
return (yield getInitialState(contextId))
.map(state => ({
state: state,
events: [],
}));
}
return (yield getEvents(contextId.get()))
.mapAsync((events) => __awaiter(void 0, void 0, void 0, function* () {
if (events.length === 0) {
return (yield getInitialState(contextId))
.map(state => ({
state: state,
events: [],
}));
}
const snapshotIdx = events.findIndex(event => event.type === configuration.SnapshotEventType);
const maybeInitialState = yield (0, cerillo_1.match)(snapshotIdx)
.when(_ => _ < 0).then((_) => __awaiter(void 0, void 0, void 0, function* () { return getInitialState(contextId); }))
.default((_) => __awaiter(void 0, void 0, void 0, function* () {
return (0, optional_1.Optional)(configuration.SnapshotSerializer.deserialize(events[_].snapshot));
}))
.get();
return maybeInitialState.map(initialState => {
const eventsReplayRange = snapshotIdx < 0 ? events.length : snapshotIdx;
const eventsToReplay = Array.from(Array(eventsReplayRange).keys())
.map(key => events[key])
.reverse();
const currentState = eventsToReplay.reduce(reduce, initialState);
return {
state: currentState,
events: eventsToReplay,
};
});
}));
}));
});
exports.loadState = loadState;
const calculateNewState = (configuration) => (newId) => (now) => (persistEvent) => (reduce) => (command, state, newEvents) => __awaiter(void 0, void 0, void 0, function* () {
return (0, optional_1.TryAsync)(() => __awaiter(void 0, void 0, void 0, function* () {
return newEvents.reduce((acumPromise, newEvent) => __awaiter(void 0, void 0, void 0, function* () {
const currentState = yield acumPromise;
const event = (yield persistEvent({
type: newEvent.type,
body: newEvent.body,
contextId: newEvent.contextId,
eventId: newId(),
eventDate: now(),
metadata: command.metadata,
emitter: command.emitter
})).get();
if ((currentState.events.length + 1) === (configuration.SnapshotFrequency - 1)) {
const snapshot = [event].reduce(reduce, currentState.state);
(yield persistEvent({
snapshot: configuration.SnapshotSerializer.serialize(snapshot),
contextId: event.contextId,
eventId: newId(),
eventDate: now(),
type: configuration.SnapshotEventType,
body: {},
})).get();
return {
state: snapshot,
events: [],
newEvents: [
...currentState.newEvents,
event,
],
};
}
else {
const updatedState = [event].reduce(reduce, currentState.state);
return {
state: updatedState,
events: [
...currentState.events,
event,
],
newEvents: [
...currentState.newEvents,
event,
],
};
}
}), Promise.resolve(Object.assign(Object.assign({}, state), { newEvents: [] })));
}));
});
exports.calculateNewState = calculateNewState;
//# sourceMappingURL=event-source.js.map