Socket
Socket
Sign inDemoInstall

@arque/core

Package Overview
Dependencies
Maintainers
4
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arque/core - npm Package Compare versions

Comparing version 0.1.0-alpha.16 to 0.2.0-alpha.0

dist/libs/adapters/config-adapter.d.ts

5

dist/index.d.ts

@@ -1,6 +0,5 @@

export * from './libs/error';
export * from './libs/event-id';
export * from './libs/types';
export * from './libs/event-id';
export * from './libs/event-store';
export * from './libs/adapters';
export * from './libs/aggregate';
export * from './libs/aggregate-factory';
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./libs/error"), exports);
tslib_1.__exportStar(require("./libs/event-id"), exports);
tslib_1.__exportStar(require("./libs/types"), exports);
tslib_1.__exportStar(require("./libs/event-id"), exports);
tslib_1.__exportStar(require("./libs/event-store"), exports);
tslib_1.__exportStar(require("./libs/adapters"), exports);
tslib_1.__exportStar(require("./libs/aggregate"), exports);
tslib_1.__exportStar(require("./libs/aggregate-factory"), exports);
//# sourceMappingURL=index.js.map

32

dist/libs/aggregate-factory.d.ts
/// <reference types="node" />
import { EventStore } from './event-store';
import { Aggregate, SnapshotOpts } from './aggregate';
import { Command, CommandHandler, Event, EventHandler } from './types';
export declare class AggregateFactory<TCommand extends Command = Command, TEvent extends Event = Event, TState = unknown> {
private readonly eventStore;
import { Aggregate, AggregateOpts } from './aggregate';
import { StoreAdapter } from './adapters/store-adapter';
import { StreamAdapter } from './adapters/stream-adapter';
type ExtractState<T> = T extends Aggregate<infer State, any, any> ? State : never;
type ExtractCommandHandler<T> = T extends Aggregate<any, infer CommandHandler, any> ? CommandHandler : never;
type ExtractEventHandler<T> = T extends Aggregate<any, any, infer EventHandler> ? EventHandler : never;
export declare class AggregateFactory<T extends Aggregate> {
private readonly store;
private readonly stream;
private commandHandlers;
private eventHandlers;
private opts?;
private readonly opts;
private cache;
constructor(eventStore: EventStore, commandHandlers: CommandHandler<TCommand, TEvent, TState>[], eventHandlers: EventHandler<TEvent, TState>[], opts?: {
readonly cacheOpts?: {
max?: number;
ttl?: number;
};
readonly snapshotOpts?: SnapshotOpts<TState>;
});
constructor(store: StoreAdapter, stream: StreamAdapter, commandHandlers: ExtractCommandHandler<T>[], eventHandlers: ExtractEventHandler<T>[], opts: {
readonly defaultState?: ExtractState<T> | (() => ExtractState<T>);
readonly cacheMax?: number;
readonly cacheTTL?: number;
} & Partial<AggregateOpts<ExtractState<T>>>);
load(id: Buffer, opts?: {
noReload?: true;
ignoreSnapshot?: true;
}): Promise<Aggregate<TCommand, TEvent, TState>>;
}): Promise<T>;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AggregateFactory = void 0;
/* eslint-disable @typescript-eslint/no-explicit-any */
const lru_cache_1 = require("lru-cache");
const aggregate_1 = require("./aggregate");
class AggregateFactory {
constructor(eventStore, commandHandlers, eventHandlers, opts) {
var _a, _b;
this.eventStore = eventStore;
constructor(store, stream, commandHandlers, eventHandlers, opts) {
this.store = store;
this.stream = stream;
this.commandHandlers = commandHandlers;

@@ -14,17 +15,25 @@ this.eventHandlers = eventHandlers;

this.cache = new lru_cache_1.LRUCache({
max: ((_a = opts === null || opts === void 0 ? void 0 : opts.cacheOpts) === null || _a === void 0 ? void 0 : _a.max) || 1000,
ttl: ((_b = opts === null || opts === void 0 ? void 0 : opts.cacheOpts) === null || _b === void 0 ? void 0 : _b.ttl) || 604800000, // 7 days
max: opts.cacheMax || 256,
ttl: opts.cacheTTL || 86400000, // 24 hours
});
}
async load(id, opts) {
const _id = id.toString('hex');
const _id = id.toString('base64');
let promise = this.cache.get(_id);
if (!promise) {
promise = (async () => {
const aggregate = new aggregate_1.Aggregate(this.eventStore, this.commandHandlers, this.eventHandlers, id, 0, null, this.opts);
const state = this.opts.defaultState ?
(this.opts.defaultState instanceof Function ? this.opts.defaultState() : this.opts.defaultState) : null;
const aggregate = new aggregate_1.Aggregate(this.store, this.stream, this.commandHandlers, this.eventHandlers, id, 0, state, {
shouldTakeSnapshot: this.opts.shouldTakeSnapshot,
snapshotInterval: this.opts.snapshotInterval,
});
if (!(opts === null || opts === void 0 ? void 0 : opts.noReload)) {
await aggregate.reload(opts);
await aggregate.reload();
}
return aggregate;
})();
})().catch(err => {
this.cache.delete(_id);
throw err;
});
this.cache.set(_id, promise);

@@ -35,3 +44,6 @@ return promise;

if (!(opts === null || opts === void 0 ? void 0 : opts.noReload)) {
await aggregate.reload(opts);
await aggregate.reload().catch(err => {
this.cache.delete(_id);
throw err;
});
}

@@ -38,0 +50,0 @@ return aggregate;

/// <reference types="node" />
import { Event, EventHandler, Command, CommandHandler } from './types';
import { EventStore } from './event-store';
export type SnapshotOpts<TState = unknown> = {
interval?: number;
shouldTakeSnapshot?: (ctx: {
import { Event, EventHandler, CommandHandler, Command } from './types';
import { StoreAdapter } from './adapters/store-adapter';
import { StreamAdapter } from './adapters/stream-adapter';
type ExtractCommand<T> = T extends CommandHandler<infer Command, any, any> ? Command : never;
export type AggregateOpts<TState> = {
readonly shouldTakeSnapshot?: (ctx: {
aggregate: {

@@ -13,31 +14,32 @@ id: Buffer;

}) => boolean;
readonly snapshotInterval?: number;
};
export declare class Aggregate<TCommand extends Command = Command, TEvent extends Event = Event, TState = unknown> {
private readonly eventStore;
export declare class Aggregate<TState = unknown, TCommandHandler extends CommandHandler<Command, Event, TState> = CommandHandler<Command, Event, TState>, TEventHandler extends EventHandler<Event, TState> = EventHandler<Event, TState>> {
private readonly store;
private readonly stream;
private _id;
private _version;
private _state;
private readonly opts?;
private mutex;
private commandHandlers;
private eventHandlers;
constructor(eventStore: EventStore, commandHandlers: CommandHandler<TCommand, TEvent, TState>[], eventHandlers: EventHandler<TEvent, TState>[], _id: Buffer, _version: number, _state: TState, opts?: {
readonly snapshotOpts?: SnapshotOpts<TState>;
});
private opts;
private _lastEvent;
constructor(store: StoreAdapter, stream: StreamAdapter, commandHandlers: TCommandHandler[], eventHandlers: TEventHandler[], _id: Buffer, _version: number, _state: TState, opts?: Partial<AggregateOpts<TState>>);
get id(): Buffer;
get version(): number;
get state(): TState;
private getCommandHandler;
private getEventHandler;
get lastEvent(): Event;
private commandHandler;
private eventHandler;
private shoudTakeSnapshot;
private digest;
private _reload;
reload(opts?: {
ignoreSnapshot?: true;
}): Promise<void>;
process(command: TCommand, opts?: {
reload(): Promise<void>;
private dispatch;
process(command: ExtractCommand<TCommandHandler>, ctx?: Buffer, opts?: {
noInitialReload?: true;
ignoreSnapshot?: true;
maxRetries?: number;
}): Promise<void>;
}
export {};

@@ -5,2 +5,3 @@ "use strict";

const tslib_1 = require("tslib");
/* eslint-disable @typescript-eslint/no-explicit-any */
const async_mutex_1 = require("async-mutex");

@@ -10,12 +11,15 @@ const exponential_backoff_1 = require("exponential-backoff");

const event_id_1 = require("./event-id");
const store_adapter_1 = require("./adapters/store-adapter");
class Aggregate {
constructor(eventStore, commandHandlers, eventHandlers, _id, _version, _state, opts) {
this.eventStore = eventStore;
constructor(store, stream, commandHandlers, eventHandlers, _id, _version, _state, opts) {
this.store = store;
this.stream = stream;
this._id = _id;
this._version = _version;
this._state = _state;
this.opts = opts;
this._lastEvent = null;
this.mutex = new async_mutex_1.Mutex();
this.commandHandlers = new Map(commandHandlers.map((item) => [item.type, item]));
this.eventHandlers = new Map(eventHandlers.map((item) => [item.type, item]));
this.opts = Object.assign({ snapshotInterval: 100 }, opts);
}

@@ -31,3 +35,6 @@ get id() {

}
getCommandHandler(type) {
get lastEvent() {
return this._lastEvent;
}
commandHandler(type) {
const handler = this.commandHandlers.get(type);

@@ -37,3 +44,3 @@ (0, assert_1.default)(handler, `command handler does not exist: type=${type}`);

}
getEventHandler(type) {
eventHandler(type) {
const handler = this.eventHandlers.get(type);

@@ -44,4 +51,3 @@ (0, assert_1.default)(handler, `event handler does not exist: type=${type}`);

shoudTakeSnapshot() {
var _a;
const { shouldTakeSnapshot, interval } = ((_a = this.opts) === null || _a === void 0 ? void 0 : _a.snapshotOpts) || {};
const { shouldTakeSnapshot, snapshotInterval } = this.opts;
if (shouldTakeSnapshot) {

@@ -56,36 +62,21 @@ return shouldTakeSnapshot({

}
return this.version % (interval || 100) === 0;
return this.version % snapshotInterval === 0;
}
async digest(events, opts) {
async digest(events) {
var _a, e_1, _b, _c;
try {
for (var _d = true, events_1 = tslib_1.__asyncValues(events), events_1_1; events_1_1 = await events_1.next(), _a = events_1_1.done, !_a;) {
for (var _d = true, events_1 = tslib_1.__asyncValues(events), events_1_1; events_1_1 = await events_1.next(), _a = events_1_1.done, !_a; _d = true) {
_c = events_1_1.value;
_d = false;
try {
const event = _c;
const eventHandler = this.getEventHandler(event.type);
const state = await eventHandler.handle({
aggregate: {
id: this.id,
version: this.version,
},
state: this.state,
}, event);
this._state = state;
this._version = event.aggregate.version;
if (!(opts === null || opts === void 0 ? void 0 : opts.disableSnapshot) && this.shoudTakeSnapshot()) {
await this.eventStore.saveSnapshot({
aggregate: {
id: this.id,
version: this.version,
},
state: this.state,
timestamp: event.timestamp,
});
}
}
finally {
_d = true;
}
const event = _c;
const state = await this.eventHandler(event.type).handle({
aggregate: {
id: this.id,
version: this.version,
},
state: this.state,
}, event);
this._state = state;
this._version = event.aggregate.version;
this._lastEvent = event;
}

@@ -101,16 +92,14 @@ }

}
async _reload(opts) {
if (!(opts === null || opts === void 0 ? void 0 : opts.ignoreSnapshot)) {
const snapshot = await this.eventStore.getLatestSnapshot({
aggregate: {
id: this.id,
version: this.version,
},
});
if (snapshot) {
this._state = snapshot.state;
this._version = snapshot.aggregate.version;
}
async _reload() {
const snapshot = await this.store.findLatestSnapshot({
aggregate: {
id: this.id,
version: this.version,
},
});
if (snapshot) {
this._state = snapshot.state;
this._version = snapshot.aggregate.version;
}
await this.digest(await this.eventStore.listEvents({
await this.digest(await this.store.listEvents({
aggregate: {

@@ -120,10 +109,8 @@ id: this.id,

},
}), {
disableSnapshot: true,
});
}));
}
async reload(opts) {
async reload() {
const release = await this.mutex.acquire();
try {
await this._reload(opts);
await this._reload();
}

@@ -134,12 +121,34 @@ finally {

}
async process(command, opts) {
await (0, exponential_backoff_1.backOff)(async () => {
const release = await this.mutex.acquire();
try {
if (!(opts === null || opts === void 0 ? void 0 : opts.noInitialReload)) {
await this._reload(opts);
async dispatch(params, ctx) {
await this.store.saveEvents(params);
const events = params.events.map((item, index) => (Object.assign(Object.assign({}, item), { timestamp: params.timestamp, aggregate: {
id: this.id,
version: this.version + index + 1,
}, meta: item.meta })));
await this.stream.sendEvents(events, 'main', ctx);
await this.digest(events);
if (this.shoudTakeSnapshot()) {
await this.store.saveSnapshot({
aggregate: {
id: this.id,
version: this.version,
},
state: this.state,
timestamp: params.timestamp,
});
}
}
async process(command, ctx, opts) {
var _a;
const handler = this.commandHandler(command.type);
const release = await this.mutex.acquire();
let firstRun = true;
try {
await (0, exponential_backoff_1.backOff)(async () => {
if (!firstRun || !(opts === null || opts === void 0 ? void 0 : opts.noInitialReload)) {
await this._reload();
}
const commandHandler = this.getCommandHandler(command.type);
firstRun = false;
const timestamp = new Date();
const _events = await commandHandler.handle({
const event = await handler.handle({
aggregate: {

@@ -151,10 +160,3 @@ id: this.id,

}, command, ...command.args);
const events = (_events instanceof Array ? _events : [_events]).map((item, index) => {
var _a;
return (Object.assign(Object.assign({}, item), { id: new event_id_1.EventId(), timestamp, aggregate: {
id: this.id,
version: this.version + index + 1,
}, meta: (_a = item.meta) !== null && _a !== void 0 ? _a : {} }));
});
await this.eventStore.saveEvents({
await this.dispatch({
aggregate: {

@@ -164,23 +166,28 @@ id: this.id,

},
events: events.map(item => ({
id: item.id,
type: item.type,
body: item.body,
meta: item.meta,
})),
events: (event instanceof Array ? event : [event]).map(item => {
var _a;
return ({
id: event_id_1.EventId.generate(),
type: item.type,
body: item.body,
meta: (_a = item.meta) !== null && _a !== void 0 ? _a : {},
});
}),
timestamp,
});
await this.digest(events);
}
finally {
release();
}
}, {
delayFirstAttempt: false,
jitter: 'full',
maxDelay: 2000,
numOfAttempts: (opts === null || opts === void 0 ? void 0 : opts.maxRetries) || 10,
startingDelay: 100,
timeMultiple: 2,
});
}, ctx);
}, {
delayFirstAttempt: false,
jitter: 'full',
maxDelay: 1600,
numOfAttempts: (_a = opts === null || opts === void 0 ? void 0 : opts.maxRetries) !== null && _a !== void 0 ? _a : 10,
startingDelay: 100,
timeMultiple: 2,
retry(err) {
return err instanceof store_adapter_1.AggregateVersionConflictError;
},
});
}
finally {
release();
}
}

@@ -187,0 +194,0 @@ }

/// <reference types="node" />
export declare class EventId {
private _buffer;
private static random;
private static counter;
private static timestamp;
constructor(value?: Buffer);
private timestamp;
get buffer(): Buffer;

@@ -12,3 +11,4 @@ compare(other: EventId): 0 | 1 | -1;

static from(value: Buffer | string): EventId;
static generate(): EventId;
toString(encoding?: 'bs58' | 'hex' | 'base64'): string;
}

@@ -7,3 +7,2 @@ "use strict";

const crypto_1 = require("crypto");
const MACHINE_ID = (0, crypto_1.randomBytes)(5);
class EventId {

@@ -16,16 +15,13 @@ constructor(value) {

this._buffer = Buffer.alloc(12, 0);
if (EventId.counter === 0xffffff) {
while (EventId.timestamp === this.timestamp()) { /* empty */ }
}
EventId.timestamp = this.timestamp();
EventId.counter = (EventId.counter + 1) & 0xffffff;
this._buffer[0] = (EventId.timestamp >> 24) & 0xff;
this._buffer[1] = (EventId.timestamp >> 16) & 0xff;
this._buffer[2] = (EventId.timestamp >> 8) & 0xff;
this._buffer[3] = EventId.timestamp & 0xff;
this._buffer[4] = MACHINE_ID[0];
this._buffer[5] = MACHINE_ID[1];
this._buffer[6] = MACHINE_ID[2];
this._buffer[7] = MACHINE_ID[3];
this._buffer[8] = MACHINE_ID[4];
const timestamp = Math.floor(Date.now() / 1000) & 0xffffffff;
EventId.counter = (EventId.counter + 1) & 0x00ffffff;
this._buffer[0] = (timestamp >> 24) & 0xff;
this._buffer[1] = (timestamp >> 16) & 0xff;
this._buffer[2] = (timestamp >> 8) & 0xff;
this._buffer[3] = timestamp & 0xff;
this._buffer[4] = EventId.random[0];
this._buffer[5] = EventId.random[1];
this._buffer[6] = EventId.random[2];
this._buffer[7] = EventId.random[3];
this._buffer[8] = EventId.random[4];
this._buffer[9] = (EventId.counter >> 16) & 0xff;

@@ -35,5 +31,2 @@ this._buffer[10] = (EventId.counter >> 8) & 0xff;

}
timestamp() {
return Math.floor(Date.now() / 1000) & 0xffffffff;
}
get buffer() {

@@ -54,4 +47,7 @@ return this._buffer;

}
toString(encoding) {
if (!encoding || encoding === 'bs58') {
static generate() {
return new EventId();
}
toString(encoding = 'bs58') {
if (encoding === 'bs58') {
return bs58_1.default.encode(this._buffer);

@@ -62,5 +58,5 @@ }

}
EventId.counter = (0, crypto_1.randomBytes)(4).readUInt32BE() & 0xffffff;
EventId.timestamp = Date.now();
exports.EventId = EventId;
EventId.random = (0, crypto_1.randomBytes)(5);
EventId.counter = (0, crypto_1.randomBytes)(4).readUInt32BE() & 0x00ffffff;
//# sourceMappingURL=event-id.js.map
/// <reference types="node" />
import { EventId } from './event-id';
export type Event<TType extends number = number, TBody extends Record<string, unknown> = Record<string, unknown>, TMeta extends Record<string, unknown> = Record<string, unknown>> = {
export type Meta<T extends Record<string, unknown> = Record<string, unknown>> = {
__ctx?: Buffer;
} & T;
export type Event<TType extends number = number, TBody = Record<string, unknown>, TMeta extends Meta = Meta> = {
id: EventId;

@@ -14,10 +17,10 @@ type: TType;

};
export type EventHandler<TEvent extends Event, TState> = {
export type EventHandler<TEvent extends Event = Event, TState = unknown> = {
type: TEvent['type'];
handle(ctx: {
aggregate: {
id: Buffer;
version: number;
readonly aggregate: {
readonly id: Buffer;
readonly version: number;
};
state: TState;
readonly state: TState;
}, event: TEvent): TState | Promise<TState>;

@@ -30,19 +33,17 @@ };

export type GeneratedEvent<TEvent extends Event> = Pick<TEvent, 'type' | 'body'> & Partial<Pick<TEvent, 'meta'>>;
export type CommandHandler<TCommand extends Command, TEvent extends Event, TState> = {
export type CommandHandler<TCommand extends Command = Command, TEvent extends Event = Event, TState = unknown> = {
type: TCommand['type'];
handle(ctx: {
aggregate: {
id: Buffer;
version: number;
readonly aggregate: {
readonly id: Buffer;
readonly version: number;
};
state: TState;
readonly state: TState;
}, command: TCommand, ...args: TCommand['args']): GeneratedEvent<TEvent> | GeneratedEvent<TEvent>[] | Promise<GeneratedEvent<TEvent>> | Promise<GeneratedEvent<TEvent>[]>;
};
export type Snapshot<TState = unknown> = {
aggregate: {
id: Buffer;
version: number;
};
state: TState;
timestamp: Date;
export type ProjectionEventHandler<TEvent extends Event = Event, TState = unknown> = {
type: TEvent['type'];
handle(ctx: {
readonly state: TState;
}, event: TEvent): void | Promise<void>;
};
{
"name": "@arque/core",
"version": "0.1.0-alpha.16",
"description": "The Event Sourcing library.",
"version": "0.2.0-alpha.0",
"description": "`arque` core library",
"author": "ScaleForge",
"homepage": "https://github.com/ScaleTechnologies/arque#README.md",
"homepage": "https://github.com/ScaleForge/arque#README.md",
"license": "MIT",

@@ -14,6 +14,6 @@ "main": "dist/index.js",

"type": "git",
"url": "git+https://github.com/ScaleTechnologies/arque.git"
"url": "git+https://github.com/ScaleForge/arque.git"
},
"bugs": {
"url": "https://github.com/ScaleTechnologies/arque/issues"
"url": "https://github.com/ScaleForge/arque/issues"
},

@@ -29,3 +29,3 @@ "scripts": {

"exponential-backoff": "3.1.1",
"lru-cache": "9.1.1"
"lru-cache": "10.0.1"
},

@@ -35,3 +35,3 @@ "publishConfig": {

},
"gitHead": "2091af6df277b13c5599bfc01cc064430d1be911"
"gitHead": "ee43fb2edae30510fbd157196919730a8901a4c1"
}

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