@livestore/common 0.4.0-dev.21 → 0.4.0-dev.23
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 +16 -9
- package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
- package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
- package/dist/WorkerTransportError.d.ts +11 -0
- package/dist/WorkerTransportError.d.ts.map +1 -0
- package/dist/WorkerTransportError.js +11 -0
- package/dist/WorkerTransportError.js.map +1 -0
- package/dist/adapter-types.d.ts +26 -3
- package/dist/adapter-types.d.ts.map +1 -1
- package/dist/adapter-types.js +27 -1
- package/dist/adapter-types.js.map +1 -1
- package/dist/bounded-collections.d.ts.map +1 -1
- package/dist/bounded-collections.js +6 -4
- package/dist/bounded-collections.js.map +1 -1
- package/dist/debug-info.js +4 -4
- package/dist/debug-info.js.map +1 -1
- package/dist/devtools/devtools-messages-client-session.d.ts +42 -22
- package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-client-session.js +12 -1
- package/dist/devtools/devtools-messages-client-session.js.map +1 -1
- package/dist/devtools/devtools-messages-common.d.ts +12 -6
- package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-common.js +8 -3
- package/dist/devtools/devtools-messages-common.js.map +1 -1
- package/dist/devtools/devtools-messages-leader.d.ts +45 -25
- package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
- package/dist/devtools/devtools-messages-leader.js +12 -1
- package/dist/devtools/devtools-messages-leader.js.map +1 -1
- package/dist/devtools/mod.js +1 -1
- package/dist/devtools/mod.js.map +1 -1
- package/dist/errors.d.ts +15 -15
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +11 -11
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.d.ts +20 -6
- package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
- package/dist/leader-thread/LeaderSyncProcessor.js +283 -253
- package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
- package/dist/leader-thread/RejectedPushError.d.ts +107 -0
- package/dist/leader-thread/RejectedPushError.d.ts.map +1 -0
- package/dist/leader-thread/RejectedPushError.js +78 -0
- package/dist/leader-thread/RejectedPushError.js.map +1 -0
- package/dist/leader-thread/connection.js +1 -1
- package/dist/leader-thread/connection.js.map +1 -1
- package/dist/leader-thread/eventlog.d.ts.map +1 -1
- package/dist/leader-thread/eventlog.js +12 -11
- 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 +34 -14
- package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.d.ts +12 -5
- package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.js +12 -11
- package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
- package/dist/leader-thread/make-leader-thread-layer.test.js +1 -1
- package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -1
- package/dist/leader-thread/materialize-event.d.ts.map +1 -1
- package/dist/leader-thread/materialize-event.js +7 -4
- package/dist/leader-thread/materialize-event.js.map +1 -1
- package/dist/leader-thread/recreate-db.js +1 -1
- package/dist/leader-thread/recreate-db.js.map +1 -1
- package/dist/leader-thread/shutdown-channel.d.ts +2 -2
- package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
- package/dist/leader-thread/shutdown-channel.js +2 -2
- package/dist/leader-thread/shutdown-channel.js.map +1 -1
- package/dist/leader-thread/stream-events.d.ts.map +1 -1
- package/dist/leader-thread/stream-events.js +4 -3
- package/dist/leader-thread/stream-events.js.map +1 -1
- package/dist/leader-thread/types.d.ts +7 -6
- package/dist/leader-thread/types.d.ts.map +1 -1
- package/dist/leader-thread/types.js.map +1 -1
- package/dist/logging.js +4 -4
- package/dist/logging.js.map +1 -1
- package/dist/make-client-session.js +2 -2
- package/dist/make-client-session.js.map +1 -1
- package/dist/materializer-helper.js +6 -6
- package/dist/materializer-helper.js.map +1 -1
- package/dist/otel.d.ts +1 -1
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +2 -2
- package/dist/otel.js.map +1 -1
- package/dist/rematerialize-from-eventlog.d.ts +1 -1
- package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
- package/dist/rematerialize-from-eventlog.js +11 -9
- package/dist/rematerialize-from-eventlog.js.map +1 -1
- package/dist/schema/EventDef/define.d.ts +16 -2
- package/dist/schema/EventDef/define.d.ts.map +1 -1
- package/dist/schema/EventDef/define.js +5 -4
- package/dist/schema/EventDef/define.js.map +1 -1
- package/dist/schema/EventDef/deprecated.d.ts +99 -0
- package/dist/schema/EventDef/deprecated.d.ts.map +1 -0
- package/dist/schema/EventDef/deprecated.js +144 -0
- package/dist/schema/EventDef/deprecated.js.map +1 -0
- package/dist/schema/EventDef/deprecated.test.d.ts +2 -0
- package/dist/schema/EventDef/deprecated.test.d.ts.map +1 -0
- package/dist/schema/EventDef/deprecated.test.js +95 -0
- package/dist/schema/EventDef/deprecated.test.js.map +1 -0
- package/dist/schema/EventDef/event-def.d.ts +4 -0
- package/dist/schema/EventDef/event-def.d.ts.map +1 -1
- package/dist/schema/EventDef/mod.d.ts +1 -0
- package/dist/schema/EventDef/mod.d.ts.map +1 -1
- package/dist/schema/EventDef/mod.js +1 -0
- package/dist/schema/EventDef/mod.js.map +1 -1
- package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
- package/dist/schema/EventSequenceNumber/client.js +11 -11
- package/dist/schema/EventSequenceNumber/client.js.map +1 -1
- package/dist/schema/EventSequenceNumber.test.js +1 -1
- package/dist/schema/EventSequenceNumber.test.js.map +1 -1
- package/dist/schema/LiveStoreEvent/client.d.ts +6 -6
- package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
- package/dist/schema/LiveStoreEvent/client.js +6 -3
- package/dist/schema/LiveStoreEvent/client.js.map +1 -1
- 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 +83 -0
- package/dist/schema/LiveStoreEvent/client.test.js.map +1 -0
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +7 -4
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.d.ts +1 -0
- package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.js +34 -13
- package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
- package/dist/schema/state/sqlite/client-document-def.test.js +121 -2
- package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.js +1 -1
- package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
- package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/column-def.js +36 -34
- package/dist/schema/state/sqlite/column-def.js.map +1 -1
- package/dist/schema/state/sqlite/column-def.test.js +7 -6
- 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 +8 -8
- package/dist/schema/state/sqlite/column-spec.js.map +1 -1
- package/dist/schema/state/sqlite/column-spec.test.js +1 -1
- package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +2 -2
- package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +2 -2
- 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 +11 -2
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js +1 -1
- package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
- package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
- package/dist/schema/state/sqlite/mod.js +3 -5
- package/dist/schema/state/sqlite/mod.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/api.d.ts +37 -13
- 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 +77 -7
- package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.js +28 -14
- package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
- package/dist/schema/state/sqlite/query-builder/impl.test.js +112 -3
- package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
- package/dist/schema/state/sqlite/schema-helpers.js +2 -2
- package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.d.ts +5 -3
- package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
- package/dist/schema/state/sqlite/table-def.js +1 -1
- package/dist/schema/state/sqlite/table-def.js.map +1 -1
- package/dist/schema/state/sqlite/table-def.test.js +57 -4
- package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
- package/dist/schema/unknown-events.d.ts +1 -1
- package/dist/schema/unknown-events.d.ts.map +1 -1
- package/dist/schema/unknown-events.js +1 -1
- package/dist/schema/unknown-events.js.map +1 -1
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +1 -1
- package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -1
- package/dist/schema-management/common.js +2 -2
- package/dist/schema-management/common.js.map +1 -1
- package/dist/schema-management/migrations.js +1 -1
- package/dist/schema-management/migrations.js.map +1 -1
- package/dist/sql-queries/sql-queries.js +8 -6
- package/dist/sql-queries/sql-queries.js.map +1 -1
- package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
- package/dist/sql-queries/sql-query-builder.js.map +1 -1
- package/dist/sqlite-db-helper.js +3 -3
- package/dist/sqlite-db-helper.js.map +1 -1
- package/dist/sqlite-types.d.ts +2 -2
- package/dist/sqlite-types.d.ts.map +1 -1
- package/dist/sqlite-types.js.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.d.ts +8 -9
- package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
- package/dist/sync/ClientSessionSyncProcessor.js +93 -107
- package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
- package/dist/sync/errors.d.ts +0 -38
- package/dist/sync/errors.d.ts.map +1 -1
- package/dist/sync/errors.js +3 -20
- package/dist/sync/errors.js.map +1 -1
- package/dist/sync/mock-sync-backend.d.ts +5 -3
- package/dist/sync/mock-sync-backend.d.ts.map +1 -1
- package/dist/sync/mock-sync-backend.js +70 -68
- package/dist/sync/mock-sync-backend.js.map +1 -1
- package/dist/sync/next/compact-events.js +6 -6
- package/dist/sync/next/compact-events.js.map +1 -1
- package/dist/sync/next/facts.d.ts.map +1 -1
- package/dist/sync/next/facts.js +6 -6
- package/dist/sync/next/facts.js.map +1 -1
- package/dist/sync/next/history-dag-common.d.ts.map +1 -1
- package/dist/sync/next/history-dag-common.js +6 -6
- package/dist/sync/next/history-dag-common.js.map +1 -1
- package/dist/sync/next/history-dag.js +3 -3
- package/dist/sync/next/history-dag.js.map +1 -1
- package/dist/sync/next/rebase-events.js +1 -1
- package/dist/sync/next/rebase-events.js.map +1 -1
- package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
- package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
- package/dist/sync/next/test/compact-events.test.d.ts.map +1 -1
- package/dist/sync/next/test/compact-events.test.js +2 -2
- package/dist/sync/next/test/compact-events.test.js.map +1 -1
- package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
- package/dist/sync/next/test/event-fixtures.js +2 -2
- package/dist/sync/next/test/event-fixtures.js.map +1 -1
- package/dist/sync/sync-backend-kv.d.ts.map +1 -1
- package/dist/sync/sync-backend-kv.js.map +1 -1
- package/dist/sync/sync-backend.d.ts +3 -3
- package/dist/sync/sync-backend.d.ts.map +1 -1
- package/dist/sync/sync-backend.js +1 -1
- package/dist/sync/sync-backend.js.map +1 -1
- package/dist/sync/sync.d.ts +20 -0
- package/dist/sync/sync.d.ts.map +1 -1
- package/dist/sync/syncstate.d.ts +4 -17
- package/dist/sync/syncstate.d.ts.map +1 -1
- package/dist/sync/syncstate.js +51 -74
- package/dist/sync/syncstate.js.map +1 -1
- package/dist/sync/syncstate.test.js +112 -96
- package/dist/sync/syncstate.test.js.map +1 -1
- package/dist/sync/transport-chunking.js +3 -3
- package/dist/sync/transport-chunking.js.map +1 -1
- 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/util.js +2 -2
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +7 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +8 -4
- package/dist/version.js.map +1 -1
- package/package.json +66 -12
- package/src/ClientSessionLeaderThreadProxy.ts +16 -9
- package/src/WorkerTransportError.ts +12 -0
- package/src/adapter-types.ts +39 -3
- package/src/bounded-collections.ts +6 -5
- package/src/debug-info.ts +4 -4
- package/src/devtools/devtools-messages-client-session.ts +12 -0
- package/src/devtools/devtools-messages-common.ts +8 -4
- package/src/devtools/devtools-messages-leader.ts +12 -0
- package/src/devtools/mod.ts +1 -1
- package/src/errors.ts +18 -17
- package/src/index.ts +2 -0
- package/src/leader-thread/LeaderSyncProcessor.ts +417 -347
- package/src/leader-thread/RejectedPushError.ts +106 -0
- package/src/leader-thread/connection.ts +1 -1
- package/src/leader-thread/eventlog.ts +16 -14
- package/src/leader-thread/leader-worker-devtools.ts +107 -66
- package/src/leader-thread/make-leader-thread-layer.test.ts +1 -1
- package/src/leader-thread/make-leader-thread-layer.ts +41 -31
- package/src/leader-thread/materialize-event.ts +8 -4
- package/src/leader-thread/recreate-db.ts +1 -1
- package/src/leader-thread/shutdown-channel.ts +2 -6
- package/src/leader-thread/stream-events.ts +10 -5
- package/src/leader-thread/types.ts +7 -6
- package/src/logging.ts +4 -4
- package/src/make-client-session.ts +2 -2
- package/src/materializer-helper.ts +9 -9
- package/src/otel.ts +3 -2
- package/src/rematerialize-from-eventlog.ts +60 -60
- package/src/schema/EventDef/define.ts +22 -6
- package/src/schema/EventDef/deprecated.test.ts +129 -0
- package/src/schema/EventDef/deprecated.ts +175 -0
- package/src/schema/EventDef/event-def.ts +5 -0
- package/src/schema/EventDef/mod.ts +1 -0
- package/src/schema/EventSequenceNumber/client.ts +11 -11
- package/src/schema/EventSequenceNumber.test.ts +2 -1
- package/src/schema/LiveStoreEvent/client.test.ts +97 -0
- package/src/schema/LiveStoreEvent/client.ts +6 -3
- package/src/schema/schema.ts +9 -4
- package/src/schema/state/sqlite/client-document-def.test.ts +142 -3
- package/src/schema/state/sqlite/client-document-def.ts +37 -14
- package/src/schema/state/sqlite/column-annotations.test.ts +2 -1
- package/src/schema/state/sqlite/column-annotations.ts +2 -1
- package/src/schema/state/sqlite/column-def.test.ts +8 -6
- package/src/schema/state/sqlite/column-def.ts +41 -36
- package/src/schema/state/sqlite/column-spec.test.ts +3 -1
- package/src/schema/state/sqlite/column-spec.ts +9 -8
- package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -2
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +2 -1
- package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +13 -4
- package/src/schema/state/sqlite/db-schema/dsl/mod.ts +3 -3
- package/src/schema/state/sqlite/mod.ts +4 -5
- package/src/schema/state/sqlite/query-builder/api.ts +37 -8
- package/src/schema/state/sqlite/query-builder/astToSql.ts +87 -7
- package/src/schema/state/sqlite/query-builder/impl.test.ts +145 -3
- package/src/schema/state/sqlite/query-builder/impl.ts +26 -12
- package/src/schema/state/sqlite/schema-helpers.ts +2 -2
- package/src/schema/state/sqlite/table-def.test.ts +67 -4
- package/src/schema/state/sqlite/table-def.ts +8 -15
- package/src/schema/unknown-events.ts +2 -2
- package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +3 -1
- package/src/schema-management/common.ts +2 -2
- package/src/schema-management/migrations.ts +1 -1
- package/src/sql-queries/sql-queries.ts +10 -6
- package/src/sql-queries/sql-query-builder.ts +1 -0
- package/src/sqlite-db-helper.ts +3 -3
- package/src/sqlite-types.ts +3 -2
- package/src/sync/ClientSessionSyncProcessor.ts +142 -133
- package/src/sync/errors.ts +10 -22
- package/src/sync/mock-sync-backend.ts +139 -97
- package/src/sync/next/compact-events.ts +5 -5
- package/src/sync/next/facts.ts +7 -6
- package/src/sync/next/history-dag-common.ts +9 -6
- package/src/sync/next/history-dag.ts +3 -3
- package/src/sync/next/rebase-events.ts +1 -1
- package/src/sync/next/test/compact-events.calculator.test.ts +3 -2
- package/src/sync/next/test/compact-events.test.ts +4 -3
- package/src/sync/next/test/event-fixtures.ts +2 -2
- package/src/sync/sync-backend-kv.ts +1 -0
- package/src/sync/sync-backend.ts +5 -4
- package/src/sync/sync.ts +21 -0
- package/src/sync/syncstate.test.ts +513 -435
- package/src/sync/syncstate.ts +80 -86
- package/src/sync/transport-chunking.ts +3 -3
- package/src/sync/validate-push-payload.ts +4 -6
- package/src/util.ts +2 -2
- package/src/version.ts +8 -4
|
@@ -2,10 +2,8 @@ import type { WebChannel } from '@livestore/utils/effect'
|
|
|
2
2
|
import { Schema } from '@livestore/utils/effect'
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
+
BackendIdMismatchError,
|
|
5
6
|
IntentionalShutdownCause,
|
|
6
|
-
InvalidPullError,
|
|
7
|
-
InvalidPushError,
|
|
8
|
-
IsOfflineError,
|
|
9
7
|
MaterializeError,
|
|
10
8
|
UnknownError,
|
|
11
9
|
} from '../index.ts'
|
|
@@ -13,9 +11,7 @@ import {
|
|
|
13
11
|
export class All extends Schema.Union(
|
|
14
12
|
IntentionalShutdownCause,
|
|
15
13
|
UnknownError,
|
|
16
|
-
|
|
17
|
-
InvalidPushError,
|
|
18
|
-
InvalidPullError,
|
|
14
|
+
BackendIdMismatchError,
|
|
19
15
|
MaterializeError,
|
|
20
16
|
) {}
|
|
21
17
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Subscribable } from '@livestore/utils/effect'
|
|
2
2
|
import { Chunk, Effect, Option, Queue, Stream } from '@livestore/utils/effect'
|
|
3
|
+
|
|
3
4
|
import { EventSequenceNumber, type LiveStoreEvent } from '../schema/mod.ts'
|
|
4
5
|
import type * as SyncState from '../sync/syncstate.ts'
|
|
5
6
|
import * as Eventlog from './eventlog.ts'
|
|
@@ -109,7 +110,10 @@ export const streamEventsWithSyncState = ({
|
|
|
109
110
|
* since === until : Prevent empty query
|
|
110
111
|
* since > until : Incorrectly inverted interval
|
|
111
112
|
*/
|
|
112
|
-
if (
|
|
113
|
+
if (
|
|
114
|
+
options.until !== undefined &&
|
|
115
|
+
EventSequenceNumber.Client.isGreaterThanOrEqual(cursor, options.until) === true
|
|
116
|
+
) {
|
|
113
117
|
return [Chunk.empty(), Option.none()]
|
|
114
118
|
}
|
|
115
119
|
|
|
@@ -144,9 +148,10 @@ export const streamEventsWithSyncState = ({
|
|
|
144
148
|
* nextHead: The latest head from headQueue
|
|
145
149
|
*/
|
|
146
150
|
const waitForHead = EventSequenceNumber.Client.isGreaterThanOrEqual(cursor, head)
|
|
147
|
-
const maybeHead =
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
const maybeHead =
|
|
152
|
+
waitForHead === true
|
|
153
|
+
? yield* Queue.take(headQueue).pipe(Effect.map(Option.some))
|
|
154
|
+
: yield* Queue.poll(headQueue)
|
|
150
155
|
const nextHead = Option.getOrElse(maybeHead, () => head)
|
|
151
156
|
const hardStop = options.until?.global ?? Number.POSITIVE_INFINITY
|
|
152
157
|
const target = EventSequenceNumber.Client.Composite.make({
|
|
@@ -181,7 +186,7 @@ export const streamEventsWithSyncState = ({
|
|
|
181
186
|
const nextState: Option.Option<{
|
|
182
187
|
cursor: EventSequenceNumber.Client.Composite
|
|
183
188
|
head: EventSequenceNumber.Client.Composite
|
|
184
|
-
}> = reachedUntil ? Option.none() : Option.some({ cursor: target, head: nextHead })
|
|
189
|
+
}> = reachedUntil === true ? Option.none() : Option.some({ cursor: target, head: nextHead })
|
|
185
190
|
|
|
186
191
|
const spanAttributes = {
|
|
187
192
|
'livestore.streamEvents.cursor.global': cursor.global,
|
|
@@ -17,13 +17,14 @@ import type { MaterializeError } from '../errors.ts'
|
|
|
17
17
|
import type {
|
|
18
18
|
BootStatus,
|
|
19
19
|
Devtools,
|
|
20
|
-
LeaderAheadError,
|
|
21
20
|
MakeSqliteDb,
|
|
22
21
|
PersistenceInfo,
|
|
23
22
|
SqliteDb,
|
|
24
23
|
SyncBackend,
|
|
25
24
|
UnknownError,
|
|
25
|
+
UnknownEventError,
|
|
26
26
|
} from '../index.ts'
|
|
27
|
+
import type { RejectedPushError } from './RejectedPushError.ts'
|
|
27
28
|
import { EventSequenceNumber, type LiveStoreEvent, type LiveStoreSchema } from '../schema/mod.ts'
|
|
28
29
|
import type * as SyncState from '../sync/syncstate.ts'
|
|
29
30
|
import type { ShutdownChannel } from './shutdown-channel.ts'
|
|
@@ -186,11 +187,11 @@ export interface LeaderSyncProcessor {
|
|
|
186
187
|
/** Used by client sessions to subscribe to upstream sync state changes */
|
|
187
188
|
pull: (args: {
|
|
188
189
|
cursor: EventSequenceNumber.Client.Composite
|
|
189
|
-
}) => Stream.Stream<{ payload: typeof SyncState.PayloadUpstream.Type }
|
|
190
|
+
}) => Stream.Stream<{ payload: typeof SyncState.PayloadUpstream.Type }>
|
|
190
191
|
/** The `pullQueue` API can be used instead of `pull` when more convenient */
|
|
191
192
|
pullQueue: (args: {
|
|
192
193
|
cursor: EventSequenceNumber.Client.Composite
|
|
193
|
-
}) => Effect.Effect<Queue.Queue<{ payload: typeof SyncState.PayloadUpstream.Type }>,
|
|
194
|
+
}) => Effect.Effect<Queue.Queue<{ payload: typeof SyncState.PayloadUpstream.Type }>, never, Scope.Scope>
|
|
194
195
|
|
|
195
196
|
/** Used by client sessions to push events to the leader thread */
|
|
196
197
|
push: (
|
|
@@ -204,18 +205,18 @@ export interface LeaderSyncProcessor {
|
|
|
204
205
|
*/
|
|
205
206
|
waitForProcessing?: boolean
|
|
206
207
|
},
|
|
207
|
-
) => Effect.Effect<void,
|
|
208
|
+
) => Effect.Effect<void, RejectedPushError>
|
|
208
209
|
|
|
209
210
|
/** Currently only used by devtools which don't provide their own event numbers */
|
|
210
211
|
pushPartial: (args: {
|
|
211
212
|
event: LiveStoreEvent.Input.Encoded
|
|
212
213
|
clientId: string
|
|
213
214
|
sessionId: string
|
|
214
|
-
}) => Effect.Effect<void,
|
|
215
|
+
}) => Effect.Effect<void, UnknownEventError>
|
|
215
216
|
|
|
216
217
|
boot: Effect.Effect<
|
|
217
218
|
{ initialLeaderHead: EventSequenceNumber.Client.Composite },
|
|
218
|
-
|
|
219
|
+
never,
|
|
219
220
|
LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
|
|
220
221
|
>
|
|
221
222
|
syncState: Subscribable.Subscribable<SyncState.SyncState>
|
package/src/logging.ts
CHANGED
|
@@ -33,11 +33,11 @@ export type LoggerDefaults = {
|
|
|
33
33
|
* Resolve the logger layer to provide to the Effect runtime.
|
|
34
34
|
*/
|
|
35
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
|
|
36
|
+
if (config?.logger !== undefined) return config.logger
|
|
37
|
+
if (defaults?.defaultLogger !== undefined) return defaults.defaultLogger
|
|
38
38
|
const threadName = defaults?.threadName ?? 'livestore'
|
|
39
39
|
const mode = defaults?.mode
|
|
40
|
-
return Logger.prettyWithThread(threadName, mode ? { mode } : {})
|
|
40
|
+
return Logger.prettyWithThread(threadName, mode !== undefined ? { mode } : {})
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -46,7 +46,7 @@ export const resolveLoggerLayer = (config?: WithLoggerOptions, defaults?: Logger
|
|
|
46
46
|
export const resolveLogLevel = (config?: WithLoggerOptions, defaults?: LoggerDefaults): LogLevel.LogLevel => {
|
|
47
47
|
if (config?.logLevel !== undefined) return config.logLevel
|
|
48
48
|
if (defaults?.defaultLogLevel !== undefined) return defaults.defaultLogLevel
|
|
49
|
-
return isDevEnv() ? LogLevel.Debug : LogLevel.Info
|
|
49
|
+
return isDevEnv() === true ? LogLevel.Debug : LogLevel.Info
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -51,11 +51,11 @@ export const makeClientSession = <R>({
|
|
|
51
51
|
origin: string | undefined
|
|
52
52
|
}): Effect.Effect<ClientSession, never, Scope.Scope | R> =>
|
|
53
53
|
Effect.gen(function* () {
|
|
54
|
-
const devtools: ClientSession['devtools'] = devtoolsEnabled
|
|
54
|
+
const devtools: ClientSession['devtools'] = devtoolsEnabled === true
|
|
55
55
|
? { enabled: true, pullLatch: yield* Effect.makeLatch(true), pushLatch: yield* Effect.makeLatch(true) }
|
|
56
56
|
: { enabled: false }
|
|
57
57
|
|
|
58
|
-
if (devtoolsEnabled) {
|
|
58
|
+
if (devtoolsEnabled === true) {
|
|
59
59
|
yield* Effect.gen(function* () {
|
|
60
60
|
const webmeshNode = yield* Webmesh.makeMeshNode(
|
|
61
61
|
Devtools.makeNodeName.client.session({ storeId, clientId, sessionId }),
|
|
@@ -34,14 +34,14 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
34
34
|
const eventDecoded =
|
|
35
35
|
event.decoded === undefined
|
|
36
36
|
? {
|
|
37
|
-
...event.encoded
|
|
38
|
-
args: Schema.decodeUnknownSync(eventDef.schema)(event.encoded
|
|
37
|
+
...event.encoded,
|
|
38
|
+
args: Schema.decodeUnknownSync(eventDef.schema)(event.encoded.args),
|
|
39
39
|
}
|
|
40
40
|
: event.decoded
|
|
41
41
|
|
|
42
|
-
const eventArgsEncoded = isNil(event.decoded?.args)
|
|
42
|
+
const eventArgsEncoded = isNil(event.decoded?.args) === true
|
|
43
43
|
? undefined
|
|
44
|
-
: Schema.encodeUnknownSync(eventDef.schema)(event.decoded
|
|
44
|
+
: Schema.encodeUnknownSync(eventDef.schema)(event.decoded.args)
|
|
45
45
|
|
|
46
46
|
const query: MaterializerContextQuery = (
|
|
47
47
|
rawQueryOrQueryBuilder:
|
|
@@ -51,7 +51,7 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
51
51
|
}
|
|
52
52
|
| QueryBuilder.Any,
|
|
53
53
|
) => {
|
|
54
|
-
if (isQueryBuilder(rawQueryOrQueryBuilder)) {
|
|
54
|
+
if (isQueryBuilder(rawQueryOrQueryBuilder) === true) {
|
|
55
55
|
const { query, bindValues } = rawQueryOrQueryBuilder.asSql()
|
|
56
56
|
const rawResults = dbState.select(query, prepareBindValues(bindValues, query))
|
|
57
57
|
const resultSchema = getResultSchema(rawQueryOrQueryBuilder)
|
|
@@ -86,7 +86,7 @@ export const getExecStatementsFromMaterializer = ({
|
|
|
86
86
|
export const makeMaterializerHash =
|
|
87
87
|
({ schema, dbState }: { schema: LiveStoreSchema; dbState: SqliteDb }) =>
|
|
88
88
|
(event: LiveStoreEvent.Client.Encoded): Option.Option<number> => {
|
|
89
|
-
if (isDevEnv()) {
|
|
89
|
+
if (isDevEnv() === true) {
|
|
90
90
|
// Hashing is only needed during dev-mode diagnostics. Skip work entirely for
|
|
91
91
|
// unknown events (no definition/materializer) so we do not introduce noisy
|
|
92
92
|
// warnings while still returning `Option.none()` to disable hash checks.
|
|
@@ -126,10 +126,10 @@ const fromMaterializerResult = (
|
|
|
126
126
|
bindValues: BindValues
|
|
127
127
|
writeTables: ReadonlySet<string> | undefined
|
|
128
128
|
}> => {
|
|
129
|
-
if (isReadonlyArray(materializerResult)) {
|
|
129
|
+
if (isReadonlyArray(materializerResult) === true) {
|
|
130
130
|
return materializerResult.flatMap(fromMaterializerResult)
|
|
131
131
|
}
|
|
132
|
-
if (isQueryBuilder(materializerResult)) {
|
|
132
|
+
if (isQueryBuilder(materializerResult) === true) {
|
|
133
133
|
const { query, bindValues, usedTables } = materializerResult.asSql()
|
|
134
134
|
return [{ sql: query, bindValues: bindValues as BindValues, writeTables: usedTables }]
|
|
135
135
|
} else if (typeof materializerResult === 'string') {
|
|
@@ -155,7 +155,7 @@ export const replaceSessionIdSymbol = (
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
const deepReplaceValue = <S, R>(input: any, searchValue: S, replaceValue: R): void => {
|
|
158
|
-
if (Array.isArray(input)) {
|
|
158
|
+
if (Array.isArray(input) === true) {
|
|
159
159
|
for (const i in input) {
|
|
160
160
|
if (input[i] === searchValue) {
|
|
161
161
|
input[i] = replaceValue
|
package/src/otel.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import * as otel from '@opentelemetry/api'
|
|
2
|
+
|
|
1
3
|
import { makeNoopTracer } from '@livestore/utils'
|
|
2
4
|
import { Effect, identity, Layer, OtelTracer } from '@livestore/utils/effect'
|
|
3
|
-
import * as otel from '@opentelemetry/api'
|
|
4
5
|
|
|
5
6
|
export const OtelLiveDummy: Layer.Layer<OtelTracer.OtelTracer> = Layer.suspend(() => {
|
|
6
7
|
const OtelTracerLive = Layer.succeed(OtelTracer.OtelTracer, makeNoopTracer())
|
|
@@ -22,7 +23,7 @@ export const provideOtel =
|
|
|
22
23
|
) as any as Layer.Layer<OtelTracer.OtelTracer>
|
|
23
24
|
|
|
24
25
|
return effect.pipe(
|
|
25
|
-
parentSpanContext
|
|
26
|
+
parentSpanContext !== undefined
|
|
26
27
|
? Effect.withParentSpan(OtelTracer.makeExternalSpan(otel.trace.getSpanContext(parentSpanContext)!))
|
|
27
28
|
: identity,
|
|
28
29
|
Effect.provide(TracingLive),
|
|
@@ -8,7 +8,10 @@ import { EventSequenceNumber, LiveStoreEvent, resolveEventDef, SystemTables } fr
|
|
|
8
8
|
import type { PreparedBindValues } from './util.ts'
|
|
9
9
|
import { sql } from './util.ts'
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/** Parse JSON string to unknown value */
|
|
12
|
+
const jsonParse = Schema.decodeUnknownSync(Schema.parseJson())
|
|
13
|
+
|
|
14
|
+
export const rematerializeFromEventlog = Effect.fn('@livestore/common:rematerializeFromEventlog')(function* ({
|
|
12
15
|
dbEventlog,
|
|
13
16
|
// TODO re-use this db when bringing back the boot in-memory db implementation
|
|
14
17
|
// db,
|
|
@@ -21,69 +24,69 @@ export const rematerializeFromEventlog = ({
|
|
|
21
24
|
schema: LiveStoreSchema
|
|
22
25
|
onProgress: (_: { done: number; total: number }) => Effect.Effect<void>
|
|
23
26
|
materializeEvent: MaterializeEvent
|
|
24
|
-
})
|
|
25
|
-
Effect.gen(function* () {
|
|
27
|
+
}) {
|
|
26
28
|
const eventsCount = dbEventlog.select<{ count: number }>(
|
|
27
29
|
`SELECT COUNT(*) AS count FROM ${SystemTables.EVENTLOG_META_TABLE}`,
|
|
28
30
|
)[0]!.count
|
|
29
31
|
|
|
30
32
|
const hashEventDef = memoizeByRef((event: EventDef.AnyWithoutFn) => Schema.hash(event.schema))
|
|
31
33
|
|
|
32
|
-
const processEvent = (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
34
|
+
const processEvent = Effect.fn(`@livestore/common:rematerializeFromEventlog:processEvent`)(function* (
|
|
35
|
+
row: SystemTables.EventlogMetaRow,
|
|
36
|
+
) {
|
|
37
|
+
const args = jsonParse(row.argsJson)
|
|
38
|
+
const eventEncoded = LiveStoreEvent.Client.EncodedWithMeta.make({
|
|
39
|
+
name: row.name,
|
|
40
|
+
args,
|
|
41
|
+
seqNum: {
|
|
42
|
+
global: row.seqNumGlobal,
|
|
43
|
+
client: row.seqNumClient,
|
|
44
|
+
rebaseGeneration: row.seqNumRebaseGeneration,
|
|
45
|
+
},
|
|
46
|
+
parentSeqNum: {
|
|
47
|
+
global: row.parentSeqNumGlobal,
|
|
48
|
+
client: row.parentSeqNumClient,
|
|
49
|
+
rebaseGeneration: row.parentSeqNumRebaseGeneration,
|
|
50
|
+
},
|
|
51
|
+
clientId: row.clientId,
|
|
52
|
+
sessionId: row.sessionId,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const resolution = yield* resolveEventDef(schema, {
|
|
56
|
+
operation: '@livestore/common:rematerializeFromEventlog:processEvent',
|
|
57
|
+
event: eventEncoded,
|
|
58
|
+
}).pipe(UnknownError.mapToUnknownError)
|
|
59
|
+
|
|
60
|
+
if (resolution._tag === 'unknown') {
|
|
61
|
+
// Old snapshots can contain newer events. Skip until the runtime has
|
|
62
|
+
// been updated; the event stays in the log for future replays.
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const { eventDef } = resolution
|
|
67
|
+
|
|
68
|
+
if (hashEventDef(eventDef) !== row.schemaHash) {
|
|
69
|
+
yield* Effect.logWarning(
|
|
70
|
+
`Schema hash mismatch for event definition ${row.name}. Trying to materialize event anyway.`,
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Checking whether the schema has changed in an incompatible way
|
|
75
|
+
yield* Schema.decodeUnknown(eventDef.schema)(args).pipe(
|
|
76
|
+
Effect.mapError((cause) =>
|
|
77
|
+
UnknownError.make({
|
|
78
|
+
cause,
|
|
79
|
+
note: `\
|
|
77
80
|
There was an error during rematerializing from the eventlog while decoding
|
|
78
81
|
the persisted event args for event definition "${row.name}".
|
|
79
82
|
This likely means the schema has changed in an incompatible way.
|
|
80
83
|
`,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
}),
|
|
85
|
+
),
|
|
86
|
+
)
|
|
84
87
|
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
yield* materializeEvent(eventEncoded, { skipEventlog: true })
|
|
89
|
+
})
|
|
87
90
|
|
|
88
91
|
const CHUNK_SIZE = 100
|
|
89
92
|
|
|
@@ -101,9 +104,9 @@ LIMIT ${CHUNK_SIZE}
|
|
|
101
104
|
SystemTables.EventlogMetaRow
|
|
102
105
|
>({ _tag: 'Initial' }, (item) => {
|
|
103
106
|
// End stream if no more rows
|
|
104
|
-
if (Chunk.isChunk(item) && item.length === 0) return Option.none()
|
|
107
|
+
if (Chunk.isChunk(item) === true && item.length === 0) return Option.none()
|
|
105
108
|
|
|
106
|
-
const lastId = Chunk.isChunk(item)
|
|
109
|
+
const lastId = Chunk.isChunk(item) === true
|
|
107
110
|
? Chunk.last(item).pipe(
|
|
108
111
|
Option.map((_) => ({ global: _.seqNumGlobal, client: _.seqNumClient })),
|
|
109
112
|
Option.getOrElse(() => EventSequenceNumber.Client.ROOT),
|
|
@@ -115,7 +118,7 @@ LIMIT ${CHUNK_SIZE}
|
|
|
115
118
|
$seqNumClient: lastId?.client,
|
|
116
119
|
} as any as PreparedBindValues),
|
|
117
120
|
)
|
|
118
|
-
const prevItem = Chunk.isChunk(item) ? item : Chunk.empty()
|
|
121
|
+
const prevItem = Chunk.isChunk(item) === true ? item : Chunk.empty()
|
|
119
122
|
return Option.some([prevItem, nextItem])
|
|
120
123
|
}).pipe(
|
|
121
124
|
Stream.bufferChunks({ capacity: 2 }),
|
|
@@ -129,7 +132,4 @@ LIMIT ${CHUNK_SIZE}
|
|
|
129
132
|
),
|
|
130
133
|
Stream.runDrain,
|
|
131
134
|
)
|
|
132
|
-
|
|
133
|
-
Effect.withPerformanceMeasure('@livestore/common:rematerializeFromEventlog'),
|
|
134
|
-
Effect.withSpan('@livestore/common:rematerializeFromEventlog'),
|
|
135
|
-
)
|
|
135
|
+
}, Effect.withPerformanceMeasure('@livestore/common:rematerializeFromEventlog'))
|
|
@@ -69,6 +69,21 @@ export type DefineEventOptions<TTo, TDerived extends boolean = false> = {
|
|
|
69
69
|
* @default false
|
|
70
70
|
*/
|
|
71
71
|
derived?: TDerived
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Marks the entire event as deprecated with a reason message.
|
|
75
|
+
* When this event is committed, a warning will be logged.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* Events.synced({
|
|
80
|
+
* name: 'v1.TodoRenamed',
|
|
81
|
+
* schema: Schema.Struct({ id: Schema.String, name: Schema.String }),
|
|
82
|
+
* deprecated: "Use 'v1.TodoUpdated' instead",
|
|
83
|
+
* })
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
deprecated?: string
|
|
72
87
|
}
|
|
73
88
|
|
|
74
89
|
/**
|
|
@@ -112,19 +127,20 @@ export const defineEvent = <TName extends string, TType, TEncoded = TType, TDeri
|
|
|
112
127
|
Object.defineProperty(makePartialEvent, 'options', {
|
|
113
128
|
value: {
|
|
114
129
|
clientOnly: options?.clientOnly ?? false,
|
|
115
|
-
facts: options?.facts
|
|
130
|
+
facts: options?.facts !== undefined
|
|
116
131
|
? (args, currentFacts) => {
|
|
117
132
|
const res = options.facts!(args, currentFacts)
|
|
118
133
|
return {
|
|
119
134
|
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(),
|
|
135
|
+
set: res.modify?.set !== undefined ? new Set(res.modify.set) : new Set(),
|
|
136
|
+
unset: res.modify?.unset !== undefined ? new Set(res.modify.unset) : new Set(),
|
|
122
137
|
},
|
|
123
|
-
require: res.require ? new Set(res.require) : new Set(),
|
|
138
|
+
require: res.require !== undefined ? new Set(res.require) : new Set(),
|
|
124
139
|
}
|
|
125
140
|
}
|
|
126
141
|
: undefined,
|
|
127
142
|
derived: options?.derived ?? false,
|
|
143
|
+
deprecated: options?.deprecated,
|
|
128
144
|
} satisfies EventDef.Any['options'],
|
|
129
145
|
})
|
|
130
146
|
|
|
@@ -163,7 +179,7 @@ export const synced = <TName extends string, TType, TEncoded = TType>(
|
|
|
163
179
|
args: {
|
|
164
180
|
name: TName
|
|
165
181
|
schema: Schema.Schema<TType, TEncoded>
|
|
166
|
-
} & Omit<DefineEventOptions<TType
|
|
182
|
+
} & Omit<DefineEventOptions<TType>, 'derived' | 'clientOnly'>,
|
|
167
183
|
): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: false })
|
|
168
184
|
|
|
169
185
|
/**
|
|
@@ -197,5 +213,5 @@ export const clientOnly = <TName extends string, TType, TEncoded = TType>(
|
|
|
197
213
|
args: {
|
|
198
214
|
name: TName
|
|
199
215
|
schema: Schema.Schema<TType, TEncoded>
|
|
200
|
-
} & Omit<DefineEventOptions<TType
|
|
216
|
+
} & Omit<DefineEventOptions<TType>, 'derived' | 'clientOnly'>,
|
|
201
217
|
): EventDef<TName, TType, TEncoded> => defineEvent({ ...args, clientOnly: true })
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { Effect, Logger, Schema } from '@livestore/utils/effect'
|
|
4
|
+
|
|
5
|
+
import { synced } from './define.ts'
|
|
6
|
+
import {
|
|
7
|
+
deprecated,
|
|
8
|
+
findDeprecatedFieldsWithValues,
|
|
9
|
+
getDeprecatedReason,
|
|
10
|
+
isDeprecated,
|
|
11
|
+
logDeprecationWarnings,
|
|
12
|
+
resetDeprecationWarnings,
|
|
13
|
+
} from './deprecated.ts'
|
|
14
|
+
|
|
15
|
+
describe('deprecated annotations', () => {
|
|
16
|
+
test('adds deprecation annotation to schema', () => {
|
|
17
|
+
const schema = Schema.String.pipe(deprecated('Use newField instead'))
|
|
18
|
+
expect(isDeprecated(schema)).toBe(true)
|
|
19
|
+
expect(getDeprecatedReason(schema)._tag).toBe('Some')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('works with optional fields in Struct', () => {
|
|
23
|
+
const struct = Schema.Struct({
|
|
24
|
+
oldField: Schema.optional(Schema.String).pipe(deprecated('Legacy')),
|
|
25
|
+
})
|
|
26
|
+
expect(findDeprecatedFieldsWithValues(struct, { oldField: 'x' })).toEqual([{ field: 'oldField', reason: 'Legacy' }])
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('non-deprecated schemas return false', () => {
|
|
30
|
+
expect(isDeprecated(Schema.String)).toBe(false)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('ignores deprecated fields without values', () => {
|
|
34
|
+
const schema = Schema.Struct({
|
|
35
|
+
id: Schema.String,
|
|
36
|
+
old: Schema.optional(Schema.String).pipe(deprecated('x')),
|
|
37
|
+
})
|
|
38
|
+
expect(findDeprecatedFieldsWithValues(schema, { id: '1' })).toEqual([])
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('finds multiple deprecated fields', () => {
|
|
42
|
+
const schema = Schema.Struct({
|
|
43
|
+
a: Schema.optional(Schema.String).pipe(deprecated('A')),
|
|
44
|
+
b: Schema.optional(Schema.String).pipe(deprecated('B')),
|
|
45
|
+
})
|
|
46
|
+
const result = findDeprecatedFieldsWithValues(schema, { a: '1', b: '2' })
|
|
47
|
+
expect(result).toHaveLength(2)
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
describe('logDeprecationWarnings', () => {
|
|
52
|
+
let logs: unknown[][]
|
|
53
|
+
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
resetDeprecationWarnings()
|
|
56
|
+
logs = []
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
afterEach(() => resetDeprecationWarnings())
|
|
60
|
+
|
|
61
|
+
const run = (effect: Effect.Effect<void>) =>
|
|
62
|
+
Effect.runSync(
|
|
63
|
+
effect.pipe(
|
|
64
|
+
Effect.provide(
|
|
65
|
+
Logger.replace(
|
|
66
|
+
Logger.defaultLogger,
|
|
67
|
+
Logger.make(({ message }) => logs.push(message as unknown[])),
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
test('logs event deprecation warning', () => {
|
|
74
|
+
const event = synced({ name: 'Old', schema: Schema.Struct({ id: Schema.String }), deprecated: 'Use New' })
|
|
75
|
+
run(logDeprecationWarnings(event, { id: '1' }))
|
|
76
|
+
expect(logs).toEqual([['@livestore/schema:deprecated-event', { event: 'Old', reason: 'Use New' }]])
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('logs field deprecation warning', () => {
|
|
80
|
+
const event = synced({
|
|
81
|
+
name: 'Ev',
|
|
82
|
+
schema: Schema.Struct({ old: Schema.optional(Schema.String).pipe(deprecated('Use new')) }),
|
|
83
|
+
})
|
|
84
|
+
run(logDeprecationWarnings(event, { old: 'x' }))
|
|
85
|
+
expect(logs).toEqual([['@livestore/schema:deprecated-field', { event: 'Ev', field: 'old', reason: 'Use new' }]])
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('deduplicates event warnings', () => {
|
|
89
|
+
const event = synced({ name: 'Dup', schema: Schema.Struct({ id: Schema.String }), deprecated: 'x' })
|
|
90
|
+
run(logDeprecationWarnings(event, { id: '1' }))
|
|
91
|
+
run(logDeprecationWarnings(event, { id: '2' }))
|
|
92
|
+
expect(logs).toHaveLength(1)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('deduplicates field warnings', () => {
|
|
96
|
+
const event = synced({
|
|
97
|
+
name: 'DupField',
|
|
98
|
+
schema: Schema.Struct({ old: Schema.optional(Schema.String).pipe(deprecated('x')) }),
|
|
99
|
+
})
|
|
100
|
+
run(logDeprecationWarnings(event, { old: 'a' }))
|
|
101
|
+
run(logDeprecationWarnings(event, { old: 'b' }))
|
|
102
|
+
expect(logs).toHaveLength(1)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test('no warning for non-deprecated event', () => {
|
|
106
|
+
const event = synced({ name: 'Normal', schema: Schema.Struct({ id: Schema.String }) })
|
|
107
|
+
run(logDeprecationWarnings(event, { id: '1' }))
|
|
108
|
+
expect(logs).toHaveLength(0)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('no warning when deprecated field is undefined', () => {
|
|
112
|
+
const event = synced({
|
|
113
|
+
name: 'Unused',
|
|
114
|
+
schema: Schema.Struct({ old: Schema.optional(Schema.String).pipe(deprecated('x')) }),
|
|
115
|
+
})
|
|
116
|
+
run(logDeprecationWarnings(event, {}))
|
|
117
|
+
expect(logs).toHaveLength(0)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test('logs both event and field warnings', () => {
|
|
121
|
+
const event = synced({
|
|
122
|
+
name: 'Both',
|
|
123
|
+
schema: Schema.Struct({ old: Schema.optional(Schema.String).pipe(deprecated('F')) }),
|
|
124
|
+
deprecated: 'E',
|
|
125
|
+
})
|
|
126
|
+
run(logDeprecationWarnings(event, { old: 'x' }))
|
|
127
|
+
expect(logs).toHaveLength(2)
|
|
128
|
+
})
|
|
129
|
+
})
|