@reventlessdev/online-shop-aggregates-catalog 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 +854 -0
- package/LICENSE +202 -0
- package/__mocks__/emptyModule.js +1 -0
- package/lib/bs/.compiler.log +2 -0
- package/lib/bs/CatalogPlugin.cmi +0 -0
- package/lib/bs/CatalogPlugin.cmj +0 -0
- package/lib/bs/CatalogPlugin.cmt +0 -0
- package/lib/bs/CatalogPlugin.mlmap +25 -0
- package/lib/bs/build.ninja +0 -0
- package/lib/bs/compiler-info.json +8 -0
- package/lib/bs/src/Category/Aggregate/Category-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Category/Aggregate/Category-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Category/Aggregate/Category-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Category/Aggregate/Category.ast +0 -0
- package/lib/bs/src/Category/Aggregate/Category.res +22 -0
- package/lib/bs/src/Category/Aggregate/Category.res.mjs +61 -0
- package/lib/bs/src/Category/Aggregate/Category_Behavior-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Category/Aggregate/Category_Behavior-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Category/Aggregate/Category_Behavior-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Category/Aggregate/Category_Behavior.ast +0 -0
- package/lib/bs/src/Category/Aggregate/Category_Behavior.res +36 -0
- package/lib/bs/src/Category/Aggregate/Category_Behavior.res.mjs +106 -0
- package/lib/bs/src/Category/ReadModel/Categories-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Category/ReadModel/Categories-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Category/ReadModel/Categories-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Category/ReadModel/Categories.ast +0 -0
- package/lib/bs/src/Category/ReadModel/Categories.res +11 -0
- package/lib/bs/src/Category/ReadModel/Categories.res.mjs +35 -0
- package/lib/bs/src/Category/ReadModel/Categories_Projections-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Category/ReadModel/Categories_Projections-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Category/ReadModel/Categories_Projections-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Category/ReadModel/Categories_Projections.ast +0 -0
- package/lib/bs/src/Category/ReadModel/Categories_Projections.res +19 -0
- package/lib/bs/src/Category/ReadModel/Categories_Projections.res.mjs +75 -0
- package/lib/bs/src/Extension/Orders_Extension-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Extension/Orders_Extension-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Extension/Orders_Extension-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Extension/Orders_Extension.ast +0 -0
- package/lib/bs/src/Extension/Orders_Extension.res +23 -0
- package/lib/bs/src/Extension/Orders_Extension.res.mjs +42 -0
- package/lib/bs/src/ExtensionPoint/Products_ExtensionPointMapping-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/ExtensionPoint/Products_ExtensionPointMapping-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/ExtensionPoint/Products_ExtensionPointMapping-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/ExtensionPoint/Products_ExtensionPointMapping.ast +0 -0
- package/lib/bs/src/ExtensionPoint/Products_ExtensionPointMapping.res +19 -0
- package/lib/bs/src/ExtensionPoint/Products_ExtensionPointMapping.res.mjs +56 -0
- package/lib/bs/src/Plugin-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Plugin-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Plugin-CatalogPlugin.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 +222 -0
- package/lib/bs/src/Product/Aggregate/Product-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Product/Aggregate/Product-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Product/Aggregate/Product-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Product/Aggregate/Product.ast +0 -0
- package/lib/bs/src/Product/Aggregate/Product.res +23 -0
- package/lib/bs/src/Product/Aggregate/Product.res.mjs +71 -0
- package/lib/bs/src/Product/Aggregate/Product_Behavior-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Product/Aggregate/Product_Behavior-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Product/Aggregate/Product_Behavior-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Product/Aggregate/Product_Behavior.ast +0 -0
- package/lib/bs/src/Product/Aggregate/Product_Behavior.res +38 -0
- package/lib/bs/src/Product/Aggregate/Product_Behavior.res.mjs +150 -0
- package/lib/bs/src/Product/ReadModel/Products-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Product/ReadModel/Products-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Product/ReadModel/Products-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Product/ReadModel/Products.ast +0 -0
- package/lib/bs/src/Product/ReadModel/Products.res +12 -0
- package/lib/bs/src/Product/ReadModel/Products.res.mjs +36 -0
- package/lib/bs/src/Product/ReadModel/Products_Projections-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Product/ReadModel/Products_Projections-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Product/ReadModel/Products_Projections-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Product/ReadModel/Products_Projections.ast +0 -0
- package/lib/bs/src/Product/ReadModel/Products_Projections.res +22 -0
- package/lib/bs/src/Product/ReadModel/Products_Projections.res.mjs +91 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand.ast +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand.res +20 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand.res.mjs +51 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand_Behavior-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand_Behavior-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand_Behavior-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand_Behavior.ast +0 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand_Behavior.res +39 -0
- package/lib/bs/src/ProductDemand/Aggregate/ProductDemand_Behavior.res.mjs +102 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands.ast +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands.res +8 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands.res.mjs +35 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands_Projections-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands_Projections-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands_Projections-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands_Projections.ast +0 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands_Projections.res +36 -0
- package/lib/bs/src/ProductDemand/ReadModel/ProductDemands_Projections.res.mjs +99 -0
- package/lib/bs/src/Task/ImportProducts-CatalogPlugin.cmi +0 -0
- package/lib/bs/src/Task/ImportProducts-CatalogPlugin.cmj +0 -0
- package/lib/bs/src/Task/ImportProducts-CatalogPlugin.cmt +0 -0
- package/lib/bs/src/Task/ImportProducts.ast +0 -0
- package/lib/bs/src/Task/ImportProducts.res +48 -0
- package/lib/bs/src/Task/ImportProducts.res.mjs +58 -0
- package/lib/bs/tests/Category/Aggregate/Category_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/Category/Aggregate/Category_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/Category/Aggregate/Category_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/Category/Aggregate/Category_GWT.ast +0 -0
- package/lib/bs/tests/Category/Aggregate/Category_GWT.res +51 -0
- package/lib/bs/tests/Category/Aggregate/Category_GWT.res.mjs +125 -0
- package/lib/bs/tests/Category/ReadModel/Categories_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/Category/ReadModel/Categories_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/Category/ReadModel/Categories_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/Category/ReadModel/Categories_GWT.ast +0 -0
- package/lib/bs/tests/Category/ReadModel/Categories_GWT.res +21 -0
- package/lib/bs/tests/Category/ReadModel/Categories_GWT.res.mjs +88 -0
- package/lib/bs/tests/Extension/Orders_Extension_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/Extension/Orders_Extension_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/Extension/Orders_Extension_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/Extension/Orders_Extension_GWT.ast +0 -0
- package/lib/bs/tests/Extension/Orders_Extension_GWT.res +21 -0
- package/lib/bs/tests/Extension/Orders_Extension_GWT.res.mjs +105 -0
- package/lib/bs/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT.ast +0 -0
- package/lib/bs/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT.res +31 -0
- package/lib/bs/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT.res.mjs +114 -0
- package/lib/bs/tests/Product/Aggregate/Product_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/Product/Aggregate/Product_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/Product/Aggregate/Product_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/Product/Aggregate/Product_GWT.ast +0 -0
- package/lib/bs/tests/Product/Aggregate/Product_GWT.res +69 -0
- package/lib/bs/tests/Product/Aggregate/Product_GWT.res.mjs +166 -0
- package/lib/bs/tests/Product/ReadModel/Products_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/Product/ReadModel/Products_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/Product/ReadModel/Products_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/Product/ReadModel/Products_GWT.ast +0 -0
- package/lib/bs/tests/Product/ReadModel/Products_GWT.res +27 -0
- package/lib/bs/tests/Product/ReadModel/Products_GWT.res.mjs +113 -0
- package/lib/bs/tests/ProductDemand/Aggregate/ProductDemand_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/ProductDemand/Aggregate/ProductDemand_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/ProductDemand/Aggregate/ProductDemand_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/ProductDemand/Aggregate/ProductDemand_GWT.ast +0 -0
- package/lib/bs/tests/ProductDemand/Aggregate/ProductDemand_GWT.res +39 -0
- package/lib/bs/tests/ProductDemand/Aggregate/ProductDemand_GWT.res.mjs +114 -0
- package/lib/bs/tests/ProductDemand/ReadModel/ProductDemands_GWT-CatalogPlugin.cmi +0 -0
- package/lib/bs/tests/ProductDemand/ReadModel/ProductDemands_GWT-CatalogPlugin.cmj +0 -0
- package/lib/bs/tests/ProductDemand/ReadModel/ProductDemands_GWT-CatalogPlugin.cmt +0 -0
- package/lib/bs/tests/ProductDemand/ReadModel/ProductDemands_GWT.ast +0 -0
- package/lib/bs/tests/ProductDemand/ReadModel/ProductDemands_GWT.res +56 -0
- package/lib/bs/tests/ProductDemand/ReadModel/ProductDemands_GWT.res.mjs +73 -0
- package/lib/ocaml/.compiler.log +2 -0
- package/lib/ocaml/CatalogPlugin.cmi +0 -0
- package/lib/ocaml/CatalogPlugin.cmj +0 -0
- package/lib/ocaml/CatalogPlugin.cmt +0 -0
- package/lib/ocaml/CatalogPlugin.mlmap +25 -0
- package/lib/ocaml/Categories-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Categories-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Categories-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Categories.ast +0 -0
- package/lib/ocaml/Categories.res +11 -0
- package/lib/ocaml/Categories_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Categories_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Categories_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Categories_GWT.ast +0 -0
- package/lib/ocaml/Categories_GWT.res +21 -0
- package/lib/ocaml/Categories_Projections-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Categories_Projections-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Categories_Projections-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Categories_Projections.ast +0 -0
- package/lib/ocaml/Categories_Projections.res +19 -0
- package/lib/ocaml/Category-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Category-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Category-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Category.ast +0 -0
- package/lib/ocaml/Category.res +22 -0
- package/lib/ocaml/Category_Behavior-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Category_Behavior-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Category_Behavior-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Category_Behavior.ast +0 -0
- package/lib/ocaml/Category_Behavior.res +36 -0
- package/lib/ocaml/Category_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Category_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Category_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Category_GWT.ast +0 -0
- package/lib/ocaml/Category_GWT.res +51 -0
- package/lib/ocaml/ImportProducts-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/ImportProducts-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/ImportProducts-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/ImportProducts.ast +0 -0
- package/lib/ocaml/ImportProducts.res +48 -0
- package/lib/ocaml/Orders_Extension-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Orders_Extension-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Orders_Extension-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Orders_Extension.ast +0 -0
- package/lib/ocaml/Orders_Extension.res +23 -0
- package/lib/ocaml/Orders_Extension_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Orders_Extension_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Orders_Extension_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Orders_Extension_GWT.ast +0 -0
- package/lib/ocaml/Orders_Extension_GWT.res +21 -0
- package/lib/ocaml/Plugin-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Plugin-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Plugin-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Plugin.ast +0 -0
- package/lib/ocaml/Plugin.res +65 -0
- package/lib/ocaml/Product-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Product-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Product-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Product.ast +0 -0
- package/lib/ocaml/Product.res +23 -0
- package/lib/ocaml/ProductDemand-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/ProductDemand-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/ProductDemand-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/ProductDemand.ast +0 -0
- package/lib/ocaml/ProductDemand.res +20 -0
- package/lib/ocaml/ProductDemand_Behavior-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/ProductDemand_Behavior-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/ProductDemand_Behavior-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/ProductDemand_Behavior.ast +0 -0
- package/lib/ocaml/ProductDemand_Behavior.res +39 -0
- package/lib/ocaml/ProductDemand_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/ProductDemand_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/ProductDemand_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/ProductDemand_GWT.ast +0 -0
- package/lib/ocaml/ProductDemand_GWT.res +39 -0
- package/lib/ocaml/ProductDemands-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/ProductDemands-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/ProductDemands-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/ProductDemands.ast +0 -0
- package/lib/ocaml/ProductDemands.res +8 -0
- package/lib/ocaml/ProductDemands_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/ProductDemands_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/ProductDemands_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/ProductDemands_GWT.ast +0 -0
- package/lib/ocaml/ProductDemands_GWT.res +56 -0
- package/lib/ocaml/ProductDemands_Projections-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/ProductDemands_Projections-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/ProductDemands_Projections-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/ProductDemands_Projections.ast +0 -0
- package/lib/ocaml/ProductDemands_Projections.res +36 -0
- package/lib/ocaml/Product_Behavior-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Product_Behavior-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Product_Behavior-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Product_Behavior.ast +0 -0
- package/lib/ocaml/Product_Behavior.res +38 -0
- package/lib/ocaml/Product_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Product_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Product_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Product_GWT.ast +0 -0
- package/lib/ocaml/Product_GWT.res +69 -0
- package/lib/ocaml/Products-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Products-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Products-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Products.ast +0 -0
- package/lib/ocaml/Products.res +12 -0
- package/lib/ocaml/Products_ExtensionPointMapping-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping.ast +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping.res +19 -0
- package/lib/ocaml/Products_ExtensionPointMapping_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping_GWT.ast +0 -0
- package/lib/ocaml/Products_ExtensionPointMapping_GWT.res +31 -0
- package/lib/ocaml/Products_GWT-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Products_GWT-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Products_GWT-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Products_GWT.ast +0 -0
- package/lib/ocaml/Products_GWT.res +27 -0
- package/lib/ocaml/Products_Projections-CatalogPlugin.cmi +0 -0
- package/lib/ocaml/Products_Projections-CatalogPlugin.cmj +0 -0
- package/lib/ocaml/Products_Projections-CatalogPlugin.cmt +0 -0
- package/lib/ocaml/Products_Projections.ast +0 -0
- package/lib/ocaml/Products_Projections.res +22 -0
- package/package.json +52 -0
- package/rescript.json +39 -0
- package/src/Category/Aggregate/Category.res +22 -0
- package/src/Category/Aggregate/Category.res.mjs +61 -0
- package/src/Category/Aggregate/Category_Behavior.res +36 -0
- package/src/Category/Aggregate/Category_Behavior.res.mjs +106 -0
- package/src/Category/ReadModel/Categories.res +11 -0
- package/src/Category/ReadModel/Categories.res.mjs +35 -0
- package/src/Category/ReadModel/Categories_Projections.res +19 -0
- package/src/Category/ReadModel/Categories_Projections.res.mjs +75 -0
- package/src/Extension/Orders_Extension.res +23 -0
- package/src/Extension/Orders_Extension.res.mjs +42 -0
- package/src/ExtensionPoint/Products_ExtensionPointMapping.res +19 -0
- package/src/ExtensionPoint/Products_ExtensionPointMapping.res.mjs +56 -0
- package/src/Plugin.res +65 -0
- package/src/Plugin.res.mjs +222 -0
- package/src/Product/Aggregate/Product.res +23 -0
- package/src/Product/Aggregate/Product.res.mjs +71 -0
- package/src/Product/Aggregate/Product_Behavior.res +38 -0
- package/src/Product/Aggregate/Product_Behavior.res.mjs +150 -0
- package/src/Product/ReadModel/Products.res +12 -0
- package/src/Product/ReadModel/Products.res.mjs +36 -0
- package/src/Product/ReadModel/Products_Projections.res +22 -0
- package/src/Product/ReadModel/Products_Projections.res.mjs +91 -0
- package/src/ProductDemand/Aggregate/ProductDemand.res +20 -0
- package/src/ProductDemand/Aggregate/ProductDemand.res.mjs +51 -0
- package/src/ProductDemand/Aggregate/ProductDemand_Behavior.res +39 -0
- package/src/ProductDemand/Aggregate/ProductDemand_Behavior.res.mjs +102 -0
- package/src/ProductDemand/ReadModel/ProductDemands.res +8 -0
- package/src/ProductDemand/ReadModel/ProductDemands.res.mjs +35 -0
- package/src/ProductDemand/ReadModel/ProductDemands_Projections.res +36 -0
- package/src/ProductDemand/ReadModel/ProductDemands_Projections.res.mjs +99 -0
- package/src/Task/ImportProducts.res +48 -0
- package/src/Task/ImportProducts.res.mjs +58 -0
- package/src/plugin.json +1 -0
- package/tests/Category/Aggregate/Category_GWT.res +51 -0
- package/tests/Category/Aggregate/Category_GWT.res.mjs +125 -0
- package/tests/Category/ReadModel/Categories_GWT.res +21 -0
- package/tests/Category/ReadModel/Categories_GWT.res.mjs +88 -0
- package/tests/Extension/Orders_Extension_GWT.res +21 -0
- package/tests/Extension/Orders_Extension_GWT.res.mjs +105 -0
- package/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT.res +31 -0
- package/tests/ExtensionPoint/Products_ExtensionPointMapping_GWT.res.mjs +114 -0
- package/tests/Product/Aggregate/Product_GWT.res +69 -0
- package/tests/Product/Aggregate/Product_GWT.res.mjs +166 -0
- package/tests/Product/ReadModel/Products_GWT.res +27 -0
- package/tests/Product/ReadModel/Products_GWT.res.mjs +113 -0
- package/tests/ProductDemand/Aggregate/ProductDemand_GWT.res +39 -0
- package/tests/ProductDemand/Aggregate/ProductDemand_GWT.res.mjs +114 -0
- package/tests/ProductDemand/ReadModel/ProductDemands_GWT.res +56 -0
- package/tests/ProductDemand/ReadModel/ProductDemands_GWT.res.mjs +73 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// AUTO-GENERATED — do not edit. Run `npm run generate` to update.
|
|
2
|
+
|
|
3
|
+
@val external uiBundleUrl: option<string> = "process.env.CATALOG_UI_BUNDLE_URL"
|
|
4
|
+
|
|
5
|
+
module Make = (Platform: ReventlessInfra.Platform.T) => {
|
|
6
|
+
// Aggregates
|
|
7
|
+
module CategoryAggregate = Platform.Aggregate.Make(
|
|
8
|
+
Category,
|
|
9
|
+
Category_Behavior,
|
|
10
|
+
ReventlessInfra.NoEventMappings.Make(Category),
|
|
11
|
+
)
|
|
12
|
+
module ProductAggregate = Platform.Aggregate.Make(
|
|
13
|
+
Product,
|
|
14
|
+
Product_Behavior,
|
|
15
|
+
ReventlessInfra.NoEventMappings.Make(Product),
|
|
16
|
+
)
|
|
17
|
+
module ProductDemandAggregate = Platform.Aggregate.Make(
|
|
18
|
+
ProductDemand,
|
|
19
|
+
ProductDemand_Behavior,
|
|
20
|
+
ReventlessInfra.NoEventMappings.Make(ProductDemand),
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
// ReadModels
|
|
24
|
+
module CategoriesReadModel = Platform.ReadModel.Make(Categories, Categories_Projections)
|
|
25
|
+
module ProductDemandsReadModel = Platform.ReadModel.Make(ProductDemands, ProductDemands_Projections)
|
|
26
|
+
module ProductsReadModel = Platform.ReadModel.Make(Products, Products_Projections)
|
|
27
|
+
|
|
28
|
+
// Tasks
|
|
29
|
+
module ImportProductsTask = Platform.Task.Make(ImportProducts)
|
|
30
|
+
|
|
31
|
+
// ExtensionPoints
|
|
32
|
+
module Products_ExtensionPoint = Platform.ExtensionPoint.Make(Products_ExtensionPointMapping)
|
|
33
|
+
|
|
34
|
+
// Extensions
|
|
35
|
+
module Orders_Extension = Platform.Extension.Make(Orders_Extension.Mapping)
|
|
36
|
+
|
|
37
|
+
let pluginStructure = Platform.Plugin.makePluginDefinition(
|
|
38
|
+
~name="Catalog",
|
|
39
|
+
~aggregates=[module(CategoryAggregate), module(ProductAggregate), module(ProductDemandAggregate)],
|
|
40
|
+
~readModels=[module(CategoriesReadModel), module(ProductDemandsReadModel), module(ProductsReadModel)],
|
|
41
|
+
~extensions=[module(Orders_Extension)],
|
|
42
|
+
~extensionPoints=[module(Products_ExtensionPointMapping)],
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
let make = () =>
|
|
46
|
+
Platform.Plugin.make(
|
|
47
|
+
~name="Catalog",
|
|
48
|
+
~heartbeatInterval=5,
|
|
49
|
+
~extensionPoints=[module(Products_ExtensionPoint)],
|
|
50
|
+
~extensions=[module(Orders_Extension)],
|
|
51
|
+
~aggregates=[module(CategoryAggregate), module(ProductAggregate), module(ProductDemandAggregate)],
|
|
52
|
+
~readModels=[module(CategoriesReadModel), module(ProductDemandsReadModel), module(ProductsReadModel)],
|
|
53
|
+
~tasks=[module(ImportProductsTask)],
|
|
54
|
+
~pluginStructure=pluginStructure,
|
|
55
|
+
~uiFragments=?uiBundleUrl->Option.map(url =>
|
|
56
|
+
Platform.Plugin.makeAutoUIManifest(
|
|
57
|
+
~remoteEntryUrl=url,
|
|
58
|
+
~name="Catalog",
|
|
59
|
+
~pluginStructure,
|
|
60
|
+
~readModelPositions=["platform-summary"],
|
|
61
|
+
~aggregatePositions=["resource-detail"],
|
|
62
|
+
)
|
|
63
|
+
),
|
|
64
|
+
)
|
|
65
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Product aggregate specification.
|
|
2
|
+
// A product listing with name, description, and price.
|
|
3
|
+
|
|
4
|
+
@@reventless.spec
|
|
5
|
+
|
|
6
|
+
@schema
|
|
7
|
+
type command =
|
|
8
|
+
| Add({name: string, description: string, price: float})
|
|
9
|
+
| UpdateName({name: string})
|
|
10
|
+
| UpdateDescription({description: string})
|
|
11
|
+
| UpdatePrice({price: float})
|
|
12
|
+
|
|
13
|
+
@schema
|
|
14
|
+
type event =
|
|
15
|
+
| Added({name: string, description: string, price: float})
|
|
16
|
+
| NameUpdated({name: string})
|
|
17
|
+
| DescriptionUpdated({description: string})
|
|
18
|
+
| PriceUpdated({price: float})
|
|
19
|
+
|
|
20
|
+
@schema
|
|
21
|
+
type error =
|
|
22
|
+
| ProductAlreadyExists
|
|
23
|
+
| ProductNotFound
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// ProductDemand aggregate specification.
|
|
2
|
+
// Records per-product order demand, driven by Ordering's OrdersExtensionPoint.
|
|
3
|
+
|
|
4
|
+
@@reventless.spec
|
|
5
|
+
|
|
6
|
+
// Not a UI/API command — driven only by Ordering's OrdersExtensionPoint.
|
|
7
|
+
// @noApi removes it from the GraphQL/MCP/AutoUI surface, so the cross-plugin
|
|
8
|
+
// `orderId` is never rendered as a picker and needs no @ref.
|
|
9
|
+
@schema @noApi
|
|
10
|
+
type command =
|
|
11
|
+
| Record({orderId: string})
|
|
12
|
+
| Revoke({orderId: string})
|
|
13
|
+
|
|
14
|
+
@schema
|
|
15
|
+
type event =
|
|
16
|
+
| Recorded({orderId: string})
|
|
17
|
+
| Revoked({orderId: string})
|
|
18
|
+
|
|
19
|
+
@schema
|
|
20
|
+
type error = unit
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ProductDemand aggregate behavior.
|
|
2
|
+
// Idempotently records and revokes order demand per product.
|
|
3
|
+
|
|
4
|
+
@@reventless.behavior
|
|
5
|
+
|
|
6
|
+
@schema
|
|
7
|
+
type state =
|
|
8
|
+
| NotCreated
|
|
9
|
+
| Created({recordedOrderIds: array<string>})
|
|
10
|
+
|
|
11
|
+
let initialState = NotCreated
|
|
12
|
+
|
|
13
|
+
let evolve = (state, event) =>
|
|
14
|
+
switch (state, event) {
|
|
15
|
+
| (NotCreated, Recorded({orderId})) => Created({recordedOrderIds: [orderId]})
|
|
16
|
+
| (Created(s), Recorded({orderId})) =>
|
|
17
|
+
Created({recordedOrderIds: Array.concat(s.recordedOrderIds, [orderId])})
|
|
18
|
+
| (Created(s), Revoked({orderId})) =>
|
|
19
|
+
Created({recordedOrderIds: s.recordedOrderIds->Array.filter(id => id !== orderId)})
|
|
20
|
+
| (NotCreated, Revoked(_)) => state
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let decide = (state, command) =>
|
|
24
|
+
switch (state, command) {
|
|
25
|
+
| (NotCreated, Record({orderId})) => Ok([Recorded({orderId: orderId})])
|
|
26
|
+
| (NotCreated, Revoke(_)) => Ok([]) // nothing recorded yet — idempotent
|
|
27
|
+
| (Created(s), Record({orderId})) =>
|
|
28
|
+
if s.recordedOrderIds->Array.includes(orderId) {
|
|
29
|
+
Ok([]) // idempotent
|
|
30
|
+
} else {
|
|
31
|
+
Ok([Recorded({orderId: orderId})])
|
|
32
|
+
}
|
|
33
|
+
| (Created(s), Revoke({orderId})) =>
|
|
34
|
+
if !(s.recordedOrderIds->Array.includes(orderId)) {
|
|
35
|
+
Ok([]) // idempotent
|
|
36
|
+
} else {
|
|
37
|
+
Ok([Revoked({orderId: orderId})])
|
|
38
|
+
}
|
|
39
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@@reventless.gwt
|
|
2
|
+
|
|
3
|
+
describe("ProductDemand Behavior", () => {
|
|
4
|
+
test("Record on new aggregate produces Recorded", () =>
|
|
5
|
+
givenEvents([])
|
|
6
|
+
->whenCmd(Record({orderId: "order-1"}))
|
|
7
|
+
->thenEvent(Recorded({orderId: "order-1"}))
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
test("Record with new orderId on existing aggregate produces Recorded", () =>
|
|
11
|
+
givenEvents([Recorded({orderId: "order-1"})])
|
|
12
|
+
->whenCmd(Record({orderId: "order-2"}))
|
|
13
|
+
->thenEvent(Recorded({orderId: "order-2"}))
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
test("Record with already-recorded orderId produces no events (idempotent)", () =>
|
|
17
|
+
givenEvents([Recorded({orderId: "order-1"})])
|
|
18
|
+
->whenCmd(Record({orderId: "order-1"}))
|
|
19
|
+
->thenNoEvent
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
test("Revoke on never-recorded aggregate produces no events (idempotent)", () =>
|
|
23
|
+
givenEvents([])
|
|
24
|
+
->whenCmd(Revoke({orderId: "order-1"}))
|
|
25
|
+
->thenNoEvent
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
test("Revoke of unrecorded orderId on existing aggregate produces no events (idempotent)", () =>
|
|
29
|
+
givenEvents([Recorded({orderId: "order-1"})])
|
|
30
|
+
->whenCmd(Revoke({orderId: "order-2"}))
|
|
31
|
+
->thenNoEvent
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
test("Revoke of recorded orderId produces Revoked", () =>
|
|
35
|
+
givenEvents([Recorded({orderId: "order-1"})])
|
|
36
|
+
->whenCmd(Revoke({orderId: "order-1"}))
|
|
37
|
+
->thenEvent(Revoked({orderId: "order-1"}))
|
|
38
|
+
)
|
|
39
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Multi-source ReadModel: separate `_GWT` instances per source mapping.
|
|
2
|
+
// `MultiSourceProjection_GWT.Make` is single-source; spec-stem uniqueness keeps
|
|
3
|
+
// the file name singular while we instantiate one functor per mapping.
|
|
4
|
+
|
|
5
|
+
module ProductGwt = ReventlessGwt.MultiSourceProjection_GWT.Make(
|
|
6
|
+
ProductDemands_Projections.ProductMapping,
|
|
7
|
+
)
|
|
8
|
+
module ProductDemandGwt = ReventlessGwt.MultiSourceProjection_GWT.Make(
|
|
9
|
+
ProductDemands_Projections.ProductDemandMapping,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
ProductGwt.describe("ProductDemands ReadModel ← Product", () => {
|
|
13
|
+
ProductGwt.test("Added initialises the entry with orderCount = 0", () =>
|
|
14
|
+
ProductGwt.givenEvents([])
|
|
15
|
+
->ProductGwt.whenEvent(Product.Added({name: "Laptop", description: "x", price: 1.0}))
|
|
16
|
+
->ProductGwt.thenState({ProductDemands.name: "Laptop", orderCount: 0})
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
ProductGwt.test("NameUpdated is ignored (handled by Products read model)", () =>
|
|
20
|
+
ProductGwt.givenEvents([Product.Added({name: "Laptop", description: "x", price: 1.0})])
|
|
21
|
+
->ProductGwt.whenEvent(Product.NameUpdated({name: "Gaming Laptop"}))
|
|
22
|
+
->ProductGwt.thenState({ProductDemands.name: "Laptop", orderCount: 0})
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
ProductGwt.test("DescriptionUpdated is ignored", () =>
|
|
26
|
+
ProductGwt.givenEvents([Product.Added({name: "Laptop", description: "x", price: 1.0})])
|
|
27
|
+
->ProductGwt.whenEvent(Product.DescriptionUpdated({description: "y"}))
|
|
28
|
+
->ProductGwt.thenState({ProductDemands.name: "Laptop", orderCount: 0})
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
ProductGwt.test("PriceUpdated is ignored", () =>
|
|
32
|
+
ProductGwt.givenEvents([Product.Added({name: "Laptop", description: "x", price: 1.0})])
|
|
33
|
+
->ProductGwt.whenEvent(Product.PriceUpdated({price: 2.0}))
|
|
34
|
+
->ProductGwt.thenState({ProductDemands.name: "Laptop", orderCount: 0})
|
|
35
|
+
)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// `MultiSourceProjection_GWT` is single-source: the ProductDemand mapping
|
|
39
|
+
// emits `Update(...)` that needs initial state seeded by the Product
|
|
40
|
+
// mapping's `Set(...)`. Tested in isolation, both Update branches surface
|
|
41
|
+
// a `StaleState` error. We assert the throw to lock in that the mapping
|
|
42
|
+
// never tries to initialise its own row — the integration relies on
|
|
43
|
+
// Product.Added arriving first.
|
|
44
|
+
ProductDemandGwt.describe("ProductDemands ReadModel ← ProductDemand", () => {
|
|
45
|
+
ProductDemandGwt.test("Recorded without prior Product.Added throws StaleState", () =>
|
|
46
|
+
ProductDemandGwt.givenEvents([])
|
|
47
|
+
->ProductDemandGwt.whenEvent(ProductDemand.Recorded({orderId: "order-1"}))
|
|
48
|
+
->ProductDemandGwt.thenThrow
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
ProductDemandGwt.test("Revoked without prior Product.Added throws StaleState", () =>
|
|
52
|
+
ProductDemandGwt.givenEvents([])
|
|
53
|
+
->ProductDemandGwt.whenEvent(ProductDemand.Revoked({orderId: "order-1"}))
|
|
54
|
+
->ProductDemandGwt.thenThrow
|
|
55
|
+
)
|
|
56
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// ProductDemands projection mappings.
|
|
2
|
+
// Multi-source read model: combines events from two aggregates.
|
|
3
|
+
// Source 1: Product — initialises the entry on Added.
|
|
4
|
+
// Source 2: ProductDemand — increments / decrements the order count.
|
|
5
|
+
@@reventless.mappings
|
|
6
|
+
|
|
7
|
+
module ProductMapping = Mapping.Make(
|
|
8
|
+
Product,
|
|
9
|
+
ProductDemands,
|
|
10
|
+
{
|
|
11
|
+
open Product
|
|
12
|
+
let project = ({event, id, _}) =>
|
|
13
|
+
switch event {
|
|
14
|
+
| Added({name}) =>
|
|
15
|
+
Set(id, {ProductDemands.name: name, orderCount: 0})
|
|
16
|
+
| _ => Ignore
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
module ProductDemandMapping = Mapping.Make(
|
|
22
|
+
ProductDemand,
|
|
23
|
+
ProductDemands,
|
|
24
|
+
{
|
|
25
|
+
open ProductDemand
|
|
26
|
+
let project = ({event, id, _}) =>
|
|
27
|
+
switch event {
|
|
28
|
+
| Recorded(_) =>
|
|
29
|
+
Update(id, (state: ProductDemands.state) => {...state, orderCount: state.orderCount + 1})
|
|
30
|
+
| Revoked(_) =>
|
|
31
|
+
Update(id, (state: ProductDemands.state) => {...state, orderCount: max(0, state.orderCount - 1)})
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
let mappings: array<module(Mapping)> = [module(ProductMapping), module(ProductDemandMapping)]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Product aggregate behavior.
|
|
2
|
+
// Implements the state machine for adding and updating products.
|
|
3
|
+
|
|
4
|
+
@@reventless.behavior
|
|
5
|
+
|
|
6
|
+
@schema
|
|
7
|
+
type state =
|
|
8
|
+
| NotCreated
|
|
9
|
+
| Created({name: string, description: string, price: float})
|
|
10
|
+
|
|
11
|
+
let initialState = NotCreated
|
|
12
|
+
|
|
13
|
+
let evolve = (state, event) =>
|
|
14
|
+
switch (state, event) {
|
|
15
|
+
| (NotCreated, Added({name, description, price})) => Created({name, description, price})
|
|
16
|
+
| (Created(_), Added({name, description, price})) => Created({name, description, price})
|
|
17
|
+
| (Created(s), NameUpdated({name})) => Created({...s, name})
|
|
18
|
+
| (Created(s), DescriptionUpdated({description})) => Created({...s, description})
|
|
19
|
+
| (Created(s), PriceUpdated({price})) => Created({...s, price})
|
|
20
|
+
| (NotCreated, _) => state
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let decide = (state, command) =>
|
|
24
|
+
switch (state, command) {
|
|
25
|
+
| (NotCreated, Add({name, description, price})) =>
|
|
26
|
+
Ok([Added({name, description, price})])
|
|
27
|
+
| (NotCreated, UpdateName(_)) => Error(ProductNotFound)
|
|
28
|
+
| (NotCreated, UpdateDescription(_)) => Error(ProductNotFound)
|
|
29
|
+
| (NotCreated, UpdatePrice(_)) => Error(ProductNotFound)
|
|
30
|
+
| (Created(_), Add(_)) => Error(ProductAlreadyExists)
|
|
31
|
+
| (Created(s), UpdateName({name})) if name == s.name => Ok([])
|
|
32
|
+
| (Created(_), UpdateName({name})) => Ok([NameUpdated({name: name})])
|
|
33
|
+
| (Created(s), UpdateDescription({description})) if description == s.description => Ok([])
|
|
34
|
+
| (Created(_), UpdateDescription({description})) =>
|
|
35
|
+
Ok([DescriptionUpdated({description: description})])
|
|
36
|
+
| (Created(s), UpdatePrice({price})) if price == s.price => Ok([])
|
|
37
|
+
| (Created(_), UpdatePrice({price})) => Ok([PriceUpdated({price: price})])
|
|
38
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
@@reventless.gwt
|
|
2
|
+
|
|
3
|
+
describe("Product Behavior", () => {
|
|
4
|
+
test("Add on new aggregate produces Added", () =>
|
|
5
|
+
givenEvents([])
|
|
6
|
+
->whenCmd(Add({name: "Laptop", description: "A laptop", price: 999.99}))
|
|
7
|
+
->thenEvent(Added({name: "Laptop", description: "A laptop", price: 999.99}))
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
test("Add on existing aggregate returns ProductAlreadyExists", () =>
|
|
11
|
+
givenEvents([Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
12
|
+
->whenCmd(Add({name: "Laptop 2", description: "Another", price: 1.0}))
|
|
13
|
+
->thenError(ProductAlreadyExists)
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
test("UpdateName on non-existent aggregate returns ProductNotFound", () =>
|
|
17
|
+
givenEvents([])
|
|
18
|
+
->whenCmd(UpdateName({name: "New Name"}))
|
|
19
|
+
->thenError(ProductNotFound)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
test("UpdateName on existing product produces NameUpdated", () =>
|
|
23
|
+
givenEvents([Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
24
|
+
->whenCmd(UpdateName({name: "Gaming Laptop"}))
|
|
25
|
+
->thenEvent(NameUpdated({name: "Gaming Laptop"}))
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
test("UpdateName to same name produces no events (idempotent)", () =>
|
|
29
|
+
givenEvents([Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
30
|
+
->whenCmd(UpdateName({name: "Laptop"}))
|
|
31
|
+
->thenNoEvent
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
test("UpdateDescription on non-existent aggregate returns ProductNotFound", () =>
|
|
35
|
+
givenEvents([])
|
|
36
|
+
->whenCmd(UpdateDescription({description: "x"}))
|
|
37
|
+
->thenError(ProductNotFound)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
test("UpdateDescription on existing product produces DescriptionUpdated", () =>
|
|
41
|
+
givenEvents([Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
42
|
+
->whenCmd(UpdateDescription({description: "A high-end laptop"}))
|
|
43
|
+
->thenEvent(DescriptionUpdated({description: "A high-end laptop"}))
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
test("UpdateDescription to same description produces no events (idempotent)", () =>
|
|
47
|
+
givenEvents([Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
48
|
+
->whenCmd(UpdateDescription({description: "A laptop"}))
|
|
49
|
+
->thenNoEvent
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
test("UpdatePrice on non-existent aggregate returns ProductNotFound", () =>
|
|
53
|
+
givenEvents([])
|
|
54
|
+
->whenCmd(UpdatePrice({price: 1.0}))
|
|
55
|
+
->thenError(ProductNotFound)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
test("UpdatePrice on existing product produces PriceUpdated", () =>
|
|
59
|
+
givenEvents([Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
60
|
+
->whenCmd(UpdatePrice({price: 899.99}))
|
|
61
|
+
->thenEvent(PriceUpdated({price: 899.99}))
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
test("UpdatePrice to same price produces no events (idempotent)", () =>
|
|
65
|
+
givenEvents([Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
66
|
+
->whenCmd(UpdatePrice({price: 999.99}))
|
|
67
|
+
->thenNoEvent
|
|
68
|
+
)
|
|
69
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Maps internal Product aggregate events to the stable ProductsExtensionPoint public API.
|
|
2
|
+
@@reventless.spec
|
|
3
|
+
|
|
4
|
+
module ExtensionPoint = CatalogSpec.Products_ExtensionPoint
|
|
5
|
+
module Delegate = Product
|
|
6
|
+
|
|
7
|
+
let mapIncomingCommand = (_id, _command, _meta) => []
|
|
8
|
+
|
|
9
|
+
let mapOutgoingEvent = Some((id, event, _meta, _queryEngine) =>
|
|
10
|
+
switch event {
|
|
11
|
+
| Product.Added({name, price}) => [
|
|
12
|
+
PublishEvent(id, CatalogSpec.Products_ExtensionPoint.ProductBecameAvailable({productId: id, name, price})),
|
|
13
|
+
]
|
|
14
|
+
| Product.PriceUpdated({price}) => [
|
|
15
|
+
PublishEvent(id, CatalogSpec.Products_ExtensionPoint.ProductPriceChanged({productId: id, price})),
|
|
16
|
+
]
|
|
17
|
+
| _ => []
|
|
18
|
+
}
|
|
19
|
+
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Boundary GWT for the Products extension point: internal Product aggregate
|
|
2
|
+
// events become the stable public events Ordering subscribes to.
|
|
3
|
+
@@reventless.gwt
|
|
4
|
+
|
|
5
|
+
describe("Products ExtensionPoint mapping", () => {
|
|
6
|
+
test("Added publishes ProductBecameAvailable", () =>
|
|
7
|
+
whenDelegateEvent(
|
|
8
|
+
Delegate.Added({name: "Book", description: "A good book", price: 9.99}),
|
|
9
|
+
)->thenPublishesEvent(
|
|
10
|
+
"gwt-id",
|
|
11
|
+
ExtensionPoint.ProductBecameAvailable({productId: "gwt-id", name: "Book", price: 9.99}),
|
|
12
|
+
)
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
test("PriceUpdated publishes ProductPriceChanged", () =>
|
|
16
|
+
whenDelegateEvent(Delegate.PriceUpdated({price: 7.5}))->thenPublishesEvent(
|
|
17
|
+
"gwt-id",
|
|
18
|
+
ExtensionPoint.ProductPriceChanged({productId: "gwt-id", price: 7.5}),
|
|
19
|
+
)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
test("NameUpdated publishes nothing", () =>
|
|
23
|
+
whenDelegateEvent(Delegate.NameUpdated({name: "Better Book"}))->thenPublishesNothing
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
test("DescriptionUpdated publishes nothing", () =>
|
|
27
|
+
whenDelegateEvent(
|
|
28
|
+
Delegate.DescriptionUpdated({description: "A really good book"}),
|
|
29
|
+
)->thenPublishesNothing
|
|
30
|
+
)
|
|
31
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
@@reventless.gwt(Products_Projections.ProductMapping)
|
|
2
|
+
|
|
3
|
+
describe("Products ReadModel ← Product", () => {
|
|
4
|
+
test("Added sets initial read model state", () =>
|
|
5
|
+
givenEvents([])
|
|
6
|
+
->whenEvent(Product.Added({name: "Laptop", description: "A laptop", price: 999.99}))
|
|
7
|
+
->thenState({Products.name: "Laptop", description: "A laptop", price: 999.99})
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
test("NameUpdated updates the name", () =>
|
|
11
|
+
givenEvents([Product.Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
12
|
+
->whenEvent(Product.NameUpdated({name: "Gaming Laptop"}))
|
|
13
|
+
->thenState({Products.name: "Gaming Laptop", description: "A laptop", price: 999.99})
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
test("DescriptionUpdated updates the description", () =>
|
|
17
|
+
givenEvents([Product.Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
18
|
+
->whenEvent(Product.DescriptionUpdated({description: "A high-end laptop"}))
|
|
19
|
+
->thenState({Products.name: "Laptop", description: "A high-end laptop", price: 999.99})
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
test("PriceUpdated updates the price", () =>
|
|
23
|
+
givenEvents([Product.Added({name: "Laptop", description: "A laptop", price: 999.99})])
|
|
24
|
+
->whenEvent(Product.PriceUpdated({price: 899.99}))
|
|
25
|
+
->thenState({Products.name: "Laptop", description: "A laptop", price: 899.99})
|
|
26
|
+
)
|
|
27
|
+
})
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|