@abloatai/humans 0.37.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/README.md +52 -0
- package/dist/Ablo.d.ts +208 -0
- package/dist/Ablo.js +120 -0
- package/dist/client.d.ts +317 -0
- package/dist/client.js +13 -0
- package/dist/core.d.ts +35 -0
- package/dist/core.js +48 -0
- package/dist/humans.d.ts +28 -0
- package/dist/humans.js +34 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +6 -0
- package/dist/local/BaseSyncedStore.d.ts +807 -0
- package/dist/local/BaseSyncedStore.js +1516 -0
- package/dist/local/Database.d.ts +322 -0
- package/dist/local/Database.js +1589 -0
- package/dist/local/InstanceCache.d.ts +255 -0
- package/dist/local/InstanceCache.js +1263 -0
- package/dist/local/LazyReferenceCollection.d.ts +177 -0
- package/dist/local/LazyReferenceCollection.js +461 -0
- package/dist/local/Model.d.ts +475 -0
- package/dist/local/Model.js +950 -0
- package/dist/local/ModelRegistry.d.ts +225 -0
- package/dist/local/ModelRegistry.js +539 -0
- package/dist/local/NetworkMonitor.d.ts +28 -0
- package/dist/local/NetworkMonitor.js +79 -0
- package/dist/local/RuntimeContext.d.ts +52 -0
- package/dist/local/RuntimeContext.js +80 -0
- package/dist/local/SyncClient.d.ts +516 -0
- package/dist/local/SyncClient.js +1754 -0
- package/dist/local/adapters/alwaysOnline.d.ts +14 -0
- package/dist/local/adapters/alwaysOnline.js +17 -0
- package/dist/local/adapters/inMemoryStorage.d.ts +37 -0
- package/dist/local/adapters/inMemoryStorage.js +122 -0
- package/dist/local/client/clientPrelude.d.ts +52 -0
- package/dist/local/client/clientPrelude.js +60 -0
- package/dist/local/client/consoleLogger.d.ts +35 -0
- package/dist/local/client/consoleLogger.js +44 -0
- package/dist/local/client/createInternalComponents.d.ts +50 -0
- package/dist/local/client/createInternalComponents.js +98 -0
- package/dist/local/client/createModelProxy.d.ts +248 -0
- package/dist/local/client/createModelProxy.js +880 -0
- package/dist/local/client/modelRegistration.d.ts +10 -0
- package/dist/local/client/modelRegistration.js +316 -0
- package/dist/local/client/options.d.ts +440 -0
- package/dist/local/client/options.js +7 -0
- package/dist/local/client/reactiveEngine.d.ts +53 -0
- package/dist/local/client/reactiveEngine.js +705 -0
- package/dist/local/client/resourceTypes.d.ts +12 -0
- package/dist/local/client/resourceTypes.js +10 -0
- package/dist/local/client/schemaConfig.d.ts +44 -0
- package/dist/local/client/schemaConfig.js +185 -0
- package/dist/local/client/storeCluster.d.ts +46 -0
- package/dist/local/client/storeCluster.js +133 -0
- package/dist/local/client/storeLifecycle.d.ts +61 -0
- package/dist/local/client/storeLifecycle.js +236 -0
- package/dist/local/client/validateAbloOptions.d.ts +42 -0
- package/dist/local/client/validateAbloOptions.js +43 -0
- package/dist/local/client/wsMutationExecutor.d.ts +27 -0
- package/dist/local/client/wsMutationExecutor.js +72 -0
- package/dist/local/context.d.ts +42 -0
- package/dist/local/context.js +81 -0
- package/dist/local/coordination/ClaimLog.d.ts +26 -0
- package/dist/local/coordination/ClaimLog.js +32 -0
- package/dist/local/interfaces/index.d.ts +311 -0
- package/dist/local/interfaces/index.js +9 -0
- package/dist/local/localModelContract.d.ts +14 -0
- package/dist/local/localModelContract.js +1 -0
- package/dist/local/logPosition.d.ts +31 -0
- package/dist/local/logPosition.js +53 -0
- package/dist/local/mutationPersistence.d.ts +6 -0
- package/dist/local/mutationPersistence.js +1 -0
- package/dist/local/mutators/RecordingMutation.d.ts +36 -0
- package/dist/local/mutators/RecordingMutation.js +182 -0
- package/dist/local/mutators/Transaction.d.ts +40 -0
- package/dist/local/mutators/Transaction.js +58 -0
- package/dist/local/mutators/UndoManager.d.ts +258 -0
- package/dist/local/mutators/UndoManager.js +665 -0
- package/dist/local/mutators/defineMutators.d.ts +60 -0
- package/dist/local/mutators/defineMutators.js +18 -0
- package/dist/local/mutators/inverseOp.d.ts +126 -0
- package/dist/local/mutators/inverseOp.js +71 -0
- package/dist/local/mutators/mutateActions.d.ts +45 -0
- package/dist/local/mutators/mutateActions.js +105 -0
- package/dist/local/mutators/readerActions.d.ts +33 -0
- package/dist/local/mutators/readerActions.js +57 -0
- package/dist/local/mutators/undoApply.d.ts +51 -0
- package/dist/local/mutators/undoApply.js +117 -0
- package/dist/local/persistence.d.ts +7 -0
- package/dist/local/persistence.js +9 -0
- package/dist/local/query/QueryProcessor.d.ts +75 -0
- package/dist/local/query/QueryProcessor.js +255 -0
- package/dist/local/query/client.d.ts +64 -0
- package/dist/local/query/client.js +138 -0
- package/dist/local/query/types.d.ts +85 -0
- package/dist/local/query/types.js +16 -0
- package/dist/local/schema/serialize.d.ts +1 -0
- package/dist/local/schema/serialize.js +1 -0
- package/dist/local/store/queryApi.d.ts +13 -0
- package/dist/local/store/queryApi.js +35 -0
- package/dist/local/storeContract.d.ts +145 -0
- package/dist/local/storeContract.js +12 -0
- package/dist/local/stores/DatabaseManager.d.ts +112 -0
- package/dist/local/stores/DatabaseManager.js +400 -0
- package/dist/local/stores/ObjectStore.d.ts +115 -0
- package/dist/local/stores/ObjectStore.js +393 -0
- package/dist/local/stores/ObjectStoreContract.d.ts +38 -0
- package/dist/local/stores/ObjectStoreContract.js +1 -0
- package/dist/local/stores/StoreManager.d.ts +114 -0
- package/dist/local/stores/StoreManager.js +304 -0
- package/dist/local/stores/SyncActionStore.d.ts +99 -0
- package/dist/local/stores/SyncActionStore.js +506 -0
- package/dist/local/stores/openIDBWithTimeout.d.ts +65 -0
- package/dist/local/stores/openIDBWithTimeout.js +153 -0
- package/dist/local/stores/persistenceCleanup.d.ts +7 -0
- package/dist/local/stores/persistenceCleanup.js +26 -0
- package/dist/local/stores/persistenceIdentity.d.ts +27 -0
- package/dist/local/stores/persistenceIdentity.js +38 -0
- package/dist/local/stores/syncAction.d.ts +26 -0
- package/dist/local/stores/syncAction.js +16 -0
- package/dist/local/stores/v1PersistenceDeletion.d.ts +8 -0
- package/dist/local/stores/v1PersistenceDeletion.js +16 -0
- package/dist/local/sync/BootstrapFetcher.d.ts +284 -0
- package/dist/local/sync/BootstrapFetcher.js +964 -0
- package/dist/local/sync/ConnectionManager.d.ts +8 -0
- package/dist/local/sync/ConnectionManager.js +8 -0
- package/dist/local/sync/OnDemandLoader.d.ts +231 -0
- package/dist/local/sync/OnDemandLoader.js +743 -0
- package/dist/local/sync/SubscriptionManager.d.ts +159 -0
- package/dist/local/sync/SubscriptionManager.js +243 -0
- package/dist/local/sync/SyncWebSocket.d.ts +173 -0
- package/dist/local/sync/SyncWebSocket.js +438 -0
- package/dist/local/sync/bootstrapApply.d.ts +73 -0
- package/dist/local/sync/bootstrapApply.js +73 -0
- package/dist/local/sync/commitFrames.d.ts +8 -0
- package/dist/local/sync/commitFrames.js +8 -0
- package/dist/local/sync/connectionManagerLifecycle.d.ts +23 -0
- package/dist/local/sync/connectionManagerLifecycle.js +126 -0
- package/dist/local/sync/contextPorts.d.ts +18 -0
- package/dist/local/sync/contextPorts.js +31 -0
- package/dist/local/sync/createClaimStream.d.ts +64 -0
- package/dist/local/sync/createClaimStream.js +475 -0
- package/dist/local/sync/createSnapshot.d.ts +29 -0
- package/dist/local/sync/createSnapshot.js +116 -0
- package/dist/local/sync/credentialLifecycle.d.ts +7 -0
- package/dist/local/sync/credentialLifecycle.js +7 -0
- package/dist/local/sync/deltaPipeline.d.ts +116 -0
- package/dist/local/sync/deltaPipeline.js +357 -0
- package/dist/local/sync/groupChange.d.ts +116 -0
- package/dist/local/sync/groupChange.js +244 -0
- package/dist/local/sync/initialize.d.ts +27 -0
- package/dist/local/sync/initialize.js +137 -0
- package/dist/local/sync/participants.d.ts +132 -0
- package/dist/local/sync/participants.js +342 -0
- package/dist/local/sync/persistedPrefix.d.ts +12 -0
- package/dist/local/sync/persistedPrefix.js +22 -0
- package/dist/local/sync/reconnect.d.ts +23 -0
- package/dist/local/sync/reconnect.js +55 -0
- package/dist/local/sync/schemaDrift.d.ts +55 -0
- package/dist/local/sync/schemaDrift.js +53 -0
- package/dist/local/sync/schemas.d.ts +71 -0
- package/dist/local/sync/schemas.js +94 -0
- package/dist/local/sync/socketEventWiring.d.ts +31 -0
- package/dist/local/sync/socketEventWiring.js +130 -0
- package/dist/local/sync/syncCursor.d.ts +40 -0
- package/dist/local/sync/syncCursor.js +55 -0
- package/dist/local/sync/syncPlan.d.ts +54 -0
- package/dist/local/sync/syncPlan.js +50 -0
- package/dist/local/sync/terminalSessionLifecycle.d.ts +20 -0
- package/dist/local/sync/terminalSessionLifecycle.js +50 -0
- package/dist/local/sync/wsFrameHandlers.d.ts +8 -0
- package/dist/local/sync/wsFrameHandlers.js +8 -0
- package/dist/local/transactions/databaseCommitOutbox.d.ts +15 -0
- package/dist/local/transactions/databaseCommitOutbox.js +16 -0
- package/dist/local/transactions/localMutation.d.ts +10 -0
- package/dist/local/transactions/localMutation.js +37 -0
- package/dist/local/transactions/mutations/MutationQueue.d.ts +511 -0
- package/dist/local/transactions/mutations/MutationQueue.js +1498 -0
- package/dist/local/transactions/mutations/MutationStore.d.ts +20 -0
- package/dist/local/transactions/mutations/MutationStore.js +53 -0
- package/dist/local/transactions/mutations/UnconfirmedWrites.d.ts +82 -0
- package/dist/local/transactions/mutations/UnconfirmedWrites.js +104 -0
- package/dist/local/transactions/mutations/batchProcessing.d.ts +64 -0
- package/dist/local/transactions/mutations/batchProcessing.js +349 -0
- package/dist/local/transactions/mutations/coalesceRules.d.ts +58 -0
- package/dist/local/transactions/mutations/coalesceRules.js +140 -0
- package/dist/local/transactions/mutations/commitApi.d.ts +19 -0
- package/dist/local/transactions/mutations/commitApi.js +74 -0
- package/dist/local/transactions/mutations/commitLane.d.ts +70 -0
- package/dist/local/transactions/mutations/commitLane.js +140 -0
- package/dist/local/transactions/mutations/commitLatency.d.ts +52 -0
- package/dist/local/transactions/mutations/commitLatency.js +130 -0
- package/dist/local/transactions/mutations/commitPayload.d.ts +165 -0
- package/dist/local/transactions/mutations/commitPayload.js +152 -0
- package/dist/local/transactions/mutations/commitTransport.d.ts +36 -0
- package/dist/local/transactions/mutations/commitTransport.js +104 -0
- package/dist/local/transactions/mutations/deltaConfirmation.d.ts +63 -0
- package/dist/local/transactions/mutations/deltaConfirmation.js +235 -0
- package/dist/local/transactions/mutations/durableCommitRestore.d.ts +17 -0
- package/dist/local/transactions/mutations/durableCommitRestore.js +95 -0
- package/dist/local/transactions/mutations/durableWriteStore.d.ts +14 -0
- package/dist/local/transactions/mutations/durableWriteStore.js +12 -0
- package/dist/local/transactions/mutations/executionSelection.d.ts +6 -0
- package/dist/local/transactions/mutations/executionSelection.js +42 -0
- package/dist/local/transactions/mutations/failureHandling.d.ts +16 -0
- package/dist/local/transactions/mutations/failureHandling.js +130 -0
- package/dist/local/transactions/mutations/failurePolicy.d.ts +13 -0
- package/dist/local/transactions/mutations/failurePolicy.js +48 -0
- package/dist/local/transactions/mutations/localMutation.d.ts +58 -0
- package/dist/local/transactions/mutations/localMutation.js +75 -0
- package/dist/local/transactions/mutations/modelOperations.d.ts +44 -0
- package/dist/local/transactions/mutations/modelOperations.js +144 -0
- package/dist/local/transactions/mutations/mutationPersistence.d.ts +25 -0
- package/dist/local/transactions/mutations/mutationPersistence.js +188 -0
- package/dist/local/transactions/mutations/pendingDrain.d.ts +33 -0
- package/dist/local/transactions/mutations/pendingDrain.js +112 -0
- package/dist/local/transactions/mutations/processingScheduler.d.ts +14 -0
- package/dist/local/transactions/mutations/processingScheduler.js +24 -0
- package/dist/local/transactions/mutations/queueCoalescing.d.ts +13 -0
- package/dist/local/transactions/mutations/queueCoalescing.js +35 -0
- package/dist/local/transactions/mutations/replayValidation.d.ts +187 -0
- package/dist/local/transactions/mutations/replayValidation.js +164 -0
- package/dist/local/transactions/reconnectDrain.d.ts +11 -0
- package/dist/local/transactions/reconnectDrain.js +13 -0
- package/dist/local/utils/mobxSetup.d.ts +53 -0
- package/dist/local/utils/mobxSetup.js +330 -0
- package/dist/local/views/QueryView.d.ts +79 -0
- package/dist/local/views/QueryView.js +218 -0
- package/dist/local/views/ViewRegistry.d.ts +20 -0
- package/dist/local/views/ViewRegistry.js +57 -0
- package/dist/local/views/incrementalView.d.ts +45 -0
- package/dist/local/views/incrementalView.js +69 -0
- package/dist/plugin.d.ts +285 -0
- package/dist/plugin.js +106 -0
- package/dist/presenceStream.d.ts +69 -0
- package/dist/presenceStream.js +200 -0
- package/dist/react/AbloProvider.d.ts +242 -0
- package/dist/react/AbloProvider.js +456 -0
- package/dist/react/ClientSideSuspense.d.ts +36 -0
- package/dist/react/ClientSideSuspense.js +17 -0
- package/dist/react/DefaultFallback.d.ts +24 -0
- package/dist/react/DefaultFallback.js +43 -0
- package/dist/react/context.d.ts +55 -0
- package/dist/react/context.js +29 -0
- package/dist/react/createAbloReact.d.ts +50 -0
- package/dist/react/createAbloReact.js +48 -0
- package/dist/react/internalContext.d.ts +33 -0
- package/dist/react/internalContext.js +3 -0
- package/dist/react/useAblo.d.ts +96 -0
- package/dist/react/useAblo.js +120 -0
- package/dist/react/useCurrentUserId.d.ts +2 -0
- package/dist/react/useCurrentUserId.js +12 -0
- package/dist/react/useErrorListener.d.ts +2 -0
- package/dist/react/useErrorListener.js +14 -0
- package/dist/react/useMutationFailureListener.d.ts +8 -0
- package/dist/react/useMutationFailureListener.js +19 -0
- package/dist/react/useMutators.d.ts +56 -0
- package/dist/react/useMutators.js +84 -0
- package/dist/react/useSyncStatus.d.ts +19 -0
- package/dist/react/useSyncStatus.js +37 -0
- package/dist/react/useUndoScope.d.ts +34 -0
- package/dist/react/useUndoScope.js +73 -0
- package/dist/react.d.ts +18 -0
- package/dist/react.js +14 -0
- package/dist/reactRuntime.d.ts +4 -0
- package/dist/reactRuntime.js +2 -0
- package/dist/surface.d.ts +36 -0
- package/dist/surface.js +77 -0
- package/dist/useReactive.d.ts +6 -0
- package/dist/useReactive.js +43 -0
- package/package.json +119 -0
- package/src/Ablo.ts +456 -0
- package/src/client.ts +374 -0
- package/src/core.ts +104 -0
- package/src/humans.ts +61 -0
- package/src/index.ts +40 -0
- package/src/local/BaseSyncedStore.ts +1991 -0
- package/src/local/Database.ts +2052 -0
- package/src/local/InstanceCache.ts +1503 -0
- package/src/local/LazyReferenceCollection.ts +563 -0
- package/src/local/Model.ts +1124 -0
- package/src/local/ModelRegistry.ts +762 -0
- package/src/local/NetworkMonitor.ts +88 -0
- package/src/local/RuntimeContext.ts +141 -0
- package/src/local/SyncClient.ts +2131 -0
- package/src/local/adapters/alwaysOnline.ts +20 -0
- package/src/local/adapters/inMemoryStorage.ts +141 -0
- package/src/local/client/clientPrelude.ts +112 -0
- package/src/local/client/consoleLogger.ts +60 -0
- package/src/local/client/createInternalComponents.ts +163 -0
- package/src/local/client/createModelProxy.ts +1390 -0
- package/src/local/client/modelRegistration.ts +350 -0
- package/src/local/client/options.ts +526 -0
- package/src/local/client/reactiveEngine.ts +935 -0
- package/src/local/client/resourceTypes.ts +37 -0
- package/src/local/client/schemaConfig.ts +194 -0
- package/src/local/client/storeCluster.ts +172 -0
- package/src/local/client/storeLifecycle.ts +343 -0
- package/src/local/client/validateAbloOptions.ts +95 -0
- package/src/local/client/wsMutationExecutor.ts +110 -0
- package/src/local/context.ts +96 -0
- package/src/local/coordination/ClaimLog.ts +39 -0
- package/src/local/interfaces/index.ts +468 -0
- package/src/local/localModelContract.ts +15 -0
- package/src/local/logPosition.ts +84 -0
- package/src/local/mutationPersistence.ts +7 -0
- package/src/local/mutators/RecordingMutation.ts +222 -0
- package/src/local/mutators/Transaction.ts +97 -0
- package/src/local/mutators/UndoManager.ts +741 -0
- package/src/local/mutators/defineMutators.ts +76 -0
- package/src/local/mutators/inverseOp.ts +83 -0
- package/src/local/mutators/mutateActions.ts +167 -0
- package/src/local/mutators/readerActions.ts +99 -0
- package/src/local/mutators/undoApply.ts +141 -0
- package/src/local/persistence.ts +16 -0
- package/src/local/query/QueryProcessor.ts +347 -0
- package/src/local/query/client.ts +197 -0
- package/src/local/query/types.ts +102 -0
- package/src/local/schema/serialize.ts +1 -0
- package/src/local/store/queryApi.ts +56 -0
- package/src/local/storeContract.ts +146 -0
- package/src/local/stores/DatabaseManager.ts +507 -0
- package/src/local/stores/ObjectStore.ts +449 -0
- package/src/local/stores/ObjectStoreContract.ts +48 -0
- package/src/local/stores/StoreManager.ts +388 -0
- package/src/local/stores/SyncActionStore.ts +579 -0
- package/src/local/stores/openIDBWithTimeout.ts +195 -0
- package/src/local/stores/persistenceCleanup.ts +43 -0
- package/src/local/stores/persistenceIdentity.ts +83 -0
- package/src/local/stores/syncAction.ts +21 -0
- package/src/local/stores/v1PersistenceDeletion.ts +21 -0
- package/src/local/sync/BootstrapFetcher.ts +1224 -0
- package/src/local/sync/ConnectionManager.ts +15 -0
- package/src/local/sync/OnDemandLoader.ts +927 -0
- package/src/local/sync/SubscriptionManager.ts +300 -0
- package/src/local/sync/SyncWebSocket.ts +584 -0
- package/src/local/sync/bootstrapApply.ts +130 -0
- package/src/local/sync/commitFrames.ts +16 -0
- package/src/local/sync/connectionManagerLifecycle.ts +158 -0
- package/src/local/sync/contextPorts.ts +37 -0
- package/src/local/sync/createClaimStream.ts +668 -0
- package/src/local/sync/createSnapshot.ts +160 -0
- package/src/local/sync/credentialLifecycle.ts +18 -0
- package/src/local/sync/deltaPipeline.ts +473 -0
- package/src/local/sync/groupChange.ts +343 -0
- package/src/local/sync/initialize.ts +205 -0
- package/src/local/sync/participants.ts +564 -0
- package/src/local/sync/persistedPrefix.ts +27 -0
- package/src/local/sync/reconnect.ts +88 -0
- package/src/local/sync/schemaDrift.ts +86 -0
- package/src/local/sync/schemas.ts +118 -0
- package/src/local/sync/socketEventWiring.ts +196 -0
- package/src/local/sync/syncCursor.ts +62 -0
- package/src/local/sync/syncPlan.ts +89 -0
- package/src/local/sync/terminalSessionLifecycle.ts +66 -0
- package/src/local/sync/wsFrameHandlers.ts +20 -0
- package/src/local/transactions/databaseCommitOutbox.ts +33 -0
- package/src/local/transactions/localMutation.ts +58 -0
- package/src/local/transactions/mutations/MutationQueue.ts +1998 -0
- package/src/local/transactions/mutations/MutationStore.ts +65 -0
- package/src/local/transactions/mutations/UnconfirmedWrites.ts +133 -0
- package/src/local/transactions/mutations/batchProcessing.ts +469 -0
- package/src/local/transactions/mutations/coalesceRules.ts +192 -0
- package/src/local/transactions/mutations/commitApi.ts +97 -0
- package/src/local/transactions/mutations/commitLane.ts +191 -0
- package/src/local/transactions/mutations/commitLatency.ts +164 -0
- package/src/local/transactions/mutations/commitPayload.ts +281 -0
- package/src/local/transactions/mutations/commitTransport.ts +174 -0
- package/src/local/transactions/mutations/deltaConfirmation.ts +298 -0
- package/src/local/transactions/mutations/durableCommitRestore.ts +128 -0
- package/src/local/transactions/mutations/durableWriteStore.ts +21 -0
- package/src/local/transactions/mutations/executionSelection.ts +42 -0
- package/src/local/transactions/mutations/failureHandling.ts +154 -0
- package/src/local/transactions/mutations/failurePolicy.ts +61 -0
- package/src/local/transactions/mutations/localMutation.ts +135 -0
- package/src/local/transactions/mutations/modelOperations.ts +210 -0
- package/src/local/transactions/mutations/mutationPersistence.ts +231 -0
- package/src/local/transactions/mutations/pendingDrain.ts +160 -0
- package/src/local/transactions/mutations/processingScheduler.ts +35 -0
- package/src/local/transactions/mutations/queueCoalescing.ts +45 -0
- package/src/local/transactions/mutations/replayValidation.ts +192 -0
- package/src/local/transactions/reconnectDrain.ts +24 -0
- package/src/local/utils/mobxSetup.ts +388 -0
- package/src/local/views/QueryView.ts +311 -0
- package/src/local/views/ViewRegistry.ts +61 -0
- package/src/local/views/incrementalView.ts +92 -0
- package/src/plugin.ts +396 -0
- package/src/presenceStream.ts +279 -0
- package/src/react/AbloProvider.tsx +744 -0
- package/src/react/ClientSideSuspense.tsx +57 -0
- package/src/react/DefaultFallback.tsx +60 -0
- package/src/react/context.ts +89 -0
- package/src/react/createAbloReact.ts +116 -0
- package/src/react/internalContext.ts +38 -0
- package/src/react/useAblo.ts +280 -0
- package/src/react/useCurrentUserId.ts +17 -0
- package/src/react/useErrorListener.ts +22 -0
- package/src/react/useMutationFailureListener.ts +34 -0
- package/src/react/useMutators.ts +184 -0
- package/src/react/useSyncStatus.ts +42 -0
- package/src/react/useUndoScope.ts +143 -0
- package/src/react.ts +69 -0
- package/src/reactRuntime.ts +10 -0
- package/src/surface.ts +106 -0
- package/src/useReactive.ts +51 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decides which sync groups a connection subscribes to as the user navigates,
|
|
3
|
+
* and pushes each change through the {@link SubscriptionTransport}'s
|
|
4
|
+
* `update_subscription` call. It smooths two kinds of churn so that opening and
|
|
5
|
+
* closing entities does not turn into a storm of subscription changes.
|
|
6
|
+
*
|
|
7
|
+
* The first is hysteresis. Calling {@link SubscriptionManager.leave | leave}
|
|
8
|
+
* on a group does not unsubscribe it right away; the group stays subscribed for
|
|
9
|
+
* a grace period — its warm window — and drops only once that window lapses.
|
|
10
|
+
* Re-entering within the window costs nothing, since the group was never
|
|
11
|
+
* dropped, so rapid back-and-forth navigation becomes a cache hit rather than a
|
|
12
|
+
* repeated bootstrap.
|
|
13
|
+
*
|
|
14
|
+
* The second is prominence. A group that holds an active write claim is pinned
|
|
15
|
+
* (see {@link SubscriptionManager.pin | pin}) and stays subscribed regardless
|
|
16
|
+
* of navigation, so a row someone is actively editing never loses its live
|
|
17
|
+
* updates. The `baseGroups` are permanent scopes that are always subscribed.
|
|
18
|
+
*
|
|
19
|
+
* The manager recomputes the full desired set on every change, diffs it against
|
|
20
|
+
* the set the transport last confirmed, and calls `update_subscription` only
|
|
21
|
+
* when the set actually changes — so the smoothing suppresses network traffic
|
|
22
|
+
* rather than merely deferring it. It depends only on
|
|
23
|
+
* {@link SubscriptionTransport}, which {@link SyncWebSocket} satisfies. The
|
|
24
|
+
* clock and the sweep timer are injectable so the policy is deterministic under
|
|
25
|
+
* test.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** The single capability this manager needs from the connection. */
|
|
29
|
+
export interface SubscriptionTransport {
|
|
30
|
+
/**
|
|
31
|
+
* Replaces the connection's read interest with the complete group set. This
|
|
32
|
+
* is a full replace, not an incremental add or remove. Resolves with the
|
|
33
|
+
* effective set the server applied, which the manager treats as authoritative
|
|
34
|
+
* for its next diff.
|
|
35
|
+
*/
|
|
36
|
+
updateSubscription(
|
|
37
|
+
syncGroups: readonly string[],
|
|
38
|
+
): Promise<{ syncGroups: string[] }>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SubscriptionManagerOptions {
|
|
42
|
+
/** Connection to drive. `SyncWebSocket` satisfies this structurally. */
|
|
43
|
+
transport: SubscriptionTransport;
|
|
44
|
+
/**
|
|
45
|
+
* Groups always present in the effective set (e.g. `org:<id>`,
|
|
46
|
+
* `user:<id>`). Never warm, never expired.
|
|
47
|
+
*/
|
|
48
|
+
baseGroups?: readonly string[];
|
|
49
|
+
/**
|
|
50
|
+
* How long a `leave`-ed group stays subscribed before it actually drops.
|
|
51
|
+
* This is the hysteresis margin. Default 30s.
|
|
52
|
+
*/
|
|
53
|
+
warmTtlMs?: number;
|
|
54
|
+
/**
|
|
55
|
+
* The maximum number of warm (left but still subscribed) groups. Under heavy
|
|
56
|
+
* navigation, warm groups would otherwise pile up until each one's window
|
|
57
|
+
* lapses, inflating the connection's subscription set. When the cap is
|
|
58
|
+
* exceeded, the least-recently-warmed group is dropped immediately instead of
|
|
59
|
+
* waiting for its window. Default 16.
|
|
60
|
+
*/
|
|
61
|
+
maxWarm?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Auto-run the warm-expiry sweep on this cadence. Set `0` to disable and
|
|
64
|
+
* drive {@link SubscriptionManager.sweep} yourself (tests do this).
|
|
65
|
+
* Default = `warmTtlMs` (checks about once per margin).
|
|
66
|
+
*/
|
|
67
|
+
sweepIntervalMs?: number;
|
|
68
|
+
/** Clock injection point for deterministic tests. Default `Date.now`. */
|
|
69
|
+
now?: () => number;
|
|
70
|
+
/**
|
|
71
|
+
* Schedule a periodic callback. Default wraps `setInterval`/
|
|
72
|
+
* `clearInterval`. Injected so tests avoid real timers.
|
|
73
|
+
*/
|
|
74
|
+
scheduler?: (fn: () => void, intervalMs: number) => () => void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function setsEqual(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean {
|
|
78
|
+
if (a.size !== b.size) return false;
|
|
79
|
+
for (const v of a) if (!b.has(v)) return false;
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class SubscriptionManager {
|
|
84
|
+
private readonly transport: SubscriptionTransport;
|
|
85
|
+
private baseGroups: ReadonlySet<string>;
|
|
86
|
+
private readonly warmTtlMs: number;
|
|
87
|
+
private readonly maxWarm: number;
|
|
88
|
+
private readonly now: () => number;
|
|
89
|
+
|
|
90
|
+
/** Groups currently in view (open entities). */
|
|
91
|
+
private readonly active = new Set<string>();
|
|
92
|
+
/** Claim-pinned groups — prominence; never warm/expire while pinned. */
|
|
93
|
+
private readonly pinned = new Set<string>();
|
|
94
|
+
/** Left-but-warm groups → epoch-ms at which they drop. */
|
|
95
|
+
private readonly warm = new Map<string, number>();
|
|
96
|
+
|
|
97
|
+
/** Last set the transport confirmed — the diff baseline. */
|
|
98
|
+
private lastSent = new Set<string>();
|
|
99
|
+
|
|
100
|
+
/** Coalescing state so concurrent mutations collapse into one in-flight call. */
|
|
101
|
+
private inFlight: Promise<void> | null = null;
|
|
102
|
+
private dirty = false;
|
|
103
|
+
|
|
104
|
+
/** Arms the sweep timer; `null` when sweeping is disabled. The timer is
|
|
105
|
+
* armed lazily, on the first warm entry — sweeping exists only to expire
|
|
106
|
+
* warm groups, so a manager that never warms one holds no timer (and a
|
|
107
|
+
* client that is constructed but never navigates holds none either). */
|
|
108
|
+
private readonly armSweep: (() => void) | null;
|
|
109
|
+
private cancelSweep: (() => void) | null = null;
|
|
110
|
+
|
|
111
|
+
constructor(options: SubscriptionManagerOptions) {
|
|
112
|
+
this.transport = options.transport;
|
|
113
|
+
this.baseGroups = new Set(options.baseGroups ?? []);
|
|
114
|
+
this.warmTtlMs = options.warmTtlMs ?? 30_000;
|
|
115
|
+
this.maxWarm = options.maxWarm ?? 16;
|
|
116
|
+
this.now = options.now ?? (() => Date.now());
|
|
117
|
+
|
|
118
|
+
const sweepInterval = options.sweepIntervalMs ?? this.warmTtlMs;
|
|
119
|
+
if (sweepInterval > 0) {
|
|
120
|
+
const schedule =
|
|
121
|
+
options.scheduler ??
|
|
122
|
+
((fn, ms) => {
|
|
123
|
+
const handle = setInterval(fn, ms);
|
|
124
|
+
return () => { clearInterval(handle); };
|
|
125
|
+
});
|
|
126
|
+
this.armSweep = () => {
|
|
127
|
+
this.cancelSweep = schedule(() => {
|
|
128
|
+
void this.sweep();
|
|
129
|
+
}, sweepInterval);
|
|
130
|
+
};
|
|
131
|
+
} else {
|
|
132
|
+
this.armSweep = null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Seeds the permanent scopes once the host resolves identity. The manager
|
|
138
|
+
* can exist from client construction — before the connection's read scope
|
|
139
|
+
* is known — so the base set is seeded rather than fixed at construction.
|
|
140
|
+
*/
|
|
141
|
+
setBaseGroups(groups: readonly string[]): void {
|
|
142
|
+
this.baseGroups = new Set(groups);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Move a group into the warm set with a fresh TTL, maintaining LRU order
|
|
147
|
+
* and the `maxWarm` cap. JS `Map` preserves insertion order, so deleting
|
|
148
|
+
* then re-setting moves the group to the most-recently-warmed position;
|
|
149
|
+
* eviction then drops from the front (oldest). Base/pinned groups never
|
|
150
|
+
* warm — callers guard before calling this.
|
|
151
|
+
*/
|
|
152
|
+
private warmGroup(group: string): void {
|
|
153
|
+
if (this.armSweep && !this.cancelSweep) this.armSweep();
|
|
154
|
+
this.warm.delete(group);
|
|
155
|
+
this.warm.set(group, this.now() + this.warmTtlMs);
|
|
156
|
+
while (this.warm.size > this.maxWarm) {
|
|
157
|
+
const oldest = this.warm.keys().next().value;
|
|
158
|
+
if (oldest === undefined) break;
|
|
159
|
+
this.warm.delete(oldest);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** The effective read set: base ∪ active ∪ pinned ∪ (warm not yet expired). */
|
|
164
|
+
private desiredGroups(): Set<string> {
|
|
165
|
+
const now = this.now();
|
|
166
|
+
const desired = new Set<string>(this.baseGroups);
|
|
167
|
+
for (const g of this.active) desired.add(g);
|
|
168
|
+
for (const g of this.pinned) desired.add(g);
|
|
169
|
+
for (const [g, expiry] of this.warm) {
|
|
170
|
+
if (expiry > now) desired.add(g);
|
|
171
|
+
}
|
|
172
|
+
return desired;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Bring a group into view. Cancels any warm timer for it. Idempotent. */
|
|
176
|
+
enter(group: string): Promise<void> {
|
|
177
|
+
this.warm.delete(group);
|
|
178
|
+
this.active.add(group);
|
|
179
|
+
return this.reconcile();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Leave a group. It does not drop immediately — it goes warm for
|
|
184
|
+
* `warmTtlMs` (unless pinned, in which case it stays via the pin).
|
|
185
|
+
* Re-entering within the window is free.
|
|
186
|
+
*/
|
|
187
|
+
leave(group: string): Promise<void> {
|
|
188
|
+
this.active.delete(group);
|
|
189
|
+
if (!this.pinned.has(group) && !this.baseGroups.has(group)) {
|
|
190
|
+
this.warmGroup(group);
|
|
191
|
+
}
|
|
192
|
+
return this.reconcile();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Pin a group (active claim / prominence). Never warm or expires while pinned. */
|
|
196
|
+
pin(group: string): Promise<void> {
|
|
197
|
+
this.warm.delete(group);
|
|
198
|
+
this.pinned.add(group);
|
|
199
|
+
return this.reconcile();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Unpin a group. If it's not currently in view, it transitions to warm
|
|
204
|
+
* (so dropping a claim gets the same hysteresis as closing a tab) rather
|
|
205
|
+
* than dropping instantly.
|
|
206
|
+
*/
|
|
207
|
+
unpin(group: string): Promise<void> {
|
|
208
|
+
this.pinned.delete(group);
|
|
209
|
+
if (!this.active.has(group) && !this.baseGroups.has(group)) {
|
|
210
|
+
this.warmGroup(group);
|
|
211
|
+
}
|
|
212
|
+
return this.reconcile();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Drop warm groups whose TTL has lapsed and reconcile. Auto-invoked on
|
|
217
|
+
* the sweep timer; call manually (with an injected `now`) in tests.
|
|
218
|
+
*/
|
|
219
|
+
sweep(): Promise<void> {
|
|
220
|
+
const now = this.now();
|
|
221
|
+
for (const [g, expiry] of this.warm) {
|
|
222
|
+
if (expiry <= now) this.warm.delete(g);
|
|
223
|
+
}
|
|
224
|
+
return this.reconcile();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** The set the manager believes is subscribed (post-confirmation). */
|
|
228
|
+
effectiveGroups(): string[] {
|
|
229
|
+
return [...this.lastSent];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Re-asserts the full desired set against the transport, forgetting what was
|
|
234
|
+
* previously confirmed. Call this after a reconnect: a fresh
|
|
235
|
+
* {@link SyncWebSocket} starts from the sync groups named in the connect-time
|
|
236
|
+
* URL, so the manager's diff baseline no longer reflects the new socket.
|
|
237
|
+
* Clearing that baseline makes the next reconcile push one
|
|
238
|
+
* `update_subscription` frame that re-establishes the current interest —
|
|
239
|
+
* including any warm or pinned groups that drifted while the connection was
|
|
240
|
+
* down. The connect-time URL already carries the last-acknowledged set, so
|
|
241
|
+
* this is a correction, not the primary mechanism.
|
|
242
|
+
*/
|
|
243
|
+
resync(): Promise<void> {
|
|
244
|
+
this.lastSent = new Set();
|
|
245
|
+
return this.reconcile();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Stop the sweep timer. The connection is unaffected. */
|
|
249
|
+
dispose(): void {
|
|
250
|
+
this.cancelSweep?.();
|
|
251
|
+
this.cancelSweep = null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Push the desired set to the transport iff it differs from the last
|
|
256
|
+
* confirmed set. Coalesces concurrent mutations: if a call is already in
|
|
257
|
+
* flight, mark dirty and let the in-flight loop pick up the newest state
|
|
258
|
+
* — so a burst of enter/leave collapses into the minimum number of
|
|
259
|
+
* `update_subscription` round-trips.
|
|
260
|
+
*/
|
|
261
|
+
private reconcile(): Promise<void> {
|
|
262
|
+
if (this.inFlight) {
|
|
263
|
+
this.dirty = true;
|
|
264
|
+
return this.inFlight;
|
|
265
|
+
}
|
|
266
|
+
if (setsEqual(this.desiredGroups(), this.lastSent)) {
|
|
267
|
+
return Promise.resolve();
|
|
268
|
+
}
|
|
269
|
+
this.inFlight = (async () => {
|
|
270
|
+
try {
|
|
271
|
+
do {
|
|
272
|
+
this.dirty = false;
|
|
273
|
+
const target = this.desiredGroups();
|
|
274
|
+
if (setsEqual(target, this.lastSent)) break;
|
|
275
|
+
try {
|
|
276
|
+
const result = await this.transport.updateSubscription([...target]);
|
|
277
|
+
this.lastSent = new Set(result.syncGroups);
|
|
278
|
+
} catch {
|
|
279
|
+
// Transport unavailable (offline, or socket not open) or the
|
|
280
|
+
// server rejected the set. Read interest is soft state, so enter,
|
|
281
|
+
// leave, and sweep never throw for an expected transient failure.
|
|
282
|
+
// Leaving `lastSent` unchanged keeps the pending diff; `resync()`
|
|
283
|
+
// on the next successful connect re-pushes the then-current desired
|
|
284
|
+
// set, which recovers any interest that changed while offline.
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
// A concurrent reconcile() arriving during the await above sets
|
|
288
|
+
// `this.dirty` back to true (the coalescing path near line 245).
|
|
289
|
+
// TypeScript's intra-closure flow analysis can't see that cross-
|
|
290
|
+
// invocation mutation and reads this as always-false, but the loop
|
|
291
|
+
// is genuinely reentrant.
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
293
|
+
} while (this.dirty);
|
|
294
|
+
} finally {
|
|
295
|
+
this.inFlight = null;
|
|
296
|
+
}
|
|
297
|
+
})();
|
|
298
|
+
return this.inFlight;
|
|
299
|
+
}
|
|
300
|
+
}
|