@reventlessdev/reventless-core 3.0.0-alpha.250 → 3.0.0-alpha.251

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.
@@ -1747,3 +1747,112 @@ describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1747
1747
  })
1748
1748
  })
1749
1749
  })
1750
+
1751
+ // The port's translation table — the pure halves of the check. The probe itself
1752
+ // needs a mapping module and is exercised by the examples' own build.
1753
+ describe("the port's translation table", () => {
1754
+ let published = (name, fromEventTypes): ReventlessInfra.ExtensionPointMapping.publishedEvent => {
1755
+ name,
1756
+ fromEventTypes,
1757
+ }
1758
+ let failures = (~declared) =>
1759
+ Plugin_Structure.translationTableFailures(
1760
+ ~label="Catalog.Products ← Product",
1761
+ ~declared,
1762
+ ~publishedNames=["ProductBecameAvailable", "ProductWithdrawn"],
1763
+ ~sourceNames=["Added", "Archived", "Discontinued", "Renamed"],
1764
+ )
1765
+
1766
+ testSync("accepts a many-to-one declaration", () =>
1767
+ expect(
1768
+ failures(~declared=[published("ProductWithdrawn", ["Archived", "Discontinued"])])->Array.length,
1769
+ )->toBe(0)
1770
+ )
1771
+
1772
+ testSync("rejects a published name the extension point does not declare", () =>
1773
+ expect(
1774
+ failures(~declared=[published("ProductRetired", ["Archived"])])->Array.length,
1775
+ )->toBe(1)
1776
+ )
1777
+
1778
+ testSync("rejects a source name the delegate does not declare", () =>
1779
+ expect(
1780
+ failures(~declared=[published("ProductWithdrawn", ["Archivd"])])->Array.length,
1781
+ )->toBe(1)
1782
+ )
1783
+
1784
+ })
1785
+
1786
+ describe("the translation table against the probe", () => {
1787
+ let declared = [
1788
+ ({
1789
+ ReventlessInfra.ExtensionPointMapping.name: "ProductWithdrawn",
1790
+ fromEventTypes: ["Archived", "Discontinued"],
1791
+ }: ReventlessInfra.ExtensionPointMapping.publishedEvent),
1792
+ ]
1793
+ let drift = (~observed, ~followed) =>
1794
+ Plugin_Structure.translationTableDrift(~label="EP", ~declared, ~observed, ~followed)
1795
+
1796
+ testSync("says nothing when the arms produce what was declared", () => {
1797
+ let (failures, warnings) = drift(
1798
+ ~observed=[("Archived", "ProductWithdrawn"), ("Discontinued", "ProductWithdrawn")],
1799
+ ~followed=["Archived", "Discontinued"],
1800
+ )
1801
+ expect((failures->Array.length, warnings->Array.length))->toEqual((0, 0))
1802
+ })
1803
+
1804
+ // The probe watched the arm publish it, so the declaration is stale.
1805
+ testSync("fails on an edge the probe saw and the declaration omits", () => {
1806
+ let (failures, _) = drift(
1807
+ ~observed=[("Archived", "ProductRelisted")],
1808
+ ~followed=["Archived"],
1809
+ )
1810
+ expect(failures->Array.length)->toBe(1)
1811
+ })
1812
+
1813
+ // The arm may branch on a payload the probe cannot synthesise.
1814
+ testSync("only warns on a declared edge the probe did not see", () => {
1815
+ let (failures, warnings) = drift(
1816
+ ~observed=[("Archived", "ProductWithdrawn")],
1817
+ ~followed=["Archived", "Discontinued"],
1818
+ )
1819
+ expect((failures->Array.length, warnings->Array.length))->toEqual((0, 1))
1820
+ })
1821
+
1822
+ // "Did not look" must not read as "no edge".
1823
+ testSync("judges nothing about a source the probe could not follow", () => {
1824
+ let (failures, warnings) = drift(~observed=[], ~followed=[])
1825
+ expect((failures->Array.length, warnings->Array.length))->toEqual((0, 0))
1826
+ })
1827
+ })
1828
+
1829
+ describe("the subscriber's half of the table", () => {
1830
+ let handled = (name, toCommandTypes): ReventlessInfra.ExtensionMapping.handledEvent => {
1831
+ name,
1832
+ toCommandTypes,
1833
+ }
1834
+ let failures = declared =>
1835
+ Plugin_Structure.handledTableFailures(
1836
+ ~label="Catalog.Products → SyncCatalogProduct",
1837
+ ~declared,
1838
+ ~eventNames=["ProductBecameAvailable"],
1839
+ // The delegate's commands and the extension point's own, resolved as one set.
1840
+ ~commandNames=["SyncNewProduct", "AckProduct"],
1841
+ )
1842
+
1843
+ testSync("accepts a delegate command and an extension point command alike", () =>
1844
+ expect(
1845
+ failures([handled("ProductBecameAvailable", ["SyncNewProduct", "AckProduct"])])->Array.length,
1846
+ )->toBe(0)
1847
+ )
1848
+
1849
+ testSync("rejects a handled event the extension point does not publish", () =>
1850
+ expect(failures([handled("ProductAdded", ["SyncNewProduct"])])->Array.length)->toBe(1)
1851
+ )
1852
+
1853
+ testSync("rejects a command neither side declares", () =>
1854
+ expect(
1855
+ failures([handled("ProductBecameAvailable", ["SyncNewProdct"])])->Array.length,
1856
+ )->toBe(1)
1857
+ )
1858
+ })
@@ -1731,6 +1731,133 @@ globalThis.describe("Plugin_Structure.make — Phase 2 graph fields", () => {
1731
1731
  });
1732
1732
  });
1733
1733
 
1734
+ globalThis.describe("the port's translation table", () => {
1735
+ let failures = declared => Plugin_Structure$ReventlessCore.translationTableFailures("Catalog.Products ← Product", declared, [
1736
+ "ProductBecameAvailable",
1737
+ "ProductWithdrawn"
1738
+ ], [
1739
+ "Added",
1740
+ "Archived",
1741
+ "Discontinued",
1742
+ "Renamed"
1743
+ ]);
1744
+ globalThis.test("accepts a many-to-one declaration", () => {
1745
+ globalThis.expect(failures([{
1746
+ name: "ProductWithdrawn",
1747
+ fromEventTypes: [
1748
+ "Archived",
1749
+ "Discontinued"
1750
+ ]
1751
+ }]).length).toBe(0);
1752
+ });
1753
+ globalThis.test("rejects a published name the extension point does not declare", () => {
1754
+ globalThis.expect(failures([{
1755
+ name: "ProductRetired",
1756
+ fromEventTypes: ["Archived"]
1757
+ }]).length).toBe(1);
1758
+ });
1759
+ globalThis.test("rejects a source name the delegate does not declare", () => {
1760
+ globalThis.expect(failures([{
1761
+ name: "ProductWithdrawn",
1762
+ fromEventTypes: ["Archivd"]
1763
+ }]).length).toBe(1);
1764
+ });
1765
+ });
1766
+
1767
+ globalThis.describe("the translation table against the probe", () => {
1768
+ let declared = [{
1769
+ name: "ProductWithdrawn",
1770
+ fromEventTypes: [
1771
+ "Archived",
1772
+ "Discontinued"
1773
+ ]
1774
+ }];
1775
+ let drift = (observed, followed) => Plugin_Structure$ReventlessCore.translationTableDrift("EP", declared, observed, followed);
1776
+ globalThis.test("says nothing when the arms produce what was declared", () => {
1777
+ let match = drift([
1778
+ [
1779
+ "Archived",
1780
+ "ProductWithdrawn"
1781
+ ],
1782
+ [
1783
+ "Discontinued",
1784
+ "ProductWithdrawn"
1785
+ ]
1786
+ ], [
1787
+ "Archived",
1788
+ "Discontinued"
1789
+ ]);
1790
+ globalThis.expect([
1791
+ match[0].length,
1792
+ match[1].length
1793
+ ]).toEqual([
1794
+ 0,
1795
+ 0
1796
+ ]);
1797
+ });
1798
+ globalThis.test("fails on an edge the probe saw and the declaration omits", () => {
1799
+ let match = drift([[
1800
+ "Archived",
1801
+ "ProductRelisted"
1802
+ ]], ["Archived"]);
1803
+ globalThis.expect(match[0].length).toBe(1);
1804
+ });
1805
+ globalThis.test("only warns on a declared edge the probe did not see", () => {
1806
+ let match = drift([[
1807
+ "Archived",
1808
+ "ProductWithdrawn"
1809
+ ]], [
1810
+ "Archived",
1811
+ "Discontinued"
1812
+ ]);
1813
+ globalThis.expect([
1814
+ match[0].length,
1815
+ match[1].length
1816
+ ]).toEqual([
1817
+ 0,
1818
+ 1
1819
+ ]);
1820
+ });
1821
+ globalThis.test("judges nothing about a source the probe could not follow", () => {
1822
+ let match = drift([], []);
1823
+ globalThis.expect([
1824
+ match[0].length,
1825
+ match[1].length
1826
+ ]).toEqual([
1827
+ 0,
1828
+ 0
1829
+ ]);
1830
+ });
1831
+ });
1832
+
1833
+ globalThis.describe("the subscriber's half of the table", () => {
1834
+ let failures = declared => Plugin_Structure$ReventlessCore.handledTableFailures("Catalog.Products → SyncCatalogProduct", declared, ["ProductBecameAvailable"], [
1835
+ "SyncNewProduct",
1836
+ "AckProduct"
1837
+ ]);
1838
+ globalThis.test("accepts a delegate command and an extension point command alike", () => {
1839
+ globalThis.expect(failures([{
1840
+ name: "ProductBecameAvailable",
1841
+ toCommandTypes: [
1842
+ "SyncNewProduct",
1843
+ "AckProduct"
1844
+ ]
1845
+ }]).length).toBe(0);
1846
+ });
1847
+ globalThis.test("rejects a handled event the extension point does not publish", () => {
1848
+ globalThis.expect(failures([{
1849
+ name: "ProductAdded",
1850
+ toCommandTypes: ["SyncNewProduct"]
1851
+ }]).length).toBe(1);
1852
+ });
1853
+ globalThis.test("rejects a command neither side declares", () => {
1854
+ globalThis.expect(failures([{
1855
+ name: "ProductBecameAvailable",
1856
+ toCommandTypes: ["SyncNewProdct"]
1857
+ }]).length).toBe(1);
1858
+ });
1859
+ });
1860
+
1734
1861
  export {
1735
1862
  PsPlaceOrderSlice,
1736
1863
  PsShipOrderSlice,
@@ -74,13 +74,21 @@
74
74
  .structure.automationSlices[].name: string
75
75
  .structure.automationSlices[].producedCommandTypes[]: string
76
76
  .structure.automationSlices[].targetName: string
77
+ .structure.extensionPoints[].acceptedCommands[].name: string
78
+ .structure.extensionPoints[].acceptedCommands[].toCommandTypes[]: string
77
79
  .structure.extensionPoints[].commandTypes[]: string
78
80
  .structure.extensionPoints[].delegateNames[]: string
79
81
  .structure.extensionPoints[].name: string
82
+ .structure.extensionPoints[].publishedEvents[].fromEventTypes[]: string
83
+ .structure.extensionPoints[].publishedEvents[].name: string
80
84
  .structure.extensionPoints[].sourceEventTypes[]: string
81
85
  .structure.extensions[].commandTypes[]: string
82
86
  .structure.extensions[].delegateNames[]: string
83
87
  .structure.extensions[].eventTypes[]: string
88
+ .structure.extensions[].handledEvents[].name: string
89
+ .structure.extensions[].handledEvents[].toCommandTypes[]: string
90
+ .structure.extensions[].issuedCommands[].fromEventTypes[]: string
91
+ .structure.extensions[].issuedCommands[].name: string
84
92
  .structure.extensions[].name: string
85
93
  .structure.inboundTranslationSlices[].commandTypes[]: string
86
94
  .structure.inboundTranslationSlices[].name: string