@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,27 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* BaseSyncedStore and drives this pipeline via `enqueueDelta` +
|
|
13
|
-
* `flushPendingDeltas`.
|
|
2
|
+
* The pipeline that takes incoming deltas from the server and lands them in
|
|
3
|
+
* local state. It has four stages: deduplicating deltas by state signature,
|
|
4
|
+
* per-delta bookkeeping and enqueue, a debounce for live traffic, and a flush
|
|
5
|
+
* that writes to the local store and then the in-memory pool. Every call it
|
|
6
|
+
* makes back into the surrounding store — resolving state fields, identifying
|
|
7
|
+
* custom entities, deduplicating, flushing, handling sync-group changes —
|
|
8
|
+
* routes through the {@link DeltaPipelineContext} interface, so a subclass that
|
|
9
|
+
* overrides any of those hooks still takes effect. The atomic frame-apply entry
|
|
10
|
+
* point lives on the store and drives this pipeline through {@link enqueueDelta}
|
|
11
|
+
* and {@link flushPendingDeltas}.
|
|
14
12
|
*/
|
|
15
13
|
import { runInAction } from 'mobx';
|
|
16
14
|
import { getContext } from '../context.js';
|
|
17
|
-
import { ModelScope } from '../
|
|
15
|
+
import { ModelScope } from '../InstanceCache.js';
|
|
18
16
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* re-bootstrap
|
|
24
|
-
*
|
|
17
|
+
* Handles a sync-group ('G' or 'S') delta whose handler rejected after the
|
|
18
|
+
* applied watermark had already advanced. That delta will never be redelivered,
|
|
19
|
+
* so a failed security clear — revoked data that must not stay cached — would
|
|
20
|
+
* otherwise fail silently. The safe fallback is blunt: drop the whole in-memory
|
|
21
|
+
* pool and force a full re-bootstrap, rebuilding local state from the server.
|
|
22
|
+
* It never throws, because it runs inside the pipeline's fire-and-forget path.
|
|
25
23
|
*/
|
|
26
24
|
export function handleGroupHandlerFailure(ctx, delta, error) {
|
|
27
25
|
getContext().logger.error('Your access changed but cached data could not be cleared — resetting local data.', {
|
|
@@ -41,7 +39,7 @@ export function handleGroupHandlerFailure(ctx, delta, error) {
|
|
|
41
39
|
// Best-effort: the reconnect/bootstrap cycle self-heals on next connect.
|
|
42
40
|
}
|
|
43
41
|
}
|
|
44
|
-
/**
|
|
42
|
+
/** Builds a small signature of a delta's state fields, used to detect no-op duplicate deltas. */
|
|
45
43
|
function extractStateSignature(ctx, delta) {
|
|
46
44
|
if (!delta.data || typeof delta.data !== 'object')
|
|
47
45
|
return null;
|
|
@@ -110,19 +108,19 @@ export function deduplicateDeltas(ctx, deltas) {
|
|
|
110
108
|
return result.sort((a, b) => a.id - b.id);
|
|
111
109
|
}
|
|
112
110
|
/**
|
|
113
|
-
*
|
|
114
|
-
* pushed onto `pendingDeltas`
|
|
115
|
-
*
|
|
116
|
-
* deferred
|
|
117
|
-
* sync-group
|
|
118
|
-
* whether to debounce
|
|
111
|
+
* Performs per-delta bookkeeping and enqueues the delta. Returns `true` when
|
|
112
|
+
* the delta was pushed onto `pendingDeltas` — a regular batchable insert,
|
|
113
|
+
* update, covering, or delete that a later flush must drain — and `false` when
|
|
114
|
+
* it was skipped as a duplicate, deferred into the bootstrap queue, or handled
|
|
115
|
+
* immediately (a 'G'/'S' sync-group change). It does not schedule the flush
|
|
116
|
+
* itself; the caller chooses whether to debounce live traffic or flush a
|
|
117
|
+
* catch-up frame atomically.
|
|
119
118
|
*/
|
|
120
119
|
export function enqueueDelta(ctx, delta, options = {}) {
|
|
121
120
|
// Dedup guard — skip already-processed deltas. The `applied` watermark is a
|
|
122
|
-
// valid skip threshold
|
|
123
|
-
// catch-up frame bypasses it
|
|
124
|
-
//
|
|
125
|
-
// to be silently dropped.
|
|
121
|
+
// valid skip threshold only for in-order live traffic; an authoritative
|
|
122
|
+
// catch-up frame bypasses it, so an out-of-order live delta that advanced the
|
|
123
|
+
// watermark can't cause the frame's lower ids to be dropped silently.
|
|
126
124
|
if (!options.authoritative && delta.id > 0 && delta.id <= ctx.highestProcessedSyncId) {
|
|
127
125
|
return false;
|
|
128
126
|
}
|
|
@@ -135,10 +133,11 @@ export function enqueueDelta(ctx, delta, options = {}) {
|
|
|
135
133
|
}
|
|
136
134
|
// Advance watermark
|
|
137
135
|
ctx.advanceApplied(delta.id);
|
|
138
|
-
// Sync group added — handle immediately.
|
|
139
|
-
// (addedGroups/removedGroups) and incremental (group/userId) payloads.
|
|
140
|
-
//
|
|
141
|
-
// handler (a failed security clear) must trigger the fallback
|
|
136
|
+
// Sync group added — handle immediately. Accepts both the batched
|
|
137
|
+
// (addedGroups/removedGroups) and incremental (group/userId) payloads. This
|
|
138
|
+
// is deliberately not fire-and-forget: the watermark has already advanced, so
|
|
139
|
+
// a rejected handler (a failed security clear) must trigger the fallback
|
|
140
|
+
// rather than vanish.
|
|
142
141
|
if (delta.actionType === 'G') {
|
|
143
142
|
void ctx.handleSyncGroupChange(delta).catch((error) => {
|
|
144
143
|
handleGroupHandlerFailure(ctx, delta, error);
|
|
@@ -154,16 +153,16 @@ export function enqueueDelta(ctx, delta, options = {}) {
|
|
|
154
153
|
});
|
|
155
154
|
return false;
|
|
156
155
|
}
|
|
157
|
-
//
|
|
158
|
-
// must run
|
|
159
|
-
// pending update transactions for soon-deleted children don't race
|
|
160
|
-
//
|
|
161
|
-
// same batched path as
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
// path
|
|
165
|
-
// `flushPendingDeltas` handles
|
|
166
|
-
//
|
|
156
|
+
// Delete — run the cascade cancel immediately (O(1) through the foreign-key
|
|
157
|
+
// index; it must run before any later update on the same model lands, so
|
|
158
|
+
// pending update transactions for soon-deleted children don't race their
|
|
159
|
+
// parent's delete). The persistence and pool write still goes through the
|
|
160
|
+
// same batched path as updates: flushing each delete on its own produced one
|
|
161
|
+
// store write, one pool mutation, and one `models:changed` event per row, so
|
|
162
|
+
// deleting a parent with many children fanned out into many of each, whereas
|
|
163
|
+
// the batched path collapses them into one per flush. Deduplication in
|
|
164
|
+
// `flushPendingDeltas` handles an update-then-delete on the same model by
|
|
165
|
+
// replaying in arrival order.
|
|
167
166
|
if (delta.actionType === 'D') {
|
|
168
167
|
ctx.cascadeCancelTransactionsForDeletedParent(delta.modelName, delta.modelId);
|
|
169
168
|
}
|
|
@@ -183,13 +182,16 @@ export function scheduleDeltaFlush(ctx) {
|
|
|
183
182
|
}, ctx.smartSyncOptions.batchingDelay);
|
|
184
183
|
}
|
|
185
184
|
}
|
|
186
|
-
/**
|
|
187
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Flushes the queued deltas: deduplicates them, applies custom-entity deltas
|
|
187
|
+
* straight to the pool, writes the rest to the local store and then the pool,
|
|
188
|
+
* and advances the acknowledgement cursor once the store write has committed.
|
|
189
|
+
*/
|
|
188
190
|
export async function flushPendingDeltas(ctx) {
|
|
189
191
|
if (ctx.pendingDeltas.length === 0)
|
|
190
192
|
return;
|
|
191
193
|
const deduplicatedDeltas = ctx.deduplicateDeltas(ctx.pendingDeltas);
|
|
192
|
-
// Custom entities → apply
|
|
194
|
+
// Custom entities → apply straight to the pool, skipping the local store.
|
|
193
195
|
const customDeltas = deduplicatedDeltas.filter((d) => ctx.isCustomEntity(d.modelName));
|
|
194
196
|
if (customDeltas.length > 0) {
|
|
195
197
|
runInAction(() => {
|
|
@@ -219,10 +221,10 @@ export async function flushPendingDeltas(ctx) {
|
|
|
219
221
|
}
|
|
220
222
|
});
|
|
221
223
|
}
|
|
222
|
-
// Regular deltas →
|
|
223
|
-
// 'G' and 'S' deltas are
|
|
224
|
-
// handleGroupRemoved) and never reach
|
|
225
|
-
//
|
|
224
|
+
// Regular deltas → the local store, then the pool.
|
|
225
|
+
// 'G' and 'S' deltas are handled earlier (handleSyncGroupChange /
|
|
226
|
+
// handleGroupRemoved) and never reach here, though the persistence
|
|
227
|
+
// signature accepts them defensively.
|
|
226
228
|
const regularDeltas = deduplicatedDeltas.filter((d) => !ctx.isCustomEntity(d.modelName));
|
|
227
229
|
const batch = await ctx.processDeltaBatch(regularDeltas.map((d) => ({
|
|
228
230
|
syncId: d.id,
|
|
@@ -230,30 +232,27 @@ export async function flushPendingDeltas(ctx) {
|
|
|
230
232
|
modelName: d.modelName,
|
|
231
233
|
modelId: d.modelId,
|
|
232
234
|
data: typeof d.data === 'string' ? JSON.parse(d.data) : d.data,
|
|
233
|
-
// Thread `transactionId` through so the receive layer can
|
|
234
|
-
//
|
|
235
|
-
// the pool mutation. See `OPTIMISTIC_RECONCILIATION.md`.
|
|
235
|
+
// Thread `transactionId` through so the receive layer can recognize
|
|
236
|
+
// echoes of locally-applied transactions and skip the pool mutation.
|
|
236
237
|
transactionId: d.transactionId,
|
|
237
238
|
})));
|
|
238
239
|
const dbResults = batch.results;
|
|
239
|
-
//
|
|
240
|
+
// Apply the batch results to the in-memory pool.
|
|
240
241
|
ctx.applyDeltaBatchToPool(dbResults);
|
|
241
|
-
// Acknowledge
|
|
242
|
+
// Acknowledge and advance the sync cursor, gated on persistence.
|
|
242
243
|
//
|
|
243
|
-
// We
|
|
244
|
-
// store transaction actually committed
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
// Replicache "same-transaction" invariant: the cursor and the
|
|
250
|
-
// persisted view must be consistent.
|
|
244
|
+
// We must acknowledge `persistedSyncId` — the high-water mark of deltas whose
|
|
245
|
+
// store transaction actually committed — not the input batch's last delta id.
|
|
246
|
+
// Acknowledging the input range would advance the server's view past deltas
|
|
247
|
+
// that never persisted; the next catch-up would then send the advanced cursor,
|
|
248
|
+
// the server would answer "you're up to date", and the unpersisted delta would
|
|
249
|
+
// be lost. The cursor and the persisted state must move together.
|
|
251
250
|
const persistedSyncId = batch.persistedSyncId;
|
|
252
251
|
if (persistedSyncId > ctx.lastAckedId) {
|
|
253
252
|
ctx.acknowledge(persistedSyncId);
|
|
254
253
|
ctx.advancePersisted(persistedSyncId);
|
|
255
254
|
}
|
|
256
|
-
// Cache invalidation
|
|
255
|
+
// Cache invalidation happens automatically via the 'models:changed' event.
|
|
257
256
|
ctx.pendingDeltas = [];
|
|
258
257
|
if (ctx.batchTimer) {
|
|
259
258
|
clearTimeout(ctx.batchTimer);
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Handles the delta types that change which sync groups a session can see. A
|
|
3
|
+
* sync group is a fan-out scope the server uses to decide which entities a
|
|
4
|
+
* client receives. When a session's membership changes, these handlers update
|
|
5
|
+
* the client's subscription list; when access is revoked, they clear cached
|
|
6
|
+
* data and trigger a full re-bootstrap so revoked rows cannot linger on the
|
|
7
|
+
* device.
|
|
3
8
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* group-set math, the force-re-bootstrap trigger, and the security-critical
|
|
7
|
-
* shrinkage check. The store keeps thin protected delegates with unchanged
|
|
8
|
-
* signatures — subclass override points stay overridable, and the leaf
|
|
9
|
-
* routes every cross-handler call back through the minimal
|
|
10
|
-
* {@link GroupChangeContext} so dynamic dispatch is preserved.
|
|
9
|
+
* Every handler takes a {@link GroupChangeContext}, the narrow facade through
|
|
10
|
+
* which it reaches the client's local storage and connection lifecycle hooks.
|
|
11
11
|
*/
|
|
12
12
|
import type { SyncDelta, SyncGroupChangePayload, GroupAddedPayload } from './SyncWebSocket.js';
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* The collaborators the group-change handlers depend on. It gathers the
|
|
15
|
+
* client's local storage, in-memory pool, and connection lifecycle hooks
|
|
16
|
+
* behind one narrow interface, so the handlers stay decoupled from the larger
|
|
17
|
+
* store that supplies them.
|
|
17
18
|
*/
|
|
18
19
|
export interface GroupChangeContext {
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
20
|
+
/**
|
|
21
|
+
* Local persistence. Performs the security clear, reads and writes the
|
|
22
|
+
* subscription metadata, and sets the flag that forces a full bootstrap.
|
|
23
|
+
*/
|
|
21
24
|
readonly database: {
|
|
22
25
|
clear(): Promise<void>;
|
|
23
26
|
getWorkspaceMetadata(): Promise<{
|
|
@@ -28,84 +31,83 @@ export interface GroupChangeContext {
|
|
|
28
31
|
}): Promise<void>;
|
|
29
32
|
markRequiresFullBootstrap(): void;
|
|
30
33
|
};
|
|
31
|
-
/** The in-memory
|
|
34
|
+
/** The in-memory object cache, cleared alongside local storage when access is revoked. */
|
|
32
35
|
readonly objectPool: {
|
|
33
36
|
clear(): void;
|
|
34
37
|
};
|
|
35
|
-
/**
|
|
38
|
+
/** Returns the sync groups the live connection is currently subscribed to. */
|
|
36
39
|
getSubscribedSyncGroups(): readonly string[];
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
40
|
+
/**
|
|
41
|
+
* Returns the session's authoritative sync groups, resolved from the current
|
|
42
|
+
* user context via {@link resolveSyncGroups}; null when no user context has
|
|
43
|
+
* been set yet.
|
|
44
|
+
*/
|
|
39
45
|
getCurrentSyncGroups(): readonly string[] | null;
|
|
40
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Returns the session's bootstrap mode. A value of 'none' means the
|
|
48
|
+
* participant never pulls a baseline, so it never re-bootstraps.
|
|
49
|
+
*/
|
|
41
50
|
getBootstrapMode(): 'full' | 'none' | undefined;
|
|
42
|
-
/**
|
|
51
|
+
/** Disconnects the live connection, one step of the forced re-bootstrap cycle. */
|
|
43
52
|
disconnectWebSocket(): void;
|
|
44
|
-
/**
|
|
53
|
+
/** Emits a connection lifecycle event to any registered listener; a no-op when none is set. */
|
|
45
54
|
emitConnectionEvent(event: string): void;
|
|
46
55
|
handleGroupAdded(payload: GroupAddedPayload, syncId: number): Promise<void>;
|
|
47
56
|
computeUpdatedSyncGroups(payload: SyncGroupChangePayload): string[];
|
|
48
57
|
forceFullRebootstrap(): void;
|
|
49
58
|
}
|
|
50
59
|
/**
|
|
51
|
-
*
|
|
60
|
+
* Handles a 'G' (group-change) delta. The server sends two shapes of this
|
|
61
|
+
* delta, told apart by the payload:
|
|
52
62
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
63
|
+
* Incremental — `{ group, userId }`: the recipient was added to a single
|
|
64
|
+
* sync group. No re-bootstrap follows; the newly visible entities arrive as
|
|
65
|
+
* ordinary 'C' (covering) deltas through the normal insert path.
|
|
55
66
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* - No re-bootstrap — entities arrive via the normal insert path.
|
|
60
|
-
*
|
|
61
|
-
* Legacy (EmitGroupChange): { addedGroups, removedGroups }
|
|
62
|
-
* - Single delta carrying the full group membership diff.
|
|
63
|
-
* - Forces a full re-bootstrap (disconnect + reconnect + fetch all).
|
|
64
|
-
* - Deprecated on the server; kept here for wire-level backward compat.
|
|
67
|
+
* Full diff — `{ addedGroups, removedGroups }`: one delta carrying the whole
|
|
68
|
+
* membership change. This forces a full re-bootstrap (disconnect, reconnect,
|
|
69
|
+
* and refetch), clearing cached data first if any group was removed.
|
|
65
70
|
*/
|
|
66
71
|
export declare function handleSyncGroupChange(ctx: GroupChangeContext, delta: SyncDelta): Promise<void>;
|
|
67
72
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* each newly-visible entity, which flow through the normal insert path.
|
|
73
|
+
* Handles an incremental group-added delta. It records the new sync group in
|
|
74
|
+
* the subscription metadata without forcing a re-bootstrap; the server then
|
|
75
|
+
* sends a 'C' (covering) delta for each newly visible entity, which flows
|
|
76
|
+
* through the normal insert path.
|
|
73
77
|
*/
|
|
74
78
|
export declare function handleGroupAdded(ctx: GroupChangeContext, payload: GroupAddedPayload, syncId: number): Promise<void>;
|
|
75
79
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* selectively purge entities belonging to that group. The safe fallback
|
|
81
|
-
* is the legacy behavior: clear local state and force a re-bootstrap
|
|
82
|
-
* with the updated group list.
|
|
83
|
-
*
|
|
84
|
-
* Future optimization: track group membership in the ObjectPool so 'S'
|
|
85
|
-
* can do a targeted purge instead of a full re-bootstrap.
|
|
80
|
+
* Handles an 'S' (group-removed) delta, which signals the recipient has lost
|
|
81
|
+
* access to a sync group. The client does not track which entities belong to
|
|
82
|
+
* which group, so it cannot purge only the affected rows; instead it clears
|
|
83
|
+
* local state and forces a re-bootstrap with the updated group list.
|
|
86
84
|
*/
|
|
87
85
|
export declare function handleGroupRemoved(ctx: GroupChangeContext, delta: SyncDelta): Promise<void>;
|
|
88
|
-
/**
|
|
86
|
+
/** Computes the new sync-group set after applying the additions and removals in a diff. */
|
|
89
87
|
export declare function computeUpdatedSyncGroups(ctx: GroupChangeContext, payload: SyncGroupChangePayload): string[];
|
|
90
|
-
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
88
|
+
/**
|
|
89
|
+
* Forces a full re-bootstrap by marking local storage as needing one,
|
|
90
|
+
* disconnecting, and emitting a connection lifecycle event that the reconnect
|
|
91
|
+
* path acts on. Does nothing for participants whose bootstrap mode is 'none':
|
|
92
|
+
* they never pull a baseline, so after a trigger such as a sync-group shrink or
|
|
93
|
+
* an access revocation they rely on covering deltas to repopulate the data they
|
|
96
94
|
* subscribe to.
|
|
97
95
|
*/
|
|
98
96
|
export declare function forceFullRebootstrap(ctx: GroupChangeContext): void;
|
|
99
97
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* here so the
|
|
105
|
-
*
|
|
98
|
+
* Resolves the sync-group list this session subscribes to, and is the single
|
|
99
|
+
* place that decision is made. The server-issued `context.syncGroups` is
|
|
100
|
+
* authoritative; when it is absent, the session subscribes to no explicit
|
|
101
|
+
* groups. {@link checkSyncGroupShrinkage} and connection setup both read
|
|
102
|
+
* through here, so the live subscription and the access-revocation check can
|
|
103
|
+
* never disagree.
|
|
106
104
|
*/
|
|
107
105
|
export declare function resolveSyncGroups(context: {
|
|
108
106
|
syncGroups?: readonly string[];
|
|
109
107
|
}): readonly string[];
|
|
110
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* Compares the session's current sync groups against the set stored from the
|
|
110
|
+
* last session. If any group is now missing, access has narrowed, so this
|
|
111
|
+
* clears cached data and forces a full bootstrap before recording the new set.
|
|
112
|
+
*/
|
|
111
113
|
export declare function checkSyncGroupShrinkage(ctx: GroupChangeContext): Promise<void>;
|