New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@castore/core

Package Overview
Dependencies
Maintainers
4
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@castore/core - npm Package Compare versions

Comparing version 1.4.0 to 1.4.1

100

dist/cjs/eventStore/eventStore.js

@@ -26,4 +26,2 @@ "use strict";

var _validateSnapshotInterval = require("./utils/validateSnapshotInterval");
var _excluded = ["aggregate", "lastEvent"];

@@ -57,5 +55,3 @@

} : _ref$simulateSideEffe,
$storageAdapter = _ref.storageAdapter,
_ref$snapshotInterval = _ref.snapshotInterval,
snapshotInterval = _ref$snapshotInterval === void 0 ? Infinity : _ref$snapshotInterval;
$storageAdapter = _ref.storageAdapter;
(0, _classCallCheck2["default"])(this, EventStore);

@@ -67,3 +63,2 @@ (0, _defineProperty2["default"])(this, "_types", void 0);

(0, _defineProperty2["default"])(this, "simulateSideEffect", void 0);
(0, _defineProperty2["default"])(this, "snapshotInterval", void 0);
(0, _defineProperty2["default"])(this, "getEvents", void 0);

@@ -87,3 +82,2 @@ (0, _defineProperty2["default"])(this, "pushEvent", void 0);

this.storageAdapter = $storageAdapter;
this.snapshotInterval = (0, _validateSnapshotInterval.validateSnapshotInterval)(snapshotInterval);

@@ -127,4 +121,3 @@ this.getStorageAdapter = function () {

var _ref3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(eventDetail) {
var storageAdapter, version, aggregateId, _yield$_this$getAggre, _aggregate;
var storageAdapter;
return _regenerator["default"].wrap(function _callee2$(_context2) {

@@ -141,29 +134,2 @@ while (1) {

case 3:
version = eventDetail.version, aggregateId = eventDetail.aggregateId;
if (!(version % _this.snapshotInterval === 0)) {
_context2.next = 14;
break;
}
_context2.next = 7;
return _this.getAggregate(aggregateId);
case 7:
_yield$_this$getAggre = _context2.sent;
_aggregate = _yield$_this$getAggre.aggregate;
if (_aggregate) {
_context2.next = 12;
break;
}
console.error('Unable to create snapshot: Aggregate not found');
return _context2.abrupt("return");
case 12:
_context2.next = 14;
return storageAdapter.putSnapshot(_aggregate);
case 14:
case "end":

@@ -208,5 +174,4 @@ return _context2.stop();

var _ref5 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(aggregateId) {
var options,
var _ref6,
maxVersion,
snapshot,
_yield$_this$getEvent,

@@ -222,28 +187,12 @@ events,

case 0:
options = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : {};
maxVersion = options.maxVersion;
if (!(maxVersion === undefined || maxVersion >= _this.snapshotInterval)) {
_context4.next = 6;
break;
}
_context4.next = 5;
return _this.getStorageAdapter().getLastSnapshot(aggregateId, {
_ref6 = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : {}, maxVersion = _ref6.maxVersion;
_context4.next = 3;
return _this.getEvents(aggregateId, {
maxVersion: maxVersion
});
case 5:
snapshot = _context4.sent.snapshot;
case 6:
_context4.next = 8;
return _this.getEvents(aggregateId, _objectSpread(_objectSpread({}, options), {}, {
minVersion: snapshot ? snapshot.version + 1 : undefined
}));
case 8:
case 3:
_yield$_this$getEvent = _context4.sent;
events = _yield$_this$getEvent.events;
aggregate = _this.buildAggregate(events, snapshot);
aggregate = _this.buildAggregate(events, undefined);
lastEvent = events[events.length - 1];

@@ -253,7 +202,6 @@ return _context4.abrupt("return", {

events: events,
lastEvent: lastEvent,
snapshot: snapshot
lastEvent: lastEvent
});
case 13:
case 8:
case "end":

@@ -272,4 +220,4 @@ return _context4.stop();

this.getExistingAggregate = /*#__PURE__*/function () {
var _ref6 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(aggregateId, options) {
var _yield$_this$getAggre2, aggregate, lastEvent, restAggregate;
var _ref7 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(aggregateId, options) {
var _yield$_this$getAggre, aggregate, lastEvent, restAggregate;

@@ -284,6 +232,6 @@ return _regenerator["default"].wrap(function _callee5$(_context5) {

case 2:
_yield$_this$getAggre2 = _context5.sent;
aggregate = _yield$_this$getAggre2.aggregate;
lastEvent = _yield$_this$getAggre2.lastEvent;
restAggregate = (0, _objectWithoutProperties2["default"])(_yield$_this$getAggre2, _excluded);
_yield$_this$getAggre = _context5.sent;
aggregate = _yield$_this$getAggre.aggregate;
lastEvent = _yield$_this$getAggre.lastEvent;
restAggregate = (0, _objectWithoutProperties2["default"])(_yield$_this$getAggre, _excluded);

@@ -315,3 +263,3 @@ if (!(aggregate === undefined || lastEvent === undefined)) {

return function (_x6, _x7) {
return _ref6.apply(this, arguments);
return _ref7.apply(this, arguments);
};

@@ -321,4 +269,4 @@ }();

this.simulateAggregate = function (events) {
var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
simulationDate = _ref7.simulationDate;
var _ref8 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
simulationDate = _ref8.simulationDate;

@@ -328,4 +276,4 @@ var eventsWithSideEffects = Object.values(events.reduce(_this.simulateSideEffect, {}));

if (simulationDate !== undefined) {
eventsWithSideEffects = eventsWithSideEffects.filter(function (_ref8) {
var timestamp = _ref8.timestamp;
eventsWithSideEffects = eventsWithSideEffects.filter(function (_ref9) {
var timestamp = _ref9.timestamp;
return timestamp <= simulationDate;

@@ -335,5 +283,5 @@ });

var sortedEventsWithSideEffects = eventsWithSideEffects.sort(function (_ref9, _ref10) {
var timestampA = _ref9.timestamp;
var timestampB = _ref10.timestamp;
var sortedEventsWithSideEffects = eventsWithSideEffects.sort(function (_ref10, _ref11) {
var timestampA = _ref10.timestamp;
var timestampB = _ref11.timestamp;
return timestampA < timestampB ? -1 : 1;

@@ -340,0 +288,0 @@ }).map(function (event, index) {

@@ -16,3 +16,2 @@ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";

import { UndefinedStorageAdapterError } from "../errors/undefinedStorageAdapterError";
import { validateSnapshotInterval } from "./utils/validateSnapshotInterval";
export var EventStore = /*#__PURE__*/_createClass(

@@ -40,5 +39,3 @@ /**

} : _ref$simulateSideEffe,
$storageAdapter = _ref.storageAdapter,
_ref$snapshotInterval = _ref.snapshotInterval,
snapshotInterval = _ref$snapshotInterval === void 0 ? Infinity : _ref$snapshotInterval;
$storageAdapter = _ref.storageAdapter;

@@ -57,4 +54,2 @@ _classCallCheck(this, EventStore);

_defineProperty(this, "snapshotInterval", void 0);
_defineProperty(this, "getEvents", void 0);

@@ -87,3 +82,2 @@

this.storageAdapter = $storageAdapter;
this.snapshotInterval = validateSnapshotInterval(snapshotInterval);

@@ -127,4 +121,3 @@ this.getStorageAdapter = function () {

var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(eventDetail) {
var storageAdapter, version, aggregateId, _yield$_this$getAggre, _aggregate;
var storageAdapter;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {

@@ -141,29 +134,2 @@ while (1) {

case 3:
version = eventDetail.version, aggregateId = eventDetail.aggregateId;
if (!(version % _this.snapshotInterval === 0)) {
_context2.next = 14;
break;
}
_context2.next = 7;
return _this.getAggregate(aggregateId);
case 7:
_yield$_this$getAggre = _context2.sent;
_aggregate = _yield$_this$getAggre.aggregate;
if (_aggregate) {
_context2.next = 12;
break;
}
console.error('Unable to create snapshot: Aggregate not found');
return _context2.abrupt("return");
case 12:
_context2.next = 14;
return storageAdapter.putSnapshot(_aggregate);
case 14:
case "end":

@@ -208,5 +174,4 @@ return _context2.stop();

var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(aggregateId) {
var options,
var _ref6,
maxVersion,
snapshot,
_yield$_this$getEvent,

@@ -222,28 +187,12 @@ events,

case 0:
options = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : {};
maxVersion = options.maxVersion;
if (!(maxVersion === undefined || maxVersion >= _this.snapshotInterval)) {
_context4.next = 6;
break;
}
_context4.next = 5;
return _this.getStorageAdapter().getLastSnapshot(aggregateId, {
_ref6 = _args4.length > 1 && _args4[1] !== undefined ? _args4[1] : {}, maxVersion = _ref6.maxVersion;
_context4.next = 3;
return _this.getEvents(aggregateId, {
maxVersion: maxVersion
});
case 5:
snapshot = _context4.sent.snapshot;
case 6:
_context4.next = 8;
return _this.getEvents(aggregateId, _objectSpread(_objectSpread({}, options), {}, {
minVersion: snapshot ? snapshot.version + 1 : undefined
}));
case 8:
case 3:
_yield$_this$getEvent = _context4.sent;
events = _yield$_this$getEvent.events;
aggregate = _this.buildAggregate(events, snapshot);
aggregate = _this.buildAggregate(events, undefined);
lastEvent = events[events.length - 1];

@@ -253,7 +202,6 @@ return _context4.abrupt("return", {

events: events,
lastEvent: lastEvent,
snapshot: snapshot
lastEvent: lastEvent
});
case 13:
case 8:
case "end":

@@ -272,4 +220,4 @@ return _context4.stop();

this.getExistingAggregate = /*#__PURE__*/function () {
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(aggregateId, options) {
var _yield$_this$getAggre2, aggregate, lastEvent, restAggregate;
var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(aggregateId, options) {
var _yield$_this$getAggre, aggregate, lastEvent, restAggregate;

@@ -284,6 +232,6 @@ return _regeneratorRuntime.wrap(function _callee5$(_context5) {

case 2:
_yield$_this$getAggre2 = _context5.sent;
aggregate = _yield$_this$getAggre2.aggregate;
lastEvent = _yield$_this$getAggre2.lastEvent;
restAggregate = _objectWithoutProperties(_yield$_this$getAggre2, _excluded);
_yield$_this$getAggre = _context5.sent;
aggregate = _yield$_this$getAggre.aggregate;
lastEvent = _yield$_this$getAggre.lastEvent;
restAggregate = _objectWithoutProperties(_yield$_this$getAggre, _excluded);

@@ -315,3 +263,3 @@ if (!(aggregate === undefined || lastEvent === undefined)) {

return function (_x6, _x7) {
return _ref6.apply(this, arguments);
return _ref7.apply(this, arguments);
};

@@ -321,4 +269,4 @@ }();

this.simulateAggregate = function (events) {
var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
simulationDate = _ref7.simulationDate;
var _ref8 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
simulationDate = _ref8.simulationDate;

@@ -328,4 +276,4 @@ var eventsWithSideEffects = Object.values(events.reduce(_this.simulateSideEffect, {}));

if (simulationDate !== undefined) {
eventsWithSideEffects = eventsWithSideEffects.filter(function (_ref8) {
var timestamp = _ref8.timestamp;
eventsWithSideEffects = eventsWithSideEffects.filter(function (_ref9) {
var timestamp = _ref9.timestamp;
return timestamp <= simulationDate;

@@ -335,5 +283,5 @@ });

var sortedEventsWithSideEffects = eventsWithSideEffects.sort(function (_ref9, _ref10) {
var timestampA = _ref9.timestamp;
var timestampB = _ref10.timestamp;
var sortedEventsWithSideEffects = eventsWithSideEffects.sort(function (_ref10, _ref11) {
var timestampA = _ref10.timestamp;
var timestampB = _ref11.timestamp;
return timestampA < timestampB ? -1 : 1;

@@ -340,0 +288,0 @@ }).map(function (event, index) {

@@ -16,3 +16,2 @@ import type { Aggregate } from "../aggregate";

simulateSideEffect: SideEffectsSimulator<D, $D>;
snapshotInterval: number;
getEvents: EventsGetter<D>;

@@ -27,3 +26,3 @@ pushEvent: EventPusher<$D>;

getStorageAdapter: () => StorageAdapter;
constructor({ eventStoreId, eventStoreEvents, reduce, simulateSideEffect, storageAdapter: $storageAdapter, snapshotInterval, }: {
constructor({ eventStoreId, eventStoreEvents, reduce, simulateSideEffect, storageAdapter: $storageAdapter, }: {
eventStoreId: I;

@@ -34,5 +33,4 @@ eventStoreEvents: E;

storageAdapter?: StorageAdapter;
snapshotInterval?: number;
});
}
//# sourceMappingURL=eventStore.d.ts.map

@@ -12,7 +12,9 @@ import type { Aggregate } from "../aggregate";

export declare type AggregateIdsLister = (listAggregateOptions?: ListAggregateIdsOptions) => Promise<ListAggregateIdsOutput>;
export declare type AggregateGetter<D extends EventDetail, A extends Aggregate, R extends boolean = false> = (aggregateId: string, options?: EventsQueryOptions) => Promise<{
export declare type GetAggregateOptions = {
maxVersion?: number;
};
export declare type AggregateGetter<D extends EventDetail, A extends Aggregate, R extends boolean = false> = (aggregateId: string, options?: GetAggregateOptions) => Promise<{
aggregate: R extends true ? A : A | undefined;
events: D[];
lastEvent: R extends true ? D : D | undefined;
snapshot: A | undefined;
}>;

@@ -19,0 +21,0 @@ export declare type SimulationOptions = {

@@ -9,7 +9,7 @@ export type { Aggregate } from './aggregate';

export type { StorageAdapter } from './storageAdapter';
export type { EventsQueryOptions, PushEventContext, ListAggregateIdsOptions, ListAggregateIdsOutput, GetLastSnapshotOptions, ListSnapshotsOptions, } from './storageAdapter';
export type { EventsQueryOptions, PushEventContext, ListAggregateIdsOptions, ListAggregateIdsOutput, } from './storageAdapter';
export { EventStore } from './eventStore';
export type { SimulationOptions, EventStoreId, EventStoreEventsTypes, EventStoreEventsDetails, EventStoreReducer, EventStoreAggregate, Reducer, } from './eventStore';
export type { GetAggregateOptions, SimulationOptions, EventStoreId, EventStoreEventsTypes, EventStoreEventsDetails, EventStoreReducer, EventStoreAggregate, Reducer, } from './eventStore';
export { Command, tuple } from './command/command';
export type { $Contravariant } from './utils';
//# sourceMappingURL=index.d.ts.map

@@ -76,3 +76,3 @@ {

},
"version": "1.4.0"
"version": "1.4.1"
}
<p align="center">
<img src="assets/logo.svg" height="128">
<h1 style="border-bottom:none;font-size:60px;margin-bottom:0;" align="center" >Castore 🦫</h1>
<h1 style="border-bottom:none;font-size:60px;margin-bottom:0;" align="center" >Castore</h1>
</p>

@@ -25,3 +25,2 @@ <p align="center">

<p align="center">

@@ -31,3 +30,2 @@ Castore is a TypeScript library that <b>makes Event Sourcing easy</b> 😎

With Castore, you'll be able to:

@@ -85,3 +83,2 @@

- [📨 Command](#-command)
- [📸 Snapshots](#-snapshots)
- [Resources](#resources)

@@ -182,3 +179,3 @@ - [🎯 Test Tools](#-test-tools)

- [JSON-Schema Event Type](./packages/json-schema-event/README.md)
- [JSON Schema Event Type](./packages/json-schema-event/README.md)
- [Zod Event Type](./packages/zod-event/README.md)

@@ -198,7 +195,7 @@

- <code>type <i>(string)</i>:</code> The event type
- <code>type <i>(string)</i></code>: The event type
```ts
const eventType = userCreatedEventType.type;
// => "USER_CREATED"
// => 'USER_CREATED'
```

@@ -304,3 +301,3 @@

> ☝️ Note that aggregates are always **computed on the fly**, and NOT stored. Changing them does not require any data migration whatsoever (except if you use snapshots, an invalidation is needed first).
> ☝️ Note that aggregates are always **computed on the fly**, and NOT stored. Changing them does not require any data migration whatsoever.

@@ -314,2 +311,3 @@ ### 🎁 `EventStore`

In Castore, `EventStore` classes are NOT responsible for actually storing data (this will come with [event storage adapters](#-eventstorageadapter)). But rather to provide a boilerplate-free and type-safe interface to perform many actions such as:
- Listing aggregate ids

@@ -339,24 +337,192 @@ - Accessing events of an aggregate

_...coming soon_
- <code>eventStoreId <i>(string)</i></code>: A string identifying the event store
- <code>eventStoreEvents <i>(EventType[])</i></code>: The list of event types in the event store
- <code>reduce <i>(EventType[])</i></code>: A [reducer function](#⚙️-reducer) that can be applied to the store event types
- <code>storageAdapter <i>(?EventStorageAdapter)</i></code>: See [`EventStorageAdapter`](#💾-eventstorageadapter)
<!-- > ☝️ Note that it's the ReturnType of the `reducer` function that is used to infer the `Aggregate` type of the EventStore. -->
> ☝️ Note that it's the return type of the `reducer` that is used to infer the `Aggregate` type of the EventStore. It is important to type it explicitely.
**Properties:**
_...coming soon_
- <code>eventStoreId <i>(string)</i></code>
**Type Helpers:**
```ts
const userEventStoreId = userEventStore.eventStoreId;
// => 'USERS'
```
_...coming soon_
- <code>eventStoreEvents <i>(EventType[])</i></code>
<!-- EventStoreId
```ts
const userEventStoreEvents = userEventStore.eventStoreEvents;
// => [userCreatedEventType, userRemovedEventType...]
```
- <code>reduce <i>((Aggregate, EventType) => Aggregate)</i></code>
```ts
const reducer = userEventStore.reduce;
// => usersReducer
```
- <code>storageAdapter <i>?EventStorageAdapter</i></code>: See [`EventStorageAdapter`](#💾-eventstorageadapter)
```ts
const storageAdapter = userEventStore.storageAdapter;
// => undefined (we did not provide one in this example)
```
> ☝️ The `storageAdapter` is not read-only so you do not have to provide it right away.
**Sync Methods:**
- <code>getStorageAdapter <i>(() => EventStorageAdapter)</i></code>: Returns the event store event storage adapter if it exists. Throws an `UndefinedStorageAdapterError` if it doesn't.
```ts
import { UndefinedStorageAdapterError } from '@castore/core';
expect(() => userEventStore.getStorageAdapter()).toThrow(
new UndefinedStorageAdapterError({ eventStoreId: 'USERS' }),
);
// => true
```
- <code>buildAggregate <i>((eventDetails: EventDetail[], initialAggregate?: Aggregate) => Aggregate | undefined)</i></code>: Applies the event store reducer to a serie of events.
```ts
const johnDowAggregate = userEventStore.buildAggregate(johnDowEvents);
```
**Async Methods:**
The following methods interact with the data layer of your event store through its [`EventStorageAdapter`](#💾-eventstorageadapter). They will throw an `UndefinedStorageAdapterError` if you did not provide one.
- <code>getEvents <i>((aggregateId: string, opt?: OptionsObj = {}) => Promise\<ResponseObj\>)</i></code>: Retrieves the events of an aggregate, ordered by `version`. Returns an empty array if no event is found for this `aggregateId`.
`OptionsObj` contains the following attributes:
- <code>minVersion <i>(?number)</i></code>: To retrieve events above a certain version
- <code>maxVersion <i>(?number)</i></code>: To retrieve events below a certain version
- <code>limit <i>(?number)</i></code>: Maximum number of events to retrieve
- <code>reverse <i>(?boolean = false)</i></code>: To retrieve events in reverse order (does not require to swap `minVersion` and `maxVersion`)
`ResponseObj` contains the following attributes:
- <code>events <i>(EventDetail[])</i></code>: The aggregate events (possibly empty)
```ts
const { events: allEvents } = await userEventStore.getEvents(aggregateId);
// => typed as UserEventDetail[] 🙌
// 👇 Retrieve a range of events
const { events: rangedEvents } = await userEventStore.getEvents(aggregateId, {
minVersion: 2,
maxVersion: 5,
});
// 👇 Retrieve the last event of the aggregate
const { events: onlyLastEvent } = await userEventStore.getEvents(aggregateId, {
reverse: true,
limit: 1,
});
```
- <code>getAggregate <i>((aggregateId: string, opt?: OptionsObj = {}) => Promise\<ResponseObj\>)</i></code>: Retrieves the events of an aggregate and build it.
`OptionsObj` contains the following attributes:
- <code>maxVersion <i>(?number)</i></code>: To retrieve aggregate below a certain version
`ResponseObj` contains the following attributes:
- <code>aggregate <i>(?Aggregate)</i></code>: The aggregate (possibly `undefined`)
- <code>events <i>(EventDetail[])</i></code>: The aggregate events (possibly empty)
- <code>lastEvent <i>(?EventDetail)</i></code>: The last event (possibly `undefined`)
```ts
const { aggregate: johnDow } = await userEventStore.getAggregate(aggregateId);
// => typed as UserAggregate | undefined 🙌
// 👇 Retrieve an aggregate below a certain version
const { aggregate: aggregateBelowVersion } = await userEventStore.getAggregate(
aggregateId,
{ maxVersion: 5 },
);
// 👇 Returns the events if you need them
const { aggregate, events } = await userEventStore.getAggregate(aggregateId);
```
- <code>getExistingAggregate <i>((aggregateId: string, opt?: OptionsObj = {}) => Promise\<ResponseObj\>)</i></code>: Same as `getAggregate` method, but ensures that the aggregate exists. Throws an `AggregateNotFoundError` if no event is found for this `aggregateId`.
```ts
import { AggregateNotFoundError } from '@castore/core';
expect(async () =>
userEventStore.getExistingAggregate(unexistingId),
).resolves.toThrow(
new AggregateNotFoundError({
eventStoreId: 'USERS',
aggregateId: unexistingId,
}),
);
// true
const { aggregate } = await userEventStore.getAggregate(aggregateId);
// => 'aggregate' and 'lastEvent' are always defined 🙌
```
- <code>pushEvent <i>((eventDetail: EventDetail) => Promise\<void\>)</i></code>: Pushes a new event to the event store. Throws an `EventAlreadyExistsError` if an event already exists for the corresponding `aggregateId` and `version`.
```ts
await userEventStore.pushEvent({
aggregateId,
version: lastVersion + 1,
timestamp: new Date().toISOString(),
type: 'USER_CREATED', // <= event type is correctly typed 🙌
payload, // <= payload is typed according to the provided event type 🙌
metadata, // <= same goes for metadata 🙌
});
```
- <code>listAggregateIds <i>((opt?: OptionsObj = {}) => Promise\<ResponseObj\>)</i></code>: Retrieves the list of `aggregateId` of an event store, ordered by `timestamp` of their first event. Returns an empty array if no aggregate is found.
`OptionsObj` contains the following attributes:
- <code>limit <i>(?number)</i></code>: Maximum number of aggregate ids to retrieve
- <code>pageToken <i>(?string)</i></code>: To retrieve a paginated result of aggregate ids
`ResponseObj` contains the following attributes:
- <code>aggregateIds <i>(string[])</i></code>: The list of aggregate ids
- <code>nextPageToken <i>(?string)</i></code>: A token for the next page of aggregate ids if one exists
```ts
const accAggregateIds: string = [];
const { aggregateIds: firstPage, nextPageToken } =
await userEventStore.getAggregate({ limit: 20 });
accAggregateIds.push(...firstPage);
if (nextPageToken) {
const { aggregateIds: secondPage } = await userEventStore.getAggregate({
limit: 20,
pageToken: nextPageToken,
});
accAggregateIds.push(...secondPage);
}
```
**Type Helpers:**
- <code>EventStoreId</code>: Returns the `EventStore` id
```ts
import type { EventStoreId } from '@castore/core';
type UserEventStoreId = EventStoreId<typeof userEventStore>;
// => "USERS"
// => 'USERS'
```
EventStoreEventsTypes
- <code>EventStoreEventsTypes</code>: Returns the `EventStore` list of events types

@@ -367,6 +533,6 @@ ```ts

type UserEventsTypes = EventStoreEventsTypes<typeof userEventStore>;
// => [typeof userCreatedEventTypeType, typeof userRemovedEventTypeType...]
// => [typeof userCreatedEventType, typeof userRemovedEventType...]
```
EventStoreEventsDetails
- <code>EventStoreEventsDetails</code>: Returns the union of all the `EventStore` possible events details

@@ -376,14 +542,26 @@ ```ts

type UserEventsDetails = EventStoreEventsTypes<typeof userEventStore>;
// => TODO
type UserEventsDetails = EventStoreEventsDetails<typeof userEventStore>;
// => EventTypeDetail<typeof userCreatedEventType>
// | EventTypeDetail<typeof userRemovedEventType>
// | ...
```
EventStoreEventsDetails
- <code>EventStoreReducer</code>: Returns the `EventStore` reducer
```ts
import type { EventStoreEventsDetails } from '@castore/core';
import type { EventStoreReducer } from '@castore/core';
type UserEventsDetails = EventStoreEventsTypes<typeof userEventStore>;
``` -->
type UserReducer = EventStoreReducer<typeof userEventStore>;
// => Reducer<UserAggregate, UserEventsDetails>
```
- <code>EventStoreAggregate</code>: Returns the `EventStore` aggregate
```ts
import type { EventStoreAggregate } from '@castore/core';
type UserReducer = EventStoreAggregate<typeof userEventStore>;
// => UserAggregate
```
### 💾 `EventStorageAdapter`

@@ -408,8 +586,22 @@

_...coming soon_
Commands represent an intent to modify the state of your application. They usually result in pushing one or several events to your event stores.
### 📸 `Snapshots`
They typically consist in:
_...coming soon_
- Fetching the required aggregates (if not the first event of a new aggregate)
- Validating that the intent is acceptable in regards to the state of the application\*
- Pushing new events with incremented versions
> \* ☝️ Note that commands should NOT use read models for the validation step. Read models are not the source of truth, and may not contain the freshest state.
Fetching and pushing events at separate non-simultaneously exposes your application to [race conditions](https://en.wikipedia.org/wiki/Race_condition). To counter that, commands executions are designed to be retried when an `EventAlreadyExistsError` is triggered.
<!-- TODO, add schema -->
_...technical description coming soon_
When writing on several event stores at once, it is important to use transactions, i.e. to make sure that all events are written or none. This ensures that the application is not in a corrupt state.
Transactions accross event stores cannot be easily abstracted, so check you adapter library on how to achieve this. For instance, the [`DynamoDBEventStorageAdapter`](./packages/dynamodb-event-storage-adapter/README.md) exposes a [`pushEventsTransaction`](./packages/dynamodb-event-storage-adapter/src/utils/pushEventsTransaction.ts) util.
## Resources

@@ -419,11 +611,25 @@

_...coming soon_
Castore comes with a handy [Test Tool package](./packages/test-tools/README.md) that facilitates the writing of unit tests: It allows mocking event stores, populating them with an initial state and resetting them to it in a boilerplate-free and type-safe way.
### 🔗 Packages List
_...coming soon_
#### 🏷 Event Types
- [JSON Schema Event Type](./packages/json-schema-event/README.md): DRY `EventType` definition using [JSON Schemas](http://json-schema.org/understanding-json-schema/reference/index.html) and [`json-schema-to-ts`](https://github.com/ThomasAribart/json-schema-to-ts)
- [Zod Event Type](./packages/zod-event/README.md): DRY `EventType` definition using [`zod`](https://github.com/colinhacks/zod)
#### 💾 Event Storage Adapters
- [DynamoDB Event Storage Adapter](./packages/dynamodb-event-storage-adapter/README.md): Implementation of the `EventStorageAdapter` interface based on DynamoDB.
- [In-Memory Event Storage Adapter](./packages/inmemory-event-storage-adapter/README.md): Implementation of the `EventStorageAdapter` interface using a local Node/JS object. To be used in manual or unit tests.
#### 📨 Commands
- [JSON Schema Command](./packages/json-schema-command/README.md): DRY `Command` definition using [JSON Schemas](http://json-schema.org/understanding-json-schema/reference/index.html) and [`json-schema-to-ts`](https://github.com/ThomasAribart/json-schema-to-ts)
### 📖 Common Patterns
_...coming soon_
- Simulating a future/past aggregate state: _...coming soon_
- Projecting on read models: _...coming soon_
- Replaying events: _...coming soon_
- Snapshotting: _...coming soon_

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc