@reventlessdev/online-shop-aggregates-ordering 3.0.0-alpha.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +846 -0
- package/LICENSE +202 -0
- package/__mocks__/emptyModule.js +1 -0
- package/lib/bs/.compiler.log +2 -0
- package/lib/bs/OrderingPlugin.cmi +0 -0
- package/lib/bs/OrderingPlugin.cmj +0 -0
- package/lib/bs/OrderingPlugin.cmt +0 -0
- package/lib/bs/OrderingPlugin.mlmap +31 -0
- package/lib/bs/build.ninja +0 -0
- package/lib/bs/compiler-info.json +8 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct.ast +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct.res +18 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct.res.mjs +50 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct_Behavior-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct_Behavior-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct_Behavior-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct_Behavior.ast +0 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct_Behavior.res +27 -0
- package/lib/bs/src/CatalogProduct/Aggregate/CatalogProduct_Behavior.res.mjs +87 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts.ast +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts.res +13 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts.res.mjs +53 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts_Projections-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts_Projections-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts_Projections-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts_Projections.ast +0 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts_Projections.res +20 -0
- package/lib/bs/src/CatalogProduct/ReadModel/AvailableProducts_Projections.res.mjs +65 -0
- package/lib/bs/src/Customer/Aggregate/Customer-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer.ast +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer.res +24 -0
- package/lib/bs/src/Customer/Aggregate/Customer.res.mjs +64 -0
- package/lib/bs/src/Customer/Aggregate/Customer_Behavior-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer_Behavior-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer_Behavior-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer_Behavior.ast +0 -0
- package/lib/bs/src/Customer/Aggregate/Customer_Behavior.res +41 -0
- package/lib/bs/src/Customer/Aggregate/Customer_Behavior.res.mjs +143 -0
- package/lib/bs/src/Customer/ReadModel/Customers-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers.ast +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers.res +12 -0
- package/lib/bs/src/Customer/ReadModel/Customers.res.mjs +36 -0
- package/lib/bs/src/Customer/ReadModel/Customers_Projections-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers_Projections-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers_Projections-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers_Projections.ast +0 -0
- package/lib/bs/src/Customer/ReadModel/Customers_Projections.res +21 -0
- package/lib/bs/src/Customer/ReadModel/Customers_Projections.res.mjs +91 -0
- package/lib/bs/src/Extension/Products_Extension-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Extension/Products_Extension-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Extension/Products_Extension-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Extension/Products_Extension.ast +0 -0
- package/lib/bs/src/Extension/Products_Extension.res +23 -0
- package/lib/bs/src/Extension/Products_Extension.res.mjs +43 -0
- package/lib/bs/src/ExtensionPoint/Orders_ExtensionPointMapping-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/ExtensionPoint/Orders_ExtensionPointMapping-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/ExtensionPoint/Orders_ExtensionPointMapping-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/ExtensionPoint/Orders_ExtensionPointMapping.ast +0 -0
- package/lib/bs/src/ExtensionPoint/Orders_ExtensionPointMapping.res +28 -0
- package/lib/bs/src/ExtensionPoint/Orders_ExtensionPointMapping.res.mjs +59 -0
- package/lib/bs/src/Order/Aggregate/Order-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Order/Aggregate/Order-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Order/Aggregate/Order-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Order/Aggregate/Order.ast +0 -0
- package/lib/bs/src/Order/Aggregate/Order.res +27 -0
- package/lib/bs/src/Order/Aggregate/Order.res.mjs +81 -0
- package/lib/bs/src/Order/Aggregate/Order_Behavior-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Behavior-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Behavior-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Behavior.ast +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Behavior.res +52 -0
- package/lib/bs/src/Order/Aggregate/Order_Behavior.res.mjs +193 -0
- package/lib/bs/src/Order/Aggregate/Order_Mappings-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Mappings-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Mappings-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Mappings.ast +0 -0
- package/lib/bs/src/Order/Aggregate/Order_Mappings.res +15 -0
- package/lib/bs/src/Order/Aggregate/Order_Mappings.res.mjs +55 -0
- package/lib/bs/src/Order/ReadModel/Orders-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Order/ReadModel/Orders-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Order/ReadModel/Orders-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Order/ReadModel/Orders.ast +0 -0
- package/lib/bs/src/Order/ReadModel/Orders.res +19 -0
- package/lib/bs/src/Order/ReadModel/Orders.res.mjs +62 -0
- package/lib/bs/src/Order/ReadModel/Orders_Projections-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Order/ReadModel/Orders_Projections-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Order/ReadModel/Orders_Projections-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Order/ReadModel/Orders_Projections.ast +0 -0
- package/lib/bs/src/Order/ReadModel/Orders_Projections.res +31 -0
- package/lib/bs/src/Order/ReadModel/Orders_Projections.res.mjs +89 -0
- package/lib/bs/src/Order/SideEffect/Order_EmailNotification-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Order/SideEffect/Order_EmailNotification-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Order/SideEffect/Order_EmailNotification-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Order/SideEffect/Order_EmailNotification.ast +0 -0
- package/lib/bs/src/Order/SideEffect/Order_EmailNotification.res +18 -0
- package/lib/bs/src/Order/SideEffect/Order_EmailNotification.res.mjs +34 -0
- package/lib/bs/src/Plugin-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Plugin-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Plugin-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Plugin.ast +0 -0
- package/lib/bs/src/Plugin.res +65 -0
- package/lib/bs/src/Plugin.res.mjs +223 -0
- package/lib/bs/src/Service/EmailService-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Service/EmailService-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Service/EmailService-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Service/EmailService.ast +0 -0
- package/lib/bs/src/Service/EmailService.res +22 -0
- package/lib/bs/src/Service/EmailService.res.mjs +23 -0
- package/lib/bs/src/Task/OrderNotifications-OrderingPlugin.cmi +0 -0
- package/lib/bs/src/Task/OrderNotifications-OrderingPlugin.cmj +0 -0
- package/lib/bs/src/Task/OrderNotifications-OrderingPlugin.cmt +0 -0
- package/lib/bs/src/Task/OrderNotifications.ast +0 -0
- package/lib/bs/src/Task/OrderNotifications.res +8 -0
- package/lib/bs/src/Task/OrderNotifications.res.mjs +29 -0
- package/lib/bs/tests/CatalogProduct/Aggregate/CatalogProduct_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/CatalogProduct/Aggregate/CatalogProduct_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/CatalogProduct/Aggregate/CatalogProduct_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/CatalogProduct/Aggregate/CatalogProduct_GWT.ast +0 -0
- package/lib/bs/tests/CatalogProduct/Aggregate/CatalogProduct_GWT.res +27 -0
- package/lib/bs/tests/CatalogProduct/Aggregate/CatalogProduct_GWT.res.mjs +102 -0
- package/lib/bs/tests/CatalogProduct/ReadModel/AvailableProducts_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/CatalogProduct/ReadModel/AvailableProducts_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/CatalogProduct/ReadModel/AvailableProducts_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/CatalogProduct/ReadModel/AvailableProducts_GWT.ast +0 -0
- package/lib/bs/tests/CatalogProduct/ReadModel/AvailableProducts_GWT.res +15 -0
- package/lib/bs/tests/CatalogProduct/ReadModel/AvailableProducts_GWT.res.mjs +83 -0
- package/lib/bs/tests/Customer/Aggregate/Customer_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Customer/Aggregate/Customer_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Customer/Aggregate/Customer_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Customer/Aggregate/Customer_GWT.ast +0 -0
- package/lib/bs/tests/Customer/Aggregate/Customer_GWT.res +90 -0
- package/lib/bs/tests/Customer/Aggregate/Customer_GWT.res.mjs +170 -0
- package/lib/bs/tests/Customer/ReadModel/Customers_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Customer/ReadModel/Customers_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Customer/ReadModel/Customers_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Customer/ReadModel/Customers_GWT.ast +0 -0
- package/lib/bs/tests/Customer/ReadModel/Customers_GWT.res +27 -0
- package/lib/bs/tests/Customer/ReadModel/Customers_GWT.res.mjs +106 -0
- package/lib/bs/tests/Extension/Products_Extension_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Extension/Products_Extension_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Extension/Products_Extension_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Extension/Products_Extension_GWT.ast +0 -0
- package/lib/bs/tests/Extension/Products_Extension_GWT.res +21 -0
- package/lib/bs/tests/Extension/Products_Extension_GWT.res.mjs +106 -0
- package/lib/bs/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT.ast +0 -0
- package/lib/bs/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT.res +33 -0
- package/lib/bs/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT.res.mjs +143 -0
- package/lib/bs/tests/Order/Aggregate/OrderMappings_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Order/Aggregate/OrderMappings_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Order/Aggregate/OrderMappings_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Order/Aggregate/OrderMappings_GWT.ast +0 -0
- package/lib/bs/tests/Order/Aggregate/OrderMappings_GWT.res +52 -0
- package/lib/bs/tests/Order/Aggregate/OrderMappings_GWT.res.mjs +162 -0
- package/lib/bs/tests/Order/Aggregate/Order_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Order/Aggregate/Order_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Order/Aggregate/Order_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Order/Aggregate/Order_GWT.ast +0 -0
- package/lib/bs/tests/Order/Aggregate/Order_GWT.res +121 -0
- package/lib/bs/tests/Order/Aggregate/Order_GWT.res.mjs +231 -0
- package/lib/bs/tests/Order/ReadModel/Orders_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Order/ReadModel/Orders_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Order/ReadModel/Orders_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Order/ReadModel/Orders_GWT.ast +0 -0
- package/lib/bs/tests/Order/ReadModel/Orders_GWT.res +46 -0
- package/lib/bs/tests/Order/ReadModel/Orders_GWT.res.mjs +118 -0
- package/lib/bs/tests/Order/SideEffect/EmailService_Mock-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Order/SideEffect/EmailService_Mock-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Order/SideEffect/EmailService_Mock-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Order/SideEffect/EmailService_Mock.ast +0 -0
- package/lib/bs/tests/Order/SideEffect/EmailService_Mock.res +31 -0
- package/lib/bs/tests/Order/SideEffect/EmailService_Mock.res.mjs +56 -0
- package/lib/bs/tests/Order/SideEffect/Order_EmailNotification_GWT-OrderingPlugin.cmi +0 -0
- package/lib/bs/tests/Order/SideEffect/Order_EmailNotification_GWT-OrderingPlugin.cmj +0 -0
- package/lib/bs/tests/Order/SideEffect/Order_EmailNotification_GWT-OrderingPlugin.cmt +0 -0
- package/lib/bs/tests/Order/SideEffect/Order_EmailNotification_GWT.ast +0 -0
- package/lib/bs/tests/Order/SideEffect/Order_EmailNotification_GWT.res +37 -0
- package/lib/bs/tests/Order/SideEffect/Order_EmailNotification_GWT.res.mjs +76 -0
- package/lib/ocaml/.compiler.log +2 -0
- package/lib/ocaml/AvailableProducts-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/AvailableProducts-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/AvailableProducts-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/AvailableProducts.ast +0 -0
- package/lib/ocaml/AvailableProducts.res +13 -0
- package/lib/ocaml/AvailableProducts_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/AvailableProducts_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/AvailableProducts_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/AvailableProducts_GWT.ast +0 -0
- package/lib/ocaml/AvailableProducts_GWT.res +15 -0
- package/lib/ocaml/AvailableProducts_Projections-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/AvailableProducts_Projections-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/AvailableProducts_Projections-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/AvailableProducts_Projections.ast +0 -0
- package/lib/ocaml/AvailableProducts_Projections.res +20 -0
- package/lib/ocaml/CatalogProduct-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/CatalogProduct-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/CatalogProduct-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/CatalogProduct.ast +0 -0
- package/lib/ocaml/CatalogProduct.res +18 -0
- package/lib/ocaml/CatalogProduct_Behavior-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/CatalogProduct_Behavior-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/CatalogProduct_Behavior-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/CatalogProduct_Behavior.ast +0 -0
- package/lib/ocaml/CatalogProduct_Behavior.res +27 -0
- package/lib/ocaml/CatalogProduct_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/CatalogProduct_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/CatalogProduct_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/CatalogProduct_GWT.ast +0 -0
- package/lib/ocaml/CatalogProduct_GWT.res +27 -0
- package/lib/ocaml/Customer-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Customer-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Customer-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Customer.ast +0 -0
- package/lib/ocaml/Customer.res +24 -0
- package/lib/ocaml/Customer_Behavior-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Customer_Behavior-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Customer_Behavior-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Customer_Behavior.ast +0 -0
- package/lib/ocaml/Customer_Behavior.res +41 -0
- package/lib/ocaml/Customer_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Customer_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Customer_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Customer_GWT.ast +0 -0
- package/lib/ocaml/Customer_GWT.res +90 -0
- package/lib/ocaml/Customers-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Customers-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Customers-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Customers.ast +0 -0
- package/lib/ocaml/Customers.res +12 -0
- package/lib/ocaml/Customers_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Customers_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Customers_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Customers_GWT.ast +0 -0
- package/lib/ocaml/Customers_GWT.res +27 -0
- package/lib/ocaml/Customers_Projections-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Customers_Projections-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Customers_Projections-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Customers_Projections.ast +0 -0
- package/lib/ocaml/Customers_Projections.res +21 -0
- package/lib/ocaml/EmailService-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/EmailService-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/EmailService-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/EmailService.ast +0 -0
- package/lib/ocaml/EmailService.res +22 -0
- package/lib/ocaml/EmailService_Mock-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/EmailService_Mock-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/EmailService_Mock-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/EmailService_Mock.ast +0 -0
- package/lib/ocaml/EmailService_Mock.res +31 -0
- package/lib/ocaml/Order-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Order-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Order-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Order.ast +0 -0
- package/lib/ocaml/Order.res +27 -0
- package/lib/ocaml/OrderMappings_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/OrderMappings_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/OrderMappings_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/OrderMappings_GWT.ast +0 -0
- package/lib/ocaml/OrderMappings_GWT.res +52 -0
- package/lib/ocaml/OrderNotifications-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/OrderNotifications-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/OrderNotifications-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/OrderNotifications.ast +0 -0
- package/lib/ocaml/OrderNotifications.res +8 -0
- package/lib/ocaml/Order_Behavior-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Order_Behavior-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Order_Behavior-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Order_Behavior.ast +0 -0
- package/lib/ocaml/Order_Behavior.res +52 -0
- package/lib/ocaml/Order_EmailNotification-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Order_EmailNotification-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Order_EmailNotification-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Order_EmailNotification.ast +0 -0
- package/lib/ocaml/Order_EmailNotification.res +18 -0
- package/lib/ocaml/Order_EmailNotification_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Order_EmailNotification_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Order_EmailNotification_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Order_EmailNotification_GWT.ast +0 -0
- package/lib/ocaml/Order_EmailNotification_GWT.res +37 -0
- package/lib/ocaml/Order_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Order_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Order_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Order_GWT.ast +0 -0
- package/lib/ocaml/Order_GWT.res +121 -0
- package/lib/ocaml/Order_Mappings-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Order_Mappings-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Order_Mappings-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Order_Mappings.ast +0 -0
- package/lib/ocaml/Order_Mappings.res +15 -0
- package/lib/ocaml/OrderingPlugin.cmi +0 -0
- package/lib/ocaml/OrderingPlugin.cmj +0 -0
- package/lib/ocaml/OrderingPlugin.cmt +0 -0
- package/lib/ocaml/OrderingPlugin.mlmap +31 -0
- package/lib/ocaml/Orders-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Orders-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Orders-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Orders.ast +0 -0
- package/lib/ocaml/Orders.res +19 -0
- package/lib/ocaml/Orders_ExtensionPointMapping-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping.ast +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping.res +28 -0
- package/lib/ocaml/Orders_ExtensionPointMapping_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping_GWT.ast +0 -0
- package/lib/ocaml/Orders_ExtensionPointMapping_GWT.res +33 -0
- package/lib/ocaml/Orders_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Orders_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Orders_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Orders_GWT.ast +0 -0
- package/lib/ocaml/Orders_GWT.res +46 -0
- package/lib/ocaml/Orders_Projections-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Orders_Projections-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Orders_Projections-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Orders_Projections.ast +0 -0
- package/lib/ocaml/Orders_Projections.res +31 -0
- package/lib/ocaml/Plugin-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Plugin-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Plugin-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Plugin.ast +0 -0
- package/lib/ocaml/Plugin.res +65 -0
- package/lib/ocaml/Products_Extension-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Products_Extension-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Products_Extension-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Products_Extension.ast +0 -0
- package/lib/ocaml/Products_Extension.res +23 -0
- package/lib/ocaml/Products_Extension_GWT-OrderingPlugin.cmi +0 -0
- package/lib/ocaml/Products_Extension_GWT-OrderingPlugin.cmj +0 -0
- package/lib/ocaml/Products_Extension_GWT-OrderingPlugin.cmt +0 -0
- package/lib/ocaml/Products_Extension_GWT.ast +0 -0
- package/lib/ocaml/Products_Extension_GWT.res +21 -0
- package/package.json +52 -0
- package/rescript.json +39 -0
- package/src/CatalogProduct/Aggregate/CatalogProduct.res +18 -0
- package/src/CatalogProduct/Aggregate/CatalogProduct.res.mjs +50 -0
- package/src/CatalogProduct/Aggregate/CatalogProduct_Behavior.res +27 -0
- package/src/CatalogProduct/Aggregate/CatalogProduct_Behavior.res.mjs +87 -0
- package/src/CatalogProduct/ReadModel/AvailableProducts.res +13 -0
- package/src/CatalogProduct/ReadModel/AvailableProducts.res.mjs +53 -0
- package/src/CatalogProduct/ReadModel/AvailableProducts_Projections.res +20 -0
- package/src/CatalogProduct/ReadModel/AvailableProducts_Projections.res.mjs +65 -0
- package/src/Customer/Aggregate/Customer.res +24 -0
- package/src/Customer/Aggregate/Customer.res.mjs +64 -0
- package/src/Customer/Aggregate/Customer_Behavior.res +41 -0
- package/src/Customer/Aggregate/Customer_Behavior.res.mjs +143 -0
- package/src/Customer/ReadModel/Customers.res +12 -0
- package/src/Customer/ReadModel/Customers.res.mjs +36 -0
- package/src/Customer/ReadModel/Customers_Projections.res +21 -0
- package/src/Customer/ReadModel/Customers_Projections.res.mjs +91 -0
- package/src/Extension/Products_Extension.res +23 -0
- package/src/Extension/Products_Extension.res.mjs +43 -0
- package/src/ExtensionPoint/Orders_ExtensionPointMapping.res +28 -0
- package/src/ExtensionPoint/Orders_ExtensionPointMapping.res.mjs +59 -0
- package/src/Order/Aggregate/Order.res +27 -0
- package/src/Order/Aggregate/Order.res.mjs +81 -0
- package/src/Order/Aggregate/Order_Behavior.res +52 -0
- package/src/Order/Aggregate/Order_Behavior.res.mjs +193 -0
- package/src/Order/Aggregate/Order_Mappings.res +15 -0
- package/src/Order/Aggregate/Order_Mappings.res.mjs +55 -0
- package/src/Order/ReadModel/Orders.res +19 -0
- package/src/Order/ReadModel/Orders.res.mjs +62 -0
- package/src/Order/ReadModel/Orders_Projections.res +31 -0
- package/src/Order/ReadModel/Orders_Projections.res.mjs +89 -0
- package/src/Order/SideEffect/Order_EmailNotification.res +18 -0
- package/src/Order/SideEffect/Order_EmailNotification.res.mjs +34 -0
- package/src/Plugin.res +65 -0
- package/src/Plugin.res.mjs +223 -0
- package/src/Service/EmailService.res +22 -0
- package/src/Service/EmailService.res.mjs +23 -0
- package/src/Task/OrderNotifications.res +8 -0
- package/src/Task/OrderNotifications.res.mjs +29 -0
- package/src/plugin.json +1 -0
- package/tests/CatalogProduct/Aggregate/CatalogProduct_GWT.res +27 -0
- package/tests/CatalogProduct/Aggregate/CatalogProduct_GWT.res.mjs +102 -0
- package/tests/CatalogProduct/ReadModel/AvailableProducts_GWT.res +15 -0
- package/tests/CatalogProduct/ReadModel/AvailableProducts_GWT.res.mjs +83 -0
- package/tests/Customer/Aggregate/Customer_GWT.res +90 -0
- package/tests/Customer/Aggregate/Customer_GWT.res.mjs +170 -0
- package/tests/Customer/ReadModel/Customers_GWT.res +27 -0
- package/tests/Customer/ReadModel/Customers_GWT.res.mjs +106 -0
- package/tests/Extension/Products_Extension_GWT.res +21 -0
- package/tests/Extension/Products_Extension_GWT.res.mjs +106 -0
- package/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT.res +33 -0
- package/tests/ExtensionPoint/Orders_ExtensionPointMapping_GWT.res.mjs +143 -0
- package/tests/Order/Aggregate/OrderMappings_GWT.res +52 -0
- package/tests/Order/Aggregate/OrderMappings_GWT.res.mjs +162 -0
- package/tests/Order/Aggregate/Order_GWT.res +121 -0
- package/tests/Order/Aggregate/Order_GWT.res.mjs +231 -0
- package/tests/Order/ReadModel/Orders_GWT.res +46 -0
- package/tests/Order/ReadModel/Orders_GWT.res.mjs +118 -0
- package/tests/Order/SideEffect/EmailService_Mock.res +31 -0
- package/tests/Order/SideEffect/EmailService_Mock.res.mjs +56 -0
- package/tests/Order/SideEffect/Order_EmailNotification_GWT.res +37 -0
- package/tests/Order/SideEffect/Order_EmailNotification_GWT.res.mjs +76 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// AvailableProducts projection mappings.
|
|
2
|
+
// Maps CatalogProduct aggregate events to the AvailableProducts read model.
|
|
3
|
+
@@reventless.mappings
|
|
4
|
+
|
|
5
|
+
module CatalogProductMapping = Mapping.Make(
|
|
6
|
+
CatalogProduct,
|
|
7
|
+
AvailableProducts,
|
|
8
|
+
{
|
|
9
|
+
open CatalogProduct
|
|
10
|
+
let project = ({event, id, _}) =>
|
|
11
|
+
switch event {
|
|
12
|
+
| Synced({name, price}) =>
|
|
13
|
+
Set(id, {AvailableProducts.name: name, price})
|
|
14
|
+
| PriceUpdated({price}) =>
|
|
15
|
+
Update(id, state => {...state, price})
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
let mappings: array<module(Mapping)> = [module(CatalogProductMapping)]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// CatalogProduct aggregate specification.
|
|
2
|
+
// Stores a synced shadow of Catalog products inside Ordering,
|
|
3
|
+
// driven by Catalog's ProductsExtensionPoint.
|
|
4
|
+
|
|
5
|
+
@@reventless.spec
|
|
6
|
+
|
|
7
|
+
@schema
|
|
8
|
+
type command =
|
|
9
|
+
| Sync({name: string, price: float})
|
|
10
|
+
| UpdatePrice({price: float})
|
|
11
|
+
|
|
12
|
+
@schema
|
|
13
|
+
type event =
|
|
14
|
+
| Synced({name: string, price: float})
|
|
15
|
+
| PriceUpdated({price: float})
|
|
16
|
+
|
|
17
|
+
@schema
|
|
18
|
+
type error = unit // always succeeds — sync is idempotent
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// CatalogProduct aggregate behavior.
|
|
2
|
+
// Idempotently syncs Catalog product state into Ordering.
|
|
3
|
+
|
|
4
|
+
@@reventless.behavior
|
|
5
|
+
|
|
6
|
+
@schema
|
|
7
|
+
type state =
|
|
8
|
+
| NotCreated
|
|
9
|
+
| Created({name: string, price: float})
|
|
10
|
+
|
|
11
|
+
let initialState = NotCreated
|
|
12
|
+
|
|
13
|
+
let evolve = (state, event) =>
|
|
14
|
+
switch (state, event) {
|
|
15
|
+
| (NotCreated, Synced({name, price})) => Created({name, price})
|
|
16
|
+
| (Created(_), Synced({name, price})) => Created({name, price})
|
|
17
|
+
| (Created(s), PriceUpdated({price})) => Created({...s, price})
|
|
18
|
+
| (NotCreated, PriceUpdated(_)) => state
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let decide = (state, command) =>
|
|
22
|
+
switch (state, command) {
|
|
23
|
+
| (NotCreated, Sync({name, price})) => Ok([Synced({name, price})])
|
|
24
|
+
| (NotCreated, UpdatePrice(_)) => Ok([]) // no aggregate yet — idempotent
|
|
25
|
+
| (Created(_), Sync(_)) => Ok([]) // already exists — idempotent
|
|
26
|
+
| (Created(_), UpdatePrice({price})) => Ok([PriceUpdated({price: price})])
|
|
27
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
@@reventless.gwt
|
|
2
|
+
|
|
3
|
+
describe("CatalogProduct Behavior", () => {
|
|
4
|
+
test("Sync on new aggregate produces Synced", () =>
|
|
5
|
+
givenEvents([])
|
|
6
|
+
->whenCmd(Sync({name: "Laptop", price: 999.99}))
|
|
7
|
+
->thenEvent(Synced({name: "Laptop", price: 999.99}))
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
test("Sync on already-synced aggregate produces no events (idempotent)", () =>
|
|
11
|
+
givenEvents([Synced({name: "Laptop", price: 999.99})])
|
|
12
|
+
->whenCmd(Sync({name: "Laptop", price: 999.99}))
|
|
13
|
+
->thenNoEvent
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
test("UpdatePrice on never-synced aggregate produces no events (idempotent)", () =>
|
|
17
|
+
givenEvents([])
|
|
18
|
+
->whenCmd(UpdatePrice({price: 1.0}))
|
|
19
|
+
->thenNoEvent
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
test("UpdatePrice on synced aggregate produces PriceUpdated", () =>
|
|
23
|
+
givenEvents([Synced({name: "Laptop", price: 999.99})])
|
|
24
|
+
->whenCmd(UpdatePrice({price: 899.99}))
|
|
25
|
+
->thenEvent(PriceUpdated({price: 899.99}))
|
|
26
|
+
)
|
|
27
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Customer aggregate specification.
|
|
2
|
+
// A registered buyer with contact details and account status.
|
|
3
|
+
|
|
4
|
+
@@reventless.spec
|
|
5
|
+
|
|
6
|
+
@schema
|
|
7
|
+
type command =
|
|
8
|
+
| Register({email: string, address: string})
|
|
9
|
+
| UpdateEmail({email: string})
|
|
10
|
+
| UpdateAddress({address: string})
|
|
11
|
+
| Deactivate
|
|
12
|
+
|
|
13
|
+
@schema
|
|
14
|
+
type event =
|
|
15
|
+
| Registered({email: string, address: string})
|
|
16
|
+
| EmailUpdated({email: string})
|
|
17
|
+
| AddressUpdated({address: string})
|
|
18
|
+
| Deactivated
|
|
19
|
+
|
|
20
|
+
@schema
|
|
21
|
+
type error =
|
|
22
|
+
| CustomerAlreadyRegistered
|
|
23
|
+
| CustomerNotFound
|
|
24
|
+
| CustomerAlreadyDeactivated
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Customer aggregate behavior.
|
|
2
|
+
// Implements the state machine for registering and managing customers.
|
|
3
|
+
|
|
4
|
+
@@reventless.behavior
|
|
5
|
+
|
|
6
|
+
@schema
|
|
7
|
+
type state =
|
|
8
|
+
| NotCreated
|
|
9
|
+
| Active({email: string, address: string})
|
|
10
|
+
| Deactivated
|
|
11
|
+
|
|
12
|
+
let initialState = NotCreated
|
|
13
|
+
|
|
14
|
+
let evolve = (state, event) =>
|
|
15
|
+
switch (state, event) {
|
|
16
|
+
| (NotCreated, Registered({email, address})) => Active({email, address})
|
|
17
|
+
| (Active(_), Registered({email, address})) => Active({email, address})
|
|
18
|
+
| (Active(s), EmailUpdated({email})) => Active({...s, email})
|
|
19
|
+
| (Active(s), AddressUpdated({address})) => Active({...s, address})
|
|
20
|
+
| (Active(_), Customer.Deactivated) => Deactivated
|
|
21
|
+
| (Deactivated, _) => state
|
|
22
|
+
| (NotCreated, _) => state
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let decide = (state, command) =>
|
|
26
|
+
switch (state, command) {
|
|
27
|
+
| (NotCreated, Register({email, address})) => Ok([Registered({email, address})])
|
|
28
|
+
| (NotCreated, UpdateEmail(_)) => Error(CustomerNotFound)
|
|
29
|
+
| (NotCreated, UpdateAddress(_)) => Error(CustomerNotFound)
|
|
30
|
+
| (NotCreated, Deactivate) => Error(CustomerNotFound)
|
|
31
|
+
| (Active(_), Register(_)) => Error(CustomerAlreadyRegistered)
|
|
32
|
+
| (Active(s), UpdateEmail({email})) if email == s.email => Ok([])
|
|
33
|
+
| (Active(_), UpdateEmail({email})) => Ok([EmailUpdated({email: email})])
|
|
34
|
+
| (Active(s), UpdateAddress({address})) if address == s.address => Ok([])
|
|
35
|
+
| (Active(_), UpdateAddress({address})) => Ok([AddressUpdated({address: address})])
|
|
36
|
+
| (Active(_), Deactivate) => Ok([Customer.Deactivated])
|
|
37
|
+
| (Deactivated, Register(_)) => Error(CustomerAlreadyDeactivated)
|
|
38
|
+
| (Deactivated, UpdateEmail(_)) => Error(CustomerAlreadyDeactivated)
|
|
39
|
+
| (Deactivated, UpdateAddress(_)) => Error(CustomerAlreadyDeactivated)
|
|
40
|
+
| (Deactivated, Deactivate) => Ok([]) // idempotent
|
|
41
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
@@reventless.gwt
|
|
2
|
+
|
|
3
|
+
describe("Customer Behavior", () => {
|
|
4
|
+
test("Register on new aggregate produces Registered", () =>
|
|
5
|
+
givenEvents([])
|
|
6
|
+
->whenCmd(Register({email: "alice@example.com", address: "123 Main St"}))
|
|
7
|
+
->thenEvent(Registered({email: "alice@example.com", address: "123 Main St"}))
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
test("Register on existing aggregate returns CustomerAlreadyRegistered", () =>
|
|
11
|
+
givenEvents([Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
12
|
+
->whenCmd(Register({email: "bob@example.com", address: "456 Oak Ave"}))
|
|
13
|
+
->thenError(CustomerAlreadyRegistered)
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
test("Register on deactivated aggregate returns CustomerAlreadyDeactivated", () =>
|
|
17
|
+
givenEvents([
|
|
18
|
+
Registered({email: "alice@example.com", address: "123 Main St"}),
|
|
19
|
+
Deactivated,
|
|
20
|
+
])
|
|
21
|
+
->whenCmd(Register({email: "bob@example.com", address: "456 Oak Ave"}))
|
|
22
|
+
->thenError(CustomerAlreadyDeactivated)
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
test("UpdateEmail on non-existent aggregate returns CustomerNotFound", () =>
|
|
26
|
+
givenEvents([])
|
|
27
|
+
->whenCmd(UpdateEmail({email: "x@y"}))
|
|
28
|
+
->thenError(CustomerNotFound)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
test("UpdateEmail on active customer produces EmailUpdated", () =>
|
|
32
|
+
givenEvents([Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
33
|
+
->whenCmd(UpdateEmail({email: "alice2@example.com"}))
|
|
34
|
+
->thenEvent(EmailUpdated({email: "alice2@example.com"}))
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
test("UpdateEmail to same email produces no events (idempotent)", () =>
|
|
38
|
+
givenEvents([Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
39
|
+
->whenCmd(UpdateEmail({email: "alice@example.com"}))
|
|
40
|
+
->thenNoEvent
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
test("UpdateEmail on deactivated customer returns CustomerAlreadyDeactivated", () =>
|
|
44
|
+
givenEvents([
|
|
45
|
+
Registered({email: "alice@example.com", address: "123 Main St"}),
|
|
46
|
+
Deactivated,
|
|
47
|
+
])
|
|
48
|
+
->whenCmd(UpdateEmail({email: "x@y"}))
|
|
49
|
+
->thenError(CustomerAlreadyDeactivated)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
test("UpdateAddress on non-existent aggregate returns CustomerNotFound", () =>
|
|
53
|
+
givenEvents([])
|
|
54
|
+
->whenCmd(UpdateAddress({address: "x"}))
|
|
55
|
+
->thenError(CustomerNotFound)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
test("UpdateAddress on active customer produces AddressUpdated", () =>
|
|
59
|
+
givenEvents([Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
60
|
+
->whenCmd(UpdateAddress({address: "789 Pine Rd"}))
|
|
61
|
+
->thenEvent(AddressUpdated({address: "789 Pine Rd"}))
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
test("UpdateAddress to same address produces no events (idempotent)", () =>
|
|
65
|
+
givenEvents([Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
66
|
+
->whenCmd(UpdateAddress({address: "123 Main St"}))
|
|
67
|
+
->thenNoEvent
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
test("Deactivate on non-existent aggregate returns CustomerNotFound", () =>
|
|
71
|
+
givenEvents([])
|
|
72
|
+
->whenCmd(Deactivate)
|
|
73
|
+
->thenError(CustomerNotFound)
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
test("Deactivate on active customer produces Deactivated", () =>
|
|
77
|
+
givenEvents([Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
78
|
+
->whenCmd(Deactivate)
|
|
79
|
+
->thenEvent(Deactivated)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
test("Deactivate on deactivated customer produces no events (idempotent)", () =>
|
|
83
|
+
givenEvents([
|
|
84
|
+
Registered({email: "alice@example.com", address: "123 Main St"}),
|
|
85
|
+
Deactivated,
|
|
86
|
+
])
|
|
87
|
+
->whenCmd(Deactivate)
|
|
88
|
+
->thenNoEvent
|
|
89
|
+
)
|
|
90
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
@@reventless.gwt(Customers_Projections.CustomerMapping)
|
|
2
|
+
|
|
3
|
+
describe("Customers ReadModel ← Customer", () => {
|
|
4
|
+
test("Registered sets initial read model state", () =>
|
|
5
|
+
givenEvents([])
|
|
6
|
+
->whenEvent(Customer.Registered({email: "alice@example.com", address: "123 Main St"}))
|
|
7
|
+
->thenState({Customers.email: "alice@example.com", address: "123 Main St", deactivated: false})
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
test("EmailUpdated updates the email", () =>
|
|
11
|
+
givenEvents([Customer.Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
12
|
+
->whenEvent(Customer.EmailUpdated({email: "alice2@example.com"}))
|
|
13
|
+
->thenState({Customers.email: "alice2@example.com", address: "123 Main St", deactivated: false})
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
test("AddressUpdated updates the address", () =>
|
|
17
|
+
givenEvents([Customer.Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
18
|
+
->whenEvent(Customer.AddressUpdated({address: "789 Pine Rd"}))
|
|
19
|
+
->thenState({Customers.email: "alice@example.com", address: "789 Pine Rd", deactivated: false})
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
test("Deactivated sets deactivated flag", () =>
|
|
23
|
+
givenEvents([Customer.Registered({email: "alice@example.com", address: "123 Main St"})])
|
|
24
|
+
->whenEvent(Customer.Deactivated)
|
|
25
|
+
->thenState({Customers.email: "alice@example.com", address: "123 Main St", deactivated: true})
|
|
26
|
+
)
|
|
27
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Customer projection mappings.
|
|
2
|
+
// Maps Customer aggregate events to Customers read model state changes.
|
|
3
|
+
@@reventless.mappings
|
|
4
|
+
|
|
5
|
+
module CustomerMapping = Mapping.Make(
|
|
6
|
+
Customer,
|
|
7
|
+
Customers,
|
|
8
|
+
{
|
|
9
|
+
open Customer
|
|
10
|
+
let project = ({event, id, _}) =>
|
|
11
|
+
switch event {
|
|
12
|
+
| Registered({email, address}) =>
|
|
13
|
+
Set(id, {Customers.email: email, address, deactivated: false})
|
|
14
|
+
| EmailUpdated({email}) => Update(id, state => {...state, email})
|
|
15
|
+
| AddressUpdated({address}) => Update(id, state => {...state, address})
|
|
16
|
+
| Deactivated => Update(id, state => {...state, deactivated: true})
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
let mappings: array<module(Mapping)> = [module(CustomerMapping)]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Stub email service for the example.
|
|
2
|
+
//
|
|
3
|
+
// The implementation goes through a `ref`-held `backend` so that tests can
|
|
4
|
+
// install a recording mock (see `EmailService_Mock.res` next to the GWT files
|
|
5
|
+
// — Option C of the `sideeffect-gwt` plan). Production code still calls
|
|
6
|
+
// `EmailService.sendOrderConfirmation(...)` directly; the indirection is
|
|
7
|
+
// invisible at the call site.
|
|
8
|
+
|
|
9
|
+
type backend = {
|
|
10
|
+
sendOrderConfirmation: (~email: string, ~orderId: string) => promise<unit>,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let liveBackend: backend = {
|
|
14
|
+
sendOrderConfirmation: async (~email as _, ~orderId as _) => {
|
|
15
|
+
Console.log("[EmailService] Order confirmation sent")
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let current = ref(liveBackend)
|
|
20
|
+
|
|
21
|
+
let sendOrderConfirmation = (~email, ~orderId) =>
|
|
22
|
+
current.contents.sendOrderConfirmation(~email, ~orderId)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Recording mock for `EmailService` (Option C of the `sideeffect-gwt` plan).
|
|
2
|
+
// `install()` swaps `EmailService.current` to a backend that records every
|
|
3
|
+
// call into a ref. `SideEffect_GWT` reads the recorded calls back via `mock`
|
|
4
|
+
// and renders assertions against them.
|
|
5
|
+
//
|
|
6
|
+
// Production code never sees this file — it lives under `tests/` and only
|
|
7
|
+
// loads when the test runner imports it.
|
|
8
|
+
|
|
9
|
+
@schema
|
|
10
|
+
type call = SendOrderConfirmation({email: string, orderId: string})
|
|
11
|
+
|
|
12
|
+
let calls: ref<array<call>> = ref([])
|
|
13
|
+
|
|
14
|
+
let reset = () => calls := []
|
|
15
|
+
|
|
16
|
+
let recordingBackend: EmailService.backend = {
|
|
17
|
+
sendOrderConfirmation: async (~email, ~orderId) => {
|
|
18
|
+
calls := calls.contents->Array.concat([SendOrderConfirmation({email, orderId})])
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Swap the live backend and clear any prior recordings. Call from `beforeEach`.
|
|
23
|
+
let install = () => {
|
|
24
|
+
EmailService.current := recordingBackend
|
|
25
|
+
reset()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let mock: ReventlessGwt.SideEffect_GWT.mock<call> = {
|
|
29
|
+
snapshot: () => calls.contents,
|
|
30
|
+
encode: c => c->S.reverseConvertToJsonOrThrow(callSchema),
|
|
31
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Order aggregate specification.
|
|
2
|
+
// A confirmed purchase referencing Product IDs and a CustomerId.
|
|
3
|
+
|
|
4
|
+
@@reventless.spec
|
|
5
|
+
|
|
6
|
+
@schema
|
|
7
|
+
type command =
|
|
8
|
+
| Place({customerId: string, @ref("AvailableProducts") @noDcbTag productIds: array<string>})
|
|
9
|
+
| @allowedStates([Orders.Placed]) Ship
|
|
10
|
+
| @allowedStates([Orders.Placed]) Cancel
|
|
11
|
+
| @allowedStates([Orders.Cancelled]) Refund({reason: string})
|
|
12
|
+
|
|
13
|
+
@schema
|
|
14
|
+
type event =
|
|
15
|
+
| Placed({customerId: string, productIds: array<string>})
|
|
16
|
+
| Shipped
|
|
17
|
+
| Cancelled({productIds: array<string>})
|
|
18
|
+
| Refunded({reason: string})
|
|
19
|
+
|
|
20
|
+
@schema
|
|
21
|
+
type error =
|
|
22
|
+
| OrderAlreadyPlaced
|
|
23
|
+
| OrderNotFound
|
|
24
|
+
| OrderAlreadyShipped
|
|
25
|
+
| OrderAlreadyCancelled
|
|
26
|
+
| OrderNotCancelled
|
|
27
|
+
| OrderAlreadyRefunded
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// `Mapping_GWT` exercises Order's self-mapping (auto-ship on placement).
|
|
2
|
+
// Bare `@@reventless.gwt` would derive the Behavior DSL from the Aggregate
|
|
3
|
+
// folder; the cross-pattern Mapping DSL is wired explicitly instead.
|
|
4
|
+
//
|
|
5
|
+
// Self-mappings need the target's per-id history pre-seeded with the
|
|
6
|
+
// source-emitted event, since Mapping_GWT models source and target as
|
|
7
|
+
// independent aggregates even when they're the same one in production.
|
|
8
|
+
|
|
9
|
+
module OrderSource = ReventlessGwt.Mapping_GWT.FromBehavior(Order, Order_Behavior)
|
|
10
|
+
module OrderTarget = ReventlessGwt.Mapping_GWT.FromBehavior(Order, Order_Behavior)
|
|
11
|
+
|
|
12
|
+
module AutoShipGwtMapping = {
|
|
13
|
+
module Source = OrderSource
|
|
14
|
+
module Target = OrderTarget
|
|
15
|
+
let map = Order_Mappings.AutoShipMapping.map
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
include ReventlessGwt.Mapping_GWT.Make(AutoShipGwtMapping)
|
|
19
|
+
|
|
20
|
+
let placedEvent = Order.Placed({customerId: "cust-1", productIds: ["prod-1"]})
|
|
21
|
+
|
|
22
|
+
describe("Order auto-ship mapping (Placed → Ship)", () => {
|
|
23
|
+
test("Place → AutoShipMapping issues Ship → target emits Shipped", () =>
|
|
24
|
+
givenSourceEvents([])
|
|
25
|
+
->andTargetEvents([("order-1", [placedEvent])])
|
|
26
|
+
->whenSourceCmd("order-1", Place({customerId: "cust-1", productIds: ["prod-1"]}))
|
|
27
|
+
->thenTargetEvent("order-1", Order.Shipped)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
test("Ship command does not fire the mapping (only Placed events do)", () =>
|
|
31
|
+
givenSourceEvents([placedEvent])
|
|
32
|
+
->andTargetEvents([("order-1", [placedEvent])])
|
|
33
|
+
->whenSourceCmd("order-1", Ship)
|
|
34
|
+
->thenNoTargetEvent
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
test("Cancel command does not fire the mapping", () =>
|
|
38
|
+
givenSourceEvents([placedEvent])
|
|
39
|
+
->andTargetEvents([("order-1", [placedEvent])])
|
|
40
|
+
->whenSourceCmd("order-1", Cancel)
|
|
41
|
+
->thenNoTargetEvent
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
test("Refund command does not fire the mapping (only Placed events do)", () =>
|
|
45
|
+
givenSourceEvents([placedEvent, Order.Cancelled({productIds: ["prod-1"]})])
|
|
46
|
+
->andTargetEvents([
|
|
47
|
+
("order-1", [placedEvent, Order.Cancelled({productIds: ["prod-1"]})]),
|
|
48
|
+
])
|
|
49
|
+
->whenSourceCmd("order-1", Refund({reason: "customer-changed-mind"}))
|
|
50
|
+
->thenNoTargetEvent
|
|
51
|
+
)
|
|
52
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Order notification task — hosts side effects for the Order aggregate.
|
|
2
|
+
// Sends email confirmations when orders are placed.
|
|
3
|
+
|
|
4
|
+
@@reventless.task
|
|
5
|
+
|
|
6
|
+
let setup = (_queryEngine, _queryBucketName, _opts) => {
|
|
7
|
+
Task.sideEffects: [module(Order_EmailNotification): module(SideEffect.T)],
|
|
8
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|