@livestore/common 0.4.0 → 0.5.0-dev.1
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 +8 -8
- package/dist/__tests__/fixture.d.ts.map +1 -1
- package/dist/__tests__/fixture.js +4 -4
- package/dist/__tests__/fixture.js.map +1 -1
- package/dist/adapter-types.d.ts +33 -57
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +24 -41
- package/dist/adapter-types.js.map +1 -1
- package/dist/bounded-collections.d.ts.map +1 -1
- package/dist/bounded-collections.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 +32 -44
- 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 +2 -1
- package/dist/devtools/devtools-compatibility.test.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +522 -334
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +80 -78
- 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 +6 -6
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +410 -348
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +105 -93
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/devtools/devtools-messages.js +3 -3
- 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 +12 -8
- 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 +19 -17
- 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 +22 -19
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +87 -18
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +548 -480
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/RejectedPushError.d.ts +72 -41
- package/dist/leader-thread/RejectedPushError.d.ts.map +1 -1
- package/dist/leader-thread/RejectedPushError.js +25 -6
- 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 +11 -10
- package/dist/leader-thread/connection.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +15 -5
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +19 -19
- 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 +36 -20
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +15 -5
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +62 -58
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.test.js +9 -9
- 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 +12 -8
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/mod.js +9 -9
- package/dist/leader-thread/recreate-db.d.ts +5 -1
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +34 -59
- 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 +16 -21
- package/dist/leader-thread/stream-events.js.map +1 -1
- package/dist/leader-thread/types.d.ts +38 -73
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js +10 -6
- 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 +2 -3
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/make-client-session.js +5 -5
- 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 +9 -37
- 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 +3 -1
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +42 -33
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef/define.d.ts +6 -6
- 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 +3 -3
- 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/EventDef/facts.d.ts.map +1 -1
- package/dist/schema/EventDef/materializer.d.ts +2 -2
- package/dist/schema/EventDef/materializer.d.ts.map +1 -1
- package/dist/schema/EventDef/mod.js +5 -5
- package/dist/schema/EventSequenceNumber/client.d.ts +12 -17
- package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber/client.js +20 -24
- 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/mod.js +2 -2
- package/dist/schema/EventSequenceNumber.test.js +6 -6
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/LiveStoreEvent/client.d.ts +58 -187
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent/client.js +33 -30
- package/dist/schema/LiveStoreEvent/client.js.map +1 -1
- package/dist/schema/LiveStoreEvent/client.test.js +13 -4
- 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 +2 -2
- package/dist/schema/LiveStoreEvent/global.js.map +1 -1
- package/dist/schema/LiveStoreEvent/input.d.ts +6 -6
- 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/LiveStoreEvent/mod.js +4 -4
- package/dist/schema/events.js +1 -1
- package/dist/schema/mod.d.ts +1 -0
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +11 -10
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/schema.d.ts +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +6 -5
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/mod.js +2 -2
- package/dist/schema/state/sqlite/client-document-def.d.ts +13 -18
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +30 -27
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +53 -18
- 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 +73 -33
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +176 -75
- package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-spec.js +1 -1
- package/dist/schema/state/sqlite/column-spec.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.test.js +4 -4
- package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.d.ts +3 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.d.ts.map +1 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.js +5 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.js.map +1 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.d.ts +5 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.d.ts.map +1 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.js +183 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.js.map +1 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.d.ts +2 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.d.ts.map +1 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.js +142 -0
- package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.js.map +1 -0
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +3 -8
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +1 -73
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts.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 +9 -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 +28 -17
- 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 +6 -4
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.d.ts +3 -0
- package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.d.ts.map +1 -0
- package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.js +6 -0
- package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.js.map +1 -0
- package/dist/schema/state/sqlite/db-schema/mod.js +2 -2
- 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 +11 -10
- 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 +22 -23
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +18 -16
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +364 -598
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/mod.js +2 -2
- package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.js +2 -2
- package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.test.js +2 -2
- 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 +5 -5
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -1
- package/dist/schema/state/sqlite/system-tables/mod.js +2 -2
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +380 -115
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -1
- package/dist/schema/state/sqlite/system-tables/state-tables.js +47 -6
- package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.d.ts +17 -20
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/table-def.js +72 -6
- package/dist/schema/state/sqlite/table-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +207 -37
- 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 +3 -2
- package/dist/schema/unknown-events.js.map +1 -1
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +28 -6
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -1
- package/dist/schema-management/common.d.ts.map +1 -1
- package/dist/schema-management/common.js +2 -2
- package/dist/schema-management/migrations.d.ts +4 -4
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js +9 -9
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/schema-management/validate-schema.d.ts.map +1 -1
- package/dist/schema-management/validate-schema.js +1 -1
- 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/index.js +3 -3
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +11 -13
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
- package/dist/sql-queries/sql-query-builder.js +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 +23 -3
- package/dist/sqlite-db-helper.d.ts.map +1 -1
- package/dist/sqlite-db-helper.js +39 -4
- 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 +41 -19
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +200 -70
- 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 +3 -3
- package/dist/sync/errors.js.map +1 -1
- package/dist/sync/index.js +6 -6
- 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 +58 -37
- 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/compact-events.d.ts.map +1 -1
- package/dist/sync/next/compact-events.js +3 -3
- package/dist/sync/next/facts.d.ts.map +1 -1
- package/dist/sync/next/facts.js +1 -1
- package/dist/sync/next/history-dag-common.d.ts +5 -1
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +53 -32
- 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 +5 -4
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/mod.js +5 -5
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +2 -2
- package/dist/sync/next/test/compact-events.calculator.test.js +6 -6
- package/dist/sync/next/test/compact-events.test.js +4 -4
- package/dist/sync/next/test/event-fixtures.d.ts +8 -8
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +6 -6
- 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/next/test/mod.js +1 -1
- package/dist/sync/sync-backend-kv.d.ts.map +1 -1
- package/dist/sync/sync-backend-kv.js +5 -3
- 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 +10 -6
- 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/sync.js +2 -2
- package/dist/sync/syncstate.d.ts +100 -176
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +36 -39
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +103 -64
- 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/sync/validate-push-payload.d.ts.map +1 -1
- package/dist/sync/validate-push-payload.js +2 -2
- package/dist/testing/event-factory.d.ts.map +1 -1
- package/dist/testing/event-factory.js +2 -2
- package/dist/testing/event-factory.js.map +1 -1
- package/dist/testing/mod.js +1 -1
- package/dist/util.d.ts +11 -4
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +20 -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 +40 -57
- 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 +28 -61
- package/src/debug-info.ts +53 -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 +777 -650
- package/src/leader-thread/RejectedPushError.ts +40 -27
- package/src/leader-thread/connection.ts +12 -8
- package/src/leader-thread/eventlog.ts +20 -12
- package/src/leader-thread/leader-worker-devtools.ts +38 -20
- package/src/leader-thread/make-leader-thread-layer.test.ts +7 -7
- package/src/leader-thread/make-leader-thread-layer.ts +100 -71
- package/src/leader-thread/materialize-event.ts +13 -8
- package/src/leader-thread/recreate-db.ts +41 -75
- package/src/leader-thread/shutdown-channel.ts +3 -14
- package/src/leader-thread/stream-events.ts +102 -101
- package/src/leader-thread/types.ts +29 -62
- package/src/logging.ts +5 -52
- package/src/make-client-session.ts +6 -6
- package/src/materializer-helper.ts +7 -36
- package/src/otel.ts +5 -14
- package/src/rematerialize-from-eventlog.ts +116 -98
- 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 +20 -24
- 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 +4 -3
- package/src/schema/state/sqlite/client-document-def.test.ts +55 -20
- 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 +213 -77
- package/src/schema/state/sqlite/column-def.ts +87 -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/fingerprint-digest.ts +6 -0
- package/src/schema/state/sqlite/db-schema/ast/fingerprint.test.ts +209 -0
- package/src/schema/state/sqlite/db-schema/ast/fingerprint.ts +225 -0
- package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -81
- 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 +26 -31
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +35 -21
- package/src/schema/state/sqlite/db-schema/has-json-string-encoding.ts +9 -0
- package/src/schema/state/sqlite/mod.ts +4 -5
- 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 +24 -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 +54 -3
- package/src/schema/state/sqlite/table-def.test.ts +270 -66
- package/src/schema/state/sqlite/table-def.ts +112 -45
- package/src/schema/unknown-events.ts +3 -2
- package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +35 -4
- package/src/schema-management/migrations.ts +7 -6
- package/src/session-id-symbol.ts +59 -0
- package/src/sql-queries/sql-queries.ts +9 -13
- 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 +19 -9
- package/src/version.ts +1 -2
- package/dist/schema/state/sqlite/db-schema/hash.d.ts +0 -2
- package/dist/schema/state/sqlite/db-schema/hash.d.ts.map +0 -1
- package/dist/schema/state/sqlite/db-schema/hash.js +0 -15
- package/dist/schema/state/sqlite/db-schema/hash.js.map +0 -1
- 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/schema/state/sqlite/db-schema/hash.ts +0 -13
- package/src/sql-queries/misc.ts +0 -2
|
@@ -12,19 +12,19 @@ import { SqliteDsl } from './db-schema/mod.ts'
|
|
|
12
12
|
* Fields with both null and undefined will emit a warning as this is a lossy conversion.
|
|
13
13
|
*/
|
|
14
14
|
export const getColumnDefForSchema = (
|
|
15
|
-
schema: Schema.
|
|
15
|
+
schema: Schema.Top,
|
|
16
16
|
propertySignature?: SchemaAST.PropertySignature,
|
|
17
17
|
forceNullable = false,
|
|
18
18
|
): SqliteDsl.ColumnDefinition.Any => {
|
|
19
19
|
const ast = schema.ast
|
|
20
20
|
|
|
21
21
|
// Extract annotations
|
|
22
|
-
const getAnnotation = <T>(annotationId:
|
|
22
|
+
const getAnnotation = <T>(annotationId: string): Option.Option<T> =>
|
|
23
23
|
propertySignature !== undefined
|
|
24
24
|
? hasPropertyAnnotation<T>(propertySignature, annotationId)
|
|
25
|
-
: SchemaAST.
|
|
25
|
+
: Option.fromUndefinedOr(SchemaAST.resolveAt<T>(annotationId)(ast))
|
|
26
26
|
|
|
27
|
-
const columnType = SchemaAST.
|
|
27
|
+
const columnType = Option.fromUndefinedOr(SchemaAST.resolveAt<SqliteDsl.FieldColumnType>(ColumnType)(ast))
|
|
28
28
|
|
|
29
29
|
// Check if schema has null (e.g., Schema.NullOr) or undefined or if it's forced nullable (optional field)
|
|
30
30
|
const isNullable = forceNullable === true || hasNull(ast) === true || hasUndefined(ast) === true
|
|
@@ -50,13 +50,13 @@ export const getColumnDefForSchema = (
|
|
|
50
50
|
|
|
51
51
|
const hasPropertyAnnotation = <T>(
|
|
52
52
|
propertySignature: SchemaAST.PropertySignature,
|
|
53
|
-
annotationId:
|
|
53
|
+
annotationId: string,
|
|
54
54
|
): Option.Option<T> => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const keyAnnotation = propertySignature.type.context?.annotations?.[annotationId] as T | undefined
|
|
56
|
+
if (keyAnnotation !== undefined) {
|
|
57
|
+
return Option.some(keyAnnotation)
|
|
58
58
|
}
|
|
59
|
-
return SchemaAST.
|
|
59
|
+
return Option.fromUndefinedOr(SchemaAST.resolveAt<T>(annotationId)(propertySignature.type))
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
@@ -72,10 +72,11 @@ export const schemaFieldsToColumns = (
|
|
|
72
72
|
for (const prop of propertySignatures) {
|
|
73
73
|
if (typeof prop.name !== 'string') continue
|
|
74
74
|
|
|
75
|
-
const
|
|
75
|
+
const isOptional = SchemaAST.isOptional(prop.type)
|
|
76
|
+
const fieldSchema = Schema.make<Schema.Top>(prop.type)
|
|
76
77
|
|
|
77
78
|
// Warn about lossy conversion for fields with both null and undefined
|
|
78
|
-
if (
|
|
79
|
+
if (isOptional === true) {
|
|
79
80
|
const { hasNull, hasUndefined } = checkNullUndefined(fieldSchema.ast)
|
|
80
81
|
if (hasNull === true && hasUndefined === true) {
|
|
81
82
|
console.warn(`Field '${prop.name}' has both null and undefined - treating | undefined as | null`)
|
|
@@ -83,7 +84,7 @@ export const schemaFieldsToColumns = (
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
// Get column definition - pass nullable flag for optional fields
|
|
86
|
-
const columnDef = getColumnDefForSchema(fieldSchema, prop,
|
|
87
|
+
const columnDef = getColumnDefForSchema(fieldSchema, prop, isOptional === true)
|
|
87
88
|
|
|
88
89
|
// Check for primary key and unique annotations
|
|
89
90
|
const hasPrimaryKey = hasPropertyAnnotation<boolean>(prop, PrimaryKeyId).pipe(Option.getOrElse(() => false))
|
|
@@ -112,8 +113,8 @@ const checkNullUndefined = (ast: SchemaAST.AST): { hasNull: boolean; hasUndefine
|
|
|
112
113
|
let hasUndefined = false
|
|
113
114
|
|
|
114
115
|
const visit = (type: SchemaAST.AST): void => {
|
|
115
|
-
if (SchemaAST.
|
|
116
|
-
else if (SchemaAST.
|
|
116
|
+
if (SchemaAST.isUndefined(type) === true) hasUndefined = true
|
|
117
|
+
else if (SchemaAST.isNull(type) === true) hasNull = true
|
|
117
118
|
else if (SchemaAST.isUnion(type) === true) type.types.forEach(visit)
|
|
118
119
|
}
|
|
119
120
|
|
|
@@ -122,7 +123,7 @@ const checkNullUndefined = (ast: SchemaAST.AST): { hasNull: boolean; hasUndefine
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
const hasNull = (ast: SchemaAST.AST): boolean => {
|
|
125
|
-
if (SchemaAST.
|
|
126
|
+
if (SchemaAST.isNull(ast) === true) return true
|
|
126
127
|
if (SchemaAST.isUnion(ast) === true) {
|
|
127
128
|
return ast.types.some((type) => hasNull(type))
|
|
128
129
|
}
|
|
@@ -130,7 +131,7 @@ const hasNull = (ast: SchemaAST.AST): boolean => {
|
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
const hasUndefined = (ast: SchemaAST.AST): boolean => {
|
|
133
|
-
if (SchemaAST.
|
|
134
|
+
if (SchemaAST.isUndefined(ast) === true) return true
|
|
134
135
|
if (SchemaAST.isUnion(ast) === true) {
|
|
135
136
|
return ast.types.some((type) => hasUndefined(type))
|
|
136
137
|
}
|
|
@@ -152,36 +153,49 @@ const getColumnForType = (columnType: string, nullable = false): SqliteDsl.Colum
|
|
|
152
153
|
}
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
const getColumnForSchema = (schema: Schema.
|
|
156
|
+
const getColumnForSchema = (schema: Schema.Top, nullable = false): SqliteDsl.ColumnDefinition.Any => {
|
|
156
157
|
const ast = schema.ast
|
|
157
158
|
// Strip nullable wrapper to get core type
|
|
158
159
|
const coreAst = stripNullable(ast)
|
|
159
|
-
const coreSchema = stripNullable(ast) === ast ? schema : Schema.make(coreAst)
|
|
160
|
+
const coreSchema = (stripNullable(ast) === ast ? schema : Schema.make(coreAst)) as Schema.Codec<any, any>
|
|
160
161
|
|
|
161
162
|
// Special case: Boolean is transformed to integer in SQLite
|
|
162
|
-
if (SchemaAST.
|
|
163
|
+
if (SchemaAST.isBoolean(coreAst) === true) {
|
|
163
164
|
return SqliteDsl.boolean({ nullable })
|
|
164
165
|
}
|
|
165
166
|
|
|
166
167
|
// Get the encoded AST - what actually gets stored in SQLite
|
|
167
|
-
const encodedAst = Schema.
|
|
168
|
+
const encodedAst = Schema.toEncoded(coreSchema).ast
|
|
169
|
+
|
|
170
|
+
// Adapt Date values on the encoded side to ISO text, then run the original
|
|
171
|
+
// codec so its checks and transformations are preserved in both directions.
|
|
172
|
+
if (hasDateRepresentation(stripNullable(encodedAst)) === true) {
|
|
173
|
+
const encodedNullable = hasNull(encodedAst)
|
|
174
|
+
const dateStorage = encodedNullable === true ? Schema.NullOr(Schema.DateFromString) : Schema.DateFromString
|
|
175
|
+
const adaptedSchema = dateStorage.pipe(Schema.decodeTo(coreSchema))
|
|
176
|
+
return {
|
|
177
|
+
...SqliteDsl.text(),
|
|
178
|
+
schema: nullable === true ? Schema.NullOr(adaptedSchema) : adaptedSchema,
|
|
179
|
+
// Encoded nulls may decode to non-null values, so allow SQL NULL without
|
|
180
|
+
// bypassing the original codec's null transformation.
|
|
181
|
+
nullable: nullable === true || encodedNullable === true,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
168
184
|
|
|
169
185
|
// Check if the encoded type matches SQLite native types
|
|
170
|
-
if (SchemaAST.
|
|
186
|
+
if (SchemaAST.isString(encodedAst) === true) {
|
|
171
187
|
return SqliteDsl.text({ schema: coreSchema, nullable })
|
|
172
188
|
}
|
|
173
189
|
|
|
174
|
-
if (SchemaAST.
|
|
175
|
-
|
|
176
|
-
const id = SchemaAST.getIdentifierAnnotation(coreAst).pipe(Option.getOrElse(() => ''))
|
|
177
|
-
if (id === 'Int' || id === 'DateFromNumber') {
|
|
190
|
+
if (SchemaAST.isNumber(encodedAst) === true) {
|
|
191
|
+
if (hasCheck(coreAst.checks, 'effect/schema/isInt') === true || hasDateRepresentation(coreAst) === true) {
|
|
178
192
|
return SqliteDsl.integer({ schema: coreSchema, nullable })
|
|
179
193
|
}
|
|
180
194
|
return SqliteDsl.real({ schema: coreSchema, nullable })
|
|
181
195
|
}
|
|
182
196
|
|
|
183
197
|
if (isUint8ArraySchema(coreAst) === true || isUint8ArraySchema(encodedAst) === true) {
|
|
184
|
-
return SqliteDsl.blob({ schema:
|
|
198
|
+
return SqliteDsl.blob({ schema: coreSchema, nullable })
|
|
185
199
|
}
|
|
186
200
|
|
|
187
201
|
const literalColumn = getLiteralColumnDefinition(encodedAst, coreSchema, nullable, coreAst)
|
|
@@ -200,7 +214,7 @@ const stripNullable = (ast: SchemaAST.AST): SchemaAST.AST => {
|
|
|
200
214
|
|
|
201
215
|
// Filter out null/undefined members while preserving any annotations on the union
|
|
202
216
|
const coreTypes = ast.types.filter(
|
|
203
|
-
(type) =>
|
|
217
|
+
(type) => SchemaAST.isNull(type) === false && SchemaAST.isUndefined(type) === false,
|
|
204
218
|
)
|
|
205
219
|
|
|
206
220
|
if (coreTypes.length === 0 || coreTypes.length === ast.types.length) {
|
|
@@ -211,12 +225,12 @@ const stripNullable = (ast: SchemaAST.AST): SchemaAST.AST => {
|
|
|
211
225
|
return coreTypes[0]!
|
|
212
226
|
}
|
|
213
227
|
|
|
214
|
-
return SchemaAST.Union
|
|
228
|
+
return new SchemaAST.Union(coreTypes, ast.options, ast.annotations)
|
|
215
229
|
}
|
|
216
230
|
|
|
217
231
|
const getLiteralColumnDefinition = (
|
|
218
232
|
ast: SchemaAST.AST,
|
|
219
|
-
schema: Schema.
|
|
233
|
+
schema: Schema.Codec<any, any>,
|
|
220
234
|
nullable: boolean,
|
|
221
235
|
sourceAst: SchemaAST.AST,
|
|
222
236
|
): SqliteDsl.ColumnDefinition.Any | null => {
|
|
@@ -228,8 +242,7 @@ const getLiteralColumnDefinition = (
|
|
|
228
242
|
case 'string':
|
|
229
243
|
return SqliteDsl.text({ schema, nullable })
|
|
230
244
|
case 'number': {
|
|
231
|
-
|
|
232
|
-
if (id === 'Int' || id === 'DateFromNumber') {
|
|
245
|
+
if (hasCheck(sourceAst.checks, 'effect/schema/isInt') === true || hasDateRepresentation(sourceAst) === true) {
|
|
233
246
|
return SqliteDsl.integer({ schema, nullable })
|
|
234
247
|
}
|
|
235
248
|
|
|
@@ -247,6 +260,9 @@ const getLiteralColumnDefinition = (
|
|
|
247
260
|
}
|
|
248
261
|
}
|
|
249
262
|
|
|
263
|
+
/** Effect's built-in date codecs expose their semantic type through the Date representation annotation. */
|
|
264
|
+
const hasDateRepresentation = (ast: SchemaAST.AST): boolean => hasRepresentation(ast, 'effect/schema/Date')
|
|
265
|
+
|
|
250
266
|
const extractLiteralValues = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.LiteralValue> | null => {
|
|
251
267
|
if (SchemaAST.isLiteral(ast) === true) return [ast.literal]
|
|
252
268
|
|
|
@@ -255,7 +271,7 @@ const extractLiteralValues = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.Liter
|
|
|
255
271
|
ast.types.length > 0 &&
|
|
256
272
|
ast.types.every((type) => SchemaAST.isLiteral(type)) === true
|
|
257
273
|
) {
|
|
258
|
-
return ast.types.map((type) =>
|
|
274
|
+
return ast.types.map((type) => type.literal)
|
|
259
275
|
}
|
|
260
276
|
|
|
261
277
|
return null
|
|
@@ -264,7 +280,7 @@ const extractLiteralValues = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.Liter
|
|
|
264
280
|
const getLiteralValueType = (
|
|
265
281
|
literals: ReadonlyArray<SchemaAST.LiteralValue>,
|
|
266
282
|
): 'string' | 'number' | 'boolean' | 'bigint' | null => {
|
|
267
|
-
const literalTypes = new Set(literals.map((value) =>
|
|
283
|
+
const literalTypes = new Set(literals.map((value) => typeof value))
|
|
268
284
|
if (literalTypes.size !== 1) return null
|
|
269
285
|
|
|
270
286
|
const [literalType] = literalTypes
|
|
@@ -273,15 +289,49 @@ const getLiteralValueType = (
|
|
|
273
289
|
: null
|
|
274
290
|
}
|
|
275
291
|
|
|
292
|
+
/**
|
|
293
|
+
* Recursively checks for Effect built-in check metadata.
|
|
294
|
+
*
|
|
295
|
+
* Checks can be attached directly as `Filter`s or nested in `FilterGroup`s when
|
|
296
|
+
* schemas compose multiple refinements, e.g. `Schema.Int.check(...)`.
|
|
297
|
+
*
|
|
298
|
+
* Effect rc.109 replaced the closed `meta` annotation with the open `representation`
|
|
299
|
+
* identity, so built-in checks are matched by their representation id.
|
|
300
|
+
*/
|
|
301
|
+
const hasCheck = (checks: ReadonlyArray<SchemaAST.Check<unknown>> | undefined, representationId: string): boolean => {
|
|
302
|
+
return (
|
|
303
|
+
checks?.some((check) => {
|
|
304
|
+
switch (check._tag) {
|
|
305
|
+
case 'Filter':
|
|
306
|
+
return check.annotations?.representation?.id === representationId
|
|
307
|
+
case 'FilterGroup':
|
|
308
|
+
return hasCheck(check.checks, representationId)
|
|
309
|
+
}
|
|
310
|
+
}) === true
|
|
311
|
+
)
|
|
312
|
+
}
|
|
313
|
+
|
|
276
314
|
const isUint8ArraySchema = (ast: SchemaAST.AST): boolean => {
|
|
277
|
-
|
|
278
|
-
if (
|
|
315
|
+
// `resolveAt` reads the last check's annotations, which can mask the declaration's representation.
|
|
316
|
+
if (hasRepresentation(ast, 'effect/schema/Uint8Array') === true) {
|
|
317
|
+
return true
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const identifier = SchemaAST.resolveIdentifier(ast)
|
|
321
|
+
if (identifier !== undefined && identifier.includes('Uint8Array') === true) {
|
|
279
322
|
return true
|
|
280
323
|
}
|
|
281
324
|
|
|
282
|
-
if (SchemaAST.
|
|
283
|
-
return ast.elements.length === 0 && ast.rest.length === 1 && SchemaAST.
|
|
325
|
+
if (SchemaAST.isArrays(ast) === true) {
|
|
326
|
+
return ast.elements.length === 0 && ast.rest.length === 1 && SchemaAST.isNumber(ast.rest[0]!)
|
|
284
327
|
}
|
|
285
328
|
|
|
286
329
|
return false
|
|
287
330
|
}
|
|
331
|
+
|
|
332
|
+
const hasRepresentation = (ast: SchemaAST.AST, id: string): boolean => {
|
|
333
|
+
const representation = ast.annotations?.representation
|
|
334
|
+
return (
|
|
335
|
+
typeof representation === 'object' && representation !== null && 'id' in representation && representation.id === id
|
|
336
|
+
)
|
|
337
|
+
}
|
|
@@ -28,9 +28,9 @@ const createColumn = (
|
|
|
28
28
|
case 'text':
|
|
29
29
|
return Schema.String
|
|
30
30
|
case 'integer':
|
|
31
|
-
return options.defaultValue === true || options.defaultValue === false ? Schema.Boolean : Schema.
|
|
31
|
+
return options.defaultValue === true || options.defaultValue === false ? Schema.Boolean : Schema.Finite
|
|
32
32
|
case 'real':
|
|
33
|
-
return Schema.
|
|
33
|
+
return Schema.Finite
|
|
34
34
|
case 'blob':
|
|
35
35
|
return Schema.Uint8ArrayFromBase64
|
|
36
36
|
default:
|
|
@@ -19,7 +19,7 @@ export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
|
|
|
19
19
|
// is only valid on a single column declared as INTEGER PRIMARY KEY (column-level).
|
|
20
20
|
const columnDefStrs = tableAst.columns.map((column) =>
|
|
21
21
|
toSqliteColumnSpec(column, {
|
|
22
|
-
inlinePrimaryKey: hasSinglePk && column === pkColumn &&
|
|
22
|
+
inlinePrimaryKey: hasSinglePk && column === pkColumn && column.primaryKey,
|
|
23
23
|
}),
|
|
24
24
|
)
|
|
25
25
|
|
|
@@ -40,7 +40,8 @@ const toSqliteColumnSpec = (column: SqliteAst.Column, opts: { inlinePrimaryKey:
|
|
|
40
40
|
const nullableStr = opts.inlinePrimaryKey === true ? '' : column.nullable === false ? 'not null' : ''
|
|
41
41
|
|
|
42
42
|
// Only include AUTOINCREMENT when it's valid: single-column INTEGER PRIMARY KEY
|
|
43
|
-
const includeAutoIncrement =
|
|
43
|
+
const includeAutoIncrement =
|
|
44
|
+
opts.inlinePrimaryKey === true && column.type._tag === 'integer' && column.autoIncrement === true
|
|
44
45
|
|
|
45
46
|
const pkStr = opts.inlinePrimaryKey === true ? 'primary key' : ''
|
|
46
47
|
const autoIncrementStr = includeAutoIncrement === true ? 'autoincrement' : ''
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { sha256 } from '@noble/hashes/sha2.js'
|
|
2
|
+
|
|
3
|
+
import { Base64Url } from '@livestore/utils/effect'
|
|
4
|
+
|
|
5
|
+
/** Preserve every digest bit while staying inside the 56-character SQLite VFS filename limit. */
|
|
6
|
+
export const digestToFingerprint = (bytes: Uint8Array): string => Base64Url.encode(sha256(bytes))
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { Schema } from '@livestore/utils/effect'
|
|
4
|
+
|
|
5
|
+
import { liveStoreStorageFormatVersion } from '../../../../../version.ts'
|
|
6
|
+
import { makeState } from '../../mod.ts'
|
|
7
|
+
import { REBUILD_META_TABLE } from '../../system-tables/state-tables.ts'
|
|
8
|
+
import { SqliteDsl } from '../mod.ts'
|
|
9
|
+
import { digestToFingerprint } from './fingerprint-digest.ts'
|
|
10
|
+
import { fingerprint } from './fingerprint.ts'
|
|
11
|
+
|
|
12
|
+
describe('SQLite storage fingerprints', () => {
|
|
13
|
+
test('pins the final fingerprint output', () => {
|
|
14
|
+
expect(fingerprint(makePhysicalTable().ast)).toBe('UnLwYzVBhwzPCK5q7TrPU3q2N0dTe8m_98bud8HsAs8')
|
|
15
|
+
expect(fingerprint(makeJsonTable('documents', representativeJsonSchema).ast)).toBe(
|
|
16
|
+
'kUzaurzV2rcXYLljHOZ64TDR9c_RebqD7y5ZUM_nPBE',
|
|
17
|
+
)
|
|
18
|
+
expect(fingerprint(makeJsonTable('documents', normalizedCheckIdsJsonSchema).ast)).toBe(
|
|
19
|
+
'I0XYuOUSYqWwG5Opxbc1u-TNNE3pFQCHzpBZ_ChYGaA',
|
|
20
|
+
)
|
|
21
|
+
expect(makeState({ tables: [], materializers: {} }).sqlite.hash).toBe('o8mmnRDnhXhkgDpBybM3FK7S-PkaLEj_pKcnbzgg3TU')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('isolates pre-completion-marker state databases without changing the hash algorithm', () => {
|
|
25
|
+
const state = makeState({ tables: [], materializers: {} })
|
|
26
|
+
const legacyTables = [...state.sqlite.tables.values()]
|
|
27
|
+
.filter((table) => table.sqliteDef.name !== REBUILD_META_TABLE)
|
|
28
|
+
.map((table) => table.sqliteDef.ast)
|
|
29
|
+
const legacyHash = fingerprint({ _tag: 'dbSchema', tables: legacyTables })
|
|
30
|
+
expect(legacyHash).toBe('H5Uktp6Ffp84WDj_RWPnfDnaQEu_E61AMl7ieZ9Zn8k')
|
|
31
|
+
expect(state.sqlite.hash).not.toBe(legacyHash)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('matches the standard SHA-256 vector', () => {
|
|
35
|
+
expect(digestToFingerprint(new TextEncoder().encode('abc'))).toBe('ungWv48Bz-pBQUDeXa4iI7ADYaOWF3qctBD_YfIAFa0')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('keeps the full digest inside the Cloudflare VFS filename limit', () => {
|
|
39
|
+
const value = fingerprint(makePhysicalTable().ast)
|
|
40
|
+
|
|
41
|
+
expect(value).toHaveLength(43)
|
|
42
|
+
expect(`state${value}@${liveStoreStorageFormatVersion}.db`.length).toBeLessThanOrEqual(56)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('is independent of table and index declaration order', () => {
|
|
46
|
+
const first = makeJsonTable('first', Schema.Struct({ value: Schema.String }))
|
|
47
|
+
const second = makeJsonTable('second', Schema.Struct({ value: Schema.Finite }))
|
|
48
|
+
|
|
49
|
+
expect(fingerprint({ _tag: 'dbSchema', tables: [first.ast, second.ast] })).toBe(
|
|
50
|
+
fingerprint({ _tag: 'dbSchema', tables: [second.ast, first.ast] }),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
const table = SqliteDsl.table(
|
|
54
|
+
'indexed',
|
|
55
|
+
{
|
|
56
|
+
id: SqliteDsl.text({ primaryKey: true }),
|
|
57
|
+
age: SqliteDsl.integer(),
|
|
58
|
+
},
|
|
59
|
+
[
|
|
60
|
+
{ name: 'indexed_by_age', columns: ['age'], isUnique: false },
|
|
61
|
+
{ name: 'indexed_by_id', columns: ['id'], isUnique: true },
|
|
62
|
+
],
|
|
63
|
+
).ast
|
|
64
|
+
expect(fingerprint({ ...table, indexes: table.indexes.toReversed() })).toBe(fingerprint(table))
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('ignores Effect metadata that does not affect accepted encoded JSON', () => {
|
|
68
|
+
const plain = makeJsonTable('documents', Schema.Struct({ value: Schema.String }))
|
|
69
|
+
const annotated = makeJsonTable(
|
|
70
|
+
'documents',
|
|
71
|
+
Schema.Struct({ value: Schema.String }).annotate({ description: 'documentation only', title: 'Document' }),
|
|
72
|
+
)
|
|
73
|
+
const readonlyArray = makeJsonTable('documents', Schema.Array(Schema.String))
|
|
74
|
+
const mutableArray = makeJsonTable('documents', Schema.mutable(Schema.Array(Schema.String)))
|
|
75
|
+
|
|
76
|
+
expect(fingerprint(plain.ast)).toBe(fingerprint(annotated.ast))
|
|
77
|
+
expect(fingerprint(readonlyArray.ast)).toBe(fingerprint(mutableArray.ast))
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('changes when represented JSON checks change', () => {
|
|
81
|
+
const minimumTwo = makeJsonTable('documents', Schema.Struct({ value: Schema.String.check(Schema.isMinLength(2)) }))
|
|
82
|
+
const minimumThree = makeJsonTable(
|
|
83
|
+
'documents',
|
|
84
|
+
Schema.Struct({ value: Schema.String.check(Schema.isMinLength(3)) }),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
expect(fingerprint(minimumTwo.ast)).not.toBe(fingerprint(minimumThree.ast))
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('distinguishes codecs with the same encoded primitive', () => {
|
|
91
|
+
const date = makeJsonTable('documents', Schema.Struct({ value: Schema.DateFromString }))
|
|
92
|
+
const string = makeJsonTable('documents', Schema.Struct({ value: Schema.String }))
|
|
93
|
+
|
|
94
|
+
expect(fingerprint(date.ast)).not.toBe(fingerprint(string.ast))
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('handles recursive JSON schemas deterministically', () => {
|
|
98
|
+
const first = makeJsonTable('trees', makeTreeSchema())
|
|
99
|
+
const second = makeJsonTable('trees', makeTreeSchema())
|
|
100
|
+
|
|
101
|
+
expect(fingerprint(first.ast)).toBe(fingerprint(second.ast))
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
test('supports opaque Effect schemas without persistence annotations', () => {
|
|
105
|
+
const OpaqueString = Schema.declare<string>((value): value is string => typeof value === 'string')
|
|
106
|
+
const table = makeJsonTable('opaque_documents', Schema.Struct({ value: OpaqueString }))
|
|
107
|
+
|
|
108
|
+
expect(() => fingerprint(table.ast)).not.toThrow()
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('keeps application-owned representation payload fields', () => {
|
|
112
|
+
const first = Schema.declare<string>((value): value is string => typeof value === 'string', {
|
|
113
|
+
representation: { id: 'example/opaque', payload: { annotations: 'first', isMutable: true } },
|
|
114
|
+
})
|
|
115
|
+
const second = Schema.declare<string>((value): value is string => typeof value === 'string', {
|
|
116
|
+
representation: { id: 'example/opaque', payload: { annotations: 'second', isMutable: true } },
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
expect(fingerprint(makeJsonTable('documents', first).ast)).not.toBe(
|
|
120
|
+
fingerprint(makeJsonTable('documents', second).ast),
|
|
121
|
+
)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('tracks JSON codecs passed through the generic text column API', () => {
|
|
125
|
+
const first = SqliteDsl.table('documents', {
|
|
126
|
+
value: SqliteDsl.text({ schema: Schema.fromJsonString(Schema.Struct({ value: Schema.String })) }),
|
|
127
|
+
})
|
|
128
|
+
const second = SqliteDsl.table('documents', {
|
|
129
|
+
value: SqliteDsl.text({ schema: Schema.fromJsonString(Schema.Struct({ value: Schema.Finite })) }),
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
expect(fingerprint(first.ast)).not.toBe(fingerprint(second.ast))
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('gives equivalent JSON DSL forms the same fingerprint', () => {
|
|
136
|
+
const valueSchema = Schema.Struct({ value: Schema.String })
|
|
137
|
+
const specialized = SqliteDsl.table('documents', {
|
|
138
|
+
value: SqliteDsl.json({ schema: valueSchema }),
|
|
139
|
+
})
|
|
140
|
+
const generic = SqliteDsl.table('documents', {
|
|
141
|
+
value: SqliteDsl.text({ schema: Schema.fromJsonString(valueSchema) }),
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
expect(fingerprint(specialized.ast)).toBe(fingerprint(generic.ast))
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test('classifies physical defaults without hashing function source text', () => {
|
|
148
|
+
const none = SqliteDsl.text()
|
|
149
|
+
const firstThunk = SqliteDsl.text({ default: () => 'first' })
|
|
150
|
+
const secondThunk = SqliteDsl.text({ default: () => 'second' })
|
|
151
|
+
const literal = SqliteDsl.text({ default: 'first' })
|
|
152
|
+
const toTable = (definition: SqliteDsl.ColumnDefinition.Any) =>
|
|
153
|
+
SqliteDsl.table('defaults', { value: definition }).ast
|
|
154
|
+
|
|
155
|
+
expect(fingerprint(toTable(firstThunk))).toBe(fingerprint(toTable(secondThunk)))
|
|
156
|
+
expect(fingerprint(toTable(firstThunk))).not.toBe(fingerprint(toTable(none)))
|
|
157
|
+
expect(fingerprint(toTable(literal))).not.toBe(fingerprint(toTable(firstThunk)))
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
const makePhysicalTable = () =>
|
|
162
|
+
SqliteDsl.table(
|
|
163
|
+
'users',
|
|
164
|
+
{
|
|
165
|
+
id: SqliteDsl.text({ primaryKey: true }),
|
|
166
|
+
age: SqliteDsl.integer({ nullable: true }),
|
|
167
|
+
},
|
|
168
|
+
[{ name: 'users_by_age', columns: ['age'], isUnique: false }],
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
const makeJsonTable = (name: string, schema: Schema.Codec<unknown, unknown>) =>
|
|
172
|
+
SqliteDsl.table(name, {
|
|
173
|
+
id: SqliteDsl.text({ primaryKey: true }),
|
|
174
|
+
value: SqliteDsl.json({ schema }),
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
const representativeJsonSchema = Schema.Struct({
|
|
178
|
+
title: Schema.String.check(Schema.isMinLength(1)),
|
|
179
|
+
tags: Schema.Array(Schema.String),
|
|
180
|
+
status: Schema.Union([Schema.Literal('draft'), Schema.Literal('published')]),
|
|
181
|
+
publishedAt: Schema.NullOr(Schema.DateFromString),
|
|
182
|
+
metadata: Schema.Record(Schema.String, Schema.Json),
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
/** Uses the JSON-compatible checks whose representation ids the fingerprint normalizes. */
|
|
186
|
+
const normalizedCheckIdsJsonSchema = Schema.Struct({
|
|
187
|
+
slug: Schema.String.check(
|
|
188
|
+
Schema.isBetweenLength(1, 64),
|
|
189
|
+
Schema.isStartingWith('a'),
|
|
190
|
+
Schema.isEndingWith('z'),
|
|
191
|
+
Schema.isIncluding('-'),
|
|
192
|
+
),
|
|
193
|
+
tags: Schema.Array(Schema.String).check(Schema.isBetweenLength(0, 10)),
|
|
194
|
+
initial: Schema.Char,
|
|
195
|
+
labels: Schema.Record(Schema.String, Schema.String).check(Schema.isBetweenProperties(0, 5)),
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
interface TreeNode {
|
|
199
|
+
readonly value: string
|
|
200
|
+
readonly children: ReadonlyArray<TreeNode>
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const makeTreeSchema = (): Schema.Codec<TreeNode> => {
|
|
204
|
+
const TreeNode: Schema.Codec<TreeNode> = Schema.Struct({
|
|
205
|
+
value: Schema.String,
|
|
206
|
+
children: Schema.Array(Schema.suspend(() => TreeNode)),
|
|
207
|
+
})
|
|
208
|
+
return TreeNode
|
|
209
|
+
}
|