@abloatai/ablo 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +101 -85
- package/dist/BaseSyncedStore.d.ts +85 -88
- package/dist/BaseSyncedStore.js +131 -147
- package/dist/Database.d.ts +54 -68
- package/dist/Database.js +97 -113
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +12 -16
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +46 -61
- package/dist/ModelRegistry.d.ts +21 -19
- package/dist/ModelRegistry.js +23 -27
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +5 -6
- package/dist/SyncClient.d.ts +112 -112
- package/dist/SyncClient.js +165 -172
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +9 -9
- package/dist/adapters/inMemoryStorage.js +9 -9
- package/dist/agent/Agent.d.ts +27 -32
- package/dist/agent/Agent.js +18 -19
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +5 -5
- package/dist/agent/session.d.ts +47 -44
- package/dist/agent/session.js +37 -48
- package/dist/agent/types.d.ts +26 -31
- package/dist/agent/types.js +6 -7
- package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
- package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
- package/dist/ai-sdk/coordinationContext.d.ts +46 -0
- package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +6 -7
- package/dist/ai-sdk/wrap.js +1 -1
- package/dist/auth/credentialPolicy.d.ts +69 -74
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +6 -5
- package/dist/auth/credentialSource.js +9 -10
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +31 -37
- package/dist/auth/schemas.d.ts +5 -4
- package/dist/auth/schemas.js +5 -4
- package/dist/batching/index.d.ts +19 -21
- package/dist/batching/index.js +14 -17
- package/dist/cli.cjs +167 -119
- package/dist/client/Ablo.d.ts +73 -73
- package/dist/client/Ablo.js +125 -160
- package/dist/client/ApiClient.d.ts +30 -19
- package/dist/client/ApiClient.js +133 -38
- package/dist/client/auth.d.ts +47 -47
- package/dist/client/auth.js +108 -117
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +5 -6
- package/dist/client/consoleLogger.js +5 -6
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +25 -30
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +152 -122
- package/dist/client/credentialEndpoint.d.ts +40 -42
- package/dist/client/credentialEndpoint.js +35 -36
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +9 -12
- package/dist/client/hostedEndpoints.js +9 -12
- package/dist/client/httpClient.d.ts +57 -53
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +47 -58
- package/dist/client/modelRegistration.d.ts +5 -9
- package/dist/client/modelRegistration.js +67 -87
- package/dist/client/options.d.ts +134 -157
- package/dist/client/options.js +3 -7
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +64 -75
- package/dist/client/resourceTypes.js +4 -10
- package/dist/client/schemaConfig.d.ts +31 -43
- package/dist/client/schemaConfig.js +38 -50
- package/dist/client/sessionMint.d.ts +16 -12
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +8 -9
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +15 -20
- package/dist/client/wsMutationExecutor.js +17 -23
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -4
- package/dist/coordination/index.d.ts +10 -8
- package/dist/coordination/index.js +14 -12
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -10
- package/dist/coordination/trace.js +13 -14
- package/dist/core/DatabaseManager.d.ts +5 -7
- package/dist/core/DatabaseManager.js +15 -19
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +22 -28
- package/dist/core/QueryView.d.ts +8 -8
- package/dist/core/QueryView.js +2 -2
- package/dist/core/StoreManager.d.ts +12 -14
- package/dist/core/StoreManager.js +21 -24
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +17 -12
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +42 -43
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +63 -61
- package/dist/core/storeContract.js +8 -12
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +107 -99
- package/dist/errorCodes.js +131 -132
- package/dist/errors.d.ts +160 -166
- package/dist/errors.js +155 -158
- package/dist/index.d.ts +30 -27
- package/dist/index.js +89 -86
- package/dist/interfaces/index.d.ts +102 -113
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +41 -40
- package/dist/mutators/RecordingTransaction.d.ts +16 -16
- package/dist/mutators/RecordingTransaction.js +31 -37
- package/dist/mutators/Transaction.d.ts +18 -26
- package/dist/mutators/Transaction.js +14 -20
- package/dist/mutators/UndoManager.d.ts +122 -131
- package/dist/mutators/UndoManager.js +145 -156
- package/dist/mutators/defineMutators.d.ts +23 -34
- package/dist/mutators/defineMutators.js +14 -20
- package/dist/mutators/inverseOp.d.ts +12 -15
- package/dist/mutators/inverseOp.js +12 -15
- package/dist/mutators/mutateActions.d.ts +10 -9
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +9 -8
- package/dist/mutators/readerActions.js +2 -2
- package/dist/mutators/undoApply.d.ts +31 -27
- package/dist/mutators/undoApply.js +26 -24
- package/dist/policy/index.d.ts +5 -3
- package/dist/policy/index.js +5 -3
- package/dist/policy/types.d.ts +104 -100
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +28 -23
- package/dist/query/client.js +45 -43
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +1 -1
- package/dist/react/AbloProvider.js +2 -2
- package/dist/react/context.d.ts +25 -28
- package/dist/react/context.js +9 -10
- package/dist/react/index.d.ts +41 -42
- package/dist/react/index.js +37 -38
- package/dist/react/internalContext.d.ts +17 -19
- package/dist/react/useAblo.d.ts +23 -22
- package/dist/react/useAblo.js +16 -14
- package/dist/react/useCurrentUserId.d.ts +8 -7
- package/dist/react/useCurrentUserId.js +8 -7
- package/dist/react/useErrorListener.d.ts +7 -7
- package/dist/react/useErrorListener.js +10 -11
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +8 -8
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useReactive.js +2 -2
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +21 -25
- package/dist/schema/coordination.js +21 -25
- package/dist/schema/ddl.d.ts +43 -39
- package/dist/schema/ddl.js +75 -68
- package/dist/schema/ddlLock.d.ts +20 -24
- package/dist/schema/ddlLock.js +18 -23
- package/dist/schema/diff.d.ts +99 -61
- package/dist/schema/diff.js +43 -34
- package/dist/schema/field.d.ts +37 -42
- package/dist/schema/field.js +35 -48
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +21 -23
- package/dist/schema/model.d.ts +118 -143
- package/dist/schema/model.js +22 -33
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +5 -3
- package/dist/schema/queries.d.ts +29 -31
- package/dist/schema/queries.js +23 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +16 -13
- package/dist/schema/residency.js +16 -13
- package/dist/schema/roles.d.ts +36 -43
- package/dist/schema/roles.js +31 -37
- package/dist/schema/schema.d.ts +33 -42
- package/dist/schema/schema.js +31 -32
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +28 -31
- package/dist/schema/serialize.js +27 -31
- package/dist/schema/sugar.d.ts +17 -32
- package/dist/schema/sugar.js +14 -29
- package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
- package/dist/schema/syncDeltaRow.js +89 -0
- package/dist/schema/tenancy.d.ts +44 -46
- package/dist/schema/tenancy.js +46 -48
- package/dist/server/adapter.d.ts +58 -58
- package/dist/server/adapter.js +13 -14
- package/dist/server/commit.d.ts +60 -64
- package/dist/server/index.d.ts +9 -10
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +70 -0
- package/dist/server/readConfig.js +8 -0
- package/dist/server/storageMode.d.ts +23 -0
- package/dist/server/storageMode.js +17 -0
- package/dist/source/adapter.d.ts +30 -25
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +30 -25
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +24 -23
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +9 -8
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +22 -25
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +17 -11
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +28 -28
- package/dist/source/connectorProtocol.d.ts +160 -0
- package/dist/source/connectorProtocol.js +162 -0
- package/dist/source/contract.d.ts +26 -27
- package/dist/source/contract.js +28 -29
- package/dist/source/factory.d.ts +46 -58
- package/dist/source/factory.js +22 -27
- package/dist/source/index.d.ts +7 -9
- package/dist/source/index.js +12 -14
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +9 -10
- package/dist/source/next.js +6 -7
- package/dist/source/pushQueue.d.ts +69 -47
- package/dist/source/pushQueue.js +32 -28
- package/dist/source/signing.d.ts +46 -17
- package/dist/source/signing.js +28 -11
- package/dist/source/types.d.ts +121 -104
- package/dist/source/types.js +13 -14
- package/dist/stores/ObjectStore.d.ts +10 -11
- package/dist/stores/ObjectStore.js +11 -12
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +7 -11
- package/dist/stores/SyncActionStore.js +13 -17
- package/dist/surface.d.ts +27 -20
- package/dist/surface.js +27 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
- package/dist/sync/ConnectionManager.d.ts +39 -50
- package/dist/sync/ConnectionManager.js +55 -66
- package/dist/sync/NetworkProbe.d.ts +24 -29
- package/dist/sync/NetworkProbe.js +63 -69
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
- package/dist/sync/SyncWebSocket.d.ts +139 -165
- package/dist/sync/SyncWebSocket.js +191 -223
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +11 -11
- package/dist/sync/bootstrapApply.d.ts +34 -24
- package/dist/sync/bootstrapApply.js +27 -19
- package/dist/sync/commitFrames.d.ts +21 -20
- package/dist/sync/commitFrames.js +18 -18
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +105 -23
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +12 -14
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +104 -104
- package/dist/sync/credentialLifecycle.js +140 -147
- package/dist/sync/deltaPipeline.d.ts +36 -34
- package/dist/sync/deltaPipeline.js +64 -65
- package/dist/sync/groupChange.d.ts +63 -61
- package/dist/sync/groupChange.js +74 -78
- package/dist/sync/heartbeat.d.ts +34 -33
- package/dist/sync/heartbeat.js +31 -31
- package/dist/sync/participants.d.ts +19 -19
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +17 -21
- package/dist/sync/syncCursor.js +17 -21
- package/dist/sync/syncPlan.d.ts +28 -36
- package/dist/sync/syncPlan.js +18 -19
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +35 -36
- package/dist/sync/wsFrameHandlers.js +63 -67
- package/dist/testing/fixtures/bootstrap.d.ts +12 -6
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +30 -33
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +11 -10
- package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
- package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
- package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +2 -2
- package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
- package/dist/testing/mocks/MockMutationExecutor.js +15 -14
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
- package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
- package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
- package/dist/testing/mocks/MockSyncContext.js +15 -13
- package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +181 -176
- package/dist/transactions/TransactionQueue.js +338 -350
- package/dist/transactions/TransactionStore.d.ts +6 -4
- package/dist/transactions/TransactionStore.js +6 -4
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +41 -17
- package/dist/transactions/coalesceRules.js +40 -17
- package/dist/transactions/commitPayload.d.ts +48 -52
- package/dist/transactions/commitPayload.js +48 -57
- package/dist/transactions/deltaConfirmation.d.ts +20 -22
- package/dist/transactions/deltaConfirmation.js +37 -45
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
- package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +71 -77
- package/dist/types/index.js +22 -22
- package/dist/types/modelData.d.ts +6 -8
- package/dist/types/modelData.js +5 -7
- package/dist/types/participant.d.ts +10 -11
- package/dist/types/participant.js +6 -8
- package/dist/types/streams.d.ts +208 -195
- package/dist/types/streams.js +7 -7
- package/dist/utils/asyncIterator.d.ts +25 -32
- package/dist/utils/asyncIterator.js +25 -32
- package/dist/utils/duration.d.ts +12 -15
- package/dist/utils/duration.js +12 -15
- package/dist/utils/mobxSetup.d.ts +53 -0
- package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
- package/dist/webhooks/events.d.ts +21 -16
- package/dist/webhooks/events.js +10 -8
- package/dist/webhooks/index.d.ts +5 -7
- package/dist/webhooks/index.js +5 -7
- package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
- package/dist/wire/delta.js +114 -0
- package/dist/wire/errorEnvelope.d.ts +30 -31
- package/dist/wire/errorEnvelope.js +34 -40
- package/dist/wire/frames.d.ts +79 -86
- package/dist/wire/frames.js +26 -33
- package/dist/wire/index.d.ts +14 -12
- package/dist/wire/index.js +30 -26
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +25 -32
- package/dist/wire/protocol.js +25 -32
- package/dist/wire/protocolVersion.d.ts +44 -40
- package/dist/wire/protocolVersion.js +44 -40
- package/docs/coordination.md +59 -0
- package/package.json +11 -10
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/read-config.d.ts +0 -67
- package/dist/server/read-config.js +0 -8
- package/dist/server/storage-mode.d.ts +0 -8
- package/dist/server/storage-mode.js +0 -28
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/transactions/optimistic.d.ts +0 -24
- package/dist/transactions/optimistic.js +0 -45
- package/dist/utils/mobx-setup.d.ts +0 -42
|
@@ -1,38 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* the
|
|
2
|
+
* Decides which sync groups a connection subscribes to as the user navigates,
|
|
3
|
+
* and pushes each change through the {@link SubscriptionTransport}'s
|
|
4
|
+
* `update_subscription` call. It smooths two kinds of churn so that opening and
|
|
5
|
+
* closing entities does not turn into a storm of subscription changes.
|
|
4
6
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* The first is hysteresis. Calling {@link SubscriptionManager.leave | leave}
|
|
8
|
+
* on a group does not unsubscribe it right away; the group stays subscribed for
|
|
9
|
+
* a grace period — its warm window — and drops only once that window lapses.
|
|
10
|
+
* Re-entering within the window costs nothing, since the group was never
|
|
11
|
+
* dropped, so rapid back-and-forth navigation becomes a cache hit rather than a
|
|
12
|
+
* repeated bootstrap.
|
|
9
13
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* (already subscribed → no bootstrap), and only when the warm TTL
|
|
15
|
-
* lapses does the group actually drop. This is the boundary hysteresis
|
|
16
|
-
* that turns deck-tab flipping from a re-bootstrap storm into a
|
|
17
|
-
* cache hit.
|
|
14
|
+
* The second is prominence. A group that holds an active write claim is pinned
|
|
15
|
+
* (see {@link SubscriptionManager.pin | pin}) and stays subscribed regardless
|
|
16
|
+
* of navigation, so a row someone is actively editing never loses its live
|
|
17
|
+
* updates. The `baseGroups` are permanent scopes that are always subscribed.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* `user:<id>`) that are always in the effective set.
|
|
27
|
-
*
|
|
28
|
-
* The effective set is recomputed and diffed against what was last sent;
|
|
29
|
-
* the transport's `update_subscription` is only called when it actually
|
|
30
|
-
* changes, so hysteresis genuinely suppresses network churn rather than
|
|
31
|
-
* just deferring it.
|
|
32
|
-
*
|
|
33
|
-
* Transport-agnostic: it depends only on {@link SubscriptionTransport},
|
|
34
|
-
* which `SyncWebSocket` satisfies structurally. `now` and the sweep timer
|
|
35
|
-
* are injectable so the policy is deterministic under test.
|
|
19
|
+
* The manager recomputes the full desired set on every change, diffs it against
|
|
20
|
+
* the set the transport last confirmed, and calls `update_subscription` only
|
|
21
|
+
* when the set actually changes — so the smoothing suppresses network traffic
|
|
22
|
+
* rather than merely deferring it. It depends only on
|
|
23
|
+
* {@link SubscriptionTransport}, which {@link SyncWebSocket} satisfies. The
|
|
24
|
+
* clock and the sweep timer are injectable so the policy is deterministic under
|
|
25
|
+
* test.
|
|
36
26
|
*/
|
|
37
27
|
function setsEqual(a, b) {
|
|
38
28
|
if (a.size !== b.size)
|
|
@@ -42,7 +32,7 @@ function setsEqual(a, b) {
|
|
|
42
32
|
return false;
|
|
43
33
|
return true;
|
|
44
34
|
}
|
|
45
|
-
export class
|
|
35
|
+
export class SubscriptionManager {
|
|
46
36
|
transport;
|
|
47
37
|
baseGroups;
|
|
48
38
|
warmTtlMs;
|
|
@@ -165,19 +155,15 @@ export class AreaOfInterestManager {
|
|
|
165
155
|
return [...this.lastSent];
|
|
166
156
|
}
|
|
167
157
|
/**
|
|
168
|
-
* Re-
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* the manager's
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* socket's server-side index matches local interest, even if warm/pinned
|
|
178
|
-
* groups drifted across the disconnect window. The connect-time URL
|
|
179
|
-
* already carries the last-acked set, so this is a correction frame, not
|
|
180
|
-
* the primary mechanism.
|
|
158
|
+
* Re-asserts the full desired set against the transport, forgetting what was
|
|
159
|
+
* previously confirmed. Call this after a reconnect: a fresh
|
|
160
|
+
* {@link SyncWebSocket} starts from the sync groups named in the connect-time
|
|
161
|
+
* URL, so the manager's diff baseline no longer reflects the new socket.
|
|
162
|
+
* Clearing that baseline makes the next reconcile push one
|
|
163
|
+
* `update_subscription` frame that re-establishes the current interest —
|
|
164
|
+
* including any warm or pinned groups that drifted while the connection was
|
|
165
|
+
* down. The connect-time URL already carries the last-acknowledged set, so
|
|
166
|
+
* this is a correction, not the primary mechanism.
|
|
181
167
|
*/
|
|
182
168
|
resync() {
|
|
183
169
|
this.lastSent = new Set();
|
|
@@ -214,14 +200,20 @@ export class AreaOfInterestManager {
|
|
|
214
200
|
this.lastSent = new Set(result.syncGroups);
|
|
215
201
|
}
|
|
216
202
|
catch {
|
|
217
|
-
// Transport unavailable (offline
|
|
218
|
-
// server rejected the set.
|
|
219
|
-
//
|
|
220
|
-
// `lastSent` unchanged
|
|
221
|
-
// next
|
|
222
|
-
// which
|
|
203
|
+
// Transport unavailable (offline, or socket not open) or the
|
|
204
|
+
// server rejected the set. Read interest is soft state, so enter,
|
|
205
|
+
// leave, and sweep never throw for an expected transient failure.
|
|
206
|
+
// Leaving `lastSent` unchanged keeps the pending diff; `resync()`
|
|
207
|
+
// on the next successful connect re-pushes the then-current desired
|
|
208
|
+
// set, which recovers any interest that changed while offline.
|
|
223
209
|
break;
|
|
224
210
|
}
|
|
211
|
+
// A concurrent reconcile() arriving during the await above sets
|
|
212
|
+
// `this.dirty` back to true (the coalescing path near line 245).
|
|
213
|
+
// TypeScript's intra-closure flow analysis can't see that cross-
|
|
214
|
+
// invocation mutation and reads this as always-false, but the loop
|
|
215
|
+
// is genuinely reentrant.
|
|
216
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
225
217
|
} while (this.dirty);
|
|
226
218
|
}
|
|
227
219
|
finally {
|
|
@@ -1,50 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - Automatic reconnection with exponential backoff
|
|
2
|
+
* Manages the WebSocket connection to the sync server. It owns the socket
|
|
3
|
+
* lifecycle (connect, reconnect, disconnect), receives and validates the
|
|
4
|
+
* incoming delta stream, sends commits and claims over the same socket, and
|
|
5
|
+
* reconnects automatically with exponential backoff. Consumers subscribe to its
|
|
6
|
+
* typed events (see {@link CoreSyncEventMap}) to react to deltas, presence, and
|
|
7
|
+
* connection changes.
|
|
9
8
|
*/
|
|
10
9
|
import { EventEmitter } from 'events';
|
|
11
10
|
import type { MutationOperation } from '../interfaces/index.js';
|
|
12
|
-
import { type ClientSyncDelta } from '../
|
|
11
|
+
import { type ClientSyncDelta } from '../wire/delta.js';
|
|
13
12
|
import type { ClaimError, ClaimRejection, StaleNotification, ReadDependency } from '../coordination/schema.js';
|
|
14
13
|
import { type CommitAck } from './commitFrames.js';
|
|
15
14
|
export type { CommitAck } from './commitFrames.js';
|
|
16
15
|
import { type AuthTokenGetter } from '../auth/credentialSource.js';
|
|
17
16
|
/**
|
|
18
|
-
* The wire delta the client receives.
|
|
19
|
-
* `clientSyncDeltaSchema`
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
17
|
+
* The wire delta the client receives. It is inferred from the canonical
|
|
18
|
+
* `clientSyncDeltaSchema` so the client and server share one contract rather
|
|
19
|
+
* than two hand-maintained definitions. The action vocabulary
|
|
20
|
+
* (`I`/`U`/`D`/`A`/`V`/`C`/`G`/`S`) and the client-only extras (`metadata`,
|
|
21
|
+
* `clientMutationId`, and the deprecated flat `createdBy`) live in that schema;
|
|
22
|
+
* see its own documentation for the full field reference.
|
|
24
23
|
*/
|
|
25
24
|
export type SyncDelta = ClientSyncDelta;
|
|
26
25
|
/**
|
|
27
|
-
* Payload for
|
|
28
|
-
*
|
|
26
|
+
* Payload for an older actionType `'G'` delta. It carries both the added and
|
|
27
|
+
* removed sync groups in one delta and forces a full re-bootstrap.
|
|
29
28
|
*/
|
|
30
29
|
export interface SyncGroupChangePayload {
|
|
31
30
|
removedGroups: string[];
|
|
32
31
|
addedGroups: string[];
|
|
33
32
|
}
|
|
34
33
|
/**
|
|
35
|
-
* Payload for incremental actionType 'G'
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* re-bootstrap required.
|
|
34
|
+
* Payload for an incremental actionType `'G'` delta. It signals that the
|
|
35
|
+
* recipient has joined a single sync group; the following `'C'` (covering)
|
|
36
|
+
* deltas deliver the newly visible entities. No re-bootstrap is required.
|
|
39
37
|
*/
|
|
40
38
|
export interface GroupAddedPayload {
|
|
41
39
|
group: string;
|
|
42
40
|
userId: string;
|
|
43
41
|
}
|
|
44
42
|
/**
|
|
45
|
-
* Payload for actionType 'S'
|
|
46
|
-
*
|
|
47
|
-
*
|
|
43
|
+
* Payload for an actionType `'S'` delta. It signals that the recipient has lost
|
|
44
|
+
* access to a sync group; the client purges the affected local entities and
|
|
45
|
+
* updates its subscription metadata.
|
|
48
46
|
*/
|
|
49
47
|
export interface GroupRemovedPayload {
|
|
50
48
|
group: string;
|
|
@@ -73,27 +71,25 @@ export interface SyncWebSocketOptions {
|
|
|
73
71
|
*/
|
|
74
72
|
collaborationEvents?: string[];
|
|
75
73
|
/**
|
|
76
|
-
*
|
|
77
|
-
* (session
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* session auth. The server reads this as the `kind` query param.
|
|
74
|
+
* The participant kind declared on the WebSocket upgrade. Defaults to
|
|
75
|
+
* `'user'` (session auth, the web app). Agent runtimes pass `'agent'` so the
|
|
76
|
+
* server verifies them by capability token instead of session auth. The
|
|
77
|
+
* server reads this as the `kind` query parameter.
|
|
81
78
|
*/
|
|
82
79
|
kind?: 'user' | 'agent' | 'system';
|
|
83
80
|
/**
|
|
84
|
-
* The agent's bearer credential — a restricted (`rk_`) API key. When
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* migration.)
|
|
81
|
+
* The agent's bearer credential — a restricted (`rk_`) API key. When set, it
|
|
82
|
+
* is sent in the `ablo.bearer.<token>` WebSocket subprotocol so the credential
|
|
83
|
+
* stays out of URLs and proxy logs. Required for `kind: 'agent'` and ignored
|
|
84
|
+
* for `kind: 'user'`.
|
|
89
85
|
*/
|
|
90
86
|
capabilityToken?: string;
|
|
91
87
|
/**
|
|
92
|
-
*
|
|
93
|
-
* instead of a copied `capabilityToken`, so reconnects use
|
|
94
|
-
* from the SDK's single
|
|
88
|
+
* Getter for the current credential. When provided, the WebSocket upgrade
|
|
89
|
+
* reads it instead of a copied `capabilityToken`, so reconnects always use
|
|
90
|
+
* the freshest token from the SDK's single credential source. Preferred over
|
|
91
|
+
* `getCapabilityToken`.
|
|
95
92
|
*/
|
|
96
|
-
/** Shared SDK auth getter. Preferred internal name. */
|
|
97
93
|
getAuthToken?: AuthTokenGetter;
|
|
98
94
|
/** @deprecated Use `getAuthToken`. Kept for direct low-level callers. */
|
|
99
95
|
getCapabilityToken?: AuthTokenGetter;
|
|
@@ -116,14 +112,11 @@ export interface BootstrapDataEvent {
|
|
|
116
112
|
cursor?: string;
|
|
117
113
|
}
|
|
118
114
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* the union of what the server actually sends. Stripping fields at
|
|
125
|
-
* this layer (the prior bug) silently broke rich-presence consumers
|
|
126
|
-
* that needed `kind`, `activity`, `isAgent` to dispatch correctly.
|
|
115
|
+
* Payload of a presence-update event, mirroring the `payload` field of the wire
|
|
116
|
+
* frame. This type is the union of everything the server may send; each
|
|
117
|
+
* consumer reads its own subset. Forwarding the full shape, rather than
|
|
118
|
+
* stripping fields here, is deliberate — presence consumers rely on `kind`,
|
|
119
|
+
* `activity`, and `isAgent` to dispatch correctly.
|
|
127
120
|
*/
|
|
128
121
|
export interface PresenceUpdateEvent {
|
|
129
122
|
/** Server-stamped transition: 'enter' on join + roster snapshot,
|
|
@@ -151,16 +144,15 @@ export interface PresenceUpdateEvent {
|
|
|
151
144
|
* not self-declare — server is the source of truth. */
|
|
152
145
|
isAgent?: boolean;
|
|
153
146
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* boolean
|
|
157
|
-
* raw wire input — normalize via `participantKindFromWire`.
|
|
147
|
+
* The canonical participant kind (`'user' | 'agent' | 'system'`), stamped by
|
|
148
|
+
* the server. Some servers omit it, in which case readers fall back to the
|
|
149
|
+
* lossy `isAgent` boolean, which cannot express `'system'`. Typed as `string`
|
|
150
|
+
* because it is raw wire input — normalize it via `participantKindFromWire`.
|
|
158
151
|
*/
|
|
159
152
|
participantKind?: string;
|
|
160
153
|
timestamp?: number;
|
|
161
|
-
/**
|
|
162
|
-
*
|
|
163
|
-
* shape mirrors `apps/sync-server/src/hub/types.ts Claim`. */
|
|
154
|
+
/** Every presence frame carries this participant's open claims, stamped by
|
|
155
|
+
* the server, so peers see them without a separate channel. */
|
|
164
156
|
activeClaims?: {
|
|
165
157
|
claimId: string;
|
|
166
158
|
entityType: string;
|
|
@@ -178,10 +170,10 @@ export interface PresenceUpdateEvent {
|
|
|
178
170
|
declaredAt: number;
|
|
179
171
|
expiresAt: number;
|
|
180
172
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
173
|
+
* The claim's lifecycle state. When absent, the reader treats it as
|
|
174
|
+
* `'active'`. A terminal state (`committed`, `expired`, or `canceled`) rides
|
|
175
|
+
* one final frame as the claim ends, so peers learn how it resolved before
|
|
176
|
+
* it drops from the active set.
|
|
185
177
|
*/
|
|
186
178
|
status?: 'active' | 'committed' | 'expired' | 'canceled';
|
|
187
179
|
error?: ClaimError;
|
|
@@ -256,14 +248,19 @@ export interface CoreSyncEventMap {
|
|
|
256
248
|
claim_granted: [Record<string, unknown>];
|
|
257
249
|
claim_lost: [Record<string, unknown>];
|
|
258
250
|
/**
|
|
259
|
-
*
|
|
260
|
-
* `
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
*
|
|
251
|
+
* Reply to an outbound `claim_heartbeat` — the lease's fate: `held` with
|
|
252
|
+
* the extended `expiresAt`, `queued` with the current `position`, or
|
|
253
|
+
* `lost`. Correlated back to the awaiting caller by `claimId` in the
|
|
254
|
+
* claim stream.
|
|
255
|
+
*/
|
|
256
|
+
claim_heartbeat_ack: [Record<string, unknown>];
|
|
257
|
+
/**
|
|
258
|
+
* A committed write guarded with `onStale: 'notify'` collided with a
|
|
259
|
+
* concurrent change. Rather than forcing an outcome, the engine returns the
|
|
260
|
+
* conflicting field's current value so the actor — an agent reasoning over the
|
|
261
|
+
* change, or a person watching the row — can reconcile it. The commit itself
|
|
262
|
+
* succeeded; the held operations were not written, and the actor re-issues
|
|
263
|
+
* them once it has reconciled.
|
|
267
264
|
*/
|
|
268
265
|
'conflict:notified': [{
|
|
269
266
|
clientTxId: string;
|
|
@@ -282,7 +279,7 @@ export type DefaultCollaborationEvents = Record<string, never>;
|
|
|
282
279
|
* `Record<string, ...>` requires an implicit string index signature, which
|
|
283
280
|
* TypeScript interfaces don't have. So a closed interface like Ablo's
|
|
284
281
|
* `AbloCollaborationEvents` would fail to satisfy `Record<string, unknown[]>`,
|
|
285
|
-
* even though every one of its values
|
|
282
|
+
* even though every one of its values is a tuple. This mapped form iterates
|
|
286
283
|
* over `keyof T` instead of demanding a string index, so it accepts both
|
|
287
284
|
* closed interfaces and open Record types — while still enforcing
|
|
288
285
|
* "every value is an array."
|
|
@@ -315,10 +312,10 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
315
312
|
/** Periodic catchup interval — polls for missed deltas every 30s while connected */
|
|
316
313
|
private catchupInterval;
|
|
317
314
|
/**
|
|
318
|
-
* Application-level heartbeat
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
315
|
+
* Application-level heartbeat: ping every 30 seconds and force-close after a
|
|
316
|
+
* 10-second silence. The {@link HeartbeatController} holds the timing and the
|
|
317
|
+
* zombie-socket rationale; the closures below are the only socket access it
|
|
318
|
+
* gets.
|
|
322
319
|
*/
|
|
323
320
|
private readonly heartbeat;
|
|
324
321
|
private isConnecting;
|
|
@@ -349,20 +346,19 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
349
346
|
private lastForceCloseReason;
|
|
350
347
|
private sessionErrorAt;
|
|
351
348
|
/**
|
|
352
|
-
* Sync-position state
|
|
353
|
-
* cursor
|
|
354
|
-
*
|
|
349
|
+
* Sync-position state: the lastSyncId watermark, version vector, and server
|
|
350
|
+
* cursor. The advance discipline is documented at `sendAck` and `handleDelta`;
|
|
351
|
+
* the state itself lives in {@link SyncCursor}.
|
|
355
352
|
*/
|
|
356
353
|
private readonly cursor;
|
|
357
354
|
/** Registered collaboration event keys (colon format) for dispatch in onmessage */
|
|
358
355
|
private collaborationEventTypes;
|
|
359
356
|
/**
|
|
360
|
-
*
|
|
361
|
-
* (
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
* state it captures exists.
|
|
357
|
+
* A minimal session adapter handed to the inbound frame dispatch table
|
|
358
|
+
* ({@link dispatchWsFrame}). It exposes only the members the handlers touch;
|
|
359
|
+
* the closure members read live state so a reassignment here (for example the
|
|
360
|
+
* `pendingSubscriptions` reset on close) cannot strand a handler on a stale
|
|
361
|
+
* reference. Built in the constructor, after the state it captures exists.
|
|
366
362
|
*/
|
|
367
363
|
private readonly frameSession;
|
|
368
364
|
/**
|
|
@@ -373,10 +369,10 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
373
369
|
*/
|
|
374
370
|
private pendingMutations;
|
|
375
371
|
/**
|
|
376
|
-
* In-flight `claim` requests keyed by claimId. Resolved when the
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
372
|
+
* In-flight `claim` requests keyed by claimId. Resolved when the matching
|
|
373
|
+
* `claim_ack` arrives, or rejected on timeout or disconnect — the same
|
|
374
|
+
* request/response pattern as `pendingMutations`, multiplexed over the one
|
|
375
|
+
* connection.
|
|
380
376
|
*/
|
|
381
377
|
private pendingClaims;
|
|
382
378
|
/**
|
|
@@ -411,28 +407,25 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
411
407
|
*/
|
|
412
408
|
private setupEventHandlers;
|
|
413
409
|
/**
|
|
414
|
-
*
|
|
415
|
-
* seam every inbound delta (`delta` frame, batch element, `sync_response`
|
|
416
|
-
* replay,
|
|
417
|
-
* persisted
|
|
410
|
+
* Validates and normalizes a wire delta at the receive boundary — the single
|
|
411
|
+
* seam every inbound delta (a `delta` frame, a batch element, a `sync_response`
|
|
412
|
+
* replay, or the older bare frame) passes through before it is emitted,
|
|
413
|
+
* persisted, or allowed to advance any watermark.
|
|
418
414
|
*
|
|
419
|
-
* Normalization
|
|
420
|
-
* - `id`: the contract says `number`, but
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
* nullable (and `createdBy` as a nested ParticipantRef); the client
|
|
429
|
-
* contract types them as optional strings and never reads them.
|
|
430
|
-
* Normalize to absent instead of rejecting every real server delta.
|
|
415
|
+
* Normalization keeps already-deployed servers compatible:
|
|
416
|
+
* - `id`: the contract says `number`, but some servers have sent the raw
|
|
417
|
+
* Postgres BIGINT serialization — a string — and every downstream watermark
|
|
418
|
+
* gate treats a string as invalid, so acks are withheld, the resume cursor
|
|
419
|
+
* never advances, and every reconnect replays from zero. Coerce it once here.
|
|
420
|
+
* - `transactionId` / `createdBy`: the server projection sends these as
|
|
421
|
+
* nullable (and `createdBy` as a nested reference); the client contract
|
|
422
|
+
* types them as optional strings and never reads them, so normalize them to
|
|
423
|
+
* absent rather than reject every real server delta.
|
|
431
424
|
*
|
|
432
|
-
* Validation
|
|
433
|
-
* contract. A frame that fails is
|
|
434
|
-
*
|
|
435
|
-
*
|
|
425
|
+
* Validation runs `clientSyncDeltaSchema.safeParse`, the canonical wire
|
|
426
|
+
* contract. A frame that fails is dropped (returns `null`) with a debug log
|
|
427
|
+
* and an observability breadcrumb; it is never applied. There is one parse per
|
|
428
|
+
* delta — callers must not re-parse.
|
|
436
429
|
*/
|
|
437
430
|
private normalizeWireDelta;
|
|
438
431
|
/**
|
|
@@ -441,15 +434,13 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
441
434
|
*/
|
|
442
435
|
private handleDelta;
|
|
443
436
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
* `
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
* cursor never gets ahead of the persisted view, so reconnect/
|
|
452
|
-
* catch-up requests can't accidentally skip un-persisted deltas.
|
|
437
|
+
* Acknowledges received deltas up to the given syncId. This is the only place
|
|
438
|
+
* `this.cursor.lastSyncId` moves forward for live deltas. The store calls it
|
|
439
|
+
* with its persisted-syncId watermark — that is, only after the deltas have
|
|
440
|
+
* committed to local storage. Advancing the cursor here, rather than at
|
|
441
|
+
* receipt in `handleDelta` or `handleSyncResponse`, keeps the cursor from
|
|
442
|
+
* getting ahead of the persisted view, so reconnect and catch-up requests
|
|
443
|
+
* cannot skip un-persisted deltas.
|
|
453
444
|
*/
|
|
454
445
|
private sendAck;
|
|
455
446
|
/**
|
|
@@ -461,23 +452,15 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
461
452
|
*/
|
|
462
453
|
send(message: any): void;
|
|
463
454
|
/**
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
* `handleCommit` path on `apps/sync-server/src/hub/Hub.ts` (see the
|
|
469
|
-
* dispatch at Hub.ts:737).
|
|
470
|
-
*
|
|
471
|
-
* Historical naming note: this was originally `sendBatchAck` back when
|
|
472
|
-
* the Go sync-engine used a GraphQL `batchAck` mutation. The TS
|
|
473
|
-
* sync-server uses `type: 'commit'` over WebSocket exclusively. The
|
|
474
|
-
* method name now matches the wire protocol so the ack/commit naming
|
|
475
|
-
* confusion stops here.
|
|
455
|
+
* Sends a `commit` mutation request over the existing WebSocket and resolves
|
|
456
|
+
* when the server's `mutation_result` frame comes back with the same
|
|
457
|
+
* `clientTxId`. The wire frame is `{ type: 'commit', payload: { operations,
|
|
458
|
+
* clientTxId } }`.
|
|
476
459
|
*
|
|
477
|
-
* Times out after
|
|
478
|
-
* during an in-flight mutation (network flap, server restart);
|
|
479
|
-
*
|
|
480
|
-
*
|
|
460
|
+
* Times out after 15 seconds of silence from the server. The socket may close
|
|
461
|
+
* during an in-flight mutation (a network flap, a server restart); this does
|
|
462
|
+
* not auto-retry — the caller's transaction queue owns retry and offline
|
|
463
|
+
* replay, and the SDK does not duplicate that logic.
|
|
481
464
|
*/
|
|
482
465
|
sendCommit(operations: readonly MutationOperation[], clientTxId: string, timeoutMs?: number, causedByTaskId?: string | null, reads?: readonly ReadDependency[] | null): Promise<CommitAck>;
|
|
483
466
|
/**
|
|
@@ -490,21 +473,14 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
490
473
|
*/
|
|
491
474
|
sendCommitQueued(operations: readonly MutationOperation[], clientTxId: string, causedByTaskId?: string | null, reads?: readonly ReadDependency[] | null): void;
|
|
492
475
|
/**
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
* Returns a promise that resolves with the server-canonicalized
|
|
499
|
-
* `syncGroups` and effective `ttlSeconds` once `claim_ack` arrives,
|
|
500
|
-
* or rejects with a typed error on `success: false` ack /
|
|
501
|
-
* timeout / disconnect.
|
|
476
|
+
* Activates a participant claim on this connection. One connection can hold
|
|
477
|
+
* several concurrent claims at once, each scoped to a different set of sync
|
|
478
|
+
* groups, so the SDK reuses the existing connection instead of opening a
|
|
479
|
+
* separate socket per scope.
|
|
502
480
|
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
* `apps/sync-server/docs/PARTICIPANT_CLAIMS.md` for the migration
|
|
507
|
-
* framing (Phase A.1).
|
|
481
|
+
* Returns a promise that resolves with the server-canonicalized `syncGroups`
|
|
482
|
+
* and effective `ttlSeconds` once `claim_ack` arrives, or rejects with a typed
|
|
483
|
+
* error on a failed ack, a timeout, or a disconnect.
|
|
508
484
|
*/
|
|
509
485
|
sendClaim(claimId: string, syncGroups: readonly string[], options?: {
|
|
510
486
|
capabilityToken?: string;
|
|
@@ -525,22 +501,21 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
525
501
|
*/
|
|
526
502
|
sendRelease(claimId: string): void;
|
|
527
503
|
/**
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
* area-of-interest
|
|
531
|
-
*
|
|
532
|
-
* chosen at connect.
|
|
504
|
+
* Moves this connection's read interest — replaces the connection-level sync
|
|
505
|
+
* groups mid-session as the user opens and closes entities. This is the
|
|
506
|
+
* area-of-interest navigation primitive: the server fans out deltas only for
|
|
507
|
+
* the groups currently in view, rather than the fixed set chosen at connect.
|
|
533
508
|
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
* requesting a group outside its allowlist), timeout, or disconnect. On
|
|
538
|
-
* success the new set is recorded as `options.syncGroups
|
|
539
|
-
*
|
|
509
|
+
* This is a full-set replace: pass the complete new group list, not a delta.
|
|
510
|
+
* Resolves with the server's effective set once `subscription_ack` arrives;
|
|
511
|
+
* rejects (with a typed error) on a scope denial (a restricted `rk_` key
|
|
512
|
+
* requesting a group outside its allowlist), a timeout, or a disconnect. On
|
|
513
|
+
* success the new set is recorded as `options.syncGroups`, so a later reconnect
|
|
514
|
+
* re-subscribes to the current interest rather than the connect-time set.
|
|
540
515
|
*
|
|
541
|
-
* Distinct from {@link sendClaim} (write
|
|
542
|
-
* the read side
|
|
543
|
-
* by the connection credential's grant.
|
|
516
|
+
* Distinct from {@link sendClaim} (a write claim, per operation, with a TTL):
|
|
517
|
+
* this is the read side, carries no capability token of its own, and is
|
|
518
|
+
* bounded by the connection credential's grant.
|
|
544
519
|
*/
|
|
545
520
|
updateSubscription(syncGroups: readonly string[], options?: {
|
|
546
521
|
timeoutMs?: number;
|
|
@@ -548,9 +523,9 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
548
523
|
syncGroups: string[];
|
|
549
524
|
}>;
|
|
550
525
|
/**
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
526
|
+
* Sets a fixed credential for callers that construct the socket directly. The
|
|
527
|
+
* SDK instead supplies `getAuthToken`, so reconnects read the shared
|
|
528
|
+
* credential source rather than this copied value.
|
|
554
529
|
*/
|
|
555
530
|
setCapabilityToken(token: string): void;
|
|
556
531
|
getAuthToken(): string | undefined;
|
|
@@ -670,7 +645,7 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
670
645
|
*/
|
|
671
646
|
getLastSyncId(): number;
|
|
672
647
|
/**
|
|
673
|
-
*
|
|
648
|
+
* Requests an incremental sync from the server, starting at the current cursor.
|
|
674
649
|
*/
|
|
675
650
|
requestIncrementalSync(): Promise<void>;
|
|
676
651
|
/**
|
|
@@ -689,13 +664,12 @@ export declare class SyncWebSocket<TCollaboration extends EventMap<TCollaboratio
|
|
|
689
664
|
*/
|
|
690
665
|
private handleBootstrapResponse;
|
|
691
666
|
/**
|
|
692
|
-
*
|
|
693
|
-
* forwarded as-is so every consumer
|
|
694
|
-
*
|
|
695
|
-
*
|
|
696
|
-
* `kind`, `activity`, `syncGroups`, `isAgent` for rich consumers.
|
|
667
|
+
* Handles a presence update from the server. The wire frame's payload is
|
|
668
|
+
* forwarded as-is, so every consumer reads the same shape; stripping fields
|
|
669
|
+
* here would drop `kind`, `activity`, `syncGroups`, and `isAgent` for
|
|
670
|
+
* consumers that need them.
|
|
697
671
|
*
|
|
698
|
-
*
|
|
672
|
+
* The wire frame is:
|
|
699
673
|
* { type: 'presence_update', payload: { kind, userId, status,
|
|
700
674
|
* syncGroups, activity, isAgent, timestamp, activeClaims } }
|
|
701
675
|
*/
|