@livestore/common 0.4.0-dev.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/ClientSessionLeaderThreadProxy.d.ts +27 -12
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
- package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
- package/dist/WorkerTransportError.d.ts +11 -0
- package/dist/WorkerTransportError.d.ts.map +1 -0
- package/dist/WorkerTransportError.js +11 -0
- package/dist/WorkerTransportError.js.map +1 -0
- package/dist/adapter-types.d.ts +37 -7
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +27 -1
- package/dist/adapter-types.js.map +1 -1
- package/dist/bounded-collections.d.ts.map +1 -1
- package/dist/bounded-collections.js +6 -4
- package/dist/bounded-collections.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-compatibility.test.d.ts +2 -0
- package/dist/devtools/devtools-compatibility.test.d.ts.map +1 -0
- package/dist/devtools/devtools-compatibility.test.js +15 -0
- package/dist/devtools/devtools-compatibility.test.js.map +1 -0
- package/dist/devtools/devtools-messages-client-session.d.ts +55 -24
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +22 -5
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +11 -14
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +7 -9
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +65 -30
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +29 -11
- 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 +48 -18
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +20 -12
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +53 -6
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +325 -257
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/RejectedPushError.d.ts +107 -0
- package/dist/leader-thread/RejectedPushError.d.ts.map +1 -0
- package/dist/leader-thread/RejectedPushError.js +78 -0
- package/dist/leader-thread/RejectedPushError.js.map +1 -0
- package/dist/leader-thread/connection.js +1 -1
- package/dist/leader-thread/connection.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +19 -14
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +78 -18
- package/dist/leader-thread/eventlog.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts +1 -2
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +90 -58
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +15 -7
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +49 -17
- 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 +1 -1
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +28 -9
- 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 -2
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +6 -6
- 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 +167 -0
- package/dist/leader-thread/stream-events.js.map +1 -0
- package/dist/leader-thread/types.d.ts +95 -17
- 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 +7 -4
- 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 +18 -8
- 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 +7 -2
- package/dist/otel.js.map +1 -1
- package/dist/rematerialize-from-eventlog.d.ts +3 -3
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +40 -29
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef/define.d.ts +161 -0
- package/dist/schema/EventDef/define.d.ts.map +1 -0
- package/dist/schema/EventDef/define.js +140 -0
- package/dist/schema/EventDef/define.js.map +1 -0
- package/dist/schema/EventDef/deprecated.d.ts +99 -0
- package/dist/schema/EventDef/deprecated.d.ts.map +1 -0
- package/dist/schema/EventDef/deprecated.js +144 -0
- package/dist/schema/EventDef/deprecated.js.map +1 -0
- package/dist/schema/EventDef/deprecated.test.d.ts +2 -0
- package/dist/schema/EventDef/deprecated.test.d.ts.map +1 -0
- package/dist/schema/EventDef/deprecated.test.js +95 -0
- package/dist/schema/EventDef/deprecated.test.js.map +1 -0
- package/dist/schema/EventDef/event-def.d.ts +110 -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 +6 -0
- package/dist/schema/EventDef/mod.d.ts.map +1 -0
- package/dist/schema/EventDef/mod.js +6 -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 +44 -44
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +102 -111
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/client.js +176 -0
- package/dist/schema/LiveStoreEvent/client.js.map +1 -0
- package/dist/schema/LiveStoreEvent/client.test.d.ts +2 -0
- package/dist/schema/LiveStoreEvent/client.test.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/client.test.js +111 -0
- package/dist/schema/LiveStoreEvent/client.test.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 +32 -4
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +2 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +36 -15
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +121 -2
- 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 +1 -1
- package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js +2 -2
- package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-def.js +96 -47
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +51 -12
- 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 +24 -15
- package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +2 -2
- 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 +16 -10
- 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 +15 -4
- 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 +1 -1
- 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 +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 +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts +2 -2
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +5 -7
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/api.d.ts +51 -22
- 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 +99 -22
- 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 +28 -15
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +231 -93
- 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 +24 -14
- 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} +21 -450
- 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 +5 -3
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/table-def.js +1 -1
- package/dist/schema/state/sqlite/table-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +92 -3
- 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/common.js +2 -2
- package/dist/schema-management/common.js.map +1 -1
- 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 +38 -6
- 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 +18 -6
- 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.map +1 -1
- package/dist/sqlite-db-helper.js +3 -3
- package/dist/sqlite-db-helper.js.map +1 -1
- package/dist/sqlite-types.d.ts +5 -5
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/sqlite-types.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +12 -12
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +99 -114
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/errors.d.ts +0 -33
- package/dist/sync/errors.d.ts.map +1 -1
- package/dist/sync/errors.js +5 -22
- package/dist/sync/errors.js.map +1 -1
- package/dist/sync/index.d.ts +2 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +2 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/mock-sync-backend.d.ts +10 -8
- package/dist/sync/mock-sync-backend.d.ts.map +1 -1
- package/dist/sync/mock-sync-backend.js +71 -69
- package/dist/sync/mock-sync-backend.js.map +1 -1
- package/dist/sync/next/compact-events.d.ts.map +1 -1
- package/dist/sync/next/compact-events.js +11 -12
- 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 +7 -8
- 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 +11 -11
- 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 +6 -6
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
- package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
- package/dist/sync/next/test/compact-events.test.d.ts.map +1 -1
- package/dist/sync/next/test/compact-events.test.js +2 -2
- package/dist/sync/next/test/compact-events.test.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 +11 -11
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/sync-backend-kv.d.ts +3 -3
- package/dist/sync/sync-backend-kv.d.ts.map +1 -1
- package/dist/sync/sync-backend-kv.js +3 -3
- package/dist/sync/sync-backend-kv.js.map +1 -1
- package/dist/sync/sync-backend.d.ts +33 -13
- package/dist/sync/sync-backend.d.ts.map +1 -1
- package/dist/sync/sync-backend.js +38 -1
- package/dist/sync/sync-backend.js.map +1 -1
- package/dist/sync/sync.d.ts +23 -2
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/syncstate.d.ts +55 -55
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +80 -98
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +221 -132
- 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 +4 -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/util.js +2 -2
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +24 -5
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +25 -8
- package/dist/version.js.map +1 -1
- package/package.json +69 -16
- package/src/ClientSessionLeaderThreadProxy.ts +27 -12
- package/src/WorkerTransportError.ts +12 -0
- package/src/adapter-types.ts +50 -7
- package/src/bounded-collections.ts +6 -5
- package/src/debug-info.ts +37 -6
- package/src/devtools/devtools-compatibility.test.ts +18 -0
- package/src/devtools/devtools-messages-client-session.ts +22 -4
- package/src/devtools/devtools-messages-common.ts +7 -12
- package/src/devtools/devtools-messages-leader.ts +29 -10
- package/src/devtools/devtools-sessioninfo.ts +8 -5
- package/src/devtools/mod.ts +11 -2
- package/src/errors.ts +32 -24
- package/src/index.ts +4 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +523 -373
- package/src/leader-thread/RejectedPushError.ts +106 -0
- package/src/leader-thread/connection.ts +1 -1
- package/src/leader-thread/eventlog.ts +112 -39
- package/src/leader-thread/leader-worker-devtools.ts +201 -120
- package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
- package/src/leader-thread/make-leader-thread-layer.ts +125 -40
- package/src/leader-thread/materialize-event.ts +40 -10
- package/src/leader-thread/mod.ts +1 -0
- package/src/leader-thread/recreate-db.ts +7 -7
- package/src/leader-thread/shutdown-channel.ts +4 -8
- package/src/leader-thread/stream-events.ts +206 -0
- package/src/leader-thread/types.ts +68 -18
- package/src/logging.ts +62 -0
- package/src/make-client-session.ts +11 -5
- package/src/materializer-helper.ts +27 -16
- package/src/otel.ts +13 -2
- package/src/rematerialize-from-eventlog.ts +61 -51
- package/src/schema/EventDef/define.ts +217 -0
- package/src/schema/EventDef/deprecated.test.ts +129 -0
- package/src/schema/EventDef/deprecated.ts +175 -0
- package/src/schema/EventDef/event-def.ts +125 -0
- package/src/schema/EventDef/facts.ts +135 -0
- package/src/schema/EventDef/materializer.ts +172 -0
- package/src/schema/EventDef/mod.ts +5 -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 +72 -53
- package/src/schema/LiveStoreEvent/client.test.ts +129 -0
- package/src/schema/LiveStoreEvent/client.ts +235 -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 +46 -5
- package/src/schema/state/sqlite/client-document-def.test.ts +144 -5
- package/src/schema/state/sqlite/client-document-def.ts +47 -34
- package/src/schema/state/sqlite/column-annotations.test.ts +3 -2
- package/src/schema/state/sqlite/column-annotations.ts +2 -1
- package/src/schema/state/sqlite/column-def.test.ts +66 -12
- package/src/schema/state/sqlite/column-def.ts +119 -47
- package/src/schema/state/sqlite/column-spec.test.ts +32 -17
- package/src/schema/state/sqlite/column-spec.ts +37 -11
- package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -2
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +2 -1
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +41 -15
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +13 -19
- package/src/schema/state/sqlite/mod.ts +7 -8
- package/src/schema/state/sqlite/query-builder/api.ts +55 -17
- package/src/schema/state/sqlite/query-builder/astToSql.ts +110 -21
- package/src/schema/state/sqlite/query-builder/impl.test.ts +267 -93
- package/src/schema/state/sqlite/query-builder/impl.ts +26 -13
- package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
- package/src/schema/state/sqlite/schema-helpers.ts +30 -22
- 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 +114 -3
- package/src/schema/state/sqlite/table-def.ts +16 -22
- package/src/schema/unknown-events.ts +131 -0
- package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +88 -0
- package/src/schema-management/common.ts +2 -2
- package/src/schema-management/migrations.ts +42 -9
- package/src/schema-management/validate-schema.ts +3 -3
- package/src/sql-queries/sql-queries.ts +18 -6
- package/src/sql-queries/sql-query-builder.ts +1 -0
- package/src/sqlite-db-helper.ts +3 -3
- package/src/sqlite-types.ts +6 -5
- package/src/sync/ClientSessionSyncProcessor.ts +152 -142
- package/src/sync/errors.ts +12 -24
- package/src/sync/index.ts +2 -0
- package/src/sync/mock-sync-backend.ts +146 -104
- package/src/sync/next/compact-events.ts +10 -11
- package/src/sync/next/facts.ts +13 -14
- package/src/sync/next/history-dag-common.ts +280 -26
- package/src/sync/next/history-dag.ts +17 -13
- package/src/sync/next/rebase-events.ts +12 -12
- package/src/sync/next/test/compact-events.calculator.test.ts +3 -2
- package/src/sync/next/test/compact-events.test.ts +4 -3
- package/src/sync/next/test/event-fixtures.ts +13 -13
- package/src/sync/sync-backend-kv.ts +4 -3
- package/src/sync/sync-backend.ts +66 -17
- package/src/sync/sync.ts +24 -2
- package/src/sync/syncstate.test.ts +583 -419
- package/src/sync/syncstate.ts +127 -122
- package/src/sync/transport-chunking.ts +90 -0
- package/src/sync/validate-push-payload.ts +6 -8
- package/src/testing/event-factory.ts +131 -0
- package/src/testing/mod.ts +1 -0
- package/src/util.ts +2 -2
- package/src/version.ts +33 -8
- package/dist/schema/EventDef.d.ts +0 -126
- 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 +0 -147
- 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 -81
- package/dist/schema/state/sqlite/system-tables.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 -222
- package/src/schema/EventSequenceNumber.ts +0 -199
- package/src/schema/LiveStoreEvent.ts +0 -286
- package/src/schema/state/sqlite/system-tables.ts +0 -106
- 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
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import { casesHandled } from '@livestore/utils'
|
|
2
2
|
import { Option, Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type SqlDefaultValue = {
|
|
5
|
+
readonly sql: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
|
|
9
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- type guard property access after structural check
|
|
10
|
+
return typeof value === 'object' && value !== null && 'sql' in value && typeof (value as any).sql === 'string'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type ColumnDefaultThunk<T> = () => T
|
|
14
|
+
|
|
15
|
+
export const isDefaultThunk = (value: unknown): value is ColumnDefaultThunk<unknown> => typeof value === 'function'
|
|
16
|
+
|
|
17
|
+
export type ColumnDefaultValue<T> = T | null | ColumnDefaultThunk<T | null> | SqlDefaultValue
|
|
18
|
+
|
|
19
|
+
export const resolveColumnDefault = <T>(value: ColumnDefaultValue<T>): T | null | SqlDefaultValue =>
|
|
20
|
+
isDefaultThunk(value) === true ? value() : value
|
|
21
|
+
|
|
22
|
+
export type ColumnDefinition<TEncoded, TDecoded, TNullable extends boolean = boolean> = {
|
|
5
23
|
readonly columnType: FieldColumnType
|
|
6
24
|
readonly schema: Schema.Schema<TDecoded, TEncoded>
|
|
7
|
-
readonly default: Option.Option<
|
|
25
|
+
readonly default: Option.Option<ColumnDefaultValue<TDecoded>>
|
|
8
26
|
/** @default false */
|
|
9
|
-
readonly nullable:
|
|
27
|
+
readonly nullable: TNullable
|
|
10
28
|
/** @default false */
|
|
11
29
|
readonly primaryKey: boolean
|
|
12
30
|
/** @default false */
|
|
@@ -23,13 +41,22 @@ export const isColumnDefinition = (value: unknown): value is ColumnDefinition.An
|
|
|
23
41
|
typeof value === 'object' &&
|
|
24
42
|
value !== null &&
|
|
25
43
|
'columnType' in value &&
|
|
44
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- type guard narrowing; columnType checked to be in valid set
|
|
26
45
|
validColumnTypes.includes(value.columnType as any)
|
|
27
46
|
)
|
|
28
47
|
}
|
|
29
48
|
|
|
49
|
+
type MaybeNull<T, TNullable extends boolean> = T | (TNullable extends true ? null : never)
|
|
50
|
+
|
|
51
|
+
type ColumnDefaultArg<T, TNullable extends boolean> =
|
|
52
|
+
| MaybeNull<T, TNullable>
|
|
53
|
+
| ColumnDefaultThunk<MaybeNull<T, TNullable>>
|
|
54
|
+
| SqlDefaultValue
|
|
55
|
+
| NoDefault
|
|
56
|
+
|
|
30
57
|
export type ColumnDefinitionInput = {
|
|
31
58
|
readonly schema?: Schema.Schema<unknown>
|
|
32
|
-
readonly default?: unknown
|
|
59
|
+
readonly default?: ColumnDefaultArg<unknown, boolean>
|
|
33
60
|
readonly nullable?: boolean
|
|
34
61
|
readonly primaryKey?: boolean
|
|
35
62
|
readonly autoIncrement?: boolean
|
|
@@ -38,14 +65,6 @@ export type ColumnDefinitionInput = {
|
|
|
38
65
|
export const NoDefault = Symbol.for('NoDefault')
|
|
39
66
|
export type NoDefault = typeof NoDefault
|
|
40
67
|
|
|
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
68
|
export type ColDefFn<TColumnType extends FieldColumnType> = {
|
|
50
69
|
(): {
|
|
51
70
|
columnType: TColumnType
|
|
@@ -59,7 +78,7 @@ export type ColDefFn<TColumnType extends FieldColumnType> = {
|
|
|
59
78
|
TEncoded extends DefaultEncodedForColumnType<TColumnType>,
|
|
60
79
|
TDecoded = DefaultEncodedForColumnType<TColumnType>,
|
|
61
80
|
const TNullable extends boolean = false,
|
|
62
|
-
const TDefault extends TDecoded
|
|
81
|
+
const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
|
|
63
82
|
const TPrimaryKey extends boolean = false,
|
|
64
83
|
const TAutoIncrement extends boolean = false,
|
|
65
84
|
>(args: {
|
|
@@ -88,6 +107,7 @@ const makeColDef =
|
|
|
88
107
|
const schema = nullable === true ? Schema.NullOr(schemaWithoutNull) : schemaWithoutNull
|
|
89
108
|
const default_ = def?.default === undefined || def.default === NoDefault ? Option.none() : Option.some(def.default)
|
|
90
109
|
|
|
110
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- column factory return type uses complex conditional generics; consumer type safety enforced by ColDefFn signature
|
|
91
111
|
return {
|
|
92
112
|
columnType,
|
|
93
113
|
schema,
|
|
@@ -132,7 +152,7 @@ export type SpecializedColDefFn<
|
|
|
132
152
|
<
|
|
133
153
|
TDecoded = TBaseDecoded,
|
|
134
154
|
const TNullable extends boolean = false,
|
|
135
|
-
const TDefault extends TDecoded
|
|
155
|
+
const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
|
|
136
156
|
const TPrimaryKey extends boolean = false,
|
|
137
157
|
const TAutoIncrement extends boolean = false,
|
|
138
158
|
>(
|
|
@@ -183,10 +203,12 @@ type MakeSpecializedColDefFn = {
|
|
|
183
203
|
|
|
184
204
|
const makeSpecializedColDef: MakeSpecializedColDefFn = (columnType, opts) => (def?: ColumnDefinitionInput) => {
|
|
185
205
|
const nullable = def?.nullable ?? false
|
|
206
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- schema type variance; custom schema compatibility checked at call site
|
|
186
207
|
const schemaWithoutNull = opts._tag === 'baseSchemaFn' ? opts.baseSchemaFn(def?.schema as any) : opts.baseSchema
|
|
187
208
|
const schema = nullable === true ? Schema.NullOr(schemaWithoutNull) : schemaWithoutNull
|
|
188
209
|
const default_ = def?.default === undefined || def.default === NoDefault ? Option.none() : Option.some(def.default)
|
|
189
210
|
|
|
211
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- specialized column factory return type uses complex conditional generics; consumer type safety enforced by SpecializedColDefFn signature
|
|
190
212
|
return {
|
|
191
213
|
columnType,
|
|
192
214
|
schema,
|
|
@@ -219,7 +241,7 @@ export const boolean: SpecializedColDefFn<'integer', false, boolean> = makeSpeci
|
|
|
219
241
|
_tag: 'baseSchema',
|
|
220
242
|
baseSchema: Schema.transform(Schema.Number, Schema.Boolean, {
|
|
221
243
|
decode: (_) => _ === 1,
|
|
222
|
-
encode: (_) => (_ ? 1 : 0),
|
|
244
|
+
encode: (_) => (_ === true ? 1 : 0),
|
|
223
245
|
}),
|
|
224
246
|
})
|
|
225
247
|
|
|
@@ -242,15 +264,19 @@ export const defaultSchemaForColumnType = <TColumnType extends FieldColumnType>(
|
|
|
242
264
|
|
|
243
265
|
switch (columnType) {
|
|
244
266
|
case 'text': {
|
|
267
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
|
|
245
268
|
return Schema.String as any as Schema.Schema<T>
|
|
246
269
|
}
|
|
247
270
|
case 'integer': {
|
|
271
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
|
|
248
272
|
return Schema.Number as any as Schema.Schema<T>
|
|
249
273
|
}
|
|
250
274
|
case 'real': {
|
|
275
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
|
|
251
276
|
return Schema.Number as any as Schema.Schema<T>
|
|
252
277
|
}
|
|
253
278
|
case 'blob': {
|
|
279
|
+
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
|
|
254
280
|
return Schema.Uint8ArrayFromSelf as any as Schema.Schema<T>
|
|
255
281
|
}
|
|
256
282
|
default: {
|
|
@@ -20,19 +20,18 @@ export type DbSchemaInput = Record<string, TableDefinition<any, any>> | Readonly
|
|
|
20
20
|
* - array: we use the table name of each array item (= table definition) as the object key
|
|
21
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
|
|
22
22
|
*/
|
|
23
|
-
export type DbSchemaFromInputSchema<TSchemaInput extends DbSchemaInput> =
|
|
24
|
-
TableDefinition<any, any
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
: 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
|
|
30
29
|
|
|
31
30
|
// TODO ensure via runtime check (possibly even via type-level check) that all index names are unique
|
|
32
31
|
export const makeDbSchema = <TDbSchemaInput extends DbSchemaInput>(
|
|
33
32
|
schema: TDbSchemaInput,
|
|
34
33
|
): DbSchemaFromInputSchema<TDbSchemaInput> => {
|
|
35
|
-
return Array.isArray(schema) ? Object.fromEntries(schema.map((_) => [_.name, _])) : (schema as any)
|
|
34
|
+
return Array.isArray(schema) === true ? Object.fromEntries(schema.map((_) => [_.name, _])) : (schema as any)
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
export const table = <TTableName extends string, TColumns extends Columns, TIndexes extends Index[]>(
|
|
@@ -77,6 +76,7 @@ export const insertStructSchemaForTable = <TTableDefinition extends TableDefinit
|
|
|
77
76
|
Object.fromEntries(
|
|
78
77
|
tableDef.ast.columns.map((column) => [
|
|
79
78
|
column.name,
|
|
79
|
+
|
|
80
80
|
column.nullable === true || column.default._tag === 'Some' ? Schema.optional(column.schema) : column.schema,
|
|
81
81
|
]),
|
|
82
82
|
),
|
|
@@ -116,12 +116,8 @@ export type TableDefinition<TName extends string, TColumns extends Columns> = {
|
|
|
116
116
|
|
|
117
117
|
export type Columns = Record<string, ColumnDefinition<any, any>>
|
|
118
118
|
|
|
119
|
-
export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> =
|
|
120
|
-
any,
|
|
121
|
-
any
|
|
122
|
-
>
|
|
123
|
-
? true
|
|
124
|
-
: false
|
|
119
|
+
export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> =
|
|
120
|
+
TColumns extends ColumnDefinition<any, any> ? true : false
|
|
125
121
|
|
|
126
122
|
/**
|
|
127
123
|
* NOTE this is only needed to avoid a TS limitation where `StructSchemaForColumns` in the default case
|
|
@@ -200,8 +196,7 @@ export namespace FromColumns {
|
|
|
200
196
|
}
|
|
201
197
|
|
|
202
198
|
export type NullableColumnNames<TColumns extends Columns> = keyof {
|
|
203
|
-
|
|
204
|
-
[K in keyof TColumns as TColumns[K] extends ColumnDefinition<any, true> ? K : never]: {}
|
|
199
|
+
[K in keyof TColumns as TColumns[K]['nullable'] extends true ? K : never]: {}
|
|
205
200
|
}
|
|
206
201
|
|
|
207
202
|
export type RequiredInsertColumns<TColumns extends Columns> = {
|
|
@@ -214,9 +209,8 @@ export namespace FromColumns {
|
|
|
214
209
|
|
|
215
210
|
export type RequiredInsertColumnNames<TColumns extends Columns> = keyof RequiredInsertColumns<TColumns>
|
|
216
211
|
|
|
217
|
-
export type RequiresInsertValues<TColumns extends Columns> =
|
|
218
|
-
? false
|
|
219
|
-
: true
|
|
212
|
+
export type RequiresInsertValues<TColumns extends Columns> =
|
|
213
|
+
RequiredInsertColumnNames<TColumns> extends never ? false : true
|
|
220
214
|
|
|
221
215
|
export type InsertRowDecoded<TColumns extends Columns> = Types.Simplify<
|
|
222
216
|
Pick<RowDecodedAll<TColumns>, RequiredInsertColumnNames<TColumns>> &
|
|
@@ -1,14 +1,14 @@
|
|
|
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,
|
|
@@ -22,16 +22,15 @@ export * from './column-spec.ts'
|
|
|
22
22
|
export * from './table-def.ts'
|
|
23
23
|
|
|
24
24
|
export const makeState = <TStateInput extends InputState>(inputSchema: TStateInput): InternalState => {
|
|
25
|
-
const inputTables: ReadonlyArray<TableDef> =
|
|
26
|
-
? inputSchema.tables
|
|
27
|
-
: Object.values(inputSchema.tables)
|
|
25
|
+
const inputTables: ReadonlyArray<TableDef> =
|
|
26
|
+
Array.isArray(inputSchema.tables) === true ? inputSchema.tables : Object.values(inputSchema.tables)
|
|
28
27
|
|
|
29
28
|
const tables = new Map<string, TableDef.Any>()
|
|
30
29
|
|
|
31
30
|
for (const tableDef of inputTables) {
|
|
32
31
|
const sqliteDef = tableDef.sqliteDef
|
|
33
32
|
// TODO validate tables (e.g. index names are unique)
|
|
34
|
-
if (tables.has(sqliteDef.ast.name)) {
|
|
33
|
+
if (tables.has(sqliteDef.ast.name) === true) {
|
|
35
34
|
shouldNeverHappen(`Duplicate table name: ${sqliteDef.ast.name}. Please use unique names for tables.`)
|
|
36
35
|
}
|
|
37
36
|
tables.set(sqliteDef.ast.name, tableDef)
|
|
@@ -48,7 +47,7 @@ export const makeState = <TStateInput extends InputState>(inputSchema: TStateInp
|
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
for (const tableDef of inputTables) {
|
|
51
|
-
if (tableIsClientDocumentTable(tableDef)) {
|
|
50
|
+
if (tableIsClientDocumentTable(tableDef) === true) {
|
|
52
51
|
materializers.set(
|
|
53
52
|
tableDef[ClientDocumentTableDefSymbol].derived.setEventDef.name,
|
|
54
53
|
tableDef[ClientDocumentTableDefSymbol].derived.setMaterializer,
|
|
@@ -128,15 +128,25 @@ export type QueryBuilder<
|
|
|
128
128
|
|
|
129
129
|
export namespace QueryBuilder {
|
|
130
130
|
export type Any = QueryBuilder<any, any, any>
|
|
131
|
-
export type WhereOps = WhereOps.Equality | WhereOps.Order | WhereOps.Like | WhereOps.In
|
|
131
|
+
export type WhereOps = WhereOps.Equality | WhereOps.Order | WhereOps.Like | WhereOps.In | WhereOps.JsonArray
|
|
132
132
|
|
|
133
133
|
export namespace WhereOps {
|
|
134
134
|
export type Equality = '=' | '!='
|
|
135
135
|
export type Order = '<' | '>' | '<=' | '>='
|
|
136
136
|
export type Like = 'LIKE' | 'NOT LIKE' | 'ILIKE' | 'NOT ILIKE'
|
|
137
137
|
export type In = 'IN' | 'NOT IN'
|
|
138
|
+
/**
|
|
139
|
+
* Operators for checking if a JSON array column contains a value.
|
|
140
|
+
*
|
|
141
|
+
* ⚠️ **Performance note**: These operators use SQLite's `json_each()` table-valued function
|
|
142
|
+
* which **cannot be indexed** and requires a full table scan. For large tables with frequent
|
|
143
|
+
* lookups, consider denormalizing the data into a separate indexed table.
|
|
144
|
+
*
|
|
145
|
+
* @see https://sqlite.org/json1.html#jeach
|
|
146
|
+
*/
|
|
147
|
+
export type JsonArray = 'JSON_CONTAINS' | 'JSON_NOT_CONTAINS'
|
|
138
148
|
|
|
139
|
-
export type SingleValue = Equality | Order | Like
|
|
149
|
+
export type SingleValue = Equality | Order | Like | JsonArray
|
|
140
150
|
export type MultiValue = In
|
|
141
151
|
}
|
|
142
152
|
|
|
@@ -155,14 +165,26 @@ export namespace QueryBuilder {
|
|
|
155
165
|
| 'returning'
|
|
156
166
|
| 'onConflict'
|
|
157
167
|
|
|
168
|
+
/** Extracts the element type from an array type, or returns never if not an array */
|
|
169
|
+
type ArrayElement<T> = T extends ReadonlyArray<infer E> ? E : never
|
|
170
|
+
|
|
158
171
|
export type WhereParams<TTableDef extends TableDefBase> = Partial<{
|
|
159
172
|
[K in keyof TTableDef['sqliteDef']['columns']]:
|
|
160
173
|
| TTableDef['sqliteDef']['columns'][K]['schema']['Type']
|
|
161
|
-
| {
|
|
174
|
+
| {
|
|
175
|
+
op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>
|
|
176
|
+
value: TTableDef['sqliteDef']['columns'][K]['schema']['Type']
|
|
177
|
+
}
|
|
162
178
|
| {
|
|
163
179
|
op: QueryBuilder.WhereOps.MultiValue
|
|
164
180
|
value: ReadonlyArray<TTableDef['sqliteDef']['columns'][K]['schema']['Type']>
|
|
165
181
|
}
|
|
182
|
+
| (ArrayElement<TTableDef['sqliteDef']['columns'][K]['schema']['Type']> extends never
|
|
183
|
+
? never
|
|
184
|
+
: {
|
|
185
|
+
op: QueryBuilder.WhereOps.JsonArray
|
|
186
|
+
value: ArrayElement<TTableDef['sqliteDef']['columns'][K]['schema']['Type']>
|
|
187
|
+
})
|
|
166
188
|
| undefined
|
|
167
189
|
}>
|
|
168
190
|
|
|
@@ -208,9 +230,8 @@ export namespace QueryBuilder {
|
|
|
208
230
|
/** Select multiple columns */
|
|
209
231
|
<TColumns extends keyof TTableDef['sqliteDef']['columns'] & string>(
|
|
210
232
|
...columns: TColumns[]
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
): QueryBuilder<
|
|
233
|
+
)// params: QueryBuilderSelectParams, // TODO also support arbitrary SQL selects
|
|
234
|
+
: QueryBuilder<
|
|
214
235
|
ReadonlyArray<{
|
|
215
236
|
readonly [K in TColumns]: TTableDef['sqliteDef']['columns'][K]['schema']['Type']
|
|
216
237
|
}>,
|
|
@@ -242,7 +263,12 @@ export namespace QueryBuilder {
|
|
|
242
263
|
): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
|
|
243
264
|
<TColName extends keyof TTableDef['sqliteDef']['columns']>(
|
|
244
265
|
col: TColName,
|
|
245
|
-
op: QueryBuilder.WhereOps,
|
|
266
|
+
op: QueryBuilder.WhereOps.MultiValue,
|
|
267
|
+
value: ReadonlyArray<TTableDef['sqliteDef']['columns'][TColName]['schema']['Type']>,
|
|
268
|
+
): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
|
|
269
|
+
<TColName extends keyof TTableDef['sqliteDef']['columns']>(
|
|
270
|
+
col: TColName,
|
|
271
|
+
op: QueryBuilder.WhereOps.SingleValue,
|
|
246
272
|
value: TTableDef['sqliteDef']['columns'][TColName]['schema']['Type'],
|
|
247
273
|
): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
|
|
248
274
|
}
|
|
@@ -331,12 +357,20 @@ export namespace QueryBuilder {
|
|
|
331
357
|
>
|
|
332
358
|
|
|
333
359
|
/**
|
|
334
|
-
* Insert a new row into the table
|
|
360
|
+
* Insert a new row into the table.
|
|
361
|
+
*
|
|
362
|
+
* @remarks
|
|
363
|
+
*
|
|
364
|
+
* Follows SQL semantics: nullable columns and columns with defaults are omittable.
|
|
365
|
+
* `NullOr(S)` and `optional(NullOr(S))` both produce nullable columns, so both are omittable.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
335
368
|
*
|
|
336
|
-
* Example:
|
|
337
369
|
* ```ts
|
|
338
370
|
* db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
|
|
339
371
|
* ```
|
|
372
|
+
*
|
|
373
|
+
* @param values - The row values to insert.
|
|
340
374
|
*/
|
|
341
375
|
readonly insert: (
|
|
342
376
|
values: TTableDef['insertSchema']['Type'],
|
|
@@ -347,22 +381,26 @@ export namespace QueryBuilder {
|
|
|
347
381
|
>
|
|
348
382
|
|
|
349
383
|
/**
|
|
350
|
-
*
|
|
384
|
+
* Upsert: insert a row, or handle conflicts on existing rows.
|
|
385
|
+
* Equivalent to SQLite's `INSERT ... ON CONFLICT` clause.
|
|
386
|
+
*
|
|
387
|
+
* Actions:
|
|
388
|
+
* - `'ignore'`: Skip the insert if a row with the same key exists
|
|
389
|
+
* - `'replace'`: Delete the existing row and insert the new one
|
|
390
|
+
* - `'update'`: Update specific columns on the existing row
|
|
391
|
+
*
|
|
351
392
|
* ```ts
|
|
393
|
+
* // Ignore: skip if row exists
|
|
352
394
|
* db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'ignore')
|
|
353
|
-
* ```
|
|
354
395
|
*
|
|
355
|
-
*
|
|
356
|
-
* ```ts
|
|
396
|
+
* // Replace: delete existing row and insert new one
|
|
357
397
|
* db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'replace')
|
|
358
|
-
* ```
|
|
359
398
|
*
|
|
360
|
-
*
|
|
361
|
-
* ```ts
|
|
399
|
+
* // Update: merge specific columns into existing row
|
|
362
400
|
* db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'update', { text: 'Buy soy milk' })
|
|
363
401
|
* ```
|
|
364
402
|
*
|
|
365
|
-
* NOTE
|
|
403
|
+
* NOTE: Composite primary keys are not yet supported.
|
|
366
404
|
*/
|
|
367
405
|
readonly onConflict: {
|
|
368
406
|
<TTarget extends SingleOrReadonlyArray<keyof TTableDef['sqliteDef']['columns']>>(
|
|
@@ -1,12 +1,77 @@
|
|
|
1
1
|
import { shouldNeverHappen } from '@livestore/utils'
|
|
2
|
-
import { Schema } from '@livestore/utils/effect'
|
|
2
|
+
import { Schema, SchemaAST } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import { SessionIdSymbol } from '../../../../adapter-types.ts'
|
|
5
5
|
import type { SqlValue } from '../../../../util.ts'
|
|
6
6
|
import type { State } from '../../../mod.ts'
|
|
7
7
|
import type { QueryBuilderAst } from './api.ts'
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Extracts array element schema from a JSON array transformation AST.
|
|
11
|
+
* Returns the element schema, or undefined if not a JSON array transformation.
|
|
12
|
+
*/
|
|
13
|
+
const extractArrayElementFromTransformation = (ast: SchemaAST.AST): Schema.Schema.Any | undefined => {
|
|
14
|
+
if (SchemaAST.isTransformation(ast) === false) return undefined
|
|
15
|
+
|
|
16
|
+
const toAst = ast.to
|
|
17
|
+
// Check if the "to" side is a TupleType (Effect's internal representation of Array)
|
|
18
|
+
if (SchemaAST.isTupleType(toAst) === false) return undefined
|
|
19
|
+
|
|
20
|
+
// For Schema.Array, rest contains { type: AST } elements - get the first one's type
|
|
21
|
+
const restElement = toAst.rest[0]
|
|
22
|
+
if (restElement === undefined) return undefined
|
|
23
|
+
|
|
24
|
+
return Schema.make(restElement.type)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* For JSON array columns, extracts the element schema from Schema.parseJson(Schema.Array(ElementSchema)).
|
|
29
|
+
* Also handles nullable JSON arrays (Schema.NullOr(Schema.parseJson(Schema.Array(...)))).
|
|
30
|
+
* Returns the element schema, or undefined if the column is not a JSON array.
|
|
31
|
+
*/
|
|
32
|
+
const getJsonArrayElementSchema = (colSchema: Schema.Schema.Any): Schema.Schema.Any | undefined => {
|
|
33
|
+
const ast = colSchema.ast
|
|
34
|
+
|
|
35
|
+
// Case 1: Direct transformation (non-nullable JSON array)
|
|
36
|
+
// Schema.parseJson(Schema.Array(ElementSchema)) creates a Transformation AST
|
|
37
|
+
if (SchemaAST.isTransformation(ast) === true) {
|
|
38
|
+
return extractArrayElementFromTransformation(ast)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Case 2: Nullable JSON array - Schema.NullOr wraps the parseJson in a Union
|
|
42
|
+
// Structure: Union([Transformation (JSON array), Literal (null)])
|
|
43
|
+
if (SchemaAST.isUnion(ast) === true) {
|
|
44
|
+
for (const member of ast.types) {
|
|
45
|
+
const result = extractArrayElementFromTransformation(member)
|
|
46
|
+
if (result !== undefined) return result
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return undefined
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Encodes a JSON array element to the representation returned by SQLite's json_each().
|
|
55
|
+
* Objects/arrays are stringified so they match json_each's TEXT representation.
|
|
56
|
+
*/
|
|
57
|
+
const encodeJsonArrayElementValue = (elementSchema: Schema.Schema.Any, value: unknown): SqlValue => {
|
|
58
|
+
const encoded = Schema.encodeSync(elementSchema as Schema.Schema<unknown, SqlValue>)(value)
|
|
59
|
+
|
|
60
|
+
if (encoded === null) return null
|
|
61
|
+
if (typeof encoded === 'object') {
|
|
62
|
+
// Objects and arrays need to be JSON-stringified to match json_each() output
|
|
63
|
+
return JSON.stringify(encoded)
|
|
64
|
+
}
|
|
65
|
+
if (typeof encoded === 'boolean') {
|
|
66
|
+
return encoded === true ? 1 : 0
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return encoded
|
|
70
|
+
}
|
|
71
|
+
|
|
9
72
|
// Helper functions for SQL generation
|
|
73
|
+
const quoteIdentifier = (identifier: string): string => `"${identifier.replace(/"/g, '""')}"`
|
|
74
|
+
|
|
10
75
|
const formatWhereClause = (
|
|
11
76
|
whereConditions: ReadonlyArray<QueryBuilderAst.Where>,
|
|
12
77
|
tableDef: State.SQLite.TableDefBase,
|
|
@@ -16,13 +81,15 @@ const formatWhereClause = (
|
|
|
16
81
|
|
|
17
82
|
const whereClause = whereConditions
|
|
18
83
|
.map(({ col, op, value }) => {
|
|
84
|
+
const quotedCol = quoteIdentifier(col)
|
|
85
|
+
|
|
19
86
|
// Handle NULL values
|
|
20
87
|
if (value === null) {
|
|
21
88
|
if (op !== '=' && op !== '!=') {
|
|
22
89
|
throw new Error(`Unsupported operator for NULL value: ${op}`)
|
|
23
90
|
}
|
|
24
91
|
const opStmt = op === '=' ? 'IS' : 'IS NOT'
|
|
25
|
-
return `${
|
|
92
|
+
return `${quotedCol} ${opStmt} NULL`
|
|
26
93
|
}
|
|
27
94
|
|
|
28
95
|
// Get column definition and encode value
|
|
@@ -31,12 +98,29 @@ const formatWhereClause = (
|
|
|
31
98
|
throw new Error(`Column ${col} not found`)
|
|
32
99
|
}
|
|
33
100
|
|
|
101
|
+
// Handle JSON array containment operators
|
|
102
|
+
if (op === 'JSON_CONTAINS' || op === 'JSON_NOT_CONTAINS') {
|
|
103
|
+
const elementSchema = getJsonArrayElementSchema(colDef.schema)
|
|
104
|
+
if (elementSchema === undefined) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`${op} operator can only be used on JSON array columns, but column "${col}" is not a JSON array`,
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const existsOp = op === 'JSON_CONTAINS' ? 'EXISTS' : 'NOT EXISTS'
|
|
111
|
+
// Encode the element value using the element schema
|
|
112
|
+
// Objects are JSON-stringified to match json_each() output
|
|
113
|
+
const encodedValue = encodeJsonArrayElementValue(elementSchema, value)
|
|
114
|
+
bindValues.push(encodedValue)
|
|
115
|
+
return `${existsOp} (SELECT 1 FROM json_each(${quotedCol}) WHERE value = ?)`
|
|
116
|
+
}
|
|
117
|
+
|
|
34
118
|
// Handle array values for IN/NOT IN operators
|
|
35
119
|
const isArray = op === 'IN' || op === 'NOT IN'
|
|
36
120
|
|
|
37
|
-
if (isArray) {
|
|
121
|
+
if (isArray === true) {
|
|
38
122
|
// Verify value is an array
|
|
39
|
-
if (
|
|
123
|
+
if (Array.isArray(value) === false) {
|
|
40
124
|
return shouldNeverHappen(`Expected array value for ${op} operator but got`, value)
|
|
41
125
|
}
|
|
42
126
|
|
|
@@ -48,11 +132,11 @@ const formatWhereClause = (
|
|
|
48
132
|
const encodedValues = value.map((v) => Schema.encodeSync(colDef.schema)(v)) as SqlValue[]
|
|
49
133
|
bindValues.push(...encodedValues)
|
|
50
134
|
const placeholders = encodedValues.map(() => '?').join(', ')
|
|
51
|
-
return `${
|
|
135
|
+
return `${quotedCol} ${op} (${placeholders})`
|
|
52
136
|
} else {
|
|
53
137
|
const encodedValue = Schema.encodeSync(colDef.schema)(value)
|
|
54
138
|
bindValues.push(encodedValue as SqlValue)
|
|
55
|
-
return `${
|
|
139
|
+
return `${quotedCol} ${op} ?`
|
|
56
140
|
}
|
|
57
141
|
})
|
|
58
142
|
.join(' AND ')
|
|
@@ -61,8 +145,8 @@ const formatWhereClause = (
|
|
|
61
145
|
}
|
|
62
146
|
|
|
63
147
|
const formatReturningClause = (returning?: string[]): string => {
|
|
64
|
-
if (
|
|
65
|
-
return ` RETURNING ${returning.join(', ')}`
|
|
148
|
+
if (returning == null || returning.length === 0) return ''
|
|
149
|
+
return ` RETURNING ${returning.map(quoteIdentifier).join(', ')}`
|
|
66
150
|
}
|
|
67
151
|
|
|
68
152
|
export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: SqlValue[]; usedTables: Set<string> } => {
|
|
@@ -72,6 +156,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
72
156
|
// INSERT query
|
|
73
157
|
if (ast._tag === 'InsertQuery') {
|
|
74
158
|
const columns = Object.keys(ast.values)
|
|
159
|
+
const quotedColumns = columns.map(quoteIdentifier)
|
|
75
160
|
const placeholders = columns.map(() => '?').join(', ')
|
|
76
161
|
const encodedValues = Schema.encodeSync(ast.tableDef.insertSchema)(ast.values)
|
|
77
162
|
|
|
@@ -84,14 +169,15 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
84
169
|
let conflictClause = '' // Store the ON CONFLICT clause separately
|
|
85
170
|
|
|
86
171
|
// Handle ON CONFLICT clause
|
|
87
|
-
if (ast.onConflict) {
|
|
172
|
+
if (ast.onConflict !== undefined) {
|
|
88
173
|
// Handle REPLACE specifically as it changes the INSERT verb
|
|
89
174
|
if (ast.onConflict.action._tag === 'replace') {
|
|
90
175
|
insertVerb = 'INSERT OR REPLACE'
|
|
91
176
|
// For REPLACE, the conflict target is implied and no further clause is needed
|
|
92
177
|
} else {
|
|
93
178
|
// Build the ON CONFLICT clause for IGNORE or UPDATE
|
|
94
|
-
|
|
179
|
+
const conflictTargets = ast.onConflict.targets.map(quoteIdentifier).join(', ')
|
|
180
|
+
conflictClause = ` ON CONFLICT (${conflictTargets}) `
|
|
95
181
|
if (ast.onConflict.action._tag === 'ignore') {
|
|
96
182
|
conflictClause += 'DO NOTHING'
|
|
97
183
|
} else {
|
|
@@ -105,8 +191,9 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
105
191
|
const updates = updateCols
|
|
106
192
|
.map((col) => {
|
|
107
193
|
const value = updateValues[col]
|
|
194
|
+
const quotedCol = quoteIdentifier(col)
|
|
108
195
|
// If the value is undefined, use excluded.col
|
|
109
|
-
return value === undefined ? `${
|
|
196
|
+
return value === undefined ? `${quotedCol} = excluded.${quotedCol}` : `${quotedCol} = ?`
|
|
110
197
|
})
|
|
111
198
|
.join(', ')
|
|
112
199
|
|
|
@@ -129,7 +216,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
129
216
|
}
|
|
130
217
|
|
|
131
218
|
// Construct the main query part
|
|
132
|
-
let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${
|
|
219
|
+
let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${quotedColumns.join(', ')}) VALUES (${placeholders})`
|
|
133
220
|
|
|
134
221
|
// Append the conflict clause if it was generated (i.e., not for REPLACE)
|
|
135
222
|
query += conflictClause
|
|
@@ -157,10 +244,12 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
157
244
|
bindValues.push(encodedValues[col] as SqlValue)
|
|
158
245
|
})
|
|
159
246
|
|
|
160
|
-
let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns
|
|
247
|
+
let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns
|
|
248
|
+
.map((col) => `${quoteIdentifier(col)} = ?`)
|
|
249
|
+
.join(', ')}`
|
|
161
250
|
|
|
162
251
|
const whereClause = formatWhereClause(ast.where, ast.tableDef, bindValues)
|
|
163
|
-
if (whereClause) query += ` ${whereClause}`
|
|
252
|
+
if (whereClause !== undefined) query += ` ${whereClause}`
|
|
164
253
|
|
|
165
254
|
query += formatReturningClause(ast.returning)
|
|
166
255
|
return { query, bindValues, usedTables }
|
|
@@ -171,7 +260,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
171
260
|
let query = `DELETE FROM '${ast.tableDef.sqliteDef.name}'`
|
|
172
261
|
|
|
173
262
|
const whereClause = formatWhereClause(ast.where, ast.tableDef, bindValues)
|
|
174
|
-
if (whereClause) query += ` ${whereClause}`
|
|
263
|
+
if (whereClause !== undefined) query += ` ${whereClause}`
|
|
175
264
|
|
|
176
265
|
query += formatReturningClause(ast.returning)
|
|
177
266
|
return { query, bindValues, usedTables }
|
|
@@ -201,31 +290,31 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
|
|
|
201
290
|
const encodedId = ast.id === SessionIdSymbol ? ast.id : Schema.encodeSync(idColDef.schema)(ast.id)
|
|
202
291
|
|
|
203
292
|
return {
|
|
204
|
-
query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE id = ?`,
|
|
293
|
+
query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE ${quoteIdentifier('id')} = ?`,
|
|
205
294
|
bindValues: [encodedId as SqlValue],
|
|
206
295
|
usedTables,
|
|
207
296
|
}
|
|
208
297
|
}
|
|
209
298
|
|
|
210
299
|
// SELECT query
|
|
211
|
-
const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.join(', ')
|
|
300
|
+
const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.map(quoteIdentifier).join(', ')
|
|
212
301
|
const selectStmt = `SELECT ${columnsStmt}`
|
|
213
302
|
const fromStmt = `FROM '${ast.tableDef.sqliteDef.name}'`
|
|
214
303
|
const whereStmt = formatWhereClause(ast.where, ast.tableDef, bindValues)
|
|
215
304
|
|
|
216
305
|
const orderByStmt =
|
|
217
306
|
ast.orderBy.length > 0
|
|
218
|
-
? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${col} ${direction}`).join(', ')}`
|
|
307
|
+
? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${quoteIdentifier(col)} ${direction}`).join(', ')}`
|
|
219
308
|
: ''
|
|
220
309
|
|
|
221
310
|
const limitStmt = ast.limit._tag === 'Some' ? `LIMIT ?` : ''
|
|
222
311
|
const offsetStmt = ast.offset._tag === 'Some' ? `OFFSET ?` : ''
|
|
223
312
|
|
|
224
|
-
// Push
|
|
225
|
-
if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
|
|
313
|
+
// Push limit and offset values in the correct order matching the query string
|
|
226
314
|
if (ast.limit._tag === 'Some') bindValues.push(ast.limit.value)
|
|
315
|
+
if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
|
|
227
316
|
|
|
228
|
-
const query = [selectStmt, fromStmt, whereStmt, orderByStmt,
|
|
317
|
+
const query = [selectStmt, fromStmt, whereStmt, orderByStmt, limitStmt, offsetStmt]
|
|
229
318
|
.map((clause) => clause.trim())
|
|
230
319
|
.filter((clause) => clause.length > 0)
|
|
231
320
|
.join(' ')
|