@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,36 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Detects real network and session connectivity for the sync engine. It exists
|
|
3
|
+
* because `navigator.onLine` is unreliable: it reports true whenever the device
|
|
4
|
+
* has a local network connection, even with no route to the internet, and after
|
|
5
|
+
* sleep/wake it can report true before Wi-Fi or DNS are working again.
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* This module provides an authenticated probe against the sync server to verify
|
|
9
|
-
* real connectivity + credential validity in a single round-trip. The probe
|
|
10
|
-
* hits `/api/auth/check`, which runs the SAME auth middleware as the WebSocket
|
|
11
|
-
* upgrade path, and classifies the response into a single {@link ProbeOutcome}
|
|
12
|
-
* via the closed recovery taxonomy ({@link classifyRecovery}):
|
|
7
|
+
* The probe makes one authenticated request to the sync server's
|
|
8
|
+
* `/api/auth/check` endpoint — which runs the same auth middleware as the
|
|
9
|
+
* WebSocket upgrade — and classifies the response into a single
|
|
10
|
+
* {@link ProbeOutcome} through the recovery taxonomy ({@link classifyRecovery}):
|
|
13
11
|
* 204 No Content → `reachable` (credential valid)
|
|
14
|
-
* 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint
|
|
12
|
+
* 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint and retry, no sign-out)
|
|
15
13
|
* 401 `session_expired` / bare 401 → `session_expired` (sign out)
|
|
16
|
-
* 401/403 credential-type/config/perm → `auth_blocked` (stop
|
|
17
|
-
* network
|
|
14
|
+
* 401/403 credential-type/config/perm → `auth_blocked` (stop; no loop, no sign-out)
|
|
15
|
+
* network failure / offline → `unreachable`
|
|
18
16
|
*
|
|
19
|
-
* This closes a real gap
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* the user to sign-in.
|
|
17
|
+
* This closes a real gap. The browser's WebSocket API hides the HTTP status of
|
|
18
|
+
* a failed handshake, so a 401 on the upgrade surfaces only as close code 1006.
|
|
19
|
+
* Without this HTTP probe, the client cannot tell an auth failure from a network
|
|
20
|
+
* blip, and loops reconnecting forever instead of sending the user to sign in.
|
|
24
21
|
*
|
|
25
22
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine
|
|
26
23
|
*/
|
|
27
24
|
import { z } from 'zod';
|
|
28
25
|
import { type AuthTokenGetter } from '../auth/credentialSource.js';
|
|
29
26
|
/**
|
|
30
|
-
* The
|
|
31
|
-
* credential
|
|
32
|
-
*
|
|
33
|
-
*
|
|
27
|
+
* The complete set of probe outcomes. Each value carries both reachability and
|
|
28
|
+
* credential state, so {@link ConnectionManager} can branch on one exhaustive
|
|
29
|
+
* discriminant instead of piecing the situation together from several booleans.
|
|
30
|
+
* It mirrors the {@link RecoveryClass} taxonomy at the connectivity layer.
|
|
34
31
|
*/
|
|
35
32
|
export declare const PROBE_OUTCOMES: readonly ["reachable", "unreachable", "session_expired", "credential_stale", "auth_blocked"];
|
|
36
33
|
/** Zod enum derived from {@link PROBE_OUTCOMES}. */
|
|
@@ -74,13 +71,11 @@ export interface NetworkProbeOptions {
|
|
|
74
71
|
authToken?: string | null;
|
|
75
72
|
}
|
|
76
73
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* ConnectionStore can make the right state transition without guessing.
|
|
74
|
+
* Probes the sync server with a lightweight HEAD request, returning both
|
|
75
|
+
* reachability and session status in a single call so {@link ConnectionManager}
|
|
76
|
+
* can pick the right state transition without guessing.
|
|
81
77
|
*
|
|
82
|
-
* @param input The sync-server base URL (HTTP or WS scheme accepted), or
|
|
83
|
-
* options bag
|
|
84
|
-
* for backwards compatibility.
|
|
78
|
+
* @param input The sync-server base URL (an HTTP or WS scheme is accepted), or
|
|
79
|
+
* an options bag. A bare string is also accepted.
|
|
85
80
|
*/
|
|
86
81
|
export declare function probeNetwork(input?: string | NetworkProbeOptions): Promise<ProbeResult>;
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Detects real network and session connectivity for the sync engine. It exists
|
|
3
|
+
* because `navigator.onLine` is unreliable: it reports true whenever the device
|
|
4
|
+
* has a local network connection, even with no route to the internet, and after
|
|
5
|
+
* sleep/wake it can report true before Wi-Fi or DNS are working again.
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* This module provides an authenticated probe against the sync server to verify
|
|
9
|
-
* real connectivity + credential validity in a single round-trip. The probe
|
|
10
|
-
* hits `/api/auth/check`, which runs the SAME auth middleware as the WebSocket
|
|
11
|
-
* upgrade path, and classifies the response into a single {@link ProbeOutcome}
|
|
12
|
-
* via the closed recovery taxonomy ({@link classifyRecovery}):
|
|
7
|
+
* The probe makes one authenticated request to the sync server's
|
|
8
|
+
* `/api/auth/check` endpoint — which runs the same auth middleware as the
|
|
9
|
+
* WebSocket upgrade — and classifies the response into a single
|
|
10
|
+
* {@link ProbeOutcome} through the recovery taxonomy ({@link classifyRecovery}):
|
|
13
11
|
* 204 No Content → `reachable` (credential valid)
|
|
14
|
-
* 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint
|
|
12
|
+
* 401 `apikey_expired` (ephemeral key) → `credential_stale` (re-mint and retry, no sign-out)
|
|
15
13
|
* 401 `session_expired` / bare 401 → `session_expired` (sign out)
|
|
16
|
-
* 401/403 credential-type/config/perm → `auth_blocked` (stop
|
|
17
|
-
* network
|
|
14
|
+
* 401/403 credential-type/config/perm → `auth_blocked` (stop; no loop, no sign-out)
|
|
15
|
+
* network failure / offline → `unreachable`
|
|
18
16
|
*
|
|
19
|
-
* This closes a real gap
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* the user to sign-in.
|
|
17
|
+
* This closes a real gap. The browser's WebSocket API hides the HTTP status of
|
|
18
|
+
* a failed handshake, so a 401 on the upgrade surfaces only as close code 1006.
|
|
19
|
+
* Without this HTTP probe, the client cannot tell an auth failure from a network
|
|
20
|
+
* blip, and loops reconnecting forever instead of sending the user to sign in.
|
|
24
21
|
*
|
|
25
22
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine
|
|
26
23
|
*/
|
|
@@ -30,24 +27,24 @@ import { classifyRecovery } from '../errors.js';
|
|
|
30
27
|
import { withAuthHeaders } from '../auth/credentialSource.js';
|
|
31
28
|
import { ABLO_DEFAULT_BASE_URL } from '../client/hostedEndpoints.js';
|
|
32
29
|
/**
|
|
33
|
-
* The
|
|
34
|
-
* credential
|
|
35
|
-
*
|
|
36
|
-
*
|
|
30
|
+
* The complete set of probe outcomes. Each value carries both reachability and
|
|
31
|
+
* credential state, so {@link ConnectionManager} can branch on one exhaustive
|
|
32
|
+
* discriminant instead of piecing the situation together from several booleans.
|
|
33
|
+
* It mirrors the {@link RecoveryClass} taxonomy at the connectivity layer.
|
|
37
34
|
*/
|
|
38
35
|
export const PROBE_OUTCOMES = [
|
|
39
36
|
/** Server reachable and the access credential is currently valid. */
|
|
40
37
|
'reachable',
|
|
41
|
-
/** Could not reach the server (offline
|
|
38
|
+
/** Could not reach the server (offline, DNS, TLS, or timeout). */
|
|
42
39
|
'unreachable',
|
|
43
|
-
/** Reachable, but the long-lived login is gone
|
|
40
|
+
/** Reachable, but the long-lived login is gone. Terminal: sign out. */
|
|
44
41
|
'session_expired',
|
|
45
|
-
/** Reachable, but the ephemeral access key (`ek_`/`rk_`) expired
|
|
46
|
-
* re-mint a fresh key from the still-valid login and retry
|
|
42
|
+
/** Reachable, but the ephemeral access key (`ek_`/`rk_`) expired. Silently
|
|
43
|
+
* re-mint a fresh key from the still-valid login and retry; not a sign-out. */
|
|
47
44
|
'credential_stale',
|
|
48
|
-
/** Reachable, but the credential
|
|
49
|
-
* untrusted issuer, no
|
|
50
|
-
* helps. Distinct from a sign-out. */
|
|
45
|
+
/** Reachable, but the credential's type or configuration was rejected (wrong
|
|
46
|
+
* key kind, untrusted issuer, no organization, or a 403). Stop: neither
|
|
47
|
+
* reconnecting nor re-authenticating helps. Distinct from a sign-out. */
|
|
51
48
|
'auth_blocked',
|
|
52
49
|
];
|
|
53
50
|
/** Zod enum derived from {@link PROBE_OUTCOMES}. */
|
|
@@ -62,13 +59,11 @@ const PROBE_TIMEOUT_MS = 4000;
|
|
|
62
59
|
/**
|
|
63
60
|
* Derive the probe URL from a sync-server base URL. Accepts `ws://`,
|
|
64
61
|
* `wss://`, `http://`, `https://`, or a bare host — mirrors the
|
|
65
|
-
* normalisation in `
|
|
62
|
+
* normalisation in `BootstrapFetcher` / `createSyncEngine`.
|
|
66
63
|
*/
|
|
67
64
|
function resolveProbeUrl(baseUrl) {
|
|
68
65
|
// No explicit baseUrl → probe the canonical hosted endpoint, matching the
|
|
69
|
-
// `Ablo()` default.
|
|
70
|
-
// `NEXT_PUBLIC_GO_SERVER_URL` and then `http://localhost:8080`, so a probe
|
|
71
|
-
// without a baseUrl reported a healthy production deployment as offline.)
|
|
66
|
+
// `Ablo()` default.
|
|
72
67
|
const resolved = baseUrl ?? ABLO_DEFAULT_BASE_URL;
|
|
73
68
|
// Normalize ws → http so fetch() accepts the URL. Strip any trailing slash
|
|
74
69
|
// so we don't produce `//api/auth/check`.
|
|
@@ -76,25 +71,23 @@ function resolveProbeUrl(baseUrl) {
|
|
|
76
71
|
return `${httpBase}/api/auth/check`;
|
|
77
72
|
}
|
|
78
73
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* ConnectionStore can make the right state transition without guessing.
|
|
74
|
+
* Probes the sync server with a lightweight HEAD request, returning both
|
|
75
|
+
* reachability and session status in a single call so {@link ConnectionManager}
|
|
76
|
+
* can pick the right state transition without guessing.
|
|
83
77
|
*
|
|
84
|
-
* @param input The sync-server base URL (HTTP or WS scheme accepted), or
|
|
85
|
-
* options bag
|
|
86
|
-
* for backwards compatibility.
|
|
78
|
+
* @param input The sync-server base URL (an HTTP or WS scheme is accepted), or
|
|
79
|
+
* an options bag. A bare string is also accepted.
|
|
87
80
|
*/
|
|
88
81
|
export async function probeNetwork(input) {
|
|
89
82
|
const baseUrl = typeof input === 'string' ? input : input?.baseUrl;
|
|
90
83
|
const getAuthToken = typeof input === 'string' ? undefined : input?.getAuthToken;
|
|
91
84
|
const authToken = typeof input === 'string' ? undefined : input?.authToken;
|
|
92
85
|
const url = resolveProbeUrl(baseUrl);
|
|
93
|
-
// Fast-fail: if navigator.onLine is false, skip the probe entirely.
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
86
|
+
// Fast-fail: if navigator.onLine is false, skip the probe entirely. This is
|
|
87
|
+
// the one case where navigator.onLine is reliable (MDN: "false means
|
|
88
|
+
// definitely offline"). Use `=== false` rather than `!onLine` because Node
|
|
89
|
+
// 22+ exposes `navigator` with `onLine === undefined`, and `!undefined` is
|
|
90
|
+
// true, which would short-circuit the probe server-side.
|
|
98
91
|
if (typeof navigator !== 'undefined' && navigator.onLine === false) {
|
|
99
92
|
return { outcome: 'unreachable', latencyMs: null };
|
|
100
93
|
}
|
|
@@ -110,13 +103,13 @@ export async function probeNetwork(input) {
|
|
|
110
103
|
headers,
|
|
111
104
|
});
|
|
112
105
|
const latencyMs = Math.round(performance.now() - start);
|
|
113
|
-
// The probe is a HEAD (no body), but the
|
|
114
|
-
// <code>` on every auth rejection. Route the code through
|
|
115
|
-
// recovery taxonomy so each failure mode gets its correct outcome
|
|
116
|
-
//
|
|
117
|
-
// (`access_credential_expiry`) must re-mint,
|
|
118
|
-
//
|
|
119
|
-
// credential
|
|
106
|
+
// The probe is a HEAD request (no body), but the server sets
|
|
107
|
+
// `X-Auth-Failure: <code>` on every auth rejection. Route the code through
|
|
108
|
+
// the recovery taxonomy so each failure mode gets its correct outcome. That
|
|
109
|
+
// distinction is the whole point: an expired ephemeral key
|
|
110
|
+
// (`access_credential_expiry`) must re-mint, not sign the user out the way a
|
|
111
|
+
// genuine login expiry (`session_expiry`) does, and not wedge the way a
|
|
112
|
+
// credential type or configuration rejection (`auth_blocked`) does.
|
|
120
113
|
const authFailure = response.headers.get('x-auth-failure');
|
|
121
114
|
if (authFailure) {
|
|
122
115
|
const recovery = classifyRecovery(authFailure);
|
|
@@ -138,10 +131,11 @@ export async function probeNetwork(input) {
|
|
|
138
131
|
case 'auth_blocked':
|
|
139
132
|
case 'permission':
|
|
140
133
|
case 'none':
|
|
141
|
-
// A non-expiry auth rejection — wrong credential type
|
|
142
|
-
// or an auth-tagged code this SDK
|
|
143
|
-
// the same rejected credential and
|
|
144
|
-
// rather than reconnect-loop or sign
|
|
134
|
+
// A non-expiry auth rejection — wrong credential type or config, a
|
|
135
|
+
// 403, or an auth-tagged code this SDK does not recognise.
|
|
136
|
+
// Re-authenticating re-mints the same rejected credential and
|
|
137
|
+
// retrying will not help, so stop rather than reconnect-loop or sign
|
|
138
|
+
// the user out.
|
|
145
139
|
getContext().logger.debug('[NetworkProbe] Reachable but auth-blocked (non-retryable, non-expiry)', {
|
|
146
140
|
status: response.status,
|
|
147
141
|
code: authFailure,
|
|
@@ -160,20 +154,20 @@ export async function probeNetwork(input) {
|
|
|
160
154
|
}
|
|
161
155
|
}
|
|
162
156
|
else if (response.status === 401) {
|
|
163
|
-
// Bare 401 with no
|
|
164
|
-
//
|
|
157
|
+
// Bare 401 with no readable structured code. This is ambiguous and must
|
|
158
|
+
// not sign the user out on its own — two common causes are both
|
|
165
159
|
// recoverable, and only one is a real logout:
|
|
166
|
-
// 1. The server
|
|
167
|
-
// custom header on a cross-origin response
|
|
168
|
-
//
|
|
169
|
-
// null
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
160
|
+
// 1. The server did send `X-Auth-Failure: apikey_expired`, but it is a
|
|
161
|
+
// custom header on a cross-origin response the server did not list in
|
|
162
|
+
// `Access-Control-Expose-Headers`, so the browser stripped it to
|
|
163
|
+
// null. The access key just needs a re-mint.
|
|
164
|
+
// 2. A genuinely expired access key on a non-Ablo proxy or cookie path.
|
|
165
|
+
// So route to `credential_stale`: the state machine attempts a re-mint,
|
|
166
|
+
// and the only way to actually sign out is that re-mint resolving `null`
|
|
167
|
+
// (the login is truly gone). If no refresher is wired, the bounded attempt
|
|
168
|
+
// counter falls through to `auth_blocked` (stop) — still never a spurious
|
|
169
|
+
// logout. The invariant holds: null is the only terminal path, never a
|
|
170
|
+
// bare 401.
|
|
177
171
|
getContext().logger.info('[NetworkProbe] Server reachable, bare 401 — re-mint (not sign-out)', {
|
|
178
172
|
latencyMs,
|
|
179
173
|
});
|
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Loads model rows on demand — the lazy-load path of the sync engine. When
|
|
3
|
+
* something needs an entity that the initial bootstrap did not fetch,
|
|
4
|
+
* {@link OnDemandLoader.fetch | fetch} finds it and populates the
|
|
5
|
+
* in-memory {@link InstanceCache} so the rest of the engine can read it normally.
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* A fetch resolves against three tiers in order, stopping at the first that can
|
|
8
|
+
* answer:
|
|
9
|
+
* 1. The object pool — if rows already in memory match the query, return them.
|
|
10
|
+
* 2. Local storage — if matching rows exist there, hydrate the pool and return.
|
|
11
|
+
* 3. The network — post the query to `/sync/query`, then hydrate both the pool
|
|
12
|
+
* and local storage.
|
|
8
13
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* 3. Network — `postQuery` against `/sync/query`, hydrate pool + IDB.
|
|
14
|
+
* Concurrent calls with the same query key share one in-flight promise, so a
|
|
15
|
+
* burst of components mounting and asking for the same data on first paint
|
|
16
|
+
* triggers a single fetch rather than one each.
|
|
13
17
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* The coordinator does NOT replace bootstrap (full sync of `instant`
|
|
19
|
-
* models) or live deltas (WS push). It only fills the gap for `lazy`
|
|
20
|
-
* models accessed by id/where after the engine is ready.
|
|
18
|
+
* The coordinator does not replace the bootstrap (which fully syncs instantly
|
|
19
|
+
* loaded models) or the live delta stream (pushed over the WebSocket). It only
|
|
20
|
+
* fills the gap for lazily loaded models read by id or filter after the engine
|
|
21
|
+
* is ready.
|
|
21
22
|
*/
|
|
22
|
-
import type {
|
|
23
|
+
import type { InstanceCache } from '../InstanceCache.js';
|
|
23
24
|
import type { Database } from '../Database.js';
|
|
24
25
|
import type { Model } from '../Model.js';
|
|
25
26
|
import type { ModelRegistry } from '../ModelRegistry.js';
|
|
26
27
|
import type { RecoveryClass } from '../errorCodes.js';
|
|
27
28
|
import type { LoadWhere, WhereClause } from '../query/types.js';
|
|
28
29
|
import type { Schema } from '../schema/schema.js';
|
|
29
|
-
export interface
|
|
30
|
-
readonly objectPool:
|
|
30
|
+
export interface OnDemandLoaderOptions {
|
|
31
|
+
readonly objectPool: InstanceCache;
|
|
31
32
|
readonly database: Database;
|
|
32
33
|
readonly registry: ModelRegistry;
|
|
33
34
|
readonly schema: Schema;
|
|
@@ -43,11 +44,11 @@ export interface HydrationCoordinatorOptions {
|
|
|
43
44
|
}
|
|
44
45
|
export interface FetchOptions<T> {
|
|
45
46
|
/**
|
|
46
|
-
* Filter clauses for the lookup. Accepts either the equality-object
|
|
47
|
-
*
|
|
48
|
-
* or the explicit tuple form (`[['name', 'ILIKE', '%
|
|
49
|
-
*
|
|
50
|
-
*
|
|
47
|
+
* Filter clauses for the lookup. Accepts either the equality-object form
|
|
48
|
+
* (`{ id: 'abc' }` becomes `WHERE id = 'abc'`, and an array value becomes an
|
|
49
|
+
* `IN`) or the explicit tuple form (`[['name', 'ILIKE', '%Acme%']]`), which
|
|
50
|
+
* mirrors the wire `WhereClause[]` exactly. Multiple entries combine with AND.
|
|
51
|
+
* See {@link LoadWhere} for the full shape.
|
|
51
52
|
*/
|
|
52
53
|
readonly where?: LoadWhere<T>;
|
|
53
54
|
readonly orderBy?: {
|
|
@@ -72,7 +73,7 @@ export interface FetchOptions<T> {
|
|
|
72
73
|
*/
|
|
73
74
|
readonly expand?: readonly string[];
|
|
74
75
|
}
|
|
75
|
-
export declare class
|
|
76
|
+
export declare class OnDemandLoader {
|
|
76
77
|
private readonly opts;
|
|
77
78
|
private readonly inFlight;
|
|
78
79
|
/**
|
|
@@ -86,9 +87,9 @@ export declare class HydrationCoordinator {
|
|
|
86
87
|
/**
|
|
87
88
|
* Query keys that have been satisfied from the server at least once this
|
|
88
89
|
* session. Once a key is here, repeat reads serve purely from the pool with
|
|
89
|
-
*
|
|
90
|
-
* re-running the HTTP query would be redundant polling. This
|
|
91
|
-
*
|
|
90
|
+
* no network round-trip: the WebSocket delta stream keeps those pool rows
|
|
91
|
+
* fresh, so re-running the HTTP query would be redundant polling. This ledger
|
|
92
|
+
* is what stops an already-open view from re-querying on every navigation.
|
|
92
93
|
*
|
|
93
94
|
* Cleared on reconnect (see {@link invalidate}) so that, after a connection
|
|
94
95
|
* drop where deltas may have been missed, the next read re-confirms once.
|
|
@@ -96,15 +97,15 @@ export declare class HydrationCoordinator {
|
|
|
96
97
|
private readonly hydratedKeys;
|
|
97
98
|
private authTokenProvider;
|
|
98
99
|
/**
|
|
99
|
-
* The
|
|
100
|
-
* late-bound like {@link setAuthTokenProvider} because the store
|
|
100
|
+
* The credential-recovery hook (the store's `recoverFromAuthRejection`),
|
|
101
|
+
* late-bound like {@link setAuthTokenProvider} because the store does not
|
|
101
102
|
* exist yet when the coordinator is constructed. Handed to `postQuery` so a
|
|
102
|
-
* 401 on the lazy lane re-mints through the
|
|
103
|
-
* probe
|
|
104
|
-
* returning empty rows against an expired key
|
|
103
|
+
* 401 on the lazy lane re-mints through the same single-flight path the
|
|
104
|
+
* WebSocket probe uses, then replays the query once — instead of silently
|
|
105
|
+
* returning empty rows against an expired key.
|
|
105
106
|
*/
|
|
106
107
|
private credentialRecovery;
|
|
107
|
-
constructor(opts:
|
|
108
|
+
constructor(opts: OnDemandLoaderOptions);
|
|
108
109
|
/**
|
|
109
110
|
* Late-bind the auth token getter. Browser cookie consumers can omit this;
|
|
110
111
|
* bearer consumers need it so lazy HTTP queries use the same credential as
|
|
@@ -144,13 +145,13 @@ export declare class HydrationCoordinator {
|
|
|
144
145
|
*/
|
|
145
146
|
private fetchFromNetwork;
|
|
146
147
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
148
|
+
* Fires the single background confirm for a query that was just served from
|
|
149
|
+
* local cache but is not hydrated yet. On success the key is marked hydrated,
|
|
150
|
+
* so every later read serves purely from local with no network until a
|
|
150
151
|
* reconnect invalidates the ledger. Deduped per query key so a render burst
|
|
151
|
-
*
|
|
152
|
-
* local snapshot, and a failed confirm leaves the key un-hydrated so the
|
|
153
|
-
*
|
|
152
|
+
* does not stampede. Errors are swallowed — the caller already has a usable
|
|
153
|
+
* local snapshot, and a failed confirm leaves the key un-hydrated so the next
|
|
154
|
+
* read simply tries again.
|
|
154
155
|
*/
|
|
155
156
|
private scheduleHydratingFetch;
|
|
156
157
|
/**
|
|
@@ -185,7 +186,7 @@ export declare class HydrationCoordinator {
|
|
|
185
186
|
* `postgres.camel` driver leaves behind when the server's SQL
|
|
186
187
|
* bakes `__typename` into a JSONB literal — the driver's
|
|
187
188
|
* snake↔camel transform misreads `__typename` as `_typename` with
|
|
188
|
-
* a leading underscore and produces `_Typename`.
|
|
189
|
+
* a leading underscore and produces `_Typename`. InstanceCache only
|
|
189
190
|
* recognises `__typename`, so without this step nested rows fall
|
|
190
191
|
* through to the 'Unknown' branch and never instantiate.
|
|
191
192
|
*/
|