@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,6 @@
|
|
|
1
1
|
import { type Nullable, shouldNeverHappen } from '@livestore/utils'
|
|
2
|
-
import {
|
|
2
|
+
import type { Schema } from '@livestore/utils/effect'
|
|
3
|
+
import { SchemaAST, type Types } from '@livestore/utils/effect'
|
|
3
4
|
|
|
4
5
|
import { getColumnDefForSchema, schemaFieldsToColumns } from './column-def.ts'
|
|
5
6
|
import { SqliteDsl } from './db-schema/mod.ts'
|
|
@@ -38,29 +39,17 @@ export type TableDef<
|
|
|
38
39
|
// https://github.com/livestorejs/livestore/issues/382
|
|
39
40
|
TSqliteDef extends DefaultSqliteTableDef = DefaultSqliteTableDefConstrained,
|
|
40
41
|
TOptions extends TableOptions = TableOptions,
|
|
41
|
-
|
|
42
|
-
// as we don't want the alias type for users to show up, so we're redefining it here
|
|
43
|
-
// TODO adjust this to `TSchema = Schema.TypeLiteral<` but requires some advance type-level work
|
|
44
|
-
TSchema = Schema.Schema<
|
|
45
|
-
SqliteDsl.AnyIfConstained<
|
|
46
|
-
TSqliteDef['columns'],
|
|
47
|
-
{ readonly [K in keyof TSqliteDef['columns']]: TSqliteDef['columns'][K]['schema']['Type'] }
|
|
48
|
-
>,
|
|
49
|
-
SqliteDsl.AnyIfConstained<
|
|
50
|
-
TSqliteDef['columns'],
|
|
51
|
-
{ readonly [K in keyof TSqliteDef['columns']]: TSqliteDef['columns'][K]['schema']['Encoded'] }
|
|
52
|
-
>
|
|
53
|
-
>,
|
|
42
|
+
TSchema extends Schema.Top = Schema.Struct<SqliteDsl.StructFieldsForColumns<TSqliteDef['columns']>>,
|
|
54
43
|
> = {
|
|
55
44
|
sqliteDef: TSqliteDef
|
|
56
45
|
options: TOptions
|
|
57
46
|
// Derived from `sqliteDef`, so only exposed for convenience
|
|
58
47
|
rowSchema: TSchema
|
|
59
48
|
insertSchema: SqliteDsl.InsertStructSchemaForColumns<TSqliteDef['columns']>
|
|
60
|
-
// query: QueryBuilder<ReadonlyArray<
|
|
61
|
-
readonly Type:
|
|
62
|
-
readonly Encoded:
|
|
63
|
-
} & QueryBuilder<ReadonlyArray<
|
|
49
|
+
// query: QueryBuilder<ReadonlyArray<TSchema['Type']>>, TableDefBase<TSqliteDef & {}, TOptions>>
|
|
50
|
+
readonly Type: TSchema['Type']
|
|
51
|
+
readonly Encoded: TSchema['Encoded']
|
|
52
|
+
} & QueryBuilder<ReadonlyArray<TSchema['Type']>, TableDefBase<TSqliteDef & {}, TOptions>>
|
|
64
53
|
|
|
65
54
|
export type TableOptionsInput = Partial<{
|
|
66
55
|
indexes: SqliteDsl.Index[]
|
|
@@ -114,7 +103,7 @@ export type TableOptions = {
|
|
|
114
103
|
* })
|
|
115
104
|
*
|
|
116
105
|
* // Option 2: With name from schema annotation (title or identifier)
|
|
117
|
-
* const AnnotatedUserSchema = UserSchema.
|
|
106
|
+
* const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })
|
|
118
107
|
* const usersTable2 = State.SQLite.table({
|
|
119
108
|
* schema: AnnotatedUserSchema,
|
|
120
109
|
* })
|
|
@@ -127,7 +116,7 @@ export type TableOptions = {
|
|
|
127
116
|
* title: Schema.String,
|
|
128
117
|
* authorId: Schema.String,
|
|
129
118
|
* createdAt: Schema.Date,
|
|
130
|
-
* }).
|
|
119
|
+
* }).annotate({ identifier: 'posts' })
|
|
131
120
|
*
|
|
132
121
|
* const postsTable = State.SQLite.table({
|
|
133
122
|
* schema: PostSchema,
|
|
@@ -161,24 +150,21 @@ export function table<
|
|
|
161
150
|
// Overload 2: With schema and explicit name
|
|
162
151
|
export function table<
|
|
163
152
|
TName extends string,
|
|
164
|
-
TSchema extends Schema.
|
|
153
|
+
TSchema extends Schema.Top,
|
|
165
154
|
const TOptionsInput extends TableOptionsInput = TableOptionsInput,
|
|
166
155
|
>(
|
|
167
156
|
args: {
|
|
168
157
|
name: TName
|
|
169
158
|
schema: TSchema
|
|
170
159
|
} & Partial<TOptionsInput>,
|
|
171
|
-
): TableDef<SqliteTableDefForSchemaInput<TName,
|
|
160
|
+
): TableDef<SqliteTableDefForSchemaInput<TName, TSchema['Type'], TSchema['Encoded'], TSchema>>
|
|
172
161
|
|
|
173
162
|
// Overload 3: With schema and no name (uses schema annotations)
|
|
174
|
-
export function table<
|
|
175
|
-
TSchema extends Schema.Schema.AnyNoContext,
|
|
176
|
-
const TOptionsInput extends TableOptionsInput = TableOptionsInput,
|
|
177
|
-
>(
|
|
163
|
+
export function table<TSchema extends Schema.Top, const TOptionsInput extends TableOptionsInput = TableOptionsInput>(
|
|
178
164
|
args: {
|
|
179
165
|
schema: TSchema
|
|
180
166
|
} & Partial<TOptionsInput>,
|
|
181
|
-
): TableDef<SqliteTableDefForSchemaInput<string,
|
|
167
|
+
): TableDef<SqliteTableDefForSchemaInput<string, TSchema['Type'], TSchema['Encoded'], TSchema>>
|
|
182
168
|
|
|
183
169
|
// Implementation
|
|
184
170
|
export function table<
|
|
@@ -193,10 +179,10 @@ export function table<
|
|
|
193
179
|
}
|
|
194
180
|
| {
|
|
195
181
|
name: TName
|
|
196
|
-
schema: Schema.
|
|
182
|
+
schema: Schema.Top
|
|
197
183
|
}
|
|
198
184
|
| {
|
|
199
|
-
schema: Schema.
|
|
185
|
+
schema: Schema.Top
|
|
200
186
|
}
|
|
201
187
|
) &
|
|
202
188
|
Partial<TOptionsInput>,
|
|
@@ -213,7 +199,7 @@ export function table<
|
|
|
213
199
|
columns = SqliteDsl.isColumnDefinition(columnOrColumns) === true ? { value: columnOrColumns } : columnOrColumns
|
|
214
200
|
additionalIndexes = []
|
|
215
201
|
} else if ('schema' in args) {
|
|
216
|
-
const result =
|
|
202
|
+
const result = args.schema.pipe(getSqlitePropertySignatures, schemaFieldsToColumns)
|
|
217
203
|
columns = result.columns
|
|
218
204
|
|
|
219
205
|
// We'll set tableName first, then use it for index names
|
|
@@ -224,14 +210,12 @@ export function table<
|
|
|
224
210
|
tempTableName = args.name
|
|
225
211
|
} else {
|
|
226
212
|
// Use title or identifier, with preference for title
|
|
227
|
-
tempTableName =
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
),
|
|
234
|
-
)
|
|
213
|
+
tempTableName =
|
|
214
|
+
SchemaAST.resolveTitle(args.schema.ast) ??
|
|
215
|
+
SchemaAST.resolveIdentifier(args.schema.ast) ??
|
|
216
|
+
shouldNeverHappen(
|
|
217
|
+
'When using schema without explicit name, the schema must have a title or identifier annotation',
|
|
218
|
+
)
|
|
235
219
|
}
|
|
236
220
|
|
|
237
221
|
tableName = tempTableName
|
|
@@ -281,6 +265,74 @@ export function table<
|
|
|
281
265
|
return tableDef as any
|
|
282
266
|
}
|
|
283
267
|
|
|
268
|
+
const getSqlitePropertySignatures = (schema: Schema.Top): ReadonlyArray<SchemaAST.PropertySignature> => {
|
|
269
|
+
const encodedPropertySignatures = getPropertySignatures(SchemaAST.toEncoded(schema.ast))
|
|
270
|
+
const typePropertySignatures = getPropertySignatures(SchemaAST.toType(schema.ast))
|
|
271
|
+
|
|
272
|
+
return encodedPropertySignatures.map((encodedPropertySignature) => {
|
|
273
|
+
const typePropertySignature = typePropertySignatures.find(
|
|
274
|
+
(propertySignature) => propertySignature.name === encodedPropertySignature.name,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
if (typePropertySignature === undefined || hasLiveStoreSqliteAnnotation(encodedPropertySignature.type) === true) {
|
|
278
|
+
return encodedPropertySignature
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return new SchemaAST.PropertySignature(encodedPropertySignature.name, typePropertySignature.type)
|
|
282
|
+
})
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const getPropertySignatures = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.PropertySignature> => {
|
|
286
|
+
if (SchemaAST.isObjects(ast) === true) return ast.propertySignatures
|
|
287
|
+
|
|
288
|
+
if (SchemaAST.isUnion(ast) === true) {
|
|
289
|
+
const members = ast.types.map(getPropertySignatures)
|
|
290
|
+
const [head, ...tail] = members
|
|
291
|
+
if (head === undefined) return []
|
|
292
|
+
|
|
293
|
+
return head.flatMap((propertySignature) => {
|
|
294
|
+
const matchingPropertySignatures: Array<SchemaAST.PropertySignature> = []
|
|
295
|
+
for (const propertySignatures of tail) {
|
|
296
|
+
const matchingPropertySignature = propertySignatures.find(
|
|
297
|
+
(memberPropertySignature) => memberPropertySignature.name === propertySignature.name,
|
|
298
|
+
)
|
|
299
|
+
if (matchingPropertySignature === undefined) {
|
|
300
|
+
return []
|
|
301
|
+
}
|
|
302
|
+
matchingPropertySignatures.push(matchingPropertySignature)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const propertySignatures = [propertySignature, ...matchingPropertySignatures]
|
|
306
|
+
/**
|
|
307
|
+
* `SchemaAST.optionalKey` became internal in Effect rc.109, so the optional-key marker is
|
|
308
|
+
* applied by constructing the union with an optional `Context`. Equivalent here because the
|
|
309
|
+
* union is freshly built and therefore carries no encoding chain to propagate the marker to.
|
|
310
|
+
*/
|
|
311
|
+
const hasOptionalMember =
|
|
312
|
+
propertySignatures.some((memberPropertySignature) => SchemaAST.isOptional(memberPropertySignature.type)) ===
|
|
313
|
+
true
|
|
314
|
+
const keyContext = hasOptionalMember === true ? new SchemaAST.Context(true, false) : undefined
|
|
315
|
+
const union = new SchemaAST.Union(
|
|
316
|
+
propertySignatures.map((memberPropertySignature) => memberPropertySignature.type),
|
|
317
|
+
ast.mode,
|
|
318
|
+
undefined,
|
|
319
|
+
undefined,
|
|
320
|
+
undefined,
|
|
321
|
+
keyContext,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
return [new SchemaAST.PropertySignature(propertySignature.name, union)]
|
|
325
|
+
})
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return []
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const hasLiveStoreSqliteAnnotation = (ast: SchemaAST.AST): boolean => {
|
|
332
|
+
const annotationKeys = [...Object.keys(ast.annotations ?? {}), ...Object.keys(ast.context?.annotations ?? {})]
|
|
333
|
+
return annotationKeys.some((key) => key.startsWith('livestore/state/sqlite/annotations/'))
|
|
334
|
+
}
|
|
335
|
+
|
|
284
336
|
export namespace FromTable {
|
|
285
337
|
// TODO this sometimes doesn't preserve the order of columns
|
|
286
338
|
export type RowDecoded<TTableDef extends TableDefBase> = Types.Simplify<
|
|
@@ -297,9 +349,7 @@ export namespace FromTable {
|
|
|
297
349
|
}
|
|
298
350
|
|
|
299
351
|
export type RowEncodeNonNullable<TTableDef extends TableDefBase> = {
|
|
300
|
-
[K in keyof TTableDef['sqliteDef']['columns']]:
|
|
301
|
-
TTableDef['sqliteDef']['columns'][K]['schema']
|
|
302
|
-
>
|
|
352
|
+
[K in keyof TTableDef['sqliteDef']['columns']]: TTableDef['sqliteDef']['columns'][K]['schema']['Encoded']
|
|
303
353
|
}
|
|
304
354
|
|
|
305
355
|
export type RowEncoded<TTableDef extends TableDefBase> = Types.Simplify<
|
|
@@ -308,7 +358,7 @@ export namespace FromTable {
|
|
|
308
358
|
>
|
|
309
359
|
|
|
310
360
|
export type RowDecodedAll<TTableDef extends TableDefBase> = {
|
|
311
|
-
[K in keyof TTableDef['sqliteDef']['columns']]:
|
|
361
|
+
[K in keyof TTableDef['sqliteDef']['columns']]: TTableDef['sqliteDef']['columns'][K]['schema']['Type']
|
|
312
362
|
}
|
|
313
363
|
}
|
|
314
364
|
|
|
@@ -320,7 +370,7 @@ export namespace FromColumns {
|
|
|
320
370
|
>
|
|
321
371
|
|
|
322
372
|
export type RowDecodedAll<TColumns extends SqliteDsl.Columns> = {
|
|
323
|
-
[K in keyof TColumns]:
|
|
373
|
+
[K in keyof TColumns]: TColumns[K]['schema']['Type']
|
|
324
374
|
}
|
|
325
375
|
|
|
326
376
|
export type RowEncoded<TColumns extends SqliteDsl.Columns> = Types.Simplify<
|
|
@@ -329,7 +379,7 @@ export namespace FromColumns {
|
|
|
329
379
|
>
|
|
330
380
|
|
|
331
381
|
export type RowEncodeNonNullable<TColumns extends SqliteDsl.Columns> = {
|
|
332
|
-
[K in keyof TColumns]:
|
|
382
|
+
[K in keyof TColumns]: TColumns[K]['schema']['Encoded']
|
|
333
383
|
}
|
|
334
384
|
|
|
335
385
|
export type NullableColumnNames<TColumns extends SqliteDsl.Columns> = keyof {
|
|
@@ -378,7 +428,8 @@ export declare namespace SchemaToColumns {
|
|
|
378
428
|
export type FromTypes<TType, TEncoded> =
|
|
379
429
|
TEncoded extends Record<string, any>
|
|
380
430
|
? {
|
|
381
|
-
[K in keyof TEncoded]-?: ColumnDefForType<
|
|
431
|
+
[K in keyof TEncoded]-?: ColumnDefForType<
|
|
432
|
+
TEncoded[K],
|
|
382
433
|
TType extends Record<string, any> ? (K extends keyof TType ? TType[K] : TEncoded[K]) : TEncoded[K]
|
|
383
434
|
>
|
|
384
435
|
}
|
|
@@ -72,8 +72,9 @@ const handleUnknownEvent = ({
|
|
|
72
72
|
case 'callback': {
|
|
73
73
|
const callback = config.onUnknownEvent
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
// @effect-diagnostics-next-line anyUnknownInErrorContext:off -- user callback errors are immediately handled and logged below
|
|
76
|
+
yield* Effect.trySyncOrPromiseOrEffect(() => callback(context, error)).pipe(
|
|
77
|
+
Effect.catch((cause) =>
|
|
77
78
|
Effect.logWarning('@livestore/common:schema:unknown-event:callback-error', {
|
|
78
79
|
event: context.event,
|
|
79
80
|
reason: context.reason,
|
|
@@ -49,7 +49,7 @@ describe('migrateTable - quoting and autoincrement', () => {
|
|
|
49
49
|
primaryKey: true,
|
|
50
50
|
autoIncrement: true,
|
|
51
51
|
default: Option.none(),
|
|
52
|
-
schema: Schema.
|
|
52
|
+
schema: Schema.Finite,
|
|
53
53
|
}),
|
|
54
54
|
SqliteAst.column({
|
|
55
55
|
name: 'text',
|
|
@@ -67,7 +67,7 @@ describe('migrateTable - quoting and autoincrement', () => {
|
|
|
67
67
|
primaryKey: false,
|
|
68
68
|
autoIncrement: false,
|
|
69
69
|
default: Option.some(0),
|
|
70
|
-
schema: Schema.
|
|
70
|
+
schema: Schema.Finite,
|
|
71
71
|
}),
|
|
72
72
|
],
|
|
73
73
|
[],
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionIdSymbol is a user-facing placeholder for "the current client session".
|
|
3
|
+
* User code can keep using the same event/query object across sessions, while the
|
|
4
|
+
* storage and eventlog layers require concrete string ids. Resolving the symbol at
|
|
5
|
+
* those boundaries preserves the symbolic API without mutating caller-owned values.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { Predicate } from '@livestore/utils/effect'
|
|
10
|
+
|
|
11
|
+
import type { Bindable, SqlValue } from './util.ts'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Can be used in queries to refer to the current session id.
|
|
15
|
+
* Will be replaced with the actual session id at runtime.
|
|
16
|
+
*
|
|
17
|
+
* In client document table:
|
|
18
|
+
* ```ts
|
|
19
|
+
* const uiState = State.SQLite.clientDocument({
|
|
20
|
+
* name: 'ui_state',
|
|
21
|
+
* schema: Schema.Struct({
|
|
22
|
+
* theme: Schema.Literals(['dark', 'light', 'system']),
|
|
23
|
+
* user: Schema.String,
|
|
24
|
+
* showToolbar: Schema.Boolean,
|
|
25
|
+
* }),
|
|
26
|
+
* default: { value: defaultFrontendState, id: SessionIdSymbol },
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Or in a client document query:
|
|
31
|
+
* ```ts
|
|
32
|
+
* const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export const SessionIdSymbol = Symbol.for('@livestore/session-id')
|
|
36
|
+
export type SessionIdSymbol = typeof SessionIdSymbol
|
|
37
|
+
|
|
38
|
+
export type BindableWithSessionIdSymbol =
|
|
39
|
+
| ReadonlyArray<SqlValue | SessionIdSymbol>
|
|
40
|
+
| Record<string, SqlValue | SessionIdSymbol>
|
|
41
|
+
|
|
42
|
+
export const resolveSessionIdSymbolInBindValues = (
|
|
43
|
+
bindValues: BindableWithSessionIdSymbol,
|
|
44
|
+
sessionId: string,
|
|
45
|
+
): Bindable => {
|
|
46
|
+
return Array.isArray(bindValues) === true
|
|
47
|
+
? bindValues.map((value) => (value === SessionIdSymbol ? sessionId : value))
|
|
48
|
+
: (Object.fromEntries(
|
|
49
|
+
Object.entries(bindValues).map(([key, value]) => [key, value === SessionIdSymbol ? sessionId : value]),
|
|
50
|
+
) as Record<string, SqlValue>)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const resolveSessionIdSymbolInEventArgs = (args: unknown, sessionId: string): unknown => {
|
|
54
|
+
if (Predicate.hasProperty(args, 'id') === false) {
|
|
55
|
+
return args
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return args.id === SessionIdSymbol ? { ...args, id: sessionId } : args
|
|
59
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
2
|
-
import { pipe, ReadonlyArray, Schema,
|
|
2
|
+
import { pipe, ReadonlyArray, ReadonlyRecord, Result, Schema, SchemaIssue } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import type { SqliteDsl } from '../schema/state/sqlite/db-schema/mod.ts'
|
|
5
5
|
import { sql } from '../util.ts'
|
|
6
|
-
import { objectEntries } from './misc.ts'
|
|
7
6
|
import * as ClientTypes from './types.ts'
|
|
8
7
|
|
|
9
8
|
export type BindValues = {
|
|
@@ -106,7 +105,6 @@ export const insertRows = <TColumns extends SqliteDsl.Columns>({
|
|
|
106
105
|
|
|
107
106
|
const bindValues = valuesArray.reduce(
|
|
108
107
|
(acc, values, itemIndex) => ({
|
|
109
|
-
// biome-ignore lint/performance/noAccumulatingSpread: TODO improve this some day
|
|
110
108
|
...acc,
|
|
111
109
|
...makeBindValues({ columns, values, variablePrefix: `item_${itemIndex}_` }),
|
|
112
110
|
}),
|
|
@@ -279,15 +277,14 @@ export const makeBindValues = <TColumns extends SqliteDsl.Columns, TKeys extends
|
|
|
279
277
|
skipNil?: boolean
|
|
280
278
|
}): Record<string, any> => {
|
|
281
279
|
const codecMap = pipe(
|
|
282
|
-
columns,
|
|
283
|
-
objectEntries,
|
|
280
|
+
ReadonlyRecord.toEntries(columns),
|
|
284
281
|
ReadonlyArray.map(([columnName, columnDef]) => [
|
|
285
282
|
columnName,
|
|
286
283
|
(value: any) => {
|
|
287
284
|
if (columnDef.nullable === true && (value === null || value === undefined)) return null
|
|
288
|
-
const res = Schema.
|
|
289
|
-
if (res
|
|
290
|
-
const parseErrorStr =
|
|
285
|
+
const res = Schema.encodeResult(columnDef.schema)(value)
|
|
286
|
+
if (Result.isFailure(res) === true) {
|
|
287
|
+
const parseErrorStr = SchemaIssue.makeFormatterDefault()(res.failure.issue)
|
|
291
288
|
const expectedSchemaStr = String(columnDef.schema.ast)
|
|
292
289
|
|
|
293
290
|
console.error(
|
|
@@ -303,9 +300,9 @@ Value:`,
|
|
|
303
300
|
)
|
|
304
301
|
// oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint for SQL decode errors
|
|
305
302
|
debugger
|
|
306
|
-
throw res.
|
|
303
|
+
throw res.failure
|
|
307
304
|
} else {
|
|
308
|
-
return res.
|
|
305
|
+
return res.success
|
|
309
306
|
}
|
|
310
307
|
},
|
|
311
308
|
]),
|
|
@@ -363,8 +360,7 @@ const buildWhereSql = <TColumns extends SqliteDsl.Columns>({
|
|
|
363
360
|
}
|
|
364
361
|
|
|
365
362
|
return pipe(
|
|
366
|
-
where,
|
|
367
|
-
objectEntries,
|
|
363
|
+
ReadonlyRecord.toEntries(where),
|
|
368
364
|
ReadonlyArray.map(([columnName, value]) => `${columnName} ${getWhereOp(columnName, value)}`),
|
|
369
365
|
ReadonlyArray.join(' AND '),
|
|
370
366
|
)
|
package/src/sql-queries/types.ts
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Schema } from '@livestore/utils/effect'
|
|
1
|
+
import type { Schema, Types } from '@livestore/utils/effect'
|
|
3
2
|
|
|
4
3
|
import type { SqliteDsl } from '../schema/state/sqlite/db-schema/mod.ts'
|
|
5
4
|
|
|
6
5
|
export type DecodedValuesForTableAll<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = {
|
|
7
|
-
[K in keyof GetColumns<TSchema, TTableName>]:
|
|
6
|
+
[K in keyof GetColumns<TSchema, TTableName>]: GetColumn<TSchema, TTableName, K>['schema']['Type']
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
export type DecodedValuesForTablePretty<
|
|
11
10
|
TSchema extends SqliteDsl.DbSchema,
|
|
12
11
|
TTableName extends keyof TSchema,
|
|
13
|
-
> =
|
|
12
|
+
> = Types.Simplify<DecodedValuesForTable<TSchema, TTableName>>
|
|
14
13
|
|
|
15
14
|
export type DecodedValuesForTable<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = Partial<
|
|
16
15
|
Pick<DecodedValuesForTableAll<TSchema, TTableName>, GetNullableColumnNamesForTable<TSchema, TTableName>>
|
|
@@ -40,7 +39,7 @@ export const isValidWhereOp = (op: string): op is WhereOp => {
|
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
export type EncodedValuesForTableAll<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = {
|
|
43
|
-
[K in keyof GetColumns<TSchema, TTableName>]:
|
|
42
|
+
[K in keyof GetColumns<TSchema, TTableName>]: GetColumn<TSchema, TTableName, K>['schema']['Type']
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
export type EncodedValuesForTable<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = Partial<
|
|
@@ -69,7 +68,7 @@ export type GetColumn<
|
|
|
69
68
|
> = TSchema[TTableName]['columns'][TColumnName]
|
|
70
69
|
|
|
71
70
|
export type DecodedValuesForColumnsAll<TColumns extends SqliteDsl.Columns> = {
|
|
72
|
-
[K in keyof TColumns]:
|
|
71
|
+
[K in keyof TColumns]: TColumns[K]['schema']['Type']
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
export type DecodedValuesForColumns<TColumns extends SqliteDsl.Columns> = Partial<
|
|
@@ -78,7 +77,7 @@ export type DecodedValuesForColumns<TColumns extends SqliteDsl.Columns> = Partia
|
|
|
78
77
|
Omit<DecodedValuesForColumnsAll<TColumns>, GetNullableColumnNames<TColumns>>
|
|
79
78
|
|
|
80
79
|
export type EncodedValuesForColumnsAll<TColumns extends SqliteDsl.Columns> = {
|
|
81
|
-
[K in keyof TColumns]:
|
|
80
|
+
[K in keyof TColumns]: TColumns[K]['schema']['Encoded']
|
|
82
81
|
}
|
|
83
82
|
|
|
84
83
|
export type EncodedValuesForColumns<TColumns extends SqliteDsl.Columns> = Partial<
|
package/src/sqlite-db-helper.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Schema } from '@livestore/utils/effect'
|
|
1
|
+
import { Effect, Exit, Function, Schema } from '@livestore/utils/effect'
|
|
2
2
|
|
|
3
3
|
import { type SqliteDb, SqliteError } from './adapter-types.ts'
|
|
4
4
|
import { getResultSchema, isQueryBuilder } from './schema/state/sqlite/query-builder/mod.ts'
|
|
@@ -33,13 +33,75 @@ export const makeSelect = <T>(
|
|
|
33
33
|
const { query, bindValues } = queryStrOrQueryBuilder.asSql()
|
|
34
34
|
const resultSchema = getResultSchema(queryStrOrQueryBuilder)
|
|
35
35
|
const results = select(query, bindValues as unknown as PreparedBindValues)
|
|
36
|
-
return Schema.
|
|
36
|
+
return Schema.decodeUnknownSync(resultSchema)(results)
|
|
37
37
|
} else {
|
|
38
38
|
return select(queryStrOrQueryBuilder, maybeBindValues)
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Runs an Effect inside an SQLite savepoint.
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
*
|
|
48
|
+
* This starts a savepoint before running `effect`, releases the savepoint on
|
|
49
|
+
* success, and rolls back to the savepoint before re-emitting the original
|
|
50
|
+
* failure on failure.
|
|
51
|
+
*
|
|
52
|
+
* Use this for atomic DB updates that need to compose with callers that may
|
|
53
|
+
* already have an open transaction.
|
|
54
|
+
*
|
|
55
|
+
* @see {@link https://sqlite.org/lang_savepoint.html | SQLite savepoint documentation}
|
|
56
|
+
* @see {@link https://sqlite.org/lang_transaction.html | SQLite transaction documentation}
|
|
57
|
+
*/
|
|
58
|
+
export const withSavepoint: {
|
|
59
|
+
(db: SqliteDb): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqliteError, R>
|
|
60
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, db: SqliteDb): Effect.Effect<A, E | SqliteError, R>
|
|
61
|
+
} = Function.dual(
|
|
62
|
+
2,
|
|
63
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, db: SqliteDb): Effect.Effect<A, E | SqliteError, R> =>
|
|
64
|
+
Effect.uninterruptibleMask((restore) =>
|
|
65
|
+
Effect.sync(generateSavepointName).pipe(
|
|
66
|
+
Effect.flatMap((savepointName) => {
|
|
67
|
+
const savepointSql = `SAVEPOINT ${savepointName}`
|
|
68
|
+
const releaseSql = `RELEASE SAVEPOINT ${savepointName}`
|
|
69
|
+
|
|
70
|
+
return executeSavepointSql(db, savepointSql).pipe(
|
|
71
|
+
// Cleanup is installed only after SQLite successfully creates the savepoint.
|
|
72
|
+
Effect.andThen(
|
|
73
|
+
restore(self).pipe(
|
|
74
|
+
Effect.exit,
|
|
75
|
+
Effect.flatMap((exit) => {
|
|
76
|
+
const cleanup =
|
|
77
|
+
Exit.isSuccess(exit) === true
|
|
78
|
+
? executeSavepointSql(db, releaseSql)
|
|
79
|
+
: executeSavepointSql(db, `ROLLBACK TO SAVEPOINT ${savepointName}`).pipe(
|
|
80
|
+
Effect.andThen(executeSavepointSql(db, releaseSql)),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
// Cleanup failures supersede the wrapped exit because the connection state is uncertain.
|
|
84
|
+
return cleanup.pipe(Effect.andThen(exit))
|
|
85
|
+
}),
|
|
86
|
+
),
|
|
87
|
+
),
|
|
88
|
+
)
|
|
89
|
+
}),
|
|
90
|
+
),
|
|
91
|
+
),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
let nextSavepointId = 0
|
|
95
|
+
|
|
96
|
+
/** Uses a reserved prefix and process-local counter to avoid caller-controlled or reused identifiers. */
|
|
97
|
+
const generateSavepointName = () => `livestore_savepoint_${nextSavepointId++}`
|
|
98
|
+
|
|
99
|
+
const executeSavepointSql = (db: SqliteDb, sql: string): Effect.Effect<void, SqliteError> =>
|
|
100
|
+
Effect.try({
|
|
101
|
+
try: () => db.execute(sql),
|
|
102
|
+
catch: (cause) => new SqliteError({ cause, query: { sql, bindValues: [] } }),
|
|
103
|
+
})
|
|
104
|
+
|
|
43
105
|
export const validateSnapshot = (snapshot: Uint8Array) => {
|
|
44
106
|
const headerBytes = new TextDecoder().decode(snapshot.slice(0, 16))
|
|
45
107
|
const hasValidHeader = headerBytes.startsWith('SQLite format 3')
|
package/src/sqlite-types.ts
CHANGED
|
@@ -18,12 +18,12 @@ export interface SqliteDb<TReq = any, TMetadata extends TReq = TReq> {
|
|
|
18
18
|
prepare(queryStr: string): PreparedStatement
|
|
19
19
|
execute(
|
|
20
20
|
queryStr: string,
|
|
21
|
-
bindValues?: PreparedBindValues
|
|
21
|
+
bindValues?: PreparedBindValues,
|
|
22
22
|
options?: { onRowsChanged?: (rowsChanged: number) => void },
|
|
23
23
|
): void
|
|
24
24
|
execute(queryBuilder: QueryBuilder.Any, options?: { onRowsChanged?: (rowsChanged: number) => void }): void
|
|
25
25
|
|
|
26
|
-
select<T>(queryStr: string, bindValues?: PreparedBindValues
|
|
26
|
+
select<T>(queryStr: string, bindValues?: PreparedBindValues): ReadonlyArray<T>
|
|
27
27
|
select<T>(queryBuilder: QueryBuilder<T, any, any>): T
|
|
28
28
|
|
|
29
29
|
export(): Uint8Array<ArrayBuffer>
|
|
@@ -67,11 +67,8 @@ export type SqliteDbChangeset = {
|
|
|
67
67
|
apply: () => void
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export const PersistenceInfo = Schema.Struct(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
74
|
-
{ key: Schema.String, value: Schema.Any },
|
|
75
|
-
).annotations({ title: 'LiveStore.PersistenceInfo' })
|
|
70
|
+
export const PersistenceInfo = Schema.StructWithRest(Schema.Struct({ fileName: Schema.String }), [
|
|
71
|
+
Schema.Record(Schema.String, Schema.Any),
|
|
72
|
+
]).annotate({ title: 'LiveStore.PersistenceInfo' })
|
|
76
73
|
|
|
77
74
|
export type PersistenceInfo<With extends {} = {}> = typeof PersistenceInfo.Type & With
|