@abloatai/ablo 0.34.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +758 -5
- package/README.md +56 -502
- package/bin/ablo.cjs +39 -0
- package/dist/BaseSyncedStore.d.ts +176 -48
- package/dist/BaseSyncedStore.js +346 -214
- package/dist/Database.d.ts +17 -44
- package/dist/Database.js +96 -79
- package/dist/InstanceCache.d.ts +31 -6
- package/dist/InstanceCache.js +65 -30
- package/dist/LazyReferenceCollection.d.ts +3 -3
- package/dist/LazyReferenceCollection.js +4 -4
- package/dist/Model.d.ts +23 -13
- package/dist/Model.js +27 -17
- package/dist/ModelRegistry.d.ts +8 -4
- package/dist/ModelRegistry.js +20 -18
- package/dist/NetworkMonitor.d.ts +3 -1
- package/dist/NetworkMonitor.js +7 -5
- package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
- package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
- package/dist/SyncClient.d.ts +47 -47
- package/dist/SyncClient.js +215 -156
- package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
- package/dist/ai-sdk/coordinatedTool.js +1 -1
- package/dist/ai-sdk/coordinationContext.d.ts +2 -2
- package/dist/ai-sdk/coordinationContext.js +1 -1
- package/dist/ai-sdk/wrap.d.ts +3 -3
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/index.d.ts +1 -156
- package/dist/auth/index.js +8 -301
- package/dist/client/Ablo.d.ts +42 -287
- package/dist/client/Ablo.js +129 -963
- package/dist/client/abloClient.d.ts +309 -0
- package/dist/client/abloClient.js +13 -0
- package/dist/client/clientPrelude.d.ts +52 -0
- package/dist/client/clientPrelude.js +60 -0
- package/dist/client/consoleLogger.d.ts +2 -2
- package/dist/client/coreClient.d.ts +60 -0
- package/dist/client/coreClient.js +118 -0
- package/dist/client/createInternalComponents.d.ts +8 -4
- package/dist/client/createInternalComponents.js +17 -10
- package/dist/client/createModelProxy.d.ts +98 -373
- package/dist/client/createModelProxy.js +233 -139
- package/dist/client/humans.d.ts +69 -0
- package/dist/client/humans.js +78 -0
- package/dist/client/modelRegistration.d.ts +1 -1
- package/dist/client/modelRegistration.js +9 -9
- package/dist/client/options.d.ts +73 -17
- package/dist/client/reactiveEngine.d.ts +53 -0
- package/dist/client/reactiveEngine.js +688 -0
- package/dist/client/resourceTypes.d.ts +9 -250
- package/dist/client/resourceTypes.js +8 -5
- package/dist/client/schemaConfig.d.ts +4 -4
- package/dist/client/schemaConfig.js +6 -2
- package/dist/client/storeCluster.d.ts +47 -0
- package/dist/client/storeCluster.js +118 -0
- package/dist/client/storeLifecycle.d.ts +61 -0
- package/dist/client/storeLifecycle.js +231 -0
- package/dist/client/validateAbloOptions.d.ts +3 -2
- package/dist/client/validateAbloOptions.js +1 -1
- package/dist/client/wsMutationExecutor.d.ts +3 -3
- package/dist/client/wsMutationExecutor.js +3 -3
- package/dist/context.d.ts +22 -9
- package/dist/context.js +33 -9
- package/dist/coordination/ClaimLog.d.ts +26 -0
- package/dist/coordination/ClaimLog.js +32 -0
- package/dist/coordination/index.d.ts +1 -15
- package/dist/coordination/index.js +8 -31
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +2 -2
- package/dist/docs/catalog.d.ts +72 -0
- package/dist/docs/catalog.js +230 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +10 -0
- package/dist/environment.d.ts +1 -40
- package/dist/environment.js +8 -37
- package/dist/index.d.ts +44 -36
- package/dist/index.js +30 -22
- package/dist/interfaces/index.d.ts +44 -134
- package/dist/keys/index.d.ts +1 -77
- package/dist/keys/index.js +8 -190
- package/dist/mutators/{RecordingTransaction.d.ts → RecordingMutation.d.ts} +4 -4
- package/dist/mutators/{RecordingTransaction.js → RecordingMutation.js} +2 -2
- package/dist/mutators/Transaction.d.ts +1 -1
- package/dist/mutators/Transaction.js +1 -1
- package/dist/mutators/UndoManager.d.ts +6 -6
- package/dist/mutators/UndoManager.js +5 -5
- package/dist/mutators/defineMutators.d.ts +3 -3
- package/dist/mutators/defineMutators.js +1 -1
- package/dist/mutators/inverseOp.js +2 -2
- package/dist/mutators/mutateActions.d.ts +3 -3
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +1 -1
- package/dist/mutators/undoApply.d.ts +1 -1
- package/dist/mutators/undoApply.js +1 -1
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +1 -1
- package/dist/query/client.d.ts +5 -2
- package/dist/query/client.js +10 -9
- package/dist/query/types.d.ts +6 -41
- package/dist/query/types.js +2 -2
- package/dist/react/AbloProvider.d.ts +18 -8
- package/dist/react/AbloProvider.js +10 -9
- package/dist/react/context.d.ts +3 -3
- package/dist/react/context.js +1 -1
- package/dist/react/createAbloReact.d.ts +56 -0
- package/dist/react/createAbloReact.js +51 -0
- package/dist/react/index.d.ts +6 -5
- package/dist/react/index.js +6 -3
- package/dist/react/internalContext.d.ts +1 -1
- package/dist/react/useAblo.d.ts +12 -5
- package/dist/react/useAblo.js +26 -8
- package/dist/react/useCurrentUserId.js +1 -1
- package/dist/react/useErrorListener.js +1 -1
- package/dist/react/useMutationFailureListener.d.ts +2 -2
- package/dist/react/useMutationFailureListener.js +1 -1
- package/dist/react/useMutators.d.ts +3 -3
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useUndoScope.d.ts +5 -5
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +69 -10
- package/dist/schema/coordination.js +90 -9
- package/dist/schema/ddl.js +2 -2
- package/dist/schema/diff.d.ts +1 -1
- package/dist/schema/generate.js +1 -1
- package/dist/schema/index.d.ts +11 -10
- package/dist/schema/index.js +22 -18
- package/dist/schema/queries.d.ts +27 -27
- package/dist/schema/queries.js +23 -23
- package/dist/schema/select.d.ts +3 -3
- package/dist/schema/select.js +6 -3
- package/dist/schema/serialize.d.ts +15 -6
- package/dist/schema/serialize.js +20 -3
- package/dist/schema/sugar.d.ts +6 -7
- package/dist/schema/sugar.js +9 -12
- package/dist/schema/syncDeltaRow.d.ts +4 -152
- package/dist/schema/syncDeltaRow.js +4 -105
- package/dist/server/adapter.d.ts +18 -1
- package/dist/server/commit.d.ts +10 -16
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +1 -1
- package/dist/source/adapter.d.ts +7 -5
- package/dist/source/adapter.js +7 -5
- package/dist/source/adapters/drizzle.d.ts +1 -1
- package/dist/source/adapters/drizzle.js +2 -2
- package/dist/source/adapters/kysely.d.ts +1 -1
- package/dist/source/adapters/kysely.js +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
- package/dist/source/adapters/kyselyMutationCore.js +2 -2
- package/dist/source/adapters/memory.js +1 -1
- package/dist/source/adapters/prisma.d.ts +8 -3
- package/dist/source/adapters/prisma.js +1 -1
- package/dist/source/connector.js +1 -1
- package/dist/source/connectorProtocol.d.ts +2 -8
- package/dist/source/connectorProtocol.js +3 -2
- package/dist/source/contract.d.ts +29 -17
- package/dist/source/contract.js +27 -22
- package/dist/source/factory.d.ts +1 -1
- package/dist/source/idempotency.js +2 -2
- package/dist/source/index.d.ts +1 -0
- package/dist/source/index.js +3 -0
- package/dist/source/next.d.ts +1 -1
- package/dist/source/signing.d.ts +9 -2
- package/dist/source/signing.js +4 -1
- package/dist/source/types.d.ts +6 -4
- package/dist/source/types.js +1 -1
- package/dist/{core/storeContract.d.ts → storeContract.d.ts} +6 -6
- package/dist/{core → stores}/DatabaseManager.d.ts +3 -1
- package/dist/{core → stores}/DatabaseManager.js +14 -13
- package/dist/stores/ObjectStore.d.ts +1 -1
- package/dist/{core → stores}/StoreManager.d.ts +9 -26
- package/dist/{core → stores}/StoreManager.js +29 -77
- package/dist/stores/SyncActionStore.d.ts +4 -2
- package/dist/stores/SyncActionStore.js +11 -17
- package/dist/stores/syncAction.d.ts +26 -0
- package/dist/stores/syncAction.js +16 -0
- package/dist/surface.d.ts +3 -3
- package/dist/surface.js +6 -4
- package/dist/sync/BootstrapFetcher.d.ts +127 -6
- package/dist/sync/BootstrapFetcher.js +511 -83
- package/dist/sync/ConnectionManager.d.ts +6 -198
- package/dist/sync/ConnectionManager.js +6 -677
- package/dist/sync/OnDemandLoader.d.ts +5 -2
- package/dist/sync/OnDemandLoader.js +61 -21
- package/dist/sync/SubscriptionManager.d.ts +13 -2
- package/dist/sync/SubscriptionManager.js +23 -5
- package/dist/sync/SyncWebSocket.d.ts +27 -510
- package/dist/sync/SyncWebSocket.js +76 -954
- package/dist/sync/awaitClaimGrant.d.ts +4 -44
- package/dist/sync/awaitClaimGrant.js +4 -109
- package/dist/sync/bootstrapApply.d.ts +3 -0
- package/dist/sync/bootstrapApply.js +2 -2
- package/dist/sync/commitFrames.d.ts +6 -40
- package/dist/sync/commitFrames.js +6 -97
- package/dist/sync/contextPorts.d.ts +18 -0
- package/dist/sync/contextPorts.js +31 -0
- package/dist/sync/createClaimStream.d.ts +5 -49
- package/dist/sync/createClaimStream.js +5 -469
- package/dist/sync/createPresenceStream.d.ts +26 -4
- package/dist/sync/createPresenceStream.js +28 -20
- package/dist/sync/createSnapshot.d.ts +2 -2
- package/dist/sync/createSnapshot.js +1 -1
- package/dist/sync/credentialLifecycle.d.ts +5 -173
- package/dist/sync/credentialLifecycle.js +5 -320
- package/dist/sync/deltaPipeline.d.ts +13 -12
- package/dist/sync/deltaPipeline.js +21 -4
- package/dist/sync/groupChange.d.ts +3 -0
- package/dist/sync/groupChange.js +16 -14
- package/dist/sync/participants.d.ts +24 -6
- package/dist/sync/participants.js +32 -23
- package/dist/sync/schemaDrift.d.ts +55 -0
- package/dist/sync/schemaDrift.js +53 -0
- package/dist/sync/schemas.d.ts +23 -33
- package/dist/sync/schemas.js +29 -20
- package/dist/sync/syncPlan.d.ts +3 -3
- package/dist/sync/wsFrameHandlers.d.ts +6 -114
- package/dist/sync/wsFrameHandlers.js +6 -392
- package/dist/syncLog/contract.d.ts +20 -0
- package/dist/syncLog/contract.js +19 -0
- package/dist/syncLog/index.d.ts +1 -0
- package/dist/syncLog/index.js +1 -0
- package/dist/transaction/ablo.d.ts +88 -0
- package/dist/transaction/ablo.js +33 -0
- package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
- package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
- package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
- package/dist/transaction/auth/bootstrapScope.js +1 -0
- package/dist/transaction/auth/capability.d.ts +212 -0
- package/dist/transaction/auth/capability.js +224 -0
- package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
- package/dist/{client → transaction/auth}/identity.d.ts +8 -7
- package/dist/{client → transaction/auth}/identity.js +1 -1
- package/dist/transaction/auth/index.d.ts +162 -0
- package/dist/transaction/auth/index.js +304 -0
- package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
- package/dist/{auth → transaction/auth}/schemas.js +13 -13
- package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
- package/dist/{client → transaction/auth}/sessionMint.js +4 -7
- package/dist/transaction/coordination/awaitClaimGrant.d.ts +56 -0
- package/dist/transaction/coordination/awaitClaimGrant.js +124 -0
- package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +34 -0
- package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +20 -0
- package/dist/transaction/coordination/claimMeta.d.ts +49 -0
- package/dist/transaction/coordination/claimMeta.js +52 -0
- package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
- package/dist/transaction/coordination/createClaimStream.js +475 -0
- package/dist/transaction/coordination/events.d.ts +74 -0
- package/dist/transaction/coordination/events.js +7 -0
- package/dist/transaction/coordination/index.d.ts +19 -0
- package/dist/transaction/coordination/index.js +45 -0
- package/dist/transaction/coordination/locator.d.ts +104 -0
- package/dist/transaction/coordination/locator.js +102 -0
- package/dist/transaction/coordination/schema.d.ts +1536 -0
- package/dist/transaction/coordination/schema.js +1177 -0
- package/dist/transaction/coordination/targetConflict.d.ts +2 -0
- package/dist/transaction/coordination/targetConflict.js +107 -0
- package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
- package/dist/{coordination → transaction/coordination}/trace.js +18 -25
- package/dist/transaction/durableWrites.d.ts +62 -0
- package/dist/{client → transaction}/durableWrites.js +28 -3
- package/dist/transaction/environment.d.ts +105 -0
- package/dist/transaction/environment.js +108 -0
- package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +12 -12
- package/dist/{errorCodes.js → transaction/errorCodes.js} +45 -18
- package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
- package/dist/{errors.js → transaction/errors.js} +85 -16
- package/dist/transaction/footprint.d.ts +111 -0
- package/dist/transaction/footprint.js +0 -0
- package/dist/transaction/index.d.ts +20 -0
- package/dist/transaction/index.js +20 -0
- package/dist/transaction/keys/index.d.ts +87 -0
- package/dist/transaction/keys/index.js +207 -0
- package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
- package/dist/transaction/log/syncDeltaRow.js +95 -0
- package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
- package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
- package/dist/transaction/logger.d.ts +16 -0
- package/dist/transaction/logger.js +7 -0
- package/dist/transaction/observability.d.ts +53 -0
- package/dist/transaction/observability.js +19 -0
- package/dist/transaction/plugin.d.ts +285 -0
- package/dist/transaction/plugin.js +106 -0
- package/dist/{policy → transaction/policy}/types.d.ts +3 -3
- package/dist/{policy → transaction/policy}/types.js +2 -0
- package/dist/transaction/resources/httpResources.d.ts +321 -0
- package/dist/transaction/resources/httpResources.js +7 -0
- package/dist/transaction/resources/modelOperations.d.ts +427 -0
- package/dist/transaction/resources/modelOperations.js +12 -0
- package/dist/transaction/resources/mutationOptions.d.ts +66 -0
- package/dist/transaction/resources/mutationOptions.js +9 -0
- package/dist/transaction/resources/where.d.ts +101 -0
- package/dist/transaction/resources/where.js +115 -0
- package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
- package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
- package/dist/{schema → transaction/schema}/field.d.ts +17 -23
- package/dist/{schema → transaction/schema}/field.js +5 -5
- package/dist/transaction/schema/fieldRef.d.ts +38 -0
- package/dist/transaction/schema/fieldRef.js +11 -0
- package/dist/transaction/schema/loadStrategy.d.ts +45 -0
- package/dist/transaction/schema/loadStrategy.js +46 -0
- package/dist/{schema → transaction/schema}/model.d.ts +50 -35
- package/dist/{schema → transaction/schema}/model.js +30 -20
- package/dist/transaction/schema/openapi.d.ts +58 -0
- package/dist/transaction/schema/openapi.js +501 -0
- package/dist/{schema → transaction/schema}/relation.d.ts +21 -16
- package/dist/{schema → transaction/schema}/relation.js +7 -7
- package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
- package/dist/{schema → transaction/schema}/residency.js +0 -5
- package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
- package/dist/{schema → transaction/schema}/roles.js +5 -5
- package/dist/{schema → transaction/schema}/schema.d.ts +39 -10
- package/dist/{schema → transaction/schema}/schema.js +24 -3
- package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
- package/dist/{schema → transaction/schema}/tenancy.js +7 -4
- package/dist/transaction/transactionLayer.d.ts +82 -0
- package/dist/transaction/transactionLayer.js +24 -0
- package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +5 -6
- package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
- package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
- package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
- package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +11 -37
- package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
- package/dist/transaction/transport/commitFrames.d.ts +90 -0
- package/dist/transaction/transport/commitFrames.js +134 -0
- package/dist/transaction/transport/connectionManager.d.ts +215 -0
- package/dist/transaction/transport/connectionManager.js +673 -0
- package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
- package/dist/transaction/transport/credentialLifecycle.js +324 -0
- package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
- package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
- package/dist/transaction/transport/httpClient.d.ts +131 -0
- package/dist/{client → transaction/transport}/httpClient.js +6 -5
- package/dist/transaction/transport/httpOptions.d.ts +33 -0
- package/dist/transaction/transport/httpOptions.js +12 -0
- package/dist/{client → transaction/transport}/httpTransport.js +295 -97
- package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
- package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
- package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
- package/dist/transaction/transport/wsFrameHandlers.js +429 -0
- package/dist/transaction/transport/wsTransport.d.ts +574 -0
- package/dist/transaction/transport/wsTransport.js +1023 -0
- package/dist/transaction/types/assertExact.d.ts +17 -0
- package/dist/transaction/types/assertExact.js +1 -0
- package/dist/{types → transaction/types}/global.d.ts +17 -2
- package/dist/{types → transaction/types}/global.js +2 -1
- package/dist/{types → transaction/types}/index.d.ts +14 -46
- package/dist/{types → transaction/types}/index.js +7 -16
- package/dist/{types → transaction/types}/streams.d.ts +73 -45
- package/dist/transaction/utils/duration.d.ts +50 -0
- package/dist/{utils → transaction/utils}/duration.js +32 -0
- package/dist/{utils → transaction/utils}/json.d.ts +18 -0
- package/dist/transaction/utils/json.js +276 -0
- package/dist/transaction/wire/accountResponses.d.ts +420 -0
- package/dist/transaction/wire/accountResponses.js +290 -0
- package/dist/transaction/wire/auth.d.ts +56 -0
- package/dist/transaction/wire/auth.js +63 -0
- package/dist/transaction/wire/claimEvent.d.ts +76 -0
- package/dist/transaction/wire/claimEvent.js +73 -0
- package/dist/transaction/wire/claims.d.ts +530 -0
- package/dist/transaction/wire/claims.js +327 -0
- package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
- package/dist/{wire → transaction/wire}/commit.js +68 -47
- package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
- package/dist/{wire → transaction/wire}/delta.js +37 -13
- package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
- package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
- package/dist/transaction/wire/feedCursor.d.ts +60 -0
- package/dist/transaction/wire/feedCursor.js +82 -0
- package/dist/transaction/wire/feedEvent.d.ts +204 -0
- package/dist/transaction/wire/feedEvent.js +65 -0
- package/dist/transaction/wire/frames.d.ts +194 -0
- package/dist/transaction/wire/frames.js +50 -0
- package/dist/transaction/wire/inboundFrames.d.ts +562 -0
- package/dist/transaction/wire/inboundFrames.js +116 -0
- package/dist/transaction/wire/index.d.ts +54 -0
- package/dist/transaction/wire/index.js +83 -0
- package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
- package/dist/transaction/wire/listEnvelope.js +42 -0
- package/dist/transaction/wire/modelMutations.d.ts +31 -0
- package/dist/transaction/wire/modelMutations.js +52 -0
- package/dist/transaction/wire/modelResponses.d.ts +85 -0
- package/dist/transaction/wire/modelResponses.js +43 -0
- package/dist/transaction/wire/modelShape.d.ts +78 -0
- package/dist/transaction/wire/modelShape.js +74 -0
- package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +85 -38
- package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +141 -80
- package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
- package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
- package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
- package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
- package/dist/transactions/mutations/commitLatency.d.ts +52 -0
- package/dist/transactions/mutations/commitLatency.js +130 -0
- package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
- package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
- package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +18 -16
- package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +15 -15
- package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +15 -11
- package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +14 -12
- package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
- package/dist/transactions/mutations/durableWriteStore.js +12 -0
- package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
- package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +4 -3
- package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +7 -5
- package/dist/utils/mobxSetup.d.ts +1 -1
- package/dist/utils/mobxSetup.js +5 -2
- package/dist/{core → views}/QueryView.d.ts +2 -2
- package/dist/{core → views}/QueryView.js +2 -2
- package/dist/{core → views}/ViewRegistry.d.ts +1 -1
- package/dist/{core/queryUtils.d.ts → views/incrementalView.d.ts} +6 -6
- package/dist/{core/queryUtils.js → views/incrementalView.js} +6 -6
- package/dist/webhooks/events.d.ts +2 -2
- package/dist/wire/index.d.ts +1 -34
- package/dist/wire/index.js +8 -49
- package/docs/agent-messaging.md +3 -3
- package/docs/agents.md +20 -13
- package/docs/api-keys.md +14 -10
- package/docs/api.md +27 -61
- package/docs/audit.md +6 -3
- package/docs/cli.md +41 -13
- package/docs/client-behavior.md +11 -9
- package/docs/concurrency-convention.md +49 -57
- package/docs/coordination.md +283 -121
- package/docs/data-sources.md +7 -5
- package/docs/debugging.md +39 -15
- package/docs/deployment.md +267 -0
- package/docs/examples/agent-human.md +49 -42
- package/docs/examples/ai-sdk-tool.md +69 -44
- package/docs/examples/existing-python-backend.md +8 -6
- package/docs/examples/nextjs.md +129 -47
- package/docs/examples/scoped-agent.md +46 -45
- package/docs/examples/server-agent.md +46 -26
- package/docs/groups.md +87 -30
- package/docs/guarantees.md +41 -12
- package/docs/how-it-works.md +38 -12
- package/docs/idempotency.md +126 -0
- package/docs/identity.md +77 -74
- package/docs/index.md +172 -86
- package/docs/integration-guide.md +31 -19
- package/docs/mcp.md +46 -21
- package/docs/migration.md +95 -18
- package/docs/operating-on-your-database.md +3 -1
- package/docs/projects.md +3 -1
- package/docs/quickstart.md +22 -5
- package/docs/react.md +31 -18
- package/docs/schema-contract.md +5 -3
- package/docs/session-settings.md +108 -0
- package/docs/sessions.md +4 -2
- package/docs/webhooks.md +12 -10
- package/llms.txt +48 -18
- package/package.json +21 -26
- package/dist/agent/Agent.d.ts +0 -366
- package/dist/agent/Agent.js +0 -514
- package/dist/agent/index.d.ts +0 -115
- package/dist/agent/index.js +0 -128
- package/dist/agent/session.d.ts +0 -93
- package/dist/agent/session.js +0 -149
- package/dist/agent/types.d.ts +0 -68
- package/dist/agent/types.js +0 -9
- package/dist/cli.cjs +0 -286329
- package/dist/client/durableWrites.d.ts +0 -21
- package/dist/client/httpClient.d.ts +0 -80
- package/dist/coordination/schema.d.ts +0 -722
- package/dist/coordination/schema.js +0 -578
- package/dist/schema/openapi.d.ts +0 -29
- package/dist/schema/openapi.js +0 -124
- package/dist/testing/fixtures/bootstrap.d.ts +0 -49
- package/dist/testing/fixtures/bootstrap.js +0 -59
- package/dist/testing/fixtures/deltas.d.ts +0 -83
- package/dist/testing/fixtures/deltas.js +0 -136
- package/dist/testing/fixtures/models.d.ts +0 -83
- package/dist/testing/fixtures/models.js +0 -272
- package/dist/testing/helpers/reactWrapper.d.ts +0 -69
- package/dist/testing/helpers/reactWrapper.js +0 -67
- package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
- package/dist/testing/helpers/syncEngineHarness.js +0 -73
- package/dist/testing/helpers/wait.d.ts +0 -30
- package/dist/testing/helpers/wait.js +0 -49
- package/dist/testing/index.d.ts +0 -23
- package/dist/testing/index.js +0 -33
- package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
- package/dist/testing/mocks/FakeDatabase.js +0 -10
- package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
- package/dist/testing/mocks/MockMutationExecutor.js +0 -192
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
- package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
- package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
- package/dist/testing/mocks/MockSyncContext.js +0 -71
- package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
- package/dist/testing/mocks/MockSyncStore.js +0 -171
- package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
- package/dist/testing/mocks/MockWebSocket.js +0 -118
- package/dist/transactions/durableWriteStore.js +0 -30
- package/dist/utils/duration.d.ts +0 -25
- package/dist/utils/json.js +0 -88
- package/dist/wire/errorEnvelope.d.ts +0 -55
- package/dist/wire/frames.d.ts +0 -197
- package/dist/wire/frames.js +0 -49
- package/dist/wire/listEnvelope.js +0 -18
- package/docs/interaction-model.md +0 -97
- /package/dist/{core → query}/QueryProcessor.d.ts +0 -0
- /package/dist/{core → query}/QueryProcessor.js +0 -0
- /package/dist/{core/storeContract.js → storeContract.js} +0 -0
- /package/dist/{core → stores}/openIDBWithTimeout.d.ts +0 -0
- /package/dist/{core → stores}/openIDBWithTimeout.js +0 -0
- /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
- /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
- /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
- /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
- /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
- /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
- /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
- /package/dist/{client → transaction}/persistence.d.ts +0 -0
- /package/dist/{client → transaction}/persistence.js +0 -0
- /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
- /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
- /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
- /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
- /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
- /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
- /package/dist/{types → transaction/types}/modelData.js +0 -0
- /package/dist/{types → transaction/types}/participant.d.ts +0 -0
- /package/dist/{types → transaction/types}/participant.js +0 -0
- /package/dist/{types → transaction/types}/streams.js +0 -0
- /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
- /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
- /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
- /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/protocol.js +0 -0
- /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
- /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
- /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
- /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
- /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
- /package/dist/{core → views}/ViewRegistry.js +0 -0
package/dist/sync/groupChange.js
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* Every handler takes a {@link GroupChangeContext}, the narrow facade through
|
|
10
10
|
* which it reaches the client's local storage and connection lifecycle hooks.
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
12
|
+
import { globalRuntime } from '../context.js';
|
|
13
|
+
/** The context's runtime, falling back to the module-global bridge. */
|
|
14
|
+
const runtimeOf = (ctx) => ctx.runtime ?? globalRuntime;
|
|
13
15
|
/**
|
|
14
16
|
* Marker returned when a group-change payload cannot be parsed, kept distinct
|
|
15
17
|
* from a valid null or absent payload, which the handlers accept normally.
|
|
@@ -22,14 +24,14 @@ const MALFORMED_PAYLOAD = Symbol('malformed-group-change-payload');
|
|
|
22
24
|
* would leave the delta pipeline after the watermark has already advanced. The
|
|
23
25
|
* delta is never re-delivered, so the security clear it carried would be lost.
|
|
24
26
|
*/
|
|
25
|
-
function parseGroupChangePayload(delta) {
|
|
27
|
+
function parseGroupChangePayload(delta, runtime) {
|
|
26
28
|
if (typeof delta.data !== 'string')
|
|
27
29
|
return delta.data;
|
|
28
30
|
try {
|
|
29
31
|
return JSON.parse(delta.data);
|
|
30
32
|
}
|
|
31
33
|
catch (error) {
|
|
32
|
-
|
|
34
|
+
runtime.logger.debug('[BaseSyncedStore] Malformed group-change payload', {
|
|
33
35
|
syncId: delta.id,
|
|
34
36
|
actionType: delta.actionType,
|
|
35
37
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -44,7 +46,7 @@ function parseGroupChangePayload(delta) {
|
|
|
44
46
|
* re-bootstrap from the server.
|
|
45
47
|
*/
|
|
46
48
|
async function clearForUnknownGroupChange(ctx, delta, kind) {
|
|
47
|
-
|
|
49
|
+
runtimeOf(ctx).logger.debug(`[BaseSyncedStore] Unreadable ${kind} payload — clearing cached data and re-bootstrapping`, { syncId: delta.id });
|
|
48
50
|
// Revoked data must not persist if the device goes offline before the
|
|
49
51
|
// re-bootstrap, the same reasoning as the explicit removed-groups path.
|
|
50
52
|
await ctx.database.clear();
|
|
@@ -64,7 +66,7 @@ async function clearForUnknownGroupChange(ctx, delta, kind) {
|
|
|
64
66
|
* and refetch), clearing cached data first if any group was removed.
|
|
65
67
|
*/
|
|
66
68
|
export async function handleSyncGroupChange(ctx, delta) {
|
|
67
|
-
const raw = parseGroupChangePayload(delta);
|
|
69
|
+
const raw = parseGroupChangePayload(delta, runtimeOf(ctx));
|
|
68
70
|
if (raw === MALFORMED_PAYLOAD) {
|
|
69
71
|
// The payload is unreadable, so we cannot tell which groups changed, and
|
|
70
72
|
// this delta will never be re-delivered because the watermark has already
|
|
@@ -88,7 +90,7 @@ export async function handleSyncGroupChange(ctx, delta) {
|
|
|
88
90
|
removedGroups: rawObj.removedGroups ?? [],
|
|
89
91
|
addedGroups: rawObj.addedGroups ?? [],
|
|
90
92
|
};
|
|
91
|
-
|
|
93
|
+
runtimeOf(ctx).logger.info('[BaseSyncedStore] Sync group change received (legacy)', {
|
|
92
94
|
removedGroups: payload.removedGroups,
|
|
93
95
|
addedGroups: payload.addedGroups,
|
|
94
96
|
syncId: delta.id,
|
|
@@ -99,7 +101,7 @@ export async function handleSyncGroupChange(ctx, delta) {
|
|
|
99
101
|
if (payload.removedGroups.length > 0) {
|
|
100
102
|
await ctx.database.clear();
|
|
101
103
|
ctx.objectPool.clear();
|
|
102
|
-
|
|
104
|
+
runtimeOf(ctx).logger.info('[BaseSyncedStore] Cleared cached data due to revoked sync groups', {
|
|
103
105
|
removedGroups: payload.removedGroups,
|
|
104
106
|
});
|
|
105
107
|
}
|
|
@@ -114,7 +116,7 @@ export async function handleSyncGroupChange(ctx, delta) {
|
|
|
114
116
|
* through the normal insert path.
|
|
115
117
|
*/
|
|
116
118
|
export async function handleGroupAdded(ctx, payload, syncId) {
|
|
117
|
-
|
|
119
|
+
runtimeOf(ctx).logger.info('[BaseSyncedStore] Group added (incremental)', {
|
|
118
120
|
group: payload.group,
|
|
119
121
|
syncId,
|
|
120
122
|
});
|
|
@@ -130,7 +132,7 @@ export async function handleGroupAdded(ctx, payload, syncId) {
|
|
|
130
132
|
* local state and forces a re-bootstrap with the updated group list.
|
|
131
133
|
*/
|
|
132
134
|
export async function handleGroupRemoved(ctx, delta) {
|
|
133
|
-
const raw = parseGroupChangePayload(delta);
|
|
135
|
+
const raw = parseGroupChangePayload(delta, runtimeOf(ctx));
|
|
134
136
|
if (raw === MALFORMED_PAYLOAD) {
|
|
135
137
|
// The payload is unreadable: access was revoked but we cannot tell which
|
|
136
138
|
// group. Fall back to a full clear, the safe direction for an
|
|
@@ -141,12 +143,12 @@ export async function handleGroupRemoved(ctx, delta) {
|
|
|
141
143
|
const rawObj = (raw ?? {});
|
|
142
144
|
const groupKey = typeof rawObj.group === 'string' ? rawObj.group : undefined;
|
|
143
145
|
if (!groupKey) {
|
|
144
|
-
|
|
146
|
+
runtimeOf(ctx).logger.debug('[BaseSyncedStore] Group removed delta missing group key', {
|
|
145
147
|
syncId: delta.id,
|
|
146
148
|
});
|
|
147
149
|
return;
|
|
148
150
|
}
|
|
149
|
-
|
|
151
|
+
runtimeOf(ctx).logger.info('[BaseSyncedStore] Group removed', {
|
|
150
152
|
group: groupKey,
|
|
151
153
|
syncId: delta.id,
|
|
152
154
|
});
|
|
@@ -181,7 +183,7 @@ export function computeUpdatedSyncGroups(ctx, payload) {
|
|
|
181
183
|
*/
|
|
182
184
|
export function forceFullRebootstrap(ctx) {
|
|
183
185
|
if (ctx.getBootstrapMode() === 'none') {
|
|
184
|
-
|
|
186
|
+
runtimeOf(ctx).logger.info('[BaseSyncedStore] forceFullRebootstrap skipped (bootstrapMode=none)');
|
|
185
187
|
return;
|
|
186
188
|
}
|
|
187
189
|
ctx.database.markRequiresFullBootstrap();
|
|
@@ -219,7 +221,7 @@ export async function checkSyncGroupShrinkage(ctx) {
|
|
|
219
221
|
const currentGroups = new Set(currentSyncGroups);
|
|
220
222
|
const removedGroups = stored.filter((g) => !currentGroups.has(g));
|
|
221
223
|
if (removedGroups.length > 0) {
|
|
222
|
-
|
|
224
|
+
runtimeOf(ctx).logger.info('[BaseSyncedStore] Sync groups shrank — forcing full bootstrap', {
|
|
223
225
|
removedGroups,
|
|
224
226
|
storedCount: stored.length,
|
|
225
227
|
currentCount: currentGroups.size,
|
|
@@ -235,7 +237,7 @@ export async function checkSyncGroupShrinkage(ctx) {
|
|
|
235
237
|
});
|
|
236
238
|
}
|
|
237
239
|
catch (error) {
|
|
238
|
-
|
|
240
|
+
runtimeOf(ctx).logger.debug('[BaseSyncedStore] Failed to check sync group shrinkage', {
|
|
239
241
|
error: error instanceof Error ? error.message : String(error),
|
|
240
242
|
});
|
|
241
243
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { JoinOptions } from '../transaction/resources/modelOperations.js';
|
|
1
2
|
import type { SyncWebSocket } from './SyncWebSocket.js';
|
|
2
|
-
import type { Schema } from '../schema/schema.js';
|
|
3
|
-
import type { Claim, Activity, ClaimTarget, ClaimStream, Peer, PresenceStream, PresenceTarget } from '../types/streams.js';
|
|
3
|
+
import type { Schema } from '../transaction/schema/schema.js';
|
|
4
|
+
import type { Claim, Activity, ClaimTarget, ClaimStream, Peer, PresenceStream, PresenceTarget } from '../transaction/types/streams.js';
|
|
4
5
|
import type { AttachableClaimStream } from './createClaimStream.js';
|
|
5
6
|
/**
|
|
6
7
|
* The scope a participant can be joined to. The usual form is an entity target
|
|
@@ -17,7 +18,13 @@ export interface EngineParticipant {
|
|
|
17
18
|
readonly presence: PresenceStream;
|
|
18
19
|
readonly claims: ClaimStream;
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The options for a participant join. It extends the public per-model
|
|
23
|
+
* {@link JoinOptions} rather than restating its members, so the lease dial is
|
|
24
|
+
* declared once, in the core, and this surface adds only what a lower-level
|
|
25
|
+
* join can additionally say.
|
|
26
|
+
*/
|
|
27
|
+
export interface ParticipantJoinOptions extends JoinOptions {
|
|
21
28
|
/**
|
|
22
29
|
* The initial focus target, named in your schema's vocabulary and optionally
|
|
23
30
|
* narrowed to a path, field, or range. When `scope` is omitted, this target
|
|
@@ -34,7 +41,17 @@ export interface ParticipantJoinOptions {
|
|
|
34
41
|
readonly scope?: ParticipantScope;
|
|
35
42
|
/** Present a narrower capability for this logical participant. */
|
|
36
43
|
readonly capabilityToken?: string;
|
|
37
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* @deprecated Use `ttl`. Removed in 0.37.0.
|
|
46
|
+
*
|
|
47
|
+
* One lease, spelled two ways, and the seconds spelling was the one that
|
|
48
|
+
* misled: it accepted a duration string, so `ablo.<model>.join(ids, { ttl:
|
|
49
|
+
* '5m' })` reached this surface as `ttlSeconds: '5m'` — a field whose name
|
|
50
|
+
* asserts a unit its value did not carry. `ttl` takes the same values and is
|
|
51
|
+
* the spelling every other lease in the SDK already uses (`claim`'s `ttl`,
|
|
52
|
+
* `ClaimLeaseOptions.ttl`). The wire is unchanged: it has always carried
|
|
53
|
+
* seconds, and still does.
|
|
54
|
+
*/
|
|
38
55
|
readonly ttlSeconds?: number | string | null;
|
|
39
56
|
/**
|
|
40
57
|
* The activity to announce as soon as the claim is acknowledged. Defaults to
|
|
@@ -64,7 +81,7 @@ export interface ScopedClaimOptions {
|
|
|
64
81
|
/** Peer-visible description of the work. Defaults to `'editing'`. */
|
|
65
82
|
readonly description?: string;
|
|
66
83
|
/** How long the claim lives; the server expires it automatically after this. */
|
|
67
|
-
readonly ttl?: import('../types/streams.js').Duration;
|
|
84
|
+
readonly ttl?: import('../transaction/types/streams.js').Duration;
|
|
68
85
|
}
|
|
69
86
|
export interface ScopedClaims {
|
|
70
87
|
readonly focus: ClaimTarget | null;
|
|
@@ -102,7 +119,8 @@ export interface ParticipantManager {
|
|
|
102
119
|
}
|
|
103
120
|
export interface ParticipantManagerConfig {
|
|
104
121
|
readonly ready: () => Promise<void>;
|
|
105
|
-
|
|
122
|
+
/** The connection, host-built and stable for the client's lifetime. */
|
|
123
|
+
readonly transport: SyncWebSocket;
|
|
106
124
|
readonly presence: PresenceStream;
|
|
107
125
|
readonly claims: AttachableClaimStream;
|
|
108
126
|
readonly schema?: Schema;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { scopeKindOf } from '../schema/model.js';
|
|
2
|
-
import {
|
|
1
|
+
import { scopeKindOf } from '../transaction/schema/model.js';
|
|
2
|
+
import { AbloValidationError } from '../transaction/errors.js';
|
|
3
|
+
import { subTarget, streamTarget, wireTarget, } from '../transaction/coordination/index.js';
|
|
3
4
|
export function createParticipantManager(config) {
|
|
4
5
|
return {
|
|
5
6
|
async join(input, overrides) {
|
|
@@ -9,15 +10,16 @@ export function createParticipantManager(config) {
|
|
|
9
10
|
: null;
|
|
10
11
|
const syncGroups = unique(resolveParticipantSyncGroups(options.scope ?? target ?? undefined, config.schema));
|
|
11
12
|
await config.ready();
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
13
|
+
// Not-connected joins surface through `sendClaim`'s diagnosed
|
|
14
|
+
// rejection below; a scopeless join needs no wire send at all.
|
|
15
|
+
const transport = config.transport;
|
|
16
16
|
const claimId = createParticipantClaimId();
|
|
17
17
|
if (syncGroups.length > 0) {
|
|
18
18
|
await transport.sendClaim(claimId, syncGroups, {
|
|
19
19
|
capabilityToken: options.capabilityToken,
|
|
20
|
-
ttlSeconds
|
|
20
|
+
// `ttl` is the spelling; `ttlSeconds` is the deprecated one, read
|
|
21
|
+
// second so a caller passing both gets the current name honored.
|
|
22
|
+
ttlSeconds: parseParticipantTtlSeconds(options.ttl ?? options.ttlSeconds),
|
|
21
23
|
});
|
|
22
24
|
}
|
|
23
25
|
const participant = createJoinedParticipant({
|
|
@@ -74,15 +76,30 @@ export function resolveParticipantSyncGroups(scope, schema) {
|
|
|
74
76
|
}
|
|
75
77
|
return out;
|
|
76
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* The group kind for a model, in the wire dialect every plane shares: a
|
|
81
|
+
* declared scope root wins; otherwise the lowercased typename — the same
|
|
82
|
+
* token the commit plane and claim targets use (`wireModel`). Never the
|
|
83
|
+
* camelCase schema key: the server validates inbound subscription groups
|
|
84
|
+
* against a lowercase-only grammar, so a key like `reportBlocks` would be
|
|
85
|
+
* rejected as malformed on subscribe — and even a lowercase key would put
|
|
86
|
+
* this client in a different group than a peer who resolved the same row
|
|
87
|
+
* through an entity ref, so the two would never see each other's claims.
|
|
88
|
+
*/
|
|
89
|
+
function groupKindForModel(def, key) {
|
|
90
|
+
return scopeKindOf(def, key) ?? (def.typename ?? key).toLowerCase();
|
|
91
|
+
}
|
|
77
92
|
export function syncGroupFromEntityRef(ref, schema) {
|
|
78
93
|
const match = findModelForEntityRef(ref, schema);
|
|
79
|
-
const kind = match
|
|
80
|
-
|
|
94
|
+
const kind = match
|
|
95
|
+
? groupKindForModel(match.def, match.key)
|
|
96
|
+
: ref.type.toLowerCase();
|
|
97
|
+
return `${kind}:${ref.id}`;
|
|
81
98
|
}
|
|
82
99
|
function syncGroupFromSchemaKey(schemaKey, id, schema) {
|
|
83
100
|
const def = schema?.models?.[schemaKey];
|
|
84
|
-
const kind = def ?
|
|
85
|
-
return `${kind
|
|
101
|
+
const kind = def ? groupKindForModel(def, schemaKey) : schemaKey.toLowerCase();
|
|
102
|
+
return `${kind}:${id}`;
|
|
86
103
|
}
|
|
87
104
|
function findModelForEntityRef(ref, schema) {
|
|
88
105
|
if (!schema?.models)
|
|
@@ -296,12 +313,8 @@ function createJoinedParticipant(args) {
|
|
|
296
313
|
}
|
|
297
314
|
function activityFromTarget(target) {
|
|
298
315
|
return {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
path: target.path,
|
|
302
|
-
range: target.range,
|
|
303
|
-
field: target.field,
|
|
304
|
-
meta: target.meta,
|
|
316
|
+
...wireTarget(target),
|
|
317
|
+
...subTarget(target),
|
|
305
318
|
};
|
|
306
319
|
}
|
|
307
320
|
function presenceMatchesParticipant(entry, target, syncGroups) {
|
|
@@ -310,12 +323,8 @@ function presenceMatchesParticipant(entry, target, syncGroups) {
|
|
|
310
323
|
if (!target)
|
|
311
324
|
return true;
|
|
312
325
|
return targetsOverlap({
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
path: entry.activity.path,
|
|
316
|
-
range: entry.activity.range,
|
|
317
|
-
field: entry.activity.field,
|
|
318
|
-
meta: entry.activity.meta,
|
|
326
|
+
...streamTarget(entry.activity),
|
|
327
|
+
...subTarget(entry.activity),
|
|
319
328
|
}, target);
|
|
320
329
|
}
|
|
321
330
|
function targetsOverlap(a, b) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The semantic schema-drift classifier — the question that matters is not
|
|
3
|
+
* "did the schema change at all?" (one whole-schema hash answers that, and
|
|
4
|
+
* welds every client to every push) but "does THIS client use anything that
|
|
5
|
+
* changed?". This module compares only the models the client declares against
|
|
6
|
+
* the server's per-model surface (`GET /api/schema`), so:
|
|
7
|
+
*
|
|
8
|
+
* - a purely additive server change (models this build never references) is
|
|
9
|
+
* SILENCE — deployed clients don't care what they don't use;
|
|
10
|
+
* - a model this build declares that the server doesn't have is named, with
|
|
11
|
+
* the push as the fix;
|
|
12
|
+
* - a shared model whose content differs is named, so "which field moved"
|
|
13
|
+
* is one `ablo status` away instead of a hash-guessing game.
|
|
14
|
+
*
|
|
15
|
+
* Pure and transport-free; the BootstrapFetcher owns fetching the surface.
|
|
16
|
+
*/
|
|
17
|
+
/** One model as the server's schema read-back reports it. */
|
|
18
|
+
export interface ServerSchemaModel {
|
|
19
|
+
readonly key: string;
|
|
20
|
+
/** Per-model content hash; absent on servers older than this check. */
|
|
21
|
+
readonly hash?: string;
|
|
22
|
+
}
|
|
23
|
+
export type SchemaDriftFinding =
|
|
24
|
+
/** Every model this client declares exists server-side with matching content
|
|
25
|
+
* (the server may know more — that's an additive lead, not drift). */
|
|
26
|
+
{
|
|
27
|
+
readonly kind: 'aligned';
|
|
28
|
+
}
|
|
29
|
+
/** Models this build declares that the server has no idea about — writes to
|
|
30
|
+
* them will be declined until the schema is pushed. */
|
|
31
|
+
| {
|
|
32
|
+
readonly kind: 'unpushed';
|
|
33
|
+
readonly models: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/** Shared models whose content differs between this build and the server
|
|
36
|
+
* (may also carry unpushed models found alongside). */
|
|
37
|
+
| {
|
|
38
|
+
readonly kind: 'changed';
|
|
39
|
+
readonly models: readonly string[];
|
|
40
|
+
readonly unpushed: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
/** The server surface carries no per-model hashes (older server) — the
|
|
43
|
+
* caller falls back to the whole-hash comparison. */
|
|
44
|
+
| {
|
|
45
|
+
readonly kind: 'unknown';
|
|
46
|
+
};
|
|
47
|
+
export declare function classifySchemaDrift(clientModels: Readonly<Record<string, string>>, serverModels: readonly ServerSchemaModel[]): SchemaDriftFinding;
|
|
48
|
+
/**
|
|
49
|
+
* The warning for a real, named divergence. Calm and specific: which models,
|
|
50
|
+
* what that means for this client, and the one next step. Never speaks about
|
|
51
|
+
* hashes — the point of the semantic check is that nobody has to compare hex.
|
|
52
|
+
*/
|
|
53
|
+
export declare function describeSchemaDrift(finding: Extract<SchemaDriftFinding, {
|
|
54
|
+
kind: 'unpushed' | 'changed';
|
|
55
|
+
}>, serverLabel: string): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The semantic schema-drift classifier — the question that matters is not
|
|
3
|
+
* "did the schema change at all?" (one whole-schema hash answers that, and
|
|
4
|
+
* welds every client to every push) but "does THIS client use anything that
|
|
5
|
+
* changed?". This module compares only the models the client declares against
|
|
6
|
+
* the server's per-model surface (`GET /api/schema`), so:
|
|
7
|
+
*
|
|
8
|
+
* - a purely additive server change (models this build never references) is
|
|
9
|
+
* SILENCE — deployed clients don't care what they don't use;
|
|
10
|
+
* - a model this build declares that the server doesn't have is named, with
|
|
11
|
+
* the push as the fix;
|
|
12
|
+
* - a shared model whose content differs is named, so "which field moved"
|
|
13
|
+
* is one `ablo status` away instead of a hash-guessing game.
|
|
14
|
+
*
|
|
15
|
+
* Pure and transport-free; the BootstrapFetcher owns fetching the surface.
|
|
16
|
+
*/
|
|
17
|
+
export function classifySchemaDrift(clientModels, serverModels) {
|
|
18
|
+
if (serverModels.length > 0 && serverModels.every((m) => !m.hash)) {
|
|
19
|
+
return { kind: 'unknown' };
|
|
20
|
+
}
|
|
21
|
+
const server = new Map(serverModels.map((m) => [m.key, m.hash]));
|
|
22
|
+
const unpushed = [];
|
|
23
|
+
const changed = [];
|
|
24
|
+
for (const [key, hash] of Object.entries(clientModels)) {
|
|
25
|
+
const serverHash = server.get(key);
|
|
26
|
+
if (serverHash === undefined)
|
|
27
|
+
unpushed.push(key);
|
|
28
|
+
else if (serverHash !== hash)
|
|
29
|
+
changed.push(key);
|
|
30
|
+
}
|
|
31
|
+
if (changed.length > 0)
|
|
32
|
+
return { kind: 'changed', models: changed, unpushed };
|
|
33
|
+
if (unpushed.length > 0)
|
|
34
|
+
return { kind: 'unpushed', models: unpushed };
|
|
35
|
+
return { kind: 'aligned' };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The warning for a real, named divergence. Calm and specific: which models,
|
|
39
|
+
* what that means for this client, and the one next step. Never speaks about
|
|
40
|
+
* hashes — the point of the semantic check is that nobody has to compare hex.
|
|
41
|
+
*/
|
|
42
|
+
export function describeSchemaDrift(finding, serverLabel) {
|
|
43
|
+
if (finding.kind === 'unpushed') {
|
|
44
|
+
return (`Ablo: This build declares models the server at ${serverLabel} doesn't have yet ` +
|
|
45
|
+
`(${finding.models.join(', ')}). Writes to them will be declined until the schema is ` +
|
|
46
|
+
`pushed — run \`ablo push\` (and \`ablo status\` to confirm it targets this server).`);
|
|
47
|
+
}
|
|
48
|
+
const alsoUnpushed = finding.unpushed.length > 0 ? ` (${finding.unpushed.join(', ')} not pushed yet)` : '';
|
|
49
|
+
return (`Ablo: These models differ between this build and the server at ${serverLabel}: ` +
|
|
50
|
+
`${finding.models.join(', ')}${alsoUnpushed}. Reads and writes touching what changed may be ` +
|
|
51
|
+
`declined — \`ablo status\` shows the deployed shape; pushing your schema or deploying a ` +
|
|
52
|
+
`current build aligns them.`);
|
|
53
|
+
}
|
package/dist/sync/schemas.d.ts
CHANGED
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
* Zod validation schemas for sync engine server responses.
|
|
3
3
|
*
|
|
4
4
|
* Validates data at the fetch boundary before it enters the sync engine.
|
|
5
|
-
*
|
|
5
|
+
* Unknown keys are kept, so a server that adds a field does not break a client
|
|
6
|
+
* that predates it.
|
|
6
7
|
*/
|
|
7
8
|
import { z } from 'zod';
|
|
9
|
+
import type { RuntimeContext } from "../RuntimeContext.js";
|
|
10
|
+
/**
|
|
11
|
+
* A delta as it arrives in a bootstrap payload.
|
|
12
|
+
*
|
|
13
|
+
* The bootstrap routes return the same rows the broadcast path does, so the
|
|
14
|
+
* fields are taken from {@link syncDeltaWireCoreSchema} rather than restated
|
|
15
|
+
* here — a delta is one shape, and this is the reader for it, not a second
|
|
16
|
+
* definition of it. Unknown keys are kept, because the server sends its own
|
|
17
|
+
* wider projection (attribution, `projectId`) that later stages may read.
|
|
18
|
+
*/
|
|
8
19
|
export declare const ServerDeltaSchema: z.ZodObject<{
|
|
9
20
|
id: z.ZodNumber;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
U: "U";
|
|
13
|
-
D: "D";
|
|
14
|
-
A: "A";
|
|
15
|
-
V: "V";
|
|
16
|
-
C: "C";
|
|
17
|
-
G: "G";
|
|
18
|
-
S: "S";
|
|
19
|
-
}>>;
|
|
20
|
-
action: z.ZodOptional<z.ZodEnum<{
|
|
21
|
+
data: z.ZodNullable<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodString]>>;
|
|
22
|
+
actionType: z.ZodEnum<{
|
|
21
23
|
I: "I";
|
|
22
24
|
U: "U";
|
|
23
25
|
D: "D";
|
|
@@ -26,33 +28,22 @@ export declare const ServerDeltaSchema: z.ZodObject<{
|
|
|
26
28
|
C: "C";
|
|
27
29
|
G: "G";
|
|
28
30
|
S: "S";
|
|
29
|
-
}
|
|
31
|
+
}>;
|
|
30
32
|
modelName: z.ZodString;
|
|
31
|
-
|
|
32
|
-
modelId: z.ZodOptional<z.ZodString>;
|
|
33
|
-
data: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
33
|
+
modelId: z.ZodString;
|
|
34
34
|
}, z.core.$loose>;
|
|
35
35
|
export type ValidatedServerDelta = z.infer<typeof ServerDeltaSchema>;
|
|
36
36
|
export declare const BootstrapResponseSchema: z.ZodObject<{
|
|
37
37
|
type: z.ZodEnum<{
|
|
38
|
-
partial: "partial";
|
|
39
38
|
full: "full";
|
|
39
|
+
partial: "partial";
|
|
40
40
|
}>;
|
|
41
41
|
lastSyncId: z.ZodNumber;
|
|
42
42
|
models: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodPipe<z.ZodUnion<readonly [z.ZodArray<z.ZodUnknown>, z.ZodString, z.ZodNull]>, z.ZodTransform<unknown[], string | unknown[] | null>>>>;
|
|
43
43
|
deltas: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
44
44
|
id: z.ZodNumber;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
U: "U";
|
|
48
|
-
D: "D";
|
|
49
|
-
A: "A";
|
|
50
|
-
V: "V";
|
|
51
|
-
C: "C";
|
|
52
|
-
G: "G";
|
|
53
|
-
S: "S";
|
|
54
|
-
}>>;
|
|
55
|
-
action: z.ZodOptional<z.ZodEnum<{
|
|
45
|
+
data: z.ZodNullable<z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodString]>>;
|
|
46
|
+
actionType: z.ZodEnum<{
|
|
56
47
|
I: "I";
|
|
57
48
|
U: "U";
|
|
58
49
|
D: "D";
|
|
@@ -61,16 +52,15 @@ export declare const BootstrapResponseSchema: z.ZodObject<{
|
|
|
61
52
|
C: "C";
|
|
62
53
|
G: "G";
|
|
63
54
|
S: "S";
|
|
64
|
-
}
|
|
55
|
+
}>;
|
|
65
56
|
modelName: z.ZodString;
|
|
66
|
-
|
|
67
|
-
modelId: z.ZodOptional<z.ZodString>;
|
|
68
|
-
data: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
57
|
+
modelId: z.ZodString;
|
|
69
58
|
}, z.core.$loose>>>;
|
|
70
59
|
deltaCount: z.ZodOptional<z.ZodNumber>;
|
|
71
60
|
failedModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
72
61
|
timestamp: z.ZodDefault<z.ZodNumber>;
|
|
73
62
|
schemaHash: z.ZodOptional<z.ZodString>;
|
|
63
|
+
nextCursor: z.ZodOptional<z.ZodString>;
|
|
74
64
|
}, z.core.$loose>;
|
|
75
65
|
export type ValidatedBootstrapResponse = z.infer<typeof BootstrapResponseSchema>;
|
|
76
66
|
/**
|
|
@@ -78,4 +68,4 @@ export type ValidatedBootstrapResponse = z.infer<typeof BootstrapResponseSchema>
|
|
|
78
68
|
* result. On failure it records a diagnostic breadcrumb and throws an
|
|
79
69
|
* {@link AbloValidationError} describing which fields were invalid.
|
|
80
70
|
*/
|
|
81
|
-
export declare function parseBootstrapResponse(raw: unknown): ValidatedBootstrapResponse;
|
|
71
|
+
export declare function parseBootstrapResponse(raw: unknown, runtime?: RuntimeContext): ValidatedBootstrapResponse;
|
package/dist/sync/schemas.js
CHANGED
|
@@ -2,27 +2,32 @@
|
|
|
2
2
|
* Zod validation schemas for sync engine server responses.
|
|
3
3
|
*
|
|
4
4
|
* Validates data at the fetch boundary before it enters the sync engine.
|
|
5
|
-
*
|
|
5
|
+
* Unknown keys are kept, so a server that adds a field does not break a client
|
|
6
|
+
* that predates it.
|
|
6
7
|
*/
|
|
7
8
|
import { z } from 'zod';
|
|
8
|
-
import {
|
|
9
|
-
import { AbloValidationError } from "../errors.js";
|
|
10
|
-
|
|
11
|
-
// The action codes a server delta can carry, matching the wire protocol's
|
|
12
|
-
// action-type set.
|
|
13
|
-
const SYNC_ACTION_VALUES = ['I', 'U', 'D', 'A', 'C', 'G', 'S', 'V'];
|
|
9
|
+
import { globalRuntime } from "../context.js";
|
|
10
|
+
import { AbloValidationError } from "../transaction/errors.js";
|
|
11
|
+
import { syncDeltaWireCoreSchema } from '../transaction/wire/delta.js';
|
|
14
12
|
// ─── Server Delta Schema ─────────────────────────────────────────────────────
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
/**
|
|
14
|
+
* A delta as it arrives in a bootstrap payload.
|
|
15
|
+
*
|
|
16
|
+
* The bootstrap routes return the same rows the broadcast path does, so the
|
|
17
|
+
* fields are taken from {@link syncDeltaWireCoreSchema} rather than restated
|
|
18
|
+
* here — a delta is one shape, and this is the reader for it, not a second
|
|
19
|
+
* definition of it. Unknown keys are kept, because the server sends its own
|
|
20
|
+
* wider projection (attribution, `projectId`) that later stages may read.
|
|
21
|
+
*/
|
|
22
|
+
export const ServerDeltaSchema = syncDeltaWireCoreSchema
|
|
23
|
+
.pick({
|
|
24
|
+
id: true,
|
|
25
|
+
actionType: true,
|
|
26
|
+
modelName: true,
|
|
27
|
+
modelId: true,
|
|
28
|
+
data: true,
|
|
24
29
|
})
|
|
25
|
-
.
|
|
30
|
+
.loose();
|
|
26
31
|
// ─── Model Value Schema ─────────────────────────────────────────────────────
|
|
27
32
|
// A model's values can arrive in more than one shape depending on how the
|
|
28
33
|
// server serialized them:
|
|
@@ -60,19 +65,23 @@ export const BootstrapResponseSchema = z
|
|
|
60
65
|
// absent when the server predates this field or the tenant has never
|
|
61
66
|
// pushed a schema.
|
|
62
67
|
schemaHash: z.string().optional(),
|
|
68
|
+
// Present when a paged single-model request stopped at its row limit
|
|
69
|
+
// with rows remaining: pass it back as the next page's cursor. Absent
|
|
70
|
+
// on the final page, on unpaged responses, and from older servers.
|
|
71
|
+
nextCursor: z.string().optional(),
|
|
63
72
|
})
|
|
64
|
-
.
|
|
73
|
+
.loose();
|
|
65
74
|
// ─── Parse Helpers ───────────────────────────────────────────────────────────
|
|
66
75
|
/**
|
|
67
76
|
* Validates a raw bootstrap response from the server and returns the typed
|
|
68
77
|
* result. On failure it records a diagnostic breadcrumb and throws an
|
|
69
78
|
* {@link AbloValidationError} describing which fields were invalid.
|
|
70
79
|
*/
|
|
71
|
-
export function parseBootstrapResponse(raw) {
|
|
80
|
+
export function parseBootstrapResponse(raw, runtime = globalRuntime) {
|
|
72
81
|
const result = BootstrapResponseSchema.safeParse(raw);
|
|
73
82
|
if (!result.success) {
|
|
74
83
|
const issues = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');
|
|
75
|
-
|
|
84
|
+
runtime.observability.breadcrumb('Bootstrap response validation failed', 'sync.bootstrap', 'error', {
|
|
76
85
|
issues,
|
|
77
86
|
rawType: typeof raw,
|
|
78
87
|
rawKeys: raw && typeof raw === 'object' ? Object.keys(raw).join(',') : 'n/a',
|
package/dist/sync/syncPlan.d.ts
CHANGED
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
* object pool, and the enrichment rules that attach related parents to
|
|
6
6
|
* incoming rows. See {@link deriveSyncPlanFromSchema}.
|
|
7
7
|
*/
|
|
8
|
-
import type { Schema } from '../schema/schema.js';
|
|
8
|
+
import type { Schema } from '../transaction/schema/schema.js';
|
|
9
9
|
/** A foreign-key index to register on the in-memory object pool when the store is constructed. */
|
|
10
10
|
export interface ForeignKeyIndexSpec {
|
|
11
11
|
/**
|
|
12
12
|
* The name of the child model, where the foreign-key field lives, and the
|
|
13
13
|
* name the object pool indexes by. Use the wire type-name casing (for
|
|
14
|
-
* example `'
|
|
14
|
+
* example `'Block'`, not `'block'`), since that is the value
|
|
15
15
|
* stamped onto reconstructed models and the key the pool looks up.
|
|
16
16
|
*/
|
|
17
17
|
readonly modelName: string;
|
|
18
|
-
/** The foreign-key field name on the child model, for example `'
|
|
18
|
+
/** The foreign-key field name on the child model, for example `'sectionId'`. */
|
|
19
19
|
readonly fieldName: string;
|
|
20
20
|
}
|
|
21
21
|
/**
|