@livestore/common 0.4.0-dev.9 → 0.5.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/ClientSessionLeaderThreadProxy.d.ts +27 -12
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
- package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
- package/dist/MaterializationJournal.d.ts +44 -0
- package/dist/MaterializationJournal.d.ts.map +1 -0
- package/dist/MaterializationJournal.js +112 -0
- package/dist/MaterializationJournal.js.map +1 -0
- package/dist/StateHead.d.ts +26 -0
- package/dist/StateHead.d.ts.map +1 -0
- package/dist/StateHead.js +50 -0
- package/dist/StateHead.js.map +1 -0
- package/dist/WorkerTransportError.d.ts +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/__tests__/fixture.d.ts +1 -1
- package/dist/__tests__/fixture.d.ts.map +1 -1
- package/dist/__tests__/fixture.js +3 -3
- package/dist/__tests__/fixture.js.map +1 -1
- package/dist/adapter-types.d.ts +59 -57
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +31 -22
- 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 +56 -56
- package/dist/debug-info.d.ts.map +1 -1
- package/dist/debug-info.js +46 -32
- package/dist/debug-info.js.map +1 -1
- package/dist/defs.d.ts +9 -9
- package/dist/defs.js +2 -2
- package/dist/devtools/devtools-compatibility.test.d.ts +2 -0
- package/dist/devtools/devtools-compatibility.test.d.ts.map +1 -0
- package/dist/devtools/devtools-compatibility.test.js +16 -0
- package/dist/devtools/devtools-compatibility.test.js.map +1 -0
- package/dist/devtools/devtools-messages-client-session.d.ts +531 -312
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +86 -67
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +32 -35
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +12 -14
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +417 -320
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +117 -87
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/devtools/devtools-sessioninfo.d.ts +28 -17
- package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
- package/dist/devtools/devtools-sessioninfo.js +12 -6
- package/dist/devtools/devtools-sessioninfo.js.map +1 -1
- package/dist/devtools/mod.d.ts +17 -7
- package/dist/devtools/mod.d.ts.map +1 -1
- package/dist/devtools/mod.js +19 -8
- package/dist/devtools/mod.js.map +1 -1
- package/dist/errors.d.ts +52 -46
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +31 -21
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +116 -21
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +596 -470
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/RejectedPushError.d.ts +138 -0
- package/dist/leader-thread/RejectedPushError.d.ts.map +1 -0
- package/dist/leader-thread/RejectedPushError.js +97 -0
- package/dist/leader-thread/RejectedPushError.js.map +1 -0
- package/dist/leader-thread/connection.d.ts +1 -0
- package/dist/leader-thread/connection.d.ts.map +1 -1
- package/dist/leader-thread/connection.js +10 -9
- package/dist/leader-thread/connection.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +20 -15
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +80 -20
- 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 +110 -62
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +19 -7
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +67 -45
- 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 -2
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +32 -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 +19 -40
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/shutdown-channel.d.ts +3 -7
- package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
- package/dist/leader-thread/shutdown-channel.js +2 -3
- package/dist/leader-thread/shutdown-channel.js.map +1 -1
- package/dist/leader-thread/stream-events.d.ts +53 -0
- package/dist/leader-thread/stream-events.d.ts.map +1 -0
- package/dist/leader-thread/stream-events.js +164 -0
- package/dist/leader-thread/stream-events.js.map +1 -0
- package/dist/leader-thread/types.d.ts +92 -51
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js +17 -4
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/logging.d.ts +15 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +2 -0
- package/dist/logging.js.map +1 -0
- package/dist/make-client-session.d.ts +6 -5
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/make-client-session.js +10 -7
- package/dist/make-client-session.js.map +1 -1
- package/dist/materializer-helper.d.ts +6 -7
- package/dist/materializer-helper.d.ts.map +1 -1
- package/dist/materializer-helper.js +22 -40
- package/dist/materializer-helper.js.map +1 -1
- package/dist/otel.d.ts +4 -4
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +8 -8
- 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 +52 -39
- 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/define.test.d.ts +2 -0
- package/dist/schema/EventDef/define.test.d.ts.map +1 -0
- package/dist/schema/EventDef/define.test.js +23 -0
- package/dist/schema/EventDef/define.test.js.map +1 -0
- package/dist/schema/EventDef/deprecated.d.ts +94 -0
- package/dist/schema/EventDef/deprecated.d.ts.map +1 -0
- package/dist/schema/EventDef/deprecated.js +143 -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 +192 -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/client.d.ts +168 -0
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/client.js +179 -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 +120 -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 +7 -4
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +6 -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 +34 -5
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +14 -18
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +54 -30
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +146 -6
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.d.ts +13 -13
- package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.js +13 -15
- package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js +19 -43
- package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.d.ts +1 -1
- package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-def.js +132 -57
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +155 -70
- 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 +26 -17
- package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -2
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +15 -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 +25 -19
- 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 +22 -16
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +28 -17
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +14 -12
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js +6 -4
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts +3 -5
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +6 -8
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/persistence.d.ts +11 -0
- package/dist/schema/state/sqlite/persistence.d.ts.map +1 -0
- package/dist/schema/state/sqlite/persistence.js +10 -0
- package/dist/schema/state/sqlite/persistence.js.map +1 -0
- package/dist/schema/state/sqlite/query-builder/api.d.ts +58 -29
- 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 +105 -24
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts +4 -2
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +42 -27
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +402 -498
- 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/eventlog-tables.d.ts +515 -0
- 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 +678 -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 +87 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
- package/dist/schema/state/sqlite/table-def.d.ts +19 -20
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/table-def.js +54 -4
- package/dist/schema/state/sqlite/table-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +226 -20
- 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 +70 -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/session-id-symbol.d.ts +29 -0
- package/dist/session-id-symbol.d.ts.map +1 -0
- package/dist/session-id-symbol.js +44 -0
- package/dist/session-id-symbol.js.map +1 -0
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +26 -16
- 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/sql-queries/types.d.ts +6 -7
- package/dist/sql-queries/types.d.ts.map +1 -1
- package/dist/sql-queries/types.js.map +1 -1
- package/dist/sqlite-db-helper.d.ts +21 -1
- package/dist/sqlite-db-helper.d.ts.map +1 -1
- package/dist/sqlite-db-helper.js +40 -5
- package/dist/sqlite-db-helper.js.map +1 -1
- package/dist/sqlite-types.d.ts +8 -11
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/sqlite-types.js +3 -3
- package/dist/sqlite-types.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +47 -25
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +269 -154
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/errors.d.ts +12 -51
- package/dist/sync/errors.d.ts.map +1 -1
- package/dist/sync/errors.js +7 -24
- 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 +11 -10
- package/dist/sync/mock-sync-backend.d.ts.map +1 -1
- package/dist/sync/mock-sync-backend.js +97 -74
- package/dist/sync/mock-sync-backend.js.map +1 -1
- package/dist/sync/mock-sync-backend.test.d.ts +2 -0
- package/dist/sync/mock-sync-backend.test.d.ts.map +1 -0
- package/dist/sync/mock-sync-backend.test.js +49 -0
- package/dist/sync/mock-sync-backend.test.js.map +1 -0
- package/dist/sync/next/compact-events.d.ts.map +1 -1
- package/dist/sync/next/compact-events.js +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 +58 -15
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +219 -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 +12 -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 +4 -4
- 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 +9 -9
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +12 -12
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/next/test/history-dag-common.test.d.ts +2 -0
- package/dist/sync/next/test/history-dag-common.test.d.ts.map +1 -0
- package/dist/sync/next/test/history-dag-common.test.js +73 -0
- package/dist/sync/next/test/history-dag-common.test.js.map +1 -0
- package/dist/sync/sync-backend-kv.d.ts +3 -3
- package/dist/sync/sync-backend-kv.d.ts.map +1 -1
- package/dist/sync/sync-backend-kv.js +6 -4
- package/dist/sync/sync-backend-kv.js.map +1 -1
- package/dist/sync/sync-backend.d.ts +41 -21
- package/dist/sync/sync-backend.d.ts.map +1 -1
- package/dist/sync/sync-backend.js +45 -4
- 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 +115 -191
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +108 -129
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +289 -161
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/transport-chunking.d.ts +35 -0
- package/dist/sync/transport-chunking.d.ts.map +1 -0
- package/dist/sync/transport-chunking.js +47 -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 +3 -3
- package/dist/testing/event-factory.d.ts.map +1 -1
- package/dist/testing/event-factory.js +5 -7
- package/dist/testing/event-factory.js.map +1 -1
- package/dist/util.d.ts +11 -4
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +21 -4
- 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 +50 -16
- package/src/ClientSessionLeaderThreadProxy.ts +27 -12
- package/src/MaterializationJournal.ts +184 -0
- package/src/StateHead.ts +80 -0
- package/src/WorkerTransportError.ts +12 -0
- package/src/__tests__/fixture.ts +3 -3
- package/src/adapter-types.ts +62 -56
- package/src/bounded-collections.ts +6 -5
- package/src/debug-info.ts +54 -43
- package/src/defs.ts +2 -2
- package/src/devtools/devtools-compatibility.test.ts +19 -0
- package/src/devtools/devtools-messages-client-session.ts +72 -63
- package/src/devtools/devtools-messages-common.ts +18 -22
- package/src/devtools/devtools-messages-leader.ts +89 -68
- package/src/devtools/devtools-sessioninfo.ts +17 -12
- package/src/devtools/mod.ts +15 -7
- package/src/errors.ts +58 -38
- package/src/index.ts +11 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +927 -674
- package/src/leader-thread/RejectedPushError.ts +119 -0
- package/src/leader-thread/connection.ts +13 -9
- package/src/leader-thread/eventlog.ts +114 -41
- package/src/leader-thread/leader-worker-devtools.ts +223 -124
- package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
- package/src/leader-thread/make-leader-thread-layer.ts +170 -82
- package/src/leader-thread/materialize-event.ts +51 -16
- package/src/leader-thread/mod.ts +1 -0
- package/src/leader-thread/recreate-db.ts +26 -61
- package/src/leader-thread/shutdown-channel.ts +3 -18
- package/src/leader-thread/stream-events.ts +209 -0
- package/src/leader-thread/types.ts +77 -65
- package/src/logging.ts +15 -0
- package/src/make-client-session.ts +16 -10
- package/src/materializer-helper.ts +31 -49
- package/src/otel.ts +15 -13
- package/src/rematerialize-from-eventlog.ts +106 -93
- package/src/schema/EventDef/define.test.ts +28 -0
- package/src/schema/EventDef/define.ts +218 -0
- package/src/schema/EventDef/deprecated.test.ts +122 -0
- package/src/schema/EventDef/deprecated.ts +172 -0
- package/src/schema/EventDef/event-def.ts +123 -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 +256 -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 +142 -0
- package/src/schema/LiveStoreEvent/client.ts +236 -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 +7 -4
- package/src/schema/schema.ts +48 -6
- package/src/schema/state/sqlite/client-document-def.test.ts +172 -14
- package/src/schema/state/sqlite/client-document-def.ts +126 -98
- package/src/schema/state/sqlite/column-annotations.test.ts +27 -45
- package/src/schema/state/sqlite/column-annotations.ts +27 -30
- package/src/schema/state/sqlite/column-def.test.ts +186 -77
- package/src/schema/state/sqlite/column-def.ts +169 -62
- package/src/schema/state/sqlite/column-spec.test.ts +34 -19
- package/src/schema/state/sqlite/column-spec.ts +38 -11
- package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +17 -7
- package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +123 -63
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +37 -17
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +65 -45
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +48 -40
- package/src/schema/state/sqlite/mod.ts +9 -12
- package/src/schema/state/sqlite/persistence.ts +11 -0
- package/src/schema/state/sqlite/query-builder/api.ts +61 -23
- package/src/schema/state/sqlite/query-builder/astToSql.ts +117 -23
- package/src/schema/state/sqlite/query-builder/impl.test.ts +489 -551
- package/src/schema/state/sqlite/query-builder/impl.ts +43 -26
- 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 +109 -0
- package/src/schema/state/sqlite/table-def.test.ts +295 -46
- package/src/schema/state/sqlite/table-def.ts +109 -64
- package/src/schema/unknown-events.ts +132 -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/session-id-symbol.ts +59 -0
- package/src/sql-queries/sql-queries.ts +26 -18
- package/src/sql-queries/sql-query-builder.ts +1 -0
- package/src/sql-queries/types.ts +6 -7
- package/src/sqlite-db-helper.ts +67 -5
- package/src/sqlite-types.ts +9 -11
- package/src/sync/ClientSessionSyncProcessor.ts +388 -194
- package/src/sync/errors.ts +18 -28
- package/src/sync/index.ts +2 -0
- package/src/sync/mock-sync-backend.test.ts +78 -0
- package/src/sync/mock-sync-backend.ts +196 -108
- 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 +306 -26
- package/src/sync/next/history-dag.ts +20 -13
- package/src/sync/next/rebase-events.ts +12 -12
- package/src/sync/next/test/compact-events.calculator.test.ts +5 -4
- package/src/sync/next/test/compact-events.test.ts +4 -3
- package/src/sync/next/test/event-fixtures.ts +14 -14
- package/src/sync/next/test/history-dag-common.test.ts +87 -0
- package/src/sync/sync-backend-kv.ts +7 -4
- package/src/sync/sync-backend.ts +75 -26
- package/src/sync/sync.ts +24 -2
- package/src/sync/syncstate.test.ts +657 -442
- package/src/sync/syncstate.ts +175 -160
- package/src/sync/transport-chunking.ts +85 -0
- package/src/sync/validate-push-payload.ts +6 -8
- package/src/testing/event-factory.ts +10 -12
- package/src/util.ts +20 -11
- package/src/version.ts +32 -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 +0 -306
- 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 +0 -976
- 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/sql-queries/misc.d.ts +0 -2
- package/dist/sql-queries/misc.d.ts.map +0 -1
- package/dist/sql-queries/misc.js +0 -2
- package/dist/sql-queries/misc.js.map +0 -1
- package/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/sql-queries/misc.ts +0 -2
- 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,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TestSchema } from 'effect/testing'
|
|
2
2
|
import { describe, expect, it } from 'vitest'
|
|
3
3
|
|
|
4
|
+
import { Schema, SchemaTransformation } from '@livestore/utils/effect'
|
|
5
|
+
|
|
4
6
|
import { State } from '../../../mod.ts'
|
|
5
|
-
import type { QueryBuilder } from './api.ts'
|
|
6
7
|
import { getResultSchema } from './impl.ts'
|
|
7
8
|
|
|
8
9
|
const todos = State.SQLite.table({
|
|
@@ -11,7 +12,7 @@ const todos = State.SQLite.table({
|
|
|
11
12
|
id: State.SQLite.text({ primaryKey: true }),
|
|
12
13
|
text: State.SQLite.text({ default: '', nullable: false }),
|
|
13
14
|
completed: State.SQLite.boolean({ default: false, nullable: false }),
|
|
14
|
-
status: State.SQLite.text({ schema: Schema.
|
|
15
|
+
status: State.SQLite.text({ schema: Schema.Literals(['active', 'completed']) }),
|
|
15
16
|
deletedAt: State.SQLite.datetime({ nullable: true }),
|
|
16
17
|
// TODO consider leaning more into Effect schema
|
|
17
18
|
// other: Schema.Number.pipe(State.SQLite.asInteger),
|
|
@@ -23,7 +24,7 @@ const todosWithIntId = State.SQLite.table({
|
|
|
23
24
|
columns: {
|
|
24
25
|
id: State.SQLite.integer({ primaryKey: true }),
|
|
25
26
|
text: State.SQLite.text({ default: '', nullable: false }),
|
|
26
|
-
status: State.SQLite.text({ schema: Schema.
|
|
27
|
+
status: State.SQLite.text({ schema: Schema.Literals(['active', 'completed']) }),
|
|
27
28
|
},
|
|
28
29
|
})
|
|
29
30
|
|
|
@@ -39,7 +40,7 @@ const comments = State.SQLite.table({
|
|
|
39
40
|
const UiState = State.SQLite.clientDocument({
|
|
40
41
|
name: 'UiState',
|
|
41
42
|
schema: Schema.Struct({
|
|
42
|
-
filter: Schema.
|
|
43
|
+
filter: Schema.Literals(['all', 'active', 'completed']),
|
|
43
44
|
}),
|
|
44
45
|
default: { value: { filter: 'all' } },
|
|
45
46
|
})
|
|
@@ -47,7 +48,7 @@ const UiState = State.SQLite.clientDocument({
|
|
|
47
48
|
const UiStateWithDefaultId = State.SQLite.clientDocument({
|
|
48
49
|
name: 'UiState',
|
|
49
50
|
schema: Schema.Struct({
|
|
50
|
-
filter: Schema.
|
|
51
|
+
filter: Schema.Literals(['all', 'active', 'completed']),
|
|
51
52
|
}),
|
|
52
53
|
default: {
|
|
53
54
|
id: 'static',
|
|
@@ -61,10 +62,10 @@ const issue = State.SQLite.table({
|
|
|
61
62
|
id: State.SQLite.integer({ primaryKey: true }),
|
|
62
63
|
title: State.SQLite.text({ default: '' }),
|
|
63
64
|
creator: State.SQLite.text({ default: '' }),
|
|
64
|
-
priority: State.SQLite.integer({ schema: Schema.
|
|
65
|
-
created: State.SQLite.integer({ schema: Schema.
|
|
66
|
-
deleted: State.SQLite.integer({ nullable: true, schema: Schema.
|
|
67
|
-
modified: State.SQLite.integer({ schema: Schema.
|
|
65
|
+
priority: State.SQLite.integer({ schema: Schema.Literals([0, 1, 2, 3, 4]), default: 0 }),
|
|
66
|
+
created: State.SQLite.integer({ schema: Schema.DateFromMillis }),
|
|
67
|
+
deleted: State.SQLite.integer({ nullable: true, schema: Schema.DateFromMillis }),
|
|
68
|
+
modified: State.SQLite.integer({ schema: Schema.DateFromMillis }),
|
|
68
69
|
kanbanorder: State.SQLite.text({ nullable: false, default: '' }),
|
|
69
70
|
},
|
|
70
71
|
indexes: [
|
|
@@ -73,360 +74,377 @@ const issue = State.SQLite.table({
|
|
|
73
74
|
],
|
|
74
75
|
})
|
|
75
76
|
|
|
76
|
-
const
|
|
77
|
+
const selections = State.SQLite.table({
|
|
78
|
+
name: 'selections',
|
|
79
|
+
columns: {
|
|
80
|
+
id: State.SQLite.integer({ primaryKey: true }),
|
|
81
|
+
group: State.SQLite.text({}),
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
const Source = Schema.Literals(['google', 'linkedin', 'facebook'])
|
|
86
|
+
const ProfileAttribute = Schema.Struct({ key: Schema.String, value: Schema.String })
|
|
77
87
|
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
const personProfiles = State.SQLite.table({
|
|
89
|
+
name: 'person_profiles',
|
|
90
|
+
columns: {
|
|
91
|
+
personId: State.SQLite.text({ primaryKey: true }),
|
|
92
|
+
sources: State.SQLite.json({ schema: Schema.Array(Source), default: [] }),
|
|
93
|
+
tags: State.SQLite.json({ schema: Schema.Array(Schema.String), default: [] }),
|
|
94
|
+
attributes: State.SQLite.json({ schema: Schema.Array(ProfileAttribute), default: [] }),
|
|
95
|
+
/** Nullable JSON array column for testing JSON_CONTAINS on nullable columns */
|
|
96
|
+
optionalTags: State.SQLite.json({ schema: Schema.Array(Schema.String), nullable: true }),
|
|
97
|
+
},
|
|
82
98
|
})
|
|
83
99
|
|
|
100
|
+
const db = { todos, todosWithIntId, comments, issue, selections, UiState, UiStateWithDefaultId, personProfiles }
|
|
101
|
+
|
|
84
102
|
describe('query builder', () => {
|
|
85
103
|
describe('basic queries', () => {
|
|
86
104
|
it('should handle simple SELECT queries', () => {
|
|
87
|
-
expect(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
`)
|
|
105
|
+
expect(db.todos.asSql()).toEqual({
|
|
106
|
+
bindValues: [],
|
|
107
|
+
query: "SELECT * FROM 'todos'",
|
|
108
|
+
usedTables: new Set(['todos']),
|
|
109
|
+
})
|
|
94
110
|
|
|
95
|
-
expect(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
`)
|
|
111
|
+
expect(db.todos.select('id').asSql()).toEqual({
|
|
112
|
+
bindValues: [],
|
|
113
|
+
query: 'SELECT "id" FROM \'todos\'',
|
|
114
|
+
usedTables: new Set(['todos']),
|
|
115
|
+
})
|
|
102
116
|
|
|
103
|
-
expect(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
expect(db.todos.select('id', 'text').asSql()).toEqual({
|
|
118
|
+
bindValues: [],
|
|
119
|
+
query: 'SELECT "id", "text" FROM \'todos\'',
|
|
120
|
+
usedTables: new Set(['todos']),
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('derives result schemas for SELECT queries', async () => {
|
|
125
|
+
const selectedRows = new TestSchema.Asserts(getResultSchema(db.todos.select('id', 'text')))
|
|
126
|
+
await selectedRows.decoding().succeed([{ id: '123', text: 'Buy milk' }])
|
|
127
|
+
|
|
128
|
+
const selectedColumn = new TestSchema.Asserts(getResultSchema(db.todos.select('id')))
|
|
129
|
+
await selectedColumn.decoding().succeed([{ id: '123' }], ['123'])
|
|
110
130
|
})
|
|
111
131
|
|
|
112
132
|
it('should handle .first()', () => {
|
|
113
|
-
expect(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{
|
|
125
|
-
"bindValues": [
|
|
126
|
-
1,
|
|
127
|
-
],
|
|
128
|
-
"query": "SELECT id, text FROM 'todos' LIMIT ?",
|
|
129
|
-
"schema": "(ReadonlyArray<{ readonly id: string; readonly text: string }> <-> { readonly id: string; readonly text: string })",
|
|
130
|
-
}
|
|
131
|
-
`)
|
|
133
|
+
expect(db.todos.select('id', 'text').first().asSql()).toEqual({
|
|
134
|
+
bindValues: [1],
|
|
135
|
+
query: 'SELECT "id", "text" FROM \'todos\' LIMIT ?',
|
|
136
|
+
usedTables: new Set(['todos']),
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
expect(db.todos.select('id', 'text').first({ behaviour: 'error' }).asSql()).toEqual({
|
|
140
|
+
bindValues: [1],
|
|
141
|
+
query: 'SELECT "id", "text" FROM \'todos\' LIMIT ?',
|
|
142
|
+
usedTables: new Set(['todos']),
|
|
143
|
+
})
|
|
132
144
|
|
|
133
145
|
expect(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
146
|
+
db.todos
|
|
147
|
+
.select('id', 'text')
|
|
148
|
+
.first({ behaviour: 'fallback', fallback: () => undefined })
|
|
149
|
+
.asSql(),
|
|
150
|
+
).toEqual({
|
|
151
|
+
bindValues: [1],
|
|
152
|
+
query: 'SELECT "id", "text" FROM \'todos\' LIMIT ?',
|
|
153
|
+
usedTables: new Set(['todos']),
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('derives result schemas for .first()', async () => {
|
|
158
|
+
const firstOrUndefined = new TestSchema.Asserts(getResultSchema(db.todos.select('id', 'text').first()))
|
|
159
|
+
await firstOrUndefined.decoding().succeed([], undefined)
|
|
160
|
+
await firstOrUndefined.decoding().succeed([{ id: '123', text: 'Buy milk' }], { id: '123', text: 'Buy milk' })
|
|
161
|
+
|
|
162
|
+
const firstOrError = new TestSchema.Asserts(
|
|
163
|
+
getResultSchema(db.todos.select('id', 'text').first({ behaviour: 'error' })),
|
|
164
|
+
)
|
|
165
|
+
await firstOrError.decoding().succeed([{ id: '123', text: 'Buy milk' }], { id: '123', text: 'Buy milk' })
|
|
166
|
+
await firstOrError.decoding().fail([], 'Unable to retrieve the first element of an empty array')
|
|
167
|
+
|
|
168
|
+
const firstOrFallback = new TestSchema.Asserts(
|
|
169
|
+
getResultSchema(db.todos.select('id', 'text').first({ behaviour: 'fallback', fallback: () => undefined })),
|
|
170
|
+
)
|
|
171
|
+
await firstOrFallback.decoding().succeed([], undefined)
|
|
144
172
|
})
|
|
145
173
|
|
|
146
174
|
it('should handle WHERE clauses', () => {
|
|
147
|
-
expect(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
"bindValues": [
|
|
168
|
-
1,
|
|
169
|
-
],
|
|
170
|
-
"query": "SELECT id, text FROM 'todos' WHERE completed = ?",
|
|
171
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
172
|
-
}
|
|
173
|
-
`)
|
|
174
|
-
expect(dump(db.todos.select('id', 'text').where({ completed: undefined }))).toMatchInlineSnapshot(`
|
|
175
|
-
{
|
|
176
|
-
"bindValues": [],
|
|
177
|
-
"query": "SELECT id, text FROM 'todos'",
|
|
178
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
179
|
-
}
|
|
180
|
-
`)
|
|
175
|
+
expect(db.todos.select('id', 'text').where('completed', true).asSql()).toEqual({
|
|
176
|
+
bindValues: [1],
|
|
177
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" = ?',
|
|
178
|
+
usedTables: new Set(['todos']),
|
|
179
|
+
})
|
|
180
|
+
expect(db.todos.select('id', 'text').where('completed', '!=', true).asSql()).toEqual({
|
|
181
|
+
bindValues: [1],
|
|
182
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" != ?',
|
|
183
|
+
usedTables: new Set(['todos']),
|
|
184
|
+
})
|
|
185
|
+
expect(db.todos.select('id', 'text').where({ completed: true }).asSql()).toEqual({
|
|
186
|
+
bindValues: [1],
|
|
187
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" = ?',
|
|
188
|
+
usedTables: new Set(['todos']),
|
|
189
|
+
})
|
|
190
|
+
expect(db.todos.select('id', 'text').where({ completed: undefined }).asSql()).toEqual({
|
|
191
|
+
bindValues: [],
|
|
192
|
+
query: 'SELECT "id", "text" FROM \'todos\'',
|
|
193
|
+
usedTables: new Set(['todos']),
|
|
194
|
+
})
|
|
181
195
|
expect(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
{
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
`)
|
|
196
|
+
db.todos
|
|
197
|
+
.select('id', 'text')
|
|
198
|
+
.where({ deletedAt: { op: '<=', value: new Date('2024-01-01') } })
|
|
199
|
+
.asSql(),
|
|
200
|
+
).toEqual({
|
|
201
|
+
bindValues: ['2024-01-01T00:00:00.000Z'],
|
|
202
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "deletedAt" <= ?',
|
|
203
|
+
usedTables: new Set(['todos']),
|
|
204
|
+
})
|
|
192
205
|
expect(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
{
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
`)
|
|
206
|
+
db.todos
|
|
207
|
+
.select('id', 'text')
|
|
208
|
+
.where({ status: { op: 'IN', value: ['active'] } })
|
|
209
|
+
.asSql(),
|
|
210
|
+
).toEqual({
|
|
211
|
+
bindValues: ['active'],
|
|
212
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "status" IN (?)',
|
|
213
|
+
usedTables: new Set(['todos']),
|
|
214
|
+
})
|
|
203
215
|
expect(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
{
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
`)
|
|
216
|
+
db.todos
|
|
217
|
+
.select('id', 'text')
|
|
218
|
+
.where({ status: { op: 'NOT IN', value: ['active', 'completed'] } })
|
|
219
|
+
.asSql(),
|
|
220
|
+
).toEqual({
|
|
221
|
+
bindValues: ['active', 'completed'],
|
|
222
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "status" NOT IN (?, ?)',
|
|
223
|
+
usedTables: new Set(['todos']),
|
|
224
|
+
})
|
|
215
225
|
|
|
216
226
|
expect(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
"active",
|
|
229
|
-
],
|
|
230
|
-
"query": "SELECT id, text FROM 'todos' WHERE completed = ? AND status IN (?)",
|
|
231
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
232
|
-
}
|
|
233
|
-
`)
|
|
227
|
+
db.todos
|
|
228
|
+
.select('id', 'text')
|
|
229
|
+
.where({ completed: false })
|
|
230
|
+
.where({ status: { op: 'IN', value: ['active'] } })
|
|
231
|
+
.where({ deletedAt: undefined })
|
|
232
|
+
.asSql(),
|
|
233
|
+
).toEqual({
|
|
234
|
+
bindValues: [0, 'active'],
|
|
235
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" = ? AND "status" IN (?)',
|
|
236
|
+
usedTables: new Set(['todos']),
|
|
237
|
+
})
|
|
234
238
|
})
|
|
235
239
|
|
|
236
240
|
it('should handle OFFSET and LIMIT clauses', () => {
|
|
237
|
-
expect(
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
10,
|
|
243
|
-
],
|
|
244
|
-
"query": "SELECT id, text FROM 'todos' WHERE completed = ? OFFSET ? LIMIT ?",
|
|
245
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
246
|
-
}
|
|
247
|
-
`)
|
|
241
|
+
expect(db.todos.select('id', 'text').where('completed', true).offset(10).limit(10).asSql()).toEqual({
|
|
242
|
+
bindValues: [1, 10, 10],
|
|
243
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" = ? LIMIT ? OFFSET ?',
|
|
244
|
+
usedTables: new Set(['todos']),
|
|
245
|
+
})
|
|
248
246
|
})
|
|
249
247
|
|
|
250
248
|
it('should handle OFFSET and LIMIT clauses correctly', () => {
|
|
251
249
|
// Test with both offset and limit
|
|
252
|
-
expect(
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
10,
|
|
258
|
-
],
|
|
259
|
-
"query": "SELECT id, text FROM 'todos' WHERE completed = ? OFFSET ? LIMIT ?",
|
|
260
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
261
|
-
}
|
|
262
|
-
`)
|
|
250
|
+
expect(db.todos.select('id', 'text').where('completed', true).offset(5).limit(10).asSql()).toEqual({
|
|
251
|
+
bindValues: [1, 10, 5],
|
|
252
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" = ? LIMIT ? OFFSET ?',
|
|
253
|
+
usedTables: new Set(['todos']),
|
|
254
|
+
})
|
|
263
255
|
|
|
264
256
|
// Test with only offset
|
|
265
|
-
expect(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
],
|
|
271
|
-
"query": "SELECT id, text FROM 'todos' WHERE completed = ? OFFSET ?",
|
|
272
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
273
|
-
}
|
|
274
|
-
`)
|
|
257
|
+
expect(db.todos.select('id', 'text').where('completed', true).offset(5).asSql()).toEqual({
|
|
258
|
+
bindValues: [1, 5],
|
|
259
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" = ? OFFSET ?',
|
|
260
|
+
usedTables: new Set(['todos']),
|
|
261
|
+
})
|
|
275
262
|
|
|
276
263
|
// Test with only limit
|
|
277
|
-
expect(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
],
|
|
283
|
-
"query": "SELECT id, text FROM 'todos' WHERE completed = ? LIMIT ?",
|
|
284
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
285
|
-
}
|
|
286
|
-
`)
|
|
264
|
+
expect(db.todos.select('id', 'text').where('completed', true).limit(10).asSql()).toEqual({
|
|
265
|
+
bindValues: [1, 10],
|
|
266
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "completed" = ? LIMIT ?',
|
|
267
|
+
usedTables: new Set(['todos']),
|
|
268
|
+
})
|
|
287
269
|
})
|
|
288
270
|
|
|
289
271
|
it('should handle COUNT queries', () => {
|
|
290
|
-
expect(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
],
|
|
311
|
-
"query": "SELECT COUNT(*) as count FROM 'todos' WHERE completed = ?",
|
|
312
|
-
"schema": "(ReadonlyArray<({ readonly count: number } <-> number)> <-> number)",
|
|
313
|
-
}
|
|
314
|
-
`)
|
|
272
|
+
expect(db.todos.count().asSql()).toEqual({
|
|
273
|
+
bindValues: [],
|
|
274
|
+
query: "SELECT COUNT(*) as count FROM 'todos'",
|
|
275
|
+
usedTables: new Set(['todos']),
|
|
276
|
+
})
|
|
277
|
+
expect(db.todos.count().where('completed', true).asSql()).toEqual({
|
|
278
|
+
bindValues: [1],
|
|
279
|
+
query: 'SELECT COUNT(*) as count FROM \'todos\' WHERE "completed" = ?',
|
|
280
|
+
usedTables: new Set(['todos']),
|
|
281
|
+
})
|
|
282
|
+
expect(db.todos.where('completed', true).count().asSql()).toEqual({
|
|
283
|
+
bindValues: [1],
|
|
284
|
+
query: 'SELECT COUNT(*) as count FROM \'todos\' WHERE "completed" = ?',
|
|
285
|
+
usedTables: new Set(['todos']),
|
|
286
|
+
})
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
it('derives result schemas for COUNT queries', async () => {
|
|
290
|
+
const countResult = new TestSchema.Asserts(getResultSchema(db.todos.count()))
|
|
291
|
+
await countResult.decoding().succeed([{ count: 3 }], 3)
|
|
315
292
|
})
|
|
316
293
|
|
|
317
294
|
it('should handle NULL comparisons', () => {
|
|
318
|
-
expect(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
"query": "SELECT id, text FROM 'todos' WHERE deletedAt IS NOT NULL",
|
|
329
|
-
"schema": "ReadonlyArray<{ readonly id: string; readonly text: string }>",
|
|
330
|
-
}
|
|
331
|
-
`)
|
|
295
|
+
expect(db.todos.select('id', 'text').where('deletedAt', '=', null).asSql()).toEqual({
|
|
296
|
+
bindValues: [],
|
|
297
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "deletedAt" IS NULL',
|
|
298
|
+
usedTables: new Set(['todos']),
|
|
299
|
+
})
|
|
300
|
+
expect(db.todos.select('id', 'text').where('deletedAt', '!=', null).asSql()).toEqual({
|
|
301
|
+
bindValues: [],
|
|
302
|
+
query: 'SELECT "id", "text" FROM \'todos\' WHERE "deletedAt" IS NOT NULL',
|
|
303
|
+
usedTables: new Set(['todos']),
|
|
304
|
+
})
|
|
332
305
|
})
|
|
333
306
|
|
|
334
307
|
it('should handle orderBy', () => {
|
|
335
|
-
expect(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
`)
|
|
308
|
+
expect(db.todos.orderBy('completed', 'desc').asSql()).toEqual({
|
|
309
|
+
bindValues: [],
|
|
310
|
+
query: 'SELECT * FROM \'todos\' ORDER BY "completed" desc',
|
|
311
|
+
usedTables: new Set(['todos']),
|
|
312
|
+
})
|
|
342
313
|
|
|
343
|
-
expect(
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
314
|
+
expect(db.todos.orderBy([{ col: 'completed', direction: 'desc' }]).asSql()).toEqual({
|
|
315
|
+
bindValues: [],
|
|
316
|
+
query: 'SELECT * FROM \'todos\' ORDER BY "completed" desc',
|
|
317
|
+
usedTables: new Set(['todos']),
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
expect(db.todos.orderBy([]).asSql()).toEqual({
|
|
321
|
+
bindValues: [],
|
|
322
|
+
query: "SELECT * FROM 'todos'",
|
|
323
|
+
usedTables: new Set(['todos']),
|
|
324
|
+
})
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
it('should handle JSON_CONTAINS operator for JSON array columns', () => {
|
|
328
|
+
expect(db.personProfiles.where({ sources: { op: 'JSON_CONTAINS', value: 'google' } }).asSql()).toEqual({
|
|
329
|
+
bindValues: ['google'],
|
|
330
|
+
query: 'SELECT * FROM \'person_profiles\' WHERE EXISTS (SELECT 1 FROM json_each("sources") WHERE value = ?)',
|
|
331
|
+
usedTables: new Set(['person_profiles']),
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
// With select
|
|
335
|
+
expect(
|
|
336
|
+
db.personProfiles
|
|
337
|
+
.select('personId')
|
|
338
|
+
.where({ sources: { op: 'JSON_CONTAINS', value: 'linkedin' } })
|
|
339
|
+
.asSql(),
|
|
340
|
+
).toEqual({
|
|
341
|
+
bindValues: ['linkedin'],
|
|
342
|
+
query:
|
|
343
|
+
'SELECT "personId" FROM \'person_profiles\' WHERE EXISTS (SELECT 1 FROM json_each("sources") WHERE value = ?)',
|
|
344
|
+
usedTables: new Set(['person_profiles']),
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
// With plain string array column
|
|
348
|
+
expect(db.personProfiles.where({ tags: { op: 'JSON_CONTAINS', value: 'important' } }).asSql()).toEqual({
|
|
349
|
+
bindValues: ['important'],
|
|
350
|
+
query: 'SELECT * FROM \'person_profiles\' WHERE EXISTS (SELECT 1 FROM json_each("tags") WHERE value = ?)',
|
|
351
|
+
usedTables: new Set(['person_profiles']),
|
|
352
|
+
})
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
it('should handle JSON_NOT_CONTAINS operator for JSON array columns', () => {
|
|
356
|
+
expect(db.personProfiles.where({ sources: { op: 'JSON_NOT_CONTAINS', value: 'google' } }).asSql()).toEqual({
|
|
357
|
+
bindValues: ['google'],
|
|
358
|
+
query:
|
|
359
|
+
'SELECT * FROM \'person_profiles\' WHERE NOT EXISTS (SELECT 1 FROM json_each("sources") WHERE value = ?)',
|
|
360
|
+
usedTables: new Set(['person_profiles']),
|
|
361
|
+
})
|
|
362
|
+
})
|
|
350
363
|
|
|
351
|
-
|
|
364
|
+
it('should JSON-stringify object elements for JSON_CONTAINS', () => {
|
|
365
|
+
expect(
|
|
366
|
+
db.personProfiles
|
|
367
|
+
.where({
|
|
368
|
+
attributes: { op: 'JSON_CONTAINS', value: { key: 'language', value: 'typescript' } },
|
|
369
|
+
})
|
|
370
|
+
.asSql(),
|
|
371
|
+
).toEqual({
|
|
372
|
+
bindValues: ['{"key":"language","value":"typescript"}'],
|
|
373
|
+
query: 'SELECT * FROM \'person_profiles\' WHERE EXISTS (SELECT 1 FROM json_each("attributes") WHERE value = ?)',
|
|
374
|
+
usedTables: new Set(['person_profiles']),
|
|
375
|
+
})
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
it('should handle combining JSON_CONTAINS with other WHERE clauses', () => {
|
|
379
|
+
expect(
|
|
380
|
+
db.personProfiles
|
|
381
|
+
.where({ sources: { op: 'JSON_CONTAINS', value: 'google' } })
|
|
382
|
+
.where({ sources: { op: 'JSON_NOT_CONTAINS', value: 'facebook' } })
|
|
383
|
+
.asSql(),
|
|
384
|
+
).toEqual({
|
|
385
|
+
bindValues: ['google', 'facebook'],
|
|
386
|
+
query:
|
|
387
|
+
'SELECT * FROM \'person_profiles\' WHERE EXISTS (SELECT 1 FROM json_each("sources") WHERE value = ?) AND NOT EXISTS (SELECT 1 FROM json_each("sources") WHERE value = ?)',
|
|
388
|
+
usedTables: new Set(['person_profiles']),
|
|
389
|
+
})
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
it('should handle JSON_CONTAINS on nullable JSON array columns', () => {
|
|
393
|
+
expect(db.personProfiles.where({ optionalTags: { op: 'JSON_CONTAINS', value: 'important' } }).asSql()).toEqual({
|
|
394
|
+
bindValues: ['important'],
|
|
395
|
+
query:
|
|
396
|
+
'SELECT * FROM \'person_profiles\' WHERE EXISTS (SELECT 1 FROM json_each("optionalTags") WHERE value = ?)',
|
|
397
|
+
usedTables: new Set(['person_profiles']),
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
// With JSON_NOT_CONTAINS
|
|
401
|
+
expect(db.personProfiles.where({ optionalTags: { op: 'JSON_NOT_CONTAINS', value: 'archived' } }).asSql()).toEqual(
|
|
352
402
|
{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
403
|
+
bindValues: ['archived'],
|
|
404
|
+
query:
|
|
405
|
+
'SELECT * FROM \'person_profiles\' WHERE NOT EXISTS (SELECT 1 FROM json_each("optionalTags") WHERE value = ?)',
|
|
406
|
+
usedTables: new Set(['person_profiles']),
|
|
407
|
+
},
|
|
408
|
+
)
|
|
358
409
|
})
|
|
359
|
-
})
|
|
360
410
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
// "query": "SELECT * FROM 'UiState' WHERE id = ?",
|
|
369
|
-
// "schema": "...", // TODO determine schema
|
|
370
|
-
// }
|
|
371
|
-
// `)
|
|
372
|
-
// })
|
|
373
|
-
|
|
374
|
-
// it('should handle getOrCreate queries with default id', () => {
|
|
375
|
-
// expect(dump(db.UiStateWithDefaultId.getOrCreate())).toMatchInlineSnapshot(`
|
|
376
|
-
// {
|
|
377
|
-
// "bindValues": [],
|
|
378
|
-
// "query": "SELECT * FROM 'UiState' WHERE id = ?",
|
|
379
|
-
// "schema": "...", // TODO determine schema
|
|
380
|
-
// }
|
|
381
|
-
// `)
|
|
382
|
-
// })
|
|
383
|
-
// // it('should handle row queries with numbers', () => {
|
|
384
|
-
// // expect(dump(db.todosWithIntId.getOrCreate(123, { insertValues: { status: 'active' } }))).toMatchInlineSnapshot(`
|
|
385
|
-
// // {
|
|
386
|
-
// // "bindValues": [
|
|
387
|
-
// // 123,
|
|
388
|
-
// // ],
|
|
389
|
-
// // "query": "SELECT * FROM 'todos_with_int_id' WHERE id = ?",
|
|
390
|
-
// // "schema": "...", // TODO determine schema
|
|
391
|
-
// // }
|
|
392
|
-
// // `)
|
|
393
|
-
// // })
|
|
394
|
-
// })
|
|
411
|
+
it('should throw error when using JSON_CONTAINS on non-JSON array column', () => {
|
|
412
|
+
expect(() =>
|
|
413
|
+
// Type system prevents this at compile time for non-array columns, but test runtime check
|
|
414
|
+
db.todos.where({ status: { op: 'JSON_CONTAINS', value: 'active' } } as any).asSql(),
|
|
415
|
+
).toThrow('JSON_CONTAINS operator can only be used on JSON array columns')
|
|
416
|
+
})
|
|
417
|
+
})
|
|
395
418
|
|
|
396
419
|
describe('write operations', () => {
|
|
397
420
|
it('should handle INSERT queries', () => {
|
|
398
|
-
expect(
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
|
|
421
|
+
expect(db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).asSql()).toEqual({
|
|
422
|
+
bindValues: ['123', 'Buy milk', 'active'],
|
|
423
|
+
query: `INSERT INTO 'todos' ("id", "text", "status") VALUES (?, ?, ?)`,
|
|
424
|
+
usedTables: new Set(['todos']),
|
|
425
|
+
})
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
it('derives result schemas for write queries', async () => {
|
|
429
|
+
const insertResult = new TestSchema.Asserts(
|
|
430
|
+
getResultSchema(db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })),
|
|
431
|
+
)
|
|
432
|
+
await insertResult.decoding().succeed(1)
|
|
409
433
|
})
|
|
410
434
|
|
|
411
435
|
it('should handle INSERT queries with undefined values', () => {
|
|
412
|
-
expect(
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
"active",
|
|
418
|
-
],
|
|
419
|
-
"query": "INSERT INTO 'todos' (id, text, status) VALUES (?, ?, ?)",
|
|
420
|
-
"schema": "number",
|
|
421
|
-
}
|
|
422
|
-
`)
|
|
436
|
+
expect(db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).asSql()).toEqual({
|
|
437
|
+
bindValues: ['123', 'Buy milk', 'active'],
|
|
438
|
+
query: 'INSERT INTO \'todos\' ("id", "text", "status") VALUES (?, ?, ?)',
|
|
439
|
+
usedTables: new Set(['todos']),
|
|
440
|
+
})
|
|
423
441
|
})
|
|
424
442
|
|
|
425
443
|
// Test helped to catch a bindValues ordering bug
|
|
426
444
|
it('should handle INSERT queries (issue)', () => {
|
|
427
445
|
expect(
|
|
428
|
-
|
|
429
|
-
|
|
446
|
+
db.issue
|
|
447
|
+
.insert({
|
|
430
448
|
id: 1,
|
|
431
449
|
title: 'Revert the user profile page',
|
|
432
450
|
priority: 2,
|
|
@@ -434,251 +452,180 @@ describe('query builder', () => {
|
|
|
434
452
|
modified: new Date('2024-12-29T17:15:20.507Z'),
|
|
435
453
|
kanbanorder: 'a2',
|
|
436
454
|
creator: 'John Doe',
|
|
437
|
-
})
|
|
438
|
-
|
|
439
|
-
).
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
1722532520507,
|
|
446
|
-
1735492520507,
|
|
447
|
-
"a2",
|
|
448
|
-
"John Doe",
|
|
449
|
-
],
|
|
450
|
-
"query": "INSERT INTO 'issue' (id, title, priority, created, modified, kanbanorder, creator) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
451
|
-
"schema": "number",
|
|
452
|
-
}
|
|
453
|
-
`)
|
|
455
|
+
})
|
|
456
|
+
.asSql(),
|
|
457
|
+
).toEqual({
|
|
458
|
+
bindValues: [1, 'Revert the user profile page', 2, 1722532520507, 1735492520507, 'a2', 'John Doe'],
|
|
459
|
+
query:
|
|
460
|
+
'INSERT INTO \'issue\' ("id", "title", "priority", "created", "modified", "kanbanorder", "creator") VALUES (?, ?, ?, ?, ?, ?, ?)',
|
|
461
|
+
usedTables: new Set(['issue']),
|
|
462
|
+
})
|
|
454
463
|
})
|
|
455
464
|
|
|
456
465
|
it('should handle UPDATE queries', () => {
|
|
457
|
-
expect(
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
],
|
|
463
|
-
"query": "UPDATE 'todos' SET status = ? WHERE id = ?",
|
|
464
|
-
"schema": "number",
|
|
465
|
-
}
|
|
466
|
-
`)
|
|
466
|
+
expect(db.todos.update({ status: 'completed' }).where({ id: '123' }).asSql()).toEqual({
|
|
467
|
+
bindValues: ['completed', '123'],
|
|
468
|
+
query: 'UPDATE \'todos\' SET "status" = ? WHERE "id" = ?',
|
|
469
|
+
usedTables: new Set(['todos']),
|
|
470
|
+
})
|
|
467
471
|
|
|
468
472
|
// empty update set
|
|
469
|
-
expect(
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
`)
|
|
473
|
+
expect(db.todos.update({}).where({ id: '123' }).asSql()).toEqual({
|
|
474
|
+
bindValues: [],
|
|
475
|
+
query: 'SELECT 1',
|
|
476
|
+
usedTables: new Set(['todos']),
|
|
477
|
+
})
|
|
476
478
|
})
|
|
477
479
|
|
|
478
480
|
it('should handle UPDATE queries with undefined values', () => {
|
|
479
|
-
expect(
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
],
|
|
485
|
-
"query": "UPDATE 'todos' SET text = ? WHERE id = ?",
|
|
486
|
-
"schema": "number",
|
|
487
|
-
}
|
|
488
|
-
`)
|
|
481
|
+
expect(db.todos.update({ text: 'some text' }).where({ id: '123' }).asSql()).toEqual({
|
|
482
|
+
bindValues: ['some text', '123'],
|
|
483
|
+
query: 'UPDATE \'todos\' SET "text" = ? WHERE "id" = ?',
|
|
484
|
+
usedTables: new Set(['todos']),
|
|
485
|
+
})
|
|
489
486
|
})
|
|
490
487
|
|
|
491
488
|
it('should handle UPDATE queries with undefined values (issue)', () => {
|
|
492
|
-
expect(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
1,
|
|
498
|
-
],
|
|
499
|
-
"query": "UPDATE 'issue' SET priority = ?, creator = ? WHERE id = ?",
|
|
500
|
-
"schema": "number",
|
|
501
|
-
}
|
|
502
|
-
`)
|
|
489
|
+
expect(db.issue.update({ priority: 2, creator: 'John Doe' }).where({ id: 1 }).asSql()).toEqual({
|
|
490
|
+
bindValues: [2, 'John Doe', 1],
|
|
491
|
+
query: 'UPDATE \'issue\' SET "priority" = ?, "creator" = ? WHERE "id" = ?',
|
|
492
|
+
usedTables: new Set(['issue']),
|
|
493
|
+
})
|
|
503
494
|
})
|
|
504
495
|
|
|
505
496
|
it('should handle DELETE queries', () => {
|
|
506
|
-
expect(
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
"query": "DELETE FROM 'todos' WHERE status = ?",
|
|
512
|
-
"schema": "number",
|
|
513
|
-
}
|
|
514
|
-
`)
|
|
497
|
+
expect(db.todos.delete().where({ status: 'completed' }).asSql()).toEqual({
|
|
498
|
+
bindValues: ['completed'],
|
|
499
|
+
query: 'DELETE FROM \'todos\' WHERE "status" = ?',
|
|
500
|
+
usedTables: new Set(['todos']),
|
|
501
|
+
})
|
|
515
502
|
})
|
|
516
503
|
|
|
517
504
|
it('should handle INSERT with ON CONFLICT', () => {
|
|
518
505
|
expect(
|
|
519
|
-
|
|
520
|
-
).
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
"active",
|
|
526
|
-
],
|
|
527
|
-
"query": "INSERT INTO 'todos' (id, text, status) VALUES (?, ?, ?) ON CONFLICT (id) DO NOTHING",
|
|
528
|
-
"schema": "number",
|
|
529
|
-
}
|
|
530
|
-
`)
|
|
506
|
+
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'ignore').asSql(),
|
|
507
|
+
).toEqual({
|
|
508
|
+
bindValues: ['123', 'Buy milk', 'active'],
|
|
509
|
+
query: 'INSERT INTO \'todos\' ("id", "text", "status") VALUES (?, ?, ?) ON CONFLICT ("id") DO NOTHING',
|
|
510
|
+
usedTables: new Set(['todos']),
|
|
511
|
+
})
|
|
531
512
|
|
|
532
513
|
expect(
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
"
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
"active",
|
|
544
|
-
"Buy soy milk",
|
|
545
|
-
"active",
|
|
546
|
-
],
|
|
547
|
-
"query": "INSERT INTO 'todos' (id, text, status) VALUES (?, ?, ?) ON CONFLICT (id) DO UPDATE SET text = ?, status = ?",
|
|
548
|
-
"schema": "number",
|
|
549
|
-
}
|
|
550
|
-
`)
|
|
514
|
+
db.todos
|
|
515
|
+
.insert({ id: '123', text: 'Buy milk', status: 'active' })
|
|
516
|
+
.onConflict('id', 'update', { text: 'Buy soy milk', status: 'active' })
|
|
517
|
+
.asSql(),
|
|
518
|
+
).toEqual({
|
|
519
|
+
bindValues: ['123', 'Buy milk', 'active', 'Buy soy milk', 'active'],
|
|
520
|
+
query:
|
|
521
|
+
'INSERT INTO \'todos\' ("id", "text", "status") VALUES (?, ?, ?) ON CONFLICT ("id") DO UPDATE SET "text" = ?, "status" = ?',
|
|
522
|
+
usedTables: new Set(['todos']),
|
|
523
|
+
})
|
|
551
524
|
|
|
552
525
|
expect(
|
|
553
|
-
|
|
554
|
-
).
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
526
|
+
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'replace').asSql(),
|
|
527
|
+
).toEqual({
|
|
528
|
+
bindValues: ['123', 'Buy milk', 'active'],
|
|
529
|
+
query: 'INSERT OR REPLACE INTO \'todos\' ("id", "text", "status") VALUES (?, ?, ?)',
|
|
530
|
+
usedTables: new Set(['todos']),
|
|
531
|
+
})
|
|
532
|
+
})
|
|
533
|
+
|
|
534
|
+
it('should quote reserved column names', () => {
|
|
535
|
+
expect(db.selections.insert({ id: 1, group: 'alpha' }).onConflict('id', 'ignore').asSql()).toEqual({
|
|
536
|
+
bindValues: [1, 'alpha'],
|
|
537
|
+
query: 'INSERT INTO \'selections\' ("id", "group") VALUES (?, ?) ON CONFLICT ("id") DO NOTHING',
|
|
538
|
+
usedTables: new Set(['selections']),
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
expect(db.selections.update({ group: 'beta' }).where({ id: 1 }).asSql()).toEqual({
|
|
542
|
+
bindValues: ['beta', 1],
|
|
543
|
+
query: 'UPDATE \'selections\' SET "group" = ? WHERE "id" = ?',
|
|
544
|
+
usedTables: new Set(['selections']),
|
|
545
|
+
})
|
|
565
546
|
})
|
|
566
547
|
|
|
567
548
|
it('should handle ON CONFLICT with multiple columns', () => {
|
|
568
549
|
expect(
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
580
|
-
`)
|
|
550
|
+
db.todos
|
|
551
|
+
.insert({ id: '123', text: 'Buy milk', status: 'active' })
|
|
552
|
+
.onConflict(['id', 'status'], 'ignore')
|
|
553
|
+
.asSql(),
|
|
554
|
+
).toEqual({
|
|
555
|
+
bindValues: ['123', 'Buy milk', 'active'],
|
|
556
|
+
query:
|
|
557
|
+
'INSERT INTO \'todos\' ("id", "text", "status") VALUES (?, ?, ?) ON CONFLICT ("id", "status") DO NOTHING',
|
|
558
|
+
usedTables: new Set(['todos']),
|
|
559
|
+
})
|
|
581
560
|
})
|
|
582
561
|
|
|
583
562
|
it('should handle RETURNING clause', () => {
|
|
584
|
-
expect(
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
"123",
|
|
590
|
-
"Buy milk",
|
|
591
|
-
"active",
|
|
592
|
-
],
|
|
593
|
-
"query": "INSERT INTO 'todos' (id, text, status) VALUES (?, ?, ?) RETURNING id",
|
|
594
|
-
"schema": "ReadonlyArray<{ readonly id: string }>",
|
|
595
|
-
}
|
|
596
|
-
`)
|
|
563
|
+
expect(db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).returning('id').asSql()).toEqual({
|
|
564
|
+
bindValues: ['123', 'Buy milk', 'active'],
|
|
565
|
+
query: 'INSERT INTO \'todos\' ("id", "text", "status") VALUES (?, ?, ?) RETURNING "id"',
|
|
566
|
+
usedTables: new Set(['todos']),
|
|
567
|
+
})
|
|
597
568
|
|
|
598
|
-
expect(
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
"query": "DELETE FROM 'todos' WHERE status = ? RETURNING id",
|
|
617
|
-
"schema": "ReadonlyArray<{ readonly id: string }>",
|
|
618
|
-
}
|
|
619
|
-
`)
|
|
569
|
+
expect(db.todos.update({ status: 'completed' }).where({ id: '123' }).returning('id').asSql()).toEqual({
|
|
570
|
+
bindValues: ['completed', '123'],
|
|
571
|
+
query: 'UPDATE \'todos\' SET "status" = ? WHERE "id" = ? RETURNING "id"',
|
|
572
|
+
usedTables: new Set(['todos']),
|
|
573
|
+
})
|
|
574
|
+
|
|
575
|
+
expect(db.todos.delete().where({ status: 'completed' }).returning('id').asSql()).toEqual({
|
|
576
|
+
bindValues: ['completed'],
|
|
577
|
+
query: 'DELETE FROM \'todos\' WHERE "status" = ? RETURNING "id"',
|
|
578
|
+
usedTables: new Set(['todos']),
|
|
579
|
+
})
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
it('derives result schemas for RETURNING clauses', async () => {
|
|
583
|
+
const returningId = new TestSchema.Asserts(
|
|
584
|
+
getResultSchema(db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).returning('id')),
|
|
585
|
+
)
|
|
586
|
+
await returningId.decoding().succeed([{ id: '123' }])
|
|
620
587
|
})
|
|
621
588
|
|
|
622
589
|
it('should handle where().delete() - preserving where clauses', () => {
|
|
623
|
-
expect(
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
"query": "DELETE FROM 'todos' WHERE status = ?",
|
|
629
|
-
"schema": "number",
|
|
630
|
-
}
|
|
631
|
-
`)
|
|
590
|
+
expect(db.todos.where({ status: 'completed' }).delete().asSql()).toEqual({
|
|
591
|
+
bindValues: ['completed'],
|
|
592
|
+
query: 'DELETE FROM \'todos\' WHERE "status" = ?',
|
|
593
|
+
usedTables: new Set(['todos']),
|
|
594
|
+
})
|
|
632
595
|
|
|
633
596
|
// Multiple where clauses
|
|
634
|
-
expect(
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
"query": "DELETE FROM 'todos' WHERE status = ? AND deletedAt IS NULL",
|
|
640
|
-
"schema": "number",
|
|
641
|
-
}
|
|
642
|
-
`)
|
|
597
|
+
expect(db.todos.where({ status: 'completed' }).where({ deletedAt: null }).delete().asSql()).toEqual({
|
|
598
|
+
bindValues: ['completed'],
|
|
599
|
+
query: 'DELETE FROM \'todos\' WHERE "status" = ? AND "deletedAt" IS NULL',
|
|
600
|
+
usedTables: new Set(['todos']),
|
|
601
|
+
})
|
|
643
602
|
})
|
|
644
603
|
|
|
645
604
|
it('should handle where().update() - preserving where clauses', () => {
|
|
646
|
-
expect(
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
],
|
|
652
|
-
"query": "UPDATE 'todos' SET status = ? WHERE id = ?",
|
|
653
|
-
"schema": "number",
|
|
654
|
-
}
|
|
655
|
-
`)
|
|
605
|
+
expect(db.todos.where({ id: '123' }).update({ status: 'completed' }).asSql()).toEqual({
|
|
606
|
+
bindValues: ['completed', '123'],
|
|
607
|
+
query: 'UPDATE \'todos\' SET "status" = ? WHERE "id" = ?',
|
|
608
|
+
usedTables: new Set(['todos']),
|
|
609
|
+
})
|
|
656
610
|
|
|
657
611
|
// Multiple where clauses
|
|
658
|
-
expect(
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
"completed",
|
|
664
|
-
"123",
|
|
665
|
-
],
|
|
666
|
-
"query": "UPDATE 'todos' SET status = ? WHERE id = ? AND deletedAt IS NULL",
|
|
667
|
-
"schema": "number",
|
|
668
|
-
}
|
|
669
|
-
`)
|
|
612
|
+
expect(db.todos.where({ id: '123' }).where({ deletedAt: null }).update({ status: 'completed' }).asSql()).toEqual({
|
|
613
|
+
bindValues: ['completed', '123'],
|
|
614
|
+
query: 'UPDATE \'todos\' SET "status" = ? WHERE "id" = ? AND "deletedAt" IS NULL',
|
|
615
|
+
usedTables: new Set(['todos']),
|
|
616
|
+
})
|
|
670
617
|
})
|
|
671
618
|
|
|
672
619
|
it('should have equivalent behavior for both delete patterns', () => {
|
|
673
|
-
const pattern1 =
|
|
674
|
-
const pattern2 =
|
|
620
|
+
const pattern1 = db.todos.where({ status: 'completed', id: '123' }).delete().asSql()
|
|
621
|
+
const pattern2 = db.todos.delete().where({ status: 'completed', id: '123' }).asSql()
|
|
675
622
|
|
|
676
623
|
expect(pattern1).toEqual(pattern2)
|
|
677
624
|
})
|
|
678
625
|
|
|
679
626
|
it('should have equivalent behavior for both update patterns', () => {
|
|
680
|
-
const pattern1 =
|
|
681
|
-
const pattern2 =
|
|
627
|
+
const pattern1 = db.todos.where({ id: '123' }).update({ status: 'completed', text: 'Updated' }).asSql()
|
|
628
|
+
const pattern2 = db.todos.update({ status: 'completed', text: 'Updated' }).where({ id: '123' }).asSql()
|
|
682
629
|
|
|
683
630
|
expect(pattern1).toEqual(pattern2)
|
|
684
631
|
})
|
|
@@ -692,32 +639,33 @@ describe('query builder', () => {
|
|
|
692
639
|
contactEmail: Schema.String.pipe(State.SQLite.withUnique),
|
|
693
640
|
})
|
|
694
641
|
|
|
695
|
-
const Nested =
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
}),
|
|
705
|
-
{
|
|
706
|
-
decode: ({ id, contactFirstName, contactLastName, contactEmail }) => ({
|
|
707
|
-
id,
|
|
708
|
-
contact: {
|
|
709
|
-
firstName: contactFirstName,
|
|
710
|
-
lastName: contactLastName,
|
|
711
|
-
email: contactEmail,
|
|
712
|
-
},
|
|
642
|
+
const Nested = Flat.pipe(
|
|
643
|
+
Schema.decodeTo(
|
|
644
|
+
Schema.Struct({
|
|
645
|
+
id: Schema.String,
|
|
646
|
+
contact: Schema.Struct({
|
|
647
|
+
firstName: Schema.String,
|
|
648
|
+
lastName: Schema.String,
|
|
649
|
+
email: Schema.String,
|
|
650
|
+
}),
|
|
713
651
|
}),
|
|
714
|
-
|
|
715
|
-
id,
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
652
|
+
SchemaTransformation.transform({
|
|
653
|
+
decode: ({ id, contactFirstName, contactLastName, contactEmail }) => ({
|
|
654
|
+
id,
|
|
655
|
+
contact: {
|
|
656
|
+
firstName: contactFirstName,
|
|
657
|
+
lastName: contactLastName,
|
|
658
|
+
email: contactEmail,
|
|
659
|
+
},
|
|
660
|
+
}),
|
|
661
|
+
encode: ({ id, contact }) => ({
|
|
662
|
+
id,
|
|
663
|
+
contactFirstName: contact.firstName,
|
|
664
|
+
contactLastName: contact.lastName,
|
|
665
|
+
contactEmail: contact.email,
|
|
666
|
+
}),
|
|
719
667
|
}),
|
|
720
|
-
|
|
668
|
+
),
|
|
721
669
|
)
|
|
722
670
|
|
|
723
671
|
const makeContactsTable = () =>
|
|
@@ -731,7 +679,7 @@ describe('query builder', () => {
|
|
|
731
679
|
const contactsTable = makeContactsTable()
|
|
732
680
|
|
|
733
681
|
type InsertInput = Parameters<(typeof contactsTable)['insert']>[0]
|
|
734
|
-
type NestedType =
|
|
682
|
+
type NestedType = (typeof Nested)['Type']
|
|
735
683
|
|
|
736
684
|
type Assert<T extends true> = T
|
|
737
685
|
|
|
@@ -755,7 +703,7 @@ describe('query builder', () => {
|
|
|
755
703
|
void contactsTable
|
|
756
704
|
})
|
|
757
705
|
|
|
758
|
-
it('
|
|
706
|
+
it('encodes flat insert values for transformed schemas', () => {
|
|
759
707
|
const contactsTable = makeContactsTable()
|
|
760
708
|
|
|
761
709
|
expect(
|
|
@@ -768,23 +716,15 @@ describe('query builder', () => {
|
|
|
768
716
|
contactEmail: 'ada@example.com',
|
|
769
717
|
})
|
|
770
718
|
.asSql(),
|
|
771
|
-
).
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
"usedTables": Set {
|
|
781
|
-
"contacts",
|
|
782
|
-
},
|
|
783
|
-
}
|
|
784
|
-
`)
|
|
785
|
-
})
|
|
786
|
-
|
|
787
|
-
it('fails to encode nested inserts because flat columns are required', () => {
|
|
719
|
+
).toEqual({
|
|
720
|
+
bindValues: ['person-1', 'Ada', 'Lovelace', 'ada@example.com'],
|
|
721
|
+
query:
|
|
722
|
+
'INSERT INTO \'contacts\' ("id", "contactFirstName", "contactLastName", "contactEmail") VALUES (?, ?, ?, ?)',
|
|
723
|
+
usedTables: new Set(['contacts']),
|
|
724
|
+
})
|
|
725
|
+
})
|
|
726
|
+
|
|
727
|
+
it('rejects nested insert values because flat columns are required', () => {
|
|
788
728
|
const contactsTable = makeContactsTable()
|
|
789
729
|
|
|
790
730
|
expect(() =>
|
|
@@ -799,15 +739,13 @@ describe('query builder', () => {
|
|
|
799
739
|
},
|
|
800
740
|
})
|
|
801
741
|
.asSql(),
|
|
802
|
-
).
|
|
803
|
-
[ParseError: contacts\n└─ ["contactFirstName"]\n └─ is missing]
|
|
804
|
-
`)
|
|
742
|
+
).toThrowError(/contactFirstName/)
|
|
805
743
|
})
|
|
806
744
|
})
|
|
807
745
|
})
|
|
808
746
|
|
|
809
747
|
// TODO nested queries
|
|
810
|
-
// const rawSql = <A, I>(sql: string, params: { [key: string]: any }, schema: Schema.
|
|
748
|
+
// const rawSql = <A, I>(sql: string, params: { [key: string]: any }, schema: Schema.Codec<A, I>) =>
|
|
811
749
|
// ({
|
|
812
750
|
// sql,
|
|
813
751
|
// params,
|