@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,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { Effect, Stream } from '@livestore/utils/effect'
|
|
1
|
+
import { type Scope, type SubscriptionRef, Effect, Latch, Stream } from '@livestore/utils/effect'
|
|
3
2
|
import * as Webmesh from '@livestore/webmesh'
|
|
4
3
|
|
|
5
4
|
import type {
|
|
@@ -51,9 +50,10 @@ export const makeClientSession = <R>({
|
|
|
51
50
|
origin: string | undefined
|
|
52
51
|
}): Effect.Effect<ClientSession, never, Scope.Scope | R> =>
|
|
53
52
|
Effect.gen(function* () {
|
|
54
|
-
const devtools: ClientSession['devtools'] =
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const devtools: ClientSession['devtools'] =
|
|
54
|
+
devtoolsEnabled === true
|
|
55
|
+
? { enabled: true, pullLatch: yield* Latch.make(true), pushLatch: yield* Latch.make(true) }
|
|
56
|
+
: { enabled: false }
|
|
57
57
|
|
|
58
58
|
if (devtoolsEnabled === true) {
|
|
59
59
|
yield* Effect.gen(function* () {
|
|
@@ -116,7 +116,7 @@ export const makeClientSession = <R>({
|
|
|
116
116
|
yield* connectDevtoolsToStore(clientSessionDevtoolsChannel)
|
|
117
117
|
},
|
|
118
118
|
Effect.tapCauseLogPretty,
|
|
119
|
-
Effect.forkScoped,
|
|
119
|
+
Effect.forkScoped(),
|
|
120
120
|
),
|
|
121
121
|
),
|
|
122
122
|
Stream.runDrain,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { isDevEnv
|
|
2
|
-
import { Hash, Option, Schema } from '@livestore/utils/effect'
|
|
1
|
+
import { isDevEnv } from '@livestore/utils'
|
|
2
|
+
import { Hash, Option, Predicate, ReadonlyArray, Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import type { SqliteDb } from './adapter-types.ts'
|
|
5
|
-
import { SessionIdSymbol } from './adapter-types.ts'
|
|
6
5
|
import type { EventDef, Materializer, MaterializerContextQuery, MaterializerResult } from './schema/EventDef/mod.ts'
|
|
7
6
|
import type * as LiveStoreEvent from './schema/LiveStoreEvent/mod.ts'
|
|
8
7
|
import type { LiveStoreSchema } from './schema/schema.ts'
|
|
@@ -39,9 +38,10 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
39
38
|
}
|
|
40
39
|
: event.decoded
|
|
41
40
|
|
|
42
|
-
const eventArgsEncoded =
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
const eventArgsEncoded =
|
|
42
|
+
Predicate.isNotUndefined(event.decoded) === true && Predicate.isNotNullish(event.decoded.args) === true
|
|
43
|
+
? Schema.encodeUnknownSync(eventDef.schema)(event.decoded.args)
|
|
44
|
+
: undefined
|
|
45
45
|
|
|
46
46
|
const query: MaterializerContextQuery = (
|
|
47
47
|
rawQueryOrQueryBuilder:
|
|
@@ -55,7 +55,7 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
55
55
|
const { query, bindValues } = rawQueryOrQueryBuilder.asSql()
|
|
56
56
|
const rawResults = dbState.select(query, prepareBindValues(bindValues, query))
|
|
57
57
|
const resultSchema = getResultSchema(rawQueryOrQueryBuilder)
|
|
58
|
-
return Schema.
|
|
58
|
+
return Schema.decodeUnknownSync(resultSchema)(rawResults)
|
|
59
59
|
} else {
|
|
60
60
|
const { query, bindValues } = rawQueryOrQueryBuilder
|
|
61
61
|
return dbState.select(query, prepareBindValues(bindValues, query))
|
|
@@ -126,7 +126,7 @@ const fromMaterializerResult = (
|
|
|
126
126
|
bindValues: BindValues
|
|
127
127
|
writeTables: ReadonlySet<string> | undefined
|
|
128
128
|
}> => {
|
|
129
|
-
if (
|
|
129
|
+
if (ReadonlyArray.isArray<MaterializerResult | ReadonlyArray<MaterializerResult>>(materializerResult) === true) {
|
|
130
130
|
return materializerResult.flatMap(fromMaterializerResult)
|
|
131
131
|
}
|
|
132
132
|
if (isQueryBuilder(materializerResult) === true) {
|
|
@@ -144,32 +144,3 @@ const fromMaterializerResult = (
|
|
|
144
144
|
]
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
-
|
|
148
|
-
// NOTE we should explore whether there is a more elegant solution
|
|
149
|
-
// e.g. by leveraging the schema to replace the sessionIdSymbol
|
|
150
|
-
export const replaceSessionIdSymbol = (
|
|
151
|
-
bindValues: Record<string, unknown> | ReadonlyArray<unknown>,
|
|
152
|
-
sessionId: string,
|
|
153
|
-
) => {
|
|
154
|
-
deepReplaceValue(bindValues, SessionIdSymbol, sessionId)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const deepReplaceValue = <S, R>(input: any, searchValue: S, replaceValue: R): void => {
|
|
158
|
-
if (Array.isArray(input) === true) {
|
|
159
|
-
for (const i in input) {
|
|
160
|
-
if (input[i] === searchValue) {
|
|
161
|
-
input[i] = replaceValue
|
|
162
|
-
} else {
|
|
163
|
-
deepReplaceValue(input[i], searchValue, replaceValue)
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
} else if (typeof input === 'object' && input !== null) {
|
|
167
|
-
for (const key in input) {
|
|
168
|
-
if (input[key] === searchValue) {
|
|
169
|
-
input[key] = replaceValue
|
|
170
|
-
} else {
|
|
171
|
-
deepReplaceValue(input[key], searchValue, replaceValue)
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
package/src/otel.ts
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api'
|
|
2
2
|
|
|
3
3
|
import { makeNoopTracer } from '@livestore/utils'
|
|
4
|
+
import type { Tracer } from '@livestore/utils/effect'
|
|
4
5
|
import { Effect, identity, Layer, OtelTracer } from '@livestore/utils/effect'
|
|
5
6
|
|
|
6
7
|
export const OtelLiveDummy: Layer.Layer<OtelTracer.OtelTracer> = Layer.suspend(() => {
|
|
7
8
|
const OtelTracerLive = Layer.succeed(OtelTracer.OtelTracer, makeNoopTracer())
|
|
8
9
|
|
|
9
|
-
const TracingLive =
|
|
10
|
-
Layer.provideMerge(OtelTracerLive),
|
|
11
|
-
)
|
|
10
|
+
const TracingLive = OtelTracer.layerWithoutOtelTracer.pipe(Layer.provideMerge(OtelTracerLive))
|
|
12
11
|
|
|
13
12
|
return TracingLive
|
|
14
13
|
})
|
|
15
14
|
|
|
16
15
|
export const provideOtel =
|
|
17
16
|
({ otelTracer, parentSpanContext }: { otelTracer?: otel.Tracer; parentSpanContext?: otel.Context }) =>
|
|
18
|
-
<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, OtelTracer.OtelTracer>> => {
|
|
17
|
+
<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, OtelTracer.OtelTracer | Tracer.Tracer>> => {
|
|
19
18
|
const OtelTracerLive = Layer.succeed(OtelTracer.OtelTracer, otelTracer ?? makeNoopTracer())
|
|
20
19
|
|
|
21
|
-
const TracingLive =
|
|
20
|
+
const TracingLive = OtelTracer.layerWithoutOtelTracer.pipe(
|
|
22
21
|
Layer.provideMerge(OtelTracerLive),
|
|
23
|
-
) as any as Layer.Layer<OtelTracer.OtelTracer>
|
|
22
|
+
) as any as Layer.Layer<OtelTracer.OtelTracer | Tracer.Tracer>
|
|
24
23
|
|
|
25
24
|
return effect.pipe(
|
|
26
25
|
parentSpanContext !== undefined
|
|
@@ -29,11 +28,3 @@ export const provideOtel =
|
|
|
29
28
|
Effect.provide(TracingLive),
|
|
30
29
|
)
|
|
31
30
|
}
|
|
32
|
-
|
|
33
|
-
export const getDurationMsFromSpan = (span: otel.Span): number => {
|
|
34
|
-
const durationHr: [seconds: number, nanos: number] = (span as any)._duration
|
|
35
|
-
return durationHr[0] * 1000 + durationHr[1] / 1_000_000
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const getStartTimeHighResFromSpan = (span: otel.Span): DOMHighResTimeStamp =>
|
|
39
|
-
(span as any)._performanceStartTime as DOMHighResTimeStamp
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { memoizeByRef } from '@livestore/utils'
|
|
2
|
-
import {
|
|
2
|
+
import { Effect, Option, ReadonlyArray as EffectArray, Schema, Stream } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import { type SqliteDb, UnknownError } from './adapter-types.ts'
|
|
5
5
|
import type { MaterializeEvent } from './leader-thread/mod.ts'
|
|
6
6
|
import type { EventDef, LiveStoreSchema } from './schema/mod.ts'
|
|
7
|
-
import { EventSequenceNumber, LiveStoreEvent,
|
|
7
|
+
import { EventSequenceNumber, LiveStoreEvent, SystemTables } from './schema/mod.ts'
|
|
8
8
|
import type { PreparedBindValues } from './util.ts'
|
|
9
9
|
import { sql } from './util.ts'
|
|
10
10
|
|
|
11
11
|
/** Parse JSON string to unknown value */
|
|
12
|
-
const jsonParse = Schema.decodeUnknownSync(Schema.
|
|
12
|
+
const jsonParse = Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Unknown))
|
|
13
13
|
|
|
14
14
|
export const rematerializeFromEventlog = Effect.fn('@livestore/common:rematerializeFromEventlog')(function* ({
|
|
15
15
|
dbEventlog,
|
|
@@ -25,111 +25,114 @@ export const rematerializeFromEventlog = Effect.fn('@livestore/common:rematerial
|
|
|
25
25
|
onProgress: (_: { done: number; total: number }) => Effect.Effect<void>
|
|
26
26
|
materializeEvent: MaterializeEvent
|
|
27
27
|
}) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const resolution = yield* resolveEventDef(schema, {
|
|
56
|
-
operation: '@livestore/common:rematerializeFromEventlog:processEvent',
|
|
57
|
-
event: eventEncoded,
|
|
58
|
-
}).pipe(UnknownError.mapToUnknownError)
|
|
59
|
-
|
|
60
|
-
if (resolution._tag === 'unknown') {
|
|
61
|
-
// Old snapshots can contain newer events. Skip until the runtime has
|
|
62
|
-
// been updated; the event stays in the log for future replays.
|
|
63
|
-
return
|
|
64
|
-
}
|
|
28
|
+
const eventsCount = dbEventlog.select<{ count: number }>(
|
|
29
|
+
`SELECT COUNT(*) AS count FROM ${SystemTables.EVENTLOG_META_TABLE}`,
|
|
30
|
+
)[0]!.count
|
|
31
|
+
|
|
32
|
+
const hashEventDef = memoizeByRef((event: EventDef.AnyWithoutFn) => Schema.hash(event.schema))
|
|
33
|
+
|
|
34
|
+
const processEvent = Effect.fn(`@livestore/common:rematerializeFromEventlog:processEvent`)(function* (
|
|
35
|
+
row: SystemTables.EventlogMetaRow,
|
|
36
|
+
) {
|
|
37
|
+
const args = jsonParse(row.argsJson)
|
|
38
|
+
const eventEncoded = LiveStoreEvent.Client.EncodedWithMeta.make({
|
|
39
|
+
name: row.name,
|
|
40
|
+
args,
|
|
41
|
+
seqNum: {
|
|
42
|
+
global: row.seqNumGlobal,
|
|
43
|
+
client: row.seqNumClient,
|
|
44
|
+
rebaseGeneration: row.seqNumRebaseGeneration,
|
|
45
|
+
},
|
|
46
|
+
parentSeqNum: {
|
|
47
|
+
global: row.parentSeqNumGlobal,
|
|
48
|
+
client: row.parentSeqNumClient,
|
|
49
|
+
rebaseGeneration: row.parentSeqNumRebaseGeneration,
|
|
50
|
+
},
|
|
51
|
+
clientId: row.clientId,
|
|
52
|
+
sessionId: row.sessionId,
|
|
53
|
+
})
|
|
65
54
|
|
|
66
|
-
|
|
55
|
+
const eventDef = schema.eventsDefsMap.get(row.name)
|
|
56
|
+
const materializer = schema.state.materializers.get(row.name)
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
58
|
+
if (eventDef === undefined || materializer === undefined) {
|
|
59
|
+
// Route unknown events through the normal materialization boundary so
|
|
60
|
+
// they advance the state snapshot head as no-ops.
|
|
61
|
+
yield* materializeEvent(eventEncoded, { skipEventlog: true })
|
|
62
|
+
return
|
|
63
|
+
}
|
|
73
64
|
|
|
74
|
-
|
|
75
|
-
yield*
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
if (hashEventDef(eventDef) !== row.schemaHash) {
|
|
66
|
+
yield* Effect.logWarning(
|
|
67
|
+
`Schema hash mismatch for event definition ${row.name}. Trying to materialize event anyway.`,
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Checking whether the schema has changed in an incompatible way
|
|
72
|
+
yield* Schema.decodeUnknownEffect(eventDef.schema)(args).pipe(
|
|
73
|
+
Effect.mapError((cause) =>
|
|
74
|
+
UnknownError.make({
|
|
75
|
+
cause,
|
|
76
|
+
note: `\
|
|
80
77
|
There was an error during rematerializing from the eventlog while decoding
|
|
81
78
|
the persisted event args for event definition "${row.name}".
|
|
82
79
|
This likely means the schema has changed in an incompatible way.
|
|
83
80
|
`,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
}),
|
|
82
|
+
),
|
|
83
|
+
)
|
|
87
84
|
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
yield* materializeEvent(eventEncoded, { skipEventlog: true })
|
|
86
|
+
})
|
|
90
87
|
|
|
91
|
-
|
|
88
|
+
const CHUNK_SIZE = 100
|
|
92
89
|
|
|
93
|
-
|
|
90
|
+
const stmt = dbEventlog.prepare(sql`\
|
|
94
91
|
SELECT * FROM ${SystemTables.EVENTLOG_META_TABLE}
|
|
95
92
|
WHERE seqNumGlobal > $seqNumGlobal OR (seqNumGlobal = $seqNumGlobal AND seqNumClient > $seqNumClient)
|
|
96
93
|
ORDER BY seqNumGlobal ASC, seqNumClient ASC
|
|
97
94
|
LIMIT ${CHUNK_SIZE}
|
|
98
95
|
`)
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
SystemTables.EventlogMetaRow
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
|
|
97
|
+
let processedEvents = 0
|
|
98
|
+
|
|
99
|
+
yield* Stream.paginate(EventSequenceNumber.Client.ROOT, (lastId) =>
|
|
100
|
+
Effect.sync(() => {
|
|
101
|
+
const rows = stmt.select<SystemTables.EventlogMetaRow>({
|
|
102
|
+
$seqNumGlobal: lastId.global,
|
|
103
|
+
$seqNumClient: lastId.client,
|
|
104
|
+
} as any as PreparedBindValues)
|
|
105
|
+
|
|
106
|
+
if (EffectArray.isReadonlyArrayNonEmpty(rows) === false) {
|
|
107
|
+
const done: readonly [
|
|
108
|
+
ReadonlyArray<SystemTables.EventlogMetaRow>,
|
|
109
|
+
Option.Option<EventSequenceNumber.Client.Composite>,
|
|
110
|
+
] = [rows, Option.none()]
|
|
111
|
+
return done
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const lastRow = EffectArray.lastNonEmpty(rows)
|
|
115
|
+
const nextCursor = EventSequenceNumber.Client.Composite.make({
|
|
116
|
+
global: lastRow.seqNumGlobal,
|
|
117
|
+
client: lastRow.seqNumClient,
|
|
118
|
+
rebaseGeneration: lastRow.seqNumRebaseGeneration,
|
|
119
|
+
})
|
|
120
|
+
const next: readonly [
|
|
121
|
+
ReadonlyArray<SystemTables.EventlogMetaRow>,
|
|
122
|
+
Option.Option<EventSequenceNumber.Client.Composite>,
|
|
123
|
+
] = [rows, Option.some(nextCursor)]
|
|
124
|
+
return next
|
|
125
|
+
}),
|
|
126
|
+
).pipe(
|
|
127
|
+
Stream.bufferArray({ capacity: 2 }),
|
|
128
|
+
Stream.tap((row) =>
|
|
129
|
+
Effect.gen(function* () {
|
|
130
|
+
yield* processEvent(row)
|
|
131
|
+
|
|
132
|
+
processedEvents++
|
|
133
|
+
yield* onProgress({ done: processedEvents, total: eventsCount })
|
|
134
|
+
}),
|
|
135
|
+
),
|
|
136
|
+
Stream.runDrain,
|
|
137
|
+
)
|
|
135
138
|
}, Effect.withPerformanceMeasure('@livestore/common:rematerializeFromEventlog'))
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { Schema } from '@livestore/utils/effect'
|
|
4
|
+
|
|
5
|
+
import { synced } from './define.ts'
|
|
6
|
+
|
|
7
|
+
describe('synced event wire schema', () => {
|
|
8
|
+
const occurredAt = new Date('2026-07-17T10:15:30.000Z')
|
|
9
|
+
const event = synced({
|
|
10
|
+
name: 'v1.Occurred',
|
|
11
|
+
schema: Schema.Struct({
|
|
12
|
+
occurredAt: Schema.DateFromString,
|
|
13
|
+
}),
|
|
14
|
+
})
|
|
15
|
+
const jsonSchema = Schema.fromJsonString(event.schema)
|
|
16
|
+
|
|
17
|
+
test('roundtrips a valid date through JSON', () => {
|
|
18
|
+
const encoded = Schema.encodeSync(jsonSchema)({ occurredAt })
|
|
19
|
+
|
|
20
|
+
expect(encoded).toBe('{"occurredAt":"2026-07-17T10:15:30.000Z"}')
|
|
21
|
+
expect(Schema.decodeSync(jsonSchema)(encoded)).toEqual({ occurredAt })
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('rejects invalid dates on encode and decode', () => {
|
|
25
|
+
expect(() => Schema.encodeSync(jsonSchema)({ occurredAt: new Date(Number.NaN) })).toThrow()
|
|
26
|
+
expect(() => Schema.decodeSync(jsonSchema)('{"occurredAt":"not-a-date"}')).toThrow()
|
|
27
|
+
})
|
|
28
|
+
})
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
31
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
32
|
-
import { Schema } from '@livestore/utils/effect'
|
|
32
|
+
import { Result, Schema } from '@livestore/utils/effect'
|
|
33
33
|
|
|
34
34
|
import type { EventDef } from './event-def.ts'
|
|
35
35
|
import type { EventDefFactInput, EventDefFacts } from './facts.ts'
|
|
@@ -105,15 +105,15 @@ export type DefineEventOptions<TTo, TDerived extends boolean = false> = {
|
|
|
105
105
|
export const defineEvent = <TName extends string, TType, TEncoded = TType, TDerived extends boolean = false>(
|
|
106
106
|
args: {
|
|
107
107
|
name: TName
|
|
108
|
-
schema: Schema.
|
|
108
|
+
schema: Schema.Codec<TType, TEncoded>
|
|
109
109
|
} & DefineEventOptions<TType, TDerived>,
|
|
110
110
|
): EventDef<TName, TType, TEncoded, TDerived> => {
|
|
111
111
|
const { name, schema, ...options } = args
|
|
112
112
|
|
|
113
113
|
const makePartialEvent = (args: TType) => {
|
|
114
|
-
const res = Schema.
|
|
115
|
-
if (res
|
|
116
|
-
shouldNeverHappen(`Invalid event args for event '${name}':`, res.
|
|
114
|
+
const res = Schema.decodeResult(Schema.toType(schema))(args)
|
|
115
|
+
if (Result.isFailure(res) === true) {
|
|
116
|
+
shouldNeverHappen(`Invalid event args for event '${name}':`, res.failure.message, '\n')
|
|
117
117
|
}
|
|
118
118
|
return { name: name, args }
|
|
119
119
|
}
|
|
@@ -127,18 +127,19 @@ export const defineEvent = <TName extends string, TType, TEncoded = TType, TDeri
|
|
|
127
127
|
Object.defineProperty(makePartialEvent, 'options', {
|
|
128
128
|
value: {
|
|
129
129
|
clientOnly: options?.clientOnly ?? false,
|
|
130
|
-
facts:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
130
|
+
facts:
|
|
131
|
+
options?.facts !== undefined
|
|
132
|
+
? (args, currentFacts) => {
|
|
133
|
+
const res = options.facts!(args, currentFacts)
|
|
134
|
+
return {
|
|
135
|
+
modify: {
|
|
136
|
+
set: res.modify?.set !== undefined ? new Set(res.modify.set) : new Set(),
|
|
137
|
+
unset: res.modify?.unset !== undefined ? new Set(res.modify.unset) : new Set(),
|
|
138
|
+
},
|
|
139
|
+
require: res.require !== undefined ? new Set(res.require) : new Set(),
|
|
140
|
+
}
|
|
139
141
|
}
|
|
140
|
-
|
|
141
|
-
: undefined,
|
|
142
|
+
: undefined,
|
|
142
143
|
derived: options?.derived ?? false,
|
|
143
144
|
deprecated: options?.deprecated,
|
|
144
145
|
} satisfies EventDef.Any['options'],
|
|
@@ -178,7 +179,7 @@ export const defineEvent = <TName extends string, TType, TEncoded = TType, TDeri
|
|
|
178
179
|
export const synced = <TName extends string, TType, TEncoded = TType>(
|
|
179
180
|
args: {
|
|
180
181
|
name: TName
|
|
181
|
-
schema: Schema.
|
|
182
|
+
schema: Schema.Codec<TType, TEncoded>
|
|
182
183
|
} & Omit<DefineEventOptions<TType>, 'derived' | 'clientOnly'>,
|
|
183
184
|
): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: false })
|
|
184
185
|
|
|
@@ -201,7 +202,7 @@ export const synced = <TName extends string, TType, TEncoded = TType>(
|
|
|
201
202
|
* name: 'UiStateSet',
|
|
202
203
|
* schema: Schema.Struct({
|
|
203
204
|
* selectedTodoId: Schema.NullOr(Schema.String),
|
|
204
|
-
* filterMode: Schema.
|
|
205
|
+
* filterMode: Schema.Literals(['all', 'active', 'completed']),
|
|
205
206
|
* }),
|
|
206
207
|
* })
|
|
207
208
|
*
|
|
@@ -212,6 +213,6 @@ export const synced = <TName extends string, TType, TEncoded = TType>(
|
|
|
212
213
|
export const clientOnly = <TName extends string, TType, TEncoded = TType>(
|
|
213
214
|
args: {
|
|
214
215
|
name: TName
|
|
215
|
-
schema: Schema.
|
|
216
|
+
schema: Schema.Codec<TType, TEncoded>
|
|
216
217
|
} & Omit<DefineEventOptions<TType>, 'derived' | 'clientOnly'>,
|
|
217
218
|
): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: true })
|
|
@@ -60,14 +60,7 @@ describe('logDeprecationWarnings', () => {
|
|
|
60
60
|
|
|
61
61
|
const run = (effect: Effect.Effect<void>) =>
|
|
62
62
|
Effect.runSync(
|
|
63
|
-
effect.pipe(
|
|
64
|
-
Effect.provide(
|
|
65
|
-
Logger.replace(
|
|
66
|
-
Logger.defaultLogger,
|
|
67
|
-
Logger.make(({ message }) => logs.push(message as unknown[])),
|
|
68
|
-
),
|
|
69
|
-
),
|
|
70
|
-
),
|
|
63
|
+
effect.pipe(Effect.provide(Logger.layer([Logger.make(({ message }) => logs.push(message as unknown[]))]))),
|
|
71
64
|
)
|
|
72
65
|
|
|
73
66
|
test('logs event deprecation warning', () => {
|
|
@@ -30,20 +30,19 @@
|
|
|
30
30
|
* @module
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
import type
|
|
34
|
-
import { Effect, Option, SchemaAST } from '@livestore/utils/effect'
|
|
33
|
+
import { type Schema, Effect, Option, SchemaAST } from '@livestore/utils/effect'
|
|
35
34
|
|
|
36
35
|
import type { EventDef } from './event-def.ts'
|
|
37
36
|
|
|
38
|
-
/**
|
|
39
|
-
export const DeprecatedId =
|
|
37
|
+
/** Annotation key used to mark schemas as deprecated. */
|
|
38
|
+
export const DeprecatedId = 'livestore/schema/annotations/deprecated'
|
|
40
39
|
|
|
41
40
|
/**
|
|
42
41
|
* Marks a schema field as deprecated with a reason message.
|
|
43
42
|
* When an event is committed with a deprecated field that has a value,
|
|
44
43
|
* a warning will be logged.
|
|
45
44
|
*
|
|
46
|
-
* Works with
|
|
45
|
+
* Works with Schema fields, including optional fields from Schema.optional.
|
|
47
46
|
*
|
|
48
47
|
* @param reason - Explanation of why this field is deprecated and what to use instead
|
|
49
48
|
* @returns A function that adds the deprecation annotation to the schema
|
|
@@ -58,8 +57,8 @@ export const DeprecatedId = Symbol.for('livestore/schema/annotations/deprecated'
|
|
|
58
57
|
*/
|
|
59
58
|
export const deprecated =
|
|
60
59
|
(reason: string) =>
|
|
61
|
-
<T extends
|
|
62
|
-
schema.
|
|
60
|
+
<T extends Schema.Top>(schema: T): T['Rebuild'] =>
|
|
61
|
+
schema.annotate({ [DeprecatedId]: reason })
|
|
63
62
|
|
|
64
63
|
/**
|
|
65
64
|
* Checks if a schema has a deprecation annotation.
|
|
@@ -67,8 +66,8 @@ export const deprecated =
|
|
|
67
66
|
* @param schema - The schema to check
|
|
68
67
|
* @returns The deprecation reason if deprecated, None otherwise
|
|
69
68
|
*/
|
|
70
|
-
export const getDeprecatedReason =
|
|
71
|
-
SchemaAST.
|
|
69
|
+
export const getDeprecatedReason = (schema: Schema.Top): Option.Option<string> =>
|
|
70
|
+
Option.fromUndefinedOr(SchemaAST.resolveAt<string>(DeprecatedId)(schema.ast))
|
|
72
71
|
|
|
73
72
|
/**
|
|
74
73
|
* Checks if a schema is deprecated.
|
|
@@ -76,8 +75,7 @@ export const getDeprecatedReason = <A, I, R>(schema: Schema.Schema<A, I, R>): Op
|
|
|
76
75
|
* @param schema - The schema to check
|
|
77
76
|
* @returns true if the schema is deprecated
|
|
78
77
|
*/
|
|
79
|
-
export const isDeprecated =
|
|
80
|
-
Option.isSome(getDeprecatedReason(schema))
|
|
78
|
+
export const isDeprecated = (schema: Schema.Top): boolean => Option.isSome(getDeprecatedReason(schema))
|
|
81
79
|
|
|
82
80
|
/**
|
|
83
81
|
* Finds deprecated fields with values in the given event arguments.
|
|
@@ -88,28 +86,27 @@ export const isDeprecated = <A, I, R>(schema: Schema.Schema<A, I, R>): boolean =
|
|
|
88
86
|
* @returns Array of objects containing field name and deprecation reason
|
|
89
87
|
*/
|
|
90
88
|
export const findDeprecatedFieldsWithValues = (
|
|
91
|
-
schema: Schema.
|
|
89
|
+
schema: Schema.Top,
|
|
92
90
|
args: Record<string, unknown>,
|
|
93
91
|
): Array<{ field: string; reason: string }> => {
|
|
94
92
|
const result: Array<{ field: string; reason: string }> = []
|
|
95
|
-
const ast = schema.ast
|
|
93
|
+
const ast = SchemaAST.toType(schema.ast)
|
|
96
94
|
|
|
97
|
-
// Handle
|
|
98
|
-
if (ast
|
|
95
|
+
// Handle Objects (Struct) schemas
|
|
96
|
+
if (SchemaAST.isObjects(ast) === true) {
|
|
99
97
|
for (const prop of ast.propertySignatures) {
|
|
100
98
|
const fieldName = String(prop.name)
|
|
101
99
|
const fieldValue = args[fieldName]
|
|
102
100
|
|
|
103
101
|
// Only check fields that have a value (not undefined)
|
|
104
102
|
if (fieldValue !== undefined) {
|
|
105
|
-
// Check deprecation on the property
|
|
106
|
-
const
|
|
107
|
-
const deprecationReason = propAnnotations?.[DeprecatedId] as string | undefined
|
|
103
|
+
// Check deprecation on the property key itself (for Schema.optional(...).pipe(deprecated(...)))
|
|
104
|
+
const deprecationReason = prop.type.context?.annotations?.[DeprecatedId] as string | undefined
|
|
108
105
|
|
|
109
106
|
// Also check deprecation on the type (for direct field deprecation)
|
|
110
|
-
const typeDeprecation = SchemaAST.
|
|
107
|
+
const typeDeprecation = SchemaAST.resolveAt<string>(DeprecatedId)(prop.type)
|
|
111
108
|
|
|
112
|
-
const reason = deprecationReason ??
|
|
109
|
+
const reason = deprecationReason ?? typeDeprecation
|
|
113
110
|
if (reason !== undefined) {
|
|
114
111
|
result.push({ field: fieldName, reason })
|
|
115
112
|
}
|
|
@@ -34,7 +34,7 @@ export type EventDef<TName extends string, TType, TEncoded = TType, TDerived ext
|
|
|
34
34
|
name: TName
|
|
35
35
|
|
|
36
36
|
/** Effect Schema used for validating and encoding/decoding event arguments. */
|
|
37
|
-
schema: Schema.
|
|
37
|
+
schema: Schema.Codec<TType, TEncoded>
|
|
38
38
|
|
|
39
39
|
options: {
|
|
40
40
|
/**
|
|
@@ -62,9 +62,7 @@ export type EventDef<TName extends string, TType, TEncoded = TType, TDerived ext
|
|
|
62
62
|
* Callable signature - creates a partial event with decoded arguments.
|
|
63
63
|
* The returned object can be passed directly to `store.commit()`.
|
|
64
64
|
*/
|
|
65
|
-
(
|
|
66
|
-
args: TType,
|
|
67
|
-
): {
|
|
65
|
+
(args: TType): {
|
|
68
66
|
name: TName
|
|
69
67
|
args: TType
|
|
70
68
|
}
|