Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

demeine

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

demeine - npm Package Compare versions

Comparing version 0.3.13 to 1.0.0

lib/aggregate/Aggregate.d.ts

19

lib/index.js

@@ -1,2 +0,17 @@

module.exports.Repository = require('./repository');
module.exports.Aggregate = require('./aggregate');
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
_exportStar(require("./aggregate"), exports);
_exportStar(require("./repository"), exports);
function _exportStar(from, to) {
Object.keys(from).forEach(function(k) {
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) Object.defineProperty(to, k, {
enumerable: true,
get: function() {
return from[k];
}
});
});
return from;
}

68

package.json
{
"name": "demeine",
"version": "0.3.13",
"version": "1.0.0",
"description": "DDDD - Distributed Domain Driven Design",
"main": "index.js",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"test": "mocha test --recursive",
"test.watch": "mocha test --color --watch --recursive",
"coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --recursive test -u exports -R spec",
"coverage-start": "istanbul cover node_modules/mocha/bin/_mocha test --recursive -- -u exports -R spec && start coverage/lcov-report/index.html",
"jshint": "jshint ./lib",
"jscs": "jscs -p google ./lib ./test"
"build": "rimraf lib && concurrently \"npm run build:src\" \"npm run build:types\"",
"build:watch": "rimraf lib && concurrently \"npm run build:src:watch\" \"npm run build:types:watch\"",
"build:src": "swc src --out-dir lib",
"build:src:watch": "npm run build:src -- --watch",
"build:types": "tsc",
"build:types:watch": "npm run build:types -- --watch",
"test": "jest --colors",
"test:watch": "npm test -- --watch",
"test:coverage": "npm test -- --collectCoverage",
"test:coverage:start": "npm run test:coverage && start coverage/lcov-report/index.html",
"lint": "eslint src",
"lint:fix": "eslint --fix src",
"format:check": "prettier --check src",
"format:fix": "prettier --write src",
"prepare": "npm test && npm run build"
},

@@ -27,12 +37,19 @@ "repository": {

"devDependencies": {
"babel-core": "^6.7.7",
"babel-preset-es2015": "^6.6.0",
"istanbul": "^0.3.2",
"jscs": "^1.11.3",
"jshint": "^2.5.10",
"mocha": "^2.5.3",
"prettier": "^2.1.2",
"@swc/cli": "^0.1.57",
"@swc/core": "^1.2.237",
"@swc/jest": "^0.2.22",
"@types/bluebird": "^3.5.36",
"@types/jest": "^28.1.7",
"@types/node": "^18.7.6",
"@types/uuid": "^8.3.4",
"concurrently": "^7.3.0",
"eslint": "^8.22.0",
"eslint-config-surikat": "^4.0.0",
"jest": "^27.4.4",
"prettier": "^2.7.1",
"prettier-config-surikaterna": "^1.0.1",
"should": "^4.1.0",
"slf-debug": "^0.2.0"
"regenerator-runtime": "^0.13.9",
"rimraf": "^3.0.2",
"slf-debug": "^0.2.0",
"typescript": "^4.7.4"
},

@@ -44,16 +61,7 @@ "bugs": {

"dependencies": {
"bluebird": "^2.9.12",
"slf": "^1.x",
"uuid": "^3.0.1"
},
"babel": {
"presets": [
"es2015"
]
},
"browserify": {
"presets": [
"es2015"
]
"bluebird": "^3.7.2",
"p-queue": "^6.6.2",
"slf": "^2.0.2",
"uuid": "^8.3.2"
}
}

@@ -1,2 +0,273 @@

# demeine
DDDD - Distributed Domain Drive Design
demeine
=======
[Demeine](https://github.com/surikaterna/demeine) is a library supporting DDDD (Distributed Domain Drive Design).
* [Purpose](#purpose)
* [Installation](#installation)
* [Usage](#usage)
* [Components](#components)
* [Aggregate](#aggregate)
* [clearUncommittedEvents](#clearuncommittedevents)
* [delete](#delete)
* [getUncommittedEvents](#getuncommittedevents)
* [getUncommittedEventsAsync](#getuncommittedeventsasync)
* [getVersion](#getversion)
* [Repository](#repository)
* [checkConcurrencyStrategy](#checkconcurrencystrategy)
* [findById](#findbyid)
* [findByQueryStreamWithSnapshot](#findbyquerystreamwithsnapshot)
* [findBySnapshot](#findbysnapshot)
* [findEventsById](#findeventsbyid)
* [save](#save)
## Purpose
Provide the base building blocks for implementing DDD in a distributed environment. This repository contains an
implementation of a _repository_, as well as a base _aggregate_ that domain specific aggregates can extend. The flow of
action → command → event → state update is supported.
## Installation
```shell
npm install demeine
```
## Usage
This example uses [TapeWORM](https://github.com/surikaterna/tapeworm) with its default in memory partition.
```ts
// User.ts
export const USER_AGGREGATE_TYPE = 'user';
export interface UserState {
id: string;
name: string;
}
export class User extends Aggregate<UserState> {
constructor(commandSink?: CommandSink, eventHandler?: EventHandler, commandHandler?: CommandHandler) {
super(commandSink, eventHandler, commandHandler);
this._state = {
id: this.id,
name: ''
};
}
register(id: string, name: string) {
this.id = id;
return this._sink({
type: 'user.register.command',
payload: { id, name },
aggregateId: this.id
});
}
processChangeName(command: Command<UserState>) {
return this._apply(
{
type: 'location.name_changed.event',
payload: command.payload,
aggregateId:
this.id
},
true
);
}
applyNameChanged(event: Event<UserState>) {
this._state.name = event.payload.name;
}
}
// userFactory.ts
import { User, UserState, USER_AGGREGATE_TYPE } from './User';
export function userFactory(id: string) {
const user = new User();
user.id = id;
user._state = { id, name: '' };
user.type = USER_AGGREGATE_TYPE;
return user;
}
// index.ts
import { Aggregate, Repository } from 'demeine';
import TapeWorm from 'tapeworm';
import { User, USER_AGGREGATE_TYPE } from './User';
import { userFactory } from './userFactory';
const tapeWorm = new TapeWorm();
const partition = await tapeWorm.openPartition('my_partition');
const userRepository = new Repository<User>(partition, USER_AGGREGATE_TYPE, userFactory);
// Not found, name: ''
const user = await userRepository.findById('123');
await user.register('123', 'Jeff');
await userRepository.save(user);
// Exists since save(user), name: 'Jeff'
const existingUser = await userRepository.findById('123');
```
## Components
### Aggregate
Base class for aggregate classes representing domain concepts.
#### clearUncommittedEvents
Remove the events created through calling the aggregate methods.
Is used in the [`save`](#save) method on the Repository in order to remove local events after they've been committed.
```typescript
const user = await userRepository.findById('123');
// Adds `user.registered.event` to uncommitted events
await user.register('123', 'Jeff');
// Removes the `registered` event
await user.clearUncommittedEvents();
await userRepository.save(user);
```
#### delete
Creates a `$stream.deleted.event` for the aggregate, which the persistence partition should handle by removing the
aggregate data.
```typescript
const user = await userRepository.findById('123');
await user.delete();
await userRepository.save(user);
// Should not exist anymore
const nonExistingUser = await userRepository.findById('123');
```
#### getUncommittedEvents
Retrieves the list of events created by calling aggregate methods. Prefer to use the async version, as this will
throw if there are unprocessed commands.
```typescript
const user = await userRepository.findById('123');
await user.register('123', 'Jeff');
await user.registerEmail('jeff@21jumpstreet.us');
// [ Event { type: 'user.registered.event' }, Event { type: 'user.email.registered.event' }]
const events = user.getUncommittedEvents();
```
#### getUncommittedEventsAsync
Retrieves the uncommitted events as soon as the processing queue is empty.
```typescript
const user = await userRepository.findById('123');
await user.register('123', 'Jeff');
await user.registerEmail('jeff@21jumpstreet.us');
// [ Event { type: 'user.registered.event' }, Event { type: 'user.email.registered.event' }]
const events = await user.getUncommittedEventsAsync();
```
#### getVersion
Retrieves the version of the aggregate, including increments for the processed uncommitted events.
```typescript
const user = await userRepository.findById('123');
// -1, non existing
const initialVersion = user.getVersion();
await user.register('123', 'Jeff');
await user.registerEmail('jeff@21jumpstreet.us');
// 2, set to 0 for initial + 2 increments for the events
const newVersion = user.getVersion();
```
### Repository
You will need to provide a Partition to the Repository.
#### checkConcurrencyStrategy
Checks the concurrency strategy provided in the Repository constructor. Returns a Promise with a boolean stating whether
it should throw an error or not. Defaults to resolving `false` if no concurrency strategy was provided.
Is used in the [`save`](#save) method on the Repository in order to throw a concurrency error when there's a version
mismatch.
```typescript
const user = await userRepository.findById('123');
const initialVersion = user.getVersion();
await user.register('123', 'Jeff');
await user.registerEmail('jeff@21jumpstreet.us');
// 2, set to 0 for initial + 2 increments for the events
const newVersion = user.getVersion();
```
#### findById
Will look up an Aggregate in the Partition provided to the Repository by the aggregate's ID.
```typescript
const user = await userRepository.findById('123');
```
#### findByQueryStreamWithSnapshot
Will create a rehydrated aggregate by looking up the events for a stream, and processing them. Returns the rehydrated
aggregate.
Requires the persistence partition to implement `queryStreamWithSnapshot`.
```typescript
const user = await userRepository.findById('123');
```
#### findBySnapshot
Will look up a snapshot for the aggregate and Will create a rehydrated aggregate by looking up the events for a stream, and processing them. Returns the rehydrated
aggregate.
Requires the persistence partition to implement `loadSnapshot` & `queryStream`.
```typescript
const user = await userRepository.findById('123');
```
#### findEventsById
Retrieves the committed (processed) events for the aggregate stream by the aggregate's ID.
```typescript
// [{ type: 'user.registered.event' }. { type: 'user.email.registered.event' }]
const events = await userRepository.findEventsById('123');
```
#### save
Persists the aggregate including executed commands to the persistence partition.
```typescript
// { id: '123', contact: [] }
const user = await userRepository.findById('123');
await user.registerEmail('jeff@21jumpstreet.us');
await userRepository.save(user);
// { id: '123', contact: [{ value: 'jeff@21jumpstreet.us', type: 'email' }] }
const updatedUser = await userRepository.findById('123');
```
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