@abloatai/ablo 0.25.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/AGENTS.md +5 -3
- package/CHANGELOG.md +34 -0
- package/README.md +104 -88
- package/dist/BaseSyncedStore.d.ts +140 -266
- package/dist/BaseSyncedStore.js +338 -739
- package/dist/Database.d.ts +62 -77
- package/dist/Database.js +106 -127
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +91 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +16 -15
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +52 -69
- package/dist/ModelRegistry.d.ts +46 -25
- package/dist/ModelRegistry.js +32 -30
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +6 -7
- package/dist/SyncClient.d.ts +119 -109
- package/dist/SyncClient.js +303 -224
- package/dist/SyncEngineContext.d.ts +1 -3
- package/dist/SyncEngineContext.js +1 -2
- 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 +39 -31
- package/dist/agent/Agent.js +35 -23
- 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} +30 -31
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +7 -8
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/credentialPolicy.d.ts +74 -71
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +7 -18
- package/dist/auth/credentialSource.js +10 -18
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +34 -40
- 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 +483 -369
- package/dist/client/Ablo.d.ts +107 -836
- package/dist/client/Ablo.js +174 -833
- package/dist/client/ApiClient.d.ts +44 -20
- package/dist/client/ApiClient.js +193 -44
- package/dist/client/auth.d.ts +51 -60
- package/dist/client/auth.js +137 -110
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +35 -0
- package/dist/client/consoleLogger.js +44 -0
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +26 -31
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +158 -124
- package/dist/client/credentialEndpoint.d.ts +61 -0
- package/dist/client/credentialEndpoint.js +86 -0
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +21 -0
- package/dist/client/hostedEndpoints.js +21 -0
- package/dist/client/httpClient.d.ts +58 -54
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +49 -59
- package/dist/client/modelRegistration.d.ts +10 -0
- package/dist/client/modelRegistration.js +301 -0
- package/dist/client/options.d.ts +373 -0
- package/dist/client/options.js +6 -0
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +333 -0
- package/dist/client/resourceTypes.js +7 -0
- package/dist/client/schemaConfig.d.ts +44 -0
- package/dist/client/schemaConfig.js +176 -0
- package/dist/client/sessionMint.d.ts +17 -13
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +9 -10
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +28 -0
- package/dist/client/wsMutationExecutor.js +71 -0
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -7
- package/dist/coordination/index.d.ts +13 -4
- package/dist/coordination/index.js +29 -4
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -11
- package/dist/coordination/trace.js +13 -15
- package/dist/core/DatabaseManager.d.ts +5 -8
- package/dist/core/DatabaseManager.js +38 -40
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +27 -34
- package/dist/core/QueryView.d.ts +17 -5
- package/dist/core/QueryView.js +6 -7
- package/dist/core/StoreManager.d.ts +14 -16
- package/dist/core/StoreManager.js +26 -25
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +18 -13
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +57 -54
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +145 -0
- package/dist/core/storeContract.js +12 -0
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +118 -101
- package/dist/errorCodes.js +277 -260
- package/dist/errors.d.ts +170 -165
- package/dist/errors.js +161 -151
- package/dist/index.d.ts +30 -27
- package/dist/index.js +90 -82
- package/dist/interfaces/index.d.ts +108 -133
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +59 -49
- 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 +149 -155
- package/dist/mutators/defineMutators.d.ts +24 -37
- 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 +105 -101
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +32 -16
- package/dist/query/client.js +103 -72
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +7 -11
- package/dist/react/AbloProvider.js +24 -17
- package/dist/react/context.d.ts +27 -146
- 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 +17 -15
- 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 +11 -12
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +9 -9
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +10 -4
- package/dist/react/useReactive.js +2 -3
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +3 -3
- 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 +35 -0
- package/dist/schema/ddlLock.js +46 -0
- 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 +36 -49
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +5 -4
- package/dist/schema/index.js +29 -21
- package/dist/schema/model.d.ts +121 -146
- package/dist/schema/model.js +24 -35
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +7 -1
- package/dist/schema/queries.d.ts +30 -32
- package/dist/schema/queries.js +24 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +38 -0
- package/dist/schema/residency.js +30 -0
- package/dist/schema/roles.d.ts +45 -27
- package/dist/schema/roles.js +52 -21
- package/dist/schema/schema.d.ts +36 -45
- package/dist/schema/schema.js +42 -39
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +36 -39
- 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} +27 -50
- 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 +31 -26
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +34 -28
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +28 -26
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +10 -9
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +27 -29
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +27 -19
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +30 -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 +94 -0
- package/dist/source/factory.js +268 -0
- package/dist/source/index.d.ts +10 -462
- package/dist/source/index.js +17 -421
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +10 -11
- package/dist/source/next.js +7 -8
- package/dist/source/pushQueue.d.ts +70 -48
- package/dist/source/pushQueue.js +36 -29
- package/dist/source/signing.d.ts +88 -0
- package/dist/source/signing.js +159 -0
- package/dist/source/types.d.ts +351 -0
- package/dist/source/types.js +43 -0
- package/dist/stores/ObjectStore.d.ts +11 -12
- package/dist/stores/ObjectStore.js +34 -35
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +8 -12
- package/dist/stores/SyncActionStore.js +77 -46
- package/dist/surface.d.ts +28 -21
- package/dist/surface.js +28 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +37 -45
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +101 -80
- package/dist/sync/ConnectionManager.d.ts +47 -50
- package/dist/sync/ConnectionManager.js +74 -70
- package/dist/sync/NetworkProbe.d.ts +27 -31
- package/dist/sync/NetworkProbe.js +67 -72
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +49 -36
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +79 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +45 -59
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +44 -52
- package/dist/sync/SyncWebSocket.d.ts +175 -250
- package/dist/sync/SyncWebSocket.js +431 -769
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +38 -30
- package/dist/sync/bootstrapApply.d.ts +70 -0
- package/dist/sync/bootstrapApply.js +73 -0
- package/dist/sync/commitFrames.d.ts +44 -0
- package/dist/sync/commitFrames.js +94 -0
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +108 -25
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +13 -17
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +175 -0
- package/dist/sync/credentialLifecycle.js +322 -0
- package/dist/sync/deltaPipeline.d.ts +113 -0
- package/dist/sync/deltaPipeline.js +261 -0
- package/dist/sync/groupChange.d.ts +113 -0
- package/dist/sync/groupChange.js +242 -0
- package/dist/sync/heartbeat.d.ts +63 -0
- package/dist/sync/heartbeat.js +91 -0
- package/dist/sync/participants.d.ts +27 -27
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +40 -0
- package/dist/sync/syncCursor.js +55 -0
- package/dist/sync/syncPlan.d.ts +54 -0
- package/dist/sync/syncPlan.js +50 -0
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +116 -0
- package/dist/sync/wsFrameHandlers.js +374 -0
- package/dist/testing/fixtures/bootstrap.d.ts +21 -17
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +31 -34
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +12 -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 -18
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +14 -11
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +4 -4
- package/dist/testing/index.js +3 -3
- 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 +21 -34
- package/dist/testing/mocks/MockSyncContext.js +16 -45
- package/dist/testing/mocks/MockSyncStore.d.ts +14 -14
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +28 -24
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +190 -221
- package/dist/transactions/TransactionQueue.js +424 -822
- package/dist/transactions/TransactionStore.d.ts +20 -0
- package/dist/transactions/TransactionStore.js +53 -0
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +58 -0
- package/dist/transactions/coalesceRules.js +140 -0
- package/dist/transactions/commitPayload.d.ts +130 -0
- package/dist/transactions/commitPayload.js +143 -0
- package/dist/transactions/deltaConfirmation.d.ts +58 -0
- package/dist/transactions/deltaConfirmation.js +215 -0
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/replayValidation.d.ts +99 -0
- package/dist/transactions/replayValidation.js +111 -0
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +74 -80
- package/dist/types/index.js +22 -27
- package/dist/types/modelData.d.ts +10 -0
- package/dist/types/modelData.js +9 -0
- package/dist/types/participant.d.ts +20 -0
- package/dist/types/participant.js +10 -0
- package/dist/types/streams.d.ts +216 -209
- 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} +44 -100
- 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 +35 -27
- package/dist/wire/errorEnvelope.js +38 -32
- package/dist/wire/frames.d.ts +150 -67
- package/dist/wire/frames.js +48 -1
- package/dist/wire/index.d.ts +18 -13
- package/dist/wire/index.js +36 -13
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +38 -0
- package/dist/wire/protocol.js +38 -0
- package/dist/wire/protocolVersion.d.ts +60 -0
- package/dist/wire/protocolVersion.js +67 -0
- package/docs/api-keys.md +4 -3
- package/docs/coordination.md +59 -0
- package/docs/examples/existing-python-backend.md +3 -3
- package/docs/identity.md +4 -4
- package/docs/integration-guide.md +1 -1
- package/docs/react.md +1 -1
- package/docs/sessions.md +5 -7
- package/package.json +24 -21
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/client/index.d.ts +0 -36
- package/dist/client/index.js +0 -33
- package/dist/config/index.d.ts +0 -10
- package/dist/config/index.js +0 -12
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/interfaces/headless.d.ts +0 -95
- package/dist/interfaces/headless.js +0 -41
- package/dist/query/index.d.ts +0 -6
- package/dist/query/index.js +0 -5
- package/dist/realtime/index.d.ts +0 -10
- package/dist/realtime/index.js +0 -9
- package/dist/schema/plane.d.ts +0 -23
- package/dist/schema/plane.js +0 -19
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/next.d.ts +0 -51
- package/dist/server/next.js +0 -47
- 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 -1
- package/dist/server/storage-mode.js +0 -18
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/sync/OfflineFlush.d.ts +0 -9
- package/dist/sync/OfflineFlush.js +0 -22
- package/dist/sync/OfflineTransactionStore.d.ts +0 -37
- package/dist/sync/OfflineTransactionStore.js +0 -263
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/index.d.ts +0 -16
- package/dist/transactions/index.js +0 -7
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/utils/mobx-setup.d.ts +0 -42
package/dist/cli.cjs
CHANGED
|
@@ -211978,9 +211978,9 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
211978
211978
|
}
|
|
211979
211979
|
});
|
|
211980
211980
|
|
|
211981
|
-
// node_modules
|
|
211981
|
+
// node_modules/balanced-match/dist/commonjs/index.js
|
|
211982
211982
|
var require_commonjs = __commonJS({
|
|
211983
|
-
"node_modules
|
|
211983
|
+
"node_modules/balanced-match/dist/commonjs/index.js"(exports2) {
|
|
211984
211984
|
"use strict";
|
|
211985
211985
|
init_cjs_shims();
|
|
211986
211986
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -212041,9 +212041,9 @@ var require_commonjs = __commonJS({
|
|
|
212041
212041
|
}
|
|
212042
212042
|
});
|
|
212043
212043
|
|
|
212044
|
-
// node_modules
|
|
212044
|
+
// node_modules/brace-expansion/dist/commonjs/index.js
|
|
212045
212045
|
var require_commonjs2 = __commonJS({
|
|
212046
|
-
"node_modules
|
|
212046
|
+
"node_modules/brace-expansion/dist/commonjs/index.js"(exports2) {
|
|
212047
212047
|
"use strict";
|
|
212048
212048
|
init_cjs_shims();
|
|
212049
212049
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -212215,9 +212215,9 @@ var require_commonjs2 = __commonJS({
|
|
|
212215
212215
|
}
|
|
212216
212216
|
});
|
|
212217
212217
|
|
|
212218
|
-
// node_modules
|
|
212218
|
+
// node_modules/minimatch/dist/commonjs/assert-valid-pattern.js
|
|
212219
212219
|
var require_assert_valid_pattern = __commonJS({
|
|
212220
|
-
"node_modules
|
|
212220
|
+
"node_modules/minimatch/dist/commonjs/assert-valid-pattern.js"(exports2) {
|
|
212221
212221
|
"use strict";
|
|
212222
212222
|
init_cjs_shims();
|
|
212223
212223
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -212235,9 +212235,9 @@ var require_assert_valid_pattern = __commonJS({
|
|
|
212235
212235
|
}
|
|
212236
212236
|
});
|
|
212237
212237
|
|
|
212238
|
-
// node_modules
|
|
212238
|
+
// node_modules/minimatch/dist/commonjs/brace-expressions.js
|
|
212239
212239
|
var require_brace_expressions = __commonJS({
|
|
212240
|
-
"node_modules
|
|
212240
|
+
"node_modules/minimatch/dist/commonjs/brace-expressions.js"(exports2) {
|
|
212241
212241
|
"use strict";
|
|
212242
212242
|
init_cjs_shims();
|
|
212243
212243
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -212353,9 +212353,9 @@ var require_brace_expressions = __commonJS({
|
|
|
212353
212353
|
}
|
|
212354
212354
|
});
|
|
212355
212355
|
|
|
212356
|
-
// node_modules
|
|
212356
|
+
// node_modules/minimatch/dist/commonjs/unescape.js
|
|
212357
212357
|
var require_unescape = __commonJS({
|
|
212358
|
-
"node_modules
|
|
212358
|
+
"node_modules/minimatch/dist/commonjs/unescape.js"(exports2) {
|
|
212359
212359
|
"use strict";
|
|
212360
212360
|
init_cjs_shims();
|
|
212361
212361
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -212370,9 +212370,9 @@ var require_unescape = __commonJS({
|
|
|
212370
212370
|
}
|
|
212371
212371
|
});
|
|
212372
212372
|
|
|
212373
|
-
// node_modules
|
|
212373
|
+
// node_modules/minimatch/dist/commonjs/ast.js
|
|
212374
212374
|
var require_ast = __commonJS({
|
|
212375
|
-
"node_modules
|
|
212375
|
+
"node_modules/minimatch/dist/commonjs/ast.js"(exports2) {
|
|
212376
212376
|
"use strict";
|
|
212377
212377
|
init_cjs_shims();
|
|
212378
212378
|
var _a;
|
|
@@ -213025,9 +213025,9 @@ var require_ast = __commonJS({
|
|
|
213025
213025
|
}
|
|
213026
213026
|
});
|
|
213027
213027
|
|
|
213028
|
-
// node_modules
|
|
213028
|
+
// node_modules/minimatch/dist/commonjs/escape.js
|
|
213029
213029
|
var require_escape = __commonJS({
|
|
213030
|
-
"node_modules
|
|
213030
|
+
"node_modules/minimatch/dist/commonjs/escape.js"(exports2) {
|
|
213031
213031
|
"use strict";
|
|
213032
213032
|
init_cjs_shims();
|
|
213033
213033
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -213042,9 +213042,9 @@ var require_escape = __commonJS({
|
|
|
213042
213042
|
}
|
|
213043
213043
|
});
|
|
213044
213044
|
|
|
213045
|
-
// node_modules
|
|
213045
|
+
// node_modules/minimatch/dist/commonjs/index.js
|
|
213046
213046
|
var require_commonjs3 = __commonJS({
|
|
213047
|
-
"node_modules
|
|
213047
|
+
"node_modules/minimatch/dist/commonjs/index.js"(exports2) {
|
|
213048
213048
|
"use strict";
|
|
213049
213049
|
init_cjs_shims();
|
|
213050
213050
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -214565,9 +214565,9 @@ var require_is_glob = __commonJS({
|
|
|
214565
214565
|
}
|
|
214566
214566
|
});
|
|
214567
214567
|
|
|
214568
|
-
// node_modules/glob-parent/index.js
|
|
214568
|
+
// node_modules/fast-glob/node_modules/glob-parent/index.js
|
|
214569
214569
|
var require_glob_parent = __commonJS({
|
|
214570
|
-
"node_modules/glob-parent/index.js"(exports2, module2) {
|
|
214570
|
+
"node_modules/fast-glob/node_modules/glob-parent/index.js"(exports2, module2) {
|
|
214571
214571
|
"use strict";
|
|
214572
214572
|
init_cjs_shims();
|
|
214573
214573
|
var isGlob = require_is_glob();
|
|
@@ -215687,9 +215687,9 @@ var require_braces = __commonJS({
|
|
|
215687
215687
|
}
|
|
215688
215688
|
});
|
|
215689
215689
|
|
|
215690
|
-
// node_modules/picomatch/lib/constants.js
|
|
215690
|
+
// node_modules/micromatch/node_modules/picomatch/lib/constants.js
|
|
215691
215691
|
var require_constants2 = __commonJS({
|
|
215692
|
-
"node_modules/picomatch/lib/constants.js"(exports2, module2) {
|
|
215692
|
+
"node_modules/micromatch/node_modules/picomatch/lib/constants.js"(exports2, module2) {
|
|
215693
215693
|
"use strict";
|
|
215694
215694
|
init_cjs_shims();
|
|
215695
215695
|
var path = require("path");
|
|
@@ -215889,9 +215889,9 @@ var require_constants2 = __commonJS({
|
|
|
215889
215889
|
}
|
|
215890
215890
|
});
|
|
215891
215891
|
|
|
215892
|
-
// node_modules/picomatch/lib/utils.js
|
|
215892
|
+
// node_modules/micromatch/node_modules/picomatch/lib/utils.js
|
|
215893
215893
|
var require_utils2 = __commonJS({
|
|
215894
|
-
"node_modules/picomatch/lib/utils.js"(exports2) {
|
|
215894
|
+
"node_modules/micromatch/node_modules/picomatch/lib/utils.js"(exports2) {
|
|
215895
215895
|
"use strict";
|
|
215896
215896
|
init_cjs_shims();
|
|
215897
215897
|
var path = require("path");
|
|
@@ -215951,9 +215951,9 @@ var require_utils2 = __commonJS({
|
|
|
215951
215951
|
}
|
|
215952
215952
|
});
|
|
215953
215953
|
|
|
215954
|
-
// node_modules/picomatch/lib/scan.js
|
|
215954
|
+
// node_modules/micromatch/node_modules/picomatch/lib/scan.js
|
|
215955
215955
|
var require_scan = __commonJS({
|
|
215956
|
-
"node_modules/picomatch/lib/scan.js"(exports2, module2) {
|
|
215956
|
+
"node_modules/micromatch/node_modules/picomatch/lib/scan.js"(exports2, module2) {
|
|
215957
215957
|
"use strict";
|
|
215958
215958
|
init_cjs_shims();
|
|
215959
215959
|
var utils = require_utils2();
|
|
@@ -216282,9 +216282,9 @@ var require_scan = __commonJS({
|
|
|
216282
216282
|
}
|
|
216283
216283
|
});
|
|
216284
216284
|
|
|
216285
|
-
// node_modules/picomatch/lib/parse.js
|
|
216285
|
+
// node_modules/micromatch/node_modules/picomatch/lib/parse.js
|
|
216286
216286
|
var require_parse2 = __commonJS({
|
|
216287
|
-
"node_modules/picomatch/lib/parse.js"(exports2, module2) {
|
|
216287
|
+
"node_modules/micromatch/node_modules/picomatch/lib/parse.js"(exports2, module2) {
|
|
216288
216288
|
"use strict";
|
|
216289
216289
|
init_cjs_shims();
|
|
216290
216290
|
var constants = require_constants2();
|
|
@@ -217285,9 +217285,9 @@ var require_parse2 = __commonJS({
|
|
|
217285
217285
|
}
|
|
217286
217286
|
});
|
|
217287
217287
|
|
|
217288
|
-
// node_modules/picomatch/lib/picomatch.js
|
|
217288
|
+
// node_modules/micromatch/node_modules/picomatch/lib/picomatch.js
|
|
217289
217289
|
var require_picomatch = __commonJS({
|
|
217290
|
-
"node_modules/picomatch/lib/picomatch.js"(exports2, module2) {
|
|
217290
|
+
"node_modules/micromatch/node_modules/picomatch/lib/picomatch.js"(exports2, module2) {
|
|
217291
217291
|
"use strict";
|
|
217292
217292
|
init_cjs_shims();
|
|
217293
217293
|
var path = require("path");
|
|
@@ -217427,9 +217427,9 @@ var require_picomatch = __commonJS({
|
|
|
217427
217427
|
}
|
|
217428
217428
|
});
|
|
217429
217429
|
|
|
217430
|
-
// node_modules/picomatch/index.js
|
|
217430
|
+
// node_modules/micromatch/node_modules/picomatch/index.js
|
|
217431
217431
|
var require_picomatch2 = __commonJS({
|
|
217432
|
-
"node_modules/picomatch/index.js"(exports2, module2) {
|
|
217432
|
+
"node_modules/micromatch/node_modules/picomatch/index.js"(exports2, module2) {
|
|
217433
217433
|
"use strict";
|
|
217434
217434
|
init_cjs_shims();
|
|
217435
217435
|
module2.exports = require_picomatch();
|
|
@@ -276770,203 +276770,208 @@ var wire = (category, httpStatus, retryable, message, recovery) => ({ category,
|
|
|
276770
276770
|
var client = (category, message) => ({ category, surface: "client", retryable: false, message });
|
|
276771
276771
|
var ERROR_CODES = {
|
|
276772
276772
|
// ── auth (401) ─────────────────────────────────────────────────────
|
|
276773
|
-
apikey_invalid: wire("auth", 401, false, "API key
|
|
276774
|
-
apikey_revoked: wire("auth", 401, false, "API key has been revoked."),
|
|
276775
|
-
//
|
|
276776
|
-
//
|
|
276777
|
-
//
|
|
276778
|
-
//
|
|
276779
|
-
//
|
|
276780
|
-
//
|
|
276781
|
-
apikey_expired: wire("auth", 401, false, "API key has expired.", "access_credential_expiry"),
|
|
276782
|
-
apikey_missing: wire("auth", 401, false, "
|
|
276783
|
-
api_key_required: wire("auth", 401, false, "This operation requires an API key."),
|
|
276784
|
-
capability_id_missing: wire("auth", 401, false, "
|
|
276785
|
-
exchange_failed: wire("auth", 401, false, "The API
|
|
276786
|
-
identity_resolve_failed: wire("auth", 401, false, "
|
|
276773
|
+
apikey_invalid: wire("auth", 401, false, "This API key isn't one Ablo recognizes \u2014 it may be mistyped, truncated, or belong to a different environment. Check the key and try again."),
|
|
276774
|
+
apikey_revoked: wire("auth", 401, false, "This API key has been revoked and can no longer be used. Mint a new key from the dashboard."),
|
|
276775
|
+
// The short-lived access credential — the ephemeral key (`ek_` for users,
|
|
276776
|
+
// `rk_` for agents) minted from the login and presented as a bearer token.
|
|
276777
|
+
// Its expiry is routine and re-mintable: get a fresh key from the still-valid
|
|
276778
|
+
// session and retry, rather than signing out. An agent's expired `rk_` must
|
|
276779
|
+
// not sign a human out either. This is the one code on the silent re-mint
|
|
276780
|
+
// path; see the `access_credential_expiry` recovery class.
|
|
276781
|
+
apikey_expired: wire("auth", 401, false, "This ephemeral API key has expired. Mint a fresh key from your still-valid session and retry the request.", "access_credential_expiry"),
|
|
276782
|
+
apikey_missing: wire("auth", 401, false, "The request arrived without an API key. Send one as `Authorization: Bearer <key>`."),
|
|
276783
|
+
api_key_required: wire("auth", 401, false, "This operation requires an API key, and none was presented. Send one as `Authorization: Bearer <key>`."),
|
|
276784
|
+
capability_id_missing: wire("auth", 401, false, "This request must name a capability id, but none was provided."),
|
|
276785
|
+
exchange_failed: wire("auth", 401, false, "The API key could not be exchanged for a working credential \u2014 the exchange was rejected. Check that the key is still valid."),
|
|
276786
|
+
identity_resolve_failed: wire("auth", 401, false, "The server could not resolve an identity for this credential \u2014 the identity lookup was rejected. Check that the credential is still valid."),
|
|
276787
276787
|
auth_no_credentials: wire("auth", 401, false, "No recognized authentication credential was presented \u2014 no API key and no bearer JWT. Send `Authorization: Bearer <token>`."),
|
|
276788
|
-
identity_missing_organization: wire("auth", 401, false, "Authentication succeeded but
|
|
276789
|
-
// The long-lived login is gone
|
|
276790
|
-
|
|
276791
|
-
|
|
276792
|
-
//
|
|
276793
|
-
//
|
|
276794
|
-
//
|
|
276795
|
-
|
|
276796
|
-
|
|
276788
|
+
identity_missing_organization: wire("auth", 401, false, "Authentication succeeded, but the credential resolves to no organization, so requests cannot be scoped. Check that the key or token carries an organization."),
|
|
276789
|
+
// The long-lived login is gone; this is terminal and drives sign-out and
|
|
276790
|
+
// re-authentication.
|
|
276791
|
+
session_expired: wire("auth", 401, false, "Your session has expired or is no longer valid. Sign in again to continue.", "session_expiry"),
|
|
276792
|
+
// `jwt_invalid` is the general fallback; the codes below it split out specific
|
|
276793
|
+
// failure modes, so an integrator can tell a wrong JWKS registration from a
|
|
276794
|
+
// token with no organization claim from a wrong audience, instead of getting
|
|
276795
|
+
// one opaque code for all of them.
|
|
276796
|
+
jwt_invalid: wire("auth", 401, false, "The bearer JWT failed validation for a reason the server could not classify further. Check the token's issuer, signature, audience, and expiry."),
|
|
276797
|
+
jwt_malformed: wire("auth", 401, false, "The bearer token is not a well-formed JWT and could not be decoded. Check that the full, unmodified token was sent."),
|
|
276797
276798
|
jwt_missing_issuer: wire("auth", 401, false, "The bearer JWT has no `iss` (issuer) claim, so it cannot be routed to a trusted issuer."),
|
|
276798
276799
|
jwt_issuer_untrusted: wire("auth", 401, false, "The bearer JWT's `iss` is not a registered trusted issuer. Register it via POST /v1/trusted-issuers, or check the token's issuer claim."),
|
|
276799
276800
|
jwt_signature_invalid: wire("auth", 401, false, "The bearer JWT's signature could not be verified against the issuer's JWKS (wrong key, rotated key, or forged token)."),
|
|
276800
276801
|
jwt_audience_mismatch: wire("auth", 401, false, "The bearer JWT's `aud` (audience) claim does not match the audience this issuer is registered with."),
|
|
276801
276802
|
jwt_missing_subject: wire("auth", 401, false, "The bearer JWT has no `sub` (subject) claim to identify the user."),
|
|
276802
276803
|
jwt_missing_organization: wire("auth", 401, false, "The bearer JWT carries no organization context \u2014 neither a fixed org for the issuer nor the configured organization claim."),
|
|
276803
|
-
//
|
|
276804
|
-
//
|
|
276805
|
-
//
|
|
276806
|
-
//
|
|
276807
|
-
|
|
276808
|
-
jwt_expired: wire("auth", 401, false, "The bearer JWT has expired; obtain a fresh token.", "session_expiry"),
|
|
276804
|
+
// Applies only to the trusted-issuer path, where a customer authenticates with
|
|
276805
|
+
// a JWT from their own identity provider. When such a token expires, the
|
|
276806
|
+
// remedy is to re-authenticate against that provider, so it classifies as a
|
|
276807
|
+
// session expiry.
|
|
276808
|
+
jwt_expired: wire("auth", 401, false, "The bearer JWT has expired. Obtain a fresh token from your identity provider and retry.", "session_expiry"),
|
|
276809
276809
|
jwt_org_membership_denied: wire("auth", 403, false, "The bearer JWT's subject is not an active member of the organization in its `org_id` claim (removed, suspended, or the claim does not match a membership)."),
|
|
276810
|
-
file_upload_auth_required: wire("auth", 401, false, "File
|
|
276811
|
-
browser_apikey_blocked: client("auth", "
|
|
276812
|
-
browser_database_url_blocked: client("auth", "A database connection string
|
|
276813
|
-
datasource_registration_failed: client("auth", "
|
|
276814
|
-
datasource_connection_unsupported: wire("validation", 400, false, "This deployment
|
|
276810
|
+
file_upload_auth_required: wire("auth", 401, false, "File uploads require an authenticated session. Sign in and retry."),
|
|
276811
|
+
browser_apikey_blocked: client("auth", "A raw API key was used from a browser, where anyone can read it. Keep secret keys server-side and hand the browser a short-lived ephemeral key instead."),
|
|
276812
|
+
browser_database_url_blocked: client("auth", "A database connection string was used from a browser context. It carries database credentials, so it must stay server-side."),
|
|
276813
|
+
datasource_registration_failed: client("auth", "The provided `databaseUrl` could not be registered as a data source. Check that the connection string is valid and the database is reachable."),
|
|
276814
|
+
datasource_connection_unsupported: wire("validation", 400, false, "This deployment does not accept direct connection-string data sources. Register a signed Data Source endpoint instead."),
|
|
276815
276815
|
datasource_direct_deprecated: wire("validation", 410, false, "The direct (connection string) datasource is deprecated. Register a signed Data Source endpoint instead \u2014 your app owns the write and your credentials never leave it."),
|
|
276816
276816
|
// ── permission / capability (403) ──────────────────────────────────
|
|
276817
|
-
capability_scope_denied: wire("capability", 403, false, "
|
|
276818
|
-
issuer_register_forbidden: wire("permission", 403, false, "Registering a trusted issuer requires a secret (sk_) API key."),
|
|
276819
|
-
capability_invalid: wire("capability", 403, false, "
|
|
276817
|
+
capability_scope_denied: wire("capability", 403, false, "This action falls outside the scope granted to the connection, so it was denied."),
|
|
276818
|
+
issuer_register_forbidden: wire("permission", 403, false, "Registering a trusted issuer requires a secret (`sk_`) API key. The key presented is not a secret key."),
|
|
276819
|
+
capability_invalid: wire("capability", 403, false, "This capability cannot be used \u2014 it is unknown, revoked, or expired. Request a fresh grant."),
|
|
276820
276820
|
test_database_not_registered: wire("permission", 403, false, "Test mode requires a registered dev database for this org \u2014 run `npx ablo init`, or construct the client with `databaseUrl` using your test key."),
|
|
276821
276821
|
tenant_routing_failed: wire("server", 500, true, "The org's registered database could not be resolved or dialed. Ablo never falls back to shared storage for a dedicated tenant \u2014 retry, and check the datasource status if it persists."),
|
|
276822
|
-
database_role_cannot_enforce_rls: wire("permission", 403, false, "The
|
|
276823
|
-
database_role_unreadable: wire("permission", 403, false, "
|
|
276824
|
-
database_tables_unforced_rls: wire("permission", 403, false, "
|
|
276825
|
-
database_host_not_allowed: wire("permission", 403, false, "The
|
|
276826
|
-
//
|
|
276827
|
-
//
|
|
276822
|
+
database_role_cannot_enforce_rls: wire("permission", 403, false, "The database role Ablo connects with is a superuser or has `BYPASSRLS`, so Postgres will not enforce row-level security for it. Connect with a role that is subject to RLS."),
|
|
276823
|
+
database_role_unreadable: wire("permission", 403, false, "Ablo could not introspect the database role it connects with, so it cannot verify that row-level security is enforced."),
|
|
276824
|
+
database_tables_unforced_rls: wire("permission", 403, false, "Some synced tables do not have `FORCE ROW LEVEL SECURITY` applied, so the table owner can bypass row isolation. Run `ALTER TABLE ... FORCE ROW LEVEL SECURITY` on each synced table."),
|
|
276825
|
+
database_host_not_allowed: wire("permission", 403, false, "The database host resolves to a private, loopback, or link-local address, which Ablo's servers will not connect to. Use a publicly resolvable host."),
|
|
276826
|
+
// Older spellings of the `database_*` codes above, still sent by some servers
|
|
276827
|
+
// and kept so they classify identically. Prefer the `database_*` codes.
|
|
276828
276828
|
byo_role_cannot_enforce_rls: wire("permission", 403, false, "The direct Postgres connector role cannot enforce row-level security."),
|
|
276829
276829
|
byo_role_unreadable: wire("permission", 403, false, "The direct Postgres connector role could not be introspected."),
|
|
276830
276830
|
byo_tenant_tables_unforced_rls: wire("permission", 403, false, "Tenant tables do not have RLS forced under the direct Postgres connector role."),
|
|
276831
276831
|
byo_host_not_allowed: wire("permission", 403, false, "The direct Postgres connector host resolves to a private, loopback, or link-local address and cannot be used."),
|
|
276832
276832
|
// ── claim / claim conflict (409) ──────────────────────────────────
|
|
276833
|
-
//
|
|
276834
|
-
//
|
|
276835
|
-
//
|
|
276836
|
-
//
|
|
276837
|
-
//
|
|
276838
|
-
|
|
276839
|
-
|
|
276840
|
-
|
|
276841
|
-
|
|
276842
|
-
|
|
276843
|
-
|
|
276844
|
-
|
|
276845
|
-
malformed_claim: wire("claim", 400, false, "The claim payload was malformed."),
|
|
276846
|
-
malformed_subscription: wire("validation", 400, false, "The update_subscription payload was malformed; expected { syncGroups: string[] }."),
|
|
276847
|
-
model_claimed: wire("claim", 409, false, "The model instance is claimed by another participant."),
|
|
276848
|
-
model_claimed_timeout: wire("claim", 409, false, "Timed out waiting for a model claim to clear."),
|
|
276833
|
+
// A rejection because another participant holds a claim is not retryable.
|
|
276834
|
+
// Re-sending the same write cannot succeed while the claim is held, and a
|
|
276835
|
+
// claim can outlive any reasonable retry budget, so an automatic retry would
|
|
276836
|
+
// only loop. Recovery belongs to the caller: take a claim, which queues fairly
|
|
276837
|
+
// behind the holder (`ablo.<model>.claim`), or re-read and rebase.
|
|
276838
|
+
claim_conflict: wire("claim", 409, false, "Another participant holds a claim on this row, so the write was rejected. Take a claim with `ablo.<model>.claim` to queue fairly behind the holder, or re-read and rebase."),
|
|
276839
|
+
claim_lost: wire("claim", 409, false, "The claim held on this row was lost before the write could apply. Re-acquire the claim and retry."),
|
|
276840
|
+
entity_claimed: wire("claim", 409, false, "This row is currently claimed by another participant, so the write was blocked. Queue behind the holder with `ablo.<model>.claim`, or wait for the claim to clear."),
|
|
276841
|
+
malformed_claim: wire("claim", 400, false, "The claim payload could not be parsed. A claim must name the model and the entity it targets; check the payload shape and resend."),
|
|
276842
|
+
malformed_subscription: wire("validation", 400, false, "The `update_subscription` payload was malformed; expected `{ syncGroups: string[] }`."),
|
|
276843
|
+
model_claimed: wire("claim", 409, false, "Another participant holds a claim on this row. Read `claim.state` to see who holds it, or queue behind them with a claim of your own."),
|
|
276844
|
+
model_claimed_timeout: wire("claim", 409, false, "Another participant held a claim on this row and did not release it in time. Retry, or read `claim.state` to see who holds it."),
|
|
276849
276845
|
model_claim_not_configured: client("claim", "Claiming requires the collaboration runtime, which the standard Ablo({ schema, apiKey }) client wires up for every model automatically \u2014 there is no per-model claim configuration to add. This appears only when a model proxy is constructed directly without that runtime (an internal/advanced path)."),
|
|
276850
276846
|
model_watch_not_configured: client("claim", "watch() opens a presence/claim subscription and needs a live WebSocket, so it is unavailable on the HTTP transport and on model proxies built without a socket. Use the standard Ablo({ schema, apiKey }) client (default WebSocket transport)."),
|
|
276851
276847
|
// ── stale context / idempotency (409) ──────────────────────────────
|
|
276852
|
-
stale_context: wire("conflict", 409, true, "The
|
|
276848
|
+
stale_context: wire("conflict", 409, true, "The row changed after you read it \u2014 the write's `readAt` watermark is older than the current row version. Re-read the row and retry."),
|
|
276853
276849
|
// Raised by the functional `update(id, current => next)` form once its
|
|
276854
|
-
// internal reconcile budget is exhausted
|
|
276855
|
-
// contended.
|
|
276856
|
-
//
|
|
276857
|
-
contention_exhausted: client("conflict", "A functional update
|
|
276858
|
-
update_aborted: client("conflict", "The functional update
|
|
276859
|
-
idempotency_conflict: wire("conflict", 409, false, "
|
|
276860
|
-
idempotency_key_too_long: wire("validation", 400, false, "The supplied Idempotency-Key exceeds the maximum length."),
|
|
276850
|
+
// internal reconcile budget is exhausted, because the row stayed continuously
|
|
276851
|
+
// contended. The SDK has already retried; the caller decides whether to back
|
|
276852
|
+
// off, raise `retries`, or move the row to the WebSocket transport.
|
|
276853
|
+
contention_exhausted: client("conflict", "A functional update kept losing to concurrent writes and exhausted its reconcile budget. Back off and retry, raise `retries`, or move the row to the WebSocket transport."),
|
|
276854
|
+
update_aborted: client("conflict", "The functional update was aborted via its `AbortSignal` before the write landed; nothing was written."),
|
|
276855
|
+
idempotency_conflict: wire("conflict", 409, false, "This `Idempotency-Key` was already used with a different request body. Reuse a key only to retry an identical request; otherwise generate a new one."),
|
|
276856
|
+
idempotency_key_too_long: wire("validation", 400, false, "The supplied `Idempotency-Key` exceeds the maximum length. Use a shorter key \u2014 a UUID works well."),
|
|
276861
276857
|
// ── validation (400 / 422) ─────────────────────────────────────────
|
|
276862
276858
|
write_options_invalid: client("validation", "The write options (`idempotencyKey` / `label` / `wait` / `readAt` / `onStale` / `claim`) failed validation against the write-options schema."),
|
|
276863
276859
|
source_operation_id_required: client("validation", "A data-source operation arrived without the entity `id` it targets."),
|
|
276864
|
-
source_adapter_misconfigured: client("validation", "The data-source ORM adapter could not map a schema model onto the backing client
|
|
276865
|
-
|
|
276860
|
+
source_adapter_misconfigured: client("validation", "The data-source ORM adapter could not map a schema model onto the backing client \u2014 the client exposes no matching delegate or model. Check that the adapter and schema agree on model names."),
|
|
276861
|
+
// The server validates every incoming data-source event before appending it
|
|
276862
|
+
// to the log and rejects the whole batch with this code; `param` names the
|
|
276863
|
+
// offending index and field path, such as `events[3].entityId`. It is also
|
|
276864
|
+
// raised on the client when an outbound source event cannot be built.
|
|
276865
|
+
source_event_invalid: wire("validation", 400, false, "A data-source event was malformed \u2014 missing or invalid id, model, entityId, type, or field value. The whole event batch was rejected and nothing was ingested; fix the offending outbox row and re-send."),
|
|
276866
276866
|
duration_invalid: client("validation", 'A duration value was not a number of seconds or a "500ms" | "30s" | "3m" | "24h" string.'),
|
|
276867
276867
|
schema_definition_invalid: client("validation", "A schema definition value was invalid (bad column identifier, non-finite backfill, or unsupported schema-JSON version)."),
|
|
276868
276868
|
cli_invalid_arguments: client("validation", "The CLI was invoked with an unknown flag or a malformed flag value."),
|
|
276869
|
-
turn_validation_failed: wire("validation", 422, false, "The agent turn failed server-side validation."),
|
|
276869
|
+
turn_validation_failed: wire("validation", 422, false, "The agent turn payload failed server-side validation and was not applied."),
|
|
276870
276870
|
commit_operation_required: wire("validation", 400, false, "A commit must carry `operation` or `operations`."),
|
|
276871
|
+
// Both commit transports — the WebSocket `commit` frame and the HTTP
|
|
276872
|
+
// `/v1/commits` endpoint — validate every operation and reject the whole batch
|
|
276873
|
+
// with this code. `param` names the offending index and field path, such as
|
|
276874
|
+
// `operations[3].readAt`.
|
|
276875
|
+
commit_operation_invalid: wire("validation", 400, false, "A commit operation failed validation against the wire commit-operation schema \u2014 wrong field type (e.g. a string `readAt`), unknown `type`, or missing `model`. The whole batch was rejected; the error names the offending operation index and field path."),
|
|
276871
276876
|
commit_operation_model_required: wire("validation", 400, false, "A commit operation is missing its `model`."),
|
|
276872
|
-
commit_operations_ambiguous: wire("validation", 400, false, "A commit supplied both `operation` and `operations`."),
|
|
276877
|
+
commit_operations_ambiguous: wire("validation", 400, false, "A commit supplied both `operation` and `operations`. Send one or the other, not both."),
|
|
276873
276878
|
commit_too_many_operations: wire("validation", 400, false, "A commit exceeded the per-commit operation limit; split it into smaller batches."),
|
|
276874
|
-
model_required_field_missing: wire("validation", 400, false, "
|
|
276875
|
-
model_identifier_missing: wire("validation", 400, false, "The
|
|
276876
|
-
snapshot_reserved_key: wire("validation", 400, false, "
|
|
276877
|
-
mesh_message_invalid_input: wire("validation", 400, false, "The mesh message failed input validation."),
|
|
276878
|
-
mesh_message_from_id_spoof: wire("validation", 403, false, "The mesh message `from` id does not match the authenticated sender."),
|
|
276879
|
-
mesh_message_from_kind_mismatch: wire("validation", 403, false, "The mesh message `from` kind does not match the sender."),
|
|
276880
|
-
agent_perception_missing_context: wire("validation", 422, false, "The agent perception request
|
|
276879
|
+
model_required_field_missing: wire("validation", 400, false, "The write is missing a field the model marks as required. Include the field and retry."),
|
|
276880
|
+
model_identifier_missing: wire("validation", 400, false, "The payload is missing the model's identifier, so the target row cannot be determined. Include the `id` field."),
|
|
276881
|
+
snapshot_reserved_key: wire("validation", 400, false, "The snapshot uses a key name that is reserved by the runtime. Rename the key and retry."),
|
|
276882
|
+
mesh_message_invalid_input: wire("validation", 400, false, "The mesh message payload failed input validation and was not delivered."),
|
|
276883
|
+
mesh_message_from_id_spoof: wire("validation", 403, false, "The mesh message's `from` id does not match the authenticated sender, so it was rejected \u2014 participants may only send as themselves."),
|
|
276884
|
+
mesh_message_from_kind_mismatch: wire("validation", 403, false, "The mesh message's `from` kind does not match the kind of the authenticated sender, so it was rejected."),
|
|
276885
|
+
agent_perception_missing_context: wire("validation", 422, false, "The agent perception request is missing context it needs to run. Include the required context fields and retry."),
|
|
276881
276886
|
// ── not found (404) ────────────────────────────────────────────────
|
|
276882
|
-
entity_not_found: wire("not_found", 404, false, "
|
|
276883
|
-
model_not_found: wire("not_found", 404, false, "
|
|
276884
|
-
mutate_update_entity_not_found: wire("not_found", 404, false, "The
|
|
276885
|
-
task_id_missing: wire("server", 502, true, "The task-create response
|
|
276886
|
-
// ── data integrity /
|
|
276887
|
-
// Emitted when a
|
|
276888
|
-
//
|
|
276889
|
-
//
|
|
276890
|
-
//
|
|
276891
|
-
//
|
|
276892
|
-
|
|
276893
|
-
|
|
276894
|
-
|
|
276895
|
-
|
|
276896
|
-
|
|
276897
|
-
constraint_violation: wire("validation", 400, false, "A database integrity constraint was violated."),
|
|
276887
|
+
entity_not_found: wire("not_found", 404, false, "No row exists with the requested id. It may have been deleted, or the id may belong to a different environment."),
|
|
276888
|
+
model_not_found: wire("not_found", 404, false, "No row of this model exists with the requested id. It may have been deleted, or the id may belong to a different environment."),
|
|
276889
|
+
mutate_update_entity_not_found: wire("not_found", 404, false, "The row targeted by this update does not exist \u2014 it may have been deleted since you read it. Re-read before retrying."),
|
|
276890
|
+
task_id_missing: wire("server", 502, true, "The task-create response arrived without a task id, so the result cannot be used. Retry the request."),
|
|
276891
|
+
// ── data integrity / database constraints ──────────────────────────
|
|
276892
|
+
// Emitted when a database integrity constraint rejects a write. None are
|
|
276893
|
+
// retryable: the same payload re-sent unchanged fails identically, so the
|
|
276894
|
+
// client must roll back rather than retry. The server maps the underlying SQL
|
|
276895
|
+
// constraint to one of these codes and places the raw constraint, column, and
|
|
276896
|
+
// table detail in `details` instead of exposing the driver's message text.
|
|
276897
|
+
not_null_violation: wire("validation", 400, false, "The database rejected the write because a required column was left empty \u2014 a not-null constraint. The error details name the column; supply a value and retry."),
|
|
276898
|
+
foreign_key_violation: wire("conflict", 409, false, "The database rejected the write on a foreign-key constraint: a referenced row does not exist, or the row being deleted is still referenced by others. The error details name the constraint."),
|
|
276899
|
+
unique_violation: wire("conflict", 409, false, "The write duplicates a value that must be unique \u2014 another row already holds it. Choose a different value, or update the existing row."),
|
|
276900
|
+
check_violation: wire("validation", 400, false, "The database rejected a value that fails one of its check constraints. The error details name the constraint; adjust the value and retry."),
|
|
276901
|
+
constraint_violation: wire("validation", 400, false, "The database rejected the write on an integrity constraint. The error details identify the specific constraint."),
|
|
276898
276902
|
column_type_mismatch: wire("validation", 400, false, "A structured (JSON) value was written to a column whose database type cannot hold it. Ablo adapts a json field to either a jsonb column (native) or a text column (serialized) \u2014 but a scalar column (integer, boolean, uuid, timestamp, \u2026) cannot store a JSON object or array. Use a jsonb or text column for this field. Ablo adapts to your column; it does not alter your schema."),
|
|
276899
276903
|
// ── tenant / unknown model (400) ───────────────────────────────────
|
|
276900
276904
|
server_execute_unknown_model: wire("tenant", 400, false, "Wrote to a model the server does not know. The server keeps its own copy of the schema \u2014 run `ablo push` (or keep `ablo dev` running) to upload `ablo/schema.ts` before writing to new or changed models."),
|
|
276901
276905
|
mutate_create_unknown_model: wire("tenant", 400, false, "Created a model the server does not know. Run `ablo push` (or keep `ablo dev` running) to upload `ablo/schema.ts` first \u2014 the server keeps its own copy of the schema."),
|
|
276902
|
-
tenant_model_columns_unknown: wire("tenant", 400, false, "The
|
|
276903
|
-
tenant_model_missing_organization_id: wire("tenant", 400, false, "
|
|
276906
|
+
tenant_model_columns_unknown: wire("tenant", 400, false, "The columns for this model could not be resolved in the tenant database, so the operation cannot be mapped onto its table."),
|
|
276907
|
+
tenant_model_missing_organization_id: wire("tenant", 400, false, "This model's table has no `organization_id` column, which Ablo requires to isolate rows by organization. Add the column before syncing this model."),
|
|
276904
276908
|
// ── schema migration / declaration (validation) ────────────────────
|
|
276905
|
-
schema_mutable_missing_meta: wire("schema", 400, false, "
|
|
276906
|
-
schema_scope_kind_invalid: wire("schema", 400, false, "A scope
|
|
276907
|
-
schema_field_not_camelcase: wire("schema", 400, false, "A schema field name is not camelCase."),
|
|
276908
|
-
schema_field_consecutive_caps: wire("schema", 400, false, "A schema field name
|
|
276909
|
+
schema_mutable_missing_meta: wire("schema", 400, false, "The schema is declared mutable but is missing its required `meta` block."),
|
|
276910
|
+
schema_scope_kind_invalid: wire("schema", 400, false, "A scope declaration in the schema uses a kind the engine does not recognize."),
|
|
276911
|
+
schema_field_not_camelcase: wire("schema", 400, false, "A schema field name is not camelCase. Rename the field (for example `dueDate`) \u2014 Ablo derives column names from camelCase field names."),
|
|
276912
|
+
schema_field_consecutive_caps: wire("schema", 400, false, "A schema field name contains consecutive capital letters, which cannot be mapped to a column name unambiguously. Write acronyms in lower case (`apiKey`, not `APIKey`)."),
|
|
276909
276913
|
schema_reserved_field: client("schema", "A model redeclared a reserved base field (id, createdAt, updatedAt, organizationId, createdBy) that the SDK provides automatically."),
|
|
276910
|
-
schema_grants_shape_invalid: wire("schema", 400, false, "A grants declaration has an invalid shape."),
|
|
276911
|
-
schema_grants_identifier_unsafe: wire("schema", 400, false, "A grants declaration
|
|
276912
|
-
schema_grants_relation_kind: wire("schema", 400, false, "A grants relation
|
|
276913
|
-
schema_grants_relation_missing: wire("schema", 400, false, "A grants declaration
|
|
276914
|
-
schema_grants_target_not_scope_root: wire("schema", 400, false, "A grants
|
|
276915
|
-
drop_field: client("schema", "
|
|
276916
|
-
drop_model: client("schema", "
|
|
276917
|
-
lossy_recreate: client("schema", "
|
|
276918
|
-
made_required: client("schema", "
|
|
276919
|
-
required_field_added: client("schema", "
|
|
276920
|
-
enum_value_removed: client("schema", "
|
|
276921
|
-
risky_cast: client("schema", "
|
|
276914
|
+
schema_grants_shape_invalid: wire("schema", 400, false, "A `grants` declaration in the schema has an invalid shape and could not be parsed."),
|
|
276915
|
+
schema_grants_identifier_unsafe: wire("schema", 400, false, "A `grants` declaration references an identifier that is not safe to use in SQL. Use plain column and relation names."),
|
|
276916
|
+
schema_grants_relation_kind: wire("schema", 400, false, "A `grants` declaration references a relation of a kind it cannot traverse."),
|
|
276917
|
+
schema_grants_relation_missing: wire("schema", 400, false, "A `grants` declaration references a relation the model does not define. Check the relation name against the model."),
|
|
276918
|
+
schema_grants_target_not_scope_root: wire("schema", 400, false, "A `grants` declaration targets a model that is not a scope root, so access cannot be derived from it."),
|
|
276919
|
+
drop_field: client("schema", "This migration would drop an existing field, destroying the data stored in it."),
|
|
276920
|
+
drop_model: client("schema", "This migration would drop an entire model and its table, destroying the rows stored in it."),
|
|
276921
|
+
lossy_recreate: client("schema", "This migration can only apply by recreating the table, which would not preserve its existing rows."),
|
|
276922
|
+
made_required: client("schema", "This migration makes an existing optional field required, which rows without a value for it would violate."),
|
|
276923
|
+
required_field_added: client("schema", "This migration adds a new required field that existing rows have no value for."),
|
|
276924
|
+
enum_value_removed: client("schema", "This migration removes an enum value that existing rows may still hold."),
|
|
276925
|
+
risky_cast: client("schema", "This migration changes a column to a type its current values may not convert to cleanly."),
|
|
276922
276926
|
// ── claim / lease (409 / transport) ───────────────────────────────
|
|
276923
|
-
claim_lease_unavailable: wire("claim", 503, true, "The claim-lease coordination subsystem is unavailable
|
|
276924
|
-
claim_not_wired: client("claim", "
|
|
276925
|
-
claim_queued: wire("claim", 409, true, "The claim was queued behind
|
|
276926
|
-
claim_wait_aborted: wire("claim", 409, true, "
|
|
276927
|
-
claim_wait_poll_interval_required: client("claim", "
|
|
276928
|
-
grant_timeout: wire("claim", 504, true, "
|
|
276929
|
-
slide_intent_missing_deck_id: wire("claim", 400, false, "
|
|
276930
|
-
slide_intent_unknown_sibling: wire("claim", 400, false, "
|
|
276927
|
+
claim_lease_unavailable: wire("claim", 503, true, "The claim-lease coordination subsystem is temporarily unavailable, so the claim could not be processed. Retry shortly."),
|
|
276928
|
+
claim_not_wired: client("claim", "Claims were used, but this runtime has no claim support wired in. The standard `Ablo({ schema, apiKey })` client wires it up automatically."),
|
|
276929
|
+
claim_queued: wire("claim", 409, true, "The claim was queued behind the current lease holder and will be granted in turn. Wait, or read `claim.queue` to see your position."),
|
|
276930
|
+
claim_wait_aborted: wire("claim", 409, true, "The wait for this claim lease was aborted before the lease was granted."),
|
|
276931
|
+
claim_wait_poll_interval_required: client("claim", "Waiting on a claim requires a poll interval, and none was provided."),
|
|
276932
|
+
grant_timeout: wire("claim", 504, true, "The wait for a capability grant timed out before one arrived. Retry the request."),
|
|
276933
|
+
slide_intent_missing_deck_id: wire("claim", 400, false, "This slide claim is missing the id of the deck it belongs to."),
|
|
276934
|
+
slide_intent_unknown_sibling: wire("claim", 400, false, "This slide claim references a sibling slide that does not exist in the deck."),
|
|
276931
276935
|
// ── bootstrap (transport) ──────────────────────────────────────────
|
|
276932
|
-
bootstrap_fetch_timeout: wire("bootstrap", 504, true, "The bootstrap fetch timed out."),
|
|
276933
|
-
bootstrap_offline: wire("bootstrap", 503, true, "Bootstrap could not run because the client is offline."),
|
|
276934
|
-
bootstrap_offline_no_cache: wire("bootstrap", 503, false, "
|
|
276935
|
-
bootstrap_response_invalid: wire("bootstrap", 502, true, "The bootstrap response
|
|
276936
|
-
bootstrap_response_schema_invalid: wire("bootstrap", 502, true, "The bootstrap response failed schema validation."),
|
|
276936
|
+
bootstrap_fetch_timeout: wire("bootstrap", 504, true, "The initial bootstrap fetch timed out before the server responded. Retry shortly."),
|
|
276937
|
+
bootstrap_offline: wire("bootstrap", 503, true, "Bootstrap could not run because the client is offline. It can proceed once the network returns."),
|
|
276938
|
+
bootstrap_offline_no_cache: wire("bootstrap", 503, false, "The client is offline and no cached snapshot is available to start from, so there is no data to load until the network returns."),
|
|
276939
|
+
bootstrap_response_invalid: wire("bootstrap", 502, true, "The bootstrap response could not be parsed. Retrying may succeed."),
|
|
276940
|
+
bootstrap_response_schema_invalid: wire("bootstrap", 502, true, "The bootstrap response parsed but failed schema validation, so it was not applied. Retrying may succeed."),
|
|
276937
276941
|
// ── transport / connection ─────────────────────────────────────────
|
|
276938
|
-
exchange_malformed_response: wire("transport", 502, true, "The credential exchange returned a
|
|
276939
|
-
exchange_network_error: wire("transport", 503, true, "A network error
|
|
276940
|
-
source_network_error: wire("transport", 503, true, "A network error occurred talking to the source."),
|
|
276941
|
-
identity_network_error: wire("transport", 503, true, "A network error occurred resolving identity."),
|
|
276942
|
-
commit_no_result: wire("transport", 504, true, "The commit was sent but no result frame arrived."),
|
|
276943
|
-
commit_failed: wire("transport", 500, true, "The commit failed to apply."),
|
|
276944
|
-
commit_offline_grace_expired: wire("transport", 503, false, "The offline grace window expired before
|
|
276945
|
-
queue_too_deep: wire("transport", 503, true, "The transaction queue
|
|
276946
|
-
flush_timeout: wire("transport", 504, true, "
|
|
276947
|
-
wait_for_timeout: wire("transport", 504, true, "A wait-for condition timed out."),
|
|
276942
|
+
exchange_malformed_response: wire("transport", 502, true, "The credential exchange returned a response that could not be parsed. Retrying may succeed."),
|
|
276943
|
+
exchange_network_error: wire("transport", 503, true, "A network error interrupted the credential exchange. Check connectivity and retry."),
|
|
276944
|
+
source_network_error: wire("transport", 503, true, "A network error occurred while talking to the data source. Check connectivity and retry."),
|
|
276945
|
+
identity_network_error: wire("transport", 503, true, "A network error occurred while resolving your identity. Check connectivity and retry."),
|
|
276946
|
+
commit_no_result: wire("transport", 504, true, "The commit was sent, but no result frame arrived, so its outcome is unknown. It is safe to retry."),
|
|
276947
|
+
commit_failed: wire("transport", 500, true, "The commit reached the server but failed to apply. Retrying may succeed."),
|
|
276948
|
+
commit_offline_grace_expired: wire("transport", 503, false, "The offline grace window expired before this commit could be sent, so it was not applied. Re-apply the change once the connection returns."),
|
|
276949
|
+
queue_too_deep: wire("transport", 503, true, "The transaction queue is over its depth limit, so new writes are being rejected until it drains. Retry shortly."),
|
|
276950
|
+
flush_timeout: wire("transport", 504, true, "Flushing the transaction queue timed out before every pending write was sent. Retry once connectivity stabilizes."),
|
|
276951
|
+
wait_for_timeout: wire("transport", 504, true, "A wait-for condition timed out before it was satisfied. Retry, or extend the timeout."),
|
|
276948
276952
|
instance_at_capacity: wire("transport", 503, true, "The server is at connection capacity. Retry shortly \u2014 transient and not specific to your credentials."),
|
|
276949
|
-
fetch_unavailable: client("transport", "
|
|
276950
|
-
base_url_missing: client("transport", "
|
|
276951
|
-
sync_not_ready: client("transport", "A sync operation
|
|
276952
|
-
ws_not_ready: client("transport", "A frame was sent before the WebSocket was
|
|
276953
|
+
fetch_unavailable: client("transport", "This environment provides no `fetch` implementation, so HTTP requests cannot be made. Run on a platform with `fetch` (Node 18+, modern browsers) or supply a polyfill."),
|
|
276954
|
+
base_url_missing: client("transport", "The client has no base URL configured, so it cannot address the server. Set the base URL when constructing the client."),
|
|
276955
|
+
sync_not_ready: client("transport", "A sync operation ran before the client finished initializing. Wait for the client to be ready before syncing."),
|
|
276956
|
+
ws_not_ready: client("transport", "A frame was sent before the WebSocket connection was established. Wait for the connection to open before sending."),
|
|
276953
276957
|
// ── quota / rate limit (429) ──────────────────────────────────────
|
|
276954
|
-
quota_exceeded: wire("rate_limit", 429, true, "
|
|
276958
|
+
quota_exceeded: wire("rate_limit", 429, true, "Your organization has used up its configured usage quota. Requests will succeed again once the quota resets or the limit is raised."),
|
|
276955
276959
|
connection_limit_exceeded: wire("rate_limit", 429, true, "Too many concurrent WebSocket connections for this principal or organization. Close idle connections, or retry once others drain."),
|
|
276956
|
-
//
|
|
276957
|
-
//
|
|
276958
|
-
// so one noisy key backs off without affecting
|
|
276959
|
-
// `Retry-After` header carries the
|
|
276960
|
-
|
|
276960
|
+
// A per-key request-rate limit — the fast, requests-per-second axis, as
|
|
276961
|
+
// opposed to `quota_exceeded`, which is the slower organization-wide usage
|
|
276962
|
+
// limit. It is keyed per API key, so one noisy key backs off without affecting
|
|
276963
|
+
// the rest of the organization. The `Retry-After` header carries the delay
|
|
276964
|
+
// before the next request is allowed.
|
|
276965
|
+
rate_limit_exceeded: wire("rate_limit", 429, true, "This API key is sending requests faster than its rate limit allows. Slow down and retry after the delay in the `Retry-After` header."),
|
|
276961
276966
|
// ── server (5xx) ───────────────────────────────────────────────────
|
|
276962
|
-
internal_error: wire("server", 500, true, "
|
|
276963
|
-
quota_lookup_failed: wire("server", 503, true, "The
|
|
276964
|
-
// The
|
|
276965
|
-
//
|
|
276966
|
-
//
|
|
276967
|
+
internal_error: wire("server", 500, true, "Something went wrong on Ablo's side \u2014 an unexpected server error. It is safe to retry."),
|
|
276968
|
+
quota_lookup_failed: wire("server", 503, true, "The server could not load this organization's quota state, so the request was rejected rather than admitted unchecked. Retry shortly."),
|
|
276969
|
+
// The rate-limiter backend was unreachable and this endpoint is configured to
|
|
276970
|
+
// fail closed, so the request was rejected rather than admitted unchecked. It
|
|
276971
|
+
// is retryable: the next attempt re-probes the backend.
|
|
276967
276972
|
rate_limiter_unavailable: wire("server", 503, true, "The rate-limiter backend is unavailable and this endpoint is configured to fail closed; retry shortly."),
|
|
276968
|
-
turn_open_failed: wire("server", 500, true, "The agent turn
|
|
276969
|
-
turn_close_failed: wire("server", 500, true, "The agent turn
|
|
276973
|
+
turn_open_failed: wire("server", 500, true, "The agent turn could not be opened on the server. It is safe to retry."),
|
|
276974
|
+
turn_close_failed: wire("server", 500, true, "The agent turn could not be closed cleanly on the server. It is safe to retry the close."),
|
|
276970
276975
|
// ── client-only invariants (never serialized) ──────────────────────
|
|
276971
276976
|
invalid_options: client("client", "The Ablo client was constructed with invalid or incomplete options."),
|
|
276972
276977
|
no_ablo_provider: client("client", "An Ablo hook was used outside of an Ablo provider."),
|
|
@@ -277006,58 +277011,72 @@ var ERROR_CODES = {
|
|
|
277006
277011
|
undo_entry_invalid: client("client", "An undo entry failed inverse-op schema validation."),
|
|
277007
277012
|
mock_mutation_failed: client("client", "A mock mutation adapter was configured to fail."),
|
|
277008
277013
|
mock_unsupported_operation: client("client", "A mock adapter received an unsupported operation."),
|
|
277009
|
-
// ── HTTP route edge codes
|
|
277014
|
+
// ── HTTP route edge codes ──────────────────────────────────────────
|
|
277010
277015
|
invalid_body: wire("validation", 400, false, "The request body was missing, unparseable, or the wrong shape."),
|
|
277011
277016
|
invalid_json: wire("validation", 400, false, "The request body was not valid JSON."),
|
|
277012
277017
|
capability_id_required: wire("validation", 400, false, "A capability id is required for this request."),
|
|
277013
277018
|
organization_mismatch: wire("permission", 403, false, "The request targeted an organization the caller is not scoped to."),
|
|
277014
277019
|
project_scope_denied: wire("permission", 403, false, "The request targeted a project the caller's key is not scoped to."),
|
|
277015
|
-
project_slug_taken: wire("validation", 409, false, "A project with this slug already exists in the organization."),
|
|
277020
|
+
project_slug_taken: wire("validation", 409, false, "A project with this slug already exists in the organization. Choose a different slug."),
|
|
277016
277021
|
forbidden: wire("permission", 403, false, "The caller lacks permission for this operation."),
|
|
277017
|
-
source_api_key_unresolved: wire("auth", 401, false, "The
|
|
277022
|
+
source_api_key_unresolved: wire("auth", 401, false, "The API key presented for this data source could not be resolved to a known key. Check the key and its environment."),
|
|
277018
277023
|
capability_auth_disabled: wire("server", 503, false, "Capability authentication is disabled on this server."),
|
|
277019
|
-
provisioner_unavailable: wire("server", 503, false, "
|
|
277020
|
-
invalid_model: wire("validation", 400, false, "The request
|
|
277021
|
-
invalid_id: wire("validation", 400, false, "The request
|
|
277024
|
+
provisioner_unavailable: wire("server", 503, false, "This deployment has no database provisioner configured, so tables cannot be created here."),
|
|
277025
|
+
invalid_model: wire("validation", 400, false, "The model name in the request is not a valid model identifier."),
|
|
277026
|
+
invalid_id: wire("validation", 400, false, "The id in the request is not a valid identifier."),
|
|
277022
277027
|
unknown_model: wire("tenant", 400, false, "Named a model the server does not know. Run `ablo push` (or keep `ablo dev` running) to upload `ablo/schema.ts` \u2014 the server keeps its own copy of the schema."),
|
|
277023
|
-
model_not_tenant_scoped: wire("tenant", 400, false, "
|
|
277028
|
+
model_not_tenant_scoped: wire("tenant", 400, false, "This model is not tenant-scoped, so it cannot be queried through the tenant-scoped read path."),
|
|
277024
277029
|
schema_table_invalid: wire("schema", 500, false, "The model's table identifier is invalid."),
|
|
277025
277030
|
schema_scope_invalid: wire("schema", 500, false, "The model's scope predicate could not be built."),
|
|
277026
|
-
entity_fetch_failed: wire("server", 500, true, "The
|
|
277027
|
-
events_required: wire("validation", 400, false, "The request must include a non-empty events array."),
|
|
277028
|
-
ingest_failed: wire("validation", 400, false, "The source-event ingest
|
|
277029
|
-
migration_failed: wire("server", 500, false, "The schema migration failed
|
|
277030
|
-
|
|
277031
|
-
|
|
277031
|
+
entity_fetch_failed: wire("server", 500, true, "The server failed to fetch the requested entity. It is safe to retry."),
|
|
277032
|
+
events_required: wire("validation", 400, false, "The request must include a non-empty `events` array."),
|
|
277033
|
+
ingest_failed: wire("validation", 400, false, "The source-event batch was rejected during ingest and nothing was appended. Check the events against the expected shape and re-send."),
|
|
277034
|
+
migration_failed: wire("server", 500, false, "The schema migration failed while applying and did not complete."),
|
|
277035
|
+
schema_provisioning_forbidden: wire(
|
|
277036
|
+
"permission",
|
|
277037
|
+
403,
|
|
277038
|
+
false,
|
|
277039
|
+
"Schema registration could not create tables in the target database: the engine is not permitted to run DDL there."
|
|
277040
|
+
),
|
|
277041
|
+
model_query_failed: wire("validation", 400, false, "The model query failed to execute. Check the query filters and operators."),
|
|
277042
|
+
queries_required: wire("validation", 400, false, "The request must include a non-empty `queries` array."),
|
|
277032
277043
|
query_unsupported_operator: wire("validation", 400, false, "The query used an unsupported operator."),
|
|
277033
|
-
|
|
277034
|
-
|
|
277044
|
+
query_invalid_like_pattern: wire("validation", 400, false, "The `LIKE` pattern must not end with an escape character."),
|
|
277045
|
+
query_invalid_boolean: wire("validation", 400, false, "The query compared a boolean column against an invalid boolean literal."),
|
|
277046
|
+
protocol_version_unsupported: wire("transport", 426, false, "The client sync-protocol version is outside the range this server supports \u2014 upgrade the SDK (or the server was rolled back mid-fleet)."),
|
|
277047
|
+
database_unreachable: wire("validation", 400, false, "Ablo could not reach this database to check that it can stream replication. The connection string may be wrong, the host may not be reachable from Ablo's servers, or the credentials may not be accepted."),
|
|
277048
|
+
database_not_replication_ready: wire("validation", 400, false, "This database is not set up for logical replication yet. Every failing item \u2014 wal_level, the publication, the replication grant, a replica identity \u2014 is listed in the error details with its exact fix. `ablo connect` prints the one-time setup; `ablo connect --check` verifies it."),
|
|
277049
|
+
replication_publication_drift: wire("validation", 400, false, "Your schema maps to tables that are not members of the replication publication, so their changes silently never stream and the source looks frozen. The missing tables and the exact `ALTER PUBLICATION \u2026 ADD TABLE \u2026` to add them are in the error details \u2014 Ablo never alters your database for you."),
|
|
277050
|
+
query_unknown_relation: wire("validation", 400, false, "The query references a relation the model does not define. Check the relation name against the schema."),
|
|
277051
|
+
query_relation_target_unknown: wire("schema", 500, false, "A relation in the query targets a model the schema does not define."),
|
|
277035
277052
|
query_invalid_identifier: wire("validation", 400, false, "The query contained an invalid identifier."),
|
|
277036
277053
|
org_id_required: wire("validation", 400, false, "An organization id is required for this request."),
|
|
277037
|
-
presence_identity_required: wire("validation", 400, false, "
|
|
277038
|
-
upload_fields_required: wire("validation", 400, false, "
|
|
277039
|
-
upload_items_required: wire("validation", 400, false, "The request must include a non-empty items array."),
|
|
277040
|
-
presigned_url_failed: wire("server", 500, true, "
|
|
277054
|
+
presence_identity_required: wire("validation", 400, false, "Presence requests must carry both `userId` and `organizationId`."),
|
|
277055
|
+
upload_fields_required: wire("validation", 400, false, "The upload request is missing a required field."),
|
|
277056
|
+
upload_items_required: wire("validation", 400, false, "The request must include a non-empty `items` array."),
|
|
277057
|
+
presigned_url_failed: wire("server", 500, true, "The server could not generate a presigned upload URL. It is safe to retry."),
|
|
277058
|
+
upload_not_configured: wire("server", 503, false, "Uploads are not configured on this deployment: the upload storage bucket and CDN domain are unset."),
|
|
277041
277059
|
task_id_required: wire("validation", 400, false, "A task id is required for this request."),
|
|
277042
|
-
claim_id_required: wire("validation", 400, false, "
|
|
277060
|
+
claim_id_required: wire("validation", 400, false, "A claim id is required for this request."),
|
|
277043
277061
|
commit_operation_action_required: wire("validation", 400, false, "A commit operation is missing its `action`."),
|
|
277044
277062
|
commit_operation_unsupported: wire("validation", 400, false, "A commit operation used an unsupported `action`."),
|
|
277045
277063
|
usage_invalid: wire("validation", 400, false, "The usage request was invalid."),
|
|
277046
277064
|
invalid_request: wire("validation", 400, false, "The request parameters were invalid."),
|
|
277047
277065
|
capability_not_found: wire("not_found", 404, false, "No capability exists with the given id."),
|
|
277048
|
-
invalid_participant_kind: wire("validation", 400, false, "The participant kind is
|
|
277049
|
-
invalid_sync_group: wire("validation", 400, false,
|
|
277050
|
-
narrow_scope_required: wire("validation", 400, false, "
|
|
277051
|
-
wide_scope_forbidden: wire("permission", 403, false, "
|
|
277052
|
-
capability_required: wire("auth", 401, false, "This operation requires a capability."),
|
|
277066
|
+
invalid_participant_kind: wire("validation", 400, false, "The participant kind is not one the server recognizes."),
|
|
277067
|
+
invalid_sync_group: wire("validation", 400, false, "Sync groups must be `default` or `<namespace>:<id>`."),
|
|
277068
|
+
narrow_scope_required: wire("validation", 400, false, "This request requires a scope narrowed to specific resources; the presented scope is too broad."),
|
|
277069
|
+
wide_scope_forbidden: wire("permission", 403, false, "This caller may not use a wide scope. Request a scope narrowed to the resources you need."),
|
|
277070
|
+
capability_required: wire("auth", 401, false, "This operation requires a capability, and none was presented."),
|
|
277053
277071
|
parent_turn_not_found: wire("not_found", 404, false, "The referenced parent turn does not exist."),
|
|
277054
|
-
parent_turn_foreign_agent: wire("permission", 403, false, "The parent turn belongs to a different agent."),
|
|
277072
|
+
parent_turn_foreign_agent: wire("permission", 403, false, "The referenced parent turn belongs to a different agent, so it cannot be used here."),
|
|
277055
277073
|
turn_not_found: wire("not_found", 404, false, "The referenced turn does not exist."),
|
|
277056
|
-
turn_foreign_agent: wire("permission", 403, false, "
|
|
277057
|
-
invalid_intent: wire("validation", 400, false, "The claim request was
|
|
277074
|
+
turn_foreign_agent: wire("permission", 403, false, "This turn belongs to a different agent, so the caller cannot act on it."),
|
|
277075
|
+
invalid_intent: wire("validation", 400, false, "The claim request was malformed and could not be processed."),
|
|
277058
277076
|
schema_too_large: wire("validation", 413, false, "The submitted schema exceeds the maximum size."),
|
|
277077
|
+
request_too_large: wire("validation", 413, false, "The request body exceeds the maximum size."),
|
|
277059
277078
|
invalid_schema: wire("validation", 400, false, "The submitted schema could not be parsed."),
|
|
277060
|
-
incompatible_change: wire("conflict", 409, false, "The schema change is incompatible with the
|
|
277079
|
+
incompatible_change: wire("conflict", 409, false, "The schema change is incompatible with the schema currently deployed and cannot be applied as-is.")
|
|
277061
277080
|
};
|
|
277062
277081
|
function errorCodeSpec(code) {
|
|
277063
277082
|
return ERROR_CODES[code];
|
|
@@ -277136,7 +277155,7 @@ var writeGuardSchema = import_zod3.z.object({
|
|
|
277136
277155
|
bypass: import_zod3.z.boolean().optional()
|
|
277137
277156
|
});
|
|
277138
277157
|
var staleNotificationSchema = import_zod3.z.object({
|
|
277139
|
-
/**
|
|
277158
|
+
/** Names this object's type; every returned object carries such a tag. */
|
|
277140
277159
|
object: import_zod3.z.literal("stale_notification").optional(),
|
|
277141
277160
|
/** Model name of the conflicting row. */
|
|
277142
277161
|
model: import_zod3.z.string(),
|
|
@@ -277156,8 +277175,8 @@ var staleNotificationSchema = import_zod3.z.object({
|
|
|
277156
277175
|
*/
|
|
277157
277176
|
conflictingFields: import_zod3.z.array(import_zod3.z.string()),
|
|
277158
277177
|
/**
|
|
277159
|
-
*
|
|
277160
|
-
* error
|
|
277178
|
+
* The live values of `conflictingFields` after the conflict — the piece a
|
|
277179
|
+
* plain stale error omits. It lets the actor reconcile without a follow-up read.
|
|
277161
277180
|
*/
|
|
277162
277181
|
currentValues: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()),
|
|
277163
277182
|
/** Who wrote the conflicting delta. */
|
|
@@ -277266,10 +277285,10 @@ var claimBeginPayloadSchema = targetRefSchema.extend({
|
|
|
277266
277285
|
/** Hint for `expiresAt`; the server caps it. */
|
|
277267
277286
|
estimatedMs: import_zod3.z.number().optional(),
|
|
277268
277287
|
/**
|
|
277269
|
-
* Opt into the fair wait queue
|
|
277270
|
-
* enqueues this claim
|
|
277271
|
-
* `claim_granted
|
|
277272
|
-
* handle the grant.
|
|
277288
|
+
* Opt into the fair wait queue. When the target is already held, the server
|
|
277289
|
+
* enqueues this claim in FIFO order and replies `claim_queued`, then
|
|
277290
|
+
* `claim_granted` later, instead of `claim_rejected`. A client that sets this
|
|
277291
|
+
* must be ready to handle the grant.
|
|
277273
277292
|
*/
|
|
277274
277293
|
queue: import_zod3.z.boolean().optional()
|
|
277275
277294
|
});
|
|
@@ -277283,6 +277302,48 @@ var claimReorderPayloadSchema = import_zod3.z.object({
|
|
|
277283
277302
|
entityId: import_zod3.z.string(),
|
|
277284
277303
|
order: import_zod3.z.array(import_zod3.z.object({ heldBy: import_zod3.z.string(), claimId: import_zod3.z.string() }))
|
|
277285
277304
|
});
|
|
277305
|
+
var claimHeartbeatFieldsSchema = import_zod3.z.object({
|
|
277306
|
+
claimId: import_zod3.z.string().optional(),
|
|
277307
|
+
entityType: import_zod3.z.string().optional(),
|
|
277308
|
+
entityId: import_zod3.z.string().optional(),
|
|
277309
|
+
/** Requested extension from now; the server clamps it, and an extension
|
|
277310
|
+
* never shortens a lease. */
|
|
277311
|
+
ttlMs: import_zod3.z.number().positive().optional(),
|
|
277312
|
+
/**
|
|
277313
|
+
* Lightweight progress the beat carries along ("42/100 pages") — stored
|
|
277314
|
+
* as the claim's `meta.progress` (last beat wins) and peer-visible via
|
|
277315
|
+
* `claim.state` while the lease is held. This is presence, not a
|
|
277316
|
+
* checkpoint: it dies with the lease. Crash-recoverable progress belongs
|
|
277317
|
+
* in the data itself — write a row, and every subscriber already sees it.
|
|
277318
|
+
*/
|
|
277319
|
+
details: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional()
|
|
277320
|
+
});
|
|
277321
|
+
var claimHeartbeatPayloadSchema = claimHeartbeatFieldsSchema.refine(
|
|
277322
|
+
(payload) => payload.claimId !== void 0 || payload.entityType !== void 0 && payload.entityId !== void 0,
|
|
277323
|
+
{
|
|
277324
|
+
message: "a heartbeat must identify its claim \u2014 pass claimId, or entityType and entityId together"
|
|
277325
|
+
}
|
|
277326
|
+
);
|
|
277327
|
+
var claimHeartbeatAckPayloadSchema = import_zod3.z.object({
|
|
277328
|
+
claimId: import_zod3.z.string(),
|
|
277329
|
+
status: import_zod3.z.enum(["held", "queued", "lost"]),
|
|
277330
|
+
expiresAt: import_zod3.z.number().optional(),
|
|
277331
|
+
position: import_zod3.z.number().optional(),
|
|
277332
|
+
/**
|
|
277333
|
+
* How many participants are waiting in line behind a held lease — the
|
|
277334
|
+
* cooperative-yield pressure signal (present on `held`). A worker that can
|
|
277335
|
+
* checkpoint may choose to release early when others wait. Hard
|
|
277336
|
+
* cancellation needs no extra field: a preempted, expired, or revoked
|
|
277337
|
+
* lease answers the next beat with `lost`.
|
|
277338
|
+
*/
|
|
277339
|
+
queueDepth: import_zod3.z.number().optional()
|
|
277340
|
+
});
|
|
277341
|
+
var claimHeartbeatBatchPayloadSchema = claimHeartbeatFieldsSchema.pick(
|
|
277342
|
+
{ ttlMs: true }
|
|
277343
|
+
);
|
|
277344
|
+
var claimHeartbeatBatchAckPayloadSchema = import_zod3.z.object({
|
|
277345
|
+
results: import_zod3.z.array(claimHeartbeatAckPayloadSchema)
|
|
277346
|
+
});
|
|
277286
277347
|
var updateSubscriptionPayloadSchema = import_zod3.z.object({
|
|
277287
277348
|
syncGroups: import_zod3.z.array(syncGroupInputSchema)
|
|
277288
277349
|
});
|
|
@@ -277332,35 +277393,34 @@ var presenceUpdateFrameSchema = import_zod3.z.object({
|
|
|
277332
277393
|
|
|
277333
277394
|
// src/errors.ts
|
|
277334
277395
|
var AbloError = class extends Error {
|
|
277335
|
-
/**
|
|
277336
|
-
*
|
|
277337
|
-
*
|
|
277396
|
+
/** A discriminator string equal to the class name. Switch on `error.type` to
|
|
277397
|
+
* distinguish error kinds when `instanceof` is unreliable, such as after an
|
|
277398
|
+
* error has crossed a serialization boundary. */
|
|
277338
277399
|
type = "AbloError";
|
|
277339
|
-
/**
|
|
277340
|
-
* {@link ErrorCode} registry —
|
|
277341
|
-
* `'capability_scope_denied'
|
|
277342
|
-
*
|
|
277343
|
-
*
|
|
277344
|
-
*
|
|
277400
|
+
/** A stable, machine-readable identifier for the error, drawn from the
|
|
277401
|
+
* {@link ErrorCode} registry — for example `'apikey_invalid'` or
|
|
277402
|
+
* `'capability_scope_denied'` — suitable for logs, metrics, and `switch`
|
|
277403
|
+
* handling. It is typed as a plain `string` rather than {@link ErrorCode} so
|
|
277404
|
+
* this client can still surface a code from a newer server that it does not
|
|
277405
|
+
* yet recognize; code producers are constrained at the constructor instead. */
|
|
277345
277406
|
code;
|
|
277346
|
-
/** HTTP status code when the error originated from an HTTP response. */
|
|
277407
|
+
/** HTTP status code, when the error originated from an HTTP response. */
|
|
277347
277408
|
httpStatus;
|
|
277348
|
-
/**
|
|
277349
|
-
* `x-request-id
|
|
277409
|
+
/** A correlation id for tracing a request through the server, present when the
|
|
277410
|
+
* server returned one on the `x-request-id` header. Include it in support
|
|
277411
|
+
* requests. */
|
|
277350
277412
|
requestId;
|
|
277351
|
-
/**
|
|
277352
|
-
* `'dataroomMember.grants.subject'
|
|
277353
|
-
*
|
|
277413
|
+
/** The specific input that caused the error, as a model or field path such as
|
|
277414
|
+
* `'dataroomMember.grants.subject'`, so tooling can point at the exact
|
|
277415
|
+
* offending value. */
|
|
277354
277416
|
param;
|
|
277355
|
-
/**
|
|
277356
|
-
*
|
|
277417
|
+
/** A link to the documentation for this error's {@link code}. When not set
|
|
277418
|
+
* explicitly, it is derived from the code by {@link docUrlForCode}. */
|
|
277357
277419
|
docUrl;
|
|
277358
|
-
/**
|
|
277359
|
-
*
|
|
277360
|
-
* conflicting rows.
|
|
277361
|
-
*
|
|
277362
|
-
* structured error keeps its detail through `toJSON` instead of being
|
|
277363
|
-
* flattened to a bare message. */
|
|
277420
|
+
/** Extra structured data specific to this error, merged into the serialized
|
|
277421
|
+
* envelope — for example a schema push's `{ warnings, unexecutable }`, or the
|
|
277422
|
+
* conflicting rows of a stale write. This detail is preserved through
|
|
277423
|
+
* {@link toJSON} rather than flattened into the message. */
|
|
277364
277424
|
details;
|
|
277365
277425
|
constructor(message, options) {
|
|
277366
277426
|
super(message);
|
|
@@ -277377,9 +277437,10 @@ var AbloError = class extends Error {
|
|
|
277377
277437
|
}
|
|
277378
277438
|
}
|
|
277379
277439
|
/**
|
|
277380
|
-
*
|
|
277381
|
-
* doc_url, request_id }
|
|
277382
|
-
*
|
|
277440
|
+
* Serializes the error to its wire shape: `{ type, code, param, message,
|
|
277441
|
+
* doc_url, request_id }`, with any {@link details} merged in. This is the same
|
|
277442
|
+
* JSON shape the SDK uses across HTTP bodies, WebSocket frames, and logs, so a
|
|
277443
|
+
* consumer parses every Ablo error the same way.
|
|
277383
277444
|
*/
|
|
277384
277445
|
toJSON() {
|
|
277385
277446
|
return {
|
|
@@ -277393,12 +277454,13 @@ var AbloError = class extends Error {
|
|
|
277393
277454
|
};
|
|
277394
277455
|
}
|
|
277395
277456
|
/**
|
|
277396
|
-
*
|
|
277397
|
-
*
|
|
277457
|
+
* Formats the error as a single line for logs and string interpolation:
|
|
277458
|
+
* `AbloValidationError [code]: message (see docs) [request_id: …]`.
|
|
277398
277459
|
*
|
|
277399
|
-
*
|
|
277400
|
-
*
|
|
277401
|
-
* payload
|
|
277460
|
+
* It intentionally omits {@link details}, the cause, and the stack, which are
|
|
277461
|
+
* what turn a logged rich error into an unreadable wall of text. The full
|
|
277462
|
+
* structured payload remains available through {@link toJSON}; this is the
|
|
277463
|
+
* concise human-readable form.
|
|
277402
277464
|
*/
|
|
277403
277465
|
toString() {
|
|
277404
277466
|
const code = this.code ? ` [${this.code}]` : "";
|
|
@@ -277439,8 +277501,8 @@ var ErrorFieldSchema = import_zod4.z.preprocess(
|
|
|
277439
277501
|
import_zod4.z.union([import_zod4.z.string(), NestedErrorShapeSchema]).optional()
|
|
277440
277502
|
).catch(void 0);
|
|
277441
277503
|
var ErrorBodyShapeSchema = import_zod4.z.object({
|
|
277442
|
-
/**
|
|
277443
|
-
*
|
|
277504
|
+
/** The `error` field may be a flat code string, as some endpoints return,
|
|
277505
|
+
* or a nested error object, as a {@link CommitReceipt} carries. */
|
|
277444
277506
|
error: ErrorFieldSchema,
|
|
277445
277507
|
code: OptionalWireStringSchema,
|
|
277446
277508
|
reason: OptionalWireStringSchema,
|
|
@@ -279600,7 +279662,7 @@ function readProjectDatabaseUrl(cwd = process.cwd()) {
|
|
|
279600
279662
|
for (const name of [".env.local", ".env"]) {
|
|
279601
279663
|
const path = (0, import_path.resolve)(cwd, name);
|
|
279602
279664
|
if (!(0, import_fs2.existsSync)(path)) continue;
|
|
279603
|
-
const match = (0, import_fs2.readFileSync)(path, "utf8")
|
|
279665
|
+
const match = /^DATABASE_URL=(.+)$/m.exec((0, import_fs2.readFileSync)(path, "utf8"));
|
|
279604
279666
|
if (match?.[1]) return match[1].trim().replace(/^["']|["']$/g, "");
|
|
279605
279667
|
}
|
|
279606
279668
|
return null;
|
|
@@ -279610,7 +279672,7 @@ function readProjectApiKey(cwd = process.cwd()) {
|
|
|
279610
279672
|
for (const name of [".env.local", ".env"]) {
|
|
279611
279673
|
const path = (0, import_path.resolve)(cwd, name);
|
|
279612
279674
|
if (!(0, import_fs2.existsSync)(path)) continue;
|
|
279613
|
-
const match = (0, import_fs2.readFileSync)(path, "utf8")
|
|
279675
|
+
const match = /^ABLO_API_KEY=(.+)$/m.exec((0, import_fs2.readFileSync)(path, "utf8"));
|
|
279614
279676
|
if (match?.[1]) return { key: match[1].trim().replace(/^["']|["']$/g, ""), source: name };
|
|
279615
279677
|
}
|
|
279616
279678
|
return null;
|
|
@@ -279645,6 +279707,12 @@ var import_path3 = require("path");
|
|
|
279645
279707
|
var import_child_process = require("child_process");
|
|
279646
279708
|
var import_schema2 = require("@abloatai/ablo/schema");
|
|
279647
279709
|
|
|
279710
|
+
// src/client/hostedEndpoints.ts
|
|
279711
|
+
init_cjs_shims();
|
|
279712
|
+
var ABLO_HOSTED_API_DOMAIN = "api.abloatai.com";
|
|
279713
|
+
var ABLO_HOSTED_HTTP_BASE_URL = `https://${ABLO_HOSTED_API_DOMAIN}`;
|
|
279714
|
+
var ABLO_DEFAULT_BASE_URL = ABLO_HOSTED_HTTP_BASE_URL;
|
|
279715
|
+
|
|
279648
279716
|
// src/cli/config.ts
|
|
279649
279717
|
init_cjs_shims();
|
|
279650
279718
|
var import_os2 = require("os");
|
|
@@ -279876,12 +279944,18 @@ function guardActiveProjectKey() {
|
|
|
279876
279944
|
const available = Object.entries(profiles).filter(([, keys]) => hasKey(keys)).map(([name]) => name);
|
|
279877
279945
|
return { ok: hasKey(profiles[activeProfile]), activeProfile, available };
|
|
279878
279946
|
}
|
|
279947
|
+
function resolveEffectiveApiKey(modeOverride, cwd) {
|
|
279948
|
+
const fromProject = readProjectApiKey(cwd);
|
|
279949
|
+
if (fromProject) return { key: fromProject.key, source: fromProject.source };
|
|
279950
|
+
const key = resolveApiKey(modeOverride);
|
|
279951
|
+
return key ? { key, source: "stored" } : { key: void 0, source: null };
|
|
279952
|
+
}
|
|
279879
279953
|
function resolvePushPlan() {
|
|
279880
|
-
const
|
|
279881
|
-
if (
|
|
279882
|
-
|
|
279883
|
-
|
|
279884
|
-
return { flow:
|
|
279954
|
+
const { key, source } = resolveEffectiveApiKey();
|
|
279955
|
+
if (key != null && source != null && source !== "stored") {
|
|
279956
|
+
return { flow: modeFromKey(key) ?? getMode(), apiKey: key, source };
|
|
279957
|
+
}
|
|
279958
|
+
return { flow: getMode(), apiKey: key, source };
|
|
279885
279959
|
}
|
|
279886
279960
|
|
|
279887
279961
|
// src/cli/theme.ts
|
|
@@ -279906,7 +279980,7 @@ function coerceBackfill(raw) {
|
|
|
279906
279980
|
}
|
|
279907
279981
|
var DEFAULT_SCHEMA_PATH = "ablo/schema.ts";
|
|
279908
279982
|
var DEFAULT_EXPORT = "schema";
|
|
279909
|
-
var DEFAULT_URL =
|
|
279983
|
+
var DEFAULT_URL = ABLO_DEFAULT_BASE_URL;
|
|
279910
279984
|
function fmtSignal(s) {
|
|
279911
279985
|
const sig = s;
|
|
279912
279986
|
const where = sig.field ? `${sig.model}.${sig.field}` : sig.model;
|
|
@@ -280049,7 +280123,9 @@ function schemaGitState(schemaPath) {
|
|
|
280049
280123
|
}
|
|
280050
280124
|
async function fetchActiveSchema(url, apiKey) {
|
|
280051
280125
|
const ctrl = new AbortController();
|
|
280052
|
-
const t = setTimeout(() =>
|
|
280126
|
+
const t = setTimeout(() => {
|
|
280127
|
+
ctrl.abort();
|
|
280128
|
+
}, 3e3);
|
|
280053
280129
|
try {
|
|
280054
280130
|
const res = await fetch(`${url}/api/schema`, {
|
|
280055
280131
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
@@ -280116,7 +280192,7 @@ async function confirmPush(args, env) {
|
|
|
280116
280192
|
const project = getActiveProject();
|
|
280117
280193
|
const expected = project?.slug ?? "production";
|
|
280118
280194
|
const typed = await he({
|
|
280119
|
-
message: `This deploys to ${import_picocolors3.default.
|
|
280195
|
+
message: `This deploys to ${import_picocolors3.default.bold("production")}. Type ${import_picocolors3.default.bold(expected)} to confirm:`,
|
|
280120
280196
|
placeholder: expected
|
|
280121
280197
|
});
|
|
280122
280198
|
if (pD(typed) || String(typed).trim() !== expected) {
|
|
@@ -280126,7 +280202,7 @@ async function confirmPush(args, env) {
|
|
|
280126
280202
|
return;
|
|
280127
280203
|
}
|
|
280128
280204
|
if (!isProd && !args.yes && tty) {
|
|
280129
|
-
const ok = await ye({ message: `Apply to ${import_picocolors3.default.
|
|
280205
|
+
const ok = await ye({ message: `Apply to ${import_picocolors3.default.bold("sandbox")}?` });
|
|
280130
280206
|
if (pD(ok) || !ok) {
|
|
280131
280207
|
xe("Aborted.");
|
|
280132
280208
|
process.exit(1);
|
|
@@ -280135,11 +280211,11 @@ async function confirmPush(args, env) {
|
|
|
280135
280211
|
}
|
|
280136
280212
|
function printPushTarget(opts) {
|
|
280137
280213
|
const env = modeFromKey(opts.apiKey);
|
|
280138
|
-
const envLabel = env === "production" ? import_picocolors3.default.
|
|
280214
|
+
const envLabel = env === "production" ? import_picocolors3.default.bold("production") : env === "sandbox" ? import_picocolors3.default.bold("sandbox") : import_picocolors3.default.yellow("unknown env");
|
|
280139
280215
|
const project = getActiveProject();
|
|
280140
|
-
const projectLabel = project ? `${import_picocolors3.default.bold(project.slug)} ${import_picocolors3.default.dim(`(${project.id})`)}` : `${import_picocolors3.default.bold("default")} ${import_picocolors3.default.dim("(org-default
|
|
280216
|
+
const projectLabel = project ? `${import_picocolors3.default.bold(project.slug)} ${import_picocolors3.default.dim(`(${project.id})`)}` : `${import_picocolors3.default.bold("default")} ${import_picocolors3.default.dim("(org-default)")}`;
|
|
280141
280217
|
const cliMode = getMode();
|
|
280142
|
-
const modeNote = env && env !== cliMode ? ` ${import_picocolors3.default.yellow(`(
|
|
280218
|
+
const modeNote = env && env !== cliMode ? ` ${import_picocolors3.default.yellow(`(cli mode: ${cliMode})`)}` : "";
|
|
280143
280219
|
console.log(`
|
|
280144
280220
|
${brand("ablo")} ${import_picocolors3.default.dim("push")} ${import_picocolors3.default.dim("\u2192")} ${envLabel}${modeNote}`);
|
|
280145
280221
|
console.log(` ${import_picocolors3.default.dim("project")} ${projectLabel}`);
|
|
@@ -280148,20 +280224,20 @@ function printPushTarget(opts) {
|
|
|
280148
280224
|
` ${import_picocolors3.default.dim("key")} ${maskKey(opts.apiKey)} ${import_picocolors3.default.dim(`(${describeKeySource(opts.keySource)})`)}`
|
|
280149
280225
|
);
|
|
280150
280226
|
console.log(
|
|
280151
|
-
` ${import_picocolors3.default.dim("schema")} ${import_picocolors3.default.bold(opts.schemaPath)} ${import_picocolors3.default.dim(
|
|
280227
|
+
` ${import_picocolors3.default.dim("schema")} ${import_picocolors3.default.bold(opts.schemaPath)} ${import_picocolors3.default.dim(`${opts.modelCount} models, hash ${opts.hash}`)}
|
|
280152
280228
|
`
|
|
280153
280229
|
);
|
|
280154
280230
|
}
|
|
280155
280231
|
function describeKeySource(source) {
|
|
280156
280232
|
switch (source) {
|
|
280157
280233
|
case "env":
|
|
280158
|
-
return "ABLO_API_KEY
|
|
280234
|
+
return "ABLO_API_KEY";
|
|
280159
280235
|
case ".env.local":
|
|
280160
280236
|
return ".env.local";
|
|
280161
280237
|
case ".env":
|
|
280162
280238
|
return ".env";
|
|
280163
|
-
case "
|
|
280164
|
-
return "
|
|
280239
|
+
case "stored":
|
|
280240
|
+
return "ablo login";
|
|
280165
280241
|
}
|
|
280166
280242
|
}
|
|
280167
280243
|
async function push(argv) {
|
|
@@ -280174,14 +280250,9 @@ async function push(argv) {
|
|
|
280174
280250
|
}
|
|
280175
280251
|
let keySource = "env";
|
|
280176
280252
|
if (!args.apiKey) {
|
|
280177
|
-
const
|
|
280178
|
-
|
|
280179
|
-
|
|
280180
|
-
keySource = fromProject.source;
|
|
280181
|
-
} else {
|
|
280182
|
-
args.apiKey = resolveApiKey();
|
|
280183
|
-
keySource = "login";
|
|
280184
|
-
}
|
|
280253
|
+
const resolved = resolveEffectiveApiKey();
|
|
280254
|
+
args.apiKey = resolved.key;
|
|
280255
|
+
keySource = resolved.source ?? "stored";
|
|
280185
280256
|
}
|
|
280186
280257
|
if (!args.apiKey) {
|
|
280187
280258
|
console.error(
|
|
@@ -280278,6 +280349,12 @@ async function push(argv) {
|
|
|
280278
280349
|
` This is a ${import_picocolors3.default.bold("database privilege")} error (Postgres 42501 / row-level security), not a key scope \u2014 a different API key won't help. The role behind this org's database can't write the target. Provision a writable, RLS-scoped role with ${import_picocolors3.default.bold("npx ablo migrate")}, or check the org's database registration. See docs/plans/read-path-logical-replication-vs-hosting.md.`
|
|
280279
280350
|
)
|
|
280280
280351
|
);
|
|
280352
|
+
} else if (code === "schema_provisioning_forbidden") {
|
|
280353
|
+
console.error(
|
|
280354
|
+
import_picocolors3.default.dim(
|
|
280355
|
+
` This is not a key problem \u2014 the push was authorized, but the target database refused to let the engine create tables (Postgres 42501). On the replication read path Ablo never runs DDL: register your database as a data source with ${import_picocolors3.default.bold("npx ablo connect --register")}, and pushes to that environment record the schema as metadata only \u2014 no tables are created anywhere.`
|
|
280356
|
+
)
|
|
280357
|
+
);
|
|
280281
280358
|
} else if (args.apiKey != null && classifyCredentialKind(args.apiKey) === "restricted") {
|
|
280282
280359
|
console.error(
|
|
280283
280360
|
import_picocolors3.default.dim(
|
|
@@ -280287,7 +280364,7 @@ async function push(argv) {
|
|
|
280287
280364
|
} else {
|
|
280288
280365
|
console.error(
|
|
280289
280366
|
import_picocolors3.default.dim(
|
|
280290
|
-
` This key isn't authorized to push schema (needs ${import_picocolors3.default.bold("schema:push")}). ` + (keySource === "
|
|
280367
|
+
` This key isn't authorized to push schema (needs ${import_picocolors3.default.bold("schema:push")}). ` + (keySource === "stored" ? `It's your stored ${import_picocolors3.default.bold("ablo login")} sandbox key \u2014 a key in ${import_picocolors3.default.bold(".env.local")} or ${import_picocolors3.default.bold("ABLO_API_KEY")} takes precedence, so put a schema:push key there (sandbox ${import_picocolors3.default.bold("sk_test_")} or production ${import_picocolors3.default.bold("sk_live_")}) and re-push. ` : `Use a schema:push key \u2014 a sandbox ${import_picocolors3.default.bold("sk_test_")} or production ${import_picocolors3.default.bold("sk_live_")}. `) + `Manage keys at https://abloatai.com`
|
|
280291
280368
|
)
|
|
280292
280369
|
);
|
|
280293
280370
|
}
|
|
@@ -280351,32 +280428,36 @@ function planFor(schema, targetSchema = "public") {
|
|
|
280351
280428
|
return { statements: [...plan.statements, ...adapterTables], concurrent: plan.concurrent ?? [] };
|
|
280352
280429
|
}
|
|
280353
280430
|
var log = {
|
|
280354
|
-
info: (msg, fields) =>
|
|
280355
|
-
|
|
280356
|
-
|
|
280431
|
+
info: (msg, fields) => {
|
|
280432
|
+
console.log(`[migrate] ${msg}`, fields);
|
|
280433
|
+
},
|
|
280434
|
+
warn: (msg, fields) => {
|
|
280435
|
+
console.warn(import_picocolors4.default.yellow(`[migrate] ${msg}`), fields);
|
|
280436
|
+
},
|
|
280437
|
+
error: (msg, fields) => {
|
|
280438
|
+
console.error(import_picocolors4.default.red(`[migrate] ${msg}`), fields);
|
|
280439
|
+
}
|
|
280357
280440
|
};
|
|
280358
|
-
var PG_LOCK_NOT_AVAILABLE = "55P03";
|
|
280359
|
-
var LOCK_TIMEOUT = process.env.ABLO_SCHEMA_LOCK_TIMEOUT ?? process.env.ABLO_DDL_LOCK_TIMEOUT ?? "5s";
|
|
280360
|
-
var MAX_LOCK_ATTEMPTS = 5;
|
|
280361
280441
|
async function applyStatements(dbUrl, targetSchema, statements, concurrent = []) {
|
|
280362
280442
|
const sql = src_default(dbUrl, { max: 1, prepare: false, onnotice: () => {
|
|
280363
280443
|
} });
|
|
280364
280444
|
const total = statements.length;
|
|
280365
280445
|
const startedAt = Date.now();
|
|
280446
|
+
const lockTimeout = (0, import_schema3.resolveDdlLockTimeout)();
|
|
280447
|
+
const maxLockAttempts = (0, import_schema3.resolveDdlMaxLockAttempts)();
|
|
280366
280448
|
log.info("applying migration plan", { targetSchema, statements: total });
|
|
280367
280449
|
try {
|
|
280368
280450
|
for (let attempt = 1; ; attempt++) {
|
|
280369
280451
|
try {
|
|
280370
280452
|
await sql.begin(async (tx) => {
|
|
280371
|
-
await tx.unsafe(`SET LOCAL lock_timeout = '${
|
|
280453
|
+
await tx.unsafe(`SET LOCAL lock_timeout = '${lockTimeout}'`);
|
|
280372
280454
|
await tx`SELECT pg_advisory_xact_lock(hashtext(${`provision:${targetSchema}`}))`;
|
|
280373
|
-
for (
|
|
280374
|
-
const statement = statements[index];
|
|
280455
|
+
for (const [index, statement] of statements.entries()) {
|
|
280375
280456
|
try {
|
|
280376
280457
|
await tx.unsafe(statement);
|
|
280377
280458
|
} catch (err) {
|
|
280378
280459
|
const pg = err ?? {};
|
|
280379
|
-
if (pg.code === PG_LOCK_NOT_AVAILABLE) throw err;
|
|
280460
|
+
if (pg.code === import_schema3.PG_LOCK_NOT_AVAILABLE) throw err;
|
|
280380
280461
|
log.error("migration plan failed", {
|
|
280381
280462
|
code: "migration_failed",
|
|
280382
280463
|
durationMs: Date.now() - startedAt,
|
|
@@ -280394,8 +280475,8 @@ async function applyStatements(dbUrl, targetSchema, statements, concurrent = [])
|
|
|
280394
280475
|
break;
|
|
280395
280476
|
} catch (err) {
|
|
280396
280477
|
const pg = err ?? {};
|
|
280397
|
-
if (pg.code === PG_LOCK_NOT_AVAILABLE && attempt <
|
|
280398
|
-
const backoffMs =
|
|
280478
|
+
if (pg.code === import_schema3.PG_LOCK_NOT_AVAILABLE && attempt < maxLockAttempts) {
|
|
280479
|
+
const backoffMs = (0, import_schema3.ddlLockRetryBackoffMs)(attempt);
|
|
280399
280480
|
log.warn("schema change blocked by a lock; backing off and retrying", { targetSchema, attempt, backoffMs });
|
|
280400
280481
|
await new Promise((resolve6) => setTimeout(resolve6, backoffMs));
|
|
280401
280482
|
continue;
|
|
@@ -280615,10 +280696,11 @@ On Neon enable Logical Replication in the project (Console \u2192 Settings \u219
|
|
|
280615
280696
|
`SELECT puballtables FROM pg_publication WHERE pubname = $1`,
|
|
280616
280697
|
[publication]
|
|
280617
280698
|
);
|
|
280699
|
+
const pubRow = pubRows[0];
|
|
280618
280700
|
items.push(
|
|
280619
|
-
|
|
280701
|
+
pubRow ? {
|
|
280620
280702
|
ok: true,
|
|
280621
|
-
label: `publication ${import_picocolors5.default.bold(publication)} exists ${import_picocolors5.default.dim(
|
|
280703
|
+
label: `publication ${import_picocolors5.default.bold(publication)} exists ${import_picocolors5.default.dim(pubRow.puballtables ? "(all tables)" : "(table subset)")}`
|
|
280622
280704
|
} : {
|
|
280623
280705
|
ok: false,
|
|
280624
280706
|
label: `publication ${import_picocolors5.default.bold(publication)} not found`,
|
|
@@ -280731,6 +280813,9 @@ async function runCheck() {
|
|
|
280731
280813
|
);
|
|
280732
280814
|
process.exit(1);
|
|
280733
280815
|
}
|
|
280816
|
+
function registerEndpoint(baseUrl2) {
|
|
280817
|
+
return `${baseUrl2.replace(/\/+$/, "")}/api/v1/datasources`;
|
|
280818
|
+
}
|
|
280734
280819
|
async function runRegister() {
|
|
280735
280820
|
const dbUrl = requireDatabaseUrl("--register");
|
|
280736
280821
|
const apiKey = resolveApiKey();
|
|
@@ -280755,7 +280840,7 @@ async function runRegister() {
|
|
|
280755
280840
|
const apiUrl2 = (process.env.ABLO_API_URL ?? DEFAULT_URL).replace(/\/+$/, "");
|
|
280756
280841
|
let res;
|
|
280757
280842
|
try {
|
|
280758
|
-
res = await fetch(
|
|
280843
|
+
res = await fetch(registerEndpoint(apiUrl2), {
|
|
280759
280844
|
method: "POST",
|
|
280760
280845
|
headers: { "content-type": "application/json", authorization: `Bearer ${apiKey}` },
|
|
280761
280846
|
body: JSON.stringify({ connectionString: dbUrl })
|
|
@@ -280776,22 +280861,32 @@ async function runRegister() {
|
|
|
280776
280861
|
process.exit(0);
|
|
280777
280862
|
}
|
|
280778
280863
|
const body = await res.json().catch(() => ({}));
|
|
280779
|
-
const code = body.error?.code;
|
|
280780
|
-
const message = body.error?.message ?? `HTTP ${res.status}`;
|
|
280864
|
+
const code = body.code ?? body.error?.code;
|
|
280865
|
+
const message = body.message ?? body.error?.message ?? `HTTP ${res.status}`;
|
|
280781
280866
|
console.error(import_picocolors5.default.red(`
|
|
280782
280867
|
Registration failed: ${message}`));
|
|
280783
280868
|
if (code === "forbidden") {
|
|
280784
280869
|
console.error(import_picocolors5.default.dim(` Registering a database needs a ${import_picocolors5.default.bold("secret")} key (sk_\u2026). Run ${import_picocolors5.default.bold("ablo login")} for one.`));
|
|
280785
|
-
} else if (code === "datasource_direct_deprecated") {
|
|
280786
|
-
console.error(
|
|
280787
|
-
import_picocolors5.default.dim(
|
|
280788
|
-
` This deployment doesn\u2019t accept new connection-string registrations yet. The operator must enable it (${import_picocolors5.default.bold("ABLO_ALLOW_DIRECT_DATASOURCE=true")}) \u2014 see ${import_picocolors5.default.bold("docs/runbooks/connect-customer-database-byo-replication.md")}.`
|
|
280789
|
-
)
|
|
280790
|
-
);
|
|
280791
280870
|
} else if (code === "datasource_connection_unsupported") {
|
|
280792
280871
|
console.error(
|
|
280793
280872
|
import_picocolors5.default.dim(` This deployment can\u2019t accept connection strings \u2014 use a self-hosted/hosted engine, or the signed endpoint fallback.`)
|
|
280794
280873
|
);
|
|
280874
|
+
} else if (code === "database_not_replication_ready") {
|
|
280875
|
+
for (const f of body.details?.failures ?? []) {
|
|
280876
|
+
console.error(` ${import_picocolors5.default.red("\u2717")} ${import_picocolors5.default.bold(f.item ?? "item")}${f.actual ? import_picocolors5.default.dim(` (${f.actual})`) : ""}`);
|
|
280877
|
+
if (f.fix) for (const line of f.fix.split("\n")) console.error(` ${import_picocolors5.default.red("\u2022")} ${line}`);
|
|
280878
|
+
}
|
|
280879
|
+
console.error(import_picocolors5.default.dim(`
|
|
280880
|
+
Apply the fixes, verify with ${import_picocolors5.default.bold("ablo connect --check")}, then re-run.`));
|
|
280881
|
+
} else if (code === "database_unreachable") {
|
|
280882
|
+
if (body.details?.reason) console.error(import_picocolors5.default.dim(` ${body.details.reason}`));
|
|
280883
|
+
console.error(
|
|
280884
|
+
import_picocolors5.default.dim(
|
|
280885
|
+
` Ablo's servers must be able to reach this database \u2014 a localhost or private-network
|
|
280886
|
+
Postgres can't be replicated by the hosted service. Use a reachable host (or a tunnel),
|
|
280887
|
+
or the signed ${import_picocolors5.default.bold("dataSource()")} endpoint fallback.`
|
|
280888
|
+
)
|
|
280889
|
+
);
|
|
280795
280890
|
}
|
|
280796
280891
|
console.error();
|
|
280797
280892
|
process.exit(1);
|
|
@@ -280989,16 +281084,17 @@ function wireEnvLocal(apiKey, cwd = process.cwd()) {
|
|
|
280989
281084
|
action = `Created ${import_picocolors7.default.bold(".env.local")} with ${import_picocolors7.default.bold("ABLO_API_KEY")}`;
|
|
280990
281085
|
} else {
|
|
280991
281086
|
const content = (0, import_fs7.readFileSync)(envPath, "utf8");
|
|
280992
|
-
const match =
|
|
281087
|
+
const match = /^ABLO_API_KEY=(.*)$/m.exec(content);
|
|
281088
|
+
const existing = match?.[1] ?? "";
|
|
280993
281089
|
if (!match) {
|
|
280994
281090
|
(0, import_fs7.appendFileSync)(envPath, `${content.endsWith("\n") || content.length === 0 ? "" : "\n"}${line}
|
|
280995
281091
|
`);
|
|
280996
281092
|
action = `Added ${import_picocolors7.default.bold("ABLO_API_KEY")} to ${import_picocolors7.default.bold(".env.local")}`;
|
|
280997
|
-
} else if (
|
|
281093
|
+
} else if (existing === apiKey) {
|
|
280998
281094
|
action = `${import_picocolors7.default.bold(".env.local")} already has this key`;
|
|
280999
281095
|
} else {
|
|
281000
281096
|
(0, import_fs7.writeFileSync)(envPath, content.replace(/^ABLO_API_KEY=.*$/m, line));
|
|
281001
|
-
action = `Updated ${import_picocolors7.default.bold("ABLO_API_KEY")} in ${import_picocolors7.default.bold(".env.local")} ${import_picocolors7.default.dim(`(was ${
|
|
281097
|
+
action = `Updated ${import_picocolors7.default.bold("ABLO_API_KEY")} in ${import_picocolors7.default.bold(".env.local")} ${import_picocolors7.default.dim(`(was ${existing.slice(0, 12)}\u2026)`)}`;
|
|
281002
281098
|
}
|
|
281003
281099
|
}
|
|
281004
281100
|
const gitignorePath = (0, import_path5.resolve)(cwd, ".gitignore");
|
|
@@ -281076,7 +281172,7 @@ async function dev(argv) {
|
|
|
281076
281172
|
console.error(import_picocolors7.default.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
281077
281173
|
process.exit(1);
|
|
281078
281174
|
}
|
|
281079
|
-
if (!args.apiKey) args.apiKey =
|
|
281175
|
+
if (!args.apiKey) args.apiKey = resolveEffectiveApiKey("sandbox").key;
|
|
281080
281176
|
const key = classifyKey(args.apiKey, getMode());
|
|
281081
281177
|
if (!key.ok) {
|
|
281082
281178
|
console.error(import_picocolors7.default.red(` ${key.reason}`));
|
|
@@ -281200,7 +281296,7 @@ async function deviceLogin(argv, deps = {}) {
|
|
|
281200
281296
|
headers: { "content-type": "application/json" },
|
|
281201
281297
|
body: JSON.stringify({ client_id: CLIENT_ID, scope: "openid profile email" })
|
|
281202
281298
|
}).catch(() => null);
|
|
281203
|
-
if (!codeRes
|
|
281299
|
+
if (!codeRes?.ok) {
|
|
281204
281300
|
M2.error(`Couldn't start login against ${AUTH_URL}. Is the dashboard reachable?`);
|
|
281205
281301
|
process.exit(1);
|
|
281206
281302
|
}
|
|
@@ -281270,7 +281366,7 @@ ${import_picocolors8.default.dim(url)}`, "Approve in your browser");
|
|
|
281270
281366
|
...targetProject ? { project_slug: targetProject } : {}
|
|
281271
281367
|
})
|
|
281272
281368
|
}).catch(() => null);
|
|
281273
|
-
if (!provRes
|
|
281369
|
+
if (!provRes?.ok) {
|
|
281274
281370
|
s.stop("Could not provision a key.");
|
|
281275
281371
|
const reason = provRes ? (await provRes.json().catch(() => ({}))).error : void 0;
|
|
281276
281372
|
if (reason) M2.error(reason);
|
|
@@ -281584,7 +281680,9 @@ function expiryLabel(iso) {
|
|
|
281584
281680
|
}
|
|
281585
281681
|
async function ping(apiUrl2) {
|
|
281586
281682
|
const ctrl = new AbortController();
|
|
281587
|
-
const t = setTimeout(() =>
|
|
281683
|
+
const t = setTimeout(() => {
|
|
281684
|
+
ctrl.abort();
|
|
281685
|
+
}, 3e3);
|
|
281588
281686
|
try {
|
|
281589
281687
|
const res = await fetch(`${apiUrl2}/api/health`, { signal: ctrl.signal });
|
|
281590
281688
|
return res.ok;
|
|
@@ -281597,7 +281695,9 @@ async function ping(apiUrl2) {
|
|
|
281597
281695
|
async function fetchPushedSchema(apiUrl2, apiKey) {
|
|
281598
281696
|
if (!apiKey) return null;
|
|
281599
281697
|
const ctrl = new AbortController();
|
|
281600
|
-
const t = setTimeout(() =>
|
|
281698
|
+
const t = setTimeout(() => {
|
|
281699
|
+
ctrl.abort();
|
|
281700
|
+
}, 3e3);
|
|
281601
281701
|
try {
|
|
281602
281702
|
const res = await fetch(`${apiUrl2}/api/schema`, {
|
|
281603
281703
|
headers: { authorization: `Bearer ${apiKey}` },
|
|
@@ -281613,7 +281713,9 @@ async function fetchPushedSchema(apiUrl2, apiKey) {
|
|
|
281613
281713
|
}
|
|
281614
281714
|
async function sampleRead(apiUrl2, apiKey, modelTypename, n) {
|
|
281615
281715
|
const ctrl = new AbortController();
|
|
281616
|
-
const t = setTimeout(() =>
|
|
281716
|
+
const t = setTimeout(() => {
|
|
281717
|
+
ctrl.abort();
|
|
281718
|
+
}, 4e3);
|
|
281617
281719
|
try {
|
|
281618
281720
|
const res = await fetch(
|
|
281619
281721
|
`${apiUrl2}/v1/models/${encodeURIComponent(modelTypename)}/__ablo_health_probe_${n}__`,
|
|
@@ -281664,12 +281766,19 @@ async function status(args = []) {
|
|
|
281664
281766
|
const key2 = describeEffectiveKey(mode2, process.env.ABLO_API_KEY, entry);
|
|
281665
281767
|
const plan2 = resolvePushPlan();
|
|
281666
281768
|
const activeProject2 = getActiveProject();
|
|
281667
|
-
const
|
|
281668
|
-
const pushed = await fetchPushedSchema(apiUrl2,
|
|
281769
|
+
const effective2 = resolveEffectiveApiKey();
|
|
281770
|
+
const pushed = await fetchPushedSchema(apiUrl2, effective2.key);
|
|
281669
281771
|
const out = {
|
|
281670
281772
|
mode: mode2,
|
|
281671
281773
|
// The locally-active project (`ablo projects use`); null = org-default.
|
|
281672
281774
|
project: activeProject2 ?? null,
|
|
281775
|
+
// The credential the CLI resolves for requests, with its source —
|
|
281776
|
+
// 'env' | '.env.local' | '.env' | 'stored'. Key confusion is a common
|
|
281777
|
+
// source of trouble, and the source is usually the answer.
|
|
281778
|
+
effectiveKey: {
|
|
281779
|
+
prefix: effective2.key ? effective2.key.slice(0, 12) : null,
|
|
281780
|
+
source: effective2.source
|
|
281781
|
+
},
|
|
281673
281782
|
keyPrefix: key2.keyPrefix,
|
|
281674
281783
|
keySource: key2.keySource,
|
|
281675
281784
|
keyMode: key2.keyMode,
|
|
@@ -281678,16 +281787,16 @@ async function status(args = []) {
|
|
|
281678
281787
|
keyMatchesStoredActiveKey: key2.keyMatchesStoredActiveKey,
|
|
281679
281788
|
keyMismatch: key2.keyMismatch,
|
|
281680
281789
|
organizationId: entry?.organizationId ?? null,
|
|
281681
|
-
// What `ablo push` would do right now — the
|
|
281682
|
-
//
|
|
281790
|
+
// What `ablo push` would do right now — the answer to "why did push
|
|
281791
|
+
// demand a different key".
|
|
281683
281792
|
push: {
|
|
281684
281793
|
flow: plan2.flow,
|
|
281685
281794
|
keyPrefix: plan2.apiKey?.slice(0, 12) ?? null,
|
|
281686
281795
|
keySource: plan2.source
|
|
281687
281796
|
},
|
|
281688
|
-
// The schema
|
|
281689
|
-
// engine enforces, which may differ from local `schema.ts`.
|
|
281690
|
-
// server
|
|
281797
|
+
// The schema active for this key's environment — the typename and conflict
|
|
281798
|
+
// rules the engine enforces, which may differ from your local `schema.ts`.
|
|
281799
|
+
// null means the server did not answer (unreachable, too old, or no key).
|
|
281691
281800
|
schema: pushed ? {
|
|
281692
281801
|
active: pushed.active,
|
|
281693
281802
|
version: pushed.version ?? null,
|
|
@@ -281703,9 +281812,11 @@ async function status(args = []) {
|
|
|
281703
281812
|
console.log(`
|
|
281704
281813
|
${brand("ablo")} ${import_picocolors11.default.dim("status")}
|
|
281705
281814
|
`);
|
|
281706
|
-
|
|
281815
|
+
const effective = resolveEffectiveApiKey();
|
|
281816
|
+
if (effective.key && effective.source && effective.source !== "stored") {
|
|
281817
|
+
const label = effective.source === "env" ? "ABLO_API_KEY env" : effective.source;
|
|
281707
281818
|
console.log(
|
|
281708
|
-
` ${import_picocolors11.default.dim("key")} ${
|
|
281819
|
+
` ${import_picocolors11.default.dim("key")} ${effective.key.slice(0, 12)}\u2026 ${import_picocolors11.default.dim(`(${label} \u2014 overrides stored)`)}`
|
|
281709
281820
|
);
|
|
281710
281821
|
} else if (!cfg) {
|
|
281711
281822
|
console.log(` ${import_picocolors11.default.yellow("!")} Not logged in \u2014 run ${import_picocolors11.default.bold("ablo login")}.`);
|
|
@@ -281740,9 +281851,9 @@ async function status(args = []) {
|
|
|
281740
281851
|
const reachable = await ping(apiUrl2);
|
|
281741
281852
|
console.log(reachable ? import_picocolors11.default.green("reachable") : import_picocolors11.default.red("unreachable"));
|
|
281742
281853
|
if (reachable) {
|
|
281743
|
-
const introspectKey =
|
|
281854
|
+
const introspectKey = effective.key;
|
|
281744
281855
|
const pushed = await fetchPushedSchema(apiUrl2, introspectKey);
|
|
281745
|
-
if (pushed
|
|
281856
|
+
if (pushed?.active) {
|
|
281746
281857
|
const when = pushed.pushedAt ? ` ${import_picocolors11.default.dim(`@ ${pushed.pushedAt.slice(0, 10)}`)}` : "";
|
|
281747
281858
|
const ver = pushed.version != null ? ` ${import_picocolors11.default.dim(`(rev ${pushed.version})`)}` : "";
|
|
281748
281859
|
console.log(` ${import_picocolors11.default.dim("schema")} ${import_picocolors11.default.bold(`${pushed.models.length} models pushed`)}${ver}${when}`);
|
|
@@ -281755,8 +281866,9 @@ async function status(args = []) {
|
|
|
281755
281866
|
} else if (pushed && !pushed.active) {
|
|
281756
281867
|
console.log(` ${import_picocolors11.default.dim("schema")} ${import_picocolors11.default.yellow("none pushed")} ${import_picocolors11.default.dim(`(run ${import_picocolors11.default.bold("ablo push")} or ${import_picocolors11.default.bold("ablo dev")})`)}`);
|
|
281757
281868
|
}
|
|
281758
|
-
|
|
281759
|
-
|
|
281869
|
+
const firstPushedModel = pushed?.active ? pushed.models[0] : void 0;
|
|
281870
|
+
if (firstPushedModel !== void 0) {
|
|
281871
|
+
const probe = await probeDataPlane(apiUrl2, introspectKey, firstPushedModel.typename);
|
|
281760
281872
|
if (probe.status === "no_database") {
|
|
281761
281873
|
console.log(` ${import_picocolors11.default.dim("data")} ${import_picocolors11.default.red("\u2717 no database registered")}${org ? import_picocolors11.default.dim(` for org ${org}`) : ""}`);
|
|
281762
281874
|
console.log(
|
|
@@ -281947,8 +282059,10 @@ function parseMode(args) {
|
|
|
281947
282059
|
function positional(args) {
|
|
281948
282060
|
for (let i = 0; i < args.length; i++) {
|
|
281949
282061
|
const a = args[i];
|
|
282062
|
+
if (a === void 0) continue;
|
|
281950
282063
|
if (a.startsWith("-")) {
|
|
281951
|
-
|
|
282064
|
+
const next = args[i + 1];
|
|
282065
|
+
if (!a.includes("=") && next && !next.startsWith("-")) i++;
|
|
281952
282066
|
continue;
|
|
281953
282067
|
}
|
|
281954
282068
|
return a;
|
|
@@ -282269,8 +282383,8 @@ function verbRewrite(call, verb) {
|
|
|
282269
282383
|
const params = VERB_ARGS[verb];
|
|
282270
282384
|
if (!params) return null;
|
|
282271
282385
|
const args = call.getArguments();
|
|
282272
|
-
if (args.length === 0) return null;
|
|
282273
282386
|
const first = args[0];
|
|
282387
|
+
if (first === void 0) return null;
|
|
282274
282388
|
const calleeText = call.getExpression().getText();
|
|
282275
282389
|
if (verb === "create") {
|
|
282276
282390
|
if (import_ts_morph.Node.isObjectLiteralExpression(first) && hasKey2(first, "data")) return null;
|
|
@@ -282319,7 +282433,7 @@ async function upgrade(argv) {
|
|
|
282319
282433
|
edits.push({ file, line: node.getStartLineNumber(), rule, before, after });
|
|
282320
282434
|
};
|
|
282321
282435
|
const flag2 = (node, rule, hint) => {
|
|
282322
|
-
manual.push({ file, line: node.getStartLineNumber(), rule, snippet: node.getText().split("\n")[0].slice(0, 120), hint });
|
|
282436
|
+
manual.push({ file, line: node.getStartLineNumber(), rule, snippet: (node.getText().split("\n")[0] ?? "").slice(0, 120), hint });
|
|
282323
282437
|
};
|
|
282324
282438
|
for (const imp of sf.getImportDeclarations()) {
|
|
282325
282439
|
if (!ABLO_REACT.has(imp.getModuleSpecifierValue())) continue;
|
|
@@ -282349,13 +282463,13 @@ async function upgrade(argv) {
|
|
|
282349
282463
|
if (method in VERB_ARGS) {
|
|
282350
282464
|
const next = verbRewrite(call, method);
|
|
282351
282465
|
if (next) {
|
|
282352
|
-
record(call, `${method}\u2192object-param`, call.getText().split("\n")[0].slice(0, 80), next.slice(0, 80));
|
|
282466
|
+
record(call, `${method}\u2192object-param`, (call.getText().split("\n")[0] ?? "").slice(0, 80), next.slice(0, 80));
|
|
282353
282467
|
call.replaceWithText(next);
|
|
282354
282468
|
}
|
|
282355
282469
|
} else if (method === "load") {
|
|
282356
282470
|
const next = loadRewrite(call);
|
|
282357
282471
|
if (next) {
|
|
282358
|
-
record(call, "load\u2192retrieve/list", call.getText().split("\n")[0].slice(0, 80), next.slice(0, 80));
|
|
282472
|
+
record(call, "load\u2192retrieve/list", (call.getText().split("\n")[0] ?? "").slice(0, 80), next.slice(0, 80));
|
|
282359
282473
|
call.replaceWithText(next);
|
|
282360
282474
|
}
|
|
282361
282475
|
}
|
|
@@ -282567,12 +282681,12 @@ async function pull(argv) {
|
|
|
282567
282681
|
);
|
|
282568
282682
|
}
|
|
282569
282683
|
|
|
282570
|
-
// src/cli/
|
|
282684
|
+
// src/cli/prismaPull.ts
|
|
282571
282685
|
init_cjs_shims();
|
|
282572
282686
|
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
282573
282687
|
var import_fs10 = require("fs");
|
|
282574
282688
|
|
|
282575
|
-
// src/cli/
|
|
282689
|
+
// src/cli/schemaIr.ts
|
|
282576
282690
|
init_cjs_shims();
|
|
282577
282691
|
function camelToSnake3(s) {
|
|
282578
282692
|
return s.replace(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
@@ -282642,7 +282756,7 @@ function emitSchemaSource(schema, importPath) {
|
|
|
282642
282756
|
return lines.join("\n");
|
|
282643
282757
|
}
|
|
282644
282758
|
|
|
282645
|
-
// src/cli/
|
|
282759
|
+
// src/cli/prismaPull.ts
|
|
282646
282760
|
var DEFAULT_SCHEMA = "prisma/schema.prisma";
|
|
282647
282761
|
var DEFAULT_OUT3 = "ablo/schema.ts";
|
|
282648
282762
|
var DEFAULT_IMPORT2 = "@abloatai/ablo/schema";
|
|
@@ -282665,7 +282779,7 @@ function stripComments(src) {
|
|
|
282665
282779
|
let inStr = false;
|
|
282666
282780
|
let res = "";
|
|
282667
282781
|
for (let i = 0; i < line.length; i++) {
|
|
282668
|
-
const c = line
|
|
282782
|
+
const c = line.charAt(i);
|
|
282669
282783
|
if (c === '"') {
|
|
282670
282784
|
inStr = !inStr;
|
|
282671
282785
|
res += c;
|
|
@@ -282693,8 +282807,10 @@ function parseBlocks(srcRaw) {
|
|
|
282693
282807
|
}
|
|
282694
282808
|
const body = src.slice(openIdx + 1, j2 - 1);
|
|
282695
282809
|
const kw = m2[1];
|
|
282810
|
+
const name = m2[2];
|
|
282811
|
+
if (name === void 0) throw new Error("unparseable block header in the Prisma schema");
|
|
282696
282812
|
const type = kw === "model" ? "model" : kw === "enum" ? "enum" : "other";
|
|
282697
|
-
blocks.push({ type, name
|
|
282813
|
+
blocks.push({ type, name, body });
|
|
282698
282814
|
headerRe.lastIndex = j2;
|
|
282699
282815
|
}
|
|
282700
282816
|
return blocks;
|
|
@@ -282705,7 +282821,7 @@ function parseEnumMembers(body) {
|
|
|
282705
282821
|
const t = line.trim();
|
|
282706
282822
|
if (!t || t.startsWith("@") || t.startsWith("@@")) continue;
|
|
282707
282823
|
const first = t.split(/\s+/)[0];
|
|
282708
|
-
if (/^\w+$/.test(first)) members.push(first);
|
|
282824
|
+
if (first !== void 0 && /^\w+$/.test(first)) members.push(first);
|
|
282709
282825
|
}
|
|
282710
282826
|
return members;
|
|
282711
282827
|
}
|
|
@@ -282714,9 +282830,11 @@ function parseFieldLine(line) {
|
|
|
282714
282830
|
if (!t || t.startsWith("@@") || t.startsWith("//")) return null;
|
|
282715
282831
|
const m2 = /^(\w+)\s+([A-Za-z_]\w*)(\[\])?(\?)?\s*(.*)$/.exec(t);
|
|
282716
282832
|
if (!m2) return null;
|
|
282833
|
+
const [, name, type] = m2;
|
|
282834
|
+
if (name === void 0 || type === void 0) return null;
|
|
282717
282835
|
return {
|
|
282718
|
-
name
|
|
282719
|
-
type
|
|
282836
|
+
name,
|
|
282837
|
+
type,
|
|
282720
282838
|
list: Boolean(m2[3]),
|
|
282721
282839
|
optional: Boolean(m2[4]),
|
|
282722
282840
|
attrs: m2[5] ?? ""
|
|
@@ -282729,11 +282847,11 @@ function blockMap(body) {
|
|
|
282729
282847
|
return /@@map\("([^"]+)"\)/.exec(body)?.[1];
|
|
282730
282848
|
}
|
|
282731
282849
|
function relationFkFields(attrs) {
|
|
282732
|
-
const rel = /@relation\(([^)]*)\)/.exec(attrs);
|
|
282733
|
-
if (
|
|
282734
|
-
const fields = /fields:\s*\[([^\]]*)\]/.exec(rel[1]
|
|
282735
|
-
if (
|
|
282736
|
-
return fields
|
|
282850
|
+
const rel = /@relation\(([^)]*)\)/.exec(attrs)?.[1];
|
|
282851
|
+
if (rel === void 0) return null;
|
|
282852
|
+
const fields = /fields:\s*\[([^\]]*)\]/.exec(rel)?.[1];
|
|
282853
|
+
if (fields === void 0) return null;
|
|
282854
|
+
return fields.split(",").map((s) => s.trim()).filter(Boolean);
|
|
282737
282855
|
}
|
|
282738
282856
|
function parsePrismaSchema(src) {
|
|
282739
282857
|
const blocks = parseBlocks(src);
|
|
@@ -282758,8 +282876,9 @@ function parsePrismaSchema(src) {
|
|
|
282758
282876
|
const column = mapAttr(raw.attrs);
|
|
282759
282877
|
if (modelNames.has(raw.type)) {
|
|
282760
282878
|
const fks = relationFkFields(raw.attrs);
|
|
282761
|
-
|
|
282762
|
-
|
|
282879
|
+
const fkField = fks && fks.length === 1 ? fks[0] : void 0;
|
|
282880
|
+
if (fkField !== void 0) {
|
|
282881
|
+
relations.push({ name: raw.name, target: tableOf.get(raw.type) ?? raw.type, fkField });
|
|
282763
282882
|
}
|
|
282764
282883
|
continue;
|
|
282765
282884
|
}
|
|
@@ -282822,6 +282941,7 @@ function parsePrismaPullArgs(argv) {
|
|
|
282822
282941
|
let force = false;
|
|
282823
282942
|
for (let i = 0; i < argv.length; i++) {
|
|
282824
282943
|
const arg = argv[i];
|
|
282944
|
+
if (arg === void 0) continue;
|
|
282825
282945
|
switch (arg) {
|
|
282826
282946
|
case "--schema":
|
|
282827
282947
|
schema = argv[++i] ?? schema;
|
|
@@ -282893,7 +283013,7 @@ async function prismaPull(argv) {
|
|
|
282893
283013
|
);
|
|
282894
283014
|
}
|
|
282895
283015
|
|
|
282896
|
-
// src/cli/
|
|
283016
|
+
// src/cli/drizzlePull.ts
|
|
282897
283017
|
init_cjs_shims();
|
|
282898
283018
|
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
282899
283019
|
var import_fs11 = require("fs");
|
|
@@ -282971,8 +283091,8 @@ async function lowerDrizzleModule(mod) {
|
|
|
282971
283091
|
const { foreignKeys } = getTableConfig(table);
|
|
282972
283092
|
for (const fk of foreignKeys) {
|
|
282973
283093
|
const ref = fk.reference();
|
|
282974
|
-
|
|
282975
|
-
|
|
283094
|
+
const [localCol, ...extraCols] = ref.columns;
|
|
283095
|
+
if (localCol === void 0 || extraCols.length > 0) continue;
|
|
282976
283096
|
const fkField = fieldKeyByColumn.get(localCol) ?? fieldKeyByColName.get(localCol.name) ?? localCol.name;
|
|
282977
283097
|
const target = getTableName(ref.foreignTable);
|
|
282978
283098
|
relations.push({ name: stripIdSuffix(fkField), target, fkField });
|
|
@@ -283000,6 +283120,7 @@ function parseDrizzlePullArgs(argv) {
|
|
|
283000
283120
|
let force = false;
|
|
283001
283121
|
for (let i = 0; i < argv.length; i++) {
|
|
283002
283122
|
const arg = argv[i];
|
|
283123
|
+
if (arg === void 0) continue;
|
|
283003
283124
|
switch (arg) {
|
|
283004
283125
|
case "--schema":
|
|
283005
283126
|
schema = argv[++i] ?? schema;
|
|
@@ -283059,7 +283180,7 @@ async function drizzlePull(argv) {
|
|
|
283059
283180
|
result = await buildSchemaSourceFromDrizzle({ mod, importPath: args.importPath });
|
|
283060
283181
|
} catch (err) {
|
|
283061
283182
|
const msg = err instanceof Error ? err.message : String(err);
|
|
283062
|
-
const hint =
|
|
283183
|
+
const hint = msg.includes("Cannot find package 'drizzle-orm'") ? import_picocolors18.default.dim(` (install ${import_picocolors18.default.bold("drizzle-orm")} in this project)`) : "";
|
|
283063
283184
|
console.error(import_picocolors18.default.red(` Couldn't load the schema: ${msg}`) + hint);
|
|
283064
283185
|
process.exit(1);
|
|
283065
283186
|
}
|
|
@@ -283091,7 +283212,7 @@ var RECOVERY_HINT = {
|
|
|
283091
283212
|
permission: "Your key isn't allowed to do this \u2014 check its scopes or role.",
|
|
283092
283213
|
session_expiry: "Your session expired \u2014 sign in again.",
|
|
283093
283214
|
access_credential_expiry: "Your access credential expired \u2014 refresh it and retry.",
|
|
283094
|
-
auth_blocked: "Authentication was blocked."
|
|
283215
|
+
auth_blocked: "Authentication was blocked \u2014 the credential itself was rejected. Check that the key matches this environment."
|
|
283095
283216
|
};
|
|
283096
283217
|
function titleForType(type) {
|
|
283097
283218
|
const core = type.replace(/^Ablo/, "").replace(/Error$/, "");
|
|
@@ -283127,7 +283248,9 @@ function renderKnownDetails(details, line) {
|
|
|
283127
283248
|
}
|
|
283128
283249
|
}
|
|
283129
283250
|
function renderCliError(err, opts = {}) {
|
|
283130
|
-
const line = opts.write ?? ((l2) =>
|
|
283251
|
+
const line = opts.write ?? ((l2) => {
|
|
283252
|
+
console.error(l2);
|
|
283253
|
+
});
|
|
283131
283254
|
const verbose = opts.verbose ?? (process.argv.includes("--verbose") || process.env.ABLO_VERBOSE === "1");
|
|
283132
283255
|
if (err instanceof AbloError) {
|
|
283133
283256
|
const codeTag = err.code ? ` ${import_picocolors19.default.dim(`[${err.code}]`)}` : "";
|
|
@@ -283356,7 +283479,7 @@ function detectOrm(override) {
|
|
|
283356
283479
|
try {
|
|
283357
283480
|
const pkg = JSON.parse((0, import_fs12.readFileSync)("package.json", "utf-8"));
|
|
283358
283481
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
283359
|
-
if (deps["@prisma/client"] || deps
|
|
283482
|
+
if (deps["@prisma/client"] || deps.prisma) return "prisma";
|
|
283360
283483
|
if (deps["drizzle-orm"]) return "drizzle";
|
|
283361
283484
|
} catch {
|
|
283362
283485
|
}
|
|
@@ -283564,7 +283687,9 @@ async function init(args = []) {
|
|
|
283564
283687
|
`Set ${import_picocolors20.default.bold("DATABASE_URL")} in ${import_picocolors20.default.bold(envFile)} \u2014 your Postgres is the system of record; rows live there, never with Ablo`,
|
|
283565
283688
|
`Run ${import_picocolors20.default.bold("npx ablo dev")} \u2014 pushes your schema definition and watches for changes`,
|
|
283566
283689
|
...storage === "replication" ? [
|
|
283567
|
-
`Connect your database
|
|
283690
|
+
`Connect your database \u2014 ${import_picocolors20.default.bold("npx ablo connect")} prints the one-time logical-replication setup SQL to run on your Postgres`,
|
|
283691
|
+
`Verify it \u2014 ${import_picocolors20.default.bold("npx ablo connect --check")} walks wal_level, the publication, the role, and replica identity, with the exact fix for anything missing`,
|
|
283692
|
+
`Register it \u2014 ${import_picocolors20.default.bold("npx ablo connect --register")} tells Ablo to start replicating; your app keeps writing through your own backend while Ablo tails the WAL`
|
|
283568
283693
|
] : storage === "direct" ? [
|
|
283569
283694
|
`Provision your DB: ${import_picocolors20.default.bold("npx ablo migrate")} (creates your synced-model tables with row-level security; keep your own migrations for everything else)`
|
|
283570
283695
|
] : [
|
|
@@ -283937,23 +284062,12 @@ import Ablo from '@abloatai/ablo';
|
|
|
283937
284062
|
import { AbloProvider } from '@abloatai/ablo/react';
|
|
283938
284063
|
import { schema } from '@/ablo/schema';
|
|
283939
284064
|
|
|
283940
|
-
// The browser client holds NO secret. The
|
|
284065
|
+
// The browser client holds NO secret. The endpoint string points at the route
|
|
283941
284066
|
// below, which mints a short-lived session token (already scoped to the org +
|
|
283942
|
-
// user); the
|
|
283943
|
-
//
|
|
283944
|
-
//
|
|
283945
|
-
const ablo = Ablo({
|
|
283946
|
-
schema,
|
|
283947
|
-
apiKey: async () => {
|
|
283948
|
-
const res = await fetch('/api/ablo-session', {
|
|
283949
|
-
method: 'POST',
|
|
283950
|
-
credentials: 'include',
|
|
283951
|
-
});
|
|
283952
|
-
if (!res.ok) return null;
|
|
283953
|
-
const { token } = (await res.json()) as { token: string | null };
|
|
283954
|
-
return token;
|
|
283955
|
-
},
|
|
283956
|
-
});
|
|
284067
|
+
// user); the SDK owns the exchange \u2014 it fetches the route (POST, same-origin
|
|
284068
|
+
// cookies) and keeps the token fresh (refresh timer + wake re-mint). A 401
|
|
284069
|
+
// from the route signs the user out; any other failure is retried.
|
|
284070
|
+
const ablo = Ablo({ schema, authEndpoint: '/api/ablo-session' });
|
|
283957
284071
|
|
|
283958
284072
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
283959
284073
|
return <AbloProvider client={ablo}>{children}</AbloProvider>;
|
|
@@ -283974,8 +284088,8 @@ export async function POST(): Promise<Response> {
|
|
|
283974
284088
|
const user = await getCurrentUser();
|
|
283975
284089
|
if (!user) return new Response('Unauthorized', { status: 401 });
|
|
283976
284090
|
|
|
283977
|
-
const { token } = await sync.sessions.create({ user: { id: user.id } });
|
|
283978
|
-
return Response.json({ token });
|
|
284091
|
+
const { token, expiresAt } = await sync.sessions.create({ user: { id: user.id } });
|
|
284092
|
+
return Response.json({ token, expiresAt });
|
|
283979
284093
|
}
|
|
283980
284094
|
|
|
283981
284095
|
// Validate the signed-in user SERVER-SIDE. This ships wired for Better Auth;
|