@livestore/common 0.4.0-dev.2 → 0.4.0-dev.21
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 +20 -12
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
- package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
- package/dist/adapter-types.d.ts +14 -6
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js.map +1 -1
- package/dist/debug-info.d.ts.map +1 -1
- package/dist/debug-info.js +33 -6
- package/dist/debug-info.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +28 -23
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +2 -2
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +7 -14
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +1 -6
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +38 -29
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +9 -8
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/devtools/devtools-sessioninfo.d.ts +14 -2
- package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
- package/dist/devtools/devtools-sessioninfo.js +7 -4
- package/dist/devtools/devtools-sessioninfo.js.map +1 -1
- package/dist/devtools/mod.d.ts +13 -2
- package/dist/devtools/mod.d.ts.map +1 -1
- package/dist/devtools/mod.js +10 -3
- package/dist/devtools/mod.js.map +1 -1
- package/dist/errors.d.ts +52 -10
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +25 -6
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +41 -4
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +158 -75
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +21 -22
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +77 -20
- package/dist/leader-thread/eventlog.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts +2 -2
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +56 -45
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +6 -6
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +79 -27
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.test.d.ts +2 -0
- package/dist/leader-thread/make-leader-thread-layer.test.d.ts.map +1 -0
- package/dist/leader-thread/make-leader-thread-layer.test.js +32 -0
- package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -0
- package/dist/leader-thread/materialize-event.d.ts +3 -3
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +25 -11
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/mod.d.ts +1 -0
- package/dist/leader-thread/mod.d.ts.map +1 -1
- package/dist/leader-thread/mod.js +1 -0
- package/dist/leader-thread/mod.js.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts +2 -3
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +5 -5
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/shutdown-channel.d.ts +2 -2
- package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
- package/dist/leader-thread/shutdown-channel.js +2 -2
- package/dist/leader-thread/shutdown-channel.js.map +1 -1
- package/dist/leader-thread/stream-events.d.ts +56 -0
- package/dist/leader-thread/stream-events.d.ts.map +1 -0
- package/dist/leader-thread/stream-events.js +166 -0
- package/dist/leader-thread/stream-events.js.map +1 -0
- package/dist/leader-thread/types.d.ts +98 -20
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js +13 -0
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/logging.d.ts +40 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +33 -0
- package/dist/logging.js.map +1 -0
- package/dist/make-client-session.d.ts +5 -3
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/make-client-session.js +5 -2
- package/dist/make-client-session.js.map +1 -1
- package/dist/materializer-helper.d.ts +6 -6
- package/dist/materializer-helper.d.ts.map +1 -1
- package/dist/materializer-helper.js +20 -4
- package/dist/materializer-helper.js.map +1 -1
- package/dist/otel.d.ts +2 -1
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +5 -0
- package/dist/otel.js.map +1 -1
- package/dist/rematerialize-from-eventlog.d.ts +2 -2
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +29 -20
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef/define.d.ts +147 -0
- package/dist/schema/EventDef/define.d.ts.map +1 -0
- package/dist/schema/EventDef/define.js +139 -0
- package/dist/schema/EventDef/define.js.map +1 -0
- package/dist/schema/EventDef/event-def.d.ts +106 -0
- package/dist/schema/EventDef/event-def.d.ts.map +1 -0
- package/dist/schema/EventDef/event-def.js +2 -0
- package/dist/schema/EventDef/event-def.js.map +1 -0
- package/dist/schema/EventDef/facts.d.ts +118 -0
- package/dist/schema/EventDef/facts.d.ts.map +1 -0
- package/dist/schema/EventDef/facts.js +53 -0
- package/dist/schema/EventDef/facts.js.map +1 -0
- package/dist/schema/EventDef/materializer.d.ts +155 -0
- package/dist/schema/EventDef/materializer.d.ts.map +1 -0
- package/dist/schema/EventDef/materializer.js +83 -0
- package/dist/schema/EventDef/materializer.js.map +1 -0
- package/dist/schema/EventDef/mod.d.ts +5 -0
- package/dist/schema/EventDef/mod.d.ts.map +1 -0
- package/dist/schema/EventDef/mod.js +5 -0
- package/dist/schema/EventDef/mod.js.map +1 -0
- package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
- package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/client.js +193 -0
- package/dist/schema/EventSequenceNumber/client.js.map +1 -0
- package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
- package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/global.js +14 -0
- package/dist/schema/EventSequenceNumber/global.js.map +1 -0
- package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
- package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/mod.js +37 -0
- package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
- package/dist/schema/EventSequenceNumber.test.js +43 -43
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +89 -106
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
- package/dist/schema/{LiveStoreEvent.js → LiveStoreEvent/client.js} +74 -58
- package/dist/schema/LiveStoreEvent/client.js.map +1 -0
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
- package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
- package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
- package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/global.js +31 -0
- package/dist/schema/LiveStoreEvent/global.js.map +1 -0
- package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
- package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/input.js +26 -0
- package/dist/schema/LiveStoreEvent/input.js.map +1 -0
- package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
- package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/mod.js +5 -0
- package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
- package/dist/schema/events.d.ts +1 -1
- package/dist/schema/events.d.ts.map +1 -1
- package/dist/schema/events.js +1 -1
- package/dist/schema/events.js.map +1 -1
- package/dist/schema/mod.d.ts +6 -4
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +5 -4
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/schema.d.ts +16 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +27 -2
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +36 -6
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +97 -6
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +16 -0
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.js +14 -6
- package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.js +69 -22
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +48 -10
- 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 +30 -12
- package/dist/schema/state/sqlite/column-spec.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.test.js +23 -14
- package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +23 -6
- 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 +14 -8
- 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 +5 -3
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js +2 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts +3 -3
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +3 -3
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/api.d.ts +19 -11
- 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 -15
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +6 -3
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +252 -88
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
- package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.js +22 -12
- package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
- package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
- package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
- package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
- package/dist/schema/state/sqlite/{system-tables.d.ts → system-tables/eventlog-tables.d.ts} +63 -456
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -0
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +54 -0
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -0
- package/dist/schema/state/sqlite/system-tables/mod.d.ts +3 -0
- package/dist/schema/state/sqlite/system-tables/mod.d.ts.map +1 -0
- package/dist/schema/state/sqlite/system-tables/mod.js +3 -0
- package/dist/schema/state/sqlite/system-tables/mod.js.map +1 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +456 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.js +55 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
- package/dist/schema/state/sqlite/table-def.d.ts +4 -4
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/table-def.js +2 -2
- package/dist/schema/state/sqlite/table-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +80 -0
- package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
- package/dist/schema/unknown-events.d.ts +47 -0
- package/dist/schema/unknown-events.d.ts.map +1 -0
- package/dist/schema/unknown-events.js +69 -0
- package/dist/schema/unknown-events.js.map +1 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts +2 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts.map +1 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +73 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -0
- package/dist/schema-management/migrations.d.ts +32 -2
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js +37 -5
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/schema-management/validate-schema.d.ts +3 -3
- package/dist/schema-management/validate-schema.d.ts.map +1 -1
- package/dist/schema-management/validate-schema.js +2 -2
- package/dist/schema-management/validate-schema.js.map +1 -1
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +11 -1
- 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 +2 -1
- package/dist/sql-queries/sql-query-builder.js.map +1 -1
- package/dist/sqlite-types.d.ts +3 -3
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +11 -13
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +45 -42
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/errors.d.ts +66 -0
- package/dist/sync/errors.d.ts.map +1 -0
- package/dist/sync/errors.js +36 -0
- package/dist/sync/errors.js.map +1 -0
- package/dist/sync/index.d.ts +3 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +3 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/mock-sync-backend.d.ts +23 -0
- package/dist/sync/mock-sync-backend.d.ts.map +1 -0
- package/dist/sync/mock-sync-backend.js +114 -0
- package/dist/sync/mock-sync-backend.js.map +1 -0
- package/dist/sync/next/compact-events.d.ts.map +1 -1
- package/dist/sync/next/compact-events.js +6 -7
- package/dist/sync/next/compact-events.js.map +1 -1
- package/dist/sync/next/facts.d.ts +5 -5
- package/dist/sync/next/facts.d.ts.map +1 -1
- package/dist/sync/next/facts.js +1 -2
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts +54 -15
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +198 -9
- 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 +10 -8
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts +5 -5
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +5 -5
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/event-fixtures.d.ts +2 -2
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +9 -9
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/sync-backend-kv.d.ts +7 -0
- package/dist/sync/sync-backend-kv.d.ts.map +1 -0
- package/dist/sync/sync-backend-kv.js +18 -0
- package/dist/sync/sync-backend-kv.js.map +1 -0
- package/dist/sync/sync-backend.d.ts +105 -0
- package/dist/sync/sync-backend.d.ts.map +1 -0
- package/dist/sync/sync-backend.js +61 -0
- package/dist/sync/sync-backend.js.map +1 -0
- package/dist/sync/sync.d.ts +9 -86
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js +2 -27
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/syncstate.d.ts +57 -44
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +50 -45
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +83 -46
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/transport-chunking.d.ts +36 -0
- package/dist/sync/transport-chunking.d.ts.map +1 -0
- package/dist/sync/transport-chunking.js +56 -0
- package/dist/sync/transport-chunking.js.map +1 -0
- package/dist/sync/validate-push-payload.d.ts +2 -2
- package/dist/sync/validate-push-payload.d.ts.map +1 -1
- package/dist/sync/validate-push-payload.js +6 -6
- package/dist/sync/validate-push-payload.js.map +1 -1
- package/dist/testing/event-factory.d.ts +68 -0
- package/dist/testing/event-factory.d.ts.map +1 -0
- package/dist/testing/event-factory.js +78 -0
- package/dist/testing/event-factory.js.map +1 -0
- package/dist/testing/mod.d.ts +2 -0
- package/dist/testing/mod.d.ts.map +1 -0
- package/dist/testing/mod.js +2 -0
- package/dist/testing/mod.js.map +1 -0
- package/dist/version.d.ts +16 -6
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +16 -6
- package/dist/version.js.map +1 -1
- package/package.json +7 -8
- package/src/ClientSessionLeaderThreadProxy.ts +20 -12
- package/src/adapter-types.ts +18 -6
- package/src/debug-info.ts +37 -6
- package/src/devtools/devtools-messages-client-session.ts +2 -2
- package/src/devtools/devtools-messages-common.ts +1 -8
- package/src/devtools/devtools-messages-leader.ts +9 -8
- package/src/devtools/devtools-sessioninfo.ts +8 -5
- package/src/devtools/mod.ts +11 -2
- package/src/errors.ts +38 -11
- package/src/index.ts +2 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +277 -105
- package/src/leader-thread/eventlog.ts +113 -38
- package/src/leader-thread/leader-worker-devtools.ts +86 -55
- package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
- package/src/leader-thread/make-leader-thread-layer.ts +156 -37
- package/src/leader-thread/materialize-event.ts +37 -12
- package/src/leader-thread/mod.ts +1 -0
- package/src/leader-thread/recreate-db.ts +15 -7
- package/src/leader-thread/shutdown-channel.ts +16 -2
- package/src/leader-thread/stream-events.ts +201 -0
- package/src/leader-thread/types.ts +70 -20
- package/src/logging.ts +62 -0
- package/src/make-client-session.ts +9 -3
- package/src/materializer-helper.ts +27 -10
- package/src/otel.ts +10 -0
- package/src/rematerialize-from-eventlog.ts +37 -27
- package/src/schema/EventDef/define.ts +201 -0
- package/src/schema/EventDef/event-def.ts +120 -0
- package/src/schema/EventDef/facts.ts +135 -0
- package/src/schema/EventDef/materializer.ts +172 -0
- package/src/schema/EventDef/mod.ts +4 -0
- package/src/schema/EventSequenceNumber/client.ts +257 -0
- package/src/schema/EventSequenceNumber/global.ts +19 -0
- package/src/schema/EventSequenceNumber/mod.ts +37 -0
- package/src/schema/EventSequenceNumber.test.ts +70 -52
- package/src/schema/LiveStoreEvent/client.ts +221 -0
- package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
- package/src/schema/LiveStoreEvent/global.ts +45 -0
- package/src/schema/LiveStoreEvent/input.ts +63 -0
- package/src/schema/LiveStoreEvent/mod.ts +4 -0
- package/src/schema/events.ts +1 -1
- package/src/schema/mod.ts +6 -4
- package/src/schema/schema.ts +39 -3
- package/src/schema/state/sqlite/client-document-def.test.ts +19 -2
- package/src/schema/state/sqlite/client-document-def.ts +127 -25
- package/src/schema/state/sqlite/column-annotations.test.ts +1 -1
- package/src/schema/state/sqlite/column-annotations.ts +16 -6
- package/src/schema/state/sqlite/column-def.test.ts +62 -10
- package/src/schema/state/sqlite/column-def.ts +88 -21
- package/src/schema/state/sqlite/column-spec.test.ts +29 -16
- package/src/schema/state/sqlite/column-spec.ts +36 -11
- package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +26 -6
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +29 -12
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +12 -17
- package/src/schema/state/sqlite/mod.ts +4 -3
- package/src/schema/state/sqlite/query-builder/api.ts +25 -11
- package/src/schema/state/sqlite/query-builder/astToSql.ts +23 -14
- package/src/schema/state/sqlite/query-builder/impl.test.ts +305 -92
- package/src/schema/state/sqlite/query-builder/impl.ts +8 -3
- package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
- package/src/schema/state/sqlite/schema-helpers.ts +28 -20
- package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +64 -0
- package/src/schema/state/sqlite/system-tables/mod.ts +2 -0
- package/src/schema/state/sqlite/system-tables/state-tables.ts +69 -0
- package/src/schema/state/sqlite/table-def.test.ts +101 -0
- package/src/schema/state/sqlite/table-def.ts +8 -6
- package/src/schema/unknown-events.ts +131 -0
- package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +86 -0
- package/src/schema-management/migrations.ts +41 -8
- package/src/schema-management/validate-schema.ts +3 -3
- package/src/sql-queries/sql-queries.ts +9 -1
- package/src/sql-queries/sql-query-builder.ts +2 -1
- package/src/sqlite-types.ts +3 -3
- package/src/sync/ClientSessionSyncProcessor.ts +69 -62
- package/src/sync/errors.ts +38 -0
- package/src/sync/index.ts +3 -0
- package/src/sync/mock-sync-backend.ts +184 -0
- package/src/sync/next/compact-events.ts +6 -7
- package/src/sync/next/facts.ts +7 -9
- package/src/sync/next/history-dag-common.ts +277 -26
- package/src/sync/next/history-dag.ts +16 -10
- package/src/sync/next/rebase-events.ts +11 -11
- package/src/sync/next/test/event-fixtures.ts +11 -11
- package/src/sync/sync-backend-kv.ts +22 -0
- package/src/sync/sync-backend.ts +185 -0
- package/src/sync/sync.ts +9 -91
- package/src/sync/syncstate.test.ts +96 -52
- package/src/sync/syncstate.ts +69 -58
- package/src/sync/transport-chunking.ts +90 -0
- package/src/sync/validate-push-payload.ts +8 -9
- package/src/testing/event-factory.ts +131 -0
- package/src/testing/mod.ts +1 -0
- package/src/version.ts +16 -6
- package/dist/schema/EventDef.d.ts +0 -123
- package/dist/schema/EventDef.d.ts.map +0 -1
- package/dist/schema/EventDef.js +0 -46
- package/dist/schema/EventDef.js.map +0 -1
- package/dist/schema/EventSequenceNumber.d.ts +0 -80
- package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
- package/dist/schema/EventSequenceNumber.js +0 -139
- package/dist/schema/EventSequenceNumber.js.map +0 -1
- package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
- package/dist/schema/LiveStoreEvent.js.map +0 -1
- package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
- package/dist/schema/state/sqlite/system-tables.js +0 -79
- package/dist/schema/state/sqlite/system-tables.js.map +0 -1
- package/dist/schema-management/migrations.test.d.ts +0 -2
- package/dist/schema-management/migrations.test.d.ts.map +0 -1
- package/dist/schema-management/migrations.test.js +0 -52
- package/dist/schema-management/migrations.test.js.map +0 -1
- package/dist/sync/next/graphology.d.ts +0 -8
- package/dist/sync/next/graphology.d.ts.map +0 -1
- package/dist/sync/next/graphology.js +0 -30
- package/dist/sync/next/graphology.js.map +0 -1
- package/dist/sync/next/graphology_.d.ts +0 -3
- package/dist/sync/next/graphology_.d.ts.map +0 -1
- package/dist/sync/next/graphology_.js +0 -3
- package/dist/sync/next/graphology_.js.map +0 -1
- package/src/schema/EventDef.ts +0 -219
- package/src/schema/EventSequenceNumber.ts +0 -199
- package/src/schema/LiveStoreEvent.ts +0 -287
- package/src/schema/state/sqlite/system-tables.ts +0 -104
- package/src/sync/next/ambient.d.ts +0 -3
- package/src/sync/next/graphology.ts +0 -41
- package/src/sync/next/graphology_.ts +0 -2
|
@@ -10,33 +10,58 @@ import { type SqliteAst, SqliteDsl } from './db-schema/mod.ts'
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const pkColumns = tableAst.columns.filter((_) => _.primaryKey)
|
|
14
|
+
const hasSinglePk = pkColumns.length === 1
|
|
15
|
+
const pkColumn = hasSinglePk ? pkColumns[0] : undefined
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
// Build column definitions, handling the special SQLite rule that AUTOINCREMENT
|
|
18
|
+
// is only valid on a single column declared as INTEGER PRIMARY KEY (column-level).
|
|
19
|
+
const columnDefStrs = tableAst.columns.map((column) =>
|
|
20
|
+
toSqliteColumnSpec(column, {
|
|
21
|
+
inlinePrimaryKey: hasSinglePk && column === pkColumn && column.primaryKey === true,
|
|
22
|
+
}),
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
// For composite primary keys, add a table-level PRIMARY KEY clause.
|
|
26
|
+
if (pkColumns.length > 1) {
|
|
27
|
+
const quotedPkCols = pkColumns.map((_) => `"${_.name}"`)
|
|
28
|
+
columnDefStrs.push(`PRIMARY KEY (${quotedPkCols.join(', ')})`)
|
|
18
29
|
}
|
|
19
30
|
|
|
20
31
|
return columnDefStrs.join(', ')
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
/** NOTE primary keys are applied on a table level not on a column level to account for multi-column primary keys */
|
|
24
|
-
const toSqliteColumnSpec = (column: SqliteAst.Column) => {
|
|
35
|
+
const toSqliteColumnSpec = (column: SqliteAst.Column, opts: { inlinePrimaryKey: boolean }) => {
|
|
25
36
|
const columnTypeStr = column.type._tag
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
// When PRIMARY KEY is declared inline, NOT NULL is implied and should not be emitted,
|
|
38
|
+
// and AUTOINCREMENT must immediately follow PRIMARY KEY within the same constraint.
|
|
39
|
+
const nullableStr = opts.inlinePrimaryKey ? '' : column.nullable === false ? 'not null' : ''
|
|
40
|
+
|
|
41
|
+
// Only include AUTOINCREMENT when it's valid: single-column INTEGER PRIMARY KEY
|
|
42
|
+
const includeAutoIncrement = opts.inlinePrimaryKey && column.type._tag === 'integer' && column.autoIncrement === true
|
|
43
|
+
|
|
44
|
+
const pkStr = opts.inlinePrimaryKey ? 'primary key' : ''
|
|
45
|
+
const autoIncrementStr = includeAutoIncrement ? 'autoincrement' : ''
|
|
46
|
+
|
|
28
47
|
const defaultValueStr = (() => {
|
|
29
48
|
if (column.default._tag === 'None') return ''
|
|
30
49
|
|
|
31
|
-
|
|
32
|
-
if (SqliteDsl.
|
|
50
|
+
const defaultValue = column.default.value
|
|
51
|
+
if (SqliteDsl.isDefaultThunk(defaultValue)) return ''
|
|
52
|
+
|
|
53
|
+
const resolvedDefault = SqliteDsl.resolveColumnDefault(defaultValue)
|
|
54
|
+
|
|
55
|
+
if (resolvedDefault === null) return 'default null'
|
|
56
|
+
if (SqliteDsl.isSqlDefaultValue(resolvedDefault)) return `default ${resolvedDefault.sql}`
|
|
33
57
|
|
|
34
58
|
const encodeValue = Schema.encodeSync(column.schema)
|
|
35
|
-
const encodedDefaultValue = encodeValue(
|
|
59
|
+
const encodedDefaultValue = encodeValue(resolvedDefault)
|
|
36
60
|
|
|
37
61
|
if (columnTypeStr === 'text') return `default '${encodedDefaultValue}'`
|
|
38
62
|
return `default ${encodedDefaultValue}`
|
|
39
63
|
})()
|
|
40
64
|
|
|
41
|
-
|
|
65
|
+
// Ensure order: PRIMARY KEY [AUTOINCREMENT] [NOT NULL] ...
|
|
66
|
+
return `"${column.name}" ${columnTypeStr} ${pkStr} ${autoIncrementStr} ${nullableStr} ${defaultValueStr}`
|
|
42
67
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { omitUndefineds } from '@livestore/utils'
|
|
2
|
+
import { type Option, Schema, SchemaAST } from '@livestore/utils/effect'
|
|
2
3
|
|
|
3
4
|
import { hashCode } from '../hash.ts'
|
|
4
5
|
|
|
@@ -45,9 +46,7 @@ export const index = (
|
|
|
45
46
|
): Index => ({
|
|
46
47
|
_tag: 'index',
|
|
47
48
|
columns,
|
|
48
|
-
name,
|
|
49
|
-
unique,
|
|
50
|
-
primaryKey,
|
|
49
|
+
...omitUndefineds({ name, unique, primaryKey }),
|
|
51
50
|
})
|
|
52
51
|
|
|
53
52
|
export type ForeignKey = {
|
|
@@ -85,7 +84,19 @@ export type DbSchema = {
|
|
|
85
84
|
export const dbSchema = (tables: Table[]): DbSchema => ({ _tag: 'dbSchema', tables })
|
|
86
85
|
|
|
87
86
|
/**
|
|
88
|
-
*
|
|
87
|
+
* Helper to detect if a column is a JSON column (has parseJson transformation)
|
|
88
|
+
*/
|
|
89
|
+
const isJsonColumn = (column: Column): boolean => {
|
|
90
|
+
if (column.type._tag !== 'text') return false
|
|
91
|
+
|
|
92
|
+
// Check if the schema AST is a parseJson transformation
|
|
93
|
+
const ast = column.schema.ast
|
|
94
|
+
return ast._tag === 'Transformation' && ast.annotations.schemaId === SchemaAST.ParseJsonSchemaId
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* NOTE we're now including JSON schema information for JSON columns
|
|
99
|
+
* to detect client document schema changes
|
|
89
100
|
*/
|
|
90
101
|
export const hash = (obj: Table | Column | Index | ForeignKey | DbSchema): number =>
|
|
91
102
|
hashCode(JSON.stringify(trimInfoForHasing(obj)))
|
|
@@ -101,7 +112,7 @@ const trimInfoForHasing = (obj: Table | Column | Index | ForeignKey | DbSchema):
|
|
|
101
112
|
}
|
|
102
113
|
}
|
|
103
114
|
case 'column': {
|
|
104
|
-
|
|
115
|
+
const baseInfo: Record<string, any> = {
|
|
105
116
|
_tag: 'column',
|
|
106
117
|
name: obj.name,
|
|
107
118
|
type: obj.type._tag,
|
|
@@ -110,6 +121,15 @@ const trimInfoForHasing = (obj: Table | Column | Index | ForeignKey | DbSchema):
|
|
|
110
121
|
autoIncrement: obj.autoIncrement,
|
|
111
122
|
default: obj.default,
|
|
112
123
|
}
|
|
124
|
+
|
|
125
|
+
// NEW: Include schema hash for JSON columns
|
|
126
|
+
// This ensures that changes to the JSON schema are detected
|
|
127
|
+
if (isJsonColumn(obj) && obj.schema) {
|
|
128
|
+
// Use Effect's Schema.hash for consistent hashing
|
|
129
|
+
baseInfo.jsonSchemaHash = Schema.hash(obj.schema)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return baseInfo
|
|
113
133
|
}
|
|
114
134
|
case 'index': {
|
|
115
135
|
return {
|
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
import { casesHandled } from '@livestore/utils'
|
|
2
2
|
import { Option, Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
|
+
export type SqlDefaultValue = {
|
|
5
|
+
readonly sql: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
|
|
9
|
+
return typeof value === 'object' && value !== null && 'sql' in value && typeof (value as any).sql === 'string'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type ColumnDefaultThunk<T> = () => T
|
|
13
|
+
|
|
14
|
+
export const isDefaultThunk = (value: unknown): value is ColumnDefaultThunk<unknown> => typeof value === 'function'
|
|
15
|
+
|
|
16
|
+
export type ColumnDefaultValue<T> = T | null | ColumnDefaultThunk<T | null> | SqlDefaultValue
|
|
17
|
+
|
|
18
|
+
export const resolveColumnDefault = <T>(value: ColumnDefaultValue<T>): T | null | SqlDefaultValue =>
|
|
19
|
+
isDefaultThunk(value) ? (value as ColumnDefaultThunk<T | null>)() : value
|
|
20
|
+
|
|
4
21
|
export type ColumnDefinition<TEncoded, TDecoded> = {
|
|
5
22
|
readonly columnType: FieldColumnType
|
|
6
23
|
readonly schema: Schema.Schema<TDecoded, TEncoded>
|
|
7
|
-
readonly default: Option.Option<
|
|
24
|
+
readonly default: Option.Option<ColumnDefaultValue<TDecoded>>
|
|
8
25
|
/** @default false */
|
|
9
26
|
readonly nullable: boolean
|
|
10
27
|
/** @default false */
|
|
@@ -27,9 +44,17 @@ export const isColumnDefinition = (value: unknown): value is ColumnDefinition.An
|
|
|
27
44
|
)
|
|
28
45
|
}
|
|
29
46
|
|
|
47
|
+
type MaybeNull<T, TNullable extends boolean> = T | (TNullable extends true ? null : never)
|
|
48
|
+
|
|
49
|
+
type ColumnDefaultArg<T, TNullable extends boolean> =
|
|
50
|
+
| MaybeNull<T, TNullable>
|
|
51
|
+
| ColumnDefaultThunk<MaybeNull<T, TNullable>>
|
|
52
|
+
| SqlDefaultValue
|
|
53
|
+
| NoDefault
|
|
54
|
+
|
|
30
55
|
export type ColumnDefinitionInput = {
|
|
31
56
|
readonly schema?: Schema.Schema<unknown>
|
|
32
|
-
readonly default?: unknown
|
|
57
|
+
readonly default?: ColumnDefaultArg<unknown, boolean>
|
|
33
58
|
readonly nullable?: boolean
|
|
34
59
|
readonly primaryKey?: boolean
|
|
35
60
|
readonly autoIncrement?: boolean
|
|
@@ -38,14 +63,6 @@ export type ColumnDefinitionInput = {
|
|
|
38
63
|
export const NoDefault = Symbol.for('NoDefault')
|
|
39
64
|
export type NoDefault = typeof NoDefault
|
|
40
65
|
|
|
41
|
-
export type SqlDefaultValue = {
|
|
42
|
-
readonly sql: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
|
|
46
|
-
return typeof value === 'object' && value !== null && 'sql' in value && typeof value.sql === 'string'
|
|
47
|
-
}
|
|
48
|
-
|
|
49
66
|
export type ColDefFn<TColumnType extends FieldColumnType> = {
|
|
50
67
|
(): {
|
|
51
68
|
columnType: TColumnType
|
|
@@ -59,7 +76,7 @@ export type ColDefFn<TColumnType extends FieldColumnType> = {
|
|
|
59
76
|
TEncoded extends DefaultEncodedForColumnType<TColumnType>,
|
|
60
77
|
TDecoded = DefaultEncodedForColumnType<TColumnType>,
|
|
61
78
|
const TNullable extends boolean = false,
|
|
62
|
-
const TDefault extends TDecoded
|
|
79
|
+
const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
|
|
63
80
|
const TPrimaryKey extends boolean = false,
|
|
64
81
|
const TAutoIncrement extends boolean = false,
|
|
65
82
|
>(args: {
|
|
@@ -132,7 +149,7 @@ export type SpecializedColDefFn<
|
|
|
132
149
|
<
|
|
133
150
|
TDecoded = TBaseDecoded,
|
|
134
151
|
const TNullable extends boolean = false,
|
|
135
|
-
const TDefault extends TDecoded
|
|
152
|
+
const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
|
|
136
153
|
const TPrimaryKey extends boolean = false,
|
|
137
154
|
const TAutoIncrement extends boolean = false,
|
|
138
155
|
>(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Nullable } from '@livestore/utils'
|
|
2
|
+
import { omitUndefineds } from '@livestore/utils'
|
|
2
3
|
import type { Option, Types } from '@livestore/utils/effect'
|
|
3
4
|
import { Schema } from '@livestore/utils/effect'
|
|
4
5
|
|
|
@@ -19,13 +20,12 @@ export type DbSchemaInput = Record<string, TableDefinition<any, any>> | Readonly
|
|
|
19
20
|
* - array: we use the table name of each array item (= table definition) as the object key
|
|
20
21
|
* - object: we discard the keys of the input object and use the table name of each object value (= table definition) as the new object key
|
|
21
22
|
*/
|
|
22
|
-
export type DbSchemaFromInputSchema<TSchemaInput extends DbSchemaInput> =
|
|
23
|
-
TableDefinition<any, any
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
: never
|
|
23
|
+
export type DbSchemaFromInputSchema<TSchemaInput extends DbSchemaInput> =
|
|
24
|
+
TSchemaInput extends ReadonlyArray<TableDefinition<any, any>>
|
|
25
|
+
? { [K in TSchemaInput[number] as K['name']]: K }
|
|
26
|
+
: TSchemaInput extends Record<string, TableDefinition<any, any>>
|
|
27
|
+
? { [K in keyof TSchemaInput as TSchemaInput[K]['name']]: TSchemaInput[K] }
|
|
28
|
+
: never
|
|
29
29
|
|
|
30
30
|
// TODO ensure via runtime check (possibly even via type-level check) that all index names are unique
|
|
31
31
|
export const makeDbSchema = <TDbSchemaInput extends DbSchemaInput>(
|
|
@@ -46,7 +46,7 @@ export const table = <TTableName extends string, TColumns extends Columns, TInde
|
|
|
46
46
|
indexes: indexesToAst(indexes ?? []),
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
return { name, columns, indexes, ast }
|
|
49
|
+
return { name, columns, ...omitUndefineds({ indexes }), ast }
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export type AnyIfConstained<In, Out> = '__constrained' extends keyof In ? any : Out
|
|
@@ -115,12 +115,8 @@ export type TableDefinition<TName extends string, TColumns extends Columns> = {
|
|
|
115
115
|
|
|
116
116
|
export type Columns = Record<string, ColumnDefinition<any, any>>
|
|
117
117
|
|
|
118
|
-
export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> =
|
|
119
|
-
any,
|
|
120
|
-
any
|
|
121
|
-
>
|
|
122
|
-
? true
|
|
123
|
-
: false
|
|
118
|
+
export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> =
|
|
119
|
+
TColumns extends ColumnDefinition<any, any> ? true : false
|
|
124
120
|
|
|
125
121
|
/**
|
|
126
122
|
* NOTE this is only needed to avoid a TS limitation where `StructSchemaForColumns` in the default case
|
|
@@ -213,9 +209,8 @@ export namespace FromColumns {
|
|
|
213
209
|
|
|
214
210
|
export type RequiredInsertColumnNames<TColumns extends Columns> = keyof RequiredInsertColumns<TColumns>
|
|
215
211
|
|
|
216
|
-
export type RequiresInsertValues<TColumns extends Columns> =
|
|
217
|
-
? false
|
|
218
|
-
: true
|
|
212
|
+
export type RequiresInsertValues<TColumns extends Columns> =
|
|
213
|
+
RequiredInsertColumnNames<TColumns> extends never ? false : true
|
|
219
214
|
|
|
220
215
|
export type InsertRowDecoded<TColumns extends Columns> = Types.Simplify<
|
|
221
216
|
Pick<RowDecodedAll<TColumns>, RequiredInsertColumnNames<TColumns>> &
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
2
2
|
|
|
3
3
|
import type { MigrationOptions } from '../../../adapter-types.ts'
|
|
4
|
-
import type { Materializer } from '../../EventDef.ts'
|
|
4
|
+
import type { Materializer } from '../../EventDef/mod.ts'
|
|
5
5
|
import type { InternalState } from '../../schema.ts'
|
|
6
6
|
import { ClientDocumentTableDefSymbol, tableIsClientDocumentTable } from './client-document-def.ts'
|
|
7
7
|
import { SqliteAst } from './db-schema/mod.ts'
|
|
8
|
-
import { stateSystemTables } from './system-tables.ts'
|
|
8
|
+
import { stateSystemTables } from './system-tables/state-tables.ts'
|
|
9
9
|
import type { TableDef, TableDefBase } from './table-def.ts'
|
|
10
10
|
|
|
11
|
-
export * from '../../EventDef.ts'
|
|
11
|
+
export * from '../../EventDef/mod.ts'
|
|
12
12
|
export {
|
|
13
13
|
type ClientDocumentTableDef,
|
|
14
14
|
ClientDocumentTableDefSymbol,
|
|
15
15
|
type ClientDocumentTableOptions,
|
|
16
16
|
clientDocument,
|
|
17
|
+
createOptimisticEventSchema,
|
|
17
18
|
tableIsClientDocumentTable,
|
|
18
19
|
} from './client-document-def.ts'
|
|
19
20
|
export * from './column-annotations.ts'
|
|
@@ -3,7 +3,7 @@ import { type Option, Predicate, type Schema } from '@livestore/utils/effect'
|
|
|
3
3
|
|
|
4
4
|
import type { SessionIdSymbol } from '../../../../adapter-types.ts'
|
|
5
5
|
import type { SqlValue } from '../../../../util.ts'
|
|
6
|
-
import type { ClientDocumentTableDef } from '../client-document-def.ts'
|
|
6
|
+
import type { ClientDocumentTableDef, ClientDocumentTableDefSymbol } from '../client-document-def.ts'
|
|
7
7
|
import type { SqliteDsl } from '../db-schema/mod.ts'
|
|
8
8
|
import type { TableDefBase } from '../table-def.ts'
|
|
9
9
|
|
|
@@ -242,7 +242,12 @@ export namespace QueryBuilder {
|
|
|
242
242
|
): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
|
|
243
243
|
<TColName extends keyof TTableDef['sqliteDef']['columns']>(
|
|
244
244
|
col: TColName,
|
|
245
|
-
op: QueryBuilder.WhereOps,
|
|
245
|
+
op: QueryBuilder.WhereOps.MultiValue,
|
|
246
|
+
value: ReadonlyArray<TTableDef['sqliteDef']['columns'][TColName]['schema']['Type']>,
|
|
247
|
+
): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
|
|
248
|
+
<TColName extends keyof TTableDef['sqliteDef']['columns']>(
|
|
249
|
+
col: TColName,
|
|
250
|
+
op: QueryBuilder.WhereOps.SingleValue,
|
|
246
251
|
value: TTableDef['sqliteDef']['columns'][TColName]['schema']['Type'],
|
|
247
252
|
): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
|
|
248
253
|
}
|
|
@@ -347,22 +352,26 @@ export namespace QueryBuilder {
|
|
|
347
352
|
>
|
|
348
353
|
|
|
349
354
|
/**
|
|
350
|
-
*
|
|
355
|
+
* Upsert: insert a row, or handle conflicts on existing rows.
|
|
356
|
+
* Equivalent to SQLite's `INSERT ... ON CONFLICT` clause.
|
|
357
|
+
*
|
|
358
|
+
* Actions:
|
|
359
|
+
* - `'ignore'`: Skip the insert if a row with the same key exists
|
|
360
|
+
* - `'replace'`: Delete the existing row and insert the new one
|
|
361
|
+
* - `'update'`: Update specific columns on the existing row
|
|
362
|
+
*
|
|
351
363
|
* ```ts
|
|
364
|
+
* // Ignore: skip if row exists
|
|
352
365
|
* db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'ignore')
|
|
353
|
-
* ```
|
|
354
366
|
*
|
|
355
|
-
*
|
|
356
|
-
* ```ts
|
|
367
|
+
* // Replace: delete existing row and insert new one
|
|
357
368
|
* db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'replace')
|
|
358
|
-
* ```
|
|
359
369
|
*
|
|
360
|
-
*
|
|
361
|
-
* ```ts
|
|
370
|
+
* // Update: merge specific columns into existing row
|
|
362
371
|
* db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'update', { text: 'Buy soy milk' })
|
|
363
372
|
* ```
|
|
364
373
|
*
|
|
365
|
-
* NOTE
|
|
374
|
+
* NOTE: Composite primary keys are not yet supported.
|
|
366
375
|
*/
|
|
367
376
|
readonly onConflict: {
|
|
368
377
|
<TTarget extends SingleOrReadonlyArray<keyof TTableDef['sqliteDef']['columns']>>(
|
|
@@ -437,7 +446,12 @@ export namespace QueryBuilder {
|
|
|
437
446
|
|
|
438
447
|
export namespace RowQuery {
|
|
439
448
|
export type GetOrCreateOptions<TTableDef extends ClientDocumentTableDef.TraitAny> = {
|
|
440
|
-
|
|
449
|
+
/**
|
|
450
|
+
* Default value to use instead of the default value from the table definition
|
|
451
|
+
*/
|
|
452
|
+
default: TTableDef[ClientDocumentTableDefSymbol]['options']['partialSet'] extends false
|
|
453
|
+
? TTableDef['Value']
|
|
454
|
+
: Partial<TTableDef['Value']>
|
|
441
455
|
}
|
|
442
456
|
|
|
443
457
|
// TODO get rid of this
|
|
@@ -7,6 +7,8 @@ import type { State } from '../../../mod.ts'
|
|
|
7
7
|
import type { QueryBuilderAst } from './api.ts'
|
|
8
8
|
|
|
9
9
|
// Helper functions for SQL generation
|
|
10
|
+
const quoteIdentifier = (identifier: string): string => `"${identifier.replace(/"/g, '""')}"`
|
|
11
|
+
|
|
10
12
|
const formatWhereClause = (
|
|
11
13
|
whereConditions: ReadonlyArray<QueryBuilderAst.Where>,
|
|
12
14
|
tableDef: State.SQLite.TableDefBase,
|
|
@@ -16,13 +18,15 @@ const formatWhereClause = (
|
|
|
16
18
|
|
|
17
19
|
const whereClause = whereConditions
|
|
18
20
|
.map(({ col, op, value }) => {
|
|
21
|
+
const quotedCol = quoteIdentifier(col)
|
|
22
|
+
|
|
19
23
|
// Handle NULL values
|
|
20
24
|
if (value === null) {
|
|
21
25
|
if (op !== '=' && op !== '!=') {
|
|
22
26
|
throw new Error(`Unsupported operator for NULL value: ${op}`)
|
|
23
27
|
}
|
|
24
28
|
const opStmt = op === '=' ? 'IS' : 'IS NOT'
|
|
25
|
-
return `${
|
|
29
|
+
return `${quotedCol} ${opStmt} NULL`
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
// Get column definition and encode value
|
|
@@ -48,11 +52,11 @@ const formatWhereClause = (
|
|
|
48
52
|
const encodedValues = value.map((v) => Schema.encodeSync(colDef.schema)(v)) as SqlValue[]
|
|
49
53
|
bindValues.push(...encodedValues)
|
|
50
54
|
const placeholders = encodedValues.map(() => '?').join(', ')
|
|
51
|
-
return `${
|
|
55
|
+
return `${quotedCol} ${op} (${placeholders})`
|
|
52
56
|
} else {
|
|
53
57
|
const encodedValue = Schema.encodeSync(colDef.schema)(value)
|
|
54
58
|
bindValues.push(encodedValue as SqlValue)
|
|
55
|
-
return `${
|
|
59
|
+
return `${quotedCol} ${op} ?`
|
|
56
60
|
}
|
|
57
61
|
})
|
|
58
62
|
.join(' AND ')
|
|
@@ -62,7 +66,7 @@ const formatWhereClause = (
|
|
|
62
66
|
|
|
63
67
|
const formatReturningClause = (returning?: string[]): string => {
|
|
64
68
|
if (!returning || returning.length === 0) return ''
|
|
65
|
-
return ` RETURNING ${returning.join(', ')}`
|
|
69
|
+
return ` RETURNING ${returning.map(quoteIdentifier).join(', ')}`
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: SqlValue[]; usedTables: Set<string> } => {
|
|
@@ -72,6 +76,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
72
76
|
// INSERT query
|
|
73
77
|
if (ast._tag === 'InsertQuery') {
|
|
74
78
|
const columns = Object.keys(ast.values)
|
|
79
|
+
const quotedColumns = columns.map(quoteIdentifier)
|
|
75
80
|
const placeholders = columns.map(() => '?').join(', ')
|
|
76
81
|
const encodedValues = Schema.encodeSync(ast.tableDef.insertSchema)(ast.values)
|
|
77
82
|
|
|
@@ -91,7 +96,8 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
91
96
|
// For REPLACE, the conflict target is implied and no further clause is needed
|
|
92
97
|
} else {
|
|
93
98
|
// Build the ON CONFLICT clause for IGNORE or UPDATE
|
|
94
|
-
|
|
99
|
+
const conflictTargets = ast.onConflict.targets.map(quoteIdentifier).join(', ')
|
|
100
|
+
conflictClause = ` ON CONFLICT (${conflictTargets}) `
|
|
95
101
|
if (ast.onConflict.action._tag === 'ignore') {
|
|
96
102
|
conflictClause += 'DO NOTHING'
|
|
97
103
|
} else {
|
|
@@ -105,8 +111,9 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
105
111
|
const updates = updateCols
|
|
106
112
|
.map((col) => {
|
|
107
113
|
const value = updateValues[col]
|
|
114
|
+
const quotedCol = quoteIdentifier(col)
|
|
108
115
|
// If the value is undefined, use excluded.col
|
|
109
|
-
return value === undefined ? `${
|
|
116
|
+
return value === undefined ? `${quotedCol} = excluded.${quotedCol}` : `${quotedCol} = ?`
|
|
110
117
|
})
|
|
111
118
|
.join(', ')
|
|
112
119
|
|
|
@@ -129,7 +136,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
// Construct the main query part
|
|
132
|
-
let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${
|
|
139
|
+
let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${quotedColumns.join(', ')}) VALUES (${placeholders})`
|
|
133
140
|
|
|
134
141
|
// Append the conflict clause if it was generated (i.e., not for REPLACE)
|
|
135
142
|
query += conflictClause
|
|
@@ -157,7 +164,9 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
157
164
|
bindValues.push(encodedValues[col] as SqlValue)
|
|
158
165
|
})
|
|
159
166
|
|
|
160
|
-
let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns
|
|
167
|
+
let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns
|
|
168
|
+
.map((col) => `${quoteIdentifier(col)} = ?`)
|
|
169
|
+
.join(', ')}`
|
|
161
170
|
|
|
162
171
|
const whereClause = formatWhereClause(ast.where, ast.tableDef, bindValues)
|
|
163
172
|
if (whereClause) query += ` ${whereClause}`
|
|
@@ -201,31 +210,31 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
201
210
|
const encodedId = ast.id === SessionIdSymbol ? ast.id : Schema.encodeSync(idColDef.schema)(ast.id)
|
|
202
211
|
|
|
203
212
|
return {
|
|
204
|
-
query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE id = ?`,
|
|
213
|
+
query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE ${quoteIdentifier('id')} = ?`,
|
|
205
214
|
bindValues: [encodedId as SqlValue],
|
|
206
215
|
usedTables,
|
|
207
216
|
}
|
|
208
217
|
}
|
|
209
218
|
|
|
210
219
|
// SELECT query
|
|
211
|
-
const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.join(', ')
|
|
220
|
+
const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.map(quoteIdentifier).join(', ')
|
|
212
221
|
const selectStmt = `SELECT ${columnsStmt}`
|
|
213
222
|
const fromStmt = `FROM '${ast.tableDef.sqliteDef.name}'`
|
|
214
223
|
const whereStmt = formatWhereClause(ast.where, ast.tableDef, bindValues)
|
|
215
224
|
|
|
216
225
|
const orderByStmt =
|
|
217
226
|
ast.orderBy.length > 0
|
|
218
|
-
? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${col} ${direction}`).join(', ')}`
|
|
227
|
+
? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${quoteIdentifier(col)} ${direction}`).join(', ')}`
|
|
219
228
|
: ''
|
|
220
229
|
|
|
221
230
|
const limitStmt = ast.limit._tag === 'Some' ? `LIMIT ?` : ''
|
|
222
231
|
const offsetStmt = ast.offset._tag === 'Some' ? `OFFSET ?` : ''
|
|
223
232
|
|
|
224
|
-
// Push
|
|
225
|
-
if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
|
|
233
|
+
// Push limit and offset values in the correct order matching the query string
|
|
226
234
|
if (ast.limit._tag === 'Some') bindValues.push(ast.limit.value)
|
|
235
|
+
if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
|
|
227
236
|
|
|
228
|
-
const query = [selectStmt, fromStmt, whereStmt, orderByStmt,
|
|
237
|
+
const query = [selectStmt, fromStmt, whereStmt, orderByStmt, limitStmt, offsetStmt]
|
|
229
238
|
.map((clause) => clause.trim())
|
|
230
239
|
.filter((clause) => clause.length > 0)
|
|
231
240
|
.join(' ')
|