@abloatai/ablo 0.25.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/AGENTS.md +5 -3
- package/CHANGELOG.md +34 -0
- package/README.md +104 -88
- package/dist/BaseSyncedStore.d.ts +140 -266
- package/dist/BaseSyncedStore.js +338 -739
- package/dist/Database.d.ts +62 -77
- package/dist/Database.js +106 -127
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +91 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +16 -15
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +52 -69
- package/dist/ModelRegistry.d.ts +46 -25
- package/dist/ModelRegistry.js +32 -30
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +6 -7
- package/dist/SyncClient.d.ts +119 -109
- package/dist/SyncClient.js +303 -224
- package/dist/SyncEngineContext.d.ts +1 -3
- package/dist/SyncEngineContext.js +1 -2
- 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 +39 -31
- package/dist/agent/Agent.js +35 -23
- 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} +30 -31
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +7 -8
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/credentialPolicy.d.ts +74 -71
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +7 -18
- package/dist/auth/credentialSource.js +10 -18
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +34 -40
- 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 +483 -369
- package/dist/client/Ablo.d.ts +107 -836
- package/dist/client/Ablo.js +174 -833
- package/dist/client/ApiClient.d.ts +44 -20
- package/dist/client/ApiClient.js +193 -44
- package/dist/client/auth.d.ts +51 -60
- package/dist/client/auth.js +137 -110
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +35 -0
- package/dist/client/consoleLogger.js +44 -0
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +26 -31
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +158 -124
- package/dist/client/credentialEndpoint.d.ts +61 -0
- package/dist/client/credentialEndpoint.js +86 -0
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +21 -0
- package/dist/client/hostedEndpoints.js +21 -0
- package/dist/client/httpClient.d.ts +58 -54
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +49 -59
- package/dist/client/modelRegistration.d.ts +10 -0
- package/dist/client/modelRegistration.js +301 -0
- package/dist/client/options.d.ts +373 -0
- package/dist/client/options.js +6 -0
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +333 -0
- package/dist/client/resourceTypes.js +7 -0
- package/dist/client/schemaConfig.d.ts +44 -0
- package/dist/client/schemaConfig.js +176 -0
- package/dist/client/sessionMint.d.ts +17 -13
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +9 -10
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +28 -0
- package/dist/client/wsMutationExecutor.js +71 -0
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -7
- package/dist/coordination/index.d.ts +13 -4
- package/dist/coordination/index.js +29 -4
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -11
- package/dist/coordination/trace.js +13 -15
- package/dist/core/DatabaseManager.d.ts +5 -8
- package/dist/core/DatabaseManager.js +38 -40
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +27 -34
- package/dist/core/QueryView.d.ts +17 -5
- package/dist/core/QueryView.js +6 -7
- package/dist/core/StoreManager.d.ts +14 -16
- package/dist/core/StoreManager.js +26 -25
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +18 -13
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +57 -54
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +145 -0
- package/dist/core/storeContract.js +12 -0
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +118 -101
- package/dist/errorCodes.js +277 -260
- package/dist/errors.d.ts +170 -165
- package/dist/errors.js +161 -151
- package/dist/index.d.ts +30 -27
- package/dist/index.js +90 -82
- package/dist/interfaces/index.d.ts +108 -133
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +59 -49
- 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 +149 -155
- package/dist/mutators/defineMutators.d.ts +24 -37
- 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 +105 -101
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +32 -16
- package/dist/query/client.js +103 -72
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +7 -11
- package/dist/react/AbloProvider.js +24 -17
- package/dist/react/context.d.ts +27 -146
- 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 +17 -15
- 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 +11 -12
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +9 -9
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +10 -4
- package/dist/react/useReactive.js +2 -3
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +3 -3
- 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 +35 -0
- package/dist/schema/ddlLock.js +46 -0
- 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 +36 -49
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +5 -4
- package/dist/schema/index.js +29 -21
- package/dist/schema/model.d.ts +121 -146
- package/dist/schema/model.js +24 -35
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +7 -1
- package/dist/schema/queries.d.ts +30 -32
- package/dist/schema/queries.js +24 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +38 -0
- package/dist/schema/residency.js +30 -0
- package/dist/schema/roles.d.ts +45 -27
- package/dist/schema/roles.js +52 -21
- package/dist/schema/schema.d.ts +36 -45
- package/dist/schema/schema.js +42 -39
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +36 -39
- 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} +27 -50
- 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 +31 -26
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +34 -28
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +28 -26
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +10 -9
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +27 -29
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +27 -19
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +30 -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 +94 -0
- package/dist/source/factory.js +268 -0
- package/dist/source/index.d.ts +10 -462
- package/dist/source/index.js +17 -421
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +10 -11
- package/dist/source/next.js +7 -8
- package/dist/source/pushQueue.d.ts +70 -48
- package/dist/source/pushQueue.js +36 -29
- package/dist/source/signing.d.ts +88 -0
- package/dist/source/signing.js +159 -0
- package/dist/source/types.d.ts +351 -0
- package/dist/source/types.js +43 -0
- package/dist/stores/ObjectStore.d.ts +11 -12
- package/dist/stores/ObjectStore.js +34 -35
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +8 -12
- package/dist/stores/SyncActionStore.js +77 -46
- package/dist/surface.d.ts +28 -21
- package/dist/surface.js +28 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +37 -45
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +101 -80
- package/dist/sync/ConnectionManager.d.ts +47 -50
- package/dist/sync/ConnectionManager.js +74 -70
- package/dist/sync/NetworkProbe.d.ts +27 -31
- package/dist/sync/NetworkProbe.js +67 -72
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +49 -36
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +79 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +45 -59
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +44 -52
- package/dist/sync/SyncWebSocket.d.ts +175 -250
- package/dist/sync/SyncWebSocket.js +431 -769
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +38 -30
- package/dist/sync/bootstrapApply.d.ts +70 -0
- package/dist/sync/bootstrapApply.js +73 -0
- package/dist/sync/commitFrames.d.ts +44 -0
- package/dist/sync/commitFrames.js +94 -0
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +108 -25
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +13 -17
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +175 -0
- package/dist/sync/credentialLifecycle.js +322 -0
- package/dist/sync/deltaPipeline.d.ts +113 -0
- package/dist/sync/deltaPipeline.js +261 -0
- package/dist/sync/groupChange.d.ts +113 -0
- package/dist/sync/groupChange.js +242 -0
- package/dist/sync/heartbeat.d.ts +63 -0
- package/dist/sync/heartbeat.js +91 -0
- package/dist/sync/participants.d.ts +27 -27
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +40 -0
- package/dist/sync/syncCursor.js +55 -0
- package/dist/sync/syncPlan.d.ts +54 -0
- package/dist/sync/syncPlan.js +50 -0
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +116 -0
- package/dist/sync/wsFrameHandlers.js +374 -0
- package/dist/testing/fixtures/bootstrap.d.ts +21 -17
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +31 -34
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +12 -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 -18
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +14 -11
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +4 -4
- package/dist/testing/index.js +3 -3
- 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 +21 -34
- package/dist/testing/mocks/MockSyncContext.js +16 -45
- package/dist/testing/mocks/MockSyncStore.d.ts +14 -14
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +28 -24
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +190 -221
- package/dist/transactions/TransactionQueue.js +424 -822
- package/dist/transactions/TransactionStore.d.ts +20 -0
- package/dist/transactions/TransactionStore.js +53 -0
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +58 -0
- package/dist/transactions/coalesceRules.js +140 -0
- package/dist/transactions/commitPayload.d.ts +130 -0
- package/dist/transactions/commitPayload.js +143 -0
- package/dist/transactions/deltaConfirmation.d.ts +58 -0
- package/dist/transactions/deltaConfirmation.js +215 -0
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/replayValidation.d.ts +99 -0
- package/dist/transactions/replayValidation.js +111 -0
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +74 -80
- package/dist/types/index.js +22 -27
- package/dist/types/modelData.d.ts +10 -0
- package/dist/types/modelData.js +9 -0
- package/dist/types/participant.d.ts +20 -0
- package/dist/types/participant.js +10 -0
- package/dist/types/streams.d.ts +216 -209
- 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} +44 -100
- 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 +35 -27
- package/dist/wire/errorEnvelope.js +38 -32
- package/dist/wire/frames.d.ts +150 -67
- package/dist/wire/frames.js +48 -1
- package/dist/wire/index.d.ts +18 -13
- package/dist/wire/index.js +36 -13
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +38 -0
- package/dist/wire/protocol.js +38 -0
- package/dist/wire/protocolVersion.d.ts +60 -0
- package/dist/wire/protocolVersion.js +67 -0
- package/docs/api-keys.md +4 -3
- package/docs/coordination.md +59 -0
- package/docs/examples/existing-python-backend.md +3 -3
- package/docs/identity.md +4 -4
- package/docs/integration-guide.md +1 -1
- package/docs/react.md +1 -1
- package/docs/sessions.md +5 -7
- package/package.json +24 -21
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/client/index.d.ts +0 -36
- package/dist/client/index.js +0 -33
- package/dist/config/index.d.ts +0 -10
- package/dist/config/index.js +0 -12
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/interfaces/headless.d.ts +0 -95
- package/dist/interfaces/headless.js +0 -41
- package/dist/query/index.d.ts +0 -6
- package/dist/query/index.js +0 -5
- package/dist/realtime/index.d.ts +0 -10
- package/dist/realtime/index.js +0 -9
- package/dist/schema/plane.d.ts +0 -23
- package/dist/schema/plane.js +0 -19
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/next.d.ts +0 -51
- package/dist/server/next.js +0 -47
- 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 -1
- package/dist/server/storage-mode.js +0 -18
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/sync/OfflineFlush.d.ts +0 -9
- package/dist/sync/OfflineFlush.js +0 -22
- package/dist/sync/OfflineTransactionStore.d.ts +0 -37
- package/dist/sync/OfflineTransactionStore.js +0 -263
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/index.d.ts +0 -16
- package/dist/transactions/index.js +0 -7
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/utils/mobx-setup.d.ts +0 -42
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The base class that application-specific sync stores extend. It supplies the
|
|
3
|
+
* shared orchestration for reads, writes, delta processing, and bootstrap, and
|
|
4
|
+
* exports the core types those stores build on.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* This file only contains types and the abstract contract — the actual
|
|
11
|
-
* implementation stays in the app's SyncedStore.ts until we incrementally
|
|
12
|
-
* pull generic methods into this base class.
|
|
6
|
+
* A subclass adds its own domain behavior — lazy-loaded relations,
|
|
7
|
+
* collaboration events, and model enrichment — by overriding the protected
|
|
8
|
+
* extension points defined here. The heavy lifting is delegated to injected
|
|
9
|
+
* collaborators: {@link SyncClient} owns pool writes and the transaction
|
|
10
|
+
* queue, {@link Database} owns local persistence, {@link InstanceCache} holds the
|
|
11
|
+
* in-memory models, and {@link ModelRegistry} holds their metadata.
|
|
13
12
|
*/
|
|
13
|
+
import type { RecoveryClass } from './errorCodes.js';
|
|
14
14
|
import { ConnectionManager } from './sync/ConnectionManager.js';
|
|
15
|
-
import {
|
|
15
|
+
import { SubscriptionManager } from './sync/SubscriptionManager.js';
|
|
16
16
|
import { type ParticipantScope } from './sync/participants.js';
|
|
17
17
|
import type { SyncClient } from './SyncClient.js';
|
|
18
18
|
import type { Database, BootstrapResult } from './Database.js';
|
|
19
|
-
import type {
|
|
19
|
+
import type { InstanceCache } from './InstanceCache.js';
|
|
20
20
|
import { ModelRegistry } from './ModelRegistry.js';
|
|
21
|
-
import { SyncWebSocket, type SyncDelta, type SyncGroupChangePayload, type GroupAddedPayload, type GroupRemovedPayload, type
|
|
21
|
+
import { SyncWebSocket, type SyncDelta, type SyncGroupChangePayload, type GroupAddedPayload, type GroupRemovedPayload, type BootstrapHint, type BootstrapDataEvent, type PresenceUpdateEvent, type EventMap, type DefaultCollaborationEvents } from './sync/SyncWebSocket.js';
|
|
22
22
|
import { QueryProcessor } from './core/QueryProcessor.js';
|
|
23
23
|
import { Model } from './Model.js';
|
|
24
|
-
import { ModelScope } from './
|
|
24
|
+
import { ModelScope } from './InstanceCache.js';
|
|
25
25
|
import type { Schema } from './schema/schema.js';
|
|
26
|
-
import type { LocalMutation } from './
|
|
26
|
+
import type { SyncStatus, LocalMutation } from './core/storeContract.js';
|
|
27
27
|
import type { AuthCredentialSource } from './auth/credentialSource.js';
|
|
28
|
+
import type { ModelData } from './types/modelData.js';
|
|
29
|
+
import type { EnrichmentPlanEntry, ForeignKeyIndexSpec } from './sync/syncPlan.js';
|
|
30
|
+
import { type CredentialRefresher } from './sync/credentialLifecycle.js';
|
|
31
|
+
import type { RehydrationStats } from './sync/bootstrapApply.js';
|
|
28
32
|
/** Constructor type for Model subclasses (accepts abstract classes) */
|
|
29
33
|
export type ModelConstructor<T extends Model> = abstract new (...args: never[]) => T;
|
|
30
34
|
/** Concrete constructor type for instantiation */
|
|
31
35
|
export type ConcreteModelConstructor<T extends Model> = new (data?: any) => T;
|
|
32
|
-
|
|
33
|
-
export type ModelData = Record<string, unknown>;
|
|
36
|
+
export type { ModelData } from './types/modelData.js';
|
|
34
37
|
/** Query result interface */
|
|
35
38
|
export interface QueryResult<T extends Model> {
|
|
36
39
|
data: T[];
|
|
@@ -38,55 +41,12 @@ export interface QueryResult<T extends Model> {
|
|
|
38
41
|
hasMore: boolean;
|
|
39
42
|
fromCache?: boolean;
|
|
40
43
|
}
|
|
41
|
-
|
|
42
|
-
export interface ForeignKeyIndexSpec {
|
|
43
|
-
/**
|
|
44
|
-
* The child model name (where the FK field lives) — this is the type
|
|
45
|
-
* that will be passed to `pool.registerForeignKey(modelName, fieldName)`
|
|
46
|
-
* and later to `pool.getByForeignKey(modelName, fieldName, value)`.
|
|
47
|
-
*
|
|
48
|
-
* Use the wire `__typename` casing (e.g., `'SlideLayer'`, not
|
|
49
|
-
* `'slideLayer'`) — that's the value `createFromData` stamps onto
|
|
50
|
-
* models and the pool indexes by.
|
|
51
|
-
*/
|
|
52
|
-
readonly modelName: string;
|
|
53
|
-
/** The FK field name on the child model, e.g. `'slideId'`. */
|
|
54
|
-
readonly fieldName: string;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* A declarative enrichment rule for the delta-apply path.
|
|
58
|
-
*
|
|
59
|
-
* When a delta for `modelName` arrives, after the model is constructed
|
|
60
|
-
* the base store reads `data[foreignKey]` from the payload, looks up
|
|
61
|
-
* the matching parent in the ObjectPool, and attaches it as
|
|
62
|
-
* `data[relationKey]`. Best-effort: if the parent isn't yet in the
|
|
63
|
-
* pool (e.g., arrived later in the same bootstrap batch), enrichment
|
|
64
|
-
* silently no-ops.
|
|
65
|
-
*
|
|
66
|
-
* Replaces the previous pattern of overriding `enrichRelations` on a
|
|
67
|
-
* subclass to hardcode per-model enrichment logic.
|
|
68
|
-
*/
|
|
69
|
-
export interface EnrichmentPlanEntry {
|
|
70
|
-
/** The child model whose incoming deltas should be enriched. */
|
|
71
|
-
readonly modelName: string;
|
|
72
|
-
/** The FK field on the child that points at the parent's id. */
|
|
73
|
-
readonly foreignKey: string;
|
|
74
|
-
/** The property name under which to attach the parent model. */
|
|
75
|
-
readonly relationKey: string;
|
|
76
|
-
}
|
|
44
|
+
export type { ForeignKeyIndexSpec, EnrichmentPlanEntry } from './sync/syncPlan.js';
|
|
77
45
|
/** Configuration for SyncedStore behavior */
|
|
78
46
|
export interface SyncedStoreConfig {
|
|
79
47
|
enableOffline?: boolean;
|
|
80
48
|
enableCache?: boolean;
|
|
81
49
|
enableTelemetry?: boolean;
|
|
82
|
-
/**
|
|
83
|
-
* Initial version vector keys, each seeded to 0. Merged with the
|
|
84
|
-
* schema-derived set (if a schema is provided to the constructor) —
|
|
85
|
-
* explicit keys here layer on top of derived ones. Replaces the
|
|
86
|
-
* subclass pattern of hardcoding `this.versionVector = { tasks: 0, ... }`
|
|
87
|
-
* in the constructor.
|
|
88
|
-
*/
|
|
89
|
-
versionVectorKeys?: readonly string[];
|
|
90
50
|
/**
|
|
91
51
|
* Declarative enrichment plan consumed by `enrichRelations`. Replaces
|
|
92
52
|
* the subclass override of `enrichRelations` for per-model parent
|
|
@@ -95,7 +55,7 @@ export interface SyncedStoreConfig {
|
|
|
95
55
|
*/
|
|
96
56
|
enrichmentPlan?: readonly EnrichmentPlanEntry[];
|
|
97
57
|
/**
|
|
98
|
-
* Foreign-key indexes to register on the
|
|
58
|
+
* Foreign-key indexes to register on the InstanceCache at construction
|
|
99
59
|
* time. Replaces the subclass override of `registerForeignKeys` for
|
|
100
60
|
* per-model FK registration. Merged with schema-derived entries
|
|
101
61
|
* (relations marked `{ index: true }` on `belongsTo`). Both sets
|
|
@@ -104,17 +64,7 @@ export interface SyncedStoreConfig {
|
|
|
104
64
|
*/
|
|
105
65
|
foreignKeyIndexes?: readonly ForeignKeyIndexSpec[];
|
|
106
66
|
}
|
|
107
|
-
|
|
108
|
-
export interface SyncStatus {
|
|
109
|
-
state: 'idle' | 'syncing' | 'error' | 'offline' | 'reconnecting';
|
|
110
|
-
progress: number;
|
|
111
|
-
error?: Error;
|
|
112
|
-
/** When true, the error is a session/auth error requiring re-authentication. */
|
|
113
|
-
isSessionError: boolean;
|
|
114
|
-
lastSyncAt?: Date;
|
|
115
|
-
pendingChanges: number;
|
|
116
|
-
offlineSince?: Date;
|
|
117
|
-
}
|
|
67
|
+
export type { SyncStatus } from './core/storeContract.js';
|
|
118
68
|
/** User context for initialization */
|
|
119
69
|
export interface UserContext {
|
|
120
70
|
userId: string;
|
|
@@ -128,8 +78,7 @@ export interface UserContext {
|
|
|
128
78
|
kind?: 'user' | 'agent' | 'system';
|
|
129
79
|
/** Restricted (`rk_`) API key for `kind: 'agent'` — the agent's
|
|
130
80
|
* bearer credential. Sent in the `ablo.bearer.<token>` WebSocket
|
|
131
|
-
* subprotocol, never in the URL.
|
|
132
|
-
* Biscuit→opaque-key migration.) */
|
|
81
|
+
* subprotocol, never in the URL. */
|
|
133
82
|
capabilityToken?: string;
|
|
134
83
|
/** Server-authoritative sync groups, supplied by auth/capability
|
|
135
84
|
* exchange. The SDK does not invent org/user/default groups; app
|
|
@@ -157,15 +106,7 @@ export interface SmartSyncOptions {
|
|
|
157
106
|
batchingDelay?: number;
|
|
158
107
|
maxBatchSize?: number;
|
|
159
108
|
}
|
|
160
|
-
|
|
161
|
-
export interface RehydrationStats {
|
|
162
|
-
added: number;
|
|
163
|
-
updated: number;
|
|
164
|
-
removed: number;
|
|
165
|
-
skipped: number;
|
|
166
|
-
healed: number;
|
|
167
|
-
elapsedMs: number;
|
|
168
|
-
}
|
|
109
|
+
export type { RehydrationStats } from './sync/bootstrapApply.js';
|
|
169
110
|
/** Bootstrap timeout configuration */
|
|
170
111
|
export declare const BOOTSTRAP_CONFIG: {
|
|
171
112
|
readonly OVERALL_TIMEOUT_MS: 15000;
|
|
@@ -173,18 +114,18 @@ export declare const BOOTSTRAP_CONFIG: {
|
|
|
173
114
|
readonly RETRY_DELAY_MS: 500;
|
|
174
115
|
};
|
|
175
116
|
export { ModelScope };
|
|
176
|
-
export type { SyncDelta, SyncGroupChangePayload, GroupAddedPayload, GroupRemovedPayload,
|
|
117
|
+
export type { SyncDelta, SyncGroupChangePayload, GroupAddedPayload, GroupRemovedPayload, BootstrapHint, BootstrapDataEvent, PresenceUpdateEvent, };
|
|
118
|
+
export { deriveSyncPlanFromSchema } from './sync/syncPlan.js';
|
|
177
119
|
/**
|
|
178
|
-
*
|
|
120
|
+
* The abstract base class that application-specific sync stores extend. It
|
|
121
|
+
* carries the injected collaborators, the observable sync status, and the
|
|
122
|
+
* orchestration for initialization, delta processing, bootstrap, and the
|
|
123
|
+
* read and write API. A subclass supplies its own domain behavior by
|
|
124
|
+
* overriding the protected extension points defined here and by typing its
|
|
125
|
+
* collaboration events through the generic parameter.
|
|
179
126
|
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* delta processing, bootstrap, query, save, delete, etc.) lives in the
|
|
183
|
-
* app's concrete subclass for now — methods will be pulled up into this
|
|
184
|
-
* base class incrementally as they are genericized.
|
|
185
|
-
*
|
|
186
|
-
* Subclasses MUST call `super(dependencies, config)` and then set up
|
|
187
|
-
* their own MobX observables.
|
|
127
|
+
* A subclass must call `super(dependencies, config)` and then set up its own
|
|
128
|
+
* MobX observables.
|
|
188
129
|
*
|
|
189
130
|
* Generic over `TCollaboration` — an app-defined event map for real-time
|
|
190
131
|
* collaboration events (cursors, selections, presence beyond the core set).
|
|
@@ -202,35 +143,11 @@ export type { SyncDelta, SyncGroupChangePayload, GroupAddedPayload, GroupRemoved
|
|
|
202
143
|
* }
|
|
203
144
|
* }
|
|
204
145
|
*/
|
|
205
|
-
/**
|
|
206
|
-
* Walk a schema and derive the three sync-plan arrays consumed by
|
|
207
|
-
* `BaseSyncedStore`'s constructor: version-vector keys, FK indexes to
|
|
208
|
-
* register on the pool, and the enrichment plan.
|
|
209
|
-
*
|
|
210
|
-
* Version vector keys are derived from each model's `typename` (lowercased
|
|
211
|
-
* to match the server's event-type convention — `'Task'` → `'task'`,
|
|
212
|
-
* `'SlideLayer'` → `'slidelayer'`). A fallback to the schema key applies
|
|
213
|
-
* when `typename` is unset, though `defineSchema()` now always resolves
|
|
214
|
-
* it during assembly so the fallback is defensive-only.
|
|
215
|
-
*
|
|
216
|
-
* FK indexes and enrichment entries are pulled from each `belongsTo`
|
|
217
|
-
* relation where `options.index` / `options.enrich` is set. Relations
|
|
218
|
-
* without those options are skipped — this is an opt-in mechanism so
|
|
219
|
-
* adding a `belongsTo` never silently changes delta or lookup semantics.
|
|
220
|
-
*
|
|
221
|
-
* Pure function: takes a Schema, returns three arrays. No side effects,
|
|
222
|
-
* no class state. Called once at construction time from `BaseSyncedStore`.
|
|
223
|
-
*/
|
|
224
|
-
export declare function deriveSyncPlanFromSchema(schema: Schema): {
|
|
225
|
-
versionVectorKeys: string[];
|
|
226
|
-
enrichmentPlan: EnrichmentPlanEntry[];
|
|
227
|
-
foreignKeyIndexes: ForeignKeyIndexSpec[];
|
|
228
|
-
};
|
|
229
146
|
export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaboration> = DefaultCollaborationEvents, TSchema extends Schema = Schema> {
|
|
230
147
|
syncStatus: SyncStatus;
|
|
231
148
|
protected readonly syncClient: SyncClient;
|
|
232
149
|
protected readonly database: Database;
|
|
233
|
-
protected readonly objectPool:
|
|
150
|
+
protected readonly objectPool: InstanceCache;
|
|
234
151
|
protected readonly modelRegistry: ModelRegistry;
|
|
235
152
|
protected readonly auth?: AuthCredentialSource;
|
|
236
153
|
/**
|
|
@@ -246,7 +163,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
246
163
|
* to whichever instance is current, so callers (the React participant
|
|
247
164
|
* hook) never hold a stale reference. Null until `setupWebSocketSync`.
|
|
248
165
|
*/
|
|
249
|
-
protected areaOfInterest:
|
|
166
|
+
protected areaOfInterest: SubscriptionManager | null;
|
|
250
167
|
/** Sync groups whose current state has been backfilled into the pool
|
|
251
168
|
* (hydrate-on-enter). Cleared when the pool is reset on (re)bootstrap. */
|
|
252
169
|
private readonly hydratedGroups;
|
|
@@ -265,22 +182,22 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
265
182
|
getSyncWebSocket(): SyncWebSocket<TCollaboration> | null;
|
|
266
183
|
private scopeToGroups;
|
|
267
184
|
/**
|
|
268
|
-
* Bring a scope into view
|
|
269
|
-
* `{ hydrate: true }`,
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
* and the live
|
|
185
|
+
* Bring a scope into view and subscribe to its sync groups. With
|
|
186
|
+
* `{ hydrate: true }`, also backfill the groups' current state into the pool
|
|
187
|
+
* once the subscription is active. The order matters: subscribing first
|
|
188
|
+
* guarantees no live delta is missed in the gap before the snapshot lands.
|
|
189
|
+
* Hydration is best-effort — a failed backfill never rejects `enterScope`,
|
|
190
|
+
* and the live delta stream keeps flowing regardless.
|
|
274
191
|
*/
|
|
275
192
|
enterScope(scope: ParticipantScope, opts?: {
|
|
276
193
|
hydrate?: boolean;
|
|
277
194
|
}): Promise<void>;
|
|
278
195
|
/**
|
|
279
|
-
* Backfill the current state of `syncGroups` into the pool
|
|
280
|
-
* snapshot fetch
|
|
281
|
-
* (skips groups already hydrated) and single-flight (concurrent
|
|
282
|
-
* same group share one fetch).
|
|
283
|
-
*
|
|
196
|
+
* Backfill the current state of `syncGroups` into the pool with a side-effect-free
|
|
197
|
+
* scoped snapshot fetch followed by the version-guarded scoped apply. The call
|
|
198
|
+
* is idempotent (it skips groups already hydrated) and single-flight (concurrent
|
|
199
|
+
* enters of the same group share one fetch). On error the groups are left
|
|
200
|
+
* unmarked, so a later re-enter retries.
|
|
284
201
|
*/
|
|
285
202
|
protected hydrateGroups(syncGroups: readonly string[]): Promise<void>;
|
|
286
203
|
/** Leave a scope → its groups go warm (hysteresis), then drop on sweep. */
|
|
@@ -291,18 +208,16 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
291
208
|
unpinScope(scope: ParticipantScope): Promise<void>;
|
|
292
209
|
protected readonly queryProcessor: QueryProcessor;
|
|
293
210
|
/**
|
|
294
|
-
* Runtime behavior flags only — the
|
|
295
|
-
* (`
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
* They don't need to persist on `this.config`.
|
|
211
|
+
* Runtime behavior flags only — the schema/config arrays
|
|
212
|
+
* (`enrichmentPlan`, `foreignKeyIndexes`) are consumed at construction
|
|
213
|
+
* time and stored on the instance as `enrichmentPlan` and
|
|
214
|
+
* pool-registered indexes. They don't need to persist on `this.config`.
|
|
299
215
|
*/
|
|
300
216
|
protected readonly config: Required<Pick<SyncedStoreConfig, 'enableOffline' | 'enableCache' | 'enableTelemetry'>>;
|
|
301
|
-
protected disposers:
|
|
217
|
+
protected disposers: (() => void)[];
|
|
302
218
|
protected initialized: boolean;
|
|
303
219
|
protected dataReady: boolean;
|
|
304
220
|
protected userContext: UserContext | null;
|
|
305
|
-
protected versionVector: VersionVector;
|
|
306
221
|
/**
|
|
307
222
|
* Declarative enrichment plan: "for model X, when a delta arrives,
|
|
308
223
|
* read data[foreignKey] and attach the matching parent from the pool
|
|
@@ -328,15 +243,14 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
328
243
|
constructor(dependencies: {
|
|
329
244
|
syncClient: SyncClient;
|
|
330
245
|
database: Database;
|
|
331
|
-
objectPool:
|
|
246
|
+
objectPool: InstanceCache;
|
|
332
247
|
modelRegistry: ModelRegistry;
|
|
333
248
|
/**
|
|
334
|
-
* Optional schema. When provided,
|
|
335
|
-
* the schema's models
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
* / `config.foreignKeyIndexes` / `config.enrichmentPlan` instead.
|
|
249
|
+
* Optional schema. When provided, {@link deriveSyncPlanFromSchema} walks
|
|
250
|
+
* the schema's models and relations to auto-populate foreign-key indexes
|
|
251
|
+
* and the enrichment plan from their declarative annotations. Subclasses
|
|
252
|
+
* that register model classes directly can instead pass explicit
|
|
253
|
+
* `config.foreignKeyIndexes` / `config.enrichmentPlan`.
|
|
340
254
|
*/
|
|
341
255
|
schema?: TSchema;
|
|
342
256
|
/** Sync server URL for WebSocket connection. Converted to wss:// automatically. */
|
|
@@ -345,17 +259,17 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
345
259
|
auth?: AuthCredentialSource;
|
|
346
260
|
}, config?: SyncedStoreConfig);
|
|
347
261
|
/**
|
|
348
|
-
* Register foreign
|
|
262
|
+
* Register foreign-key indexes for constant-time lookups.
|
|
349
263
|
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
264
|
+
* This is an override hook. The preferred way to declare a foreign-key
|
|
265
|
+
* index is `config.foreignKeyIndexes` at construction time, or marking the
|
|
266
|
+
* `belongsTo` relation with `{ index: true }` in the schema. The hook fires
|
|
267
|
+
* after the schema-derived and config registrations, so a subclass can
|
|
268
|
+
* layer additional indexes on top.
|
|
355
269
|
*/
|
|
356
270
|
protected registerForeignKeys(): void;
|
|
357
271
|
/**
|
|
358
|
-
* Enrich delta data with related models from the
|
|
272
|
+
* Enrich delta data with related models from the InstanceCache.
|
|
359
273
|
*
|
|
360
274
|
* Base implementation walks `this.enrichmentPlan` — entries populated
|
|
361
275
|
* from the schema's `{ enrich: true }` relations and from
|
|
@@ -391,23 +305,15 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
391
305
|
*/
|
|
392
306
|
protected connectionManager: import('./sync/ConnectionManager.js').ConnectionManager | null;
|
|
393
307
|
/**
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
private credentialRefresher;
|
|
404
|
-
/** Single-flight guard so a wake nudge + an in-flight request + a probe don't
|
|
405
|
-
* all mint at once (the classic "token thrash → random logout" bug). */
|
|
406
|
-
private inFlightCredentialRefresh;
|
|
407
|
-
/** Teardown for the proactive credential lifecycle (refresh timer + wake/
|
|
408
|
-
* online/focus listeners) installed by {@link startCredentialLifecycle};
|
|
409
|
-
* cleared on {@link disconnect}. Null when no resolver is wired. */
|
|
410
|
-
private credentialLifecycleTeardown;
|
|
308
|
+
* Access-credential re-mint + proactive pre-roll — extracted to
|
|
309
|
+
* sync/credentialLifecycle.ts. Owns the refresher hook, the single-flight
|
|
310
|
+
* guard, and the browser-only refresh timer / wake listener; talks back
|
|
311
|
+
* through three lazily-resolved callbacks (the ConnectionManager doesn't
|
|
312
|
+
* exist until `setupWebSocketSync`). The `setCredentialRefresher` /
|
|
313
|
+
* `performCredentialRefresh` / `startCredentialLifecycle` methods below
|
|
314
|
+
* are thin delegates so the store's public surface is unchanged.
|
|
315
|
+
*/
|
|
316
|
+
private readonly credentialLifecycle;
|
|
411
317
|
/**
|
|
412
318
|
* Listeners registered via `subscribeSessionError()`. Fired when the
|
|
413
319
|
* WebSocket closes with a session-invalid code (1008/4001/4003) or a
|
|
@@ -448,7 +354,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
448
354
|
waitForConfirmation(modelName: string, modelId: string): Promise<void>;
|
|
449
355
|
/**
|
|
450
356
|
* Observe the LOCAL mutation stream for undo recording (see
|
|
451
|
-
* {@link import('./
|
|
357
|
+
* {@link import('./core/storeContract.js').LocalMutation}). Taps the
|
|
452
358
|
* TransactionQueue's `transaction:created` event — fired once per local
|
|
453
359
|
* create/update/delete/archive with `previousData` already captured.
|
|
454
360
|
* Remote/collaborator deltas apply via `applyDeltaBatchToPool` and never
|
|
@@ -469,28 +375,25 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
469
375
|
/**
|
|
470
376
|
* Register the access-credential re-mint hook. Called by the React provider
|
|
471
377
|
* with a thunk that mints a fresh `ek_`/`rk_` (typically its `getToken`).
|
|
472
|
-
* See {@link
|
|
378
|
+
* See {@link CredentialLifecycle.setRefresher}.
|
|
473
379
|
*/
|
|
474
|
-
setCredentialRefresher(refresher:
|
|
380
|
+
setCredentialRefresher(refresher: CredentialRefresher | null): void;
|
|
475
381
|
/**
|
|
476
382
|
* Re-mint the short-lived access credential and push it into the credential
|
|
477
383
|
* source, reporting a tri-state outcome the {@link ConnectionManager} maps to
|
|
478
|
-
* its FSM.
|
|
479
|
-
*
|
|
480
|
-
* return/throw):
|
|
481
|
-
* - token string → `'refreshed'` (fresh key in place; re-probe & reconnect)
|
|
482
|
-
* - `null` → `'session_error'` (login itself is gone → terminal, sign out)
|
|
483
|
-
* - throw → `'network_error'` (couldn't reach the mint endpoint → transient)
|
|
484
|
-
*
|
|
485
|
-
* SINGLE-FLIGHT: concurrent callers (a wake nudge, an in-flight request, the
|
|
486
|
-
* probe) share one in-flight promise so we never double-mint — the canonical
|
|
487
|
-
* fix for the "every 401 mints a token → thrash → spurious logout" anti-pattern.
|
|
488
|
-
*
|
|
489
|
-
* No refresher wired ⇒ `'refreshed'` (a no-op re-probe): a static-`apiKey`
|
|
490
|
-
* deployment has no session to re-mint from; its credential source refreshes
|
|
491
|
-
* out-of-band, so we just re-probe with whatever it currently holds.
|
|
384
|
+
* its FSM. Single-flight; no refresher wired ⇒ `'refreshed'` (a no-op
|
|
385
|
+
* re-probe). Full contract on {@link CredentialLifecycle.refresh}.
|
|
492
386
|
*/
|
|
493
387
|
performCredentialRefresh(): Promise<'refreshed' | 'session_error' | 'network_error'>;
|
|
388
|
+
/**
|
|
389
|
+
* The authentication-recovery path for HTTP transports, such as the lazy
|
|
390
|
+
* query lane. It runs a single-flight credential re-mint driven by the
|
|
391
|
+
* rejection's recovery class, routing outcomes through the same state
|
|
392
|
+
* machine the WebSocket probe uses. `'retry'` means a fresh credential is
|
|
393
|
+
* now in the credential source and the request should be replayed once.
|
|
394
|
+
* Full contract on {@link CredentialLifecycle.recoverFromAuthRejection}.
|
|
395
|
+
*/
|
|
396
|
+
recoverFromAuthRejection(recovery: RecoveryClass): Promise<'retry' | 'stop'>;
|
|
494
397
|
/**
|
|
495
398
|
* Nudge the connection FSM to re-probe with the current credential. Idempotent
|
|
496
399
|
* and safe in any state (ignored while `connected`). Call after pushing a
|
|
@@ -500,72 +403,40 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
500
403
|
*/
|
|
501
404
|
nudgeReconnect(): void;
|
|
502
405
|
/**
|
|
503
|
-
* Install the access-credential lifecycle
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
*
|
|
508
|
-
* timer inside the TTL, plus re-mint on OS wake. The ENTIRE proactive
|
|
509
|
-
* block is browser-gated (`typeof window`): server/SSR has no socket to
|
|
510
|
-
* keep warm and the resolver is browser-oriented, so arming it in Node
|
|
511
|
-
* would fire a relative-URL fetch and throw. (Agents pass a static
|
|
512
|
-
* `apiKey` with no resolver, so this method is never called for them.)
|
|
513
|
-
*
|
|
514
|
-
* Config-driven and invisible, like Supabase's `autoRefreshToken` — consumers
|
|
515
|
-
* never call a refresh method. Idempotent (a second call replaces the first);
|
|
516
|
-
* torn down on {@link disconnect}.
|
|
406
|
+
* Install the client-owned access-credential lifecycle: register `getToken`
|
|
407
|
+
* as the reactive re-mint hook and arm the browser-only proactive refresh
|
|
408
|
+
* (a refresh timer plus an OS-wake re-mint). Idempotent — a second call
|
|
409
|
+
* replaces the first — and torn down on {@link disconnect}. Full rationale
|
|
410
|
+
* on {@link CredentialLifecycle.start}.
|
|
517
411
|
*/
|
|
518
|
-
startCredentialLifecycle(getToken:
|
|
412
|
+
startCredentialLifecycle(getToken: CredentialRefresher, opts?: {
|
|
413
|
+
proactiveInNode?: boolean;
|
|
414
|
+
}): void;
|
|
519
415
|
/** Tear down the proactive credential lifecycle (idempotent). */
|
|
520
416
|
private stopCredentialLifecycle;
|
|
417
|
+
/** Narrow context the group-change leaf talks back through. */
|
|
418
|
+
private groupChangeContext;
|
|
521
419
|
/**
|
|
522
|
-
* Handle an actionType 'G' delta
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* shape:
|
|
526
|
-
*
|
|
527
|
-
* Incremental (EmitGroupAdded): { group, userId }
|
|
528
|
-
* - The recipient was added to a single sync group.
|
|
529
|
-
* - Subsequent 'C' (Covering) deltas deliver each newly-visible entity.
|
|
530
|
-
* - No re-bootstrap — entities arrive via the normal insert path.
|
|
531
|
-
*
|
|
532
|
-
* Legacy (EmitGroupChange): { addedGroups, removedGroups }
|
|
533
|
-
* - Single delta carrying the full group membership diff.
|
|
534
|
-
* - Forces a full re-bootstrap (disconnect + reconnect + fetch all).
|
|
535
|
-
* - Deprecated on the server; kept here for wire-level backward compat.
|
|
420
|
+
* Handle an actionType 'G' delta — incremental `{ group, userId }` or
|
|
421
|
+
* legacy `{ addedGroups, removedGroups }` payloads. Full pathway doc on
|
|
422
|
+
* {@link groupChange.handleSyncGroupChange}.
|
|
536
423
|
*/
|
|
537
424
|
protected handleSyncGroupChange(delta: SyncDelta): Promise<void>;
|
|
538
425
|
/**
|
|
539
|
-
* Handle an incremental GroupAdded delta
|
|
540
|
-
*
|
|
541
|
-
* Adds the new group to the subscription metadata without triggering a
|
|
542
|
-
* re-bootstrap. The server will follow up with 'C' (Covering) deltas for
|
|
543
|
-
* each newly-visible entity, which flow through the normal insert path.
|
|
426
|
+
* Handle an incremental GroupAdded delta — metadata only, no re-bootstrap
|
|
427
|
+
* (covering deltas bring the entities). See {@link groupChange.handleGroupAdded}.
|
|
544
428
|
*/
|
|
545
429
|
protected handleGroupAdded(payload: GroupAddedPayload, syncId: number): Promise<void>;
|
|
546
430
|
/**
|
|
547
|
-
* Handle an actionType 'S' (GroupRemoved) delta
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
* the client does not track per-entity group membership, we can't
|
|
551
|
-
* selectively purge entities belonging to that group. The safe fallback
|
|
552
|
-
* is the legacy behavior: clear local state and force a re-bootstrap
|
|
553
|
-
* with the updated group list.
|
|
554
|
-
*
|
|
555
|
-
* Future optimization: track group membership in the ObjectPool so 'S'
|
|
556
|
-
* can do a targeted purge instead of a full re-bootstrap.
|
|
431
|
+
* Handle an actionType 'S' (GroupRemoved) delta: for safety, clear the
|
|
432
|
+
* revoked local state and trigger a full re-bootstrap. See
|
|
433
|
+
* {@link groupChange.handleGroupRemoved}.
|
|
557
434
|
*/
|
|
558
435
|
protected handleGroupRemoved(delta: SyncDelta): Promise<void>;
|
|
559
436
|
/** Compute new sync groups after applying additions and removals */
|
|
560
437
|
protected computeUpdatedSyncGroups(payload: SyncGroupChangePayload): string[];
|
|
561
|
-
/** Force a full re-bootstrap via connection lifecycle event
|
|
562
|
-
*
|
|
563
|
-
* No-op for `bootstrapMode: 'none'` participants — they never pull
|
|
564
|
-
* baseline state, so a "force re-bootstrap" trigger (sync-group
|
|
565
|
-
* shrink, scope revocation) instead just flushes the local pool and
|
|
566
|
-
* relies on covering deltas to repopulate the data they actually
|
|
567
|
-
* subscribe to.
|
|
568
|
-
*/
|
|
438
|
+
/** Force a full re-bootstrap via connection lifecycle event (no-op for
|
|
439
|
+
* `bootstrapMode: 'none'` participants — see {@link groupChange.forceFullRebootstrap}). */
|
|
569
440
|
protected forceFullRebootstrap(): void;
|
|
570
441
|
/**
|
|
571
442
|
* Single source of truth for the sync-group list this session is
|
|
@@ -578,8 +449,9 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
578
449
|
protected resolveSyncGroups(context: UserContext): readonly string[];
|
|
579
450
|
/** Check if sync groups shrank since last session — force full bootstrap if so */
|
|
580
451
|
protected checkSyncGroupShrinkage(): Promise<void>;
|
|
581
|
-
/**
|
|
582
|
-
|
|
452
|
+
/** Narrow context the bootstrap-apply leaf talks back through. */
|
|
453
|
+
private poolContext;
|
|
454
|
+
/** Apply bootstrap data to the {@link InstanceCache}, removing entities that are no longer present (ghost removal). Pool writes are delegated to {@link SyncClient}. */
|
|
583
455
|
protected applyBootstrapToPool(bootstrapResult: BootstrapResult, protectedIds?: ReadonlySet<string>): RehydrationStats;
|
|
584
456
|
/**
|
|
585
457
|
* Initialize the sync engine with user context.
|
|
@@ -595,7 +467,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
595
467
|
protected withDeltaQueuing<T>(fn: () => Promise<T>): Promise<T>;
|
|
596
468
|
/** Collect IDs that must survive ghost removal (added by deltas during bootstrap) */
|
|
597
469
|
protected collectDeltaProtectedIds(preBootstrapIds: ReadonlySet<string>): Set<string>;
|
|
598
|
-
/** Replay deltas queued during bootstrap */
|
|
470
|
+
/** Replay deltas queued during bootstrap (atomically, via `applyDeltaFrame`). */
|
|
599
471
|
protected replayQueuedDeltas(): void;
|
|
600
472
|
/**
|
|
601
473
|
* Factory for the internal `ConnectionManager`. Override to return
|
|
@@ -664,11 +536,13 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
664
536
|
*/
|
|
665
537
|
protected waitForWebSocketConnected(timeoutMs: number): Promise<boolean>;
|
|
666
538
|
protected setupWebSocketSync(context: UserContext, lastSyncId: number): void;
|
|
667
|
-
/**
|
|
668
|
-
|
|
539
|
+
/** Memoized pipeline context — `enqueueDelta` runs once per delta, so the
|
|
540
|
+
* accessor object is built once and reused (the get/set accessors always
|
|
541
|
+
* read the live host fields). */
|
|
542
|
+
private _deltaPipelineContext;
|
|
543
|
+
private get deltaPipelineContext();
|
|
669
544
|
/** Get fields that represent meaningful state for deduplication. Override for model-specific fields. */
|
|
670
545
|
protected getStateFields(_modelName: string): string[];
|
|
671
|
-
private isSameState;
|
|
672
546
|
/** Deduplicate deltas to the same entity — keep meaningful state transitions only */
|
|
673
547
|
protected deduplicateDeltas(deltas: SyncDelta[]): SyncDelta[];
|
|
674
548
|
/** Process incoming delta with smart batching */
|
|
@@ -676,23 +550,24 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
676
550
|
/**
|
|
677
551
|
* Apply a complete, server-delivered delta frame atomically.
|
|
678
552
|
*
|
|
679
|
-
* A `delta_batch`
|
|
680
|
-
* the
|
|
681
|
-
* `processDeltaWithBatching` path re-
|
|
682
|
-
* debounce timer
|
|
683
|
-
*
|
|
684
|
-
*
|
|
685
|
-
*
|
|
553
|
+
* A `delta_batch` WebSocket event (a reconnect or catch-up replay) already
|
|
554
|
+
* carries the full set of missed deltas. Routing it through the per-delta
|
|
555
|
+
* `processDeltaWithBatching` path would re-chunk it via the live-traffic
|
|
556
|
+
* debounce timer and `maxBatchSize` force-flush, so a 300-delta catch-up
|
|
557
|
+
* would fan out into several separate `flushPendingDeltas` cycles — each its
|
|
558
|
+
* own local write, pool mutation, `models:changed` emit, and re-render, so
|
|
559
|
+
* the UI visibly repaints once per chunk.
|
|
686
560
|
*
|
|
687
|
-
*
|
|
688
|
-
* watermark,
|
|
689
|
-
* a flush, then
|
|
690
|
-
*
|
|
691
|
-
*
|
|
561
|
+
* Instead, this runs the per-delta bookkeeping (deduplication, ack, version
|
|
562
|
+
* vector, watermark, group-change routing, delete cascade) for every delta
|
|
563
|
+
* without scheduling a flush, then flushes once — collapsing the whole frame
|
|
564
|
+
* into a single local write, pool mutation, `models:changed` emit, and
|
|
565
|
+
* re-render. The post-bootstrap replay of deltas queued during bootstrap
|
|
566
|
+
* uses the same path.
|
|
692
567
|
*
|
|
693
|
-
*
|
|
694
|
-
* with
|
|
695
|
-
* eventually drives through `flushPendingDeltas`.
|
|
568
|
+
* It is named `applyDeltaFrame`, not `processDeltaBatch`, to avoid confusion
|
|
569
|
+
* with {@link Database.processDeltaBatch} — the lower-level local write this
|
|
570
|
+
* eventually drives through `flushPendingDeltas`.
|
|
696
571
|
*/
|
|
697
572
|
protected applyDeltaFrame(deltas: SyncDelta[]): void;
|
|
698
573
|
/**
|
|
@@ -720,8 +595,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
720
595
|
* skips both the scan AND the allocation.
|
|
721
596
|
*/
|
|
722
597
|
protected cascadeCancelTransactionsForDeletedParent(parentModelName: string, parentId: string): void;
|
|
723
|
-
/** Flush pending deltas with deduplication
|
|
724
|
-
/** Flush pending deltas with deduplication. Delegates pool writes to SyncClient. */
|
|
598
|
+
/** Flush pending deltas with deduplication. Pool writes are delegated to {@link SyncClient}. */
|
|
725
599
|
protected flushPendingDeltas(): Promise<void>;
|
|
726
600
|
/** Check if a model type is local-only (no sync). Override for domain-specific models. */
|
|
727
601
|
protected isLocalOnlyModel(_modelName: string): boolean;
|
|
@@ -786,10 +660,10 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
786
660
|
*/
|
|
787
661
|
create<K extends keyof TSchema['models'] & string>(typename: K, data: Record<string, unknown>): import('./schema/schema.js').InferModel<TSchema, K> | null;
|
|
788
662
|
/**
|
|
789
|
-
*
|
|
790
|
-
*
|
|
791
|
-
*
|
|
792
|
-
*
|
|
663
|
+
* Query entry point for callers that hold a {@link Model} constructor and an
|
|
664
|
+
* options object. It filters, orders, and paginates the matching models from
|
|
665
|
+
* the pool. Prefer the schema-typed read surface (`ablo.<model>.list`) where
|
|
666
|
+
* you can, since it infers concrete row types without a class value or cast.
|
|
793
667
|
*/
|
|
794
668
|
queryByClass(modelClass: ModelConstructor<Model>, options?: {
|
|
795
669
|
predicate?: (model: Model) => boolean;
|
|
@@ -818,7 +692,7 @@ export declare class BaseSyncedStore<TCollaboration extends EventMap<TCollaborat
|
|
|
818
692
|
protected incrementPendingChanges(): void;
|
|
819
693
|
protected decrementPendingChanges(): void;
|
|
820
694
|
protected updateSyncStatus(updates: Partial<SyncStatus>): void;
|
|
821
|
-
get pool():
|
|
695
|
+
get pool(): InstanceCache;
|
|
822
696
|
get lastSyncId(): number;
|
|
823
697
|
get isReady(): boolean;
|
|
824
698
|
get isSyncing(): boolean;
|