@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,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useContext, useEffect, useRef } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
AbloInternalContext,
|
|
6
|
+
type QueuedMutation,
|
|
7
|
+
} from '../reactRuntime.js';
|
|
8
|
+
import { AbloValidationError } from '@abloatai/transaction/errors';
|
|
9
|
+
|
|
10
|
+
export interface MutationFailurePayload {
|
|
11
|
+
transaction: QueuedMutation;
|
|
12
|
+
error: Error;
|
|
13
|
+
permanent?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Subscribe to optimistic mutation rollbacks and permanent write failures. */
|
|
17
|
+
export function useMutationFailureListener(
|
|
18
|
+
listener: (payload: MutationFailurePayload) => void,
|
|
19
|
+
): void {
|
|
20
|
+
const context = useContext(AbloInternalContext);
|
|
21
|
+
if (!context) {
|
|
22
|
+
throw new AbloValidationError(
|
|
23
|
+
'useMutationFailureListener: no <AbloProvider> mounted above this component.',
|
|
24
|
+
{ code: 'no_ablo_provider' },
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const listenerRef = useRef(listener);
|
|
28
|
+
listenerRef.current = listener;
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
const engine = context.engine;
|
|
31
|
+
if (!engine) return;
|
|
32
|
+
return engine.onMutationFailure((payload) => listenerRef.current(payload));
|
|
33
|
+
}, [context, context.engine]);
|
|
34
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import type { Schema } from '@abloatai/transaction/schema/schema';
|
|
5
|
+
import type {
|
|
6
|
+
MutatorDefs,
|
|
7
|
+
MutatorFn,
|
|
8
|
+
} from '../local/mutators/defineMutators.js';
|
|
9
|
+
import { createTransaction } from '../local/mutators/Transaction.js';
|
|
10
|
+
import { createRecordingMutation } from '../local/mutators/RecordingMutation.js';
|
|
11
|
+
import type { UndoScope } from '../local/mutators/UndoManager.js';
|
|
12
|
+
import type { ResolveSchema } from '@abloatai/transaction/types/global';
|
|
13
|
+
import { useSyncContext } from './context.js';
|
|
14
|
+
import { AbloValidationError } from '@abloatai/transaction/errors';
|
|
15
|
+
import { getContext } from '../local/context.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Turns a mutator tree built with `defineMutators` into callable invokers. The
|
|
19
|
+
* returned object mirrors that tree one-to-one, but each leaf becomes an
|
|
20
|
+
* `(args) => Promise<TResult>` function.
|
|
21
|
+
*
|
|
22
|
+
* Each invocation builds a fresh `Transaction` bound to the current store and
|
|
23
|
+
* organization, calls your mutator with `{ tx, args }`, and returns whatever
|
|
24
|
+
* the mutator resolves to.
|
|
25
|
+
*
|
|
26
|
+
* If a mutator throws, the error propagates to the caller and any writes it
|
|
27
|
+
* already dispatched stay in place — there is no automatic rollback. Wrap the
|
|
28
|
+
* call in your own try/catch and issue compensating writes when you need to
|
|
29
|
+
* undo a partial change, or pass an `undoScope` (see {@link UseMutatorsOptions})
|
|
30
|
+
* to record inverses for undo and redo.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Map a `MutatorFn` onto its invoker form — strip `tx`, keep `args`/return.
|
|
35
|
+
*
|
|
36
|
+
* Uses nested `infer O` so the `args`/`result` types are extracted from the
|
|
37
|
+
* function signature without binding the `tx` parameter to a specific
|
|
38
|
+
* `Transaction<S>` variance. Function parameters are contravariant, so a
|
|
39
|
+
* match against `MutatorFn<Schema>` would reject mutators declared against
|
|
40
|
+
* a narrower schema (e.g. `Transaction<typeof appSchema>`). The two-step
|
|
41
|
+
* inference sidesteps that without resorting to `any`/`unknown` placeholders.
|
|
42
|
+
*/
|
|
43
|
+
export type InvokerFor<F> = F extends (options: infer O) => Promise<infer R>
|
|
44
|
+
? O extends { args: infer A }
|
|
45
|
+
? (args: A) => Promise<R>
|
|
46
|
+
: never
|
|
47
|
+
: never;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The hook's return shape: same tree as the input `MutatorDefs`, every leaf
|
|
51
|
+
* rewritten to its invoker form.
|
|
52
|
+
*/
|
|
53
|
+
export type MutatorInvokers<M> = {
|
|
54
|
+
[K in keyof M]: {
|
|
55
|
+
[N in keyof M[K]]: InvokerFor<M[K][N]>;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Options passed to `useMutators`. When `undoScope` is set, every mutator
|
|
61
|
+
* invocation is wrapped in a `RecordingMutation` and its inverses are
|
|
62
|
+
* pushed to the scope as one undo entry.
|
|
63
|
+
*/
|
|
64
|
+
export interface UseMutatorsOptions<S extends Schema> {
|
|
65
|
+
/** Target undo scope for recording inverses. Omit to disable recording. */
|
|
66
|
+
undoScope?: UndoScope<S>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Mutator invokers (explicit schema arg). */
|
|
70
|
+
export function useMutators<S extends Schema, M extends MutatorDefs<S>>(
|
|
71
|
+
schema: S,
|
|
72
|
+
mutators: M,
|
|
73
|
+
options?: UseMutatorsOptions<S>,
|
|
74
|
+
): MutatorInvokers<M>;
|
|
75
|
+
|
|
76
|
+
/** Mutator invokers via the `Register` module augmentation. Schema comes
|
|
77
|
+
* from the `SyncProvider`'s context; the mutator tree is typed against
|
|
78
|
+
* `ResolveSchema` at the call site. */
|
|
79
|
+
export function useMutators<
|
|
80
|
+
M extends ResolveSchema extends Schema ? MutatorDefs<ResolveSchema> : MutatorDefs<Schema>,
|
|
81
|
+
>(
|
|
82
|
+
mutators: M,
|
|
83
|
+
options?: UseMutatorsOptions<ResolveSchema extends Schema ? ResolveSchema : Schema>,
|
|
84
|
+
): MutatorInvokers<M>;
|
|
85
|
+
|
|
86
|
+
export function useMutators(
|
|
87
|
+
schemaOrMutators: Schema | MutatorDefs<Schema>,
|
|
88
|
+
mutatorsOrOptions?: MutatorDefs<Schema> | UseMutatorsOptions<Schema>,
|
|
89
|
+
maybeOptions?: UseMutatorsOptions<Schema>,
|
|
90
|
+
): MutatorInvokers<MutatorDefs<Schema>> {
|
|
91
|
+
const { store, organizationId, schema: ctxSchema } = useSyncContext();
|
|
92
|
+
|
|
93
|
+
// Disambiguate: explicit-schema path has the schema object in first slot;
|
|
94
|
+
// the global-resolved path has the mutator tree there. A schema object
|
|
95
|
+
// has a `.models` property; a mutator tree doesn't.
|
|
96
|
+
const isExplicit =
|
|
97
|
+
typeof schemaOrMutators === 'object' &&
|
|
98
|
+
schemaOrMutators !== null &&
|
|
99
|
+
'models' in schemaOrMutators;
|
|
100
|
+
|
|
101
|
+
const schema = isExplicit ? (schemaOrMutators as Schema) : ctxSchema;
|
|
102
|
+
const mutators = (isExplicit ? mutatorsOrOptions : schemaOrMutators) as MutatorDefs<Schema>;
|
|
103
|
+
const options = (isExplicit ? maybeOptions : mutatorsOrOptions) as
|
|
104
|
+
| UseMutatorsOptions<Schema>
|
|
105
|
+
| undefined;
|
|
106
|
+
|
|
107
|
+
if (!schema) {
|
|
108
|
+
throw new AbloValidationError(
|
|
109
|
+
'useMutators: no schema available. Pass the schema as the first arg, ' +
|
|
110
|
+
'or build the <AbloProvider> above with `Ablo({ schema })` so the ' +
|
|
111
|
+
'zero-arg overload can read it from context.',
|
|
112
|
+
{ code: 'mutators_schema_missing' },
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const { undoScope } = options ?? {};
|
|
117
|
+
|
|
118
|
+
return useMemo<MutatorInvokers<MutatorDefs<Schema>>>(() => {
|
|
119
|
+
const out: Record<string, Record<string, (args: unknown) => Promise<unknown>>> = {};
|
|
120
|
+
|
|
121
|
+
for (const modelKey of Object.keys(mutators)) {
|
|
122
|
+
const group = (mutators as Record<string, Record<string, MutatorFn<Schema, unknown, unknown>>>)[modelKey];
|
|
123
|
+
if (!group) continue;
|
|
124
|
+
|
|
125
|
+
const invokers: Record<string, (args: unknown) => Promise<unknown>> = {};
|
|
126
|
+
for (const mutatorName of Object.keys(group)) {
|
|
127
|
+
const maybeFn = group[mutatorName];
|
|
128
|
+
if (!maybeFn) continue;
|
|
129
|
+
// Bind the narrowed value: `noUncheckedIndexedAccess` types the indexed
|
|
130
|
+
// read as `Fn | undefined`, and that narrowing doesn't survive into the
|
|
131
|
+
// deferred invoker closures below — a non-optional local does.
|
|
132
|
+
const fn = maybeFn;
|
|
133
|
+
const label = `${String(modelKey)}.${mutatorName}`;
|
|
134
|
+
|
|
135
|
+
invokers[mutatorName] = async (args: unknown) => {
|
|
136
|
+
// Recording path: wrap the transaction so each write snapshots its
|
|
137
|
+
// inverse. On success, push the captured entry to the scope.
|
|
138
|
+
//
|
|
139
|
+
// The whole snapshot → write → record sequence runs on the scope's
|
|
140
|
+
// serialization chain so concurrent invocations (a caller may fire
|
|
141
|
+
// writes without awaiting them) record in invocation order and never
|
|
142
|
+
// interleave their shared-model snapshots. See UndoScope.runRecorded.
|
|
143
|
+
if (undoScope) {
|
|
144
|
+
return undoScope.runRecorded(async () => {
|
|
145
|
+
const recording = createRecordingMutation(schema, store, organizationId);
|
|
146
|
+
try {
|
|
147
|
+
const result = await fn({ tx: recording.tx, args });
|
|
148
|
+
const entry = recording.getEntry(label);
|
|
149
|
+
if (entry) undoScope.record(entry);
|
|
150
|
+
return result;
|
|
151
|
+
} catch (err) {
|
|
152
|
+
// The error is re-thrown to the caller's await (the real
|
|
153
|
+
// consumer surface), so this is a forensic follow-on → debug.
|
|
154
|
+
getContext().logger.debug(
|
|
155
|
+
`[useMutators] mutator "${label}" threw`,
|
|
156
|
+
{ error: err },
|
|
157
|
+
);
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Non-recording path — plain transaction, no inverse capture.
|
|
164
|
+
const tx = createTransaction(schema, store, organizationId);
|
|
165
|
+
try {
|
|
166
|
+
return await fn({ tx, args });
|
|
167
|
+
} catch (err) {
|
|
168
|
+
// Re-thrown to the caller's await (the real consumer surface) →
|
|
169
|
+
// this duplicate is forensic, debug only.
|
|
170
|
+
getContext().logger.debug(
|
|
171
|
+
`[useMutators] mutator "${label}" threw`,
|
|
172
|
+
{ error: err },
|
|
173
|
+
);
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
out[modelKey] = invokers;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return out;
|
|
183
|
+
}, [schema, mutators, store, organizationId, undoScope]);
|
|
184
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
useSyncContext,
|
|
6
|
+
type SyncStoreContract,
|
|
7
|
+
} from './context.js';
|
|
8
|
+
import { useReactive } from '../useReactive.js';
|
|
9
|
+
|
|
10
|
+
export type SyncStatusSnapshot =
|
|
11
|
+
| { readonly name: 'initial' }
|
|
12
|
+
| { readonly name: 'connecting'; readonly progress: number }
|
|
13
|
+
| { readonly name: 'connected'; readonly hasUnsyncedChanges: boolean }
|
|
14
|
+
| { readonly name: 'reconnecting'; readonly reason?: string }
|
|
15
|
+
| { readonly name: 'disconnected'; readonly reason?: string }
|
|
16
|
+
| { readonly name: 'needs-auth' };
|
|
17
|
+
|
|
18
|
+
/** Reactively exposes the local store's connection and settlement status. */
|
|
19
|
+
export function useSyncStatus(): SyncStatusSnapshot {
|
|
20
|
+
const { store } = useSyncContext();
|
|
21
|
+
const compute = useCallback(() => deriveStatus(store), [store]);
|
|
22
|
+
return useReactive(compute, sameSnapshot);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function deriveStatus(store: SyncStoreContract): SyncStatusSnapshot {
|
|
26
|
+
const { state, progress, pendingChanges, isSessionError, error } = store.syncStatus;
|
|
27
|
+
if (isSessionError) return { name: 'needs-auth' };
|
|
28
|
+
if (state === 'reconnecting') return { name: 'reconnecting', reason: error?.message };
|
|
29
|
+
if (state === 'offline') return { name: 'disconnected', reason: 'offline' };
|
|
30
|
+
if (state === 'error') return { name: 'disconnected', reason: error?.message };
|
|
31
|
+
if (store.isReady) return { name: 'connected', hasUnsyncedChanges: pendingChanges > 0 };
|
|
32
|
+
if (state === 'idle' || state === 'syncing') return { name: 'connecting', progress };
|
|
33
|
+
return { name: 'initial' };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function sameSnapshot(a: SyncStatusSnapshot, b: SyncStatusSnapshot): boolean {
|
|
37
|
+
if (a.name !== b.name) return false;
|
|
38
|
+
if (a.name === 'initial' || a.name === 'needs-auth') return true;
|
|
39
|
+
if (a.name === 'connecting') return b.name === 'connecting' && a.progress === b.progress;
|
|
40
|
+
if (a.name === 'connected') return b.name === 'connected' && a.hasUnsyncedChanges === b.hasUnsyncedChanges;
|
|
41
|
+
return (b.name === 'reconnecting' || b.name === 'disconnected') && a.reason === b.reason;
|
|
42
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
4
|
+
import type { Schema } from '@abloatai/transaction/schema/schema';
|
|
5
|
+
import {
|
|
6
|
+
UndoManager,
|
|
7
|
+
type UndoScope,
|
|
8
|
+
type UndoScopeOptions,
|
|
9
|
+
} from '../local/mutators/UndoManager.js';
|
|
10
|
+
import type { ResolveSchema } from '@abloatai/transaction/types/global';
|
|
11
|
+
import { useSyncContext } from './context.js';
|
|
12
|
+
import { AbloValidationError } from '@abloatai/transaction/errors';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Provides per-surface undo and redo for mutator invocations. Each named scope
|
|
16
|
+
* owns an independent undo/redo stack, so different parts of your app — a main
|
|
17
|
+
* editor, a sidebar form — can undo separately without stepping on each other.
|
|
18
|
+
*
|
|
19
|
+
* Wire the returned `scope` into `useMutators(schema, mutators, { undoScope:
|
|
20
|
+
* scope })` and those invocations become recorded. `undo()` and `redo()` replay
|
|
21
|
+
* the captured inverses and forwards as new transactions that do not record
|
|
22
|
+
* themselves; the manager moves the entry between the two stacks explicitly.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const { undo, redo, canUndo, canRedo, scope } = useUndoScope('report-editor');
|
|
26
|
+
* const mutate = useMutators(schema, reportMutators, { undoScope: scope });
|
|
27
|
+
*
|
|
28
|
+
* // Cmd+Z handler
|
|
29
|
+
* useHotkey('mod+z', () => { if (canUndo) void undo(); });
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
export interface UseUndoScopeResult<S extends Schema> {
|
|
33
|
+
/** Pass to `useMutators(..., { undoScope })` to enable recording. */
|
|
34
|
+
scope: UndoScope<S>;
|
|
35
|
+
undo: () => Promise<void>;
|
|
36
|
+
redo: () => Promise<void>;
|
|
37
|
+
canUndo: boolean;
|
|
38
|
+
canRedo: boolean;
|
|
39
|
+
/** Drop history. Use after sync errors / auth context changes. */
|
|
40
|
+
clear: () => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Module-level weak registry: `SyncStoreContract` → `UndoManager`.
|
|
44
|
+
// A single app wiring through one SyncProvider shares one manager across
|
|
45
|
+
// every useUndoScope call, so scopes with the same name are identity-equal.
|
|
46
|
+
// The hook implementation already operates on the runtime-wide `Schema` type;
|
|
47
|
+
// its overloads restore the caller's precise schema type at the public boundary,
|
|
48
|
+
// so the registry can keep that same non-generic runtime representation.
|
|
49
|
+
const managers = new WeakMap<object, UndoManager<Schema>>();
|
|
50
|
+
|
|
51
|
+
function getManager(
|
|
52
|
+
key: object,
|
|
53
|
+
factory: () => UndoManager<Schema>,
|
|
54
|
+
): UndoManager<Schema> {
|
|
55
|
+
let m = managers.get(key);
|
|
56
|
+
if (!m) {
|
|
57
|
+
const created = factory();
|
|
58
|
+
managers.set(key, created);
|
|
59
|
+
m = created;
|
|
60
|
+
}
|
|
61
|
+
return m;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Per-surface undo/redo (explicit schema arg). */
|
|
65
|
+
export function useUndoScope<S extends Schema>(
|
|
66
|
+
schema: S,
|
|
67
|
+
name: string,
|
|
68
|
+
options?: UndoScopeOptions,
|
|
69
|
+
): UseUndoScopeResult<S>;
|
|
70
|
+
|
|
71
|
+
/** Per-surface undo/redo via the `Register` module augmentation. */
|
|
72
|
+
export function useUndoScope(
|
|
73
|
+
name: string,
|
|
74
|
+
options?: UndoScopeOptions,
|
|
75
|
+
): UseUndoScopeResult<ResolveSchema extends Schema ? ResolveSchema : Schema>;
|
|
76
|
+
|
|
77
|
+
export function useUndoScope(
|
|
78
|
+
schemaOrName: Schema | string,
|
|
79
|
+
nameOrOptions?: string | UndoScopeOptions,
|
|
80
|
+
maybeOptions?: UndoScopeOptions,
|
|
81
|
+
): UseUndoScopeResult<Schema> {
|
|
82
|
+
const { store, organizationId, schema: ctxSchema } = useSyncContext();
|
|
83
|
+
|
|
84
|
+
const isExplicit = typeof schemaOrName !== 'string';
|
|
85
|
+
const schema = isExplicit ? (schemaOrName) : ctxSchema;
|
|
86
|
+
const name = isExplicit ? (nameOrOptions as string) : schemaOrName;
|
|
87
|
+
const options = (isExplicit ? maybeOptions : nameOrOptions) as UndoScopeOptions | undefined;
|
|
88
|
+
|
|
89
|
+
if (!schema) {
|
|
90
|
+
throw new AbloValidationError(
|
|
91
|
+
'useUndoScope: no schema available. Pass the schema as the first arg, ' +
|
|
92
|
+
'or build the <AbloProvider> above with `Ablo({ schema })` so the ' +
|
|
93
|
+
'zero-arg overload can read it from context.',
|
|
94
|
+
{ code: 'undo_scope_schema_missing' },
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const scope = useMemo(() => {
|
|
99
|
+
// Store is the identity for the manager — one per SyncProvider.
|
|
100
|
+
const manager = getManager(store, () => new UndoManager(schema, store, organizationId));
|
|
101
|
+
return manager.getScope(name, options);
|
|
102
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
103
|
+
}, [store, organizationId, name]);
|
|
104
|
+
|
|
105
|
+
// Local tick forces re-render after undo/redo/clear so canUndo/canRedo
|
|
106
|
+
// reflect the new stack sizes. The scope itself doesn't emit React-
|
|
107
|
+
// friendly notifications; callers that want cross-component reactivity
|
|
108
|
+
// can wire a mobx observable or custom event bus on top.
|
|
109
|
+
const [, setTick] = useState(0);
|
|
110
|
+
|
|
111
|
+
// Reset tick when scope identity changes (new store / new orgId).
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
setTick(0);
|
|
114
|
+
}, [scope]);
|
|
115
|
+
|
|
116
|
+
// Re-render on any stack change — including entries recorded from the local-
|
|
117
|
+
// mutation stream, which don't otherwise trigger a React update. Without this
|
|
118
|
+
// `canUndo`/`canRedo` go stale in every consumer that didn't itself call
|
|
119
|
+
// undo/redo (e.g. a keyboard handler whose Cmd+Z gate then never fires).
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
return scope.onChange(() => { setTick((t: number) => t + 1); });
|
|
122
|
+
}, [scope]);
|
|
123
|
+
|
|
124
|
+
const size = scope.size();
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
scope,
|
|
128
|
+
undo: async () => {
|
|
129
|
+
await scope.undo();
|
|
130
|
+
setTick((t: number) => t + 1);
|
|
131
|
+
},
|
|
132
|
+
redo: async () => {
|
|
133
|
+
await scope.redo();
|
|
134
|
+
setTick((t: number) => t + 1);
|
|
135
|
+
},
|
|
136
|
+
canUndo: size.undo > 0,
|
|
137
|
+
canRedo: size.redo > 0,
|
|
138
|
+
clear: () => {
|
|
139
|
+
scope.clear();
|
|
140
|
+
setTick((t: number) => t + 1);
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
package/src/react.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** React bindings for the optional human-facing local-state package. */
|
|
2
|
+
export { useReactive } from './useReactive.js';
|
|
3
|
+
export { useCurrentUserId } from './react/useCurrentUserId.js';
|
|
4
|
+
export { useErrorListener } from './react/useErrorListener.js';
|
|
5
|
+
export { useSyncStatus, type SyncStatusSnapshot } from './react/useSyncStatus.js';
|
|
6
|
+
export {
|
|
7
|
+
useMutationFailureListener,
|
|
8
|
+
type MutationFailurePayload,
|
|
9
|
+
} from './react/useMutationFailureListener.js';
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
AbloProvider,
|
|
13
|
+
useJoin,
|
|
14
|
+
usePeers,
|
|
15
|
+
useSync,
|
|
16
|
+
useSyncStore,
|
|
17
|
+
type AbloProviderProps,
|
|
18
|
+
type ParticipantScope,
|
|
19
|
+
type ParticipantStatus,
|
|
20
|
+
type UseJoinOptions,
|
|
21
|
+
type UseJoinReturn,
|
|
22
|
+
} from './react/AbloProvider.js';
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
ClientSideSuspense,
|
|
26
|
+
type ClientSideSuspenseProps,
|
|
27
|
+
} from './react/ClientSideSuspense.js';
|
|
28
|
+
|
|
29
|
+
export { DefaultFallback } from './react/DefaultFallback.js';
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
createAbloReact,
|
|
33
|
+
type AbloReactBinding,
|
|
34
|
+
} from './react/createAbloReact.js';
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
useAblo,
|
|
38
|
+
type UseAbloHydratedModelResult,
|
|
39
|
+
type UseAbloModelOptions,
|
|
40
|
+
type UseAbloModelResult,
|
|
41
|
+
} from './react/useAblo.js';
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
useMutators,
|
|
45
|
+
type InvokerFor,
|
|
46
|
+
type MutatorInvokers,
|
|
47
|
+
type UseMutatorsOptions,
|
|
48
|
+
} from './react/useMutators.js';
|
|
49
|
+
|
|
50
|
+
export {
|
|
51
|
+
useUndoScope,
|
|
52
|
+
type UseUndoScopeResult,
|
|
53
|
+
} from './react/useUndoScope.js';
|
|
54
|
+
|
|
55
|
+
export type {
|
|
56
|
+
DefaultSyncShape,
|
|
57
|
+
ResolveSchema,
|
|
58
|
+
ResolveUserMeta,
|
|
59
|
+
ResolveClaimMeta,
|
|
60
|
+
ResolveModelKey,
|
|
61
|
+
} from '@abloatai/transaction/types/global';
|
|
62
|
+
|
|
63
|
+
export { ModelScope } from '@abloatai/transaction/types';
|
|
64
|
+
export type { SyncStoreContract } from './react/context.js';
|
|
65
|
+
export type { MutateActions } from './local/mutators/mutateActions.js';
|
|
66
|
+
export type {
|
|
67
|
+
ReaderActions,
|
|
68
|
+
ReaderFindOptions,
|
|
69
|
+
} from './local/mutators/readerActions.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export {
|
|
2
|
+
AbloInternalContext,
|
|
3
|
+
type AbloInternalContextValue,
|
|
4
|
+
} from './react/internalContext.js';
|
|
5
|
+
export {
|
|
6
|
+
useSyncContext,
|
|
7
|
+
type SyncReactContext,
|
|
8
|
+
} from './react/context.js';
|
|
9
|
+
export type { SyncStoreContract } from './local/storeContract.js';
|
|
10
|
+
export type { QueuedMutation } from './local/transactions/mutations/MutationQueue.js';
|
package/src/surface.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A machine-checked manifest of this package's public API surface. It lists,
|
|
3
|
+
* as string tuples, the method names on `ablo.<model>`, the keys accepted by
|
|
4
|
+
* the list-style read options, and the keys of the client constructor
|
|
5
|
+
* options. Each tuple is proven equal to the keys of its source interface at
|
|
6
|
+
* compile time, so the lists cannot drift from the real types: add or remove
|
|
7
|
+
* a name on either side without updating the matching tuple and this file
|
|
8
|
+
* fails to compile, in both directions — no name the interface lacks, and no
|
|
9
|
+
* interface key the tuple omits.
|
|
10
|
+
*
|
|
11
|
+
* Documentation tooling reads these tuples to describe the surface, which
|
|
12
|
+
* guarantees a generated summary never names a method or option that does
|
|
13
|
+
* not exist. The names are verified here; their prose descriptions are
|
|
14
|
+
* written by hand, since prose cannot be type-checked.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { ModelOperations, LocalReadOptions } from './local/client/createModelProxy.js';
|
|
18
|
+
import type { AbloOptions } from './Ablo.js';
|
|
19
|
+
|
|
20
|
+
// ── compile-time exact-equality (no runtime, no casts) ─────────────────────
|
|
21
|
+
// Standard invariant type-equality: true only when A and B are mutually assignable.
|
|
22
|
+
type Equal<A, B> =
|
|
23
|
+
(<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false;
|
|
24
|
+
// `Expect<T extends true>` errors at the declaration when T is `false`.
|
|
25
|
+
type Expect<T extends true> = T;
|
|
26
|
+
|
|
27
|
+
// ── the per-`ablo.<model>` verb surface ────────────────────────────────────
|
|
28
|
+
/**
|
|
29
|
+
* The names of every method available on `ablo.<model>`, matching the keys of
|
|
30
|
+
* the {@link ModelOperations} interface. Documentation tooling reads this
|
|
31
|
+
* tuple, so it is the one list of model-verb names a generated summary can
|
|
32
|
+
* describe.
|
|
33
|
+
*/
|
|
34
|
+
export const PUBLIC_MODEL_VERBS = [
|
|
35
|
+
'get',
|
|
36
|
+
'retrieve',
|
|
37
|
+
'list',
|
|
38
|
+
'local',
|
|
39
|
+
'create',
|
|
40
|
+
'update',
|
|
41
|
+
'delete',
|
|
42
|
+
'claim',
|
|
43
|
+
'track',
|
|
44
|
+
'join',
|
|
45
|
+
'onChange',
|
|
46
|
+
] as const;
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
48
|
+
type _ModelVerbsExact = Expect<
|
|
49
|
+
Equal<(typeof PUBLIC_MODEL_VERBS)[number], keyof ModelOperations<unknown, unknown> & string>
|
|
50
|
+
>;
|
|
51
|
+
|
|
52
|
+
// ── the read/list query option surface ─────────────────────────────────────
|
|
53
|
+
/**
|
|
54
|
+
* The option keys accepted by `local.list` and `onChange`, matching the
|
|
55
|
+
* keys of {@link LocalReadOptions}. Note that the lifecycle filter is named
|
|
56
|
+
* `state`, not `scope`.
|
|
57
|
+
*/
|
|
58
|
+
export const PUBLIC_LIST_OPTION_KEYS = [
|
|
59
|
+
'where',
|
|
60
|
+
'filter',
|
|
61
|
+
'orderBy',
|
|
62
|
+
'limit',
|
|
63
|
+
'offset',
|
|
64
|
+
'state',
|
|
65
|
+
] as const;
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
67
|
+
type _ListOptionKeysExact = Expect<
|
|
68
|
+
Equal<(typeof PUBLIC_LIST_OPTION_KEYS)[number], keyof LocalReadOptions<unknown> & string>
|
|
69
|
+
>;
|
|
70
|
+
|
|
71
|
+
// ── the `Ablo({ … })` constructor option surface ───────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* The keys of the client constructor options, {@link AbloOptions}. Only
|
|
74
|
+
* `schema` is required; every other key is optional.
|
|
75
|
+
*/
|
|
76
|
+
export const PUBLIC_ABLO_OPTION_KEYS = [
|
|
77
|
+
'schema',
|
|
78
|
+
'apiKey',
|
|
79
|
+
'authEndpoint',
|
|
80
|
+
'authTimeoutMs',
|
|
81
|
+
'allowCrossOriginAuthEndpoint',
|
|
82
|
+
'persistence',
|
|
83
|
+
'durableWrites',
|
|
84
|
+
'commitOutbox',
|
|
85
|
+
'commitOutboxScope',
|
|
86
|
+
'debug',
|
|
87
|
+
'logLevel',
|
|
88
|
+
'logger',
|
|
89
|
+
'authToken',
|
|
90
|
+
'baseURL',
|
|
91
|
+
'fetch',
|
|
92
|
+
'defaultHeaders',
|
|
93
|
+
'defaultQuery',
|
|
94
|
+
'dangerouslyAllowBrowser',
|
|
95
|
+
'collaborationEvents',
|
|
96
|
+
'plugins',
|
|
97
|
+
'wait',
|
|
98
|
+
] as const;
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
100
|
+
type _AbloOptionKeysExact = Expect<
|
|
101
|
+
Equal<(typeof PUBLIC_ABLO_OPTION_KEYS)[number], keyof AbloOptions & string>
|
|
102
|
+
>;
|
|
103
|
+
|
|
104
|
+
export type ModelVerb = (typeof PUBLIC_MODEL_VERBS)[number];
|
|
105
|
+
export type ListOptionKey = (typeof PUBLIC_LIST_OPTION_KEYS)[number];
|
|
106
|
+
export type AbloOptionKey = (typeof PUBLIC_ABLO_OPTION_KEYS)[number];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useRef } from 'react';
|
|
4
|
+
import { useSyncExternalStore } from 'react';
|
|
5
|
+
import { reaction } from 'mobx';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Subscribe a React component to a MobX computation with a cached snapshot.
|
|
9
|
+
* This is the framework-level reactive primitive owned by @abloatai/humans;
|
|
10
|
+
* store/model hooks are layered above it.
|
|
11
|
+
*/
|
|
12
|
+
export function useReactive<T>(
|
|
13
|
+
compute: () => T,
|
|
14
|
+
equals: (a: T, b: T) => boolean = defaultEquals,
|
|
15
|
+
): T {
|
|
16
|
+
const computeRef = useRef(compute);
|
|
17
|
+
const equalsRef = useRef(equals);
|
|
18
|
+
const snapshotRef = useRef<{ value: T } | null>(null);
|
|
19
|
+
const versionRef = useRef(0);
|
|
20
|
+
|
|
21
|
+
equalsRef.current = equals;
|
|
22
|
+
if (snapshotRef.current === null) {
|
|
23
|
+
snapshotRef.current = { value: compute() };
|
|
24
|
+
} else if (computeRef.current !== compute) {
|
|
25
|
+
const next = compute();
|
|
26
|
+
if (!equals(snapshotRef.current.value, next)) {
|
|
27
|
+
snapshotRef.current = { value: next };
|
|
28
|
+
versionRef.current++;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
computeRef.current = compute;
|
|
32
|
+
|
|
33
|
+
const subscribe = useCallback((onChange: () => void) => reaction(
|
|
34
|
+
() => computeRef.current(),
|
|
35
|
+
(next) => {
|
|
36
|
+
const current = snapshotRef.current!.value;
|
|
37
|
+
if (!equalsRef.current(current, next)) {
|
|
38
|
+
snapshotRef.current = { value: next };
|
|
39
|
+
onChange();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
), [versionRef.current]);
|
|
43
|
+
const getSnapshot = useCallback(() => snapshotRef.current!.value, []);
|
|
44
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function defaultEquals<T>(a: T, b: T): boolean {
|
|
48
|
+
if (Object.is(a, b)) return true;
|
|
49
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
50
|
+
return a.every((value, index) => Object.is(value, b[index]));
|
|
51
|
+
}
|