@livestore/common 0.4.0-dev.2 → 0.4.0-dev.20
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 +17 -12
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
- package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
- package/dist/adapter-types.d.ts +14 -6
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js.map +1 -1
- package/dist/debug-info.d.ts.map +1 -1
- package/dist/debug-info.js +33 -6
- package/dist/debug-info.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +28 -23
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +2 -2
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +7 -14
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +1 -6
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +36 -29
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +8 -8
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/devtools/devtools-sessioninfo.d.ts +14 -2
- package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
- package/dist/devtools/devtools-sessioninfo.js +7 -4
- package/dist/devtools/devtools-sessioninfo.js.map +1 -1
- package/dist/devtools/mod.d.ts +13 -2
- package/dist/devtools/mod.d.ts.map +1 -1
- package/dist/devtools/mod.js +10 -3
- package/dist/devtools/mod.js.map +1 -1
- package/dist/errors.d.ts +52 -10
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +25 -6
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +8 -4
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +156 -73
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts +15 -21
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +18 -18
- package/dist/leader-thread/eventlog.js.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.d.ts +2 -2
- package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
- package/dist/leader-thread/leader-worker-devtools.js +30 -42
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +6 -6
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +79 -27
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.test.d.ts +2 -0
- package/dist/leader-thread/make-leader-thread-layer.test.d.ts.map +1 -0
- package/dist/leader-thread/make-leader-thread-layer.test.js +32 -0
- package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -0
- package/dist/leader-thread/materialize-event.d.ts +3 -3
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +25 -11
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/recreate-db.d.ts +2 -3
- package/dist/leader-thread/recreate-db.d.ts.map +1 -1
- package/dist/leader-thread/recreate-db.js +5 -5
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/shutdown-channel.d.ts +2 -2
- package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
- package/dist/leader-thread/shutdown-channel.js +2 -2
- package/dist/leader-thread/shutdown-channel.js.map +1 -1
- package/dist/leader-thread/types.d.ts +21 -19
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/logging.d.ts +40 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +33 -0
- package/dist/logging.js.map +1 -0
- package/dist/make-client-session.d.ts +5 -3
- package/dist/make-client-session.d.ts.map +1 -1
- package/dist/make-client-session.js +5 -2
- package/dist/make-client-session.js.map +1 -1
- package/dist/materializer-helper.d.ts +6 -6
- package/dist/materializer-helper.d.ts.map +1 -1
- package/dist/materializer-helper.js +20 -4
- package/dist/materializer-helper.js.map +1 -1
- package/dist/rematerialize-from-eventlog.d.ts +2 -2
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +29 -20
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef/define.d.ts +147 -0
- package/dist/schema/EventDef/define.d.ts.map +1 -0
- package/dist/schema/EventDef/define.js +139 -0
- package/dist/schema/EventDef/define.js.map +1 -0
- package/dist/schema/EventDef/event-def.d.ts +106 -0
- package/dist/schema/EventDef/event-def.d.ts.map +1 -0
- package/dist/schema/EventDef/event-def.js +2 -0
- package/dist/schema/EventDef/event-def.js.map +1 -0
- package/dist/schema/EventDef/facts.d.ts +118 -0
- package/dist/schema/EventDef/facts.d.ts.map +1 -0
- package/dist/schema/EventDef/facts.js +53 -0
- package/dist/schema/EventDef/facts.js.map +1 -0
- package/dist/schema/EventDef/materializer.d.ts +155 -0
- package/dist/schema/EventDef/materializer.d.ts.map +1 -0
- package/dist/schema/EventDef/materializer.js +83 -0
- package/dist/schema/EventDef/materializer.js.map +1 -0
- package/dist/schema/EventDef/mod.d.ts +5 -0
- package/dist/schema/EventDef/mod.d.ts.map +1 -0
- package/dist/schema/EventDef/mod.js +5 -0
- package/dist/schema/EventDef/mod.js.map +1 -0
- package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
- package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/client.js +193 -0
- package/dist/schema/EventSequenceNumber/client.js.map +1 -0
- package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
- package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/global.js +14 -0
- package/dist/schema/EventSequenceNumber/global.js.map +1 -0
- package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
- package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
- package/dist/schema/EventSequenceNumber/mod.js +37 -0
- package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
- package/dist/schema/EventSequenceNumber.test.js +43 -43
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +89 -106
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
- package/dist/schema/{LiveStoreEvent.js → LiveStoreEvent/client.js} +74 -58
- package/dist/schema/LiveStoreEvent/client.js.map +1 -0
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
- package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
- package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
- package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
- package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/global.js +31 -0
- package/dist/schema/LiveStoreEvent/global.js.map +1 -0
- package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
- package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/input.js +26 -0
- package/dist/schema/LiveStoreEvent/input.js.map +1 -0
- package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
- package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
- package/dist/schema/LiveStoreEvent/mod.js +5 -0
- package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
- package/dist/schema/events.d.ts +1 -1
- package/dist/schema/events.d.ts.map +1 -1
- package/dist/schema/events.js +1 -1
- package/dist/schema/events.js.map +1 -1
- package/dist/schema/mod.d.ts +6 -4
- package/dist/schema/mod.d.ts.map +1 -1
- package/dist/schema/mod.js +5 -4
- package/dist/schema/mod.js.map +1 -1
- package/dist/schema/schema.d.ts +16 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +27 -2
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +36 -6
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +97 -6
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +16 -0
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.js +14 -6
- package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.js +69 -22
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +46 -7
- package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-spec.js +30 -12
- package/dist/schema/state/sqlite/column-spec.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.test.js +23 -14
- package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +23 -6
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +14 -8
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +5 -3
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js +2 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts +3 -3
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +3 -3
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/api.d.ts +17 -10
- package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/astToSql.js +22 -15
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +6 -3
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +252 -88
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
- package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.js +22 -12
- package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
- package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
- package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
- package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
- package/dist/schema/state/sqlite/{system-tables.d.ts → system-tables/eventlog-tables.d.ts} +63 -456
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -0
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +54 -0
- package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -0
- package/dist/schema/state/sqlite/system-tables/mod.d.ts +3 -0
- package/dist/schema/state/sqlite/system-tables/mod.d.ts.map +1 -0
- package/dist/schema/state/sqlite/system-tables/mod.js +3 -0
- package/dist/schema/state/sqlite/system-tables/mod.js.map +1 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +456 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.js +55 -0
- package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
- package/dist/schema/state/sqlite/table-def.d.ts +4 -4
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/table-def.js +2 -2
- package/dist/schema/state/sqlite/table-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +80 -0
- package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
- package/dist/schema/unknown-events.d.ts +47 -0
- package/dist/schema/unknown-events.d.ts.map +1 -0
- package/dist/schema/unknown-events.js +69 -0
- package/dist/schema/unknown-events.js.map +1 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts +2 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts.map +1 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +73 -0
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -0
- package/dist/schema-management/migrations.d.ts +32 -2
- package/dist/schema-management/migrations.d.ts.map +1 -1
- package/dist/schema-management/migrations.js +37 -5
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/schema-management/validate-schema.d.ts +3 -3
- package/dist/schema-management/validate-schema.d.ts.map +1 -1
- package/dist/schema-management/validate-schema.js +2 -2
- package/dist/schema-management/validate-schema.js.map +1 -1
- package/dist/sql-queries/sql-queries.d.ts.map +1 -1
- package/dist/sql-queries/sql-queries.js +11 -1
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
- package/dist/sql-queries/sql-query-builder.js +2 -1
- package/dist/sql-queries/sql-query-builder.js.map +1 -1
- package/dist/sqlite-types.d.ts +3 -3
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +11 -13
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +45 -42
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/errors.d.ts +66 -0
- package/dist/sync/errors.d.ts.map +1 -0
- package/dist/sync/errors.js +36 -0
- package/dist/sync/errors.js.map +1 -0
- package/dist/sync/index.d.ts +3 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +3 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/mock-sync-backend.d.ts +23 -0
- package/dist/sync/mock-sync-backend.d.ts.map +1 -0
- package/dist/sync/mock-sync-backend.js +114 -0
- package/dist/sync/mock-sync-backend.js.map +1 -0
- package/dist/sync/next/compact-events.d.ts.map +1 -1
- package/dist/sync/next/compact-events.js +6 -7
- package/dist/sync/next/compact-events.js.map +1 -1
- package/dist/sync/next/facts.d.ts +5 -5
- package/dist/sync/next/facts.d.ts.map +1 -1
- package/dist/sync/next/facts.js +1 -2
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts +54 -15
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +198 -9
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/history-dag.d.ts.map +1 -1
- package/dist/sync/next/history-dag.js +10 -8
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.d.ts +5 -5
- package/dist/sync/next/rebase-events.d.ts.map +1 -1
- package/dist/sync/next/rebase-events.js +5 -5
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/event-fixtures.d.ts +2 -2
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +9 -9
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/sync-backend-kv.d.ts +7 -0
- package/dist/sync/sync-backend-kv.d.ts.map +1 -0
- package/dist/sync/sync-backend-kv.js +18 -0
- package/dist/sync/sync-backend-kv.js.map +1 -0
- package/dist/sync/sync-backend.d.ts +105 -0
- package/dist/sync/sync-backend.d.ts.map +1 -0
- package/dist/sync/sync-backend.js +61 -0
- package/dist/sync/sync-backend.js.map +1 -0
- package/dist/sync/sync.d.ts +9 -86
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/sync.js +2 -27
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/syncstate.d.ts +57 -44
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +50 -45
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +83 -46
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/transport-chunking.d.ts +36 -0
- package/dist/sync/transport-chunking.d.ts.map +1 -0
- package/dist/sync/transport-chunking.js +56 -0
- package/dist/sync/transport-chunking.js.map +1 -0
- package/dist/sync/validate-push-payload.d.ts +2 -2
- package/dist/sync/validate-push-payload.d.ts.map +1 -1
- package/dist/sync/validate-push-payload.js +6 -6
- package/dist/sync/validate-push-payload.js.map +1 -1
- package/dist/testing/event-factory.d.ts +68 -0
- package/dist/testing/event-factory.d.ts.map +1 -0
- package/dist/testing/event-factory.js +78 -0
- package/dist/testing/event-factory.js.map +1 -0
- package/dist/testing/mod.d.ts +2 -0
- package/dist/testing/mod.d.ts.map +1 -0
- package/dist/testing/mod.js +2 -0
- package/dist/testing/mod.js.map +1 -0
- package/dist/version.d.ts +16 -6
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +16 -6
- package/dist/version.js.map +1 -1
- package/package.json +7 -8
- package/src/ClientSessionLeaderThreadProxy.ts +17 -12
- package/src/adapter-types.ts +18 -6
- package/src/debug-info.ts +37 -6
- package/src/devtools/devtools-messages-client-session.ts +2 -2
- package/src/devtools/devtools-messages-common.ts +1 -8
- package/src/devtools/devtools-messages-leader.ts +8 -8
- package/src/devtools/devtools-sessioninfo.ts +8 -5
- package/src/devtools/mod.ts +11 -2
- package/src/errors.ts +38 -11
- package/src/index.ts +2 -1
- package/src/leader-thread/LeaderSyncProcessor.ts +242 -103
- package/src/leader-thread/eventlog.ts +33 -34
- package/src/leader-thread/leader-worker-devtools.ts +50 -54
- package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
- package/src/leader-thread/make-leader-thread-layer.ts +156 -37
- package/src/leader-thread/materialize-event.ts +37 -12
- package/src/leader-thread/recreate-db.ts +15 -7
- package/src/leader-thread/shutdown-channel.ts +16 -2
- package/src/leader-thread/types.ts +21 -19
- package/src/logging.ts +62 -0
- package/src/make-client-session.ts +9 -3
- package/src/materializer-helper.ts +27 -10
- package/src/rematerialize-from-eventlog.ts +37 -27
- package/src/schema/EventDef/define.ts +201 -0
- package/src/schema/EventDef/event-def.ts +120 -0
- package/src/schema/EventDef/facts.ts +135 -0
- package/src/schema/EventDef/materializer.ts +172 -0
- package/src/schema/EventDef/mod.ts +4 -0
- package/src/schema/EventSequenceNumber/client.ts +257 -0
- package/src/schema/EventSequenceNumber/global.ts +19 -0
- package/src/schema/EventSequenceNumber/mod.ts +37 -0
- package/src/schema/EventSequenceNumber.test.ts +70 -52
- package/src/schema/LiveStoreEvent/client.ts +221 -0
- package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
- package/src/schema/LiveStoreEvent/global.ts +45 -0
- package/src/schema/LiveStoreEvent/input.ts +63 -0
- package/src/schema/LiveStoreEvent/mod.ts +4 -0
- package/src/schema/events.ts +1 -1
- package/src/schema/mod.ts +6 -4
- package/src/schema/schema.ts +39 -3
- package/src/schema/state/sqlite/client-document-def.test.ts +19 -2
- package/src/schema/state/sqlite/client-document-def.ts +120 -8
- package/src/schema/state/sqlite/column-annotations.test.ts +1 -1
- package/src/schema/state/sqlite/column-annotations.ts +16 -6
- package/src/schema/state/sqlite/column-def.test.ts +60 -7
- package/src/schema/state/sqlite/column-def.ts +88 -21
- package/src/schema/state/sqlite/column-spec.test.ts +29 -16
- package/src/schema/state/sqlite/column-spec.ts +36 -11
- package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +26 -6
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +29 -12
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +2 -1
- package/src/schema/state/sqlite/mod.ts +4 -3
- package/src/schema/state/sqlite/query-builder/api.ts +19 -10
- package/src/schema/state/sqlite/query-builder/astToSql.ts +23 -14
- package/src/schema/state/sqlite/query-builder/impl.test.ts +305 -92
- package/src/schema/state/sqlite/query-builder/impl.ts +8 -3
- package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
- package/src/schema/state/sqlite/schema-helpers.ts +28 -20
- package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +64 -0
- package/src/schema/state/sqlite/system-tables/mod.ts +2 -0
- package/src/schema/state/sqlite/system-tables/state-tables.ts +69 -0
- package/src/schema/state/sqlite/table-def.test.ts +101 -0
- package/src/schema/state/sqlite/table-def.ts +9 -8
- package/src/schema/unknown-events.ts +131 -0
- package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +86 -0
- package/src/schema-management/migrations.ts +41 -8
- package/src/schema-management/validate-schema.ts +3 -3
- package/src/sql-queries/sql-queries.ts +9 -1
- package/src/sql-queries/sql-query-builder.ts +2 -1
- package/src/sqlite-types.ts +3 -3
- package/src/sync/ClientSessionSyncProcessor.ts +69 -62
- package/src/sync/errors.ts +38 -0
- package/src/sync/index.ts +3 -0
- package/src/sync/mock-sync-backend.ts +184 -0
- package/src/sync/next/compact-events.ts +6 -7
- package/src/sync/next/facts.ts +7 -9
- package/src/sync/next/history-dag-common.ts +277 -26
- package/src/sync/next/history-dag.ts +16 -10
- package/src/sync/next/rebase-events.ts +11 -11
- package/src/sync/next/test/event-fixtures.ts +11 -11
- package/src/sync/sync-backend-kv.ts +22 -0
- package/src/sync/sync-backend.ts +185 -0
- package/src/sync/sync.ts +9 -91
- package/src/sync/syncstate.test.ts +96 -52
- package/src/sync/syncstate.ts +69 -58
- package/src/sync/transport-chunking.ts +90 -0
- package/src/sync/validate-push-payload.ts +8 -9
- package/src/testing/event-factory.ts +131 -0
- package/src/testing/mod.ts +1 -0
- package/src/version.ts +16 -6
- package/dist/schema/EventDef.d.ts +0 -123
- package/dist/schema/EventDef.d.ts.map +0 -1
- package/dist/schema/EventDef.js +0 -46
- package/dist/schema/EventDef.js.map +0 -1
- package/dist/schema/EventSequenceNumber.d.ts +0 -80
- package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
- package/dist/schema/EventSequenceNumber.js +0 -139
- package/dist/schema/EventSequenceNumber.js.map +0 -1
- package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
- package/dist/schema/LiveStoreEvent.js.map +0 -1
- package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
- package/dist/schema/state/sqlite/system-tables.js +0 -79
- package/dist/schema/state/sqlite/system-tables.js.map +0 -1
- package/dist/schema-management/migrations.test.d.ts +0 -2
- package/dist/schema-management/migrations.test.d.ts.map +0 -1
- package/dist/schema-management/migrations.test.js +0 -52
- package/dist/schema-management/migrations.test.js.map +0 -1
- package/dist/sync/next/graphology.d.ts +0 -8
- package/dist/sync/next/graphology.d.ts.map +0 -1
- package/dist/sync/next/graphology.js +0 -30
- package/dist/sync/next/graphology.js.map +0 -1
- package/dist/sync/next/graphology_.d.ts +0 -3
- package/dist/sync/next/graphology_.d.ts.map +0 -1
- package/dist/sync/next/graphology_.js +0 -3
- package/dist/sync/next/graphology_.js.map +0 -1
- package/src/schema/EventDef.ts +0 -219
- package/src/schema/EventSequenceNumber.ts +0 -199
- package/src/schema/LiveStoreEvent.ts +0 -287
- package/src/schema/state/sqlite/system-tables.ts +0 -104
- package/src/sync/next/ambient.d.ts +0 -3
- package/src/sync/next/graphology.ts +0 -41
- package/src/sync/next/graphology_.ts +0 -2
package/src/logging.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { isDevEnv } from '@livestore/utils'
|
|
2
|
+
import { Effect, type Layer, Logger, LogLevel } from '@livestore/utils/effect'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Optional Effect logger configuration that LiveStore entry points accept.
|
|
6
|
+
*
|
|
7
|
+
* When provided, `logger` replaces the default pretty logger for the runtime.
|
|
8
|
+
* Use `logLevel` to control verbosity. Set to `LogLevel.None` to disable logging
|
|
9
|
+
* entirely while keeping the same logger implementation.
|
|
10
|
+
*/
|
|
11
|
+
export type WithLoggerOptions = {
|
|
12
|
+
/** Optional Effect logger layer to control logging output. */
|
|
13
|
+
logger?: Layer.Layer<never> | undefined
|
|
14
|
+
/** Optional minimum log level for the runtime. */
|
|
15
|
+
logLevel?: LogLevel.LogLevel | undefined
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Common defaults for resolving a logger configuration.
|
|
20
|
+
* - `threadName` is used by the default pretty logger when `logger` is not provided.
|
|
21
|
+
* - `mode` selects pretty logger mode (e.g. 'browser' for web workers).
|
|
22
|
+
* - `defaultLogLevel` is used when `logLevel` is not provided.
|
|
23
|
+
*/
|
|
24
|
+
export type LoggerDefaults = {
|
|
25
|
+
threadName?: string
|
|
26
|
+
mode?: 'tty' | 'browser'
|
|
27
|
+
defaultLogLevel?: LogLevel.LogLevel
|
|
28
|
+
/** Optional default logger layer to use when `config.logger` is not provided. */
|
|
29
|
+
defaultLogger?: Layer.Layer<never>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the logger layer to provide to the Effect runtime.
|
|
34
|
+
*/
|
|
35
|
+
export const resolveLoggerLayer = (config?: WithLoggerOptions, defaults?: LoggerDefaults): Layer.Layer<never> => {
|
|
36
|
+
if (config?.logger) return config.logger
|
|
37
|
+
if (defaults?.defaultLogger) return defaults.defaultLogger
|
|
38
|
+
const threadName = defaults?.threadName ?? 'livestore'
|
|
39
|
+
const mode = defaults?.mode
|
|
40
|
+
return Logger.prettyWithThread(threadName, mode ? { mode } : {})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the minimum log level, falling back to `defaults.defaultLogLevel` then `LogLevel.Debug`.
|
|
45
|
+
*/
|
|
46
|
+
export const resolveLogLevel = (config?: WithLoggerOptions, defaults?: LoggerDefaults): LogLevel.LogLevel => {
|
|
47
|
+
if (config?.logLevel !== undefined) return config.logLevel
|
|
48
|
+
if (defaults?.defaultLogLevel !== undefined) return defaults.defaultLogLevel
|
|
49
|
+
return isDevEnv() ? LogLevel.Debug : LogLevel.Info
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Wrap an effect by applying the resolved minimum log level and providing the resolved logger layer.
|
|
54
|
+
*/
|
|
55
|
+
export const withLoggerConfig = <TEnv, TError, TOut>(
|
|
56
|
+
config?: WithLoggerOptions,
|
|
57
|
+
defaults?: LoggerDefaults,
|
|
58
|
+
): ((effect: Effect.Effect<TOut, TError, TEnv>) => Effect.Effect<TOut, TError, TEnv>) => {
|
|
59
|
+
const level = resolveLogLevel(config, defaults)
|
|
60
|
+
const layer = resolveLoggerLayer(config, defaults)
|
|
61
|
+
return (effect) => effect.pipe(Logger.withMinimumLogLevel(level), Effect.provide(layer))
|
|
62
|
+
}
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
ClientSessionLeaderThreadProxy,
|
|
9
9
|
LockStatus,
|
|
10
10
|
SqliteDb,
|
|
11
|
-
|
|
11
|
+
UnknownError,
|
|
12
12
|
} from './adapter-types.ts'
|
|
13
13
|
import * as Devtools from './devtools/mod.ts'
|
|
14
14
|
import { liveStoreVersion } from './version.ts'
|
|
@@ -33,6 +33,7 @@ export const makeClientSession = <R>({
|
|
|
33
33
|
webmeshMode,
|
|
34
34
|
registerBeforeUnload,
|
|
35
35
|
debugInstanceId,
|
|
36
|
+
origin,
|
|
36
37
|
}: AdapterArgs & {
|
|
37
38
|
clientId: string
|
|
38
39
|
sessionId: string
|
|
@@ -43,9 +44,11 @@ export const makeClientSession = <R>({
|
|
|
43
44
|
connectWebmeshNode: (args: {
|
|
44
45
|
webmeshNode: Webmesh.MeshNode
|
|
45
46
|
sessionInfo: Devtools.SessionInfo.SessionInfo
|
|
46
|
-
}) => Effect.Effect<void,
|
|
47
|
+
}) => Effect.Effect<void, UnknownError, Scope.Scope | R>
|
|
47
48
|
webmeshMode: 'direct' | 'proxy'
|
|
48
49
|
registerBeforeUnload: (onBeforeUnload: () => void) => () => void
|
|
50
|
+
/** Browser origin of the client session; used for origin-scoped DevTools mesh channels */
|
|
51
|
+
origin: string | undefined
|
|
49
52
|
}): Effect.Effect<ClientSession, never, Scope.Scope | R> =>
|
|
50
53
|
Effect.gen(function* () {
|
|
51
54
|
const devtools: ClientSession['devtools'] = devtoolsEnabled
|
|
@@ -67,11 +70,14 @@ export const makeClientSession = <R>({
|
|
|
67
70
|
sessionId,
|
|
68
71
|
schemaAlias,
|
|
69
72
|
isLeader,
|
|
73
|
+
origin,
|
|
70
74
|
})
|
|
71
75
|
|
|
72
76
|
yield* connectWebmeshNode({ webmeshNode, sessionInfo })
|
|
73
77
|
|
|
74
|
-
const sessionInfoBroadcastChannel = yield* Devtools.makeSessionInfoBroadcastChannel(webmeshNode
|
|
78
|
+
const sessionInfoBroadcastChannel = yield* Devtools.makeSessionInfoBroadcastChannel(webmeshNode, {
|
|
79
|
+
origin,
|
|
80
|
+
})
|
|
75
81
|
|
|
76
82
|
yield* Devtools.SessionInfo.provideSessionInfo({
|
|
77
83
|
webChannel: sessionInfoBroadcastChannel,
|
|
@@ -3,9 +3,9 @@ import { Hash, Option, Schema } from '@livestore/utils/effect'
|
|
|
3
3
|
|
|
4
4
|
import type { SqliteDb } from './adapter-types.ts'
|
|
5
5
|
import { SessionIdSymbol } from './adapter-types.ts'
|
|
6
|
-
import type { EventDef, Materializer, MaterializerContextQuery, MaterializerResult } from './schema/EventDef.ts'
|
|
7
|
-
import type * as LiveStoreEvent from './schema/LiveStoreEvent.ts'
|
|
8
|
-
import {
|
|
6
|
+
import type { EventDef, Materializer, MaterializerContextQuery, MaterializerResult } from './schema/EventDef/mod.ts'
|
|
7
|
+
import type * as LiveStoreEvent from './schema/LiveStoreEvent/mod.ts'
|
|
8
|
+
import type { LiveStoreSchema } from './schema/schema.ts'
|
|
9
9
|
import type { QueryBuilder } from './schema/state/sqlite/query-builder/api.ts'
|
|
10
10
|
import { isQueryBuilder } from './schema/state/sqlite/query-builder/api.ts'
|
|
11
11
|
import { getResultSchema } from './schema/state/sqlite/query-builder/impl.ts'
|
|
@@ -24,15 +24,20 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
24
24
|
dbState: SqliteDb
|
|
25
25
|
/** Both encoded and decoded events are supported to reduce the number of times we need to decode/encode */
|
|
26
26
|
event:
|
|
27
|
-
| { decoded: LiveStoreEvent.
|
|
28
|
-
| { decoded: undefined; encoded: LiveStoreEvent.
|
|
27
|
+
| { decoded: LiveStoreEvent.Client.Decoded; encoded: undefined }
|
|
28
|
+
| { decoded: undefined; encoded: LiveStoreEvent.Client.Encoded }
|
|
29
29
|
}): ReadonlyArray<{
|
|
30
30
|
statementSql: string
|
|
31
31
|
bindValues: PreparedBindValues
|
|
32
32
|
writeTables: ReadonlySet<string> | undefined
|
|
33
33
|
}> => {
|
|
34
|
-
const
|
|
35
|
-
event.decoded === undefined
|
|
34
|
+
const eventDecoded =
|
|
35
|
+
event.decoded === undefined
|
|
36
|
+
? {
|
|
37
|
+
...event.encoded!,
|
|
38
|
+
args: Schema.decodeUnknownSync(eventDef.schema)(event.encoded!.args),
|
|
39
|
+
}
|
|
40
|
+
: event.decoded
|
|
36
41
|
|
|
37
42
|
const eventArgsEncoded = isNil(event.decoded?.args)
|
|
38
43
|
? undefined
|
|
@@ -58,11 +63,12 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
const statementResults = fromMaterializerResult(
|
|
61
|
-
materializer(
|
|
66
|
+
materializer(eventDecoded.args, {
|
|
62
67
|
eventDef,
|
|
63
68
|
query,
|
|
64
69
|
// TODO properly implement this
|
|
65
70
|
currentFacts: new Map(),
|
|
71
|
+
event: eventDecoded,
|
|
66
72
|
}),
|
|
67
73
|
)
|
|
68
74
|
|
|
@@ -79,9 +85,20 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
79
85
|
|
|
80
86
|
export const makeMaterializerHash =
|
|
81
87
|
({ schema, dbState }: { schema: LiveStoreSchema; dbState: SqliteDb }) =>
|
|
82
|
-
(event: LiveStoreEvent.
|
|
88
|
+
(event: LiveStoreEvent.Client.Encoded): Option.Option<number> => {
|
|
83
89
|
if (isDevEnv()) {
|
|
84
|
-
|
|
90
|
+
// Hashing is only needed during dev-mode diagnostics. Skip work entirely for
|
|
91
|
+
// unknown events (no definition/materializer) so we do not introduce noisy
|
|
92
|
+
// warnings while still returning `Option.none()` to disable hash checks.
|
|
93
|
+
const eventDef = schema.eventsDefsMap.get(event.name)
|
|
94
|
+
const materializer = schema.state.materializers.get(event.name)
|
|
95
|
+
if (eventDef === undefined || materializer === undefined) {
|
|
96
|
+
return Option.none()
|
|
97
|
+
}
|
|
98
|
+
// For known events we replay the materializer with the encoded payload and
|
|
99
|
+
// hash the resulting SQL statements. This lets us cheaply detect
|
|
100
|
+
// side-effects or logic drift between leader/client materializers without
|
|
101
|
+
// mutating the underlying state.
|
|
85
102
|
const materializerResults = getExecStatementsFromMaterializer({
|
|
86
103
|
eventDef,
|
|
87
104
|
materializer,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { memoizeByRef } from '@livestore/utils'
|
|
2
2
|
import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
|
-
import { type SqliteDb,
|
|
4
|
+
import { type SqliteDb, UnknownError } from './adapter-types.ts'
|
|
5
5
|
import type { MaterializeEvent } from './leader-thread/mod.ts'
|
|
6
6
|
import type { EventDef, LiveStoreSchema } from './schema/mod.ts'
|
|
7
|
-
import { EventSequenceNumber,
|
|
7
|
+
import { EventSequenceNumber, LiveStoreEvent, resolveEventDef, SystemTables } from './schema/mod.ts'
|
|
8
8
|
import type { PreparedBindValues } from './util.ts'
|
|
9
9
|
import { sql } from './util.ts'
|
|
10
10
|
|
|
@@ -31,20 +31,47 @@ export const rematerializeFromEventlog = ({
|
|
|
31
31
|
|
|
32
32
|
const processEvent = (row: SystemTables.EventlogMetaRow) =>
|
|
33
33
|
Effect.gen(function* () {
|
|
34
|
-
const
|
|
34
|
+
const args = JSON.parse(row.argsJson)
|
|
35
|
+
const eventEncoded = LiveStoreEvent.Client.EncodedWithMeta.make({
|
|
36
|
+
name: row.name,
|
|
37
|
+
args,
|
|
38
|
+
seqNum: {
|
|
39
|
+
global: row.seqNumGlobal,
|
|
40
|
+
client: row.seqNumClient,
|
|
41
|
+
rebaseGeneration: row.seqNumRebaseGeneration,
|
|
42
|
+
},
|
|
43
|
+
parentSeqNum: {
|
|
44
|
+
global: row.parentSeqNumGlobal,
|
|
45
|
+
client: row.parentSeqNumClient,
|
|
46
|
+
rebaseGeneration: row.parentSeqNumRebaseGeneration,
|
|
47
|
+
},
|
|
48
|
+
clientId: row.clientId,
|
|
49
|
+
sessionId: row.sessionId,
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const resolution = yield* resolveEventDef(schema, {
|
|
53
|
+
operation: '@livestore/common:rematerializeFromEventlog:processEvent',
|
|
54
|
+
event: eventEncoded,
|
|
55
|
+
}).pipe(UnknownError.mapToUnknownError)
|
|
56
|
+
|
|
57
|
+
if (resolution._tag === 'unknown') {
|
|
58
|
+
// Old snapshots can contain newer events. Skip until the runtime has
|
|
59
|
+
// been updated; the event stays in the log for future replays.
|
|
60
|
+
return
|
|
61
|
+
}
|
|
35
62
|
|
|
36
|
-
|
|
63
|
+
const { eventDef } = resolution
|
|
64
|
+
|
|
65
|
+
if (hashEventDef(eventDef) !== row.schemaHash) {
|
|
37
66
|
yield* Effect.logWarning(
|
|
38
67
|
`Schema hash mismatch for event definition ${row.name}. Trying to materialize event anyway.`,
|
|
39
68
|
)
|
|
40
69
|
}
|
|
41
70
|
|
|
42
|
-
const args = JSON.parse(row.argsJson)
|
|
43
|
-
|
|
44
71
|
// Checking whether the schema has changed in an incompatible way
|
|
45
|
-
yield* Schema.decodeUnknown(eventDef.
|
|
72
|
+
yield* Schema.decodeUnknown(eventDef.schema)(args).pipe(
|
|
46
73
|
Effect.mapError((cause) =>
|
|
47
|
-
|
|
74
|
+
UnknownError.make({
|
|
48
75
|
cause,
|
|
49
76
|
note: `\
|
|
50
77
|
There was an error during rematerializing from the eventlog while decoding
|
|
@@ -55,23 +82,6 @@ This likely means the schema has changed in an incompatible way.
|
|
|
55
82
|
),
|
|
56
83
|
)
|
|
57
84
|
|
|
58
|
-
const eventEncoded = LiveStoreEvent.EncodedWithMeta.make({
|
|
59
|
-
seqNum: {
|
|
60
|
-
global: row.seqNumGlobal,
|
|
61
|
-
client: row.seqNumClient,
|
|
62
|
-
rebaseGeneration: row.seqNumRebaseGeneration,
|
|
63
|
-
},
|
|
64
|
-
parentSeqNum: {
|
|
65
|
-
global: row.parentSeqNumGlobal,
|
|
66
|
-
client: row.parentSeqNumClient,
|
|
67
|
-
rebaseGeneration: row.parentSeqNumRebaseGeneration,
|
|
68
|
-
},
|
|
69
|
-
name: row.name,
|
|
70
|
-
args,
|
|
71
|
-
clientId: row.clientId,
|
|
72
|
-
sessionId: row.sessionId,
|
|
73
|
-
})
|
|
74
|
-
|
|
75
85
|
yield* materializeEvent(eventEncoded, { skipEventlog: true })
|
|
76
86
|
}).pipe(Effect.withSpan(`@livestore/common:rematerializeFromEventlog:processEvent`))
|
|
77
87
|
|
|
@@ -96,9 +106,9 @@ LIMIT ${CHUNK_SIZE}
|
|
|
96
106
|
const lastId = Chunk.isChunk(item)
|
|
97
107
|
? Chunk.last(item).pipe(
|
|
98
108
|
Option.map((_) => ({ global: _.seqNumGlobal, client: _.seqNumClient })),
|
|
99
|
-
Option.getOrElse(() => EventSequenceNumber.ROOT),
|
|
109
|
+
Option.getOrElse(() => EventSequenceNumber.Client.ROOT),
|
|
100
110
|
)
|
|
101
|
-
: EventSequenceNumber.ROOT
|
|
111
|
+
: EventSequenceNumber.Client.ROOT
|
|
102
112
|
const nextItem = Chunk.fromIterable(
|
|
103
113
|
stmt.select<SystemTables.EventlogMetaRow>({
|
|
104
114
|
$seqNumGlobal: lastId?.global,
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Definition Functions
|
|
3
|
+
*
|
|
4
|
+
* This module provides functions for creating event definitions in LiveStore.
|
|
5
|
+
* Events are the core unit of state change - all mutations to the database
|
|
6
|
+
* happen through events that are committed to the eventlog.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { Events } from '@livestore/livestore'
|
|
11
|
+
* import { Schema } from 'effect'
|
|
12
|
+
*
|
|
13
|
+
* // Define events for your application
|
|
14
|
+
* export const events = {
|
|
15
|
+
* // Synced events are sent to the sync backend
|
|
16
|
+
* todoCreated: Events.synced({
|
|
17
|
+
* name: 'v1.TodoCreated',
|
|
18
|
+
* schema: Schema.Struct({ id: Schema.String, text: Schema.String }),
|
|
19
|
+
* }),
|
|
20
|
+
*
|
|
21
|
+
* // Client-only events stay local (useful for UI state)
|
|
22
|
+
* uiStateSet: Events.clientOnly({
|
|
23
|
+
* name: 'UiStateSet',
|
|
24
|
+
* schema: Schema.Struct({ selectedId: Schema.NullOr(Schema.String) }),
|
|
25
|
+
* }),
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
* @module
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { shouldNeverHappen } from '@livestore/utils'
|
|
32
|
+
import { Schema } from '@livestore/utils/effect'
|
|
33
|
+
|
|
34
|
+
import type { EventDef } from './event-def.ts'
|
|
35
|
+
import type { EventDefFactInput, EventDefFacts } from './facts.ts'
|
|
36
|
+
|
|
37
|
+
/** Options for defining an event. */
|
|
38
|
+
export type DefineEventOptions<TTo, TDerived extends boolean = false> = {
|
|
39
|
+
/**
|
|
40
|
+
* Callback defining fact constraints for this event.
|
|
41
|
+
* @experimental This feature is not fully implemented yet.
|
|
42
|
+
*/
|
|
43
|
+
facts?: (
|
|
44
|
+
args: TTo,
|
|
45
|
+
currentFacts: EventDefFacts,
|
|
46
|
+
) => {
|
|
47
|
+
modify?: {
|
|
48
|
+
/** Facts to set (create or update). */
|
|
49
|
+
set?: Iterable<EventDefFactInput>
|
|
50
|
+
/** Facts to unset (remove). */
|
|
51
|
+
unset?: Iterable<EventDefFactInput>
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Facts that must exist for this event to be valid.
|
|
55
|
+
* Used for history constraints and compaction rules.
|
|
56
|
+
*/
|
|
57
|
+
require?: Iterable<EventDefFactInput>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* When true, the event is only synced within the same client's sessions
|
|
62
|
+
* but never sent to the sync backend. Useful for UI state.
|
|
63
|
+
* @default false
|
|
64
|
+
*/
|
|
65
|
+
clientOnly?: boolean
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* When true, marks this as a derived event that cannot have materializers.
|
|
69
|
+
* @default false
|
|
70
|
+
*/
|
|
71
|
+
derived?: TDerived
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Creates an event definition with full control over all options.
|
|
76
|
+
*
|
|
77
|
+
* This is the low-level function for creating events. For most cases,
|
|
78
|
+
* prefer using `synced()` or `clientOnly()` which provide simpler APIs.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const customEvent = defineEvent({
|
|
83
|
+
* name: 'v1.CustomEvent',
|
|
84
|
+
* schema: Schema.Struct({ data: Schema.String }),
|
|
85
|
+
* clientOnly: false,
|
|
86
|
+
* derived: false,
|
|
87
|
+
* })
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export const defineEvent = <TName extends string, TType, TEncoded = TType, TDerived extends boolean = false>(
|
|
91
|
+
args: {
|
|
92
|
+
name: TName
|
|
93
|
+
schema: Schema.Schema<TType, TEncoded>
|
|
94
|
+
} & DefineEventOptions<TType, TDerived>,
|
|
95
|
+
): EventDef<TName, TType, TEncoded, TDerived> => {
|
|
96
|
+
const { name, schema, ...options } = args
|
|
97
|
+
|
|
98
|
+
const makePartialEvent = (args: TType) => {
|
|
99
|
+
const res = Schema.validateEither(schema)(args)
|
|
100
|
+
if (res._tag === 'Left') {
|
|
101
|
+
shouldNeverHappen(`Invalid event args for event '${name}':`, res.left.message, '\n')
|
|
102
|
+
}
|
|
103
|
+
return { name: name, args }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
Object.defineProperty(makePartialEvent, 'name', { value: name })
|
|
107
|
+
Object.defineProperty(makePartialEvent, 'schema', { value: schema })
|
|
108
|
+
Object.defineProperty(makePartialEvent, 'encoded', {
|
|
109
|
+
value: (args: TEncoded) => ({ name: name, args }),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
Object.defineProperty(makePartialEvent, 'options', {
|
|
113
|
+
value: {
|
|
114
|
+
clientOnly: options?.clientOnly ?? false,
|
|
115
|
+
facts: options?.facts
|
|
116
|
+
? (args, currentFacts) => {
|
|
117
|
+
const res = options.facts!(args, currentFacts)
|
|
118
|
+
return {
|
|
119
|
+
modify: {
|
|
120
|
+
set: res.modify?.set ? new Set(res.modify.set) : new Set(),
|
|
121
|
+
unset: res.modify?.unset ? new Set(res.modify.unset) : new Set(),
|
|
122
|
+
},
|
|
123
|
+
require: res.require ? new Set(res.require) : new Set(),
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
: undefined,
|
|
127
|
+
derived: options?.derived ?? false,
|
|
128
|
+
} satisfies EventDef.Any['options'],
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
return makePartialEvent as EventDef<TName, TType, TEncoded, TDerived>
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Creates a synced event definition.
|
|
136
|
+
*
|
|
137
|
+
* Synced events are sent to the sync backend and distributed to all connected
|
|
138
|
+
* clients. Use this for collaborative data that should be shared across users
|
|
139
|
+
* and devices.
|
|
140
|
+
*
|
|
141
|
+
* Event names should be versioned (e.g., `v1.TodoCreated`) to support
|
|
142
|
+
* schema evolution over time.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* import { Events } from '@livestore/livestore'
|
|
147
|
+
* import { Schema } from 'effect'
|
|
148
|
+
*
|
|
149
|
+
* const todoCreated = Events.synced({
|
|
150
|
+
* name: 'v1.TodoCreated',
|
|
151
|
+
* schema: Schema.Struct({
|
|
152
|
+
* id: Schema.String,
|
|
153
|
+
* text: Schema.String,
|
|
154
|
+
* completed: Schema.Boolean,
|
|
155
|
+
* }),
|
|
156
|
+
* })
|
|
157
|
+
*
|
|
158
|
+
* // Commit the event
|
|
159
|
+
* store.commit(todoCreated({ id: 'abc', text: 'Buy milk', completed: false }))
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
export const synced = <TName extends string, TType, TEncoded = TType>(
|
|
163
|
+
args: {
|
|
164
|
+
name: TName
|
|
165
|
+
schema: Schema.Schema<TType, TEncoded>
|
|
166
|
+
} & Omit<DefineEventOptions<TType, false>, 'derived' | 'clientOnly'>,
|
|
167
|
+
): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: false })
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Creates a client-only event definition.
|
|
171
|
+
*
|
|
172
|
+
* Client-only events are synced within the same client's sessions (e.g., across
|
|
173
|
+
* browser tabs) but are never sent to the sync backend. Use this for local UI
|
|
174
|
+
* state like selected items, filter settings, or draft content.
|
|
175
|
+
*
|
|
176
|
+
* Note: Client-only events still require materializers and are stored in the
|
|
177
|
+
* local eventlog, they just don't participate in server-side sync.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* import { Events } from '@livestore/livestore'
|
|
182
|
+
* import { Schema } from 'effect'
|
|
183
|
+
*
|
|
184
|
+
* const uiStateSet = Events.clientOnly({
|
|
185
|
+
* name: 'UiStateSet',
|
|
186
|
+
* schema: Schema.Struct({
|
|
187
|
+
* selectedTodoId: Schema.NullOr(Schema.String),
|
|
188
|
+
* filterMode: Schema.Literal('all', 'active', 'completed'),
|
|
189
|
+
* }),
|
|
190
|
+
* })
|
|
191
|
+
*
|
|
192
|
+
* // Update local UI state
|
|
193
|
+
* store.commit(uiStateSet({ selectedTodoId: 'abc', filterMode: 'active' }))
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export const clientOnly = <TName extends string, TType, TEncoded = TType>(
|
|
197
|
+
args: {
|
|
198
|
+
name: TName
|
|
199
|
+
schema: Schema.Schema<TType, TEncoded>
|
|
200
|
+
} & Omit<DefineEventOptions<TType, false>, 'derived' | 'clientOnly'>,
|
|
201
|
+
): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: true })
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { Schema } from '@livestore/utils/effect'
|
|
2
|
+
|
|
3
|
+
import type { FactsCallback } from './facts.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Core type representing an event definition in LiveStore.
|
|
7
|
+
*
|
|
8
|
+
* An EventDef defines the structure and behavior of an event type, including:
|
|
9
|
+
* - A unique name identifying the event type (conventionally versioned, e.g., `v1.TodoCreated`)
|
|
10
|
+
* - A schema for validating and encoding/decoding event arguments
|
|
11
|
+
* - Options controlling sync behavior and constraints
|
|
12
|
+
*
|
|
13
|
+
* EventDefs are callable - invoking them creates a partial event object suitable for `store.commit()`.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Events } from '@livestore/livestore'
|
|
18
|
+
* import { Schema } from 'effect'
|
|
19
|
+
*
|
|
20
|
+
* const todoCreated = Events.synced({
|
|
21
|
+
* name: 'v1.TodoCreated',
|
|
22
|
+
* schema: Schema.Struct({
|
|
23
|
+
* id: Schema.String,
|
|
24
|
+
* text: Schema.String,
|
|
25
|
+
* }),
|
|
26
|
+
* })
|
|
27
|
+
*
|
|
28
|
+
* // Use the EventDef as a constructor
|
|
29
|
+
* store.commit(todoCreated({ id: 'abc', text: 'Buy milk' }))
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export type EventDef<TName extends string, TType, TEncoded = TType, TDerived extends boolean = false> = {
|
|
33
|
+
/** Unique identifier for this event type. Conventionally versioned (e.g., `v1.TodoCreated`). */
|
|
34
|
+
name: TName
|
|
35
|
+
|
|
36
|
+
/** Effect Schema used for validating and encoding/decoding event arguments. */
|
|
37
|
+
schema: Schema.Schema<TType, TEncoded>
|
|
38
|
+
|
|
39
|
+
options: {
|
|
40
|
+
/**
|
|
41
|
+
* When true, the event is only synced within the same client's sessions (e.g., across tabs)
|
|
42
|
+
* but never sent to the sync backend. Useful for UI state like selected items or filters.
|
|
43
|
+
*/
|
|
44
|
+
clientOnly: boolean
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Callback defining fact constraints for this event.
|
|
48
|
+
* @experimental This feature is not fully implemented yet.
|
|
49
|
+
*/
|
|
50
|
+
facts: FactsCallback<TType> | undefined
|
|
51
|
+
|
|
52
|
+
/** Whether this is a derived event. Derived events cannot have materializers. */
|
|
53
|
+
derived: TDerived
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Callable signature - creates a partial event with decoded arguments.
|
|
58
|
+
* The returned object can be passed directly to `store.commit()`.
|
|
59
|
+
*/
|
|
60
|
+
(
|
|
61
|
+
args: TType,
|
|
62
|
+
): {
|
|
63
|
+
name: TName
|
|
64
|
+
args: TType
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Creates a partial event with pre-encoded arguments.
|
|
69
|
+
* Useful when working with already-serialized data.
|
|
70
|
+
*/
|
|
71
|
+
encoded: (args: TEncoded) => {
|
|
72
|
+
name: TName
|
|
73
|
+
args: TEncoded
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Type helper for accessing the event's shape with name and decoded args. */
|
|
77
|
+
readonly Event: {
|
|
78
|
+
name: TName
|
|
79
|
+
args: TType
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export namespace EventDef {
|
|
84
|
+
/**
|
|
85
|
+
* Wildcard type matching any EventDef regardless of type parameters.
|
|
86
|
+
* Used as a type constraint in generic functions and collections.
|
|
87
|
+
*/
|
|
88
|
+
export type Any = EventDef<string, any, any, boolean>
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* EventDef without the callable function signature.
|
|
92
|
+
* Used in contexts where only the metadata (name, schema, options) is needed,
|
|
93
|
+
* such as materializer definitions.
|
|
94
|
+
*/
|
|
95
|
+
export type AnyWithoutFn = Pick<Any, 'name' | 'schema' | 'options'>
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Container holding a Map of event definitions keyed by name.
|
|
100
|
+
* Used internally by LiveStoreSchema.
|
|
101
|
+
*/
|
|
102
|
+
export type EventDefMap = {
|
|
103
|
+
map: Map<string, EventDef.Any>
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Plain object record of event definitions keyed by name.
|
|
108
|
+
* This is the typical shape when defining events in user code.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* const events = {
|
|
113
|
+
* todoCreated: Events.synced({ name: 'v1.TodoCreated', schema: ... }),
|
|
114
|
+
* todoDeleted: Events.synced({ name: 'v1.TodoDeleted', schema: ... }),
|
|
115
|
+
* } satisfies EventDefRecord
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export type EventDefRecord = {
|
|
119
|
+
[name: string]: EventDef.Any
|
|
120
|
+
}
|