@livestore/common 0.4.0 → 0.5.0-dev.0
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/dist/.tsbuildinfo +1 -1
- package/dist/ClientSessionLeaderThreadProxy.d.ts +1 -1
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
- package/dist/MaterializationJournal.d.ts +44 -0
- package/dist/MaterializationJournal.d.ts.map +1 -0
- package/dist/MaterializationJournal.js +112 -0
- package/dist/MaterializationJournal.js.map +1 -0
- package/dist/StateHead.d.ts +26 -0
- package/dist/StateHead.d.ts.map +1 -0
- package/dist/StateHead.js +50 -0
- package/dist/StateHead.js.map +1 -0
- package/dist/WorkerTransportError.d.ts +3 -3
- package/dist/WorkerTransportError.d.ts.map +1 -1
- package/dist/WorkerTransportError.js +3 -3
- package/dist/WorkerTransportError.js.map +1 -1
- package/dist/__tests__/fixture.d.ts +1 -1
- package/dist/__tests__/fixture.d.ts.map +1 -1
- package/dist/__tests__/fixture.js +3 -3
- package/dist/__tests__/fixture.js.map +1 -1
- package/dist/adapter-types.d.ts +29 -57
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +20 -37
- package/dist/adapter-types.js.map +1 -1
- package/dist/debug-info.d.ts +56 -56
- package/dist/debug-info.d.ts.map +1 -1
- package/dist/debug-info.js +28 -41
- package/dist/debug-info.js.map +1 -1
- package/dist/defs.d.ts +9 -9
- package/dist/defs.js +2 -2
- package/dist/devtools/devtools-compatibility.test.js +1 -0
- package/dist/devtools/devtools-compatibility.test.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +520 -332
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +76 -74
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +27 -27
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +5 -5
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +405 -343
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +101 -89
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/devtools/devtools-sessioninfo.d.ts +18 -19
- package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
- package/dist/devtools/devtools-sessioninfo.js +8 -5
- package/dist/devtools/devtools-sessioninfo.js.map +1 -1
- package/dist/devtools/mod.d.ts +4 -5
- package/dist/devtools/mod.d.ts.map +1 -1
- package/dist/devtools/mod.js +9 -5
- package/dist/devtools/mod.js.map +1 -1
- package/dist/errors.d.ts +45 -69
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -16
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +66 -18
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +519 -461
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/RejectedPushError.d.ts +67 -36
- package/dist/leader-thread/RejectedPushError.d.ts.map +1 -1
- package/dist/leader-thread/RejectedPushError.js +24 -5
- package/dist/leader-thread/RejectedPushError.js.map +1 -1
- package/dist/leader-thread/connection.d.ts +1 -0
- package/dist/leader-thread/connection.d.ts.map +1 -1
- package/dist/leader-thread/connection.js +9 -8
- package/dist/leader-thread/connection.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +4 -4
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +6 -6
- package/dist/leader-thread/eventlog.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +33 -17
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +9 -5
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +25 -35
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.test.js +7 -7
- package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -1
- package/dist/leader-thread/materialize-event.d.ts +2 -1
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +4 -0
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +18 -39
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/shutdown-channel.d.ts +2 -6
- package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
- package/dist/leader-thread/shutdown-channel.js +2 -3
- package/dist/leader-thread/shutdown-channel.js.map +1 -1
- package/dist/leader-thread/stream-events.d.ts +4 -7
- package/dist/leader-thread/stream-events.d.ts.map +1 -1
- package/dist/leader-thread/stream-events.js +13 -16
- package/dist/leader-thread/stream-events.js.map +1 -1
- package/dist/leader-thread/types.d.ts +32 -69
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js +5 -5
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/logging.d.ts +5 -30
- package/dist/logging.d.ts.map +1 -1
- package/dist/logging.js +1 -32
- package/dist/logging.js.map +1 -1
- package/dist/make-client-session.d.ts +1 -2
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/make-client-session.js +3 -3
- package/dist/make-client-session.js.map +1 -1
- package/dist/materializer-helper.d.ts +0 -1
- package/dist/materializer-helper.d.ts.map +1 -1
- package/dist/materializer-helper.js +7 -35
- package/dist/materializer-helper.js.map +1 -1
- package/dist/otel.d.ts +2 -3
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +2 -7
- package/dist/otel.js.map +1 -1
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +28 -26
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef/define.d.ts +4 -4
- package/dist/schema/EventDef/define.d.ts.map +1 -1
- package/dist/schema/EventDef/define.js +5 -5
- package/dist/schema/EventDef/define.js.map +1 -1
- package/dist/schema/EventDef/define.test.d.ts +2 -0
- package/dist/schema/EventDef/define.test.d.ts.map +1 -0
- package/dist/schema/EventDef/define.test.js +23 -0
- package/dist/schema/EventDef/define.test.js.map +1 -0
- package/dist/schema/EventDef/deprecated.d.ts +8 -13
- package/dist/schema/EventDef/deprecated.d.ts.map +1 -1
- package/dist/schema/EventDef/deprecated.js +12 -13
- package/dist/schema/EventDef/deprecated.js.map +1 -1
- package/dist/schema/EventDef/deprecated.test.js +1 -1
- package/dist/schema/EventDef/deprecated.test.js.map +1 -1
- package/dist/schema/EventDef/event-def.d.ts +1 -1
- package/dist/schema/EventDef/event-def.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber/client.d.ts +12 -12
- package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber/client.js +8 -9
- package/dist/schema/EventSequenceNumber/client.js.map +1 -1
- package/dist/schema/EventSequenceNumber/global.d.ts +2 -2
- package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber/global.js +1 -1
- package/dist/schema/EventSequenceNumber/global.js.map +1 -1
- package/dist/schema/EventSequenceNumber.test.js +5 -5
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/LiveStoreEvent/client.d.ts +50 -179
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent/client.js +32 -29
- package/dist/schema/LiveStoreEvent/client.js.map +1 -1
- package/dist/schema/LiveStoreEvent/client.test.js +11 -2
- package/dist/schema/LiveStoreEvent/client.test.js.map +1 -1
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts +7 -7
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent/global.d.ts +6 -6
- package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent/global.js +1 -1
- package/dist/schema/LiveStoreEvent/global.js.map +1 -1
- package/dist/schema/LiveStoreEvent/input.d.ts +5 -5
- package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent/input.js +3 -3
- package/dist/schema/LiveStoreEvent/input.js.map +1 -1
- package/dist/schema/mod.d.ts +1 -0
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +1 -0
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +3 -2
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +12 -17
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +23 -20
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +29 -8
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.d.ts +13 -13
- package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.js +13 -15
- package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js +19 -43
- package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.d.ts +1 -1
- package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-def.js +57 -31
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +118 -72
- package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.test.js +2 -2
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -2
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +13 -4
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +9 -9
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +8 -13
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +27 -16
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +13 -11
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js +5 -3
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts +1 -3
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +1 -1
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/persistence.d.ts +11 -0
- package/dist/schema/state/sqlite/persistence.d.ts.map +1 -0
- package/dist/schema/state/sqlite/persistence.js +10 -0
- package/dist/schema/state/sqlite/persistence.js.map +1 -0
- package/dist/schema/state/sqlite/query-builder/api.d.ts +7 -7
- package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.js +27 -23
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts +3 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +16 -14
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +362 -596
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.js +1 -1
- package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts +102 -134
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -1
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +2 -2
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -1
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +328 -106
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -1
- package/dist/schema/state/sqlite/system-tables/state-tables.js +33 -1
- package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.d.ts +16 -19
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/table-def.js +53 -3
- package/dist/schema/state/sqlite/table-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +153 -36
- package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
- package/dist/schema/unknown-events.d.ts.map +1 -1
- package/dist/schema/unknown-events.js +2 -1
- package/dist/schema/unknown-events.js.map +1 -1
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +2 -2
- package/dist/session-id-symbol.d.ts +29 -0
- package/dist/session-id-symbol.d.ts.map +1 -0
- package/dist/session-id-symbol.js +44 -0
- package/dist/session-id-symbol.js.map +1 -0
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +8 -10
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/sql-queries/types.d.ts +6 -7
- package/dist/sql-queries/types.d.ts.map +1 -1
- package/dist/sql-queries/types.js.map +1 -1
- package/dist/sqlite-db-helper.d.ts +21 -1
- package/dist/sqlite-db-helper.d.ts.map +1 -1
- package/dist/sqlite-db-helper.js +37 -2
- package/dist/sqlite-db-helper.js.map +1 -1
- package/dist/sqlite-types.d.ts +3 -6
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/sqlite-types.js +3 -3
- package/dist/sqlite-types.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +38 -16
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +196 -66
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/errors.d.ts +12 -18
- package/dist/sync/errors.d.ts.map +1 -1
- package/dist/sync/errors.js +2 -2
- package/dist/sync/errors.js.map +1 -1
- package/dist/sync/mock-sync-backend.d.ts +2 -3
- package/dist/sync/mock-sync-backend.d.ts.map +1 -1
- package/dist/sync/mock-sync-backend.js +54 -33
- package/dist/sync/mock-sync-backend.js.map +1 -1
- package/dist/sync/mock-sync-backend.test.d.ts +2 -0
- package/dist/sync/mock-sync-backend.test.d.ts.map +1 -0
- package/dist/sync/mock-sync-backend.test.js +49 -0
- package/dist/sync/mock-sync-backend.test.js.map +1 -0
- package/dist/sync/next/history-dag-common.d.ts +4 -0
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +52 -31
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/history-dag.d.ts.map +1 -1
- package/dist/sync/next/history-dag.js +2 -1
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
- package/dist/sync/next/test/event-fixtures.d.ts +7 -7
- package/dist/sync/next/test/event-fixtures.js +1 -1
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/next/test/history-dag-common.test.d.ts +2 -0
- package/dist/sync/next/test/history-dag-common.test.d.ts.map +1 -0
- package/dist/sync/next/test/history-dag-common.test.js +73 -0
- package/dist/sync/next/test/history-dag-common.test.js.map +1 -0
- package/dist/sync/sync-backend-kv.d.ts.map +1 -1
- package/dist/sync/sync-backend-kv.js +4 -2
- package/dist/sync/sync-backend-kv.js.map +1 -1
- package/dist/sync/sync-backend.d.ts +15 -15
- package/dist/sync/sync-backend.d.ts.map +1 -1
- package/dist/sync/sync-backend.js +9 -5
- package/dist/sync/sync-backend.js.map +1 -1
- package/dist/sync/sync.d.ts +1 -1
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/syncstate.d.ts +97 -173
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +34 -37
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +100 -61
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/transport-chunking.d.ts +15 -16
- package/dist/sync/transport-chunking.d.ts.map +1 -1
- package/dist/sync/transport-chunking.js +23 -32
- package/dist/sync/transport-chunking.js.map +1 -1
- package/dist/util.d.ts +11 -4
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +19 -2
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +19 -37
- package/src/ClientSessionLeaderThreadProxy.ts +1 -1
- package/src/MaterializationJournal.ts +184 -0
- package/src/StateHead.ts +80 -0
- package/src/WorkerTransportError.ts +4 -4
- package/src/__tests__/fixture.ts +3 -3
- package/src/adapter-types.ts +24 -61
- package/src/debug-info.ts +50 -70
- package/src/defs.ts +2 -2
- package/src/devtools/devtools-compatibility.test.ts +1 -0
- package/src/devtools/devtools-messages-client-session.ts +56 -65
- package/src/devtools/devtools-messages-common.ts +12 -11
- package/src/devtools/devtools-messages-leader.ts +71 -69
- package/src/devtools/devtools-sessioninfo.ts +13 -11
- package/src/devtools/mod.ts +4 -5
- package/src/errors.ts +46 -34
- package/src/index.ts +8 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +794 -691
- package/src/leader-thread/RejectedPushError.ts +40 -27
- package/src/leader-thread/connection.ts +12 -8
- package/src/leader-thread/eventlog.ts +7 -7
- package/src/leader-thread/leader-worker-devtools.ts +37 -19
- package/src/leader-thread/make-leader-thread-layer.test.ts +7 -7
- package/src/leader-thread/make-leader-thread-layer.ts +56 -53
- package/src/leader-thread/materialize-event.ts +13 -8
- package/src/leader-thread/recreate-db.ts +24 -59
- package/src/leader-thread/shutdown-channel.ts +3 -14
- package/src/leader-thread/stream-events.ts +104 -101
- package/src/leader-thread/types.ts +24 -62
- package/src/logging.ts +5 -52
- package/src/make-client-session.ts +6 -6
- package/src/materializer-helper.ts +8 -37
- package/src/otel.ts +5 -14
- package/src/rematerialize-from-eventlog.ts +97 -94
- package/src/schema/EventDef/define.test.ts +28 -0
- package/src/schema/EventDef/define.ts +20 -19
- package/src/schema/EventDef/deprecated.test.ts +1 -8
- package/src/schema/EventDef/deprecated.ts +17 -20
- package/src/schema/EventDef/event-def.ts +2 -4
- package/src/schema/EventSequenceNumber/client.ts +8 -9
- package/src/schema/EventSequenceNumber/global.ts +1 -1
- package/src/schema/EventSequenceNumber.test.ts +5 -5
- package/src/schema/LiveStoreEvent/client.test.ts +17 -4
- package/src/schema/LiveStoreEvent/client.ts +36 -35
- package/src/schema/LiveStoreEvent/for-event-def.ts +7 -7
- package/src/schema/LiveStoreEvent/global.ts +1 -1
- package/src/schema/LiveStoreEvent/input.ts +6 -6
- package/src/schema/mod.ts +1 -0
- package/src/schema/schema.ts +3 -2
- package/src/schema/state/sqlite/client-document-def.test.ts +32 -13
- package/src/schema/state/sqlite/client-document-def.ts +95 -80
- package/src/schema/state/sqlite/column-annotations.test.ts +26 -45
- package/src/schema/state/sqlite/column-annotations.ts +26 -30
- package/src/schema/state/sqlite/column-def.test.ts +132 -77
- package/src/schema/state/sqlite/column-def.ts +72 -37
- package/src/schema/state/sqlite/column-spec.test.ts +2 -2
- package/src/schema/state/sqlite/column-spec.ts +3 -2
- package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +15 -5
- package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +123 -63
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -16
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +25 -31
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +35 -21
- package/src/schema/state/sqlite/mod.ts +2 -4
- package/src/schema/state/sqlite/persistence.ts +11 -0
- package/src/schema/state/sqlite/query-builder/api.ts +9 -9
- package/src/schema/state/sqlite/query-builder/astToSql.ts +31 -26
- package/src/schema/state/sqlite/query-builder/impl.test.ts +433 -669
- package/src/schema/state/sqlite/query-builder/impl.ts +19 -15
- package/src/schema/state/sqlite/schema-helpers.ts +1 -1
- package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +2 -2
- package/src/schema/state/sqlite/system-tables/state-tables.ts +41 -1
- package/src/schema/state/sqlite/table-def.test.ts +204 -66
- package/src/schema/state/sqlite/table-def.ts +96 -45
- package/src/schema/unknown-events.ts +3 -2
- package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +2 -2
- package/src/session-id-symbol.ts +59 -0
- package/src/sql-queries/sql-queries.ts +8 -12
- package/src/sql-queries/types.ts +6 -7
- package/src/sqlite-db-helper.ts +64 -2
- package/src/sqlite-types.ts +5 -8
- package/src/sync/ClientSessionSyncProcessor.ts +303 -119
- package/src/sync/errors.ts +14 -12
- package/src/sync/mock-sync-backend.test.ts +78 -0
- package/src/sync/mock-sync-backend.ts +93 -47
- package/src/sync/next/history-dag-common.ts +60 -34
- package/src/sync/next/history-dag.ts +4 -1
- package/src/sync/next/test/compact-events.calculator.test.ts +2 -2
- package/src/sync/next/test/event-fixtures.ts +1 -1
- package/src/sync/next/test/history-dag-common.test.ts +87 -0
- package/src/sync/sync-backend-kv.ts +4 -2
- package/src/sync/sync-backend.ts +15 -15
- package/src/sync/sync.ts +1 -1
- package/src/sync/syncstate.test.ts +191 -140
- package/src/sync/syncstate.ts +63 -53
- package/src/sync/transport-chunking.ts +34 -39
- package/src/util.ts +18 -9
- package/src/version.ts +1 -2
- package/dist/sql-queries/misc.d.ts +0 -2
- package/dist/sql-queries/misc.d.ts.map +0 -1
- package/dist/sql-queries/misc.js +0 -2
- package/dist/sql-queries/misc.js.map +0 -1
- package/src/sql-queries/misc.ts +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Push validation errors returned by {@link LeaderSyncProcessor.push}.
|
|
3
3
|
*
|
|
4
|
-
* All
|
|
4
|
+
* All errors share a common {@link RejectedPushErrorTypeId} so consumers can catch the
|
|
5
5
|
* family as a group via {@link isRejectedPushError} instead of matching individual tags.
|
|
6
6
|
* Recovery is the same in every case: the client should rebase and retry.
|
|
7
7
|
*
|
|
@@ -23,19 +23,16 @@ export const RejectedPushErrorTypeId = '~@livestore/common/RejectedPushError' as
|
|
|
23
23
|
*/
|
|
24
24
|
export class NonMonotonicBatchError extends Schema.TaggedError<NonMonotonicBatchError>(
|
|
25
25
|
`${RejectedPushErrorTypeId}/NonMonotonicBatchError`,
|
|
26
|
-
)(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
sessionId: Schema.String,
|
|
37
|
-
},
|
|
38
|
-
) {
|
|
26
|
+
)('NonMonotonicBatchError', {
|
|
27
|
+
/** The sequence number that broke the monotonic invariant (i.e. the one that is >= the next). */
|
|
28
|
+
precedingSeqNum: EventSequenceNumber.Client.Composite,
|
|
29
|
+
/** The sequence number that was expected to be greater than `precedingSeqNum`. */
|
|
30
|
+
violatingSeqNum: EventSequenceNumber.Client.Composite,
|
|
31
|
+
/** The index in the batch where the violation occurred. */
|
|
32
|
+
violationIndex: Schema.Finite,
|
|
33
|
+
/** The session that produced the malformed batch. */
|
|
34
|
+
sessionId: Schema.String,
|
|
35
|
+
}) {
|
|
39
36
|
readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
|
|
40
37
|
|
|
41
38
|
override get message(): string {
|
|
@@ -43,6 +40,24 @@ export class NonMonotonicBatchError extends Schema.TaggedError<NonMonotonicBatch
|
|
|
43
40
|
}
|
|
44
41
|
}
|
|
45
42
|
|
|
43
|
+
/** A pushed batch skips an event required to connect it to the leader's admitted push prefix. */
|
|
44
|
+
export class NonContiguousBatchError extends Schema.TaggedError<NonContiguousBatchError>(
|
|
45
|
+
`${RejectedPushErrorTypeId}/NonContiguousBatchError`,
|
|
46
|
+
)('NonContiguousBatchError', {
|
|
47
|
+
expectedSeqNum: EventSequenceNumber.Client.Composite,
|
|
48
|
+
providedSeqNum: EventSequenceNumber.Client.Composite,
|
|
49
|
+
expectedParentSeqNum: EventSequenceNumber.Client.Composite,
|
|
50
|
+
providedParentSeqNum: EventSequenceNumber.Client.Composite,
|
|
51
|
+
violationIndex: Schema.Finite,
|
|
52
|
+
sessionId: Schema.String,
|
|
53
|
+
}) {
|
|
54
|
+
readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
|
|
55
|
+
|
|
56
|
+
override get message(): string {
|
|
57
|
+
return `Pushed events are not contiguous at index ${this.violationIndex} (session ${this.sessionId}): expected ${EventSequenceNumber.Client.toString(this.expectedSeqNum)} after ${EventSequenceNumber.Client.toString(this.expectedParentSeqNum)}, got ${EventSequenceNumber.Client.toString(this.providedSeqNum)} after ${EventSequenceNumber.Client.toString(this.providedParentSeqNum)}`
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
46
61
|
/**
|
|
47
62
|
* A pushed batch of events failed validation because its rebase generation is older than the leader's current rebase generation.
|
|
48
63
|
*
|
|
@@ -52,17 +67,14 @@ export class NonMonotonicBatchError extends Schema.TaggedError<NonMonotonicBatch
|
|
|
52
67
|
*/
|
|
53
68
|
export class StaleRebaseGenerationError extends Schema.TaggedError<StaleRebaseGenerationError>(
|
|
54
69
|
`${RejectedPushErrorTypeId}/StaleRebaseGenerationError`,
|
|
55
|
-
)(
|
|
56
|
-
'
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
sessionId: Schema.String,
|
|
64
|
-
},
|
|
65
|
-
) {
|
|
70
|
+
)('StaleRebaseGenerationError', {
|
|
71
|
+
/** The leader's current rebase generation. */
|
|
72
|
+
currentRebaseGeneration: Schema.Finite,
|
|
73
|
+
/** The rebase generation carried by the dropped events. */
|
|
74
|
+
providedRebaseGeneration: Schema.Finite,
|
|
75
|
+
/** The session that produced the stale batch. */
|
|
76
|
+
sessionId: Schema.String,
|
|
77
|
+
}) {
|
|
66
78
|
readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
|
|
67
79
|
|
|
68
80
|
override get message(): string {
|
|
@@ -94,11 +106,12 @@ export class LeaderAheadError extends Schema.TaggedError<LeaderAheadError>(
|
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
108
|
|
|
97
|
-
export const RejectedPushError = Schema.Union(
|
|
109
|
+
export const RejectedPushError = Schema.Union([
|
|
98
110
|
LeaderAheadError,
|
|
111
|
+
NonContiguousBatchError,
|
|
99
112
|
NonMonotonicBatchError,
|
|
100
113
|
StaleRebaseGenerationError,
|
|
101
|
-
)
|
|
114
|
+
])
|
|
102
115
|
|
|
103
116
|
export type RejectedPushError = typeof RejectedPushError.Type
|
|
104
117
|
|
|
@@ -83,14 +83,18 @@ export const execSql = (sqliteDb: SqliteDb, sql: string, bind: BindValues) => {
|
|
|
83
83
|
)
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
export const selectSql = <T>(sqliteDb: SqliteDb, sql: string, bind: BindValues) => {
|
|
87
|
+
const bindValues = prepareBindValues(bind, sql)
|
|
88
|
+
return Effect.try({
|
|
89
|
+
try: () => sqliteDb.select<T>(sql, bindValues),
|
|
90
|
+
catch: (cause) =>
|
|
91
|
+
new SqliteError({ cause, query: { bindValues, sql }, code: (cause as WaSqlite.SQLiteError).code }),
|
|
92
|
+
}).pipe(
|
|
93
|
+
Effect.withSpan(`@livestore/common:selectSql`, {
|
|
94
|
+
attributes: { 'span.label': sql, sql, bindValueKeys: Object.keys(bindValues) },
|
|
95
|
+
}),
|
|
96
|
+
)
|
|
97
|
+
}
|
|
94
98
|
|
|
95
99
|
// TODO actually use prepared statements
|
|
96
100
|
export const execSqlPrepared = (sqliteDb: SqliteDb, sql: string, bindValues: PreparedBindValues) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
|
|
2
|
-
import {
|
|
2
|
+
import { Effect, Option, Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import type { SqliteDb } from '../adapter-types.ts'
|
|
5
5
|
import { migrateTable } from '../schema-management/migrations.ts'
|
|
@@ -107,7 +107,7 @@ export const getEventsFromEventlog = ({
|
|
|
107
107
|
}: {
|
|
108
108
|
dbEventlog: SqliteDb
|
|
109
109
|
options: StreamEventsOptions
|
|
110
|
-
}): Effect.Effect<
|
|
110
|
+
}): Effect.Effect<ReadonlyArray<LiveStoreEvent.Client.Encoded>> =>
|
|
111
111
|
Effect.gen(function* () {
|
|
112
112
|
const since = options.since ?? EventSequenceNumber.Client.ROOT
|
|
113
113
|
const batchSize = options.batchSize ?? STREAM_EVENTS_BATCH_SIZE_DEFAULT
|
|
@@ -146,7 +146,7 @@ export const getEventsFromEventlog = ({
|
|
|
146
146
|
const eventlogEvents = yield* Effect.sync(() => dbEventlog.select(makeQuery()))
|
|
147
147
|
|
|
148
148
|
if (eventlogEvents.length === 0) {
|
|
149
|
-
return
|
|
149
|
+
return []
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
const spanAttributes = {
|
|
@@ -174,7 +174,7 @@ export const getEventsFromEventlog = ({
|
|
|
174
174
|
})
|
|
175
175
|
})
|
|
176
176
|
|
|
177
|
-
return
|
|
177
|
+
return encodedEvents
|
|
178
178
|
}).pipe(Effect.withSpan('@livestore/common:eventlog:getEventsFromEventlog', { attributes: spanAttributes }))
|
|
179
179
|
})
|
|
180
180
|
|
|
@@ -201,7 +201,7 @@ export const updateBackendHead = (dbEventlog: SqliteDb, head: EventSequenceNumbe
|
|
|
201
201
|
dbEventlog.execute(sql`UPDATE ${SYNC_STATUS_TABLE} SET head = ${head.global}`)
|
|
202
202
|
|
|
203
203
|
export const getBackendIdFromDb = (dbEventlog: SqliteDb): Option.Option<string> =>
|
|
204
|
-
Option.
|
|
204
|
+
Option.fromNullishOr(
|
|
205
205
|
dbEventlog.select<{ backendId: string | null }>(sql`select backendId from ${SYNC_STATUS_TABLE}`)[0]?.backendId,
|
|
206
206
|
)
|
|
207
207
|
|
|
@@ -284,14 +284,14 @@ export const getSyncBackendCursorInfo = ({ remoteHead }: { remoteHead: EventSequ
|
|
|
284
284
|
if (remoteHead === EventSequenceNumber.Client.ROOT.global) return Option.none()
|
|
285
285
|
|
|
286
286
|
const EventlogQuerySchema = Schema.Struct({
|
|
287
|
-
syncMetadataJson: Schema.
|
|
287
|
+
syncMetadataJson: Schema.fromJsonString(Schema.toCodecJson(Schema.Option(Schema.Json))),
|
|
288
288
|
}).pipe(Schema.pluck('syncMetadataJson'), Schema.Array, Schema.head)
|
|
289
289
|
|
|
290
290
|
const syncMetadataOption = yield* Effect.sync(() =>
|
|
291
291
|
dbEventlog.select<{ syncMetadataJson: string }>(
|
|
292
292
|
sql`SELECT syncMetadataJson FROM ${EVENTLOG_META_TABLE} WHERE seqNumGlobal = ${remoteHead} ORDER BY seqNumClient ASC LIMIT 1`,
|
|
293
293
|
),
|
|
294
|
-
).pipe(Effect.andThen(Schema.
|
|
294
|
+
).pipe(Effect.andThen(Schema.decodeEffect(EventlogQuerySchema)), Effect.map(Option.flatten), Effect.orDie)
|
|
295
295
|
|
|
296
296
|
return Option.some({
|
|
297
297
|
eventSequenceNumber: remoteHead,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Effect, FiberMap, Option, Stream, SubscriptionRef } from '@livestore/utils/effect'
|
|
1
|
+
import { Cause, Effect, FiberMap, Option, Stream, SubscriptionRef } from '@livestore/utils/effect'
|
|
2
2
|
import { nanoid } from '@livestore/utils/nanoid'
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -18,7 +18,8 @@ type SendMessageToDevtools = (message: Devtools.Leader.MessageFromApp) => Effect
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Type guard for DevtoolsViteNotInstalledError.
|
|
21
|
-
*
|
|
21
|
+
* Adapter-specific devtools boot implementations may surface this tagged error;
|
|
22
|
+
* common handles it structurally to keep devtools startup environment-agnostic.
|
|
22
23
|
*/
|
|
23
24
|
const isDevtoolsViteNotInstalledError = (
|
|
24
25
|
error: unknown,
|
|
@@ -47,7 +48,7 @@ export const bootDevtools = Effect.fn('@livestore/common:leader-thread:devtools:
|
|
|
47
48
|
Effect.as(Option.none()),
|
|
48
49
|
),
|
|
49
50
|
),
|
|
50
|
-
Effect.
|
|
51
|
+
Effect.catchCause((cause) =>
|
|
51
52
|
Effect.logWarning(
|
|
52
53
|
`[@livestore/devtools] Failed to start devtools server. Devtools will be disabled.`,
|
|
53
54
|
cause,
|
|
@@ -80,7 +81,7 @@ export const bootDevtools = Effect.fn('@livestore/common:leader-thread:devtools:
|
|
|
80
81
|
.pipe(
|
|
81
82
|
Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
|
|
82
83
|
Effect.interruptible,
|
|
83
|
-
Effect.
|
|
84
|
+
Effect.ignore,
|
|
84
85
|
)
|
|
85
86
|
|
|
86
87
|
const syncState = yield* syncProcessor.syncState
|
|
@@ -92,7 +93,7 @@ export const bootDevtools = Effect.fn('@livestore/common:leader-thread:devtools:
|
|
|
92
93
|
)
|
|
93
94
|
|
|
94
95
|
yield* listenToDevtools({
|
|
95
|
-
incomingMessages: channel.listen.pipe(Stream.
|
|
96
|
+
incomingMessages: channel.listen.pipe(Stream.mapEffect(Effect.fromResult), Stream.orDie),
|
|
96
97
|
sendMessage,
|
|
97
98
|
persistenceInfo,
|
|
98
99
|
})
|
|
@@ -181,7 +182,9 @@ const listenToDevtools = ({
|
|
|
181
182
|
appVersion: liveStoreVersion,
|
|
182
183
|
receivedVersion: decodedEvent.liveStoreVersion,
|
|
183
184
|
appDevtoolsProtocolVersion: devtoolsProtocolVersion,
|
|
184
|
-
receivedDevtoolsProtocolVersion: resolveDevtoolsProtocolVersion(
|
|
185
|
+
receivedDevtoolsProtocolVersion: resolveDevtoolsProtocolVersion(
|
|
186
|
+
decodedEvent.devtoolsProtocolVersion,
|
|
187
|
+
),
|
|
185
188
|
}),
|
|
186
189
|
)
|
|
187
190
|
return
|
|
@@ -204,10 +207,13 @@ const listenToDevtools = ({
|
|
|
204
207
|
Effect.sync(() => db.close()),
|
|
205
208
|
).pipe(
|
|
206
209
|
Effect.flatMap((db) =>
|
|
207
|
-
Effect.try(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
210
|
+
Effect.try({
|
|
211
|
+
try: () => {
|
|
212
|
+
db.import(data)
|
|
213
|
+
const rows = db.select<{ name: string }>(`select name from sqlite_master where type = 'table'`)
|
|
214
|
+
return new Set(rows.map((r) => r.name))
|
|
215
|
+
},
|
|
216
|
+
catch: (cause) => new Cause.UnknownError(cause),
|
|
211
217
|
}),
|
|
212
218
|
),
|
|
213
219
|
)
|
|
@@ -217,10 +223,16 @@ const listenToDevtools = ({
|
|
|
217
223
|
if (tableNames.has(SystemTables.EVENTLOG_META_TABLE) === true) {
|
|
218
224
|
databaseKind = 'eventlog'
|
|
219
225
|
yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
|
|
220
|
-
yield* Effect.try(
|
|
226
|
+
yield* Effect.try({
|
|
227
|
+
try: () => dbEventlog.import(data),
|
|
228
|
+
catch: (cause) => new Cause.UnknownError(cause),
|
|
229
|
+
})
|
|
221
230
|
|
|
222
231
|
if (batchId === undefined) {
|
|
223
|
-
yield* Effect.try(
|
|
232
|
+
yield* Effect.try({
|
|
233
|
+
try: () => dbState.destroy(),
|
|
234
|
+
catch: (cause) => new Cause.UnknownError(cause),
|
|
235
|
+
})
|
|
224
236
|
}
|
|
225
237
|
} else if (
|
|
226
238
|
tableNames.has(SystemTables.SCHEMA_META_TABLE) === true &&
|
|
@@ -228,10 +240,16 @@ const listenToDevtools = ({
|
|
|
228
240
|
) {
|
|
229
241
|
databaseKind = 'state'
|
|
230
242
|
yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
|
|
231
|
-
yield* Effect.try(
|
|
243
|
+
yield* Effect.try({
|
|
244
|
+
try: () => dbState.import(data),
|
|
245
|
+
catch: (cause) => new Cause.UnknownError(cause),
|
|
246
|
+
})
|
|
232
247
|
|
|
233
248
|
if (batchId === undefined) {
|
|
234
|
-
yield* Effect.try(
|
|
249
|
+
yield* Effect.try({
|
|
250
|
+
try: () => dbEventlog.destroy(),
|
|
251
|
+
catch: (cause) => new Cause.UnknownError(cause),
|
|
252
|
+
})
|
|
235
253
|
}
|
|
236
254
|
} else {
|
|
237
255
|
return yield* Effect.fail({ _tag: 'unsupported-database' } as const)
|
|
@@ -261,9 +279,9 @@ const listenToDevtools = ({
|
|
|
261
279
|
}),
|
|
262
280
|
),
|
|
263
281
|
),
|
|
264
|
-
Effect.
|
|
282
|
+
Effect.catch((cause) =>
|
|
265
283
|
Effect.logWarning('Error importing database file', cause).pipe(
|
|
266
|
-
Effect.
|
|
284
|
+
Effect.andThen(
|
|
267
285
|
sendMessage(
|
|
268
286
|
Devtools.Leader.LoadDatabaseFile.Error.make({
|
|
269
287
|
...reqPayload,
|
|
@@ -339,7 +357,7 @@ const listenToDevtools = ({
|
|
|
339
357
|
// TODO consider piggybacking on the existing leader-thread sync-pulling
|
|
340
358
|
yield* syncBackend.pull(Option.none(), { live: true }).pipe(
|
|
341
359
|
Stream.map((_) => _.batch),
|
|
342
|
-
Stream.
|
|
360
|
+
Stream.flattenIterable,
|
|
343
361
|
Stream.tap(({ eventEncoded, metadata }) =>
|
|
344
362
|
sendMessage(
|
|
345
363
|
Devtools.Leader.SyncHistoryRes.make({
|
|
@@ -388,9 +406,9 @@ const listenToDevtools = ({
|
|
|
388
406
|
yield* Effect.sleep(1000)
|
|
389
407
|
|
|
390
408
|
yield* Stream.zipLatest(
|
|
391
|
-
syncBackend.isConnected
|
|
409
|
+
SubscriptionRef.changes(syncBackend.isConnected),
|
|
392
410
|
devtools.enabled === true
|
|
393
|
-
? devtools.syncBackendLatchState
|
|
411
|
+
? SubscriptionRef.changes(devtools.syncBackendLatchState)
|
|
394
412
|
: Stream.make({ latchClosed: false }),
|
|
395
413
|
).pipe(
|
|
396
414
|
Stream.tap(([isConnected, { latchClosed }]) =>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Vitest } from '@livestore/utils-dev/node-vitest'
|
|
2
|
-
import { Effect, Stream, SubscriptionRef } from '@livestore/utils/effect'
|
|
2
|
+
import { Effect, Fiber, Latch, Stream, SubscriptionRef } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import { makeMockSyncBackend } from '../sync/mock-sync-backend.ts'
|
|
5
5
|
import type { SyncBackend } from '../sync/sync.ts'
|
|
@@ -7,7 +7,7 @@ import { makeNetworkStatusSubscribable } from './make-leader-thread-layer.ts'
|
|
|
7
7
|
import type { DevtoolsContext } from './types.ts'
|
|
8
8
|
|
|
9
9
|
Vitest.describe('makeNetworkStatusSubscribable', () => {
|
|
10
|
-
Vitest.
|
|
10
|
+
Vitest.live('tracks sync backend connectivity and devtools latch state', () =>
|
|
11
11
|
Effect.gen(function* () {
|
|
12
12
|
const mockBackend = yield* makeMockSyncBackend({ startConnected: false })
|
|
13
13
|
const syncBackend = yield* mockBackend.makeSyncBackend
|
|
@@ -15,7 +15,7 @@ Vitest.describe('makeNetworkStatusSubscribable', () => {
|
|
|
15
15
|
|
|
16
16
|
const devtoolsContext: DevtoolsContext = {
|
|
17
17
|
enabled: true,
|
|
18
|
-
syncBackendLatch: yield*
|
|
18
|
+
syncBackendLatch: yield* Latch.make(true),
|
|
19
19
|
syncBackendLatchState: latchStateRef,
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -26,17 +26,17 @@ Vitest.describe('makeNetworkStatusSubscribable', () => {
|
|
|
26
26
|
Vitest.expect(initial.devtools.latchClosed).toBe(false)
|
|
27
27
|
|
|
28
28
|
const waitFor = (predicate: (status: SyncBackend.NetworkStatus) => boolean) =>
|
|
29
|
-
networkStatus.changes.pipe(Stream.filter(predicate), Stream.
|
|
29
|
+
networkStatus.changes.pipe(Stream.filter(predicate), Stream.runFirstUnsafe)
|
|
30
30
|
|
|
31
31
|
const onlineFiber = yield* waitFor((status) => status.isConnected).pipe(Effect.forkScoped)
|
|
32
32
|
yield* mockBackend.connect
|
|
33
|
-
const online = yield* onlineFiber
|
|
33
|
+
const online = yield* Fiber.join(onlineFiber)
|
|
34
34
|
Vitest.expect(online.isConnected).toBe(true)
|
|
35
|
-
Vitest.expect(online.timestampMs).
|
|
35
|
+
Vitest.expect(online.timestampMs).toBeGreaterThanOrEqual(initial.timestampMs)
|
|
36
36
|
|
|
37
37
|
const latchedFiber = yield* waitFor((status) => status.devtools.latchClosed).pipe(Effect.forkScoped)
|
|
38
38
|
yield* SubscriptionRef.set(latchStateRef, { latchClosed: true })
|
|
39
|
-
const latched = yield* latchedFiber
|
|
39
|
+
const latched = yield* Fiber.join(latchedFiber)
|
|
40
40
|
Vitest.expect(latched.devtools.latchClosed).toBe(true)
|
|
41
41
|
Vitest.expect(latched.timestampMs).toBeGreaterThanOrEqual(online.timestampMs)
|
|
42
42
|
}),
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { omitUndefineds, shouldNeverHappen } from '@livestore/utils'
|
|
2
|
-
import type { HttpClient, Scope } from '@livestore/utils/effect'
|
|
3
2
|
import {
|
|
3
|
+
type HttpClient,
|
|
4
|
+
type Scope,
|
|
4
5
|
Deferred,
|
|
5
6
|
Effect,
|
|
6
7
|
KeyValueStore,
|
|
8
|
+
Latch,
|
|
7
9
|
Layer,
|
|
8
|
-
|
|
10
|
+
Option,
|
|
9
11
|
Queue,
|
|
12
|
+
ReadonlyArray,
|
|
10
13
|
Schema,
|
|
11
14
|
Stream,
|
|
12
15
|
Subscribable,
|
|
@@ -24,12 +27,13 @@ import type { MigrationsReport } from '../defs.ts'
|
|
|
24
27
|
import type * as Devtools from '../devtools/mod.ts'
|
|
25
28
|
import type { LiveStoreSchema } from '../schema/mod.ts'
|
|
26
29
|
import { EventSequenceNumber, LiveStoreEvent, SystemTables } from '../schema/mod.ts'
|
|
30
|
+
import type * as StateHead from '../StateHead.ts'
|
|
27
31
|
import type { SyncBackend, SyncOptions } from '../sync/sync.ts'
|
|
28
32
|
import { SyncState } from '../sync/syncstate.ts'
|
|
29
33
|
import { sql } from '../util.ts'
|
|
30
34
|
import * as Eventlog from './eventlog.ts'
|
|
31
|
-
import { makeLeaderSyncProcessor } from './LeaderSyncProcessor.ts'
|
|
32
35
|
import { bootDevtools } from './leader-worker-devtools.ts'
|
|
36
|
+
import * as LeaderSyncProcessor from './LeaderSyncProcessor.ts'
|
|
33
37
|
import { makeMaterializeEvent } from './materialize-event.ts'
|
|
34
38
|
import { recreateDb } from './recreate-db.ts'
|
|
35
39
|
import type { ShutdownChannel } from './shutdown-channel.ts'
|
|
@@ -45,8 +49,8 @@ import { LeaderThreadCtx } from './types.ts'
|
|
|
45
49
|
|
|
46
50
|
export interface MakeLeaderThreadLayerParams {
|
|
47
51
|
storeId: string
|
|
48
|
-
syncPayloadSchema: Schema.Schema
|
|
49
|
-
syncPayloadEncoded: Schema.
|
|
52
|
+
syncPayloadSchema: Schema.Decoder<Schema.Json> | undefined
|
|
53
|
+
syncPayloadEncoded: Schema.Json | undefined
|
|
50
54
|
clientId: string
|
|
51
55
|
schema: LiveStoreSchema
|
|
52
56
|
makeSqliteDb: MakeSqliteDb
|
|
@@ -66,6 +70,9 @@ export interface MakeLeaderThreadLayerParams {
|
|
|
66
70
|
delays?: {
|
|
67
71
|
localPushProcessing?: Effect.Effect<void>
|
|
68
72
|
}
|
|
73
|
+
hooks?: {
|
|
74
|
+
localPushAdmitted?: (events: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>) => Effect.Effect<void>
|
|
75
|
+
}
|
|
69
76
|
}
|
|
70
77
|
}
|
|
71
78
|
}
|
|
@@ -74,7 +81,7 @@ export const makeLeaderThreadLayer = ({
|
|
|
74
81
|
schema,
|
|
75
82
|
storeId,
|
|
76
83
|
clientId,
|
|
77
|
-
syncPayloadSchema = Schema.
|
|
84
|
+
syncPayloadSchema = Schema.Json,
|
|
78
85
|
syncPayloadEncoded,
|
|
79
86
|
makeSqliteDb,
|
|
80
87
|
syncOptions,
|
|
@@ -85,12 +92,18 @@ export const makeLeaderThreadLayer = ({
|
|
|
85
92
|
bootWarning,
|
|
86
93
|
params,
|
|
87
94
|
testing,
|
|
88
|
-
}: MakeLeaderThreadLayerParams): Layer.Layer<
|
|
95
|
+
}: MakeLeaderThreadLayerParams): Layer.Layer<
|
|
96
|
+
LeaderThreadCtx,
|
|
97
|
+
UnknownError,
|
|
98
|
+
Scope.Scope | HttpClient.HttpClient | StateHead.StateHead
|
|
99
|
+
> =>
|
|
89
100
|
Effect.gen(function* () {
|
|
90
101
|
const syncPayloadDecoded =
|
|
91
|
-
syncPayloadEncoded === undefined
|
|
102
|
+
syncPayloadEncoded === undefined
|
|
103
|
+
? undefined
|
|
104
|
+
: yield* Schema.decodeUnknownEffect(syncPayloadSchema)(syncPayloadEncoded)
|
|
92
105
|
|
|
93
|
-
const bootStatusQueue = yield* Queue.unbounded<BootStatus>()
|
|
106
|
+
const bootStatusQueue = yield* Effect.acquireRelease(Queue.unbounded<BootStatus>(), Queue.shutdown)
|
|
94
107
|
|
|
95
108
|
// Emit boot warning if present (e.g., OPFS unavailable in private browsing)
|
|
96
109
|
if (bootWarning !== undefined) {
|
|
@@ -114,29 +127,30 @@ export const makeLeaderThreadLayer = ({
|
|
|
114
127
|
KeyValueStore.makeStringOnly({
|
|
115
128
|
get: (_key) =>
|
|
116
129
|
Effect.sync(() => Eventlog.getBackendIdFromDb(dbEventlog)).pipe(
|
|
117
|
-
Effect.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
130
|
+
Effect.map(Option.getOrUndefined),
|
|
131
|
+
Effect.catchDefect(
|
|
132
|
+
(cause) =>
|
|
133
|
+
new KeyValueStore.KeyValueStoreError({
|
|
134
|
+
method: 'getBackendIdFromDb',
|
|
135
|
+
message: 'Failed to get backendId',
|
|
136
|
+
cause,
|
|
137
|
+
}),
|
|
124
138
|
),
|
|
125
139
|
),
|
|
126
140
|
set: (_key, value) =>
|
|
127
141
|
Effect.sync(() => Eventlog.updateBackendId(dbEventlog, value)).pipe(
|
|
128
|
-
Effect.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
Effect.catchDefect(
|
|
143
|
+
(cause) =>
|
|
144
|
+
new KeyValueStore.KeyValueStoreError({
|
|
145
|
+
method: 'updateBackendId',
|
|
146
|
+
message: 'Failed to update backendId',
|
|
147
|
+
cause,
|
|
148
|
+
}),
|
|
135
149
|
),
|
|
136
150
|
),
|
|
137
|
-
clear: Effect.
|
|
138
|
-
remove: () => Effect.
|
|
139
|
-
size: Effect.
|
|
151
|
+
clear: Effect.die(new Error(`Not implemented. Should never be used.`)),
|
|
152
|
+
remove: () => Effect.die(new Error(`Not implemented. Should never be used.`)),
|
|
153
|
+
size: Effect.die(new Error(`Not implemented. Should never be used.`)),
|
|
140
154
|
}),
|
|
141
155
|
),
|
|
142
156
|
),
|
|
@@ -161,7 +175,7 @@ export const makeLeaderThreadLayer = ({
|
|
|
161
175
|
? yield* recreateDb({ dbState, dbEventlog, schema, bootStatusQueue, materializeEvent })
|
|
162
176
|
: { migrationsReport: { migrations: [] } }
|
|
163
177
|
|
|
164
|
-
const syncProcessor = yield*
|
|
178
|
+
const syncProcessor = yield* LeaderSyncProcessor.make({
|
|
165
179
|
schema,
|
|
166
180
|
dbState,
|
|
167
181
|
initialSyncState: getInitialSyncState({ dbEventlog, dbState, dbEventlogMissing }),
|
|
@@ -176,19 +190,20 @@ export const makeLeaderThreadLayer = ({
|
|
|
176
190
|
}),
|
|
177
191
|
},
|
|
178
192
|
testing: {
|
|
179
|
-
...omitUndefineds({ delays: testing?.syncProcessor?.delays }),
|
|
193
|
+
...omitUndefineds({ delays: testing?.syncProcessor?.delays, hooks: testing?.syncProcessor?.hooks }),
|
|
180
194
|
},
|
|
181
195
|
})
|
|
182
196
|
|
|
183
|
-
const extraIncomingMessagesQueue = yield*
|
|
184
|
-
|
|
197
|
+
const extraIncomingMessagesQueue = yield* Effect.acquireRelease(
|
|
198
|
+
Queue.unbounded<Devtools.Leader.MessageToApp>(),
|
|
199
|
+
Queue.shutdown,
|
|
185
200
|
)
|
|
186
201
|
|
|
187
202
|
const devtoolsContext =
|
|
188
203
|
devtoolsOptions.enabled === true
|
|
189
204
|
? {
|
|
190
205
|
enabled: true as const,
|
|
191
|
-
syncBackendLatch: yield*
|
|
206
|
+
syncBackendLatch: yield* Latch.make(true),
|
|
192
207
|
syncBackendLatchState: yield* SubscriptionRef.make<{ latchClosed: boolean }>({ latchClosed: false }),
|
|
193
208
|
}
|
|
194
209
|
: { enabled: false as const }
|
|
@@ -213,13 +228,13 @@ export const makeLeaderThreadLayer = ({
|
|
|
213
228
|
devtools: devtoolsContext,
|
|
214
229
|
networkStatus,
|
|
215
230
|
// State will be set during `bootLeaderThread`
|
|
216
|
-
initialState: {} as any as LeaderThreadCtx['
|
|
217
|
-
} satisfies
|
|
231
|
+
initialState: {} as any as LeaderThreadCtx['Service']['initialState'],
|
|
232
|
+
} satisfies LeaderThreadCtx['Service']
|
|
218
233
|
|
|
219
234
|
// @ts-expect-error For debugging purposes
|
|
220
235
|
globalThis.__leaderThreadCtx = ctx
|
|
221
236
|
|
|
222
|
-
const layer = Layer.succeed(LeaderThreadCtx, ctx)
|
|
237
|
+
const layer = Layer.succeed(LeaderThreadCtx, LeaderThreadCtx.of(ctx))
|
|
223
238
|
|
|
224
239
|
ctx.initialState = yield* bootLeaderThread({
|
|
225
240
|
migrationsReport,
|
|
@@ -233,29 +248,17 @@ export const makeLeaderThreadLayer = ({
|
|
|
233
248
|
Effect.withSpanScoped('@livestore/common:leader-thread'),
|
|
234
249
|
UnknownError.mapToUnknownError,
|
|
235
250
|
Effect.tapCauseLogPretty,
|
|
236
|
-
Layer.
|
|
251
|
+
Layer.unwrap,
|
|
237
252
|
)
|
|
238
253
|
|
|
239
254
|
const hasEventlogTables = (db: SqliteDb) => {
|
|
240
255
|
const tableNames = new Set(db.select<{ name: string }>(sql`select name from sqlite_master`).map((_) => _.name))
|
|
241
|
-
|
|
242
|
-
return isSubsetOf(eventlogTables, tableNames)
|
|
256
|
+
return ReadonlyArray.every(SystemTables.eventlogSystemTables, (_) => tableNames.has(_.sqliteDef.name))
|
|
243
257
|
}
|
|
244
258
|
|
|
245
259
|
const hasStateTables = (db: SqliteDb) => {
|
|
246
260
|
const tableNames = new Set(db.select<{ name: string }>(sql`select name from sqlite_master`).map((_) => _.name))
|
|
247
|
-
|
|
248
|
-
return isSubsetOf(stateTables, tableNames)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const isSubsetOf = (a: Set<string>, b: Set<string>): boolean => {
|
|
252
|
-
for (const item of a) {
|
|
253
|
-
if (b.has(item) === false) {
|
|
254
|
-
return false
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return true
|
|
261
|
+
return ReadonlyArray.every(SystemTables.stateSystemTables, (_) => tableNames.has(_.sqliteDef.name))
|
|
259
262
|
}
|
|
260
263
|
|
|
261
264
|
const getInitialSyncState = ({
|
|
@@ -361,7 +364,7 @@ const bootLeaderThread = ({
|
|
|
361
364
|
initialBlockingSyncContext: InitialBlockingSyncContext
|
|
362
365
|
devtoolsOptions: DevtoolsOptions
|
|
363
366
|
}): Effect.Effect<
|
|
364
|
-
LeaderThreadCtx['
|
|
367
|
+
LeaderThreadCtx['Service']['initialState'],
|
|
365
368
|
UnknownError | MaterializerHashMismatchError,
|
|
366
369
|
LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
|
|
367
370
|
> =>
|
|
@@ -378,7 +381,7 @@ const bootLeaderThread = ({
|
|
|
378
381
|
progress: { done: 0, total: -1 },
|
|
379
382
|
})
|
|
380
383
|
|
|
381
|
-
yield* initialBlockingSyncContext.blockingDeferred.pipe(
|
|
384
|
+
yield* Deferred.await(initialBlockingSyncContext.blockingDeferred).pipe(
|
|
382
385
|
Effect.withSpan('@livestore/common:leader-thread:initial-sync-blocking'),
|
|
383
386
|
)
|
|
384
387
|
}
|
|
@@ -421,7 +424,7 @@ export const makeNetworkStatusSubscribable = ({
|
|
|
421
424
|
}))
|
|
422
425
|
|
|
423
426
|
if (syncBackend !== undefined) {
|
|
424
|
-
yield* syncBackend.isConnected.
|
|
427
|
+
yield* SubscriptionRef.changes(syncBackend.isConnected).pipe(
|
|
425
428
|
Stream.tap((isConnected) => updateNetworkStatus({ isConnected })),
|
|
426
429
|
Stream.runDrain,
|
|
427
430
|
Effect.interruptible,
|
|
@@ -431,7 +434,7 @@ export const makeNetworkStatusSubscribable = ({
|
|
|
431
434
|
}
|
|
432
435
|
|
|
433
436
|
if (devtoolsContext.enabled === true) {
|
|
434
|
-
yield* devtoolsContext.syncBackendLatchState.
|
|
437
|
+
yield* SubscriptionRef.changes(devtoolsContext.syncBackendLatchState).pipe(
|
|
435
438
|
Stream.tap(({ latchClosed }) => updateNetworkStatus({ latchClosed })),
|
|
436
439
|
Stream.runDrain,
|
|
437
440
|
Effect.interruptible,
|