{"id":17956146,"url":"https://github.com/sleipnir/cloudstate-dart-support","last_synced_at":"2025-08-16T07:32:09.243Z","repository":{"id":61972863,"uuid":"254279789","full_name":"sleipnir/cloudstate-dart-support","owner":"sleipnir","description":"Cloudstate Dart Language Support (This repository has been moved to https://github.com/cloudstateio/dart-support)","archived":false,"fork":false,"pushed_at":"2020-04-17T20:58:51.000Z","size":1307,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-29T11:12:52.431Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://cloudstate.io/","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sleipnir.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-09T05:30:44.000Z","updated_at":"2024-08-20T18:38:23.000Z","dependencies_parsed_at":"2022-10-24T13:30:27.107Z","dependency_job_id":null,"html_url":"https://github.com/sleipnir/cloudstate-dart-support","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sleipnir%2Fcloudstate-dart-support","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sleipnir%2Fcloudstate-dart-support/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sleipnir%2Fcloudstate-dart-support/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sleipnir%2Fcloudstate-dart-support/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sleipnir","download_url":"https://codeload.github.com/sleipnir/cloudstate-dart-support/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230020464,"owners_count":18160735,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-29T10:35:02.984Z","updated_at":"2024-12-16T20:22:56.320Z","avatar_url":"https://github.com/sleipnir.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"Cloudstate Dart library\n\n## Usage\n\nA simple usage example:\n\nCreate new Dart project.\n\nAdd dependencies in pubspec.yml:\n\n```yaml\nname: shopping_cart\nversion: 0.5.1\ndescription: A Cloudstate Dart ShoppingCart Example.\nauthor: Adriano Santos \u003csleipnir@bsd.com.br\u003e\n\nenvironment:\n  sdk: '\u003e=2.7.0 \u003c3.0.0'\n\ndependencies:\n  cloudstate: ^0.5.1\n\ndev_dependencies:\n  pedantic: ^1.8.0\n  build_runner: ^1.5.2\n  build_test: ^0.10.8\n  build_web_compilers: ^2.1.1\n  mockito: ^4.1.0\n  test: ^1.6.4\n\n```\n\nWrite Protofiles:\n```proto\n// File =\u003e protos/shoppingcart.proto\n\n// This is the public API offered by the shopping cart entity.\nsyntax = \"proto3\";\n\npackage com.example.shoppingcart;\n\nimport \"google/protobuf/empty.proto\";\nimport \"cloudstate/entity_key.proto\";\nimport \"cloudstate/eventing.proto\";\nimport \"google/api/annotations.proto\";\nimport \"google/api/http.proto\";\nimport \"google/api/httpbody.proto\";\n\nmessage AddLineItem {\n    string user_id = 1 [(.cloudstate.entity_key) = true];\n    string product_id = 2;\n    string name = 3;\n    int32 quantity = 4;\n}\n\nmessage RemoveLineItem {\n    string user_id = 1 [(.cloudstate.entity_key) = true];\n    string product_id = 2;\n}\n\nmessage GetShoppingCart {\n    string user_id = 1 [(.cloudstate.entity_key) = true];\n}\n\nmessage LineItem {\n    string product_id = 1;\n    string name = 2;\n    int32 quantity = 3;\n}\n\nmessage Cart {\n    repeated LineItem items = 1;\n}\n\nservice ShoppingCart {\n    rpc AddItem(AddLineItem) returns (google.protobuf.Empty) {\n        option (google.api.http) = {\n            post: \"/cart/{user_id}/items/add\",\n            body: \"*\",\n        };\n        option (.cloudstate.eventing).in = \"items\";\n    }\n\n    rpc RemoveItem(RemoveLineItem) returns (google.protobuf.Empty) {\n        option (google.api.http).post = \"/cart/{user_id}/items/{product_id}/remove\";\n    }\n\n    rpc GetCart(GetShoppingCart) returns (Cart) {\n        option (google.api.http) = {\n          get: \"/carts/{user_id}\",\n          additional_bindings: {\n            get: \"/carts/{user_id}/items\",\n            response_body: \"items\"\n          }\n        };\n    }\n}\n\n// File =\u003e protos/persistence/domain.proto\n// These are the messages that get persisted - the events, plus the current state (Cart) for snapshots.\nsyntax = \"proto3\";\n\npackage com.example.shoppingcart.persistence;\n\nmessage LineItem {\n    string productId = 1;\n    string name = 2;\n    int32 quantity = 3;\n}\n\n// The item added event.\nmessage ItemAdded {\n    LineItem item = 1;\n}\n\n// The item removed event.\nmessage ItemRemoved {\n    string productId = 1;\n}\n\n// The shopping cart state.\nmessage Cart {\n    repeated LineItem items = 1;\n}\n\n```\n\nCompiling your proto files:\n```shell script\n[sleipnir@sleipnir example]# protoc --include_imports \\\n     --descriptor_set_out=user-function.desc \\\n     -I protos/persistence/domain.proto protos/shoppingcart.proto \\\n     --dart_out=grpc:lib/src/generated\n````\n\nWrite file =\u003e lib/eventsourced_entity.dart:\n```dart\n\nimport 'package:cloudstate/cloudstate.dart';\n\nimport 'generated/google/protobuf/empty.pb.dart';\nimport 'generated/persistence/domain.pb.dart' as Domain;\nimport 'generated/shoppingcart.pb.dart' as Shoppingcart;\n\n@EventSourcedEntity()\nclass ShoppingCartEntity {\n  final Map\u003cString, Shoppingcart.LineItem\u003e _cart = {};\n  \n  String entityId;\n  Context context;\n  \n  ShoppingCartEntity.create(@EntityId() String entityId, Context context) {\n    this.entityId = entityId;\n    this.context = context;\n  }\n\n  @Snapshot()\n  Domain.Cart snapshot() {\n    return Domain.Cart.create()\n        ..items.addAll(\n            _cart.values.map((e) =\u003e convertShoppingItem(e))\n            .toList());\n  }\n\n  @SnapshotHandler()\n  void handleSnapshot(Domain.Cart cart) {\n    _cart.clear();\n    for (var item in cart.items) {\n      _cart[item.productId] =  convert(item);\n    }\n\n  }\n\n  @EventHandler()\n  void itemAdded(Domain.ItemAdded itemAdded) {\n    var item = _cart[itemAdded.item.productId];\n    if (item == null) {\n      item = convert(itemAdded.item);\n    } else {\n      item =\n          item..quantity = item.quantity + itemAdded.item.quantity;\n    }\n    _cart[item.productId] = item;\n  }\n\n  @EventHandler()\n  void itemRemoved(Domain.ItemRemoved itemRemoved) {\n    _cart.remove(itemRemoved.productId);\n  }\n\n  @EventSourcedCommandHandler()\n  Shoppingcart.Cart getCart() {\n    return Shoppingcart.Cart.create()\n        ..items.addAll(_cart.values);\n  }\n\n  @EventSourcedCommandHandler()\n  Empty addItem(Shoppingcart.AddLineItem item, CommandContext ctx) {\n    if (item.quantity \u003c= 0) {\n      ctx.fail('Cannot add negative quantity of to item ${item.productId}');\n    }\n\n    var lineIem = Domain.LineItem.create()\n      ..productId = item.productId\n      ..name = item.name\n      ..quantity = item.quantity;\n\n    ctx.emit(Domain.ItemAdded.create()..item = lineIem);\n    return Empty.getDefault();\n  }\n\n  @EventSourcedCommandHandler()\n  Empty removeItem(Shoppingcart.RemoveLineItem item, CommandContext ctx) {\n    if (!_cart.containsKey(item.productId)) {\n      ctx.fail('Cannot remove item ${item.productId} because it is not in the cart.');\n    }\n    ctx.emit(Domain.ItemRemoved.create()..productId = item.productId);\n    return Empty.getDefault();\n  }\n\n  Shoppingcart.LineItem convert(Domain.LineItem item) {\n    return Shoppingcart.LineItem.create()\n        ..productId = item.productId\n        ..name = item.name\n        ..quantity = item.quantity;\n  }\n\n  Domain.LineItem convertShoppingItem(Shoppingcart.LineItem item) {\n    return Domain.LineItem.create()\n        ..productId = item.productId\n        ..name = item.name\n        ..quantity = item.quantity;\n  }\n\n}\n```\n\n***Note: You are not required to create a constructor, but it is useful if you want to access the entity id \nor the EventSourcedCreatedContext. In this case, the class is only allowed to have only one constructor, which can be a \nnormal constructor or a Named Constructor. Don't forget to annotate the entity parameter with the @EntityId annotation***\n\n\nWrite file =\u003e bin/shopping_cart.dart:\n\n```dart\n\nimport 'package:cloudstate/cloudstate.dart';\nimport 'package:shopping_cart/src/eventsourced_entity.dart';\n\nvoid main() {\n  Cloudstate()\n    ..port = 8080\n    ..address = 'localhost'\n    ..registerEventSourcedEntity('com.example.shoppingcart.ShoppingCart', ShoppingCartEntity)\n    ..start();\n}\n```\n\nBuild and run on docker:\n\n```\ndocker build -t sleipnir/cloudstate-dart-shoppingcart:0.5.1\n\ndocker run --rm -p 8080:8080 -p 8181:8181 --name dart-shoppingcartsleipnir/cloudstate-dart-shoppingcart:0.5.1\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsleipnir%2Fcloudstate-dart-support","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsleipnir%2Fcloudstate-dart-support","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsleipnir%2Fcloudstate-dart-support/lists"}