@reventlessdev/reventless-local 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 +30 -0
- package/package.json +13 -13
- package/src/BakedManifest.res +5 -6
- package/src/EmitCapabilities.res +3 -1
- package/src/LocalPlatformRegistry.res +3 -1
- package/src/LocalPlatformStart.res +7 -6
- package/src/LocalSeedTarget.res +3 -1
- package/src/Platform.res +291 -215
- package/src/ShellConfig.res +10 -17
- package/src/UiHints.res +8 -14
- package/src/UiSlots.res +10 -17
- package/src/adapter/Api/LocalEvents_Server.res +5 -3
- package/src/adapter/Api/LocalGraphQL_Adapter.res +4 -4
- package/src/adapter/Auth/LocalAuth.res +12 -16
- package/src/adapter/Auth/LocalAuth.res.mjs +2 -1
- package/src/adapter/Auth/UserStore.res +13 -40
- package/src/adapter/Auth/UserStore.res.mjs +11 -67
- package/src/adapter/Backend.res +1 -2
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_GraphQL.res +42 -26
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_GraphQL.res +13 -3
- package/src/adapter/CommandTopic/LocalCommandTopicChannel.res +15 -17
- package/src/adapter/CommandTopic/LocalCommandTopicRemoteChannel.res +18 -22
- package/src/adapter/Counter/LocalCounterHandler.res +1 -1
- package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res +33 -22
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res +57 -57
- package/src/adapter/DomainGraphQL_Server.res +35 -34
- package/src/adapter/DomainMCP_Server.res +45 -41
- package/src/adapter/EventCollector/LocalEventCollectorChannel.res +47 -36
- package/src/adapter/EventHistory/EventHistoryResolvers_GraphQL.res +15 -12
- package/src/adapter/EventLog/EventLogStorage_InMemory.res +9 -4
- package/src/adapter/EventLog/EventLogStorage_Sqlite.res +36 -24
- package/src/adapter/EventTopic/LocalEventTopicPublisher.res +9 -3
- package/src/adapter/Heartbeat/LocalHeartbeatRunner.res +9 -14
- package/src/adapter/LocalBus.res +12 -12
- package/src/adapter/LocalCapabilities.res +6 -0
- package/src/adapter/LocalCapabilities.res.mjs +5 -2
- package/src/adapter/LocalGeocodeResolvers.res +1 -4
- package/src/adapter/LocalSideEffectHandler.res +1 -1
- package/src/adapter/LocalStateChangeDescriptor.res +2 -1
- package/src/adapter/MCP_ServerInstance.res +51 -39
- package/src/adapter/ObjectStore/LocalObjectStore.res +5 -2
- package/src/adapter/ObjectStore/ObjectStoreStorage_FileSystem.res +1 -2
- package/src/adapter/PlatformGraphQL_Server.res +10 -6
- package/src/adapter/PlatformGraphQL_Server.res.mjs +2 -1
- package/src/adapter/ProjectionCheckpoint.res +8 -1
- package/src/adapter/ProjectionPending.res +1 -3
- package/src/adapter/QueryDb/LocalQueryDbStorage.res +2 -1
- package/src/adapter/QueryDb/QueryDbResolvers_GraphQL.res +367 -269
- package/src/adapter/QueryDb/QueryDbStorage_InMemory.res +5 -3
- package/src/adapter/QueryDb/QueryDbStorage_Sqlite.res +63 -40
- package/src/adapter/QueryDb/SortKey_Filter.res +14 -6
- package/src/adapter/Runtime/LocalAggregateRuntime_Builder.res +12 -10
- package/src/adapter/Runtime/LocalEventCollectorRuntime_Builder.res +8 -2
- package/src/adapter/Runtime/LocalPluginRuntime_Builder.res +1 -4
- package/src/adapter/Scheduler/LocalScheduledPublisher.res +12 -12
- package/src/adapter/SqliteDriver.res +16 -4
- package/src/adapter/Task/TaskBucket_Sqlite.res +5 -6
- package/src/components/Aggregate_Builder.res +6 -1
- package/src/components/Counter_Builder.res +1 -5
- package/src/components/DcbEventLog_Builder.res +5 -3
- package/src/components/ExtensionPoint_Builder.res +13 -15
- package/src/components/InboundTranslationSlice_Builder.res +3 -2
- package/src/components/OutboundTranslationSlice_Builder.res +3 -2
- package/src/components/ReadModel_Builder.res +18 -20
- package/src/components/StateViewSlice_Builder.res +3 -2
- package/src/components/Task_Builder.res +12 -13
- package/src/reset/LocalSeedReset.res +2 -5
- package/src/test/Mocks/MockDcbEventLogStorage.res +5 -1
- package/src/test/Mocks/MockEventLogStorage.res +8 -3
- package/src/test/Mocks/MockQueryDbStorage.res +3 -2
- package/src/test/TestRunner.res +1 -1
- package/tests/BakedManifestFilesTest.res +7 -10
- package/tests/LocalEventTapTest.res +26 -21
- package/tests/LocalPlatformStartTest.res +33 -28
- package/tests/PluginEventDecodeTest.res +3 -3
- package/tests/ShellConfigTest.res +30 -21
- package/tests/SplitApiFixtures.res +34 -10
- package/tests/SplitApiTest.res +92 -62
- package/tests/adapter/BackendParityTest.res +180 -130
- package/tests/adapter/CollectNEventsTest.res +6 -4
- package/tests/adapter/CommandAuthorizationTest.res +47 -41
- package/tests/adapter/CommandTopicChannelTest.res +163 -139
- package/tests/adapter/CounterHandlerTest.res +95 -77
- package/tests/adapter/DcbEventLogStorageSqliteTest.res +171 -168
- package/tests/adapter/DcbEventLogStorageTest.res +264 -207
- package/tests/adapter/DomainGraphQL_ServerTest.res +53 -43
- package/tests/adapter/EventCollectorChannelTest.res +153 -124
- package/tests/adapter/EventHistoryResolverTest.res +46 -18
- package/tests/adapter/EventLogSnapshotParityTest.res +57 -45
- package/tests/adapter/EventLogStorageSqliteTest.res +9 -10
- package/tests/adapter/EventTapTest.res +37 -20
- package/tests/adapter/EventTopicPublisherTest.res +74 -50
- package/tests/adapter/GraphQLSubscriptionBridgeTest.res +4 -3
- package/tests/adapter/GraphQL_SchemaInspectorTest.res +666 -568
- package/tests/adapter/GraphQL_SubscriptionResolversTest.res +105 -96
- package/tests/adapter/HeartbeatRunnerTest.res +99 -81
- package/tests/adapter/InboundTranslationMutationTest.res +4 -1
- package/tests/adapter/LocalAuthHttpTest.res +79 -85
- package/tests/adapter/LocalAuthLoginTest.res +42 -50
- package/tests/adapter/LocalAuthTest.res +8 -16
- package/tests/adapter/LocalAuthUserStoreTest.res +2 -7
- package/tests/adapter/LocalBusBoundedTest.res +187 -117
- package/tests/adapter/LocalBusPubSubTest.res +118 -76
- package/tests/adapter/LocalDispatchContextTest.res +1 -2
- package/tests/adapter/LocalEvents_ServerTest.res +242 -187
- package/tests/adapter/PgProjectionCatchupTest.res +44 -10
- package/tests/adapter/ProjectionCheckpointTest.res +261 -206
- package/tests/adapter/QueryDbGsiTtlTest.res +123 -83
- package/tests/adapter/QueryDbListPushdownParityTest.res +107 -67
- package/tests/adapter/QueryDbListResolverTest.res +225 -208
- package/tests/adapter/QueryDbResolvedFieldsTest.res +17 -14
- package/tests/adapter/QueryDbStorageSqliteTest.res +33 -49
- package/tests/adapter/QueryDbStorageTest.res +163 -117
- package/tests/adapter/QueryDbUnionRoundTripTest.res +8 -10
- package/tests/adapter/QueryEngineTest.res +179 -126
- package/tests/adapter/ScheduledPublisherTest.res +171 -135
- package/tests/adapter/ServedBucketHttpTest.res +65 -59
- package/tests/adapter/SortKey_FilterTest.res +19 -3
- package/tests/adapter/SqliteDriverTest.res +13 -10
- package/tests/adapter/TaskBucketTest.res +94 -80
- package/tests/components/aggregate/AggregateTest.res +31 -18
- package/tests/components/automationslice/AutomationSliceCallbackTest.res +259 -222
- package/tests/components/automationslice/AutomationSliceFixtures.res +4 -2
- package/tests/components/automationslice/AutomationSliceSelfDeadlockFixtures.res +38 -38
- package/tests/components/automationslice/MixedSourceAutomationSliceFixtures.res +12 -14
- package/tests/components/automationslice/MixedSourceAutomationSliceTest.res +8 -32
- package/tests/components/commandgenerator/CommandGeneratorFixtures.res +7 -5
- package/tests/components/commandgenerator/CommandGeneratorTest.res +40 -31
- package/tests/components/commandtopic/CommandTopicFixtures.res +3 -4
- package/tests/components/commandtopic/CommandTopicStreamFixtures.res +7 -5
- package/tests/components/commandtopic/CommandTopicTest.res +24 -15
- package/tests/components/counter/CounterFixtures.res +6 -8
- package/tests/components/dcb/DcbCrossPartitionFixtures.res +8 -2
- package/tests/components/dcb/DcbCrossPartitionReadTest.res +20 -13
- package/tests/components/dcb/DcbEventLogAppendStreamTest.res +12 -8
- package/tests/components/dcb/DcbEventLogStreamTest.res +88 -61
- package/tests/components/dcb/DcbFixtures.res +4 -1
- package/tests/components/dcb/DcbTest.res +9 -6
- package/tests/components/eventcollector/EventCollectorFixtures.res +0 -1
- package/tests/components/eventcollector/EventCollectorTest.res +6 -3
- package/tests/components/eventlog/EventLogAppendStreamTest.res +88 -68
- package/tests/components/eventlog/EventLogConflictTest.res +8 -4
- package/tests/components/eventlog/EventLogFixtures.res +3 -3
- package/tests/components/eventlog/EventLogProvisioningSeamTest.res +26 -13
- package/tests/components/eventlog/EventLogStreamTest.res +119 -56
- package/tests/components/eventlog/EventLogTest.res +20 -4
- package/tests/components/eventtopic/EventTopicFixtures.res +3 -3
- package/tests/components/eventtopic/EventTopicStreamFixtures.res +1 -2
- package/tests/components/eventtopic/EventTopicStreamTest.res +7 -1
- package/tests/components/extensionpoint/ExtensionPointFixtures.res +14 -9
- package/tests/components/extensionpoint/ExtensionPointTest.res +3 -2
- package/tests/components/heartbeat/HeartbeatFixtures.res +5 -6
- package/tests/components/heartbeat/HeartbeatTest.res +56 -47
- package/tests/components/inboundtranslationslice/InboundTranslationSliceCallbackTest.res +271 -249
- package/tests/components/inboundtranslationslice/InboundTranslationSliceFixtures.res +3 -2
- package/tests/components/outboundtranslationslice/OutboundTranslationSliceCallbackTest.res +361 -276
- package/tests/components/outboundtranslationslice/OutboundTranslationSliceFixtures.res +8 -10
- package/tests/components/outboundtranslationslice/OutboundTranslationSlicePlatformFixtures.res +37 -43
- package/tests/components/querydb/QueryDbFixtures.res +1 -5
- package/tests/components/querydb/QueryDbTest.res +2 -4
- package/tests/components/readmodel/DcbReadModelE2EFixtures.res +15 -18
- package/tests/components/readmodel/MixedSourceReadModelFixtures.res +5 -7
- package/tests/components/readmodel/ReadModelFixtures.res +8 -8
- package/tests/components/scheduler/SchedulerTest.res +76 -58
- package/tests/components/sideeffecthandler/SideEffectHandlerFixtures.res +4 -4
- package/tests/components/stateviewslice/StateViewSliceDisplayNameFixtures.res +5 -7
- package/tests/components/stateviewslice/StateViewSliceFixtures.res +8 -6
- package/tests/components/stateviewslice/StateViewSliceSubIdFixtures.res +17 -11
- package/tests/components/stateviewslice/StateViewSliceSubIdTest.res +12 -2
- package/tests/components/task/TaskFixtures.res +5 -5
- package/tests/components/task/TaskTest.res +95 -80
- package/tests/plugin/PluginsProjection_GWT.res +3 -1
- package/tests/plugin/UiFragments_GWT.res +6 -1
- package/tests/reset/LocalSeedResetTest.res +1 -0
|
@@ -66,14 +66,20 @@ let plainCtx = ctxFor(~groups=["User"])
|
|
|
66
66
|
let noArgs: JSON.t = JSON.Encode.object(Dict.make())
|
|
67
67
|
|
|
68
68
|
let getString = (json: JSON.t, key: string): option<string> =>
|
|
69
|
-
json
|
|
69
|
+
json
|
|
70
|
+
->JSON.Decode.object
|
|
71
|
+
->Option.flatMap(d => d->Dict.get(key))
|
|
72
|
+
->Option.flatMap(JSON.Decode.string)
|
|
70
73
|
|
|
71
74
|
let names = (json: JSON.t): array<string> =>
|
|
72
75
|
json->JSON.Decode.array->Option.getOr([])->Array.filterMap(item => item->getString("name"))
|
|
73
76
|
|
|
74
77
|
// One Bus carrying both views, resolvers registered for the Orders view with the
|
|
75
78
|
// two configs the PPX writes from `@resolves` / `@resolvesMany`.
|
|
76
|
-
let buildFixture = async (
|
|
79
|
+
let buildFixture = async (
|
|
80
|
+
~suffix: string,
|
|
81
|
+
~retired: option<Reventless.StateAnnotations.retiredSpec>,
|
|
82
|
+
) => {
|
|
77
83
|
module Bus = LocalBus.Make()
|
|
78
84
|
module Storage = LocalQueryDbStorage.Make(Bus)
|
|
79
85
|
module Resolvers = QueryDbResolvers_GraphQL.Make(Bus)
|
|
@@ -144,10 +150,7 @@ let buildFixture = async (~suffix: string, ~retired: option<Reventless.StateAnno
|
|
|
144
150
|
ReventlessCore.Plugin_Helpers.stateSchemaRegistry->Dict.set(
|
|
145
151
|
productsName,
|
|
146
152
|
productRowSchema
|
|
147
|
-
->S.Metadata.set(
|
|
148
|
-
~id=Reventless.StateAnnotations.stateAnnotationsId,
|
|
149
|
-
annotations(~retired),
|
|
150
|
-
)
|
|
153
|
+
->S.Metadata.set(~id=Reventless.StateAnnotations.stateAnnotationsId, annotations(~retired))
|
|
151
154
|
->S.castToUnknown,
|
|
152
155
|
)
|
|
153
156
|
|
|
@@ -169,7 +172,12 @@ let buildFixture = async (~suffix: string, ~retired: option<Reventless.StateAnno
|
|
|
169
172
|
~opts=({}: Pulumi.CustomResourceOptions.t),
|
|
170
173
|
)
|
|
171
174
|
|
|
172
|
-
let _ = await productOps.save(
|
|
175
|
+
let _ = await productOps.save(
|
|
176
|
+
"p-1",
|
|
177
|
+
{productId: "p-1", name: "Book", archived: false},
|
|
178
|
+
Init,
|
|
179
|
+
None,
|
|
180
|
+
)
|
|
173
181
|
let _ = await productOps.save("p-2", {productId: "p-2", name: "Pen", archived: true}, Init, None)
|
|
174
182
|
let _ = await orderOps.save(
|
|
175
183
|
"o-1",
|
|
@@ -188,10 +196,7 @@ let buildFixture = async (~suffix: string, ~retired: option<Reventless.StateAnno
|
|
|
188
196
|
Dict.fromArray([
|
|
189
197
|
("orderId", JSON.Encode.string("o-1")),
|
|
190
198
|
("productId", JSON.Encode.string("p-1")),
|
|
191
|
-
(
|
|
192
|
-
"productIds",
|
|
193
|
-
["p-1", "gone", "p-2"]->Array.map(JSON.Encode.string)->JSON.Encode.array,
|
|
194
|
-
),
|
|
199
|
+
("productIds", ["p-1", "gone", "p-2"]->Array.map(JSON.Encode.string)->JSON.Encode.array),
|
|
195
200
|
]),
|
|
196
201
|
)
|
|
197
202
|
|
|
@@ -222,9 +227,7 @@ describe("QueryDb cross-table field resolvers", () => {
|
|
|
222
227
|
|
|
223
228
|
testPromise("a foreign key naming no row resolves to nothing", async () => {
|
|
224
229
|
let (resolverFor, _) = await buildFixture(~suffix="C", ~retired=None)
|
|
225
|
-
let orphan = JSON.Encode.object(
|
|
226
|
-
Dict.fromArray([("productId", JSON.Encode.string("nope"))]),
|
|
227
|
-
)
|
|
230
|
+
let orphan = JSON.Encode.object(Dict.fromArray([("productId", JSON.Encode.string("nope"))]))
|
|
228
231
|
let product = await resolverFor("product")(orphan, noArgs, plainCtx)
|
|
229
232
|
expect(product)->toBe(JSON.Encode.null)
|
|
230
233
|
})
|
|
@@ -18,18 +18,12 @@ describe("QueryDbStorage_Sqlite", () => {
|
|
|
18
18
|
let s = Storage.make(~name="rm1", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
19
19
|
let ops = await s.operations->TestRunner.resolve
|
|
20
20
|
|
|
21
|
-
let _ = await ops.save(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let items =
|
|
29
|
-
await ops.loadStream("id1")
|
|
30
|
-
->Stream.runCollect
|
|
31
|
-
->Effect.catchAll(_ => Effect.succeed([]))
|
|
32
|
-
->Effect.runPromise
|
|
21
|
+
let _ = await ops.save("id1", JSON.Encode.string("value1"), ReventlessCore.QueryDb.Any, None)
|
|
22
|
+
|
|
23
|
+
let items = await ops.loadStream("id1")
|
|
24
|
+
->Stream.runCollect
|
|
25
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
26
|
+
->Effect.runPromise
|
|
33
27
|
|
|
34
28
|
expect(items->Array.length)->toBe(1)
|
|
35
29
|
expect(items->Array.getUnsafe(0))->toEqual(JSON.Encode.string("value1"))
|
|
@@ -48,11 +42,10 @@ describe("QueryDbStorage_Sqlite", () => {
|
|
|
48
42
|
let _ = await ops.save("k", JSON.Encode.string("a"), ReventlessCore.QueryDb.Any, None)
|
|
49
43
|
let _ = await ops.save("k", JSON.Encode.string("b"), ReventlessCore.QueryDb.Any, None)
|
|
50
44
|
|
|
51
|
-
let items =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
->Effect.runPromise
|
|
45
|
+
let items = await ops.loadStream("k")
|
|
46
|
+
->Stream.runCollect
|
|
47
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
48
|
+
->Effect.runPromise
|
|
56
49
|
|
|
57
50
|
expect(items->Array.length)->toBe(1)
|
|
58
51
|
expect(items->Array.getUnsafe(0))->toEqual(JSON.Encode.string("b"))
|
|
@@ -74,21 +67,18 @@ describe("QueryDbStorage_Sqlite", () => {
|
|
|
74
67
|
("id3", JSON.Encode.string("three"), None),
|
|
75
68
|
])
|
|
76
69
|
|
|
77
|
-
let items1 =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
->Stream.runCollect
|
|
90
|
-
->Effect.catchAll(_ => Effect.succeed([]))
|
|
91
|
-
->Effect.runPromise
|
|
70
|
+
let items1 = await ops.loadStream("id1")
|
|
71
|
+
->Stream.runCollect
|
|
72
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
73
|
+
->Effect.runPromise
|
|
74
|
+
let items2 = await ops.loadStream("id2")
|
|
75
|
+
->Stream.runCollect
|
|
76
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
77
|
+
->Effect.runPromise
|
|
78
|
+
let items3 = await ops.loadStream("id3")
|
|
79
|
+
->Stream.runCollect
|
|
80
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
81
|
+
->Effect.runPromise
|
|
92
82
|
|
|
93
83
|
expect(items1->Array.length)->toBe(1)
|
|
94
84
|
expect(items2->Array.length)->toBe(1)
|
|
@@ -108,11 +98,10 @@ describe("QueryDbStorage_Sqlite", () => {
|
|
|
108
98
|
let _ = await ops.save("k", JSON.Encode.string("a"), ReventlessCore.QueryDb.Any, None)
|
|
109
99
|
let _ = await ops.delete("k", None)
|
|
110
100
|
|
|
111
|
-
let items =
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
->Effect.runPromise
|
|
101
|
+
let items = await ops.loadStream("k")
|
|
102
|
+
->Stream.runCollect
|
|
103
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
104
|
+
->Effect.runPromise
|
|
116
105
|
|
|
117
106
|
expect(items->Array.length)->toBe(0)
|
|
118
107
|
})
|
|
@@ -120,8 +109,9 @@ describe("QueryDbStorage_Sqlite", () => {
|
|
|
120
109
|
testPromise("items persist across a file reopen", async () => {
|
|
121
110
|
let path = `/tmp/reventless-test-qdb-${Float.toString(Date.now())}.db`
|
|
122
111
|
|
|
123
|
-
// Session 1: write
|
|
124
112
|
{
|
|
113
|
+
// Session 1: write
|
|
114
|
+
|
|
125
115
|
module TestBus = LocalBus.Make()
|
|
126
116
|
module DbProvider = {
|
|
127
117
|
let db = SqliteDriver.openDb(~path)
|
|
@@ -129,12 +119,7 @@ describe("QueryDbStorage_Sqlite", () => {
|
|
|
129
119
|
module Storage = QueryDbStorage_Sqlite.Make(TestBus, DbProvider)
|
|
130
120
|
let s = Storage.make(~name="persist", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
131
121
|
let ops = await s.operations->TestRunner.resolve
|
|
132
|
-
let _ = await ops.save(
|
|
133
|
-
"k",
|
|
134
|
-
JSON.Encode.string("hello"),
|
|
135
|
-
ReventlessCore.QueryDb.Any,
|
|
136
|
-
None,
|
|
137
|
-
)
|
|
122
|
+
let _ = await ops.save("k", JSON.Encode.string("hello"), ReventlessCore.QueryDb.Any, None)
|
|
138
123
|
DbProvider.db->SqliteDriver.close
|
|
139
124
|
}
|
|
140
125
|
|
|
@@ -146,11 +131,10 @@ describe("QueryDbStorage_Sqlite", () => {
|
|
|
146
131
|
module Storage2 = QueryDbStorage_Sqlite.Make(TestBus2, DbProvider2)
|
|
147
132
|
let s2 = Storage2.make(~name="persist", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
148
133
|
let ops2 = await s2.operations->TestRunner.resolve
|
|
149
|
-
let items =
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
->Effect.runPromise
|
|
134
|
+
let items = await ops2.loadStream("k")
|
|
135
|
+
->Stream.runCollect
|
|
136
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
137
|
+
->Effect.runPromise
|
|
154
138
|
|
|
155
139
|
expect(items->Array.length)->toBe(1)
|
|
156
140
|
expect(items->Array.getUnsafe(0))->toEqual(JSON.Encode.string("hello"))
|
|
@@ -9,163 +9,209 @@ let opts: Pulumi.CustomResourceOptions.t = {}
|
|
|
9
9
|
|
|
10
10
|
describe("QueryDbStorage_InMemory", () => {
|
|
11
11
|
describe("save and load", () => {
|
|
12
|
-
testPromise(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
await ops.
|
|
12
|
+
testPromise(
|
|
13
|
+
"save stores state; loadStream retrieves it by id",
|
|
14
|
+
async () => {
|
|
15
|
+
module TestBus = LocalBus.Make()
|
|
16
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
17
|
+
let s = Storage.make(~name="rm1", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
18
|
+
let ops = await s.operations->TestRunner.resolve
|
|
19
|
+
let _ = await ops.save(
|
|
20
|
+
"id1",
|
|
21
|
+
JSON.Encode.string("value1"),
|
|
22
|
+
ReventlessCore.QueryDb.Any,
|
|
23
|
+
None,
|
|
24
|
+
)
|
|
25
|
+
let items = await ops.loadStream("id1")
|
|
20
26
|
->Stream.runCollect
|
|
21
27
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
22
28
|
->Effect.runPromise
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
expect(items->Array.length)->toBe(1)
|
|
30
|
+
expect(items->Array.getUnsafe(0))->toEqual(JSON.Encode.string("value1"))
|
|
31
|
+
},
|
|
32
|
+
)
|
|
26
33
|
|
|
27
|
-
testPromise(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
await
|
|
34
|
+
testPromise(
|
|
35
|
+
"loadStream returns empty for unknown id",
|
|
36
|
+
async () => {
|
|
37
|
+
module TestBus = LocalBus.Make()
|
|
38
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
39
|
+
let s = Storage.make(~name="rm2", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
40
|
+
let ops = await s.operations->TestRunner.resolve
|
|
41
|
+
let items = await ops.loadStream("unknown")
|
|
34
42
|
->Stream.runCollect
|
|
35
43
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
36
44
|
->Effect.runPromise
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
expect(items->Array.length)->toBe(0)
|
|
46
|
+
},
|
|
47
|
+
)
|
|
39
48
|
|
|
40
|
-
testPromise(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
await ops.
|
|
49
|
+
testPromise(
|
|
50
|
+
"save overwrites previous state for same id",
|
|
51
|
+
async () => {
|
|
52
|
+
module TestBus = LocalBus.Make()
|
|
53
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
54
|
+
let s = Storage.make(~name="rm3", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
55
|
+
let ops = await s.operations->TestRunner.resolve
|
|
56
|
+
let _ = await ops.save("id1", JSON.Encode.string("old"), ReventlessCore.QueryDb.Any, None)
|
|
57
|
+
let _ = await ops.save("id1", JSON.Encode.string("new"), ReventlessCore.QueryDb.Any, None)
|
|
58
|
+
let items = await ops.loadStream("id1")
|
|
49
59
|
->Stream.runCollect
|
|
50
60
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
51
61
|
->Effect.runPromise
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
expect(items->Array.length)->toBe(1)
|
|
63
|
+
expect(items->Array.getUnsafe(0))->toEqual(JSON.Encode.string("new"))
|
|
64
|
+
},
|
|
65
|
+
)
|
|
55
66
|
|
|
56
|
-
testPromise(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
testPromise(
|
|
68
|
+
"load delegates to loadStream (backward-compat)",
|
|
69
|
+
async () => {
|
|
70
|
+
module TestBus = LocalBus.Make()
|
|
71
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
72
|
+
let s = Storage.make(
|
|
73
|
+
~name="load-compat",
|
|
74
|
+
~indexes=[],
|
|
75
|
+
~api=(),
|
|
76
|
+
~apiRole=(),
|
|
77
|
+
~owner=None,
|
|
78
|
+
~opts,
|
|
79
|
+
)
|
|
80
|
+
let ops = await s.operations->TestRunner.resolve
|
|
81
|
+
let _ = await ops.save(
|
|
82
|
+
"compat-id",
|
|
83
|
+
JSON.Encode.string("compat-val"),
|
|
84
|
+
ReventlessCore.QueryDb.Any,
|
|
85
|
+
None,
|
|
86
|
+
)
|
|
87
|
+
let streamed = await ops.loadStream("compat-id")->Stream.runCollect->Effect.runPromise
|
|
88
|
+
let loaded = await ops.load("compat-id")
|
|
89
|
+
expect(loaded)->toEqual(Ok(streamed))
|
|
90
|
+
},
|
|
91
|
+
)
|
|
66
92
|
})
|
|
67
93
|
|
|
68
94
|
describe("saveBatch", () => {
|
|
69
|
-
testPromise(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
95
|
+
testPromise(
|
|
96
|
+
"stores multiple items; loadStream retrieves each by id",
|
|
97
|
+
async () => {
|
|
98
|
+
module TestBus = LocalBus.Make()
|
|
99
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
100
|
+
let s = Storage.make(~name="rm4", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
101
|
+
let ops = await s.operations->TestRunner.resolve
|
|
102
|
+
let _ = await ops.saveBatch([
|
|
103
|
+
("a", JSON.Encode.string("val-a"), None),
|
|
104
|
+
("b", JSON.Encode.string("val-b"), None),
|
|
105
|
+
])
|
|
106
|
+
let itemsA = await ops.loadStream("a")
|
|
80
107
|
->Stream.runCollect
|
|
81
108
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
82
109
|
->Effect.runPromise
|
|
83
|
-
|
|
84
|
-
await ops.loadStream("b")
|
|
110
|
+
let itemsB = await ops.loadStream("b")
|
|
85
111
|
->Stream.runCollect
|
|
86
112
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
87
113
|
->Effect.runPromise
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
114
|
+
expect(itemsA->Array.getUnsafe(0))->toEqual(JSON.Encode.string("val-a"))
|
|
115
|
+
expect(itemsB->Array.getUnsafe(0))->toEqual(JSON.Encode.string("val-b"))
|
|
116
|
+
},
|
|
117
|
+
)
|
|
91
118
|
})
|
|
92
119
|
|
|
93
120
|
describe("count", () => {
|
|
94
|
-
testPromise(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
121
|
+
testPromise(
|
|
122
|
+
"returns the increment value (no real counting semantics)",
|
|
123
|
+
async () => {
|
|
124
|
+
module TestBus = LocalBus.Make()
|
|
125
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
126
|
+
let s = Storage.make(~name="rm5", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
127
|
+
let ops = await s.operations->TestRunner.resolve
|
|
128
|
+
let result = await ops.count("id1", "field", 5)
|
|
129
|
+
expect(result)->toEqual(Ok(5))
|
|
130
|
+
},
|
|
131
|
+
)
|
|
102
132
|
})
|
|
103
133
|
|
|
104
134
|
describe("delete", () => {
|
|
105
|
-
testPromise(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
await ops.
|
|
135
|
+
testPromise(
|
|
136
|
+
"removes item; loadStream returns empty",
|
|
137
|
+
async () => {
|
|
138
|
+
module TestBus = LocalBus.Make()
|
|
139
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
140
|
+
let s = Storage.make(~name="rm6", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
141
|
+
let ops = await s.operations->TestRunner.resolve
|
|
142
|
+
let _ = await ops.save("del-id", JSON.Encode.string("v"), ReventlessCore.QueryDb.Any, None)
|
|
143
|
+
let _ = await ops.delete("del-id", None)
|
|
144
|
+
let items = await ops.loadStream("del-id")
|
|
114
145
|
->Stream.runCollect
|
|
115
146
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
116
147
|
->Effect.runPromise
|
|
117
|
-
|
|
118
|
-
|
|
148
|
+
expect(items->Array.length)->toBe(0)
|
|
149
|
+
},
|
|
150
|
+
)
|
|
119
151
|
|
|
120
|
-
testPromise(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
await ops.
|
|
152
|
+
testPromise(
|
|
153
|
+
"deleteBatch removes multiple items",
|
|
154
|
+
async () => {
|
|
155
|
+
module TestBus = LocalBus.Make()
|
|
156
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
157
|
+
let s = Storage.make(~name="rm7", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
158
|
+
let ops = await s.operations->TestRunner.resolve
|
|
159
|
+
let _ = await ops.saveBatch([
|
|
160
|
+
("x", JSON.Encode.string("vx"), None),
|
|
161
|
+
("y", JSON.Encode.string("vy"), None),
|
|
162
|
+
])
|
|
163
|
+
let _ = await ops.deleteBatch([("x", None), ("y", None)])
|
|
164
|
+
let rx = await ops.loadStream("x")
|
|
132
165
|
->Stream.runCollect
|
|
133
166
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
134
167
|
->Effect.runPromise
|
|
135
|
-
|
|
136
|
-
await ops.loadStream("y")
|
|
168
|
+
let ry = await ops.loadStream("y")
|
|
137
169
|
->Stream.runCollect
|
|
138
170
|
->Effect.catchAll(_ => Effect.succeed([]))
|
|
139
171
|
->Effect.runPromise
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
172
|
+
expect(rx->Array.length)->toBe(0)
|
|
173
|
+
expect(ry->Array.length)->toBe(0)
|
|
174
|
+
},
|
|
175
|
+
)
|
|
143
176
|
})
|
|
144
177
|
|
|
145
178
|
describe("scan registration", () => {
|
|
146
|
-
testPromise(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
179
|
+
testPromise(
|
|
180
|
+
"after save, scan function returns all stored items",
|
|
181
|
+
async () => {
|
|
182
|
+
module TestBus = LocalBus.Make()
|
|
183
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
184
|
+
let s = Storage.make(~name="scan-rm", ~indexes=[], ~api=(), ~apiRole=(), ~owner=None, ~opts)
|
|
185
|
+
let ops = await s.operations->TestRunner.resolve
|
|
186
|
+
let _ = await ops.save("s1", JSON.Encode.string("item1"), ReventlessCore.QueryDb.Any, None)
|
|
187
|
+
let _ = await ops.save("s2", JSON.Encode.string("item2"), ReventlessCore.QueryDb.Any, None)
|
|
188
|
+
let scanFn = TestBus.getQueryDbScan("scan-rm")->Option.getOr(() => [])
|
|
189
|
+
let all = scanFn()
|
|
190
|
+
expect(all->Array.length)->toBe(2)
|
|
191
|
+
},
|
|
192
|
+
)
|
|
157
193
|
|
|
158
|
-
testPromise(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
194
|
+
testPromise(
|
|
195
|
+
"after delete, scan function excludes deleted item",
|
|
196
|
+
async () => {
|
|
197
|
+
module TestBus = LocalBus.Make()
|
|
198
|
+
module Storage = LocalQueryDbStorage.Make(TestBus)
|
|
199
|
+
let s = Storage.make(
|
|
200
|
+
~name="scan-rm2",
|
|
201
|
+
~indexes=[],
|
|
202
|
+
~api=(),
|
|
203
|
+
~apiRole=(),
|
|
204
|
+
~owner=None,
|
|
205
|
+
~opts,
|
|
206
|
+
)
|
|
207
|
+
let ops = await s.operations->TestRunner.resolve
|
|
208
|
+
let _ = await ops.save("keep", JSON.Encode.string("keep"), ReventlessCore.QueryDb.Any, None)
|
|
209
|
+
let _ = await ops.save("gone", JSON.Encode.string("gone"), ReventlessCore.QueryDb.Any, None)
|
|
210
|
+
let _ = await ops.delete("gone", None)
|
|
211
|
+
let scanFn = TestBus.getQueryDbScan("scan-rm2")->Option.getOr(() => [])
|
|
212
|
+
let all = scanFn()
|
|
213
|
+
expect(all->Array.length)->toBe(1)
|
|
214
|
+
},
|
|
215
|
+
)
|
|
170
216
|
})
|
|
171
217
|
})
|
|
@@ -76,11 +76,10 @@ describe("QueryDb round-trips a union field", () => {
|
|
|
76
76
|
)
|
|
77
77
|
|
|
78
78
|
// The stored row, as any read door would hand it back.
|
|
79
|
-
let stored =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
->Effect.runPromise
|
|
79
|
+
let stored = await jsonOps.loadStream("c-1")
|
|
80
|
+
->Stream.runCollect
|
|
81
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
82
|
+
->Effect.runPromise
|
|
84
83
|
let typename =
|
|
85
84
|
stored
|
|
86
85
|
->Array.get(0)
|
|
@@ -91,11 +90,10 @@ describe("QueryDb round-trips a union field", () => {
|
|
|
91
90
|
->Option.flatMap(JSON.Decode.string)
|
|
92
91
|
expect(typename)->toEqual(Some("GeolocationLocated"))
|
|
93
92
|
|
|
94
|
-
let items =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
->Effect.runPromise
|
|
93
|
+
let items = await Ops.loadStream("c-1"->CustomersSpec.Id.makeFromString)
|
|
94
|
+
->Stream.runCollect
|
|
95
|
+
->Effect.catchAll(_ => Effect.succeed([]))
|
|
96
|
+
->Effect.runPromise
|
|
99
97
|
switch items {
|
|
100
98
|
| [{geolocation: Located({lat, lng})}] => expect((lat, lng))->toEqual((48.2082, 16.3738))
|
|
101
99
|
| _ => expect("round trip")->toBe("Located with its point intact")
|