@reventlessdev/reventless-local 3.0.0-alpha.115 → 3.0.0-alpha.116

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 (59) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +6 -6
  3. package/src/Platform.res +91 -17
  4. package/src/Platform.res.mjs +89 -30
  5. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res +102 -17
  6. package/src/adapter/DcbEventLog/DcbEventLogStorage_InMemory.res.mjs +105 -22
  7. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res +113 -39
  8. package/src/adapter/DcbEventLog/DcbEventLogStorage_Sqlite.res.mjs +87 -23
  9. package/src/adapter/EventCollector/LocalEventCollectorChannel.res +33 -0
  10. package/src/adapter/EventCollector/LocalEventCollectorChannel.res.mjs +44 -0
  11. package/src/adapter/EventLog/EventLogStorage_InMemory.res +23 -2
  12. package/src/adapter/EventLog/EventLogStorage_InMemory.res.mjs +20 -3
  13. package/src/adapter/EventLog/EventLogStorage_Sqlite.res +132 -24
  14. package/src/adapter/EventLog/EventLogStorage_Sqlite.res.mjs +119 -37
  15. package/src/adapter/LocalBus.res +62 -0
  16. package/src/adapter/LocalBus.res.mjs +120 -0
  17. package/src/adapter/ProjectionCheckpoint.res +350 -0
  18. package/src/adapter/ProjectionCheckpoint.res.mjs +327 -0
  19. package/src/adapter/ProjectionPending.res +60 -0
  20. package/src/adapter/ProjectionPending.res.mjs +64 -0
  21. package/src/adapter/QueryDb/QueryDbListQuery.res +261 -0
  22. package/src/adapter/QueryDb/QueryDbListQuery.res.mjs +212 -0
  23. package/src/adapter/QueryDb/QueryDbResolvers_GraphQL.res +54 -286
  24. package/src/adapter/QueryDb/QueryDbResolvers_GraphQL.res.mjs +28 -190
  25. package/src/adapter/QueryDb/QueryDbStorage_InMemory.res +32 -6
  26. package/src/adapter/QueryDb/QueryDbStorage_InMemory.res.mjs +30 -14
  27. package/src/adapter/QueryDb/QueryDbStorage_Sqlite.res +163 -11
  28. package/src/adapter/QueryDb/QueryDbStorage_Sqlite.res.mjs +101 -3
  29. package/src/adapter/SqliteDriver.res +11 -1
  30. package/src/adapter/SqliteDriver.res.mjs +5 -1
  31. package/src/components/ReadModel_Builder.res +3 -1
  32. package/src/components/ReadModel_Builder.res.mjs +13 -4
  33. package/src/components/StateViewSlice_Builder.res +4 -1
  34. package/src/components/StateViewSlice_Builder.res.mjs +9 -3
  35. package/src/test/Mocks/MockEventLogStorage.res +19 -2
  36. package/src/test/Mocks/MockEventLogStorage.res.mjs +21 -2
  37. package/tests/PluginEventDecodeTest.res +51 -0
  38. package/tests/PluginEventDecodeTest.res.mjs +63 -0
  39. package/tests/adapter/DcbEventLogStorageSqliteTest.res +73 -0
  40. package/tests/adapter/DcbEventLogStorageSqliteTest.res.mjs +86 -0
  41. package/tests/adapter/DcbEventLogStorageTest.res +46 -0
  42. package/tests/adapter/DcbEventLogStorageTest.res.mjs +63 -0
  43. package/tests/adapter/EventLogSnapshotParityTest.res +81 -0
  44. package/tests/adapter/EventLogSnapshotParityTest.res.mjs +141 -0
  45. package/tests/adapter/EventLogStorageSqliteTest.res +128 -0
  46. package/tests/adapter/EventLogStorageSqliteTest.res.mjs +189 -0
  47. package/tests/adapter/ProjectionCheckpointTest.res +422 -0
  48. package/tests/adapter/ProjectionCheckpointTest.res.mjs +401 -0
  49. package/tests/adapter/QueryDbGsiTtlTest.res +78 -0
  50. package/tests/adapter/QueryDbGsiTtlTest.res.mjs +77 -0
  51. package/tests/adapter/QueryDbListPushdownParityTest.res +197 -0
  52. package/tests/adapter/QueryDbListPushdownParityTest.res.mjs +292 -0
  53. package/tests/adapter/QueryDbListResolverTest.res +76 -0
  54. package/tests/adapter/QueryDbListResolverTest.res.mjs +84 -0
  55. package/tests/components/aggregate/AggregateFixtures.res +4 -0
  56. package/tests/components/aggregate/AggregateFixtures.res.mjs +1 -0
  57. package/tests/components/eventlog/EventLogAppendStreamTest.res.mjs +4 -4
  58. package/tests/components/eventlog/EventLogStreamTest.res.mjs +8 -8
  59. package/tests/plugin/PluginBehavior_GWT.res.mjs +1 -0
@@ -154,6 +154,33 @@ module type T = {
154
154
  // Used by LocalQueryEngine to honour ~limit via Stream.take without loading all items.
155
155
  let registerQueryDbStream: (string, unit => Stream.t<JSON.t, string, unit>) => unit
156
156
  let getQueryDbStream: string => option<unit => Stream.t<JSON.t, string, unit>>
157
+ // Indexed equality lookup: (field, value) → matching items. The SQLite backend
158
+ // registers a closure that pushes the predicate down to a `json_extract` GSI
159
+ // index instead of materialising + parsing the whole table; the in-memory
160
+ // backend registers a scan+filter. The `{name}By{Index}` resolvers use this
161
+ // when present and fall back to `getQueryDbScan` otherwise.
162
+ let registerQueryDbIndexLookup: (string, (string, string) => array<JSON.t>) => unit
163
+ let getQueryDbIndexLookup: string => option<(string, string) => array<JSON.t>>
164
+ // Connection-list push-down: given the GraphQL args + derived capability +
165
+ // label field, a backend may return a ready Relay connection object computed
166
+ // entirely in storage (SQLite: json_extract predicates + ORDER BY … LIMIT), or
167
+ // `None` when it can't serve that query shape — the resolver then falls back to
168
+ // materialise + `QueryDbListQuery.run`. Only the SQLite backend registers one.
169
+ let registerQueryDbListPage: (
170
+ string,
171
+ (
172
+ ~argsDict: dict<JSON.t>,
173
+ ~capability: ReventlessCore.GraphQL_FragmentGenerator.serverCapability,
174
+ ~labelField: string,
175
+ ) => option<JSON.t>,
176
+ ) => unit
177
+ let getQueryDbListPage: string => option<
178
+ (
179
+ ~argsDict: dict<JSON.t>,
180
+ ~capability: ReventlessCore.GraphQL_FragmentGenerator.serverCapability,
181
+ ~labelField: string,
182
+ ) => option<JSON.t>,
183
+ >
157
184
 
158
185
  // Event log replay registry: aggregate EventLog name → replay function (entityId → events)
159
186
  let registerEventLogReplay: (string, string => promise<array<JSON.t>>) => unit
@@ -196,6 +223,15 @@ module type T = {
196
223
  let registerEventCollectorHandler: (string, (JSON.t, unit) => promise<unit>) => unit
197
224
  let subscribeEventCollectorToTopic: (string, string) => unit
198
225
 
226
+ // Projection catch-up registry: collector name → its resolved JSON event
227
+ // handler, registered only by projection-type collectors (the ReadModel
228
+ // builders, via LocalEventCollectorChannel.MakeProjection). The SQLite
229
+ // backend's startup catch-up (ProjectionCheckpoint.runCatchup) replays missed
230
+ // stored events into these handlers; automation/translation collectors are
231
+ // deliberately NOT in this registry so catch-up can never re-run side effects.
232
+ let registerProjectionCatchupHandler: (string, (JSON.t, unit) => promise<unit>) => unit
233
+ let projectionCatchupHandlers: unit => array<(string, (JSON.t, unit) => promise<unit>)>
234
+
199
235
  let reset: unit => unit
200
236
  }
201
237
 
@@ -227,6 +263,16 @@ module Impl = (C: BusConfig): T => {
227
263
  let queryDbRegistry: ref<dict<ReventlessCore.QueryDb_Adapter.operations>> = ref(Dict.make())
228
264
  let queryDbScanRegistry: ref<dict<unit => array<JSON.t>>> = ref(Dict.make())
229
265
  let queryDbStreamRegistry: ref<dict<unit => Stream.t<JSON.t, string, unit>>> = ref(Dict.make())
266
+ let queryDbIndexLookupRegistry: ref<dict<(string, string) => array<JSON.t>>> = ref(Dict.make())
267
+ let queryDbListPageRegistry: ref<
268
+ dict<
269
+ (
270
+ ~argsDict: dict<JSON.t>,
271
+ ~capability: ReventlessCore.GraphQL_FragmentGenerator.serverCapability,
272
+ ~labelField: string,
273
+ ) => option<JSON.t>,
274
+ >,
275
+ > = ref(Dict.make())
230
276
  let eventLogReplayRegistry: ref<dict<string => promise<array<JSON.t>>>> = ref(Dict.make())
231
277
  let dcbEventLogReadRegistry: ref<
232
278
  dict<
@@ -401,6 +447,12 @@ module Impl = (C: BusConfig): T => {
401
447
  let registerQueryDbStream = (name, streamFn) =>
402
448
  queryDbStreamRegistry.contents->Dict.set(name, streamFn)
403
449
  let getQueryDbStream = name => queryDbStreamRegistry.contents->Dict.get(name)
450
+ let registerQueryDbIndexLookup = (name, lookup) =>
451
+ queryDbIndexLookupRegistry.contents->Dict.set(name, lookup)
452
+ let getQueryDbIndexLookup = name => queryDbIndexLookupRegistry.contents->Dict.get(name)
453
+ let registerQueryDbListPage = (name, listPage) =>
454
+ queryDbListPageRegistry.contents->Dict.set(name, listPage)
455
+ let getQueryDbListPage = name => queryDbListPageRegistry.contents->Dict.get(name)
404
456
 
405
457
  let registerEventLogReplay = (name, replay) =>
406
458
  eventLogReplayRegistry.contents->Dict.set(name, replay)
@@ -460,6 +512,13 @@ module Impl = (C: BusConfig): T => {
460
512
  }
461
513
  }
462
514
 
515
+ let projectionCatchupRegistry: ref<dict<(JSON.t, unit) => promise<unit>>> = ref(Dict.make())
516
+
517
+ let registerProjectionCatchupHandler = (name, handler) =>
518
+ projectionCatchupRegistry.contents->Dict.set(name, handler)
519
+
520
+ let projectionCatchupHandlers = () => projectionCatchupRegistry.contents->Dict.toArray
521
+
463
522
  let reset = () => {
464
523
  // Shut down all hubs — PubSub.shutdown interrupts Stream.fromQueue consumers,
465
524
  // causing Stream.runForEach to complete and Effect.scoped to close the subscription.
@@ -477,11 +536,14 @@ module Impl = (C: BusConfig): T => {
477
536
  queryDbRegistry := Dict.make()
478
537
  queryDbScanRegistry := Dict.make()
479
538
  queryDbStreamRegistry := Dict.make()
539
+ queryDbIndexLookupRegistry := Dict.make()
540
+ queryDbListPageRegistry := Dict.make()
480
541
  eventLogReplayRegistry := Dict.make()
481
542
  dcbEventLogReadRegistry := Dict.make()
482
543
  stateChangeListeners := Dict.make()
483
544
  eventCollectorHandlers := Dict.make()
484
545
  eventCollectorPendingTopics := Dict.make()
546
+ projectionCatchupRegistry := Dict.make()
485
547
  }
486
548
  }
487
549
 
@@ -104,6 +104,12 @@ function Impl(C) {
104
104
  let queryDbStreamRegistry = {
105
105
  contents: {}
106
106
  };
107
+ let queryDbIndexLookupRegistry = {
108
+ contents: {}
109
+ };
110
+ let queryDbListPageRegistry = {
111
+ contents: {}
112
+ };
107
113
  let eventLogReplayRegistry = {
108
114
  contents: {}
109
115
  };
@@ -234,6 +240,14 @@ function Impl(C) {
234
240
  queryDbStreamRegistry.contents[name] = streamFn;
235
241
  };
236
242
  let getQueryDbStream = name => queryDbStreamRegistry.contents[name];
243
+ let registerQueryDbIndexLookup = (name, lookup) => {
244
+ queryDbIndexLookupRegistry.contents[name] = lookup;
245
+ };
246
+ let getQueryDbIndexLookup = name => queryDbIndexLookupRegistry.contents[name];
247
+ let registerQueryDbListPage = (name, listPage) => {
248
+ queryDbListPageRegistry.contents[name] = listPage;
249
+ };
250
+ let getQueryDbListPage = name => queryDbListPageRegistry.contents[name];
237
251
  let registerEventLogReplay = (name, replay) => {
238
252
  eventLogReplayRegistry.contents[name] = replay;
239
253
  };
@@ -282,6 +296,13 @@ function Impl(C) {
282
296
  pending.push(topicName);
283
297
  eventCollectorPendingTopics.contents[ecName] = pending;
284
298
  };
299
+ let projectionCatchupRegistry = {
300
+ contents: {}
301
+ };
302
+ let registerProjectionCatchupHandler = (name, handler) => {
303
+ projectionCatchupRegistry.contents[name] = handler;
304
+ };
305
+ let projectionCatchupHandlers = () => Object.entries(projectionCatchupRegistry.contents);
285
306
  let reset = () => {
286
307
  let shutdownAll = Effect$1.map(Effect$1.all(Object.values(eventHubs.contents).map(hub => PubSub.shutdown(hub)), {
287
308
  concurrency: "unbounded"
@@ -294,11 +315,14 @@ function Impl(C) {
294
315
  queryDbRegistry.contents = {};
295
316
  queryDbScanRegistry.contents = {};
296
317
  queryDbStreamRegistry.contents = {};
318
+ queryDbIndexLookupRegistry.contents = {};
319
+ queryDbListPageRegistry.contents = {};
297
320
  eventLogReplayRegistry.contents = {};
298
321
  dcbEventLogReadRegistry.contents = {};
299
322
  stateChangeListeners.contents = {};
300
323
  eventCollectorHandlers.contents = {};
301
324
  eventCollectorPendingTopics.contents = {};
325
+ projectionCatchupRegistry.contents = {};
302
326
  };
303
327
  return {
304
328
  publishEvent: publishEvent,
@@ -312,6 +336,10 @@ function Impl(C) {
312
336
  getQueryDbScan: getQueryDbScan,
313
337
  registerQueryDbStream: registerQueryDbStream,
314
338
  getQueryDbStream: getQueryDbStream,
339
+ registerQueryDbIndexLookup: registerQueryDbIndexLookup,
340
+ getQueryDbIndexLookup: getQueryDbIndexLookup,
341
+ registerQueryDbListPage: registerQueryDbListPage,
342
+ getQueryDbListPage: getQueryDbListPage,
315
343
  registerEventLogReplay: registerEventLogReplay,
316
344
  getEventLogReplay: getEventLogReplay,
317
345
  registerDcbEventLogRead: registerDcbEventLogRead,
@@ -320,6 +348,8 @@ function Impl(C) {
320
348
  subscribeToStateChanges: subscribeToStateChanges,
321
349
  registerEventCollectorHandler: registerEventCollectorHandler,
322
350
  subscribeEventCollectorToTopic: subscribeEventCollectorToTopic,
351
+ registerProjectionCatchupHandler: registerProjectionCatchupHandler,
352
+ projectionCatchupHandlers: projectionCatchupHandlers,
323
353
  reset: reset
324
354
  };
325
355
  }
@@ -346,6 +376,12 @@ function Make($star) {
346
376
  let queryDbStreamRegistry = {
347
377
  contents: {}
348
378
  };
379
+ let queryDbIndexLookupRegistry = {
380
+ contents: {}
381
+ };
382
+ let queryDbListPageRegistry = {
383
+ contents: {}
384
+ };
349
385
  let eventLogReplayRegistry = {
350
386
  contents: {}
351
387
  };
@@ -470,6 +506,14 @@ function Make($star) {
470
506
  queryDbStreamRegistry.contents[name] = streamFn;
471
507
  };
472
508
  let getQueryDbStream = name => queryDbStreamRegistry.contents[name];
509
+ let registerQueryDbIndexLookup = (name, lookup) => {
510
+ queryDbIndexLookupRegistry.contents[name] = lookup;
511
+ };
512
+ let getQueryDbIndexLookup = name => queryDbIndexLookupRegistry.contents[name];
513
+ let registerQueryDbListPage = (name, listPage) => {
514
+ queryDbListPageRegistry.contents[name] = listPage;
515
+ };
516
+ let getQueryDbListPage = name => queryDbListPageRegistry.contents[name];
473
517
  let registerEventLogReplay = (name, replay) => {
474
518
  eventLogReplayRegistry.contents[name] = replay;
475
519
  };
@@ -518,6 +562,13 @@ function Make($star) {
518
562
  pending.push(topicName);
519
563
  eventCollectorPendingTopics.contents[ecName] = pending;
520
564
  };
565
+ let projectionCatchupRegistry = {
566
+ contents: {}
567
+ };
568
+ let registerProjectionCatchupHandler = (name, handler) => {
569
+ projectionCatchupRegistry.contents[name] = handler;
570
+ };
571
+ let projectionCatchupHandlers = () => Object.entries(projectionCatchupRegistry.contents);
521
572
  let reset = () => {
522
573
  let shutdownAll = Effect$1.map(Effect$1.all(Object.values(eventHubs.contents).map(hub => PubSub.shutdown(hub)), {
523
574
  concurrency: "unbounded"
@@ -530,11 +581,14 @@ function Make($star) {
530
581
  queryDbRegistry.contents = {};
531
582
  queryDbScanRegistry.contents = {};
532
583
  queryDbStreamRegistry.contents = {};
584
+ queryDbIndexLookupRegistry.contents = {};
585
+ queryDbListPageRegistry.contents = {};
533
586
  eventLogReplayRegistry.contents = {};
534
587
  dcbEventLogReadRegistry.contents = {};
535
588
  stateChangeListeners.contents = {};
536
589
  eventCollectorHandlers.contents = {};
537
590
  eventCollectorPendingTopics.contents = {};
591
+ projectionCatchupRegistry.contents = {};
538
592
  };
539
593
  return {
540
594
  publishEvent: publishEvent,
@@ -548,6 +602,10 @@ function Make($star) {
548
602
  getQueryDbScan: getQueryDbScan,
549
603
  registerQueryDbStream: registerQueryDbStream,
550
604
  getQueryDbStream: getQueryDbStream,
605
+ registerQueryDbIndexLookup: registerQueryDbIndexLookup,
606
+ getQueryDbIndexLookup: getQueryDbIndexLookup,
607
+ registerQueryDbListPage: registerQueryDbListPage,
608
+ getQueryDbListPage: getQueryDbListPage,
551
609
  registerEventLogReplay: registerEventLogReplay,
552
610
  getEventLogReplay: getEventLogReplay,
553
611
  registerDcbEventLogRead: registerDcbEventLogRead,
@@ -556,6 +614,8 @@ function Make($star) {
556
614
  subscribeToStateChanges: subscribeToStateChanges,
557
615
  registerEventCollectorHandler: registerEventCollectorHandler,
558
616
  subscribeEventCollectorToTopic: subscribeEventCollectorToTopic,
617
+ registerProjectionCatchupHandler: registerProjectionCatchupHandler,
618
+ projectionCatchupHandlers: projectionCatchupHandlers,
559
619
  reset: reset
560
620
  };
561
621
  }
@@ -582,6 +642,12 @@ function MakeSilent($star) {
582
642
  let queryDbStreamRegistry = {
583
643
  contents: {}
584
644
  };
645
+ let queryDbIndexLookupRegistry = {
646
+ contents: {}
647
+ };
648
+ let queryDbListPageRegistry = {
649
+ contents: {}
650
+ };
585
651
  let eventLogReplayRegistry = {
586
652
  contents: {}
587
653
  };
@@ -706,6 +772,14 @@ function MakeSilent($star) {
706
772
  queryDbStreamRegistry.contents[name] = streamFn;
707
773
  };
708
774
  let getQueryDbStream = name => queryDbStreamRegistry.contents[name];
775
+ let registerQueryDbIndexLookup = (name, lookup) => {
776
+ queryDbIndexLookupRegistry.contents[name] = lookup;
777
+ };
778
+ let getQueryDbIndexLookup = name => queryDbIndexLookupRegistry.contents[name];
779
+ let registerQueryDbListPage = (name, listPage) => {
780
+ queryDbListPageRegistry.contents[name] = listPage;
781
+ };
782
+ let getQueryDbListPage = name => queryDbListPageRegistry.contents[name];
709
783
  let registerEventLogReplay = (name, replay) => {
710
784
  eventLogReplayRegistry.contents[name] = replay;
711
785
  };
@@ -754,6 +828,13 @@ function MakeSilent($star) {
754
828
  pending.push(topicName);
755
829
  eventCollectorPendingTopics.contents[ecName] = pending;
756
830
  };
831
+ let projectionCatchupRegistry = {
832
+ contents: {}
833
+ };
834
+ let registerProjectionCatchupHandler = (name, handler) => {
835
+ projectionCatchupRegistry.contents[name] = handler;
836
+ };
837
+ let projectionCatchupHandlers = () => Object.entries(projectionCatchupRegistry.contents);
757
838
  let reset = () => {
758
839
  let shutdownAll = Effect$1.map(Effect$1.all(Object.values(eventHubs.contents).map(hub => PubSub.shutdown(hub)), {
759
840
  concurrency: "unbounded"
@@ -766,11 +847,14 @@ function MakeSilent($star) {
766
847
  queryDbRegistry.contents = {};
767
848
  queryDbScanRegistry.contents = {};
768
849
  queryDbStreamRegistry.contents = {};
850
+ queryDbIndexLookupRegistry.contents = {};
851
+ queryDbListPageRegistry.contents = {};
769
852
  eventLogReplayRegistry.contents = {};
770
853
  dcbEventLogReadRegistry.contents = {};
771
854
  stateChangeListeners.contents = {};
772
855
  eventCollectorHandlers.contents = {};
773
856
  eventCollectorPendingTopics.contents = {};
857
+ projectionCatchupRegistry.contents = {};
774
858
  };
775
859
  return {
776
860
  publishEvent: publishEvent,
@@ -784,6 +868,10 @@ function MakeSilent($star) {
784
868
  getQueryDbScan: getQueryDbScan,
785
869
  registerQueryDbStream: registerQueryDbStream,
786
870
  getQueryDbStream: getQueryDbStream,
871
+ registerQueryDbIndexLookup: registerQueryDbIndexLookup,
872
+ getQueryDbIndexLookup: getQueryDbIndexLookup,
873
+ registerQueryDbListPage: registerQueryDbListPage,
874
+ getQueryDbListPage: getQueryDbListPage,
787
875
  registerEventLogReplay: registerEventLogReplay,
788
876
  getEventLogReplay: getEventLogReplay,
789
877
  registerDcbEventLogRead: registerDcbEventLogRead,
@@ -792,6 +880,8 @@ function MakeSilent($star) {
792
880
  subscribeToStateChanges: subscribeToStateChanges,
793
881
  registerEventCollectorHandler: registerEventCollectorHandler,
794
882
  subscribeEventCollectorToTopic: subscribeEventCollectorToTopic,
883
+ registerProjectionCatchupHandler: registerProjectionCatchupHandler,
884
+ projectionCatchupHandlers: projectionCatchupHandlers,
795
885
  reset: reset
796
886
  };
797
887
  }
@@ -819,6 +909,12 @@ function MakeBounded(C) {
819
909
  let queryDbStreamRegistry = {
820
910
  contents: {}
821
911
  };
912
+ let queryDbIndexLookupRegistry = {
913
+ contents: {}
914
+ };
915
+ let queryDbListPageRegistry = {
916
+ contents: {}
917
+ };
822
918
  let eventLogReplayRegistry = {
823
919
  contents: {}
824
920
  };
@@ -940,6 +1036,14 @@ function MakeBounded(C) {
940
1036
  queryDbStreamRegistry.contents[name] = streamFn;
941
1037
  };
942
1038
  let getQueryDbStream = name => queryDbStreamRegistry.contents[name];
1039
+ let registerQueryDbIndexLookup = (name, lookup) => {
1040
+ queryDbIndexLookupRegistry.contents[name] = lookup;
1041
+ };
1042
+ let getQueryDbIndexLookup = name => queryDbIndexLookupRegistry.contents[name];
1043
+ let registerQueryDbListPage = (name, listPage) => {
1044
+ queryDbListPageRegistry.contents[name] = listPage;
1045
+ };
1046
+ let getQueryDbListPage = name => queryDbListPageRegistry.contents[name];
943
1047
  let registerEventLogReplay = (name, replay) => {
944
1048
  eventLogReplayRegistry.contents[name] = replay;
945
1049
  };
@@ -988,6 +1092,13 @@ function MakeBounded(C) {
988
1092
  pending.push(topicName);
989
1093
  eventCollectorPendingTopics.contents[ecName] = pending;
990
1094
  };
1095
+ let projectionCatchupRegistry = {
1096
+ contents: {}
1097
+ };
1098
+ let registerProjectionCatchupHandler = (name, handler) => {
1099
+ projectionCatchupRegistry.contents[name] = handler;
1100
+ };
1101
+ let projectionCatchupHandlers = () => Object.entries(projectionCatchupRegistry.contents);
991
1102
  let reset = () => {
992
1103
  let shutdownAll = Effect$1.map(Effect$1.all(Object.values(eventHubs.contents).map(hub => PubSub.shutdown(hub)), {
993
1104
  concurrency: "unbounded"
@@ -1000,11 +1111,14 @@ function MakeBounded(C) {
1000
1111
  queryDbRegistry.contents = {};
1001
1112
  queryDbScanRegistry.contents = {};
1002
1113
  queryDbStreamRegistry.contents = {};
1114
+ queryDbIndexLookupRegistry.contents = {};
1115
+ queryDbListPageRegistry.contents = {};
1003
1116
  eventLogReplayRegistry.contents = {};
1004
1117
  dcbEventLogReadRegistry.contents = {};
1005
1118
  stateChangeListeners.contents = {};
1006
1119
  eventCollectorHandlers.contents = {};
1007
1120
  eventCollectorPendingTopics.contents = {};
1121
+ projectionCatchupRegistry.contents = {};
1008
1122
  };
1009
1123
  return {
1010
1124
  publishEvent: publishEvent,
@@ -1018,6 +1132,10 @@ function MakeBounded(C) {
1018
1132
  getQueryDbScan: getQueryDbScan,
1019
1133
  registerQueryDbStream: registerQueryDbStream,
1020
1134
  getQueryDbStream: getQueryDbStream,
1135
+ registerQueryDbIndexLookup: registerQueryDbIndexLookup,
1136
+ getQueryDbIndexLookup: getQueryDbIndexLookup,
1137
+ registerQueryDbListPage: registerQueryDbListPage,
1138
+ getQueryDbListPage: getQueryDbListPage,
1021
1139
  registerEventLogReplay: registerEventLogReplay,
1022
1140
  getEventLogReplay: getEventLogReplay,
1023
1141
  registerDcbEventLogRead: registerDcbEventLogRead,
@@ -1026,6 +1144,8 @@ function MakeBounded(C) {
1026
1144
  subscribeToStateChanges: subscribeToStateChanges,
1027
1145
  registerEventCollectorHandler: registerEventCollectorHandler,
1028
1146
  subscribeEventCollectorToTopic: subscribeEventCollectorToTopic,
1147
+ registerProjectionCatchupHandler: registerProjectionCatchupHandler,
1148
+ projectionCatchupHandlers: projectionCatchupHandlers,
1029
1149
  reset: reset
1030
1150
  };
1031
1151
  }