@reventlessdev/reventless-aws 3.0.0-alpha.232 → 3.0.0-alpha.234

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.
Files changed (110) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/package.json +7 -7
  3. package/src/adapter/Api/AppSyncEventsSigner_Ops.res +137 -0
  4. package/src/adapter/Api/AppSyncEventsSigner_Ops.res.mjs +121 -0
  5. package/src/adapter/Api/Platform_AdminScan_Ops.res +136 -0
  6. package/src/adapter/Api/Platform_AdminScan_Ops.res.mjs +98 -0
  7. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +12 -90
  8. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +11 -84
  9. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +86 -0
  10. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res.mjs +79 -0
  11. package/src/adapter/Api/Platform_UIFragments_Lambda.res +9 -79
  12. package/src/adapter/Api/Platform_UIFragments_Lambda.res.mjs +7 -143
  13. package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +48 -0
  14. package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res.mjs +63 -0
  15. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +21 -80
  16. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +23 -68
  17. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +70 -0
  18. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res.mjs +68 -0
  19. package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +1 -1
  20. package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res.mjs +1 -1
  21. package/src/adapter/Postgres/PgMigration_Builder.res +1 -1
  22. package/src/adapter/Postgres/PgMigration_Builder.res.mjs +1 -1
  23. package/src/adapter/Runtime/AutomationSliceEntryPoint.mjs +42 -126
  24. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +246 -0
  25. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res.mjs +145 -0
  26. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +27 -2
  27. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +10 -3
  28. package/src/adapter/Runtime/CounterEntryPoint.mjs +19 -73
  29. package/src/adapter/Runtime/CounterEntryPoint_Ops.res +145 -0
  30. package/src/adapter/Runtime/CounterEntryPoint_Ops.res.mjs +129 -0
  31. package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +14 -1
  32. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +22 -2
  33. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +15 -4
  34. package/src/adapter/Runtime/EventCollectorEntryPoint.mjs +52 -510
  35. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +816 -0
  36. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res.mjs +651 -0
  37. package/src/adapter/Runtime/EventMapperEntryPoint.mjs +23 -67
  38. package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +126 -0
  39. package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res.mjs +83 -0
  40. package/src/adapter/Runtime/ExtensionPointEntryPoint.mjs +16 -63
  41. package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +150 -0
  42. package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res.mjs +111 -0
  43. package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +96 -0
  44. package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res.mjs +70 -0
  45. package/src/adapter/Runtime/PgMigrationEntryPoint.res +54 -0
  46. package/src/adapter/Runtime/PgMigrationEntryPoint.res.mjs +37 -0
  47. package/src/adapter/Runtime/PgQueryResolverEntryPoint.mjs +20 -55
  48. package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +155 -0
  49. package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res.mjs +94 -0
  50. package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +80 -0
  51. package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res.mjs +39 -0
  52. package/src/adapter/Runtime/QueryDbEntryPoint_Ops.res +4 -4
  53. package/src/adapter/Runtime/ReadModelEntryPoint.mjs +34 -153
  54. package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res +114 -0
  55. package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res.mjs +83 -0
  56. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +26 -6
  57. package/src/adapter/Runtime/SideEffectEntryPoint.mjs +23 -64
  58. package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res +71 -0
  59. package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res.mjs +57 -0
  60. package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +5 -2
  61. package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +1 -1
  62. package/src/adapter/Runtime/StateViewSliceEntryPoint.mjs +34 -165
  63. package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +206 -0
  64. package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res.mjs +105 -0
  65. package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +156 -0
  66. package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res.mjs +123 -0
  67. package/src/adapter/Runtime/TaskBucketEntryPoint.mjs +18 -138
  68. package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +198 -0
  69. package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res.mjs +155 -0
  70. package/src/adapter/StateTopic/StateTopic_AppSync.res +12 -170
  71. package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +7 -167
  72. package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +208 -0
  73. package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res.mjs +183 -0
  74. package/src/components/AutomationSlice_Builder.res +2 -0
  75. package/src/components/AutomationSlice_Builder.res.mjs +1 -1
  76. package/src/components/OutboundTranslationSlice_Builder.res +1 -0
  77. package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
  78. package/src/plugin/runtime/PluginRuntime_Builder.res +13 -4
  79. package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +1 -1
  80. package/tests/AppSyncEventsSigner_OpsTest.res +75 -0
  81. package/tests/AppSyncEventsSigner_OpsTest.res.mjs +44 -0
  82. package/tests/AppSyncEventsSigner_ParityFixture.mjs +36 -0
  83. package/tests/AutomationSliceEntryPoint_OpsTest.res +165 -0
  84. package/tests/AutomationSliceEntryPoint_OpsTest.res.mjs +280 -0
  85. package/tests/CounterEntryPoint_OpsTest.res +115 -0
  86. package/tests/CounterEntryPoint_OpsTest.res.mjs +150 -0
  87. package/tests/EventCollectorEntryPoint_OpsTest.res +216 -0
  88. package/tests/EventCollectorEntryPoint_OpsTest.res.mjs +339 -0
  89. package/tests/EventMapperEntryPoint_OpsTest.res +103 -0
  90. package/tests/EventMapperEntryPoint_OpsTest.res.mjs +120 -0
  91. package/tests/ExtensionPointEntryPoint_OpsTest.res +57 -0
  92. package/tests/ExtensionPointEntryPoint_OpsTest.res.mjs +54 -0
  93. package/tests/PgMigrationEntryPoint_IntegrationTest.res +22 -31
  94. package/tests/PgMigrationEntryPoint_IntegrationTest.res.mjs +20 -23
  95. package/tests/PgQueryResolverEntryPoint_OpsTest.res +38 -0
  96. package/tests/PgQueryResolverEntryPoint_OpsTest.res.mjs +31 -0
  97. package/tests/Platform_AdminScan_OpsTest.res +80 -0
  98. package/tests/Platform_AdminScan_OpsTest.res.mjs +127 -0
  99. package/tests/ReadModelEntryPoint_OpsTest.res +141 -0
  100. package/tests/ReadModelEntryPoint_OpsTest.res.mjs +267 -0
  101. package/tests/SideEffectEntryPoint_OpsTest.res +79 -0
  102. package/tests/SideEffectEntryPoint_OpsTest.res.mjs +105 -0
  103. package/tests/StateViewSliceEntryPoint_OpsTest.res +167 -0
  104. package/tests/StateViewSliceEntryPoint_OpsTest.res.mjs +296 -0
  105. package/tests/TaskBucketEntryPoint_OpsTest.res +117 -0
  106. package/tests/TaskBucketEntryPoint_OpsTest.res.mjs +165 -0
  107. package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +42 -13
  108. package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res.mjs +29 -6
  109. package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.mjs +0 -57
  110. package/src/adapter/Runtime/PgMigrationEntryPoint.mjs +0 -40
@@ -0,0 +1,141 @@
1
+ // Guards the typed cold-start core hoisted out of ReadModelEntryPoint.mjs:
2
+ // - parseHandlerConfig — the HANDLER_CONFIG contract every read-model Lambda
3
+ // cold-starts on, incl. the optional attribution (comp/plugin) and backend
4
+ // (pgConnection/stateTopicName) fields.
5
+ // - injectId / withInjectedId — the id-injection wrap on save/saveBatch;
6
+ // query resolvers and the live-update publisher read `id` off the row, so
7
+ // silently dropping the injection would strand every list query.
8
+
9
+ open JestGlobals
10
+
11
+ let str = JSON.Encode.string
12
+ let obj = pairs => JSON.Encode.object(Dict.fromArray(pairs))
13
+
14
+ describe("ReadModelEntryPoint_Ops.parseHandlerConfig", () => {
15
+ testSync("empty raw config yields no handlers", () => {
16
+ expect(ReadModelEntryPoint_Ops.parseHandlerConfig("")->Array.length)->toBe(0)
17
+ expect(ReadModelEntryPoint_Ops.parseHandlerConfig(`{"handlers":[]}`)->Array.length)->toBe(0)
18
+ })
19
+
20
+ testSync("decodes a full entry incl. attribution and Postgres fields", () => {
21
+ let config = obj([
22
+ (
23
+ "handlers",
24
+ JSON.Encode.array([
25
+ obj([
26
+ ("specModule", str("@x/spec/src/ReadModel/Products.res.mjs")),
27
+ ("mappingsModule", str("@x/spec/src/ReadModel/Products_Projections.res.mjs")),
28
+ ("queryDbTableName", str("Products-abc")),
29
+ ("sourceUrn", str("arn:aws:sqs:eu-west-1:1:q")),
30
+ ("comp", str("EventCollector(ProductsEC)")),
31
+ ("plugin", str("Catalog")),
32
+ ("stateTopicName", str("catalogProducts")),
33
+ (
34
+ "pgConnection",
35
+ obj([
36
+ ("host", str("db.local")),
37
+ ("port", JSON.Encode.int(5432)),
38
+ ("database", str("app")),
39
+ ("username", str("master")),
40
+ ("secretArn", str("arn:secret")),
41
+ ]),
42
+ ),
43
+ ]),
44
+ ]),
45
+ ),
46
+ ])->JSON.stringify
47
+ let entries = ReadModelEntryPoint_Ops.parseHandlerConfig(config)
48
+ expect(entries->Array.length)->toBe(1)
49
+ let e = entries->Array.getUnsafe(0)
50
+ expect(e.specModule)->toBe("@x/spec/src/ReadModel/Products.res.mjs")
51
+ expect(e.mappingsModule)->toBe("@x/spec/src/ReadModel/Products_Projections.res.mjs")
52
+ expect(e.queryDbTableName)->toBe("Products-abc")
53
+ expect(e.sourceUrn)->toBe("arn:aws:sqs:eu-west-1:1:q")
54
+ expect(e.comp)->toEqual(Some("EventCollector(ProductsEC)"))
55
+ expect(e.plugin)->toEqual(Some("Catalog"))
56
+ expect(e.stateTopicName)->toEqual(Some("catalogProducts"))
57
+ switch e.pgConnection {
58
+ | Some(cc) => {
59
+ expect(cc.host)->toBe("db.local")
60
+ expect(cc.port)->toBe(5432)
61
+ expect(cc.database)->toBe("app")
62
+ }
63
+ | None => JsError.throwWithMessage("expected Some(pgConnection)")
64
+ }
65
+ })
66
+
67
+ testSync("optional fields default to None; null pgConnection maps to None", () => {
68
+ let config = obj([
69
+ (
70
+ "handlers",
71
+ JSON.Encode.array([
72
+ obj([
73
+ ("specModule", str("a.res.mjs")),
74
+ ("mappingsModule", str("b.res.mjs")),
75
+ ("queryDbTableName", str("t")),
76
+ ("sourceUrn", str("u")),
77
+ ("pgConnection", JSON.Null),
78
+ ]),
79
+ ]),
80
+ ),
81
+ ])->JSON.stringify
82
+ let e = ReadModelEntryPoint_Ops.parseHandlerConfig(config)->Array.getUnsafe(0)
83
+ expect(e.comp->Option.isNone)->toBe(true)
84
+ expect(e.plugin->Option.isNone)->toBe(true)
85
+ expect(e.stateTopicName->Option.isNone)->toBe(true)
86
+ expect(e.pgConnection->Option.isNone)->toBe(true)
87
+ })
88
+ })
89
+
90
+ describe("ReadModelEntryPoint_Ops.injectId", () => {
91
+ testSync("injects (and overwrites) id on object states", () => {
92
+ expect(ReadModelEntryPoint_Ops.injectId("p-1", obj([("name", str("Widget"))])))->toEqual(
93
+ obj([("name", str("Widget")), ("id", str("p-1"))]),
94
+ )
95
+ expect(ReadModelEntryPoint_Ops.injectId("p-1", obj([("id", str("stale"))])))->toEqual(
96
+ obj([("id", str("p-1"))]),
97
+ )
98
+ })
99
+
100
+ testSync("passes non-object states through unchanged", () => {
101
+ expect(ReadModelEntryPoint_Ops.injectId("p-1", str("scalar")))->toEqual(str("scalar"))
102
+ expect(
103
+ ReadModelEntryPoint_Ops.injectId("p-1", JSON.Encode.array([str("a")])),
104
+ )->toEqual(JSON.Encode.array([str("a")]))
105
+ expect(ReadModelEntryPoint_Ops.injectId("p-1", JSON.Null))->toEqual(JSON.Null)
106
+ })
107
+ })
108
+
109
+ describe("ReadModelEntryPoint_Ops.withInjectedId", () => {
110
+ // Capturing stub operation set — only save/saveBatch matter for the wrap.
111
+ let makeStub = (saved: array<(string, JSON.t)>): ReventlessCore.QueryDb_Adapter.operations => {
112
+ load: async _ => Ok([]),
113
+ loadStream: _ => Stream.fromIterable([]),
114
+ save: async (id, state, _mode, _ttl) => {
115
+ saved->Array.push((id, state))
116
+ Ok()
117
+ },
118
+ saveBatch: async items => {
119
+ items->Array.forEach(((id, state, _ttl)) => saved->Array.push((id, state)))
120
+ Ok()
121
+ },
122
+ count: async (_, _, _) => Ok(0),
123
+ delete: async (_, _) => Ok(),
124
+ deleteBatch: async _ => Ok(),
125
+ }
126
+
127
+ test("save and saveBatch write id-injected states", async () => {
128
+ let saved = []
129
+ let ops = ReadModelEntryPoint_Ops.withInjectedId(makeStub(saved))
130
+ let _ = await ops.save("p-1", obj([("name", str("A"))]), ReventlessCore.QueryDb.Any, None)
131
+ let _ = await ops.saveBatch([
132
+ ("p-2", obj([("name", str("B"))]), None),
133
+ ("p-3", str("scalar"), None),
134
+ ])
135
+ expect(saved)->toEqual([
136
+ ("p-1", obj([("name", str("A")), ("id", str("p-1"))])),
137
+ ("p-2", obj([("name", str("B")), ("id", str("p-2"))])),
138
+ ("p-3", str("scalar")),
139
+ ])
140
+ })
141
+ })
@@ -0,0 +1,267 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+ import * as Stream from "effect/Stream";
5
+ import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
6
+ import * as ReadModelEntryPoint_Ops$ReventlessAws from "../src/adapter/Runtime/ReadModelEntryPoint_Ops.res.mjs";
7
+
8
+ function str(prim) {
9
+ return prim;
10
+ }
11
+
12
+ function obj(pairs) {
13
+ return Object.fromEntries(pairs);
14
+ }
15
+
16
+ globalThis.describe("ReadModelEntryPoint_Ops.parseHandlerConfig", () => {
17
+ globalThis.test("empty raw config yields no handlers", () => {
18
+ globalThis.expect(ReadModelEntryPoint_Ops$ReventlessAws.parseHandlerConfig("").length).toBe(0);
19
+ globalThis.expect(ReadModelEntryPoint_Ops$ReventlessAws.parseHandlerConfig(`{"handlers":[]}`).length).toBe(0);
20
+ });
21
+ globalThis.test("decodes a full entry incl. attribution and Postgres fields", () => {
22
+ let config = JSON.stringify(Object.fromEntries([[
23
+ "handlers",
24
+ [Object.fromEntries([
25
+ [
26
+ "specModule",
27
+ "@x/spec/src/ReadModel/Products.res.mjs"
28
+ ],
29
+ [
30
+ "mappingsModule",
31
+ "@x/spec/src/ReadModel/Products_Projections.res.mjs"
32
+ ],
33
+ [
34
+ "queryDbTableName",
35
+ "Products-abc"
36
+ ],
37
+ [
38
+ "sourceUrn",
39
+ "arn:aws:sqs:eu-west-1:1:q"
40
+ ],
41
+ [
42
+ "comp",
43
+ "EventCollector(ProductsEC)"
44
+ ],
45
+ [
46
+ "plugin",
47
+ "Catalog"
48
+ ],
49
+ [
50
+ "stateTopicName",
51
+ "catalogProducts"
52
+ ],
53
+ [
54
+ "pgConnection",
55
+ Object.fromEntries([
56
+ [
57
+ "host",
58
+ "db.local"
59
+ ],
60
+ [
61
+ "port",
62
+ 5432
63
+ ],
64
+ [
65
+ "database",
66
+ "app"
67
+ ],
68
+ [
69
+ "username",
70
+ "master"
71
+ ],
72
+ [
73
+ "secretArn",
74
+ "arn:secret"
75
+ ]
76
+ ])
77
+ ]
78
+ ])]
79
+ ]]));
80
+ let entries = ReadModelEntryPoint_Ops$ReventlessAws.parseHandlerConfig(config);
81
+ globalThis.expect(entries.length).toBe(1);
82
+ let e = entries[0];
83
+ globalThis.expect(e.specModule).toBe("@x/spec/src/ReadModel/Products.res.mjs");
84
+ globalThis.expect(e.mappingsModule).toBe("@x/spec/src/ReadModel/Products_Projections.res.mjs");
85
+ globalThis.expect(e.queryDbTableName).toBe("Products-abc");
86
+ globalThis.expect(e.sourceUrn).toBe("arn:aws:sqs:eu-west-1:1:q");
87
+ globalThis.expect(e.comp).toEqual("EventCollector(ProductsEC)");
88
+ globalThis.expect(e.plugin).toEqual("Catalog");
89
+ globalThis.expect(e.stateTopicName).toEqual("catalogProducts");
90
+ let cc = e.pgConnection;
91
+ if (cc !== undefined) {
92
+ globalThis.expect(cc.host).toBe("db.local");
93
+ globalThis.expect(cc.port).toBe(5432);
94
+ globalThis.expect(cc.database).toBe("app");
95
+ return;
96
+ } else {
97
+ return Stdlib_JsError.throwWithMessage("expected Some(pgConnection)");
98
+ }
99
+ });
100
+ globalThis.test("optional fields default to None; null pgConnection maps to None", () => {
101
+ let config = JSON.stringify(Object.fromEntries([[
102
+ "handlers",
103
+ [Object.fromEntries([
104
+ [
105
+ "specModule",
106
+ "a.res.mjs"
107
+ ],
108
+ [
109
+ "mappingsModule",
110
+ "b.res.mjs"
111
+ ],
112
+ [
113
+ "queryDbTableName",
114
+ "t"
115
+ ],
116
+ [
117
+ "sourceUrn",
118
+ "u"
119
+ ],
120
+ [
121
+ "pgConnection",
122
+ null
123
+ ]
124
+ ])]
125
+ ]]));
126
+ let e = ReadModelEntryPoint_Ops$ReventlessAws.parseHandlerConfig(config)[0];
127
+ globalThis.expect(Stdlib_Option.isNone(e.comp)).toBe(true);
128
+ globalThis.expect(Stdlib_Option.isNone(e.plugin)).toBe(true);
129
+ globalThis.expect(Stdlib_Option.isNone(e.stateTopicName)).toBe(true);
130
+ globalThis.expect(Stdlib_Option.isNone(e.pgConnection)).toBe(true);
131
+ });
132
+ });
133
+
134
+ globalThis.describe("ReadModelEntryPoint_Ops.injectId", () => {
135
+ globalThis.test("injects (and overwrites) id on object states", () => {
136
+ globalThis.expect(ReadModelEntryPoint_Ops$ReventlessAws.injectId("p-1", Object.fromEntries([[
137
+ "name",
138
+ "Widget"
139
+ ]]))).toEqual(Object.fromEntries([
140
+ [
141
+ "name",
142
+ "Widget"
143
+ ],
144
+ [
145
+ "id",
146
+ "p-1"
147
+ ]
148
+ ]));
149
+ globalThis.expect(ReadModelEntryPoint_Ops$ReventlessAws.injectId("p-1", Object.fromEntries([[
150
+ "id",
151
+ "stale"
152
+ ]]))).toEqual(Object.fromEntries([[
153
+ "id",
154
+ "p-1"
155
+ ]]));
156
+ });
157
+ globalThis.test("passes non-object states through unchanged", () => {
158
+ globalThis.expect(ReadModelEntryPoint_Ops$ReventlessAws.injectId("p-1", "scalar")).toEqual("scalar");
159
+ globalThis.expect(ReadModelEntryPoint_Ops$ReventlessAws.injectId("p-1", ["a"])).toEqual(["a"]);
160
+ globalThis.expect(ReadModelEntryPoint_Ops$ReventlessAws.injectId("p-1", null)).toEqual(null);
161
+ });
162
+ });
163
+
164
+ globalThis.describe("ReadModelEntryPoint_Ops.withInjectedId", () => {
165
+ let makeStub = saved => ({
166
+ load: async param => ({
167
+ TAG: "Ok",
168
+ _0: []
169
+ }),
170
+ loadStream: param => Stream.fromIterable([]),
171
+ save: async (id, state, _mode, _ttl) => {
172
+ saved.push([
173
+ id,
174
+ state
175
+ ]);
176
+ return {
177
+ TAG: "Ok",
178
+ _0: undefined
179
+ };
180
+ },
181
+ saveBatch: async items => {
182
+ items.forEach(param => {
183
+ saved.push([
184
+ param[0],
185
+ param[1]
186
+ ]);
187
+ });
188
+ return {
189
+ TAG: "Ok",
190
+ _0: undefined
191
+ };
192
+ },
193
+ count: async (param, param$1, param$2) => ({
194
+ TAG: "Ok",
195
+ _0: 0
196
+ }),
197
+ delete: async (param, param$1) => ({
198
+ TAG: "Ok",
199
+ _0: undefined
200
+ }),
201
+ deleteBatch: async param => ({
202
+ TAG: "Ok",
203
+ _0: undefined
204
+ })
205
+ });
206
+ globalThis.test("save and saveBatch write id-injected states", async () => {
207
+ let saved = [];
208
+ let ops = ReadModelEntryPoint_Ops$ReventlessAws.withInjectedId(makeStub(saved));
209
+ await ops.save("p-1", Object.fromEntries([[
210
+ "name",
211
+ "A"
212
+ ]]), "Any", undefined);
213
+ await ops.saveBatch([
214
+ [
215
+ "p-2",
216
+ Object.fromEntries([[
217
+ "name",
218
+ "B"
219
+ ]]),
220
+ undefined
221
+ ],
222
+ [
223
+ "p-3",
224
+ "scalar",
225
+ undefined
226
+ ]
227
+ ]);
228
+ globalThis.expect(saved).toEqual([
229
+ [
230
+ "p-1",
231
+ Object.fromEntries([
232
+ [
233
+ "name",
234
+ "A"
235
+ ],
236
+ [
237
+ "id",
238
+ "p-1"
239
+ ]
240
+ ])
241
+ ],
242
+ [
243
+ "p-2",
244
+ Object.fromEntries([
245
+ [
246
+ "name",
247
+ "B"
248
+ ],
249
+ [
250
+ "id",
251
+ "p-2"
252
+ ]
253
+ ])
254
+ ],
255
+ [
256
+ "p-3",
257
+ "scalar"
258
+ ]
259
+ ]);
260
+ });
261
+ });
262
+
263
+ export {
264
+ str,
265
+ obj,
266
+ }
267
+ /* Not a pure module */
@@ -0,0 +1,79 @@
1
+ // Guards the typed cold-start core hoisted out of SideEffectEntryPoint.mjs:
2
+ // - parseHandlerConfig — the {handlers:[{sideEffectModules, sourceUrn,
3
+ // comp, plugin}]} shape written by SideEffectHandlerRuntime_Builder_Single;
4
+ // a drift here silently drops a side effect's stream subscription.
5
+ // - makeRegisteredHandler — comp/plugin attribution threading into the
6
+ // shared routed dispatch boundary.
7
+
8
+ open JestGlobals
9
+
10
+ let str = JSON.Encode.string
11
+ let obj = pairs => JSON.Encode.object(Dict.fromArray(pairs))
12
+
13
+ describe("SideEffectEntryPoint_Ops.parseHandlerConfig", () => {
14
+ testSync("empty raw config yields no handlers", () => {
15
+ expect(SideEffectEntryPoint_Ops.parseHandlerConfig("")->Array.length)->toBe(0)
16
+ })
17
+
18
+ testSync("decodes handlers incl. attribution fields", () => {
19
+ let config = obj([
20
+ (
21
+ "handlers",
22
+ JSON.Encode.array([
23
+ obj([
24
+ ("sideEffectModules", JSON.Encode.array([str("@x/p/src/A.res.mjs"), str("@x/p/src/B.res.mjs")])),
25
+ ("sourceUrn", str("arn:stream-1")),
26
+ ("comp", str("SideEffectHandler(Mailer)")),
27
+ ("plugin", str("Ordering")),
28
+ ]),
29
+ obj([
30
+ ("sideEffectModules", JSON.Encode.array([str("@x/p/src/C.res.mjs")])),
31
+ ("sourceUrn", str("arn:stream-2")),
32
+ ]),
33
+ ]),
34
+ ),
35
+ ])->JSON.stringify
36
+ let entries = SideEffectEntryPoint_Ops.parseHandlerConfig(config)
37
+ expect(entries->Array.length)->toBe(2)
38
+ let first = entries->Array.getUnsafe(0)
39
+ expect(first.sourceUrn)->toBe("arn:stream-1")
40
+ expect(first.sideEffectModules)->toEqual(["@x/p/src/A.res.mjs", "@x/p/src/B.res.mjs"])
41
+ expect(first.comp)->toEqual(Some("SideEffectHandler(Mailer)"))
42
+ expect(first.plugin)->toEqual(Some("Ordering"))
43
+ let second = entries->Array.getUnsafe(1)
44
+ expect(second.comp->Option.isNone)->toBe(true)
45
+ expect(second.plugin->Option.isNone)->toBe(true)
46
+ })
47
+ })
48
+
49
+ describe("SideEffectEntryPoint_Ops.noopQueryEngine", () => {
50
+ test("returns empty results for scan and query", async () => {
51
+ let scanned = await SideEffectEntryPoint_Ops.noopQueryEngine.scan(
52
+ ~readModelName="X",
53
+ ~filterConfigs=[],
54
+ ~limit=10,
55
+ )
56
+ expect(scanned->Array.length)->toBe(0)
57
+ let queried = await SideEffectEntryPoint_Ops.noopQueryEngine.query(
58
+ ~readModelName="X",
59
+ ~id=Reventless.QueryEngine.String("a"),
60
+ )
61
+ expect(queried->Array.length)->toBe(0)
62
+ })
63
+ })
64
+
65
+ describe("SideEffectEntryPoint_Ops.makeRegisteredHandler", () => {
66
+ testSync("threads comp/plugin onto the registered handler", () => {
67
+ let entry: SideEffectEntryPoint_Ops.handlerEntry = {
68
+ sourceUrn: "arn:stream-1",
69
+ sideEffectModules: [],
70
+ comp: Some("SideEffectHandler(Mailer)"),
71
+ plugin: Some("Ordering"),
72
+ }
73
+ let registered = SideEffectEntryPoint_Ops.makeRegisteredHandler(entry, _stream =>
74
+ Effect.succeed()
75
+ )
76
+ expect(registered.comp)->toEqual(Some("SideEffectHandler(Mailer)"))
77
+ expect(registered.plugin)->toEqual(Some("Ordering"))
78
+ })
79
+ })
@@ -0,0 +1,105 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
4
+ import * as Effect from "effect/Effect";
5
+ import * as SideEffectEntryPoint_Ops$ReventlessAws from "../src/adapter/Runtime/SideEffectEntryPoint_Ops.res.mjs";
6
+
7
+ function str(prim) {
8
+ return prim;
9
+ }
10
+
11
+ function obj(pairs) {
12
+ return Object.fromEntries(pairs);
13
+ }
14
+
15
+ globalThis.describe("SideEffectEntryPoint_Ops.parseHandlerConfig", () => {
16
+ globalThis.test("empty raw config yields no handlers", () => {
17
+ globalThis.expect(SideEffectEntryPoint_Ops$ReventlessAws.parseHandlerConfig("").length).toBe(0);
18
+ });
19
+ globalThis.test("decodes handlers incl. attribution fields", () => {
20
+ let config = JSON.stringify(Object.fromEntries([[
21
+ "handlers",
22
+ [
23
+ Object.fromEntries([
24
+ [
25
+ "sideEffectModules",
26
+ [
27
+ "@x/p/src/A.res.mjs",
28
+ "@x/p/src/B.res.mjs"
29
+ ]
30
+ ],
31
+ [
32
+ "sourceUrn",
33
+ "arn:stream-1"
34
+ ],
35
+ [
36
+ "comp",
37
+ "SideEffectHandler(Mailer)"
38
+ ],
39
+ [
40
+ "plugin",
41
+ "Ordering"
42
+ ]
43
+ ]),
44
+ Object.fromEntries([
45
+ [
46
+ "sideEffectModules",
47
+ ["@x/p/src/C.res.mjs"]
48
+ ],
49
+ [
50
+ "sourceUrn",
51
+ "arn:stream-2"
52
+ ]
53
+ ])
54
+ ]
55
+ ]]));
56
+ let entries = SideEffectEntryPoint_Ops$ReventlessAws.parseHandlerConfig(config);
57
+ globalThis.expect(entries.length).toBe(2);
58
+ let first = entries[0];
59
+ globalThis.expect(first.sourceUrn).toBe("arn:stream-1");
60
+ globalThis.expect(first.sideEffectModules).toEqual([
61
+ "@x/p/src/A.res.mjs",
62
+ "@x/p/src/B.res.mjs"
63
+ ]);
64
+ globalThis.expect(first.comp).toEqual("SideEffectHandler(Mailer)");
65
+ globalThis.expect(first.plugin).toEqual("Ordering");
66
+ let second = entries[1];
67
+ globalThis.expect(Stdlib_Option.isNone(second.comp)).toBe(true);
68
+ globalThis.expect(Stdlib_Option.isNone(second.plugin)).toBe(true);
69
+ });
70
+ });
71
+
72
+ globalThis.describe("SideEffectEntryPoint_Ops.noopQueryEngine", () => {
73
+ globalThis.test("returns empty results for scan and query", async () => {
74
+ let scanned = await SideEffectEntryPoint_Ops$ReventlessAws.noopQueryEngine.scan("X", [], 10);
75
+ globalThis.expect(scanned.length).toBe(0);
76
+ let queried = await SideEffectEntryPoint_Ops$ReventlessAws.noopQueryEngine.query("X", undefined, {
77
+ TAG: "String",
78
+ _0: "a"
79
+ }, undefined, undefined, undefined, undefined);
80
+ globalThis.expect(queried.length).toBe(0);
81
+ });
82
+ });
83
+
84
+ globalThis.describe("SideEffectEntryPoint_Ops.makeRegisteredHandler", () => {
85
+ globalThis.test("threads comp/plugin onto the registered handler", () => {
86
+ let entry_sideEffectModules = [];
87
+ let entry_comp = "SideEffectHandler(Mailer)";
88
+ let entry_plugin = "Ordering";
89
+ let entry = {
90
+ sourceUrn: "arn:stream-1",
91
+ sideEffectModules: entry_sideEffectModules,
92
+ comp: entry_comp,
93
+ plugin: entry_plugin
94
+ };
95
+ let registered = SideEffectEntryPoint_Ops$ReventlessAws.makeRegisteredHandler(entry, _stream => Effect.succeed());
96
+ globalThis.expect(registered.comp).toEqual("SideEffectHandler(Mailer)");
97
+ globalThis.expect(registered.plugin).toEqual("Ordering");
98
+ });
99
+ });
100
+
101
+ export {
102
+ str,
103
+ obj,
104
+ }
105
+ /* Not a pure module */