@abloatai/ablo 0.34.1 → 0.35.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 +674 -5
- package/README.md +39 -22
- package/dist/BaseSyncedStore.d.ts +152 -44
- package/dist/BaseSyncedStore.js +300 -184
- package/dist/Database.d.ts +9 -24
- package/dist/Database.js +37 -22
- package/dist/InstanceCache.d.ts +25 -4
- package/dist/InstanceCache.js +48 -15
- package/dist/LazyReferenceCollection.d.ts +3 -3
- package/dist/LazyReferenceCollection.js +4 -4
- package/dist/Model.d.ts +6 -6
- package/dist/Model.js +10 -10
- package/dist/ModelRegistry.d.ts +4 -4
- package/dist/ModelRegistry.js +3 -3
- package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
- package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
- package/dist/SyncClient.d.ts +42 -32
- package/dist/SyncClient.js +166 -110
- 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/cli.cjs +3344 -1073
- package/dist/client/Ablo.d.ts +42 -287
- package/dist/client/Ablo.js +118 -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 +4 -4
- package/dist/client/createInternalComponents.js +9 -8
- package/dist/client/createModelProxy.d.ts +78 -373
- package/dist/client/createModelProxy.js +114 -86
- package/dist/client/humans.d.ts +48 -0
- package/dist/client/humans.js +52 -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 +48 -0
- package/dist/client/reactiveEngine.js +910 -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/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 +9 -9
- package/dist/context.js +10 -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/DatabaseManager.js +1 -1
- package/dist/core/QueryView.d.ts +1 -1
- package/dist/core/QueryView.js +1 -1
- package/dist/core/StoreManager.d.ts +4 -23
- package/dist/core/StoreManager.js +5 -55
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/core/storeContract.d.ts +2 -2
- package/dist/docs/catalog.d.ts +72 -0
- package/dist/docs/catalog.js +227 -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 +40 -34
- package/dist/index.js +26 -20
- 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 +2 -2
- package/dist/query/client.js +4 -4
- package/dist/query/types.d.ts +6 -41
- package/dist/query/types.js +2 -2
- package/dist/react/AbloProvider.d.ts +6 -8
- package/dist/react/AbloProvider.js +5 -7
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js +1 -1
- package/dist/react/index.d.ts +5 -5
- package/dist/react/index.js +3 -3
- package/dist/react/internalContext.d.ts +1 -1
- package/dist/react/useAblo.d.ts +3 -3
- package/dist/react/useAblo.js +1 -1
- 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 +86 -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 +10 -10
- package/dist/schema/index.js +18 -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 +3 -3
- package/dist/schema/serialize.d.ts +15 -6
- package/dist/schema/serialize.js +17 -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/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/footprint.d.ts +111 -0
- package/dist/source/footprint.js +0 -0
- 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/stores/ObjectStore.d.ts +1 -1
- package/dist/stores/SyncActionStore.d.ts +1 -1
- package/dist/stores/SyncActionStore.js +2 -10
- 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 +123 -6
- package/dist/sync/BootstrapFetcher.js +492 -66
- package/dist/sync/ConnectionManager.d.ts +6 -198
- package/dist/sync/ConnectionManager.js +6 -677
- package/dist/sync/OnDemandLoader.d.ts +2 -2
- package/dist/sync/OnDemandLoader.js +60 -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/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 +1 -1
- package/dist/sync/participants.d.ts +5 -4
- package/dist/sync/participants.js +29 -22
- package/dist/sync/schemaDrift.d.ts +55 -0
- package/dist/sync/schemaDrift.js +53 -0
- package/dist/sync/schemas.d.ts +21 -32
- package/dist/sync/schemas.js +26 -17
- 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/testing/fixtures/bootstrap.d.ts +1 -1
- package/dist/testing/fixtures/deltas.d.ts +1 -1
- package/dist/testing/fixtures/httpResponses.d.ts +70 -0
- package/dist/testing/fixtures/httpResponses.js +90 -0
- package/dist/testing/fixtures/models.js +1 -1
- package/dist/testing/helpers/wait.js +1 -1
- package/dist/testing/mocks/MockMutationExecutor.d.ts +2 -2
- package/dist/testing/mocks/MockMutationExecutor.js +8 -14
- package/dist/testing/mocks/MockSyncContext.d.ts +11 -11
- package/dist/testing/mocks/MockSyncContext.js +10 -9
- package/dist/testing/mocks/MockSyncStore.js +1 -1
- package/dist/testing/mocks/MockWebSocket.d.ts +2 -2
- 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 +177 -0
- package/dist/transaction/auth/capability.js +199 -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 +49 -0
- package/dist/transaction/coordination/awaitClaimGrant.js +112 -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 +44 -0
- package/dist/transaction/coordination/locator.d.ts +83 -0
- package/dist/transaction/coordination/locator.js +82 -0
- package/dist/transaction/coordination/schema.d.ts +1473 -0
- package/dist/{coordination → transaction/coordination}/schema.js +490 -55
- package/dist/transaction/coordination/targetConflict.d.ts +2 -0
- package/dist/transaction/coordination/targetConflict.js +103 -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} +11 -11
- package/dist/{errorCodes.js → transaction/errorCodes.js} +35 -12
- package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
- package/dist/{errors.js → transaction/errors.js} +85 -16
- 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 +192 -0
- package/dist/transaction/plugin.js +87 -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 +266 -0
- package/dist/transaction/resources/httpResources.js +7 -0
- package/dist/transaction/resources/modelOperations.d.ts +319 -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 +85 -0
- package/dist/transaction/resources/where.js +70 -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 +5 -5
- package/dist/{schema → transaction/schema}/field.js +5 -5
- 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 +57 -0
- package/dist/transaction/schema/openapi.js +340 -0
- package/dist/{schema → transaction/schema}/relation.d.ts +14 -14
- 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 +12 -10
- package/dist/{schema → transaction/schema}/schema.js +4 -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 +4 -5
- 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} +10 -36
- 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/{client → transaction/transport}/httpClient.d.ts +59 -16
- package/dist/{client → transaction/transport}/httpClient.js +5 -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 +171 -85
- 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 +576 -0
- package/dist/transaction/transport/wsTransport.js +1017 -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 +63 -45
- 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 +351 -0
- package/dist/transaction/wire/accountResponses.js +255 -0
- package/dist/transaction/wire/auth.d.ts +49 -0
- package/dist/transaction/wire/auth.js +57 -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 +463 -0
- package/dist/transaction/wire/claims.js +229 -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 +177 -0
- package/dist/transaction/wire/feedEvent.js +39 -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 +552 -0
- package/dist/transaction/wire/inboundFrames.js +116 -0
- package/dist/transaction/wire/index.d.ts +50 -0
- package/dist/transaction/wire/index.js +74 -0
- package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
- package/dist/transaction/wire/listEnvelope.js +42 -0
- package/dist/transaction/wire/modelResponses.d.ts +85 -0
- package/dist/transaction/wire/modelResponses.js +43 -0
- package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +79 -38
- package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +110 -59
- 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} +16 -15
- package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +12 -12
- package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +11 -11
- package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +7 -7
- 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} +3 -3
- package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +4 -3
- package/dist/utils/mobxSetup.d.ts +1 -1
- package/dist/utils/mobxSetup.js +5 -2
- 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 +19 -12
- package/docs/api-keys.md +8 -4
- package/docs/api.md +22 -18
- package/docs/audit.md +2 -0
- package/docs/cli.md +31 -3
- package/docs/client-behavior.md +8 -6
- package/docs/concurrency-convention.md +30 -24
- package/docs/coordination.md +48 -38
- package/docs/data-sources.md +3 -1
- package/docs/debugging.md +5 -3
- 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 +45 -44
- package/docs/examples/server-agent.md +46 -26
- package/docs/groups.md +32 -29
- package/docs/guarantees.md +4 -2
- package/docs/how-it-works.md +9 -7
- package/docs/idempotency.md +126 -0
- package/docs/identity.md +58 -54
- package/docs/index.md +172 -86
- package/docs/integration-guide.md +17 -16
- package/docs/interaction-model.md +6 -4
- package/docs/mcp.md +41 -16
- package/docs/migration.md +63 -5
- package/docs/operating-on-your-database.md +3 -1
- package/docs/projects.md +2 -0
- package/docs/quickstart.md +22 -5
- package/docs/react.md +12 -10
- package/docs/schema-contract.md +5 -3
- package/docs/session-settings.md +108 -0
- package/docs/sessions.md +3 -1
- package/docs/webhooks.md +3 -1
- package/llms.txt +47 -17
- package/package.json +10 -8
- 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/client/durableWrites.d.ts +0 -21
- package/dist/coordination/schema.d.ts +0 -722
- package/dist/schema/openapi.d.ts +0 -29
- package/dist/schema/openapi.js +0 -124
- package/dist/transactions/durableWriteStore.js +0 -30
- 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/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/coordination}/claimHeartbeatLoop.d.ts +0 -0
- /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.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/{utils → transaction/utils}/duration.d.ts +0 -0
- /package/dist/{utils → transaction/utils}/duration.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
|
@@ -3,29 +3,56 @@
|
|
|
3
3
|
* `ablo.<model>`.
|
|
4
4
|
*
|
|
5
5
|
* Each schema model gets one {@link ModelOperations}: the async server reads
|
|
6
|
-
* `retrieve` and `list`, the
|
|
7
|
-
*
|
|
6
|
+
* `retrieve` and `list`, the same verbs restricted to the local graph under
|
|
7
|
+
* `local`, the writes `create`, `update`, and `delete`, the coordination
|
|
8
8
|
* namespace `claim` (callable as `claim({ id })`, plus `claim.state`,
|
|
9
9
|
* `claim.queue`, `claim.release`, and `claim.reorder`), `join`, and `onChange`.
|
|
10
10
|
* The factory returns a plain object; the client assembles the `ablo.<model>`
|
|
11
11
|
* lookup table from one of these per model.
|
|
12
12
|
*/
|
|
13
13
|
import { autorun } from 'mobx';
|
|
14
|
-
import { AbloClaimedError,
|
|
15
|
-
import { reconcileFunctionalUpdate, } from '
|
|
14
|
+
import { AbloClaimedError, AbloValidationError, formatClaimedErrorMessage, toAbloError, } from '../transaction/errors.js';
|
|
15
|
+
import { reconcileFunctionalUpdate, } from '../transaction/resources/functionalUpdate.js';
|
|
16
|
+
import { claimDescription, } from '../transaction/coordination/schema.js';
|
|
16
17
|
import { Model, modelAsRow } from '../Model.js';
|
|
17
|
-
import { toMs } from '../utils/duration.js';
|
|
18
|
-
import { LEASE_TTL_MS } from '../wire/protocol.js';
|
|
19
|
-
import { heartbeatCadenceMs, resolveHeartbeatOptions, startClaimHeartbeatLoop, } from '
|
|
20
|
-
import { assertWriteOptions } from '
|
|
21
|
-
import {
|
|
18
|
+
import { toMs } from '../transaction/utils/duration.js';
|
|
19
|
+
import { LEASE_TTL_MS } from '../transaction/wire/protocol.js';
|
|
20
|
+
import { heartbeatCadenceMs, resolveHeartbeatOptions, startClaimHeartbeatLoop, } from '../transaction/coordination/claimHeartbeatLoop.js';
|
|
21
|
+
import { assertWriteOptions } from '../transaction/resources/writeOptionsSchema.js';
|
|
22
|
+
import { modelTarget, subTarget } from '../transaction/coordination/index.js';
|
|
23
|
+
import { ModelScope } from '../transaction/types/index.js';
|
|
22
24
|
const modelClientMeta = new WeakMap();
|
|
23
25
|
export function getModelClientMeta(modelClient) {
|
|
24
26
|
if (typeof modelClient !== 'object' || modelClient === null)
|
|
25
27
|
return undefined;
|
|
26
28
|
return modelClientMeta.get(modelClient);
|
|
27
29
|
}
|
|
28
|
-
export function createModelProxy(schemaKey, registeredModelName, objectPool, syncClient, registry, hydration, collaboration
|
|
30
|
+
export function createModelProxy(schemaKey, registeredModelName, objectPool, syncClient, registry, hydration, collaboration,
|
|
31
|
+
/** The client-wide `wait` default; a per-call `wait` still wins over it. */
|
|
32
|
+
defaultWait) {
|
|
33
|
+
/**
|
|
34
|
+
* Resolve a row **this** resource owns.
|
|
35
|
+
*
|
|
36
|
+
* The pool is one id space, so `objectPool.get(id)` happily returns another
|
|
37
|
+
* model's row. Every write path below addresses rows by bare id, so without
|
|
38
|
+
* this an id from a sibling model resolves and gets written — silently
|
|
39
|
+
* corrupting a row the caller never named.
|
|
40
|
+
*
|
|
41
|
+
* `undefined` means genuinely absent. A row belonging to another model throws:
|
|
42
|
+
* unlike a read, a cross-model *write* is never a legitimate outcome, and
|
|
43
|
+
* naming both models turns a silent corruption into a one-line diagnosis.
|
|
44
|
+
*/
|
|
45
|
+
const ownRowOrThrow = (id) => {
|
|
46
|
+
const own = objectPool.getOfType(id, registeredModelName);
|
|
47
|
+
if (own)
|
|
48
|
+
return own;
|
|
49
|
+
const foreign = objectPool.get(id);
|
|
50
|
+
if (!foreign)
|
|
51
|
+
return undefined;
|
|
52
|
+
const owner = foreign.getModelName();
|
|
53
|
+
throw new AbloValidationError(`No ${registeredModelName} with id ${id} — that id belongs to a ${owner}. ` +
|
|
54
|
+
`Read or write it through ${owner}.`, { code: 'entity_not_found' });
|
|
55
|
+
};
|
|
29
56
|
const ModelClass = registry.getModelByName(registeredModelName);
|
|
30
57
|
if (!ModelClass) {
|
|
31
58
|
throw new AbloValidationError(`Ablo: schema model "${schemaKey}" resolved to "${registeredModelName}", ` +
|
|
@@ -66,7 +93,11 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
66
93
|
return rows;
|
|
67
94
|
};
|
|
68
95
|
const waitForMutation = async (model, options) => {
|
|
69
|
-
|
|
96
|
+
// A per-call `wait` wins; otherwise the client-wide default decides. This
|
|
97
|
+
// is the single point that turns "confirmed" into actually waiting, so a
|
|
98
|
+
// client configured that way rejects on a refused write everywhere rather
|
|
99
|
+
// than in the one place a caller remembered to ask.
|
|
100
|
+
if ((options?.wait ?? defaultWait) !== 'confirmed')
|
|
70
101
|
return;
|
|
71
102
|
await syncClient.syncNow();
|
|
72
103
|
await syncClient.waitForConfirmation(model.getModelName(), model.id);
|
|
@@ -93,7 +124,6 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
93
124
|
value.object === 'claim' &&
|
|
94
125
|
typeof value.id === 'string' &&
|
|
95
126
|
typeof value.release === 'function';
|
|
96
|
-
const claimMeta = (options) => options?.meta;
|
|
97
127
|
const claimContextFromClaim = (claim) => {
|
|
98
128
|
return {
|
|
99
129
|
id: claim.id,
|
|
@@ -104,12 +134,8 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
104
134
|
status: claim.status,
|
|
105
135
|
expiresAt: claim.expiresAt,
|
|
106
136
|
target: {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
path: claim.target.path,
|
|
110
|
-
range: claim.target.range,
|
|
111
|
-
field: claim.target.field,
|
|
112
|
-
meta: claim.target.meta,
|
|
137
|
+
...modelTarget(claim.target),
|
|
138
|
+
...subTarget(claim.target),
|
|
113
139
|
},
|
|
114
140
|
};
|
|
115
141
|
};
|
|
@@ -155,10 +181,10 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
155
181
|
}), { code: 'entity_claimed', claims: [claim] });
|
|
156
182
|
}
|
|
157
183
|
// Ensure the row exists locally before claiming.
|
|
158
|
-
let model =
|
|
184
|
+
let model = ownRowOrThrow(id);
|
|
159
185
|
if (!model) {
|
|
160
186
|
await load({ where: [['id', id]] });
|
|
161
|
-
model =
|
|
187
|
+
model = ownRowOrThrow(id);
|
|
162
188
|
}
|
|
163
189
|
if (!model) {
|
|
164
190
|
throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
|
|
@@ -180,12 +206,12 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
180
206
|
target: {
|
|
181
207
|
model: wireModel,
|
|
182
208
|
id,
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
...(
|
|
209
|
+
// The whole sub-entity locator in one move — listing its members here
|
|
210
|
+
// is what let `fields` die between the caller and the lease, so the
|
|
211
|
+
// claim covered the whole row while the caller believed it named parts.
|
|
212
|
+
...subTarget(options),
|
|
187
213
|
},
|
|
188
|
-
description: options
|
|
214
|
+
description: claimDescription(options),
|
|
189
215
|
ttl: options.ttl,
|
|
190
216
|
queue: !failFast,
|
|
191
217
|
maxQueueDepth: options.maxQueueDepth,
|
|
@@ -205,20 +231,17 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
205
231
|
// holder's final write may not have fanned out yet — the exact
|
|
206
232
|
// stale-snapshot race this re-read closes.
|
|
207
233
|
await load({ where: [['id', id]], type: 'complete' });
|
|
208
|
-
model =
|
|
234
|
+
model = ownRowOrThrow(id) ?? model;
|
|
209
235
|
}
|
|
210
236
|
const snapshot = collaboration.createSnapshot(schemaKey, id);
|
|
211
|
-
const description = options
|
|
237
|
+
const description = claimDescription(options);
|
|
212
238
|
// The self-claim's `ClaimTarget` mirrors what a peer's `claim.state` would
|
|
213
239
|
// report (`state` maps `held.target.model` to `type`), so a holder and a
|
|
214
240
|
// peer see the same `target.type` for one row — the wire model token.
|
|
215
241
|
const selfTarget = {
|
|
216
242
|
type: wireModel,
|
|
217
243
|
id,
|
|
218
|
-
...(options
|
|
219
|
-
...(options.path ? { path: options.path } : {}),
|
|
220
|
-
...(options.range ? { range: options.range } : {}),
|
|
221
|
-
...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
|
|
244
|
+
...subTarget(options),
|
|
222
245
|
};
|
|
223
246
|
const ttlMs = options.ttl !== undefined ? toMs(options.ttl) : DEFAULT_LEASE_TTL_MS;
|
|
224
247
|
const expiresAt = Date.now() + ttlMs;
|
|
@@ -232,10 +255,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
232
255
|
const target = {
|
|
233
256
|
type: schemaKey,
|
|
234
257
|
id,
|
|
235
|
-
...(options
|
|
236
|
-
...(options.path ? { path: options.path } : {}),
|
|
237
|
-
...(options.range ? { range: options.range } : {}),
|
|
238
|
-
...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
|
|
258
|
+
...subTarget(options),
|
|
239
259
|
};
|
|
240
260
|
// A beat resolves with the server's extended expiry; keep the local
|
|
241
261
|
// self-claim estimate in step so `claim.state` renders the real window,
|
|
@@ -329,12 +349,12 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
329
349
|
target: {
|
|
330
350
|
model: wireModel,
|
|
331
351
|
id,
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
...(
|
|
352
|
+
// The whole sub-entity locator in one move — listing its members here
|
|
353
|
+
// is what let `fields` die between the caller and the lease, so the
|
|
354
|
+
// claim covered the whole row while the caller believed it named parts.
|
|
355
|
+
...subTarget(options),
|
|
336
356
|
},
|
|
337
|
-
description: options
|
|
357
|
+
description: claimDescription(options),
|
|
338
358
|
ttl: options.ttl,
|
|
339
359
|
queue: !failFast,
|
|
340
360
|
maxQueueDepth: options.maxQueueDepth,
|
|
@@ -344,14 +364,11 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
344
364
|
// empty). It costs nothing extra and gives a write taken under this lease a
|
|
345
365
|
// real `readAt` to guard against changes since the lease was acquired.
|
|
346
366
|
const snapshot = collaboration.createSnapshot(schemaKey, id);
|
|
347
|
-
const description = options
|
|
367
|
+
const description = claimDescription(options);
|
|
348
368
|
const selfTarget = {
|
|
349
369
|
type: wireModel,
|
|
350
370
|
id,
|
|
351
|
-
...(options
|
|
352
|
-
...(options.path ? { path: options.path } : {}),
|
|
353
|
-
...(options.range ? { range: options.range } : {}),
|
|
354
|
-
...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
|
|
371
|
+
...subTarget(options),
|
|
355
372
|
};
|
|
356
373
|
const ttlMs = options.ttl !== undefined ? toMs(options.ttl) : DEFAULT_LEASE_TTL_MS;
|
|
357
374
|
const expiresAt = Date.now() + ttlMs;
|
|
@@ -365,10 +382,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
365
382
|
const target = {
|
|
366
383
|
type: schemaKey,
|
|
367
384
|
id,
|
|
368
|
-
...(options
|
|
369
|
-
...(options.path ? { path: options.path } : {}),
|
|
370
|
-
...(options.range ? { range: options.range } : {}),
|
|
371
|
-
...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
|
|
385
|
+
...subTarget(options),
|
|
372
386
|
};
|
|
373
387
|
// A beat resolves with the server's extended expiry; keep the local
|
|
374
388
|
// self-claim estimate in step so `claim.state` renders the real window.
|
|
@@ -434,7 +448,14 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
434
448
|
// members to read/steer the coordination plane. Attach the readers to the
|
|
435
449
|
// callable so `ablo.<model>.claim(...)` and `ablo.<model>.claim.state(...)`
|
|
436
450
|
// are the same object.
|
|
437
|
-
|
|
451
|
+
// `state` and `queue` take a caller-named `meta` shape. The runtime cannot
|
|
452
|
+
// check it and is not meant to: `target.meta` is application data the
|
|
453
|
+
// protocol carries verbatim and never interprets, so naming its type is the
|
|
454
|
+
// caller asserting what it put there — the same bargain as parsing your own
|
|
455
|
+
// JSON into an interface. These read as `Claim` here, and the one assertion
|
|
456
|
+
// that applies the caller's parameter is on the assignment below, in one
|
|
457
|
+
// place rather than at every call site.
|
|
458
|
+
const claimReaders = {
|
|
438
459
|
state(params) {
|
|
439
460
|
// Read interest: a passive observer of a row's claim state must enter that
|
|
440
461
|
// row's entity scope, or it sits only on broader `org:`/`user:` groups and
|
|
@@ -470,28 +491,17 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
470
491
|
collaboration?.reorder({ model: wireModel, id: params.id }, params.order);
|
|
471
492
|
},
|
|
472
493
|
release: guard((params) => releaseClaim(isClaimHandle(params) ? params.target.id : params.id)),
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
//
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
...params,
|
|
483
|
-
where: [['id', params.id]],
|
|
484
|
-
limit: 1,
|
|
485
|
-
});
|
|
486
|
-
return rows[0];
|
|
487
|
-
}),
|
|
488
|
-
// No automatic scope enrolment on bulk `list`/`getAll`: that would subscribe
|
|
489
|
-
// to an unbounded set of rows' entity groups.
|
|
490
|
-
list: guard(load),
|
|
491
|
-
get(id) {
|
|
492
|
-
return objectPool.get(id);
|
|
494
|
+
};
|
|
495
|
+
// The one place the caller's `meta` parameter is applied — see the note on
|
|
496
|
+
// `claimReaders`. Everything else about this object is checked structurally.
|
|
497
|
+
const claimApi = Object.assign(claim, claimReaders);
|
|
498
|
+
const local = {
|
|
499
|
+
retrieve(id) {
|
|
500
|
+
// Scoped to this model: an id belonging to a sibling model reads as
|
|
501
|
+
// absent rather than being handed back as if it were a `T`.
|
|
502
|
+
return objectPool.getOfType(id, registeredModelName);
|
|
493
503
|
},
|
|
494
|
-
|
|
504
|
+
list(options) {
|
|
495
505
|
const all = objectPool.getByType(ModelClass, (options?.state ?? ModelScope.live));
|
|
496
506
|
let result = all;
|
|
497
507
|
if (options?.where) {
|
|
@@ -525,9 +535,28 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
525
535
|
result = result.slice(0, options.limit);
|
|
526
536
|
return result;
|
|
527
537
|
},
|
|
528
|
-
|
|
529
|
-
return
|
|
538
|
+
count(options) {
|
|
539
|
+
return local.list(options).length;
|
|
530
540
|
},
|
|
541
|
+
};
|
|
542
|
+
const operations = {
|
|
543
|
+
local,
|
|
544
|
+
retrieve: guard(async (params) => {
|
|
545
|
+
// Read-interest enrolment: reading a row enters its entity scope, so a
|
|
546
|
+
// client lands in the same group the holder's claim presence fans out
|
|
547
|
+
// on and `claim.state`/`claim.queue` report peers. Best-effort and
|
|
548
|
+
// fire-and-forget — it never makes the read reject or run slower.
|
|
549
|
+
void collaboration?.enterScope?.({ [schemaKey]: params.id });
|
|
550
|
+
const rows = await load({
|
|
551
|
+
...params,
|
|
552
|
+
where: [['id', params.id]],
|
|
553
|
+
limit: 1,
|
|
554
|
+
});
|
|
555
|
+
return rows[0];
|
|
556
|
+
}),
|
|
557
|
+
// No automatic scope enrolment on bulk `list`: that would subscribe to an
|
|
558
|
+
// unbounded set of rows' entity groups.
|
|
559
|
+
list: guard(load),
|
|
531
560
|
create: guard(async (params) => {
|
|
532
561
|
const id = params.id ?? Model.generateId();
|
|
533
562
|
const opts = mutationOptions(params);
|
|
@@ -547,12 +576,9 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
547
576
|
target: {
|
|
548
577
|
model: wireModel,
|
|
549
578
|
id,
|
|
550
|
-
...(claim
|
|
551
|
-
...(claim.path ? { path: claim.path } : {}),
|
|
552
|
-
...(claim.range ? { range: claim.range } : {}),
|
|
553
|
-
...(claimMeta(claim) ? { meta: claimMeta(claim) } : {}),
|
|
579
|
+
...subTarget(claim),
|
|
554
580
|
},
|
|
555
|
-
description: claim
|
|
581
|
+
description: claimDescription(claim, 'creating'),
|
|
556
582
|
ttl: claim.ttl,
|
|
557
583
|
queue: claim.queue !== false,
|
|
558
584
|
maxQueueDepth: claim.maxQueueDepth,
|
|
@@ -615,7 +641,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
615
641
|
// `type: 'complete'` forces the round-trip — the hydration ledger
|
|
616
642
|
// would otherwise serve a possibly-stale local row for a hydrated id.
|
|
617
643
|
await load({ where: [['id', id]], type: 'complete' });
|
|
618
|
-
const fresh =
|
|
644
|
+
const fresh = ownRowOrThrow(id);
|
|
619
645
|
const snapshot = collaboration.createSnapshot(schemaKey, id);
|
|
620
646
|
return {
|
|
621
647
|
data: fresh ? modelAsRow(fresh) : undefined,
|
|
@@ -623,7 +649,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
623
649
|
};
|
|
624
650
|
},
|
|
625
651
|
writeNext: async (patch, readAt) => {
|
|
626
|
-
const model =
|
|
652
|
+
const model = ownRowOrThrow(id);
|
|
627
653
|
if (!model) {
|
|
628
654
|
throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
|
|
629
655
|
}
|
|
@@ -651,7 +677,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
651
677
|
}
|
|
652
678
|
}
|
|
653
679
|
const { id } = params;
|
|
654
|
-
const model =
|
|
680
|
+
const model = ownRowOrThrow(id);
|
|
655
681
|
if (!model)
|
|
656
682
|
throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
|
|
657
683
|
// If we hold a claim on this row, guard the write with its snapshot
|
|
@@ -711,7 +737,10 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
711
737
|
return;
|
|
712
738
|
}
|
|
713
739
|
const { id } = params;
|
|
714
|
-
|
|
740
|
+
// Scoped: "ensure absent" stays idempotent for an id this model simply
|
|
741
|
+
// doesn't hold, but an id owned by a sibling model throws rather than
|
|
742
|
+
// deleting a row the caller never addressed.
|
|
743
|
+
const model = ownRowOrThrow(id);
|
|
715
744
|
// Idempotent delete: "ensure absent". A row that isn't in this client's
|
|
716
745
|
// replicated view is already gone from its perspective, so a delete is a
|
|
717
746
|
// no-op success rather than an `entity_not_found` error. This matches the
|
|
@@ -758,13 +787,13 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
758
787
|
};
|
|
759
788
|
// A track carries no write, so it rides the commit lane as a zero-operation
|
|
760
789
|
// commit: the queue tolerates disconnects and de-dupes replays, and the
|
|
761
|
-
// server's track-only path registers the
|
|
790
|
+
// server's track-only path registers the premise and reports anything
|
|
762
791
|
// that already fired. Reuse the same lane the batch `commits.create` door
|
|
763
792
|
// uses rather than opening a bespoke transport.
|
|
764
793
|
const clientTxId = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
|
|
765
794
|
? crypto.randomUUID()
|
|
766
795
|
: `tx_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
767
|
-
const queue = syncClient.
|
|
796
|
+
const queue = syncClient.getMutationQueue();
|
|
768
797
|
await queue.enqueueCommit(clientTxId, [], { track: [dep] });
|
|
769
798
|
const { notifications } = await queue.waitForCommitReceipt(clientTxId);
|
|
770
799
|
return notifications && notifications.length > 0 ? { notifications } : {};
|
|
@@ -777,8 +806,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
|
|
|
777
806
|
}),
|
|
778
807
|
onChange(callback, options) {
|
|
779
808
|
return autorun(() => {
|
|
780
|
-
|
|
781
|
-
callback(entities);
|
|
809
|
+
callback(local.list(options));
|
|
782
810
|
});
|
|
783
811
|
},
|
|
784
812
|
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `humans()` — the reactive materialiser, declared as a capability (ADR 0016).
|
|
3
|
+
*
|
|
4
|
+
* The bare client is the coordination layer: commit, read, observe, claim.
|
|
5
|
+
* Add `humans()` when people are watching — it declares the local, watchable
|
|
6
|
+
* copy: the offline store, live queries, presence, and the framework
|
|
7
|
+
* bindings. There is no `agents()` counterpart, and the absence is the
|
|
8
|
+
* message: agents are the default caller, not a special one.
|
|
9
|
+
*
|
|
10
|
+
* Transitional shape: the contract fields do real configuration work
|
|
11
|
+
* (`requires.duplex` rejects it on a request-response client at construction
|
|
12
|
+
* time; `materialises` is the five-second membership test as a checkable
|
|
13
|
+
* property), and `init` constructs what the widened context already carries
|
|
14
|
+
* enough to build — the presence stream, attached to the connection the
|
|
15
|
+
* context carries (the host built it before resolving the plugin list). The
|
|
16
|
+
* rest of the materialiser (store, bootstrap, delta pipeline, framework
|
|
17
|
+
* bindings) still lives in the composition root and migrates here as the
|
|
18
|
+
* context grows to carry what it needs.
|
|
19
|
+
*/
|
|
20
|
+
import type { PluginContext } from '../transaction/plugin.js';
|
|
21
|
+
import { type AttachablePresenceStream } from '../sync/createPresenceStream.js';
|
|
22
|
+
/**
|
|
23
|
+
* What `humans()` contributes to the client — exactly the members that merge
|
|
24
|
+
* onto it, nothing else. Whether a plugin materialises is declared on the
|
|
25
|
+
* plugin itself, never restated on its surface.
|
|
26
|
+
*/
|
|
27
|
+
export interface HumansSurface {
|
|
28
|
+
/**
|
|
29
|
+
* Who is here and what they are doing. Attached to the connection at
|
|
30
|
+
* construction; calls before the socket opens mutate local state and skip
|
|
31
|
+
* the wire send, and the stream re-announces on every connect.
|
|
32
|
+
*/
|
|
33
|
+
readonly presence: AttachablePresenceStream;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The reactive materialiser. Installed by default when `Ablo({ ... })` is
|
|
37
|
+
* constructed over the socket with no `plugins` list; listed explicitly, it
|
|
38
|
+
* reads as what it is — this client renders for people.
|
|
39
|
+
*/
|
|
40
|
+
export declare function humans(): {
|
|
41
|
+
readonly id: "humans";
|
|
42
|
+
readonly requires: {
|
|
43
|
+
readonly duplex: true;
|
|
44
|
+
};
|
|
45
|
+
readonly materialises: true;
|
|
46
|
+
readonly stage: "apply";
|
|
47
|
+
readonly init: (context: PluginContext) => HumansSurface;
|
|
48
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `humans()` — the reactive materialiser, declared as a capability (ADR 0016).
|
|
3
|
+
*
|
|
4
|
+
* The bare client is the coordination layer: commit, read, observe, claim.
|
|
5
|
+
* Add `humans()` when people are watching — it declares the local, watchable
|
|
6
|
+
* copy: the offline store, live queries, presence, and the framework
|
|
7
|
+
* bindings. There is no `agents()` counterpart, and the absence is the
|
|
8
|
+
* message: agents are the default caller, not a special one.
|
|
9
|
+
*
|
|
10
|
+
* Transitional shape: the contract fields do real configuration work
|
|
11
|
+
* (`requires.duplex` rejects it on a request-response client at construction
|
|
12
|
+
* time; `materialises` is the five-second membership test as a checkable
|
|
13
|
+
* property), and `init` constructs what the widened context already carries
|
|
14
|
+
* enough to build — the presence stream, attached to the connection the
|
|
15
|
+
* context carries (the host built it before resolving the plugin list). The
|
|
16
|
+
* rest of the materialiser (store, bootstrap, delta pipeline, framework
|
|
17
|
+
* bindings) still lives in the composition root and migrates here as the
|
|
18
|
+
* context grows to carry what it needs.
|
|
19
|
+
*/
|
|
20
|
+
import { createPresenceStream, } from '../sync/createPresenceStream.js';
|
|
21
|
+
/**
|
|
22
|
+
* The reactive materialiser. Installed by default when `Ablo({ ... })` is
|
|
23
|
+
* constructed over the socket with no `plugins` list; listed explicitly, it
|
|
24
|
+
* reads as what it is — this client renders for people.
|
|
25
|
+
*/
|
|
26
|
+
export function humans() {
|
|
27
|
+
return {
|
|
28
|
+
id: 'humans',
|
|
29
|
+
// Live queries, presence, and claim push are server-initiated frames, so
|
|
30
|
+
// a request-response client rejects this plugin while it is being
|
|
31
|
+
// configured — a typed error, not a subscription that never delivers.
|
|
32
|
+
requires: { duplex: true },
|
|
33
|
+
// The point of the plugin: it keeps a local copy of rows. A stateless
|
|
34
|
+
// caller can assert its own list is uniformly false.
|
|
35
|
+
materialises: true,
|
|
36
|
+
// Deltas land in the materialised in-memory graph at `apply`.
|
|
37
|
+
stage: 'apply',
|
|
38
|
+
init: (context) => ({
|
|
39
|
+
presence: createPresenceStream({
|
|
40
|
+
participantId: context.participant?.id ?? '',
|
|
41
|
+
syncGroups: [...(context.syncGroups ?? [])],
|
|
42
|
+
// Peers' kinds are server-stamped; only the local `self` entry is ours.
|
|
43
|
+
isAgent: context.participant?.kind === 'agent',
|
|
44
|
+
},
|
|
45
|
+
// The host built the connection before resolving the plugin list, so
|
|
46
|
+
// the stream attaches now and starts the moment the feed opens.
|
|
47
|
+
context.transport ?? null),
|
|
48
|
+
}),
|
|
49
|
+
// `satisfies` rather than a return annotation, so `id` keeps its literal
|
|
50
|
+
// type and a plugin list's surface can be keyed by id at the type level.
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* and opt-in field-level reactivity) and registers the model's properties,
|
|
6
6
|
* relations, and any local-database indexes.
|
|
7
7
|
*/
|
|
8
|
-
import type { Schema } from '../schema/schema.js';
|
|
8
|
+
import type { Schema } from '../transaction/schema/schema.js';
|
|
9
9
|
import type { ModelRegistry } from '../ModelRegistry.js';
|
|
10
10
|
export declare function registerModelsFromSchema(schema: Schema, registry: ModelRegistry): void;
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* relations, and any local-database indexes.
|
|
7
7
|
*/
|
|
8
8
|
import { z } from 'zod';
|
|
9
|
-
import { baseFieldsSchema } from '../schema/schema.js';
|
|
9
|
+
import { baseFieldsSchema } from '../transaction/schema/schema.js';
|
|
10
10
|
import { Model } from '../Model.js';
|
|
11
|
-
import {
|
|
11
|
+
import { PropertyType } from '../transaction/types/index.js';
|
|
12
12
|
// ── Auto model registration from schema ───────────────────────────────────
|
|
13
13
|
export function registerModelsFromSchema(schema, registry) {
|
|
14
14
|
registry.startBatch();
|
|
@@ -50,10 +50,10 @@ export function registerModelsFromSchema(schema, registry) {
|
|
|
50
50
|
];
|
|
51
51
|
const computed = modelDef.computed;
|
|
52
52
|
const DynamicModel = createDynamicModelClass(modelName, jsonSubFields, fieldNames, computed, isLazy);
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
// The schema's strategy carries straight through — authoring and runtime
|
|
54
|
+
// name the same set, so there is nothing here to translate and nothing to
|
|
55
|
+
// fall out of step. Lazy models skip IDB hydration and bootstrap.
|
|
56
|
+
const loadStrategy = modelDef.load;
|
|
57
57
|
registry.registerModel(modelName, DynamicModel, {
|
|
58
58
|
loadStrategy,
|
|
59
59
|
fields: modelDef.fields,
|
|
@@ -70,14 +70,14 @@ export function registerModelsFromSchema(schema, registry) {
|
|
|
70
70
|
// id, and indexing every scalar is worse still.
|
|
71
71
|
const indexedFields = new Set();
|
|
72
72
|
for (const relDef of Object.values(modelDef.relations)) {
|
|
73
|
-
if (relDef.type === 'belongsTo' && relDef.foreignKey && relDef.options
|
|
73
|
+
if (relDef.type === 'belongsTo' && relDef.foreignKey && relDef.options.index === true) {
|
|
74
74
|
indexedFields.add(relDef.foreignKey);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
// Register fields as properties (from Zod shape).
|
|
78
78
|
for (const [fieldName, rawZodType] of Object.entries(modelDef.shape)) {
|
|
79
79
|
const zodType = rawZodType;
|
|
80
|
-
const isOptional = zodType.isOptional
|
|
80
|
+
const isOptional = zodType.isOptional();
|
|
81
81
|
// A field is indexed if it is the foreign key of a
|
|
82
82
|
// `belongsTo({ index: true })` relation. A `description === 'indexed'` tag
|
|
83
83
|
// also works, for consumers using the `field.*().indexed()` builder.
|
|
@@ -87,7 +87,7 @@ export function registerModelsFromSchema(schema, registry) {
|
|
|
87
87
|
// would walk every nested property and create an atom per leaf, producing a
|
|
88
88
|
// storm of updates on each commit or streaming change. Reference tracking
|
|
89
89
|
// watches only reassignment, which is how blob consumers actually use them.
|
|
90
|
-
const wireType = modelDef.fields
|
|
90
|
+
const wireType = modelDef.fields[fieldName]?.type;
|
|
91
91
|
const observability = wireType === 'json' ? 'ref' : undefined;
|
|
92
92
|
registry.registerProperty(modelName, fieldName, {
|
|
93
93
|
type: PropertyType.property,
|