jaguar_cqrs 2.1.5

  • Readme
  • Changelog
  • Installing
  • 58

CQRS/ES #

Command Query Responsibility Separation and Event Sourcing library for Dart.

Usage #

Define Domain model #

class Account implements AggregateModel {
  String id;

  String owner;

  double amount;

  Account({this.id, this.owner, this.amount});
}

Define commands #

abstract class ForAccount {
  final String forAggregate = "account";
}

class CreateAccountCmd extends Command with ForAccount {
  final String modelId;

  final String owner;

  CreateAccountCmd({@required this.owner, @required this.modelId});
}

class DepositCmd extends Command with ForAccount {
  final String modelId;

  final double amount;

  DepositCmd({@required this.amount, @required this.modelId});
}

class WithdrawCmd extends Command with ForAccount {
  final String modelId;

  final double amount;

  WithdrawCmd({@required this.amount, @required this.modelId});
}

Define events #

class AccountCreatedEvent implements Event {
  String get forAggregate => "account";

  final String id;

  final String owner;

  AccountCreatedEvent({@required this.id, @required this.owner});

  String toString() => "Created account ($id) for $owner.";
}

class DepositPerformedEvent implements Event {
  String get forAggregate => "account";

  final String id;

  final double amount;

  DepositPerformedEvent({@required this.id, @required this.amount});

  String toString() => "Deposited $amount\$ into account $id.";
}

class WithdrawalPerformedEvent implements Event {
  String get forAggregate => "account";

  final String id;

  final double amount;

  WithdrawalPerformedEvent({@required this.id, @required this.amount});

  String toString() => "Withdrew $amount\$ from account $id.";
}

Define aggregate #

class AccountAggregate extends Aggregate<Account> {
  final String name = 'account';

  @override
  Account initializeModel() => Account();

  @override
  Future<void> apply(Account model, DomainEvent event) async {
    if (event is AccountCreatedEvent) {
      model.id = event.id;
      model.owner = event.owner;
      model.amount = 0.0;
    } else if (event is DepositPerformedEvent) {
      model.amount += event.amount;
    } else if (event is WithdrawalPerformedEvent) {
      model.amount -= event.amount;
    } else {
      throw Exception("Unknown event!");
    }
  }

  @override
  Future<void> handleCommand(
      Command cmd, Account model, CommandOutput out) async {
    if (cmd is CreateAccountCmd) {
      if (model.id != null) {
        out.setError("Model with id ${cmd.modelId} already exists!");
        return;
      }
      out.addEvent(AccountCreatedEvent(id: cmd.modelId, owner: cmd.owner));
    } else if (cmd is DepositCmd) {
      out.addEvent(DepositPerformedEvent(id: cmd.modelId, amount: cmd.amount));
    } else if (cmd is WithdrawCmd) {
      if (model.amount < cmd.amount) {
        out.setError("Not enough balance!");
        return;
      }
      out.addEvent(
          WithdrawalPerformedEvent(id: cmd.modelId, amount: cmd.amount));
      return;
    } else {
      throw UnsupportedError(cmd.runtimeType.toString());
    }
  }
}

Glue them all together #

main() async {
  final cqrs = Cqrs()
    ..registerAggregate(AccountAggregate())
    ..registerRepository(InMemoryRepository<Account>(forAggregate: "account"));

  cqrs.events.listen(print);

  await cqrs.submitCommand(CreateAccountCmd(owner: "Teja", modelId: "1"));
  await cqrs.submitCommand(DepositCmd(modelId: "1", amount: 200.0));
  await cqrs.submitCommand(DepositCmd(modelId: "1", amount: 200.0));
  await cqrs.submitCommand(WithdrawCmd(modelId: "1", amount: 300.0));
  await cqrs.submitCommand(DepositCmd(modelId: "1", amount: 400.0));
}

Outputs.

Created account (1) for Teja. Deposited 200.0$ into account 1. Deposited 200.0$ into account 1. Withdrew 300.0$ from account 1. Deposited 400.0$ into account 1.

2.1.5 #

  • Command results
  • Event stream

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  jaguar_cqrs: ^2.1.5

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:jaguar_cqrs/jaguar_cqrs.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
18
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
98
Overall:
Weighted score of the above. [more]
58
Learn more about scoring.

We analyzed this package on Oct 11, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.5.1
  • pana: 0.12.21

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:jaguar_cqrs/jaguar_cqrs.dart.

Health suggestions

Fix lib/application.dart. (-0.50 points)

Analysis of lib/application.dart reported 1 hint:

line 93 col 5: Future results in async function bodies must be awaited or marked unawaited using package:pedantic.

Maintenance suggestions

Package is getting outdated. (-2.19 points)

The package was last published 53 weeks ago.

Maintain an example.

None of the files in the package's example/ directory matches known example patterns.

Common filename patterns include main.dart, example.dart, and jaguar_cqrs.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
meta ^1.1.6 1.1.7
Dev dependencies
test ^1.3.0