@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
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
// Pulled from the endpoints module to keep this schema file free of the client's
|
|
2
|
+
// error-handling and credential dependencies.
|
|
3
|
+
import { ABLO_HOSTED_HTTP_BASE_URL } from '../auth/hostedEndpoints.js';
|
|
4
|
+
// The commit body is DERIVED from the schema the server validates against —
|
|
5
|
+
// one definition site, so the documented surface cannot drift from the
|
|
6
|
+
// enforced one.
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { commitRequestSchema, commitReceiptSchema } from '../wire/commit.js';
|
|
9
|
+
import { claimRequestSchema, claimHeartbeatRequestSchema, listQuerySchema, claimStateSchema, claimAcquiredResponseSchema, claimQueuedResponseSchema, claimHeartbeatReplySchema, } from '../wire/claims.js';
|
|
10
|
+
import { modelReadResponseSchema, modelListResponseSchema } from '../wire/modelResponses.js';
|
|
11
|
+
import { ephemeralKeyRequestSchema, capabilityRequestSchema } from '../wire/auth.js';
|
|
12
|
+
import { EphemeralKeyResponseSchema } from '../auth/schemas.js';
|
|
13
|
+
function fieldSchema(f) {
|
|
14
|
+
switch (f.type) {
|
|
15
|
+
case 'number':
|
|
16
|
+
return { type: 'number' };
|
|
17
|
+
case 'boolean':
|
|
18
|
+
return { type: 'boolean' };
|
|
19
|
+
case 'date':
|
|
20
|
+
return { type: 'string', format: 'date-time' };
|
|
21
|
+
case 'enum':
|
|
22
|
+
return f.enumValues ? { type: 'string', enum: [...f.enumValues] } : { type: 'string' };
|
|
23
|
+
case 'json':
|
|
24
|
+
return { type: 'object', additionalProperties: true };
|
|
25
|
+
case 'string':
|
|
26
|
+
default:
|
|
27
|
+
return { type: 'string' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const pascal = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
31
|
+
const idParam = () => ({ name: 'id', in: 'path', required: true, schema: { type: 'string' } });
|
|
32
|
+
const jsonBody = (schema) => ({
|
|
33
|
+
required: true,
|
|
34
|
+
content: { 'application/json': { schema } },
|
|
35
|
+
});
|
|
36
|
+
/** For routes where an empty body is meaningful — a bare claim, a plain beat. */
|
|
37
|
+
const optionalJsonBody = (schema) => ({
|
|
38
|
+
required: false,
|
|
39
|
+
content: { 'application/json': { schema } },
|
|
40
|
+
});
|
|
41
|
+
const jsonResp = (description, schema) => ({
|
|
42
|
+
description,
|
|
43
|
+
content: { 'application/json': { schema } },
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Derive a JSON Schema from a wire schema.
|
|
47
|
+
*
|
|
48
|
+
* `io` is not optional by accident. A request is what the caller SENDS, so it
|
|
49
|
+
* derives from the input type; a response is what the server RETURNS, so it
|
|
50
|
+
* derives from the output type. Reversing them is silent — the document still
|
|
51
|
+
* looks like a working spec — which is why the direction is stated at every
|
|
52
|
+
* call site rather than defaulted.
|
|
53
|
+
*/
|
|
54
|
+
const derive = (schema, io) => z.toJSONSchema(schema, { io, unrepresentable: 'any' });
|
|
55
|
+
const commitReceipt = () => jsonResp('Commit receipt', derive(commitReceiptSchema, 'output'));
|
|
56
|
+
const modelParam = () => ({
|
|
57
|
+
name: 'model',
|
|
58
|
+
in: 'path',
|
|
59
|
+
required: true,
|
|
60
|
+
schema: { type: 'string' },
|
|
61
|
+
description: 'A model name from your pushed schema, e.g. `task`.',
|
|
62
|
+
});
|
|
63
|
+
const genericRow = () => ({ type: 'object', additionalProperties: true });
|
|
64
|
+
/**
|
|
65
|
+
* Fill in `data` on a derived model-response schema.
|
|
66
|
+
*
|
|
67
|
+
* The wire schemas type a row as `unknown`, because the transport that reads
|
|
68
|
+
* them serves every schema and knows none of them. A reference has the opposite
|
|
69
|
+
* need — a reader wants to see that `data` holds rows — so the envelope is
|
|
70
|
+
* still derived, and only the one deliberately-open field is described. Both
|
|
71
|
+
* shapes of that field are handled: an array for a list, a bare object for a
|
|
72
|
+
* single read.
|
|
73
|
+
*/
|
|
74
|
+
function withGenericRows(derived) {
|
|
75
|
+
const properties = { ...derived.properties };
|
|
76
|
+
if (!('data' in properties))
|
|
77
|
+
return derived;
|
|
78
|
+
properties.data =
|
|
79
|
+
properties.data?.type === 'array'
|
|
80
|
+
? { type: 'array', items: genericRow() }
|
|
81
|
+
: genericRow();
|
|
82
|
+
return { ...derived, properties };
|
|
83
|
+
}
|
|
84
|
+
/** Query parameters derived from the schema the route reads them with. */
|
|
85
|
+
function listQueryParams() {
|
|
86
|
+
const props = (derive(listQuerySchema, 'input').properties ?? {});
|
|
87
|
+
return Object.entries(props).map(([name, schema]) => ({ name, in: 'query', schema }));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The `POST /v1/commits` body, derived from {@link commitRequestSchema} — the
|
|
91
|
+
* same schema the server validates the request against.
|
|
92
|
+
*
|
|
93
|
+
* Deriving rather than describing is the point: a hand-written copy of this
|
|
94
|
+
* shape would drift silently, and the tests would pin the copy to itself.
|
|
95
|
+
*/
|
|
96
|
+
const commitBody = () => jsonBody(derive(commitRequestSchema, 'input'));
|
|
97
|
+
/** The envelope shared by both specs — same server, same auth, same version. */
|
|
98
|
+
function envelope(options, description, paths, schemas) {
|
|
99
|
+
return {
|
|
100
|
+
openapi: '3.1.0',
|
|
101
|
+
info: {
|
|
102
|
+
title: options.title ?? 'Ablo API',
|
|
103
|
+
version: options.version ?? '1.0.0',
|
|
104
|
+
description,
|
|
105
|
+
},
|
|
106
|
+
servers: [{ url: options.serverUrl ?? `${ABLO_HOSTED_HTTP_BASE_URL}/api` }],
|
|
107
|
+
security: [{ bearerAuth: [] }],
|
|
108
|
+
components: {
|
|
109
|
+
securitySchemes: {
|
|
110
|
+
bearerAuth: { type: 'http', scheme: 'bearer', description: 'Your Ablo API key (sk_… / rk_…).' },
|
|
111
|
+
},
|
|
112
|
+
schemas,
|
|
113
|
+
},
|
|
114
|
+
paths,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The protocol reference: the five route templates the server actually serves,
|
|
119
|
+
* plus `/v1/commits`.
|
|
120
|
+
*
|
|
121
|
+
* This takes no schema, and that is the point. The server registers one
|
|
122
|
+
* parameterised route family (`/api/v1/models/:model/...`), so the API is five
|
|
123
|
+
* routes no matter how many models a tenant defines — and a spec that cannot see
|
|
124
|
+
* a schema cannot grow with one. It is publishable once, identical for every
|
|
125
|
+
* caller, and stable across every schema push: the document a Python or Go
|
|
126
|
+
* client is generated from, and the surface an agent is handed.
|
|
127
|
+
*
|
|
128
|
+
* Payload shapes are generic here by design. A caller that wants them typed
|
|
129
|
+
* either reads the schema at runtime or generates the per-tenant expansion with
|
|
130
|
+
* {@link schemaToOpenApi}.
|
|
131
|
+
*/
|
|
132
|
+
export function abloOpenApi(options = {}) {
|
|
133
|
+
const rowResp = jsonResp('The row, with the watermark it was read at and who holds it.', withGenericRows(derive(modelReadResponseSchema, 'output')));
|
|
134
|
+
const writeBody = jsonBody(genericRow());
|
|
135
|
+
const tags = ['models'];
|
|
136
|
+
const paths = {
|
|
137
|
+
'/v1/models/{model}': {
|
|
138
|
+
get: {
|
|
139
|
+
tags,
|
|
140
|
+
summary: 'List rows of a model',
|
|
141
|
+
parameters: [modelParam(), ...listQueryParams()],
|
|
142
|
+
responses: {
|
|
143
|
+
'200': jsonResp('A page of rows. `next_cursor` feeds `starting_after` on the next ' +
|
|
144
|
+
'call; `stamp` is the watermark the page was read at.', withGenericRows(derive(modelListResponseSchema, 'output'))),
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
post: { tags, summary: 'Create a row', parameters: [modelParam()], requestBody: writeBody, responses: { '200': commitReceipt() } },
|
|
148
|
+
},
|
|
149
|
+
'/v1/models/{model}/{id}': {
|
|
150
|
+
get: { tags, summary: 'Retrieve a row', parameters: [modelParam(), idParam()], responses: { '200': rowResp } },
|
|
151
|
+
patch: { tags, summary: 'Update a row', parameters: [modelParam(), idParam()], requestBody: writeBody, responses: { '200': commitReceipt() } },
|
|
152
|
+
delete: { tags, summary: 'Delete a row', parameters: [modelParam(), idParam()], responses: { '200': commitReceipt() } },
|
|
153
|
+
},
|
|
154
|
+
'/v1/models/{model}/{id}/claim': {
|
|
155
|
+
post: {
|
|
156
|
+
tags: ['claims'],
|
|
157
|
+
summary: 'Claim a row (acquire lease)',
|
|
158
|
+
parameters: [modelParam(), idParam()],
|
|
159
|
+
requestBody: optionalJsonBody(derive(claimRequestSchema, 'input')),
|
|
160
|
+
responses: {
|
|
161
|
+
'201': jsonResp('The lease is yours. `claim.fenceToken` is set when the coordinator ' +
|
|
162
|
+
'minted one; carry it on writes made under the lease.', derive(claimAcquiredResponseSchema, 'output')),
|
|
163
|
+
'202': jsonResp('The row was already held and you asked to queue. You are in line at ' +
|
|
164
|
+
'`position` — heartbeat to keep the slot, and poll ' +
|
|
165
|
+
'`GET /v1/claims/{claimId}` for the grant.', derive(claimQueuedResponseSchema, 'output')),
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
delete: { tags: ['claims'], summary: 'Release a claim', parameters: [modelParam(), idParam()], responses: { '200': jsonResp('Released', { type: 'object' }) } },
|
|
169
|
+
},
|
|
170
|
+
'/v1/models/{model}/{id}/claim/heartbeat': {
|
|
171
|
+
post: {
|
|
172
|
+
tags: ['claims'],
|
|
173
|
+
summary: 'Heartbeat a held claim (extend the lease for long-running work)',
|
|
174
|
+
parameters: [modelParam(), idParam()],
|
|
175
|
+
requestBody: optionalJsonBody(derive(claimHeartbeatRequestSchema, 'input')),
|
|
176
|
+
responses: {
|
|
177
|
+
'200': jsonResp('Lease extended (or queued slot refreshed)', derive(claimHeartbeatReplySchema, 'output')),
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
'/v1/models/{model}/{id}/claim/reorder': {
|
|
182
|
+
post: { tags: ['claims'], summary: 'Reorder the wait-line (privileged)', parameters: [modelParam(), idParam()], responses: { '200': jsonResp('Reordered', { type: 'object' }) } },
|
|
183
|
+
},
|
|
184
|
+
'/v1/ephemeral_keys': {
|
|
185
|
+
post: {
|
|
186
|
+
tags: ['credentials'],
|
|
187
|
+
summary: 'Mint a short-lived session credential',
|
|
188
|
+
description: 'Call this first: every other route needs the key it returns. Requires a ' +
|
|
189
|
+
'secret (`sk_`) key — a session cannot mint itself.',
|
|
190
|
+
parameters: [
|
|
191
|
+
{ name: 'Idempotency-Key', in: 'header', schema: { type: 'string' }, description: 'Replay-safe key; the server returns the cached credential on retry.' },
|
|
192
|
+
],
|
|
193
|
+
requestBody: jsonBody(derive(ephemeralKeyRequestSchema, 'input')),
|
|
194
|
+
responses: { '200': jsonResp('The minted credential', derive(EphemeralKeyResponseSchema, 'output')) },
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
'/v1/claims/{claimId}': {
|
|
198
|
+
get: {
|
|
199
|
+
tags: ['claims'],
|
|
200
|
+
summary: 'Poll a claim for its current state',
|
|
201
|
+
description: 'How a caller without a persistent connection learns its queued claim ' +
|
|
202
|
+
'was granted. `position` is advisory — a privileged reorder can move it ' +
|
|
203
|
+
'up — so branch on `status`, never on position.',
|
|
204
|
+
parameters: [{ name: 'claimId', in: 'path', required: true, schema: { type: 'string' } }],
|
|
205
|
+
responses: { '200': jsonResp('The claim state', derive(claimStateSchema, 'output')) },
|
|
206
|
+
},
|
|
207
|
+
delete: {
|
|
208
|
+
tags: ['claims'],
|
|
209
|
+
summary: 'Release a claim, or leave the wait line',
|
|
210
|
+
description: 'The same call for both: releasing a held lease and abandoning a queued ' +
|
|
211
|
+
'position are one operation, because a queue entry is a lease in a ' +
|
|
212
|
+
'different state.',
|
|
213
|
+
parameters: [{ name: 'claimId', in: 'path', required: true, schema: { type: 'string' } }],
|
|
214
|
+
responses: { '200': jsonResp('Released', { type: 'object' }) },
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
'/v1/capabilities': {
|
|
218
|
+
post: {
|
|
219
|
+
tags: ['credentials'],
|
|
220
|
+
summary: 'Mint a capability for an agent or system',
|
|
221
|
+
description: 'A scoped, revocable grant. Narrow by default: an agent or system ' +
|
|
222
|
+
'capability must name its `syncGroups` and `operations`.',
|
|
223
|
+
requestBody: jsonBody(derive(capabilityRequestSchema, 'input')),
|
|
224
|
+
responses: { '200': jsonResp('The minted capability', { type: 'object' }) },
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
'/v1/capabilities/{id}': {
|
|
228
|
+
get: {
|
|
229
|
+
tags: ['credentials'],
|
|
230
|
+
summary: 'Inspect a capability',
|
|
231
|
+
parameters: [idParam()],
|
|
232
|
+
responses: { '200': jsonResp('The capability', { type: 'object' }) },
|
|
233
|
+
},
|
|
234
|
+
delete: {
|
|
235
|
+
tags: ['credentials'],
|
|
236
|
+
summary: 'Revoke a capability',
|
|
237
|
+
parameters: [idParam()],
|
|
238
|
+
responses: { '200': jsonResp('Revoked', { type: 'object' }) },
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
'/v1/capabilities/{id}/rotate': {
|
|
242
|
+
post: {
|
|
243
|
+
tags: ['credentials'],
|
|
244
|
+
summary: 'Rotate a capability, keeping its grant',
|
|
245
|
+
parameters: [idParam()],
|
|
246
|
+
responses: { '200': jsonResp('The rotated capability', { type: 'object' }) },
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
'/v1/commits': {
|
|
250
|
+
post: {
|
|
251
|
+
tags: ['commits'],
|
|
252
|
+
summary: 'Commit a batch of operations atomically, and/or register durable premises',
|
|
253
|
+
parameters: [{ name: 'Idempotency-Key', in: 'header', schema: { type: 'string' }, description: 'Replay-safe key; the server returns the cached receipt on retry.' }],
|
|
254
|
+
requestBody: commitBody(),
|
|
255
|
+
responses: { '200': commitReceipt() },
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
return envelope(options, 'The Ablo transaction layer: commit, read, and claim. `{model}` is any model ' +
|
|
260
|
+
'from your pushed schema — the routes are the same whichever it is. ' +
|
|
261
|
+
'Authenticate every request with your API key as a Bearer token.', paths, {});
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* The per-tenant expansion: every model's routes written out with typed payloads.
|
|
265
|
+
*
|
|
266
|
+
* Useful when you want generated types for one schema — five paths per model, so
|
|
267
|
+
* it grows with the schema and is regenerated on every push. It documents the
|
|
268
|
+
* same five routes {@link abloOpenApi} describes; it does not describe a
|
|
269
|
+
* different API.
|
|
270
|
+
*/
|
|
271
|
+
export function schemaToOpenApi(schema, options = {}) {
|
|
272
|
+
const models = schema.models;
|
|
273
|
+
const paths = {};
|
|
274
|
+
const schemas = {};
|
|
275
|
+
for (const [key, def] of Object.entries(models)) {
|
|
276
|
+
const ref = { $ref: `#/components/schemas/${pascal(key)}` };
|
|
277
|
+
const properties = { id: { type: 'string' } };
|
|
278
|
+
const required = ['id'];
|
|
279
|
+
const createProps = {};
|
|
280
|
+
for (const [fname, fmeta] of Object.entries(def.fields)) {
|
|
281
|
+
const fs = fieldSchema(fmeta);
|
|
282
|
+
properties[fname] = fs;
|
|
283
|
+
createProps[fname] = fs;
|
|
284
|
+
if (!fmeta.isOptional)
|
|
285
|
+
required.push(fname);
|
|
286
|
+
}
|
|
287
|
+
schemas[pascal(key)] = { type: 'object', properties, required };
|
|
288
|
+
const createBody = jsonBody({ type: 'object', properties: createProps });
|
|
289
|
+
paths[`/v1/models/${key}`] = {
|
|
290
|
+
get: {
|
|
291
|
+
tags: [key],
|
|
292
|
+
summary: `List ${key}`,
|
|
293
|
+
parameters: listQueryParams(),
|
|
294
|
+
responses: {
|
|
295
|
+
'200': jsonResp('List of rows', {
|
|
296
|
+
type: 'object',
|
|
297
|
+
properties: { object: { type: 'string', enum: ['list'] }, data: { type: 'array', items: ref } },
|
|
298
|
+
}),
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
post: { tags: [key], summary: `Create a ${key}`, requestBody: createBody, responses: { '200': commitReceipt() } },
|
|
302
|
+
};
|
|
303
|
+
paths[`/v1/models/${key}/{id}`] = {
|
|
304
|
+
get: {
|
|
305
|
+
tags: [key],
|
|
306
|
+
summary: `Retrieve a ${key}`,
|
|
307
|
+
parameters: [idParam()],
|
|
308
|
+
responses: {
|
|
309
|
+
'200': jsonResp('The row', {
|
|
310
|
+
type: 'object',
|
|
311
|
+
properties: { data: ref, stamp: { type: 'integer' } },
|
|
312
|
+
}),
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
patch: { tags: [key], summary: `Update a ${key}`, parameters: [idParam()], requestBody: createBody, responses: { '200': commitReceipt() } },
|
|
316
|
+
delete: { tags: [key], summary: `Delete a ${key}`, parameters: [idParam()], responses: { '200': commitReceipt() } },
|
|
317
|
+
};
|
|
318
|
+
paths[`/v1/models/${key}/{id}/claim`] = {
|
|
319
|
+
post: { tags: [key], summary: `Claim a ${key} (acquire lease)`, parameters: [idParam()], responses: { '200': jsonResp('Claim acquired', { type: 'object' }) } },
|
|
320
|
+
delete: { tags: [key], summary: `Release a ${key} claim`, parameters: [idParam()], responses: { '200': jsonResp('Released', { type: 'object' }) } },
|
|
321
|
+
};
|
|
322
|
+
paths[`/v1/models/${key}/{id}/claim/heartbeat`] = {
|
|
323
|
+
post: { tags: [key], summary: `Heartbeat a held ${key} claim (extend the lease for long-running work)`, parameters: [idParam()], responses: { '200': jsonResp('Lease extended (or queued slot refreshed)', derive(claimHeartbeatReplySchema, 'output')) } },
|
|
324
|
+
};
|
|
325
|
+
paths[`/v1/models/${key}/{id}/claim/reorder`] = {
|
|
326
|
+
post: { tags: [key], summary: `Reorder the ${key} wait-line (privileged)`, parameters: [idParam()], responses: { '200': jsonResp('Reordered', { type: 'object' }) } },
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
paths['/v1/commits'] = {
|
|
330
|
+
post: {
|
|
331
|
+
tags: ['commits'],
|
|
332
|
+
summary: 'Commit a batch of operations atomically, and/or register durable premises',
|
|
333
|
+
parameters: [{ name: 'Idempotency-Key', in: 'header', schema: { type: 'string' }, description: 'Replay-safe key; the server returns the cached receipt on retry.' }],
|
|
334
|
+
requestBody: commitBody(),
|
|
335
|
+
responses: { '200': commitReceipt() },
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
return envelope(options, 'Generated from your pushed Ablo schema — these routes are your models. ' +
|
|
339
|
+
'Authenticate every request with your API key as a Bearer token.', paths, schemas);
|
|
340
|
+
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* `index: true` registers a foreign-key index for the child model when the
|
|
23
23
|
* engine starts, turning "every child that points at this parent" from a full
|
|
24
24
|
* scan into a constant-time lookup. Reach for it on relations you query this
|
|
25
|
-
* way often, such as a
|
|
25
|
+
* way often, such as a block's `sectionId`.
|
|
26
26
|
*
|
|
27
27
|
* `enrich: true` auto-populates the parent reference on an incoming change
|
|
28
28
|
* before the child data lands. A change to `Task { teamId: 't1' }` picks up the
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
* relax the foreign-key check itself. For example:
|
|
45
45
|
*
|
|
46
46
|
* ```ts
|
|
47
|
-
* layouts: model({
|
|
48
|
-
* // The
|
|
49
|
-
* // created first; marking it `defer` lets the
|
|
47
|
+
* layouts: model({ reportId: z.string().nullish() }, {
|
|
48
|
+
* // The report-owns-layout link is nullable and the layout is always
|
|
49
|
+
* // created first; marking it `defer` lets the report commit ahead of the
|
|
50
50
|
* // layout instead of sharing its insert-order slot.
|
|
51
|
-
*
|
|
51
|
+
* report: relation.belongsTo('reports', 'reportId', { defer: true }),
|
|
52
52
|
* }),
|
|
53
53
|
* ```
|
|
54
54
|
*/
|
|
@@ -65,14 +65,14 @@ export interface BelongsToOptions {
|
|
|
65
65
|
* container to the things it holds, as a folder does to its files.
|
|
66
66
|
*
|
|
67
67
|
* Do not set `parent` on a reference that merely points at another record for
|
|
68
|
-
* provenance or as a template, such as `
|
|
68
|
+
* provenance or as a template, such as `sourceSectionId` or `templateId`; doing
|
|
69
69
|
* so would leak the record into an unrelated scope. The engine also cannot
|
|
70
70
|
* infer the parent from whether a field is optional — many real parent keys
|
|
71
71
|
* are optional, like a root folder or an inbox task — so you must declare the
|
|
72
72
|
* parent edge explicitly.
|
|
73
73
|
*
|
|
74
74
|
* It reads naturally at the call site:
|
|
75
|
-
* `belongsTo('
|
|
75
|
+
* `belongsTo('report', 'reportId', { parent: true })` — the report is the parent.
|
|
76
76
|
*/
|
|
77
77
|
readonly parent?: boolean;
|
|
78
78
|
/**
|
|
@@ -84,7 +84,7 @@ export interface BelongsToOptions {
|
|
|
84
84
|
*
|
|
85
85
|
* Set `fk: true` only when the target row lives in the same database and is
|
|
86
86
|
* written in the same commit as this row, and points at a strong, contained
|
|
87
|
-
* entity. Leave it off provenance or template pointers (`
|
|
87
|
+
* entity. Leave it off provenance or template pointers (`sourceSectionId`,
|
|
88
88
|
* `templateId`), cross-tenant references, or anything that may be written in a
|
|
89
89
|
* different transaction than its target — a hard constraint there would reject
|
|
90
90
|
* the write and break out-of-order sync. The constraint is emitted as
|
|
@@ -157,7 +157,7 @@ export declare const relation: {
|
|
|
157
157
|
* project: relation.belongsTo('projects', 'projectId'),
|
|
158
158
|
*
|
|
159
159
|
* // Register an FK index for O(1) child lookups
|
|
160
|
-
*
|
|
160
|
+
* section: relation.belongsTo('sections', 'sectionId', { index: true }),
|
|
161
161
|
*
|
|
162
162
|
* // Auto-populate the parent on delta arrival
|
|
163
163
|
* team: relation.belongsTo('teams', 'teamId', { enrich: true }),
|
|
@@ -167,7 +167,7 @@ export declare const relation: {
|
|
|
167
167
|
*
|
|
168
168
|
* // Mark the soft side of a cycle so the priority computer breaks
|
|
169
169
|
* // the cycle deterministically instead of tying the two models.
|
|
170
|
-
*
|
|
170
|
+
* report: relation.belongsTo('reports', 'reportId', { defer: true }),
|
|
171
171
|
* ```
|
|
172
172
|
*/
|
|
173
173
|
readonly belongsTo: <Target extends string, Field extends string, const Opts extends BelongsToOptions = Record<string, never>>(target: Target, foreignKey: Field, options?: Opts) => RelationDef<"belongsTo", Target, Field, Opts>;
|
|
@@ -180,11 +180,11 @@ export declare const relation: {
|
|
|
180
180
|
* child model automatically.
|
|
181
181
|
*
|
|
182
182
|
* ```ts
|
|
183
|
-
*
|
|
184
|
-
* // →
|
|
183
|
+
* blocks: relation.hasMany('blocks', 'sectionId'),
|
|
184
|
+
* // → section.blocks returns all Block[] where sectionId === section.id
|
|
185
185
|
*
|
|
186
|
-
*
|
|
187
|
-
* // →
|
|
186
|
+
* blocks: relation.hasMany('blocks', 'sectionId', { orderBy: 'zIndex' }),
|
|
187
|
+
* // → section.blocks returns Block[] sorted by zIndex ascending
|
|
188
188
|
* ```
|
|
189
189
|
*/
|
|
190
190
|
readonly hasMany: <Target extends string, Field extends string>(target: Target, foreignKey: Field, options?: {
|
|
@@ -33,7 +33,7 @@ class RelationBuilder {
|
|
|
33
33
|
* Stashed by `hasMany` when the caller provides `{ orderBy }`. Read
|
|
34
34
|
* back in `createSyncEngine` to install the sort comparator on the
|
|
35
35
|
* generated relation getter. Declared on the builder so both writer
|
|
36
|
-
* and reader stay type-safe — no
|
|
36
|
+
* and reader stay type-safe — no double-cast smuggle through `Record<...>`.
|
|
37
37
|
*/
|
|
38
38
|
_orderBy;
|
|
39
39
|
constructor(type, target, foreignKey, options) {
|
|
@@ -55,7 +55,7 @@ export const relation = {
|
|
|
55
55
|
* project: relation.belongsTo('projects', 'projectId'),
|
|
56
56
|
*
|
|
57
57
|
* // Register an FK index for O(1) child lookups
|
|
58
|
-
*
|
|
58
|
+
* section: relation.belongsTo('sections', 'sectionId', { index: true }),
|
|
59
59
|
*
|
|
60
60
|
* // Auto-populate the parent on delta arrival
|
|
61
61
|
* team: relation.belongsTo('teams', 'teamId', { enrich: true }),
|
|
@@ -65,7 +65,7 @@ export const relation = {
|
|
|
65
65
|
*
|
|
66
66
|
* // Mark the soft side of a cycle so the priority computer breaks
|
|
67
67
|
* // the cycle deterministically instead of tying the two models.
|
|
68
|
-
*
|
|
68
|
+
* report: relation.belongsTo('reports', 'reportId', { defer: true }),
|
|
69
69
|
* ```
|
|
70
70
|
*/
|
|
71
71
|
belongsTo(target, foreignKey, options) {
|
|
@@ -80,11 +80,11 @@ export const relation = {
|
|
|
80
80
|
* child model automatically.
|
|
81
81
|
*
|
|
82
82
|
* ```ts
|
|
83
|
-
*
|
|
84
|
-
* // →
|
|
83
|
+
* blocks: relation.hasMany('blocks', 'sectionId'),
|
|
84
|
+
* // → section.blocks returns all Block[] where sectionId === section.id
|
|
85
85
|
*
|
|
86
|
-
*
|
|
87
|
-
* // →
|
|
86
|
+
* blocks: relation.hasMany('blocks', 'sectionId', { orderBy: 'zIndex' }),
|
|
87
|
+
* // → section.blocks returns Block[] sorted by zIndex ascending
|
|
88
88
|
* ```
|
|
89
89
|
*/
|
|
90
90
|
hasMany(target, foreignKey, options) {
|
|
@@ -27,12 +27,3 @@ export declare const residencySchema: z.ZodEnum<{
|
|
|
27
27
|
export type ModelResidency = z.infer<typeof residencySchema>;
|
|
28
28
|
/** Default residency for a model that doesn't declare one — the tenant data plane. */
|
|
29
29
|
export declare const DEFAULT_RESIDENCY: ModelResidency;
|
|
30
|
-
/** @deprecated Use `residencySchema`. */
|
|
31
|
-
export declare const planeSchema: z.ZodEnum<{
|
|
32
|
-
tenant: "tenant";
|
|
33
|
-
control: "control";
|
|
34
|
-
}>;
|
|
35
|
-
/** @deprecated Use `ModelResidency`. */
|
|
36
|
-
export type SchemaPlane = ModelResidency;
|
|
37
|
-
/** @deprecated Use `DEFAULT_RESIDENCY`. */
|
|
38
|
-
export declare const DEFAULT_PLANE: "tenant";
|
|
@@ -23,8 +23,3 @@ import { z } from 'zod';
|
|
|
23
23
|
export const residencySchema = z.enum(['tenant', 'control']);
|
|
24
24
|
/** Default residency for a model that doesn't declare one — the tenant data plane. */
|
|
25
25
|
export const DEFAULT_RESIDENCY = 'tenant';
|
|
26
|
-
// ── Deprecated aliases (published schema subpath) ───────────────────────────
|
|
27
|
-
/** @deprecated Use `residencySchema`. */
|
|
28
|
-
export const planeSchema = residencySchema;
|
|
29
|
-
/** @deprecated Use `DEFAULT_RESIDENCY`. */
|
|
30
|
-
export const DEFAULT_PLANE = DEFAULT_RESIDENCY;
|
|
@@ -14,7 +14,7 @@ import { z } from 'zod';
|
|
|
14
14
|
* Reads fields off an identity context (`organizationId`, `teamIds`).
|
|
15
15
|
*
|
|
16
16
|
* • {@link EntityRole} — "which groups does this *record* live in?" Reads
|
|
17
|
-
* fields off the record itself (`id`, `
|
|
17
|
+
* fields off the record itself (`id`, `reportId`), so the server can fan a
|
|
18
18
|
* committed delta to the right entity streams regardless of what the
|
|
19
19
|
* committer was subscribed to.
|
|
20
20
|
*
|
|
@@ -110,11 +110,11 @@ export type Role = z.infer<typeof roleSchema>;
|
|
|
110
110
|
export type IdentityRole = Role;
|
|
111
111
|
/**
|
|
112
112
|
* Record-anchored role. Reads a record field; `kind` names the group. A record
|
|
113
|
-
* can route to a group keyed by its own `id` *or* a foreign key like `
|
|
113
|
+
* can route to a group keyed by its own `id` *or* a foreign key like `reportId`.
|
|
114
114
|
*
|
|
115
115
|
* ```ts
|
|
116
|
-
* entityRole({ kind: '
|
|
117
|
-
* entityRole({ kind: '
|
|
116
|
+
* entityRole({ kind: 'report', source: 'id' }) // a report → report:<id>
|
|
117
|
+
* entityRole({ kind: 'report', source: 'reportId' }) // a block → its parent report
|
|
118
118
|
* ```
|
|
119
119
|
*/
|
|
120
120
|
export type EntityRole = Role;
|
|
@@ -203,7 +203,7 @@ export declare function entityRole(spec: {
|
|
|
203
203
|
/**
|
|
204
204
|
* Evaluate a {@link RoleSource} against a context. Absent or falsy fields yield
|
|
205
205
|
* `[]`, so a role whose field isn't present (a user with no `teamIds`, a record
|
|
206
|
-
* with no `
|
|
206
|
+
* with no `reportId`) is a silent no-op.
|
|
207
207
|
*/
|
|
208
208
|
export declare function extractRoleIds(context: RoleContext, source: RoleSource): readonly string[];
|
|
209
209
|
/** Identity-side name for {@link extractRoleIds}. */
|
|
@@ -14,7 +14,7 @@ import { z } from 'zod';
|
|
|
14
14
|
* Reads fields off an identity context (`organizationId`, `teamIds`).
|
|
15
15
|
*
|
|
16
16
|
* • {@link EntityRole} — "which groups does this *record* live in?" Reads
|
|
17
|
-
* fields off the record itself (`id`, `
|
|
17
|
+
* fields off the record itself (`id`, `reportId`), so the server can fan a
|
|
18
18
|
* committed delta to the right entity streams regardless of what the
|
|
19
19
|
* committer was subscribed to.
|
|
20
20
|
*
|
|
@@ -73,7 +73,7 @@ export function identityAnchor(kind, id) {
|
|
|
73
73
|
// ── Role source ─────────────────────────────────────────────────────────────
|
|
74
74
|
/** Validates how a role pulls ids out of a context (identity or record). */
|
|
75
75
|
export const roleSourceSchema = z.object({
|
|
76
|
-
/** The context field to read, e.g. `'organizationId'`, `'id'`, `'
|
|
76
|
+
/** The context field to read, e.g. `'organizationId'`, `'id'`, `'reportId'`. */
|
|
77
77
|
field: z.string().regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, 'source must be a valid identifier'),
|
|
78
78
|
/**
|
|
79
79
|
* When `true`, `field` holds an array; every non-empty string element yields
|
|
@@ -88,7 +88,7 @@ export const roleSourceSchema = z.object({
|
|
|
88
88
|
* no template/placeholder for the author to get wrong.
|
|
89
89
|
*/
|
|
90
90
|
export const roleSchema = z.object({
|
|
91
|
-
kind: z.string().regex(/^[a-z][a-z0-9_]*$/, 'kind must be a lowercase identifier, e.g. "
|
|
91
|
+
kind: z.string().regex(/^[a-z][a-z0-9_]*$/, 'kind must be a lowercase identifier, e.g. "report"'),
|
|
92
92
|
source: roleSourceSchema,
|
|
93
93
|
});
|
|
94
94
|
/** Validates an {@link IdentityRole}. */
|
|
@@ -102,7 +102,7 @@ export const entityRoleSchema = roleSchema;
|
|
|
102
102
|
*/
|
|
103
103
|
export const scopeSchema = z.union([
|
|
104
104
|
z.boolean(),
|
|
105
|
-
z.string().regex(/^[a-z][a-z0-9_]*$/, 'scope kind must be a lowercase identifier, e.g. "
|
|
105
|
+
z.string().regex(/^[a-z][a-z0-9_]*$/, 'scope kind must be a lowercase identifier, e.g. "workspace"'),
|
|
106
106
|
]);
|
|
107
107
|
/**
|
|
108
108
|
* Validates a model's `grants` membership edge. Both values are relation names
|
|
@@ -148,7 +148,7 @@ export function entityRole(spec) {
|
|
|
148
148
|
/**
|
|
149
149
|
* Evaluate a {@link RoleSource} against a context. Absent or falsy fields yield
|
|
150
150
|
* `[]`, so a role whose field isn't present (a user with no `teamIds`, a record
|
|
151
|
-
* with no `
|
|
151
|
+
* with no `reportId`) is a silent no-op.
|
|
152
152
|
*/
|
|
153
153
|
export function extractRoleIds(context, source) {
|
|
154
154
|
const raw = context[source.field];
|
|
@@ -141,7 +141,7 @@ export type BaseModelFields = z.infer<typeof baseFieldsSchema>;
|
|
|
141
141
|
* input types, since methods are not valid input.
|
|
142
142
|
*/
|
|
143
143
|
export interface BaseModelMethods {
|
|
144
|
-
/** Wire-format model name (e.g. `'
|
|
144
|
+
/** Wire-format model name (e.g. `'Section'`, `'Comment'`). */
|
|
145
145
|
getModelName(): string;
|
|
146
146
|
/** Plain-object serialization suitable for sending over the wire. */
|
|
147
147
|
toJSON(): Record<string, unknown>;
|
|
@@ -208,9 +208,11 @@ type RegisteredSchema = import('../types/global.js').Register extends {
|
|
|
208
208
|
*/
|
|
209
209
|
export type Model<A, B = never> = [B] extends [never] ? A extends keyof RegisteredSchema['models'] ? InferModel<RegisteredSchema, A> : never : A extends Schema ? InferModel<A, B extends keyof A['models'] ? B : never> : never;
|
|
210
210
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
211
|
+
* The row type {@link Model} resolves to. Internal: `Model<typeof schema,
|
|
212
|
+
* 'tasks'>` is the published spelling, because it reads as the domain rather
|
|
213
|
+
* than the machinery. This one is no longer exported from any subpath — it
|
|
214
|
+
* stays because `Model` is defined in terms of it, not as a second name for
|
|
215
|
+
* the same idea.
|
|
214
216
|
*/
|
|
215
217
|
export type InferModel<S extends Schema, ModelName extends keyof S['models']> = S['models'][ModelName] extends ModelDef<infer Shape, infer R, infer C> ? // `Omit<…, keyof BaseModelFields>` so a model that (wrongly) redeclares a
|
|
216
218
|
Omit<z.infer<z.ZodObject<Shape>>, keyof BaseModelFields> & BaseModelFields & BaseModelMethods & InferComputed<C> & InferRelations<S, R> : never;
|
|
@@ -218,7 +220,7 @@ Omit<z.infer<z.ZodObject<Shape>>, keyof BaseModelFields> & BaseModelFields & Bas
|
|
|
218
220
|
* Infer the relation accessor types from a model's relations record.
|
|
219
221
|
*
|
|
220
222
|
* At runtime the engine installs a getter for each declared relation, so this
|
|
221
|
-
* type mirrors them and you can read `
|
|
223
|
+
* type mirrors them and you can read `section.blocks` and `section.report` without a
|
|
222
224
|
* cast.
|
|
223
225
|
*
|
|
224
226
|
* - `hasMany` → `InferModel<S, Target>[]`
|
|
@@ -226,7 +228,7 @@ Omit<z.infer<z.ZodObject<Shape>>, keyof BaseModelFields> & BaseModelFields & Bas
|
|
|
226
228
|
* when the foreign key is unset or the parent has not loaded yet)
|
|
227
229
|
*
|
|
228
230
|
* Kept `readonly` because the accessors are getters with no setter — assigning
|
|
229
|
-
* to `
|
|
231
|
+
* to `section.blocks` would have no effect at runtime.
|
|
230
232
|
*/
|
|
231
233
|
export type InferRelations<S extends Schema, R extends RelationRecord> = string extends keyof R ? unknown : {
|
|
232
234
|
readonly [K in keyof R]: R[K] extends RelationDef<infer Type, infer Target> ? Target extends keyof S['models'] ? Type extends 'hasMany' ? InferModel<S, Target>[] : Type extends 'hasOne' | 'belongsTo' ? InferModel<S, Target> | undefined : never : never : never;
|
|
@@ -239,7 +241,7 @@ export type InferRelations<S extends Schema, R extends RelationRecord> = string
|
|
|
239
241
|
*
|
|
240
242
|
* Relations (`hasMany` / `belongsTo`) are store-backed getters that exist only
|
|
241
243
|
* on the pool's model instances, so a reactive row honestly omits them —
|
|
242
|
-
* reading `row.
|
|
244
|
+
* reading `row.blocks` is a compile error instead of a silent `undefined`.
|
|
243
245
|
* Compose relations through a selector or hook instead.
|
|
244
246
|
*
|
|
245
247
|
* The same pairing other data layers converged on: Zero's data-only `Row<...>`
|
|
@@ -253,12 +255,12 @@ Omit<z.infer<z.ZodObject<Shape>>, keyof BaseModelFields> & BaseModelFields & Inf
|
|
|
253
255
|
* `ablo/register.ts` registers the schema, a single argument is all it takes:
|
|
254
256
|
*
|
|
255
257
|
* ```ts
|
|
256
|
-
* type
|
|
257
|
-
* type
|
|
258
|
+
* type SectionRow = Row<'sections'>; // data fields + computeds, no relations
|
|
259
|
+
* type Section = Model<'sections'>; // the pool's model instance
|
|
258
260
|
* ```
|
|
259
261
|
*
|
|
260
262
|
* Without that registration, or for a second schema, pass the schema
|
|
261
|
-
* explicitly: `Row<typeof schema, '
|
|
263
|
+
* explicitly: `Row<typeof schema, 'sections'>`.
|
|
262
264
|
*/
|
|
263
265
|
export type Row<A, B = never> = [B] extends [never] ? A extends keyof RegisteredSchema['models'] ? InferRow<RegisteredSchema, A> : never : A extends Schema ? InferRow<A, B extends keyof A['models'] ? B : never> : never;
|
|
264
266
|
/**
|