@abloatai/ablo 0.26.0 → 0.28.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 +42 -2
- package/README.md +102 -86
- package/dist/BaseSyncedStore.d.ts +85 -88
- package/dist/BaseSyncedStore.js +134 -151
- package/dist/Database.d.ts +68 -69
- package/dist/Database.js +316 -135
- 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 +54 -52
- package/dist/Model.js +78 -62
- 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 +122 -118
- package/dist/SyncClient.js +541 -245
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +10 -9
- package/dist/adapters/inMemoryStorage.js +21 -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 +173 -121
- package/dist/client/Ablo.d.ts +97 -74
- package/dist/client/Ablo.js +129 -163
- package/dist/client/ApiClient.d.ts +30 -19
- package/dist/client/ApiClient.js +442 -81
- 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 +16 -17
- package/dist/client/createInternalComponents.js +26 -31
- 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 +59 -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 +78 -87
- package/dist/client/options.d.ts +157 -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 +16 -20
- package/dist/client/wsMutationExecutor.js +18 -23
- package/dist/commit/contract.d.ts +493 -0
- package/dist/commit/contract.js +187 -0
- package/dist/commit/index.d.ts +6 -0
- package/dist/commit/index.js +5 -0
- 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 +14 -14
- package/dist/core/StoreManager.js +33 -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 +137 -134
- package/dist/errors.d.ts +160 -166
- package/dist/errors.js +155 -158
- package/dist/index.d.ts +36 -27
- package/dist/index.js +91 -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 +124 -131
- package/dist/mutators/UndoManager.js +177 -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 +28 -25
- package/dist/react/useAblo.js +41 -17
- 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 +3 -3
- 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 +64 -43
- 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 +24 -12
- package/dist/stores/ObjectStore.js +38 -16
- package/dist/stores/ObjectStoreContract.d.ts +14 -15
- package/dist/stores/SyncActionStore.d.ts +7 -11
- package/dist/stores/SyncActionStore.js +13 -17
- package/dist/surface.d.ts +28 -21
- package/dist/surface.js +29 -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 +141 -166
- 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/persistedPrefix.d.ts +12 -0
- package/dist/sync/persistedPrefix.js +22 -0
- 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 +5 -3
- package/dist/testing/index.js +3 -2
- package/dist/testing/mocks/FakeDatabase.d.ts +18 -0
- package/dist/testing/mocks/FakeDatabase.js +10 -0
- 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 +28 -23
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +244 -181
- package/dist/transactions/TransactionQueue.js +929 -423
- 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/commitEnvelope.d.ts +132 -0
- package/dist/transactions/commitEnvelope.js +139 -0
- package/dist/transactions/commitOutboxStore.d.ts +32 -0
- package/dist/transactions/commitOutboxStore.js +26 -0
- package/dist/transactions/commitPayload.d.ts +63 -52
- package/dist/transactions/commitPayload.js +54 -57
- package/dist/transactions/deltaConfirmation.d.ts +20 -22
- package/dist/transactions/deltaConfirmation.js +37 -45
- package/dist/transactions/httpCommitEnvelope.d.ts +43 -0
- package/dist/transactions/httpCommitEnvelope.js +179 -0
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/replayValidation.d.ts +182 -0
- package/dist/transactions/replayValidation.js +156 -0
- 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/wire/bootstrapReason.d.ts +9 -0
- package/dist/wire/bootstrapReason.js +8 -0
- 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 +315 -86
- package/dist/wire/frames.js +47 -33
- package/dist/wire/index.d.ts +18 -14
- package/dist/wire/index.js +32 -27
- 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/api.md +10 -10
- package/docs/coordination.md +59 -0
- package/docs/mcp.md +1 -1
- package/package.json +17 -11
- 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/transactions/persistedReplay.d.ts +0 -93
- package/dist/transactions/persistedReplay.js +0 -105
- package/dist/utils/mobx-setup.d.ts +0 -42
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `startCredentialLifecycle`) so its published surface is unchanged, and
|
|
9
|
-
* talks back through the minimal {@link CredentialLifecycleContext} —
|
|
10
|
-
* never the store's class type — so no module cycle forms.
|
|
2
|
+
* Keeps the short-lived access credential fresh. It owns the re-mint hook, a
|
|
3
|
+
* single-flight guard that stops concurrent triggers from minting more than
|
|
4
|
+
* once, and a browser-only proactive refresh — a timer plus an OS-wake listener
|
|
5
|
+
* — that renews the credential ahead of expiry. It reaches the rest of the
|
|
6
|
+
* client only through the small {@link CredentialLifecycleContext} interface,
|
|
7
|
+
* so the two can reference each other without an import cycle.
|
|
11
8
|
*/
|
|
12
9
|
import { getContext } from '../context.js';
|
|
13
|
-
/**
|
|
14
|
-
* comfortably inside the server's
|
|
15
|
-
* the refresher reports no expiry. */
|
|
10
|
+
/** The fallback pre-roll interval, and also its ceiling: 10 minutes, which sits
|
|
11
|
+
* comfortably inside the server's 15-minute default credential lifetime. Used
|
|
12
|
+
* as-is when the refresher reports no expiry. */
|
|
16
13
|
export const DEFAULT_PREROLL_INTERVAL_MS = 10 * 60 * 1000;
|
|
17
14
|
/** Floor so a very short (or already-elapsed) TTL can't hot-loop the mint. */
|
|
18
15
|
export const MIN_PREROLL_DELAY_MS = 30 * 1000;
|
|
19
16
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
17
|
+
* Computes how long to wait before pre-rolling a credential that expires at
|
|
18
|
+
* `expiresAtMs`: about two-thirds of the remaining lifetime (a 15-minute
|
|
19
|
+
* credential yields 10 minutes), clamped to
|
|
20
|
+
* [{@link MIN_PREROLL_DELAY_MS}, {@link DEFAULT_PREROLL_INTERVAL_MS}]. An
|
|
21
|
+
* unknown expiry (`null`) falls back to the 10-minute interval. Exported for
|
|
22
|
+
* unit tests.
|
|
24
23
|
*/
|
|
25
24
|
export function computePrerollDelayMs(expiresAtMs, nowMs) {
|
|
26
25
|
if (expiresAtMs === null || !Number.isFinite(expiresAtMs)) {
|
|
@@ -47,60 +46,60 @@ function normalizeExpiresAtMs(expiresAt) {
|
|
|
47
46
|
export class CredentialLifecycle {
|
|
48
47
|
ctx;
|
|
49
48
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* resolves a token string on success, `null` when
|
|
55
|
-
* gone (terminal), and
|
|
56
|
-
* {@link refresh}.
|
|
57
|
-
* `apiKey`
|
|
49
|
+
* The hook that mints a fresh short-lived access credential (the `ek_`/`rk_`
|
|
50
|
+
* key). An integrator wires it from their own token endpoint: this lifecycle
|
|
51
|
+
* decides when to refresh (a stale-credential probe or an external nudge),
|
|
52
|
+
* and the hook decides how to mint. It follows the same contract as a
|
|
53
|
+
* `getToken` function — it resolves a token string on success, `null` when
|
|
54
|
+
* the long-lived login is gone (a terminal state), and throws on a transient
|
|
55
|
+
* or offline failure. Used by {@link refresh}. When it is absent there is no
|
|
56
|
+
* silent re-mint, as with a static `apiKey` whose credential source is
|
|
57
|
+
* refreshed elsewhere.
|
|
58
58
|
*/
|
|
59
59
|
credentialRefresher = null;
|
|
60
60
|
/** Single-flight guard so a wake nudge + an in-flight request + a probe don't
|
|
61
61
|
* all mint at once (the classic "token thrash → random logout" bug). */
|
|
62
62
|
inFlightCredentialRefresh = null;
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
63
|
+
/** Tears down the proactive credential lifecycle (the refresh timer and the
|
|
64
|
+
* OS-wake listener) installed by {@link start}; cleared when the client
|
|
65
|
+
* disconnects. Null when no refresher is wired. */
|
|
66
66
|
credentialLifecycleTeardown = null;
|
|
67
|
-
/** Epoch
|
|
68
|
-
* (object
|
|
69
|
-
* string-form resolver
|
|
67
|
+
/** Epoch milliseconds at which the current credential expires, when the
|
|
68
|
+
* refresher reports it (the object form of {@link CredentialRefreshResult}).
|
|
69
|
+
* `null` for the string-form resolver, in which case the pre-roll uses its
|
|
70
|
+
* fixed interval. */
|
|
70
71
|
credentialExpiresAtMs = null;
|
|
71
|
-
/** Re-
|
|
72
|
-
*
|
|
73
|
-
* the
|
|
74
|
-
*
|
|
72
|
+
/** Re-arms the proactive pre-roll timer (set by {@link start}). Called after
|
|
73
|
+
* every successful mint, so a refresh triggered reactively (by a probe, an
|
|
74
|
+
* OS wake, or the first mint) re-anchors the schedule to the fresh
|
|
75
|
+
* credential's real expiry instead of a stale fixed delay. */
|
|
75
76
|
prerollReschedule = null;
|
|
76
77
|
constructor(ctx) {
|
|
77
78
|
this.ctx = ctx;
|
|
78
79
|
}
|
|
79
80
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
81
|
+
* Registers the re-mint hook for the access credential — a function that
|
|
82
|
+
* mints a fresh `ek_`/`rk_` key, typically the integrator's `getToken`. See
|
|
83
|
+
* {@link credentialRefresher}.
|
|
83
84
|
*/
|
|
84
85
|
setRefresher(refresher) {
|
|
85
86
|
this.credentialRefresher = refresher;
|
|
86
87
|
}
|
|
87
88
|
/**
|
|
88
|
-
* Re-
|
|
89
|
-
* source,
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* - token string → `'refreshed'` (fresh key in place; re-probe & reconnect)
|
|
94
|
-
* - `null` → `'session_error'` (login itself is gone → terminal, sign out)
|
|
95
|
-
* - throw → `'network_error'` (couldn't reach the mint endpoint → transient)
|
|
89
|
+
* Re-mints the short-lived access credential, pushes it into the credential
|
|
90
|
+
* source, and reports a three-way outcome the connection layer acts on:
|
|
91
|
+
* - a token string → `'refreshed'` (the fresh key is in place; re-probe and reconnect)
|
|
92
|
+
* - `null` → `'session_error'` (the login itself is gone — terminal, sign out)
|
|
93
|
+
* - a thrown error → `'network_error'` (the mint endpoint was unreachable — transient)
|
|
96
94
|
*
|
|
97
|
-
*
|
|
98
|
-
* probe) share one in-flight promise so
|
|
99
|
-
*
|
|
95
|
+
* The call is single-flight: concurrent triggers (an OS wake, an in-flight
|
|
96
|
+
* request, a probe) share one in-flight promise, so the credential is never
|
|
97
|
+
* minted twice at once. This avoids the failure where every rejected request
|
|
98
|
+
* mints a new token and the resulting thrash logs the user out.
|
|
100
99
|
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
100
|
+
* With no refresher wired, it resolves `'refreshed'` as a no-op re-probe: a
|
|
101
|
+
* static-`apiKey` client has no session to mint from and its credential
|
|
102
|
+
* source is refreshed elsewhere, so it simply re-probes with what it holds.
|
|
104
103
|
*/
|
|
105
104
|
async refresh() {
|
|
106
105
|
const refresher = this.credentialRefresher;
|
|
@@ -113,8 +112,8 @@ export class CredentialLifecycle {
|
|
|
113
112
|
const result = await refresher();
|
|
114
113
|
const token = typeof result === 'string' ? result : result?.token;
|
|
115
114
|
if (!token) {
|
|
116
|
-
// null = the long-lived login is gone (mint endpoint answered
|
|
117
|
-
// Terminal —
|
|
115
|
+
// null = the long-lived login is gone (the mint endpoint answered
|
|
116
|
+
// 401/403). Terminal — this routes to sign-out.
|
|
118
117
|
return 'session_error';
|
|
119
118
|
}
|
|
120
119
|
// Object-form resolvers carry the mint's actual expiry; remember it so
|
|
@@ -134,12 +133,12 @@ export class CredentialLifecycle {
|
|
|
134
133
|
// login may be perfectly valid; never sign out for this — back off and
|
|
135
134
|
// retry. Mirrors the `getToken` throw-vs-null contract end-to-end.
|
|
136
135
|
const message = error?.message ?? String(error);
|
|
137
|
-
// A relative-URL resolver invoked server
|
|
138
|
-
// to resolve against)
|
|
139
|
-
// absolute URLs are supported". Translate it into something
|
|
140
|
-
//
|
|
141
|
-
// browser-only, so
|
|
142
|
-
// a server route.
|
|
136
|
+
// A relative-URL resolver invoked on the server (Node's fetch has no
|
|
137
|
+
// origin to resolve against) throws the opaque "Failed to parse URL" or
|
|
138
|
+
// "Only absolute URLs are supported". Translate it into something
|
|
139
|
+
// actionable rather than a mystery transient blip: the proactive
|
|
140
|
+
// refresh is browser-only, so reaching here means the resolver fired
|
|
141
|
+
// from a server render or a server route.
|
|
143
142
|
if (typeof window === 'undefined' && /parse URL|absolute URLs?/i.test(message)) {
|
|
144
143
|
getContext().logger.warn('credential resolver ran on the server with a relative URL — Node fetch needs an absolute URL. ' +
|
|
145
144
|
'Refresh the Ablo client in the browser, or build an absolute URL server-side ' +
|
|
@@ -160,9 +159,10 @@ export class CredentialLifecycle {
|
|
|
160
159
|
}
|
|
161
160
|
}
|
|
162
161
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* HTTP auth-recovery path so every
|
|
162
|
+
* Interprets a refresh outcome and drives the connection accordingly. This is
|
|
163
|
+
* the single place the three-way outcome is acted on, shared by the proactive
|
|
164
|
+
* pre-roll, the OS-wake nudge, and the HTTP auth-recovery path, so every
|
|
165
|
+
* trigger converges on the same behavior.
|
|
166
166
|
*/
|
|
167
167
|
routeRefreshOutcome(outcome) {
|
|
168
168
|
if (outcome === 'refreshed') {
|
|
@@ -172,32 +172,31 @@ export class CredentialLifecycle {
|
|
|
172
172
|
return 'retry';
|
|
173
173
|
}
|
|
174
174
|
if (outcome === 'session_error') {
|
|
175
|
-
// The long-lived login is gone (mint answered 401/403).
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
// owns the authoritative log.
|
|
175
|
+
// The long-lived login is gone (the mint answered 401/403). Report it;
|
|
176
|
+
// this is harmless in connection states that don't accept the event,
|
|
177
|
+
// which converge on sign-out anyway.
|
|
179
178
|
this.ctx.reportSessionExpired();
|
|
180
179
|
return 'stop';
|
|
181
180
|
}
|
|
182
|
-
// 'network_error' → transient (offline
|
|
183
|
-
// tick or the
|
|
181
|
+
// 'network_error' → transient (offline or a mint hiccup); the next proactive
|
|
182
|
+
// tick or the connection's own probe retries. Never sign out, never replay now.
|
|
184
183
|
return 'stop';
|
|
185
184
|
}
|
|
186
185
|
/**
|
|
187
|
-
*
|
|
188
|
-
* The
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
186
|
+
* The shared recovery path for a request rejected on authentication, over any
|
|
187
|
+
* transport. The WebSocket probe already routes its own 401s; HTTP callers
|
|
188
|
+
* call this instead of inventing their own handling, so every path shares one
|
|
189
|
+
* single-flight mint, one outcome routing, and one taxonomy. It classifies
|
|
190
|
+
* the same recovery codes the connection probe does:
|
|
191
|
+
* - `access_credential_expiry` — the routine case, an expired `ek_`/`rk_`:
|
|
192
|
+
* silently re-mint through the single-flight {@link refresh} and tell the
|
|
193
|
+
* caller to replay once on success. This never signs out on its own; the
|
|
194
|
+
* only terminal path is the mint resolving `null`.
|
|
195
|
+
* - `session_expiry` — the login is gone: report it (which drives sign-out)
|
|
196
|
+
* and stop, since replaying is pointless.
|
|
197
|
+
* - `auth_blocked`, `permission`, and everything else — re-minting would
|
|
198
|
+
* produce the same rejected credential, so stop and leave the connection
|
|
199
|
+
* alone.
|
|
201
200
|
*/
|
|
202
201
|
async recoverFromAuthRejection(recovery) {
|
|
203
202
|
switch (recovery) {
|
|
@@ -211,40 +210,38 @@ export class CredentialLifecycle {
|
|
|
211
210
|
}
|
|
212
211
|
}
|
|
213
212
|
/**
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
213
|
+
* Installs the credential lifecycle. It has two parts:
|
|
214
|
+
* 1. Reactive — registers `getToken` as the re-mint hook the connection
|
|
215
|
+
* calls when a probe finds the key stale, or on a nudge.
|
|
216
|
+
* 2. Proactive — keeps the short-lived key fresh ahead of expiry with a
|
|
217
|
+
* refresh timer inside the credential's lifetime, plus a re-mint on OS
|
|
218
|
+
* wake. The whole proactive block is browser-gated on `typeof window`,
|
|
219
|
+
* because a server render has no socket to keep warm and the resolver is
|
|
220
|
+
* browser-oriented; arming it under Node would fire a relative-URL fetch
|
|
221
|
+
* and throw. (Agents pass a static `apiKey` with no resolver, so this
|
|
222
|
+
* method is never called for them.)
|
|
224
223
|
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
224
|
+
* Refreshing is automatic — a consumer never calls a refresh method. The call
|
|
225
|
+
* is idempotent: a second call replaces the first, and it is torn down when
|
|
226
|
+
* the client disconnects.
|
|
228
227
|
*
|
|
229
|
-
* `opts.proactiveInNode` arms the refresh
|
|
230
|
-
*
|
|
231
|
-
* `rk_`/`ek_` must renew
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
228
|
+
* `opts.proactiveInNode` arms the refresh timer on a windowless host as well.
|
|
229
|
+
* Set it for agent or system participants — long-lived server sockets whose
|
|
230
|
+
* `rk_`/`ek_` must renew before the server's keepalive check closes them.
|
|
231
|
+
* Node timers are `unref`ed, so a finishing script is never held alive by the
|
|
232
|
+
* pre-roll. The OS-wake listener stays browser-only regardless, since there
|
|
233
|
+
* is no `window` to listen on.
|
|
235
234
|
*/
|
|
236
235
|
start(getToken, opts) {
|
|
237
236
|
this.stop();
|
|
238
237
|
this.setRefresher(getToken);
|
|
239
|
-
// Re-mint through the
|
|
240
|
-
// (`refresh`) rather than calling `getToken()` directly.
|
|
241
|
-
//
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
// every tab focus and logged "signing out" forever without ever signing
|
|
247
|
-
// out. `session_error` now drives the FSM to actually expire.
|
|
238
|
+
// Re-mint through the same single-flight path the reactive probe uses
|
|
239
|
+
// (`refresh`) rather than calling `getToken()` directly. This gives two
|
|
240
|
+
// things: the mint stays single-flight, so an OS wake, an in-flight probe,
|
|
241
|
+
// and this proactive roll share one in-flight promise instead of thrashing;
|
|
242
|
+
// and the three-way outcome is honored, so a `null` result (the login is
|
|
243
|
+
// gone) actually drives expiry instead of being dropped, which would leave a
|
|
244
|
+
// zombie session that re-mints on every tab focus.
|
|
248
245
|
const refresh = async () => {
|
|
249
246
|
// Same outcome routing as every other trigger (see routeRefreshOutcome):
|
|
250
247
|
// refreshed → nudge, session_error → report, network_error → wait for
|
|
@@ -252,37 +249,37 @@ export class CredentialLifecycle {
|
|
|
252
249
|
this.routeRefreshOutcome(await this.refresh());
|
|
253
250
|
};
|
|
254
251
|
const teardowns = [];
|
|
255
|
-
// The proactive pre-roll arms in the browser, or
|
|
256
|
-
//
|
|
257
|
-
// Node posture stays reactive-only because a
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
// real connection probe, which can't happen during a bare SSR module eval.
|
|
252
|
+
// The proactive pre-roll arms in the browser, or under Node when the host
|
|
253
|
+
// opts in (`proactiveInNode`, for agent or system participants). The
|
|
254
|
+
// default Node posture stays reactive-only, because a server render can
|
|
255
|
+
// construct user-kind clients whose resolver is browser-oriented (a
|
|
256
|
+
// relative-URL `fetch('/api/ablo-session')`); arming a timer there fires
|
|
257
|
+
// that resolver under Node, where fetch has no origin for a relative URL and
|
|
258
|
+
// throws "Failed to parse URL" on every tick. Long-lived server
|
|
259
|
+
// participants are the opposite case: their socket must outlive the
|
|
260
|
+
// credential's lifetime, so they get the timer. The reactive re-mint hook
|
|
261
|
+
// (`setRefresher` above) stays unconditional: it only fires on a real
|
|
262
|
+
// connection probe, which can't happen during a bare server-side module
|
|
263
|
+
// evaluation.
|
|
268
264
|
if (typeof window !== 'undefined' || opts?.proactiveInNode === true) {
|
|
269
|
-
// A missed (background
|
|
270
|
-
// the reactive probe.
|
|
271
|
-
// the key warm ahead of expiry even while the socket
|
|
272
|
-
//
|
|
273
|
-
// the minted credential's
|
|
274
|
-
// one (
|
|
275
|
-
// ceiling
|
|
276
|
-
//
|
|
265
|
+
// A missed tick (throttled in the background) is recovered by the next
|
|
266
|
+
// one, or by the reactive probe. This timer is the only proactive
|
|
267
|
+
// pre-roll — it keeps the key warm ahead of expiry even while the socket
|
|
268
|
+
// sits healthy and connected, a state the connection never probes. The
|
|
269
|
+
// delay comes from the minted credential's real `expiresAt` when the
|
|
270
|
+
// refresher reports one (about two-thirds of the remaining lifetime), with
|
|
271
|
+
// the 10-minute value as both ceiling and fallback, so a deployment that
|
|
272
|
+
// mints shorter-lived keys still pre-rolls in time rather than dropping to
|
|
273
|
+
// reactive-only recovery.
|
|
277
274
|
let timer = null;
|
|
278
275
|
const scheduleNext = () => {
|
|
279
276
|
if (timer !== null)
|
|
280
277
|
clearTimeout(timer); // idempotent re-arm
|
|
281
278
|
const delay = computePrerollDelayMs(this.credentialExpiresAtMs, Date.now());
|
|
282
279
|
timer = setTimeout(() => {
|
|
283
|
-
// `.finally` keeps the chain alive
|
|
284
|
-
//
|
|
285
|
-
//
|
|
280
|
+
// `.finally` keeps the chain alive after a transient failure; a
|
|
281
|
+
// successful mint has already re-armed via `prerollReschedule` (the
|
|
282
|
+
// clearTimeout above makes the double-arm a no-op).
|
|
286
283
|
void refresh().finally(scheduleNext);
|
|
287
284
|
}, delay);
|
|
288
285
|
// Node: never keep a finishing process alive just for the pre-roll
|
|
@@ -297,19 +294,15 @@ export class CredentialLifecycle {
|
|
|
297
294
|
timer = null;
|
|
298
295
|
this.prerollReschedule = null;
|
|
299
296
|
});
|
|
300
|
-
// OS-wake
|
|
301
|
-
// 'resume' to this DOM event.
|
|
302
|
-
// still owns, because `visibilitychange` does
|
|
303
|
-
// and
|
|
304
|
-
// browser
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
308
|
-
//
|
|
309
|
-
// were REMOVED: the FSM already re-probes on NETWORK_ONLINE / TAB_VISIBLE
|
|
310
|
-
// through this exact credential path, so registering them here too only
|
|
311
|
-
// fired a second, null-swallowing mint per focus — the "session-key
|
|
312
|
-
// POSTed on every tab focus" spam in the console.
|
|
297
|
+
// OS-wake, on desktop only: the Electron shell bridges `powerMonitor`
|
|
298
|
+
// 'resume' to this DOM event. It is the one event trigger this lifecycle
|
|
299
|
+
// still owns, because `visibilitychange` does not fire on wake-from-sleep
|
|
300
|
+
// and the connection's own browser listeners don't cover wake. It is
|
|
301
|
+
// browser-gated separately from the timer, since a `proactiveInNode` host
|
|
302
|
+
// has no `window` to listen on and no OS sleep to wake from. Coming back
|
|
303
|
+
// online and regaining tab visibility are handled elsewhere — the
|
|
304
|
+
// connection already re-probes through this same credential path — so
|
|
305
|
+
// listening for them here too would only fire a second, redundant mint.
|
|
313
306
|
if (typeof window !== 'undefined') {
|
|
314
307
|
const onWake = () => void refresh();
|
|
315
308
|
window.addEventListener('ablo:wake', onWake);
|
|
@@ -1,22 +1,20 @@
|
|
|
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
|
-
import { ModelScope } from '../
|
|
13
|
+
import { ModelScope } from '../InstanceCache.js';
|
|
16
14
|
import type { Model } from '../Model.js';
|
|
17
15
|
import type { ModelData } from '../types/modelData.js';
|
|
18
16
|
import type { SyncDelta } from './SyncWebSocket.js';
|
|
19
|
-
/** One applied-delta result
|
|
17
|
+
/** One applied-delta result from the persistence layer's batch write, forwarded to the pool. */
|
|
20
18
|
interface DeltaDbResult {
|
|
21
19
|
action: 'add' | 'update' | 'remove' | 'archive' | 'verify';
|
|
22
20
|
modelName: string;
|
|
@@ -25,10 +23,10 @@ interface DeltaDbResult {
|
|
|
25
23
|
transactionId?: string;
|
|
26
24
|
}
|
|
27
25
|
/**
|
|
28
|
-
* What the pipeline needs back from
|
|
29
|
-
* pipeline state (backed by
|
|
30
|
-
* persistence
|
|
31
|
-
* overrides
|
|
26
|
+
* What the pipeline needs back from the surrounding store: the shared mutable
|
|
27
|
+
* pipeline state (backed by the store's own fields through accessors), narrow
|
|
28
|
+
* persistence and pool facades, and the store's overridable hooks, so a
|
|
29
|
+
* subclass's overrides continue to take effect.
|
|
32
30
|
*/
|
|
33
31
|
export interface DeltaPipelineContext {
|
|
34
32
|
pendingDeltas: SyncDelta[];
|
|
@@ -57,9 +55,9 @@ export interface DeltaPipelineContext {
|
|
|
57
55
|
results: DeltaDbResult[];
|
|
58
56
|
persistedSyncId: number;
|
|
59
57
|
}>;
|
|
60
|
-
/**
|
|
58
|
+
/** Applies persisted delta results to the in-memory pool, with the host's relation enrichment bound. */
|
|
61
59
|
applyDeltaBatchToPool(results: DeltaDbResult[]): void;
|
|
62
|
-
/**
|
|
60
|
+
/** Acknowledges a sync id back to the server; a no-op when the socket is down. */
|
|
63
61
|
acknowledge(syncId: number): void;
|
|
64
62
|
readonly objectPool: {
|
|
65
63
|
get(id: string): Model | undefined;
|
|
@@ -82,30 +80,34 @@ export interface DeltaPipelineContext {
|
|
|
82
80
|
cascadeCancelTransactionsForDeletedParent(parentModelName: string, parentId: string): void;
|
|
83
81
|
}
|
|
84
82
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* re-bootstrap
|
|
90
|
-
*
|
|
83
|
+
* Handles a sync-group ('G' or 'S') delta whose handler rejected after the
|
|
84
|
+
* applied watermark had already advanced. That delta will never be redelivered,
|
|
85
|
+
* so a failed security clear — revoked data that must not stay cached — would
|
|
86
|
+
* otherwise fail silently. The safe fallback is blunt: drop the whole in-memory
|
|
87
|
+
* pool and force a full re-bootstrap, rebuilding local state from the server.
|
|
88
|
+
* It never throws, because it runs inside the pipeline's fire-and-forget path.
|
|
91
89
|
*/
|
|
92
90
|
export declare function handleGroupHandlerFailure(ctx: DeltaPipelineContext, delta: SyncDelta, error: unknown): void;
|
|
93
91
|
/** Deduplicate deltas to the same entity — keep meaningful state transitions only */
|
|
94
92
|
export declare function deduplicateDeltas(ctx: DeltaPipelineContext, deltas: SyncDelta[]): SyncDelta[];
|
|
95
93
|
/**
|
|
96
|
-
*
|
|
97
|
-
* pushed onto `pendingDeltas`
|
|
98
|
-
*
|
|
99
|
-
* deferred
|
|
100
|
-
* sync-group
|
|
101
|
-
* whether to debounce
|
|
94
|
+
* Performs per-delta bookkeeping and enqueues the delta. Returns `true` when
|
|
95
|
+
* the delta was pushed onto `pendingDeltas` — a regular batchable insert,
|
|
96
|
+
* update, covering, or delete that a later flush must drain — and `false` when
|
|
97
|
+
* it was skipped as a duplicate, deferred into the bootstrap queue, or handled
|
|
98
|
+
* immediately (a 'G'/'S' sync-group change). It does not schedule the flush
|
|
99
|
+
* itself; the caller chooses whether to debounce live traffic or flush a
|
|
100
|
+
* catch-up frame atomically.
|
|
102
101
|
*/
|
|
103
102
|
export declare function enqueueDelta(ctx: DeltaPipelineContext, delta: SyncDelta, options?: {
|
|
104
103
|
authoritative?: boolean;
|
|
105
104
|
}): boolean;
|
|
106
105
|
/** Debounce a flush for live single-delta traffic. */
|
|
107
106
|
export declare function scheduleDeltaFlush(ctx: DeltaPipelineContext): void;
|
|
108
|
-
/**
|
|
109
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Flushes the queued deltas: deduplicates them, applies custom-entity deltas
|
|
109
|
+
* straight to the pool, writes the rest to the local store and then the pool,
|
|
110
|
+
* and advances the acknowledgement cursor once the store write has committed.
|
|
111
|
+
*/
|
|
110
112
|
export declare function flushPendingDeltas(ctx: DeltaPipelineContext): Promise<void>;
|
|
111
113
|
export {};
|