@reventlessdev/reventless-core 3.0.0-alpha.249 → 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.
- package/CHANGELOG.md +32 -0
- package/package.json +9 -9
- package/src/admin/Platform_ComponentDefinitionsApi.res +31 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +29 -1
- package/src/admin/Platform_PluginStructuresApi.res +37 -1
- package/src/admin/Platform_PluginStructuresApi.res.mjs +29 -1
- package/src/components/Api/QueryDbListQuery.res +26 -6
- package/src/components/Api/QueryDbListQuery.res.mjs +12 -5
- package/src/plugin/component/Plugin_Structure.res +620 -370
- package/src/plugin/component/Plugin_Structure.res.mjs +341 -3
- package/src/plugin/connect/PluginConnectExtension_Mapping.res +3 -6
- package/src/plugin/connect/PluginConnectExtension_Mapping.res.mjs +11 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res +0 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +60 -2
- package/src/plugin/connect/PluginExtensionPoint_UiFragment.res.mjs +19 -2
- package/tests/admin/AdminApiSchemaDriftTest.res +460 -0
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +599 -0
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +6 -0
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +9 -1
- package/tests/admin/Platform_PluginStructuresApiTest.res +12 -1
- package/tests/admin/Platform_PluginStructuresApiTest.res.mjs +10 -2
- package/tests/plugin/PluginStructureTest.res +109 -0
- package/tests/plugin/PluginStructureTest.res.mjs +127 -0
- package/tests/plugin/pluginDefinitionRequiredScalars.txt +8 -0
|
@@ -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
|