@abloatai/ablo 0.26.0 → 0.27.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/CHANGELOG.md +14 -0
- package/README.md +101 -85
- package/dist/BaseSyncedStore.d.ts +85 -88
- package/dist/BaseSyncedStore.js +131 -147
- package/dist/Database.d.ts +54 -68
- package/dist/Database.js +97 -113
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +12 -16
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +46 -61
- package/dist/ModelRegistry.d.ts +21 -19
- package/dist/ModelRegistry.js +23 -27
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +5 -6
- package/dist/SyncClient.d.ts +112 -112
- package/dist/SyncClient.js +165 -172
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +9 -9
- package/dist/adapters/inMemoryStorage.js +9 -9
- package/dist/agent/Agent.d.ts +27 -32
- package/dist/agent/Agent.js +18 -19
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +5 -5
- package/dist/agent/session.d.ts +47 -44
- package/dist/agent/session.js +37 -48
- package/dist/agent/types.d.ts +26 -31
- package/dist/agent/types.js +6 -7
- package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
- package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
- package/dist/ai-sdk/coordinationContext.d.ts +46 -0
- package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +6 -7
- package/dist/ai-sdk/wrap.js +1 -1
- package/dist/auth/credentialPolicy.d.ts +69 -74
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +6 -5
- package/dist/auth/credentialSource.js +9 -10
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +31 -37
- package/dist/auth/schemas.d.ts +5 -4
- package/dist/auth/schemas.js +5 -4
- package/dist/batching/index.d.ts +19 -21
- package/dist/batching/index.js +14 -17
- package/dist/cli.cjs +167 -119
- package/dist/client/Ablo.d.ts +73 -73
- package/dist/client/Ablo.js +125 -160
- package/dist/client/ApiClient.d.ts +30 -19
- package/dist/client/ApiClient.js +133 -38
- package/dist/client/auth.d.ts +47 -47
- package/dist/client/auth.js +108 -117
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +5 -6
- package/dist/client/consoleLogger.js +5 -6
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +25 -30
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +152 -122
- package/dist/client/credentialEndpoint.d.ts +40 -42
- package/dist/client/credentialEndpoint.js +35 -36
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +9 -12
- package/dist/client/hostedEndpoints.js +9 -12
- package/dist/client/httpClient.d.ts +57 -53
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +47 -58
- package/dist/client/modelRegistration.d.ts +5 -9
- package/dist/client/modelRegistration.js +67 -87
- package/dist/client/options.d.ts +134 -157
- package/dist/client/options.js +3 -7
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +64 -75
- package/dist/client/resourceTypes.js +4 -10
- package/dist/client/schemaConfig.d.ts +31 -43
- package/dist/client/schemaConfig.js +38 -50
- package/dist/client/sessionMint.d.ts +16 -12
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +8 -9
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +15 -20
- package/dist/client/wsMutationExecutor.js +17 -23
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -4
- package/dist/coordination/index.d.ts +10 -8
- package/dist/coordination/index.js +14 -12
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -10
- package/dist/coordination/trace.js +13 -14
- package/dist/core/DatabaseManager.d.ts +5 -7
- package/dist/core/DatabaseManager.js +15 -19
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +22 -28
- package/dist/core/QueryView.d.ts +8 -8
- package/dist/core/QueryView.js +2 -2
- package/dist/core/StoreManager.d.ts +12 -14
- package/dist/core/StoreManager.js +21 -24
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +17 -12
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +42 -43
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +63 -61
- package/dist/core/storeContract.js +8 -12
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +107 -99
- package/dist/errorCodes.js +131 -132
- package/dist/errors.d.ts +160 -166
- package/dist/errors.js +155 -158
- package/dist/index.d.ts +30 -27
- package/dist/index.js +89 -86
- package/dist/interfaces/index.d.ts +102 -113
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +41 -40
- package/dist/mutators/RecordingTransaction.d.ts +16 -16
- package/dist/mutators/RecordingTransaction.js +31 -37
- package/dist/mutators/Transaction.d.ts +18 -26
- package/dist/mutators/Transaction.js +14 -20
- package/dist/mutators/UndoManager.d.ts +122 -131
- package/dist/mutators/UndoManager.js +145 -156
- package/dist/mutators/defineMutators.d.ts +23 -34
- package/dist/mutators/defineMutators.js +14 -20
- package/dist/mutators/inverseOp.d.ts +12 -15
- package/dist/mutators/inverseOp.js +12 -15
- package/dist/mutators/mutateActions.d.ts +10 -9
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +9 -8
- package/dist/mutators/readerActions.js +2 -2
- package/dist/mutators/undoApply.d.ts +31 -27
- package/dist/mutators/undoApply.js +26 -24
- package/dist/policy/index.d.ts +5 -3
- package/dist/policy/index.js +5 -3
- package/dist/policy/types.d.ts +104 -100
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +28 -23
- package/dist/query/client.js +45 -43
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +1 -1
- package/dist/react/AbloProvider.js +2 -2
- package/dist/react/context.d.ts +25 -28
- package/dist/react/context.js +9 -10
- package/dist/react/index.d.ts +41 -42
- package/dist/react/index.js +37 -38
- package/dist/react/internalContext.d.ts +17 -19
- package/dist/react/useAblo.d.ts +23 -22
- package/dist/react/useAblo.js +16 -14
- package/dist/react/useCurrentUserId.d.ts +8 -7
- package/dist/react/useCurrentUserId.js +8 -7
- package/dist/react/useErrorListener.d.ts +7 -7
- package/dist/react/useErrorListener.js +10 -11
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +8 -8
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useReactive.js +2 -2
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +21 -25
- package/dist/schema/coordination.js +21 -25
- package/dist/schema/ddl.d.ts +43 -39
- package/dist/schema/ddl.js +75 -68
- package/dist/schema/ddlLock.d.ts +20 -24
- package/dist/schema/ddlLock.js +18 -23
- package/dist/schema/diff.d.ts +99 -61
- package/dist/schema/diff.js +43 -34
- package/dist/schema/field.d.ts +37 -42
- package/dist/schema/field.js +35 -48
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +21 -23
- package/dist/schema/model.d.ts +118 -143
- package/dist/schema/model.js +22 -33
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +5 -3
- package/dist/schema/queries.d.ts +29 -31
- package/dist/schema/queries.js +23 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +16 -13
- package/dist/schema/residency.js +16 -13
- package/dist/schema/roles.d.ts +36 -43
- package/dist/schema/roles.js +31 -37
- package/dist/schema/schema.d.ts +33 -42
- package/dist/schema/schema.js +31 -32
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +28 -31
- package/dist/schema/serialize.js +27 -31
- package/dist/schema/sugar.d.ts +17 -32
- package/dist/schema/sugar.js +14 -29
- package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
- package/dist/schema/syncDeltaRow.js +89 -0
- package/dist/schema/tenancy.d.ts +44 -46
- package/dist/schema/tenancy.js +46 -48
- package/dist/server/adapter.d.ts +58 -58
- package/dist/server/adapter.js +13 -14
- package/dist/server/commit.d.ts +60 -64
- package/dist/server/index.d.ts +9 -10
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +70 -0
- package/dist/server/readConfig.js +8 -0
- package/dist/server/storageMode.d.ts +23 -0
- package/dist/server/storageMode.js +17 -0
- package/dist/source/adapter.d.ts +30 -25
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +30 -25
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +24 -23
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +9 -8
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +22 -25
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +17 -11
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +28 -28
- package/dist/source/connectorProtocol.d.ts +160 -0
- package/dist/source/connectorProtocol.js +162 -0
- package/dist/source/contract.d.ts +26 -27
- package/dist/source/contract.js +28 -29
- package/dist/source/factory.d.ts +46 -58
- package/dist/source/factory.js +22 -27
- package/dist/source/index.d.ts +7 -9
- package/dist/source/index.js +12 -14
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +9 -10
- package/dist/source/next.js +6 -7
- package/dist/source/pushQueue.d.ts +69 -47
- package/dist/source/pushQueue.js +32 -28
- package/dist/source/signing.d.ts +46 -17
- package/dist/source/signing.js +28 -11
- package/dist/source/types.d.ts +121 -104
- package/dist/source/types.js +13 -14
- package/dist/stores/ObjectStore.d.ts +10 -11
- package/dist/stores/ObjectStore.js +11 -12
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +7 -11
- package/dist/stores/SyncActionStore.js +13 -17
- package/dist/surface.d.ts +27 -20
- package/dist/surface.js +27 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
- package/dist/sync/ConnectionManager.d.ts +39 -50
- package/dist/sync/ConnectionManager.js +55 -66
- package/dist/sync/NetworkProbe.d.ts +24 -29
- package/dist/sync/NetworkProbe.js +63 -69
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
- package/dist/sync/SyncWebSocket.d.ts +139 -165
- package/dist/sync/SyncWebSocket.js +191 -223
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +11 -11
- package/dist/sync/bootstrapApply.d.ts +34 -24
- package/dist/sync/bootstrapApply.js +27 -19
- package/dist/sync/commitFrames.d.ts +21 -20
- package/dist/sync/commitFrames.js +18 -18
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +105 -23
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +12 -14
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +104 -104
- package/dist/sync/credentialLifecycle.js +140 -147
- package/dist/sync/deltaPipeline.d.ts +36 -34
- package/dist/sync/deltaPipeline.js +64 -65
- package/dist/sync/groupChange.d.ts +63 -61
- package/dist/sync/groupChange.js +74 -78
- package/dist/sync/heartbeat.d.ts +34 -33
- package/dist/sync/heartbeat.js +31 -31
- package/dist/sync/participants.d.ts +19 -19
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +17 -21
- package/dist/sync/syncCursor.js +17 -21
- package/dist/sync/syncPlan.d.ts +28 -36
- package/dist/sync/syncPlan.js +18 -19
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +35 -36
- package/dist/sync/wsFrameHandlers.js +63 -67
- package/dist/testing/fixtures/bootstrap.d.ts +12 -6
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +30 -33
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +11 -10
- package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
- package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
- package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +2 -2
- package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
- package/dist/testing/mocks/MockMutationExecutor.js +15 -14
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
- package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
- package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
- package/dist/testing/mocks/MockSyncContext.js +15 -13
- package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +181 -176
- package/dist/transactions/TransactionQueue.js +338 -350
- package/dist/transactions/TransactionStore.d.ts +6 -4
- package/dist/transactions/TransactionStore.js +6 -4
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +41 -17
- package/dist/transactions/coalesceRules.js +40 -17
- package/dist/transactions/commitPayload.d.ts +48 -52
- package/dist/transactions/commitPayload.js +48 -57
- package/dist/transactions/deltaConfirmation.d.ts +20 -22
- package/dist/transactions/deltaConfirmation.js +37 -45
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
- package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +71 -77
- package/dist/types/index.js +22 -22
- package/dist/types/modelData.d.ts +6 -8
- package/dist/types/modelData.js +5 -7
- package/dist/types/participant.d.ts +10 -11
- package/dist/types/participant.js +6 -8
- package/dist/types/streams.d.ts +208 -195
- package/dist/types/streams.js +7 -7
- package/dist/utils/asyncIterator.d.ts +25 -32
- package/dist/utils/asyncIterator.js +25 -32
- package/dist/utils/duration.d.ts +12 -15
- package/dist/utils/duration.js +12 -15
- package/dist/utils/mobxSetup.d.ts +53 -0
- package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
- package/dist/webhooks/events.d.ts +21 -16
- package/dist/webhooks/events.js +10 -8
- package/dist/webhooks/index.d.ts +5 -7
- package/dist/webhooks/index.js +5 -7
- package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
- package/dist/wire/delta.js +114 -0
- package/dist/wire/errorEnvelope.d.ts +30 -31
- package/dist/wire/errorEnvelope.js +34 -40
- package/dist/wire/frames.d.ts +79 -86
- package/dist/wire/frames.js +26 -33
- package/dist/wire/index.d.ts +14 -12
- package/dist/wire/index.js +30 -26
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +25 -32
- package/dist/wire/protocol.js +25 -32
- package/dist/wire/protocolVersion.d.ts +44 -40
- package/dist/wire/protocolVersion.js +44 -40
- package/docs/coordination.md +59 -0
- package/package.json +11 -10
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/read-config.d.ts +0 -67
- package/dist/server/read-config.js +0 -8
- package/dist/server/storage-mode.d.ts +0 -8
- package/dist/server/storage-mode.js +0 -28
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/transactions/optimistic.d.ts +0 -24
- package/dist/transactions/optimistic.js +0 -45
- package/dist/utils/mobx-setup.d.ts +0 -42
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Support for the endpoint-string form of `apiKey`.
|
|
3
3
|
*
|
|
4
|
-
* `Ablo({ schema, apiKey: '/api/ablo-session' })
|
|
5
|
-
* session-mint route and the
|
|
6
|
-
* parses the minted token, keeps it fresh
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* function form of `apiKey` remains the escape hatch for custom headers,
|
|
4
|
+
* With `Ablo({ schema, apiKey: '/api/ablo-session' })`, you point the client at
|
|
5
|
+
* your own session-mint route and the client owns the exchange: it POSTs to the
|
|
6
|
+
* endpoint, parses the minted token, keeps it fresh, and classifies failures
|
|
7
|
+
* onto the resolver's three outcomes. The string form covers the common case;
|
|
8
|
+
* the function form of `apiKey` remains the escape hatch for custom headers,
|
|
10
9
|
* bodies, or non-HTTP mints.
|
|
11
10
|
*
|
|
12
|
-
*
|
|
13
|
-
* `https://` is an endpoint
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* always a literal key
|
|
11
|
+
* The form is detected by prefix: a string starting with `/`, `http://`, or
|
|
12
|
+
* `https://` is an endpoint, and anything else is a literal key. Ablo keys are
|
|
13
|
+
* prefixed (`sk_`/`pk_`/`ek_`/`rk_`), so the two shapes cannot collide. An
|
|
14
|
+
* `ABLO_API_KEY` environment value is never treated as an endpoint — it is
|
|
15
|
+
* always a literal key (see `resolveApiKey`).
|
|
17
16
|
*
|
|
18
|
-
* Wire contract
|
|
17
|
+
* Wire contract:
|
|
19
18
|
* POST <endpoint> (same-origin, `credentials: 'include'` so cookies flow)
|
|
20
|
-
* → 200 `{ token, expiresAt? }`
|
|
21
|
-
* → 200 `{ token: null }` or 401/403
|
|
22
|
-
* → anything else
|
|
19
|
+
* → 200 `{ token, expiresAt? }` a fresh short-lived `ek_`/`rk_`
|
|
20
|
+
* → 200 `{ token: null }` or 401/403 the login itself is gone (sign out)
|
|
21
|
+
* → anything else transient — retry, do not sign out
|
|
23
22
|
*
|
|
24
|
-
* The
|
|
25
|
-
*
|
|
26
|
-
* user out on a 500
|
|
27
|
-
*
|
|
28
|
-
* retry contract, translated to HTTP statuses).
|
|
23
|
+
* The three-way mapping is the reason to build this in. Hand-written token
|
|
24
|
+
* fetchers routinely get it wrong — mapping any non-OK response to `null` signs
|
|
25
|
+
* the user out on a 500. Encoded here once, every consumer inherits the correct
|
|
26
|
+
* split between a terminal sign-out and a transient retry.
|
|
29
27
|
*/
|
|
30
28
|
/**
|
|
31
29
|
* Is this `apiKey` string a session-mint endpoint rather than a literal key?
|
|
@@ -35,22 +33,23 @@ export function isCredentialEndpoint(value) {
|
|
|
35
33
|
return value.startsWith('/') || /^https?:\/\//i.test(value);
|
|
36
34
|
}
|
|
37
35
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* - resolves the minted token string on success
|
|
41
|
-
* - resolves `null` when the login is gone (401
|
|
42
|
-
* `{ token: null }`)
|
|
43
|
-
* -
|
|
44
|
-
* response)
|
|
36
|
+
* Builds the resolver behind an endpoint-string `apiKey`. It follows the
|
|
37
|
+
* {@link ApiKeySetter} contract end to end:
|
|
38
|
+
* - resolves the minted token string on success;
|
|
39
|
+
* - resolves `null` when the login is gone (a 401 or 403, or an explicit
|
|
40
|
+
* `{ token: null }`) — terminal, so the client signs out;
|
|
41
|
+
* - throws on anything transient (a network failure, a 5xx or 429, or a
|
|
42
|
+
* malformed response) — so the lifecycle backs off and retries without
|
|
43
|
+
* signing out.
|
|
45
44
|
*
|
|
46
|
-
* A relative endpoint invoked server
|
|
47
|
-
* transient by contract
|
|
48
|
-
*
|
|
45
|
+
* A relative endpoint invoked on a server (where `fetch` has no origin) throws,
|
|
46
|
+
* which is transient by contract; the credential lifecycle translates that exact
|
|
47
|
+
* failure into an actionable "use an absolute URL server-side" warning.
|
|
49
48
|
*/
|
|
50
49
|
export function createEndpointCredentialResolver(endpoint) {
|
|
51
50
|
return async () => {
|
|
52
|
-
// fetch() rejections (offline, DNS, relative URL
|
|
53
|
-
// a throw
|
|
51
|
+
// `fetch()` rejections (offline, DNS, a relative URL on a server) propagate
|
|
52
|
+
// as-is: a throw is the transient signal in the resolver contract.
|
|
54
53
|
const res = await fetch(endpoint, {
|
|
55
54
|
method: 'POST',
|
|
56
55
|
credentials: 'include',
|
|
@@ -70,9 +69,9 @@ export function createEndpointCredentialResolver(endpoint) {
|
|
|
70
69
|
catch {
|
|
71
70
|
throw new Error(`credential endpoint ${endpoint} returned non-JSON — expected { token }`);
|
|
72
71
|
}
|
|
73
|
-
// Distinguish "explicitly signed out" ({ token: null }) from "not a mint
|
|
74
|
-
// endpoint at all" (no `token` key
|
|
75
|
-
//
|
|
72
|
+
// Distinguish "explicitly signed out" (`{ token: null }`) from "not a mint
|
|
73
|
+
// endpoint at all" (no `token` key). A misconfiguration must fail loudly and
|
|
74
|
+
// transiently, never as a silent sign-out.
|
|
76
75
|
if (typeof body !== 'object' || body === null || !('token' in body)) {
|
|
77
76
|
throw new Error(`credential endpoint ${endpoint} returned no \`token\` field — expected { token }`);
|
|
78
77
|
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The functional update — `ablo.<model>.update(id, current => next)`.
|
|
3
3
|
*
|
|
4
|
-
* This is the
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* write re-
|
|
9
|
-
* awareness, and no `stale_context`
|
|
4
|
+
* This is the surface that just works under contention. You express only your
|
|
5
|
+
* intent — given the latest row, here is the next state — and the client does
|
|
6
|
+
* the rest: it reads the fresh row and its watermark, runs your updater, writes
|
|
7
|
+
* the result as a compare-and-swap against that watermark, and on any concurrent
|
|
8
|
+
* write it re-reads, recomputes, and retries. No claim, no identity, no transport
|
|
9
|
+
* awareness, and no `stale_context` or `claim_*` error codes ever reach the
|
|
10
10
|
* caller. The write either lands or, at the extreme, throws a single
|
|
11
|
-
* {@link AbloContentionError}
|
|
11
|
+
* {@link AbloContentionError} once the reconcile budget is spent.
|
|
12
12
|
*
|
|
13
|
-
* Correctness comes from the `readAt` watermark
|
|
14
|
-
* (optimistic concurrency
|
|
15
|
-
*
|
|
16
|
-
* behaves identically on both transports
|
|
17
|
-
* the same two
|
|
18
|
-
* the guarantee
|
|
13
|
+
* Correctness comes from the `readAt` watermark plus `onStale: 'reject'`
|
|
14
|
+
* (optimistic concurrency, or compare-and-swap), not from participant identity.
|
|
15
|
+
* That is why it is immune to the shared-credential silent-overwrite hazard and
|
|
16
|
+
* behaves identically on both transports: the HTTP and WebSocket clients inject
|
|
17
|
+
* the same two functions ({@link ReconcileTransport}) into the shared loop below,
|
|
18
|
+
* so the guarantee cannot drift between them — only the mechanism differs.
|
|
19
19
|
*
|
|
20
20
|
* The mental model is React's `setState(prev => next)`: pass a function of the
|
|
21
|
-
* current state
|
|
21
|
+
* current state and the runtime owns reconciliation.
|
|
22
22
|
*/
|
|
23
23
|
import { AbloContentionError } from '../errors.js';
|
|
24
24
|
/**
|
|
25
25
|
* The functional form of an update: given the freshly-read row, return the
|
|
26
|
-
* fields to write. Return `null`
|
|
27
|
-
* caller
|
|
26
|
+
* fields to write. Return `null` or `undefined` to make no write — a no-op the
|
|
27
|
+
* caller chose after seeing the latest state (for example, "already done").
|
|
28
28
|
*/
|
|
29
29
|
export type ModelUpdater<T> = (current: T) => Partial<T> | null | undefined | Promise<Partial<T> | null | undefined>;
|
|
30
30
|
/** Tuning for the functional update's internal reconcile loop. */
|
|
@@ -41,30 +41,32 @@ export interface ContentionOptions {
|
|
|
41
41
|
/** Reconcile rounds before a hot row is declared permanently contended. */
|
|
42
42
|
export declare const DEFAULT_CONTENTION_RETRIES = 16;
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
45
|
-
* retry" rather than a genuine failure to surface
|
|
46
|
-
* concurrency signals the functional update reconciles against:
|
|
47
|
-
* - `stale_context` —
|
|
48
|
-
* - `claim_lost` — a holder preempted
|
|
44
|
+
* Reports whether a thrown error means "another writer moved the row — re-read
|
|
45
|
+
* and retry" rather than a genuine failure to surface. These are the
|
|
46
|
+
* optimistic-concurrency signals the functional update reconciles against:
|
|
47
|
+
* - `stale_context` — the `readAt` watermark was overtaken by a concurrent write
|
|
48
|
+
* - `claim_lost` — a holder preempted the write (for example a human under `humansOverwrite`)
|
|
49
49
|
* - `claim_queued` — a holder is actively editing the row right now
|
|
50
50
|
*/
|
|
51
51
|
export declare function isReconcilableConflict(err: unknown): boolean;
|
|
52
52
|
/**
|
|
53
|
-
*
|
|
54
|
-
* own pair —
|
|
53
|
+
* The transport-specific read and write that the shared loop drives. Each client
|
|
54
|
+
* injects its own pair — the one thing that differs between the HTTP and
|
|
55
|
+
* WebSocket transports.
|
|
55
56
|
*/
|
|
56
57
|
export interface ReconcileTransport<T, R> {
|
|
57
58
|
readonly model: string;
|
|
58
59
|
readonly id: string;
|
|
59
|
-
/** Read the latest row
|
|
60
|
+
/** Read the latest row and its watermark from the authoritative store. */
|
|
60
61
|
readFresh: () => Promise<{
|
|
61
62
|
readonly data: T | null | undefined;
|
|
62
63
|
readonly stamp: number;
|
|
63
64
|
}>;
|
|
64
65
|
/**
|
|
65
|
-
* Write the computed patch as a compare-and-swap against `readAt`.
|
|
66
|
-
* a reconcilable conflict (`stale_context`
|
|
67
|
-
* overtaken — that rejection is what drives the next reconcile
|
|
66
|
+
* Write the computed patch as a compare-and-swap against `readAt`. It must
|
|
67
|
+
* throw a reconcilable conflict (`stale_context` or `claim_*`) when the
|
|
68
|
+
* watermark was overtaken — that rejection is what drives the next reconcile
|
|
69
|
+
* round.
|
|
68
70
|
*/
|
|
69
71
|
writeNext: (patch: Partial<T>, readAt: number) => Promise<R>;
|
|
70
72
|
}
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The functional update — `ablo.<model>.update(id, current => next)`.
|
|
3
3
|
*
|
|
4
|
-
* This is the
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* write re-
|
|
9
|
-
* awareness, and no `stale_context`
|
|
4
|
+
* This is the surface that just works under contention. You express only your
|
|
5
|
+
* intent — given the latest row, here is the next state — and the client does
|
|
6
|
+
* the rest: it reads the fresh row and its watermark, runs your updater, writes
|
|
7
|
+
* the result as a compare-and-swap against that watermark, and on any concurrent
|
|
8
|
+
* write it re-reads, recomputes, and retries. No claim, no identity, no transport
|
|
9
|
+
* awareness, and no `stale_context` or `claim_*` error codes ever reach the
|
|
10
10
|
* caller. The write either lands or, at the extreme, throws a single
|
|
11
|
-
* {@link AbloContentionError}
|
|
11
|
+
* {@link AbloContentionError} once the reconcile budget is spent.
|
|
12
12
|
*
|
|
13
|
-
* Correctness comes from the `readAt` watermark
|
|
14
|
-
* (optimistic concurrency
|
|
15
|
-
*
|
|
16
|
-
* behaves identically on both transports
|
|
17
|
-
* the same two
|
|
18
|
-
* the guarantee
|
|
13
|
+
* Correctness comes from the `readAt` watermark plus `onStale: 'reject'`
|
|
14
|
+
* (optimistic concurrency, or compare-and-swap), not from participant identity.
|
|
15
|
+
* That is why it is immune to the shared-credential silent-overwrite hazard and
|
|
16
|
+
* behaves identically on both transports: the HTTP and WebSocket clients inject
|
|
17
|
+
* the same two functions ({@link ReconcileTransport}) into the shared loop below,
|
|
18
|
+
* so the guarantee cannot drift between them — only the mechanism differs.
|
|
19
19
|
*
|
|
20
20
|
* The mental model is React's `setState(prev => next)`: pass a function of the
|
|
21
|
-
* current state
|
|
21
|
+
* current state and the runtime owns reconciliation.
|
|
22
22
|
*/
|
|
23
23
|
import { AbloError, AbloNotFoundError, AbloStaleContextError, AbloClaimedError, AbloContentionError, } from '../errors.js';
|
|
24
24
|
/** Reconcile rounds before a hot row is declared permanently contended. */
|
|
25
25
|
export const DEFAULT_CONTENTION_RETRIES = 16;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
* retry" rather than a genuine failure to surface
|
|
29
|
-
* concurrency signals the functional update reconciles against:
|
|
30
|
-
* - `stale_context` —
|
|
31
|
-
* - `claim_lost` — a holder preempted
|
|
27
|
+
* Reports whether a thrown error means "another writer moved the row — re-read
|
|
28
|
+
* and retry" rather than a genuine failure to surface. These are the
|
|
29
|
+
* optimistic-concurrency signals the functional update reconciles against:
|
|
30
|
+
* - `stale_context` — the `readAt` watermark was overtaken by a concurrent write
|
|
31
|
+
* - `claim_lost` — a holder preempted the write (for example a human under `humansOverwrite`)
|
|
32
32
|
* - `claim_queued` — a holder is actively editing the row right now
|
|
33
33
|
*/
|
|
34
34
|
export function isReconcilableConflict(err) {
|
|
@@ -82,6 +82,6 @@ export async function reconcileFunctionalUpdate(updater, options, transport) {
|
|
|
82
82
|
cause: lastConflict,
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
-
// Re-exported so call sites import the loop
|
|
86
|
-
// the class itself lives with the rest of the hierarchy
|
|
85
|
+
// Re-exported so call sites import the loop and its terminal error from one
|
|
86
|
+
// place; the class itself lives with the rest of the error hierarchy.
|
|
87
87
|
export { AbloContentionError };
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The hosted Ablo Cloud endpoint constants, with no dependencies of their own.
|
|
3
3
|
*
|
|
4
|
-
* This is the single place the hosted API host is declared.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* migration is ONE edit — the `LEGACY_HOSTED_API_HOSTS` rewrite list in
|
|
9
|
-
* `client/auth.ts` (four retired ablo.finance hosts) is proof such
|
|
10
|
-
* migrations happen.
|
|
4
|
+
* This is the single place the hosted API host is declared. URL resolution, the
|
|
5
|
+
* CLI's default URL, the data-source connector's base, the generated OpenAPI
|
|
6
|
+
* server entry, and the network probe's default all import from here, so
|
|
7
|
+
* changing the API domain is a one-line edit.
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
* consume
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
* These constants are kept dependency-free deliberately: several low-level
|
|
10
|
+
* modules consume them, and routing those modules through the auth layer would
|
|
11
|
+
* pull the error registry and credential policy into otherwise-clean paths and
|
|
12
|
+
* risk an import cycle.
|
|
16
13
|
*/
|
|
17
14
|
/** The hosted API domain (no scheme). */
|
|
18
15
|
export declare const ABLO_HOSTED_API_DOMAIN = "api.abloatai.com";
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The hosted Ablo Cloud endpoint constants, with no dependencies of their own.
|
|
3
3
|
*
|
|
4
|
-
* This is the single place the hosted API host is declared.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* migration is ONE edit — the `LEGACY_HOSTED_API_HOSTS` rewrite list in
|
|
9
|
-
* `client/auth.ts` (four retired ablo.finance hosts) is proof such
|
|
10
|
-
* migrations happen.
|
|
4
|
+
* This is the single place the hosted API host is declared. URL resolution, the
|
|
5
|
+
* CLI's default URL, the data-source connector's base, the generated OpenAPI
|
|
6
|
+
* server entry, and the network probe's default all import from here, so
|
|
7
|
+
* changing the API domain is a one-line edit.
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
* consume
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
* These constants are kept dependency-free deliberately: several low-level
|
|
10
|
+
* modules consume them, and routing those modules through the auth layer would
|
|
11
|
+
* pull the error registry and credential policy into otherwise-clean paths and
|
|
12
|
+
* risk an import cycle.
|
|
16
13
|
*/
|
|
17
14
|
/** The hosted API domain (no scheme). */
|
|
18
15
|
export const ABLO_HOSTED_API_DOMAIN = 'api.abloatai.com';
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Creates a stateless, typed HTTP client for server-side actors — agents,
|
|
3
|
+
* workers, and serverless handlers. It talks to Ablo over plain request/response
|
|
4
|
+
* HTTP, uses the bearer credential as its identity, and holds no WebSocket and no
|
|
5
|
+
* connection state.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* client — it's a separate stateless client where the credential carries identity
|
|
15
|
-
* and the SERVER resolves it per request.
|
|
7
|
+
* This is the counterpart to the stateful {@link Ablo} client. The stateful
|
|
8
|
+
* client is for interactive participants: it opens a WebSocket, learns its
|
|
9
|
+
* identity (user id and organization id) during the connect-and-bootstrap step,
|
|
10
|
+
* and routes writes through a queue that waits for that identity. A server-side
|
|
11
|
+
* actor has no socket, so instead of reusing that machinery it uses this client,
|
|
12
|
+
* where the credential itself carries identity and the server resolves it on
|
|
13
|
+
* every request.
|
|
16
14
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* `POST /v1/commits` and reads
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* surface as the browser client — typed proxies, stateless transport.
|
|
15
|
+
* Under the hood this wraps the schema-agnostic protocol client that
|
|
16
|
+
* {@link createProtocolClient} returns in a typed proxy. The protocol client
|
|
17
|
+
* commits over `POST /v1/commits` and reads over HTTP, authenticating with the
|
|
18
|
+
* bearer token each time; its model access is string-keyed (`api.model('slides')`).
|
|
19
|
+
* The proxy gives server code the same typed `client.<model>` surface the
|
|
20
|
+
* stateful client offers, over stateless transport.
|
|
24
21
|
*/
|
|
25
22
|
import { type AbloApiClientOptions } from './ApiClient.js';
|
|
26
23
|
import type { CommitReceipt, CommitResource, HttpClaimApi, ModelRead, ModelReadOptions, CreateSessionParams, AbloSession } from './resourceTypes.js';
|
|
@@ -28,73 +25,80 @@ import type { ModelCreateParams, ModelDeleteParams, ServerReadOptions, ModelRetr
|
|
|
28
25
|
import type { Schema, SchemaRecord, InferModel, InferCreate } from '../schema/schema.js';
|
|
29
26
|
import type { ModelUpdater, ContentionOptions } from './functionalUpdate.js';
|
|
30
27
|
export interface AbloHttpClientOptions<S extends SchemaRecord> extends Omit<AbloApiClientOptions, 'schema'> {
|
|
31
|
-
/** The schema
|
|
28
|
+
/** The schema. Used only to type the model proxies; it is never sent over the wire or read at runtime. */
|
|
32
29
|
readonly schema: Schema<S>;
|
|
33
30
|
}
|
|
34
31
|
/**
|
|
35
|
-
* The per-model
|
|
36
|
-
* request/response: reads (`retrieve
|
|
37
|
-
* and the durable-lease
|
|
38
|
-
*
|
|
39
|
-
*
|
|
32
|
+
* The per-model surface of the stateless HTTP client — everything reachable over
|
|
33
|
+
* request/response: reads (`retrieve` and `list`), writes (`create`, `update`,
|
|
34
|
+
* and `delete`), and the durable-lease {@link HttpClaimApi | claim} plane for
|
|
35
|
+
* coordinated writes. It deliberately omits the stateful client's local-cache
|
|
36
|
+
* reads (`get`, `getAll`, `getCount`) and live subscriptions (`onChange`), which
|
|
37
|
+
* need a persistent socket; those are absent from the type, so reaching for one
|
|
38
|
+
* is a compile error rather than a runtime gap.
|
|
40
39
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
40
|
+
* The read shapes differ on purpose. `retrieve` returns a {@link ModelRead}
|
|
41
|
+
* envelope of `{ data, stamp, claims }`, because a stateless client keeps no local
|
|
42
|
+
* copy of the data: the watermark (`stamp`) and any active claims must travel
|
|
43
|
+
* inline on the read so a caller can follow it with a stale-guarded write. `list`
|
|
44
|
+
* returns a plain array.
|
|
46
45
|
*/
|
|
47
46
|
export interface HttpModelClient<T, C = T> {
|
|
48
47
|
retrieve(params: ModelRetrieveParams & ModelReadOptions): Promise<ModelRead<T>>;
|
|
49
48
|
list(options?: ServerReadOptions<T>): Promise<T[]>;
|
|
50
49
|
/**
|
|
51
|
-
*
|
|
52
|
-
* framework defaults
|
|
53
|
-
*
|
|
50
|
+
* Creates a row and returns the confirmed server row, including any
|
|
51
|
+
* framework-applied defaults. Matches the stateful client's `create`. Passing an
|
|
52
|
+
* id that already exists is idempotent: the existing row is returned unchanged.
|
|
54
53
|
*/
|
|
55
54
|
create(params: ModelCreateParams<T, C>): Promise<T>;
|
|
56
55
|
update(params: ModelUpdateParams<C>): Promise<CommitReceipt>;
|
|
57
56
|
/**
|
|
58
|
-
*
|
|
59
|
-
* `setState(prev => next)`
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
57
|
+
* Updates a row with a function of its latest value — `update(id, current =>
|
|
58
|
+
* next)`, the data-layer equivalent of a `setState(prev => next)` reducer. The
|
|
59
|
+
* client reads the freshest row, runs your updater, and writes the result as a
|
|
60
|
+
* compare-and-swap against the row's watermark; if another write landed first it
|
|
61
|
+
* re-reads and re-runs. No claim or conflict handling is needed: the write either
|
|
62
|
+
* lands or throws `AbloContentionError` once its retry budget is spent. Return
|
|
63
|
+
* `null` or `undefined` from the updater to skip the write.
|
|
63
64
|
*/
|
|
64
65
|
update(id: string, updater: ModelUpdater<T>, options?: ContentionOptions): Promise<CommitReceipt | undefined>;
|
|
65
66
|
delete(params: ModelDeleteParams<T>): Promise<CommitReceipt>;
|
|
66
67
|
claim: HttpClaimApi<T>;
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
69
|
-
* The
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* `
|
|
70
|
+
* The type of the stateless HTTP client: a typed {@link HttpModelClient} per
|
|
71
|
+
* schema model, plus `commits`, `dispose`, and the session-mint surface. It
|
|
72
|
+
* exposes only what request/response transport can do, so reaching for a
|
|
73
|
+
* stateful-only capability — `get`, `getAll`, `getCount`, `onChange`, or the
|
|
74
|
+
* synchronous `claim.state`/`queue`/`reorder` reads — is a compile error rather
|
|
75
|
+
* than a value that is `undefined` at runtime.
|
|
74
76
|
*/
|
|
75
77
|
export type AbloHttpClient<S extends SchemaRecord> = {
|
|
76
78
|
readonly [K in keyof S & string]: HttpModelClient<InferModel<Schema<S>, K>, InferCreate<Schema<S>, K>>;
|
|
77
79
|
} & {
|
|
78
|
-
/**
|
|
80
|
+
/** Runs one-time setup, such as registering a configured `databaseUrl` data source, before the client is used. It also runs lazily ahead of the first request, so calling it yourself is optional. */
|
|
79
81
|
ready(): Promise<void>;
|
|
80
82
|
readonly commits: CommitResource;
|
|
81
83
|
dispose(): Promise<void>;
|
|
82
|
-
/**
|
|
84
|
+
/** Resolves the bearer credential this client authenticates with, or `null` if none is set. */
|
|
83
85
|
getAuthToken(): Promise<string | null>;
|
|
84
86
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
87
|
+
* Mints a short-lived, scoped session token. Minting is itself a stateless
|
|
88
|
+
* request, so it is available here even though the local-cache reads are not.
|
|
89
|
+
* Pass `{ user }` to mint an end-user key (`ek_`) or `{ agent, can }` to mint a
|
|
90
|
+
* scoped agent key (`rk_`). See {@link CreateSessionParams}.
|
|
88
91
|
*/
|
|
89
92
|
readonly sessions: {
|
|
90
93
|
create(params: CreateSessionParams<S>): Promise<AbloSession>;
|
|
91
94
|
};
|
|
92
|
-
/**
|
|
95
|
+
/** Looks up a model client by name, for when the model name is only known at runtime. */
|
|
93
96
|
model<T = Record<string, unknown>>(name: string): HttpModelClient<T>;
|
|
94
97
|
};
|
|
95
98
|
/**
|
|
96
|
-
*
|
|
97
|
-
* client's
|
|
98
|
-
* ever opened;
|
|
99
|
+
* Builds the stateless, typed HTTP client. Each `client.<model>` resolves to the
|
|
100
|
+
* protocol client's model accessor, while `commits`, `dispose`, and the other
|
|
101
|
+
* protocol members pass through unchanged. No socket is ever opened; the bearer
|
|
102
|
+
* credential is the identity.
|
|
99
103
|
*/
|
|
100
104
|
export declare function createAbloHttpClient<S extends SchemaRecord>(options: AbloHttpClientOptions<S>): AbloHttpClient<S>;
|
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Creates a stateless, typed HTTP client for server-side actors — agents,
|
|
3
|
+
* workers, and serverless handlers. It talks to Ablo over plain request/response
|
|
4
|
+
* HTTP, uses the bearer credential as its identity, and holds no WebSocket and no
|
|
5
|
+
* connection state.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* client — it's a separate stateless client where the credential carries identity
|
|
15
|
-
* and the SERVER resolves it per request.
|
|
7
|
+
* This is the counterpart to the stateful {@link Ablo} client. The stateful
|
|
8
|
+
* client is for interactive participants: it opens a WebSocket, learns its
|
|
9
|
+
* identity (user id and organization id) during the connect-and-bootstrap step,
|
|
10
|
+
* and routes writes through a queue that waits for that identity. A server-side
|
|
11
|
+
* actor has no socket, so instead of reusing that machinery it uses this client,
|
|
12
|
+
* where the credential itself carries identity and the server resolves it on
|
|
13
|
+
* every request.
|
|
16
14
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* `POST /v1/commits` and reads
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* surface as the browser client — typed proxies, stateless transport.
|
|
15
|
+
* Under the hood this wraps the schema-agnostic protocol client that
|
|
16
|
+
* {@link createProtocolClient} returns in a typed proxy. The protocol client
|
|
17
|
+
* commits over `POST /v1/commits` and reads over HTTP, authenticating with the
|
|
18
|
+
* bearer token each time; its model access is string-keyed (`api.model('slides')`).
|
|
19
|
+
* The proxy gives server code the same typed `client.<model>` surface the
|
|
20
|
+
* stateful client offers, over stateless transport.
|
|
24
21
|
*/
|
|
25
22
|
import { createProtocolClient, } from './ApiClient.js';
|
|
26
23
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* the genuinely-
|
|
24
|
+
* Names on the underlying protocol client that pass straight through the proxy.
|
|
25
|
+
* This set intentionally leaves out names that collide with common schema models —
|
|
26
|
+
* `tasks`, `claims`, `capabilities`, `agent` — so that `client.tasks` resolves to
|
|
27
|
+
* the schema model named `tasks` rather than a protocol resource. Only lifecycle
|
|
28
|
+
* methods and the genuinely protocol-level members belong here.
|
|
32
29
|
*/
|
|
33
30
|
const PROTOCOL_MEMBERS = new Set([
|
|
34
31
|
'ready',
|
|
@@ -41,9 +38,10 @@ const PROTOCOL_MEMBERS = new Set([
|
|
|
41
38
|
'sessions',
|
|
42
39
|
]);
|
|
43
40
|
/**
|
|
44
|
-
*
|
|
45
|
-
* client's
|
|
46
|
-
* ever opened;
|
|
41
|
+
* Builds the stateless, typed HTTP client. Each `client.<model>` resolves to the
|
|
42
|
+
* protocol client's model accessor, while `commits`, `dispose`, and the other
|
|
43
|
+
* protocol members pass through unchanged. No socket is ever opened; the bearer
|
|
44
|
+
* credential is the identity.
|
|
47
45
|
*/
|
|
48
46
|
export function createAbloHttpClient(options) {
|
|
49
47
|
// The schema is type-level only; the protocol client is schema-agnostic.
|
|
@@ -62,8 +60,8 @@ export function createAbloHttpClient(options) {
|
|
|
62
60
|
return api.model(prop);
|
|
63
61
|
},
|
|
64
62
|
});
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
63
|
+
// A single boundary cast. `AbloHttpClient<S>` declares only what the model
|
|
64
|
+
// accessor and the passed-through protocol members actually implement, so no
|
|
65
|
+
// method on this type is missing at runtime.
|
|
68
66
|
return facade;
|
|
69
67
|
}
|