@abloatai/ablo 0.36.0 → 0.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +55 -2014
- package/NOTICE +2 -2
- package/README.md +45 -63
- package/assets/banner.png +0 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +2 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +3 -0
- package/dist/client.js.map +1 -0
- package/dist/coordination.d.ts +2 -0
- package/dist/coordination.d.ts.map +1 -0
- package/dist/coordination.js +2 -0
- package/dist/coordination.js.map +1 -0
- package/dist/index.d.ts +3 -114
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -163
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +4 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +3 -0
- package/dist/react.js.map +1 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +2 -0
- package/dist/schema.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/source-conformance.d.ts +2 -0
- package/dist/source-conformance.d.ts.map +1 -0
- package/dist/source-conformance.js +2 -0
- package/dist/source-conformance.js.map +1 -0
- package/dist/source-drizzle.d.ts +2 -0
- package/dist/source-drizzle.d.ts.map +1 -0
- package/dist/source-drizzle.js +2 -0
- package/dist/source-drizzle.js.map +1 -0
- package/dist/source-kysely.d.ts +2 -0
- package/dist/source-kysely.d.ts.map +1 -0
- package/dist/source-kysely.js +2 -0
- package/dist/source-kysely.js.map +1 -0
- package/dist/source-next.d.ts +2 -0
- package/dist/source-next.d.ts.map +1 -0
- package/dist/source-next.js +2 -0
- package/dist/source-next.js.map +1 -0
- package/dist/source.d.ts +2 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +2 -0
- package/dist/source.js.map +1 -0
- package/dist/wire.d.ts +2 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +2 -0
- package/dist/wire.js.map +1 -0
- package/docs/agents.md +1 -1
- package/docs/api-keys.md +7 -6
- package/docs/api.md +10 -10
- package/docs/client-behavior.md +5 -5
- package/docs/coordination.md +52 -62
- package/docs/data-sources.md +1 -1
- package/docs/examples/agent-human.md +4 -4
- package/docs/examples/ai-sdk-tool.md +1 -1
- package/docs/examples/existing-python-backend.md +15 -4
- package/docs/examples/nextjs.md +27 -6
- package/docs/examples/server-agent.md +2 -2
- package/docs/how-it-works.md +4 -4
- package/docs/identity.md +2 -1
- package/docs/integration-guide.md +24 -13
- package/docs/internal/README.md +18 -0
- package/docs/internal/agent-fleet-coordination-design.md +171 -0
- package/docs/internal/agent-orchestration.md +58 -0
- package/docs/internal/commit-identifiers.md +91 -0
- package/docs/internal/concurrency-open-decisions.md +37 -0
- package/docs/internal/data-source-reverse-channel.md +150 -0
- package/docs/internal/per-field-conflict-detection.md +165 -0
- package/docs/internal/postgres-replication.md +64 -0
- package/docs/internal/serializable-schema.md +119 -0
- package/docs/internal/structure.md +32 -0
- package/docs/mcp.md +2 -2
- package/docs/migration.md +3 -3
- package/docs/quickstart.md +2 -2
- package/docs/react.md +5 -5
- package/docs/schema-contract.md +3 -3
- package/docs/sessions.md +91 -37
- package/examples/README.md +2 -2
- package/examples/data-source/README.md +1 -1
- package/examples/data-source/ablo-driver.ts +1 -1
- package/examples/data-source/customer-server.ts +1 -1
- package/examples/data-source/run.ts +1 -1
- package/examples/data-source/schema.ts +1 -1
- package/examples/quickstart.ts +2 -2
- package/llms.txt +8 -8
- package/package.json +63 -166
- package/bin/ablo.cjs +0 -39
- package/dist/BaseSyncedStore.d.ts +0 -843
- package/dist/BaseSyncedStore.js +0 -1971
- package/dist/Database.d.ts +0 -323
- package/dist/Database.js +0 -1502
- package/dist/InstanceCache.d.ts +0 -237
- package/dist/InstanceCache.js +0 -1166
- package/dist/LazyReferenceCollection.d.ts +0 -177
- package/dist/LazyReferenceCollection.js +0 -461
- package/dist/Model.d.ts +0 -454
- package/dist/Model.js +0 -919
- package/dist/ModelRegistry.d.ts +0 -225
- package/dist/ModelRegistry.js +0 -539
- package/dist/NetworkMonitor.d.ts +0 -28
- package/dist/NetworkMonitor.js +0 -79
- package/dist/RuntimeContext.d.ts +0 -52
- package/dist/RuntimeContext.js +0 -80
- package/dist/SyncClient.d.ts +0 -541
- package/dist/SyncClient.js +0 -2202
- package/dist/adapters/alwaysOnline.d.ts +0 -14
- package/dist/adapters/alwaysOnline.js +0 -17
- package/dist/adapters/inMemoryStorage.d.ts +0 -31
- package/dist/adapters/inMemoryStorage.js +0 -110
- package/dist/ai-sdk/coordinatedTool.d.ts +0 -120
- package/dist/ai-sdk/coordinatedTool.js +0 -134
- package/dist/ai-sdk/coordinationContext.d.ts +0 -46
- package/dist/ai-sdk/coordinationContext.js +0 -106
- package/dist/ai-sdk/index.d.ts +0 -121
- package/dist/ai-sdk/index.js +0 -121
- package/dist/ai-sdk/wrap.d.ts +0 -65
- package/dist/ai-sdk/wrap.js +0 -39
- package/dist/auth/index.d.ts +0 -1
- package/dist/auth/index.js +0 -8
- package/dist/batching/index.d.ts +0 -55
- package/dist/batching/index.js +0 -147
- package/dist/client/Ablo.d.ts +0 -231
- package/dist/client/Ablo.js +0 -160
- package/dist/client/abloClient.d.ts +0 -309
- package/dist/client/abloClient.js +0 -13
- package/dist/client/clientPrelude.d.ts +0 -52
- package/dist/client/clientPrelude.js +0 -60
- package/dist/client/consoleLogger.d.ts +0 -35
- package/dist/client/consoleLogger.js +0 -44
- package/dist/client/coreClient.d.ts +0 -60
- package/dist/client/coreClient.js +0 -118
- package/dist/client/createInternalComponents.d.ts +0 -50
- package/dist/client/createInternalComponents.js +0 -98
- package/dist/client/createModelProxy.d.ts +0 -248
- package/dist/client/createModelProxy.js +0 -884
- package/dist/client/humans.d.ts +0 -69
- package/dist/client/humans.js +0 -78
- package/dist/client/modelRegistration.d.ts +0 -10
- package/dist/client/modelRegistration.js +0 -312
- package/dist/client/options.d.ts +0 -461
- package/dist/client/options.js +0 -7
- package/dist/client/reactiveEngine.d.ts +0 -53
- package/dist/client/reactiveEngine.js +0 -688
- package/dist/client/resourceTypes.d.ts +0 -12
- package/dist/client/resourceTypes.js +0 -10
- package/dist/client/schemaConfig.d.ts +0 -44
- package/dist/client/schemaConfig.js +0 -185
- package/dist/client/storeCluster.d.ts +0 -47
- package/dist/client/storeCluster.js +0 -118
- package/dist/client/storeLifecycle.d.ts +0 -61
- package/dist/client/storeLifecycle.js +0 -231
- package/dist/client/validateAbloOptions.d.ts +0 -42
- package/dist/client/validateAbloOptions.js +0 -43
- package/dist/client/wsMutationExecutor.d.ts +0 -27
- package/dist/client/wsMutationExecutor.js +0 -72
- package/dist/context.d.ts +0 -42
- package/dist/context.js +0 -81
- package/dist/coordination/ClaimLog.d.ts +0 -26
- package/dist/coordination/ClaimLog.js +0 -32
- package/dist/coordination/index.d.ts +0 -1
- package/dist/coordination/index.js +0 -8
- package/dist/core/index.d.ts +0 -33
- package/dist/core/index.js +0 -48
- package/dist/docs/catalog.d.ts +0 -72
- package/dist/docs/catalog.js +0 -230
- package/dist/docs/index.d.ts +0 -10
- package/dist/docs/index.js +0 -10
- package/dist/environment.d.ts +0 -1
- package/dist/environment.js +0 -8
- package/dist/interfaces/index.d.ts +0 -311
- package/dist/interfaces/index.js +0 -9
- package/dist/keys/index.d.ts +0 -1
- package/dist/keys/index.js +0 -8
- package/dist/mutators/RecordingMutation.d.ts +0 -36
- package/dist/mutators/RecordingMutation.js +0 -182
- package/dist/mutators/Transaction.d.ts +0 -40
- package/dist/mutators/Transaction.js +0 -58
- package/dist/mutators/UndoManager.d.ts +0 -258
- package/dist/mutators/UndoManager.js +0 -658
- package/dist/mutators/defineMutators.d.ts +0 -60
- package/dist/mutators/defineMutators.js +0 -18
- package/dist/mutators/inverseOp.d.ts +0 -126
- package/dist/mutators/inverseOp.js +0 -71
- package/dist/mutators/mutateActions.d.ts +0 -45
- package/dist/mutators/mutateActions.js +0 -105
- package/dist/mutators/readerActions.d.ts +0 -33
- package/dist/mutators/readerActions.js +0 -57
- package/dist/mutators/undoApply.d.ts +0 -51
- package/dist/mutators/undoApply.js +0 -117
- package/dist/policy/index.d.ts +0 -21
- package/dist/policy/index.js +0 -20
- package/dist/query/QueryProcessor.d.ts +0 -75
- package/dist/query/QueryProcessor.js +0 -255
- package/dist/query/client.d.ts +0 -64
- package/dist/query/client.js +0 -138
- package/dist/query/types.d.ts +0 -85
- package/dist/query/types.js +0 -16
- package/dist/react/AbloProvider.d.ts +0 -242
- package/dist/react/AbloProvider.js +0 -458
- package/dist/react/ClientSideSuspense.d.ts +0 -36
- package/dist/react/ClientSideSuspense.js +0 -17
- package/dist/react/DefaultFallback.d.ts +0 -24
- package/dist/react/DefaultFallback.js +0 -43
- package/dist/react/context.d.ts +0 -55
- package/dist/react/context.js +0 -29
- package/dist/react/createAbloReact.d.ts +0 -56
- package/dist/react/createAbloReact.js +0 -51
- package/dist/react/index.d.ts +0 -62
- package/dist/react/index.js +0 -69
- package/dist/react/internalContext.d.ts +0 -33
- package/dist/react/internalContext.js +0 -3
- package/dist/react/useAblo.d.ts +0 -82
- package/dist/react/useAblo.js +0 -120
- package/dist/react/useCurrentUserId.d.ts +0 -22
- package/dist/react/useCurrentUserId.js +0 -34
- package/dist/react/useErrorListener.d.ts +0 -20
- package/dist/react/useErrorListener.js +0 -38
- package/dist/react/useMutationFailureListener.d.ts +0 -26
- package/dist/react/useMutationFailureListener.js +0 -38
- package/dist/react/useMutators.d.ts +0 -56
- package/dist/react/useMutators.js +0 -84
- package/dist/react/useReactive.d.ts +0 -35
- package/dist/react/useReactive.js +0 -123
- package/dist/react/useSyncStatus.d.ts +0 -59
- package/dist/react/useSyncStatus.js +0 -76
- package/dist/react/useUndoScope.d.ts +0 -34
- package/dist/react/useUndoScope.js +0 -81
- package/dist/schema/coordination.d.ts +0 -112
- package/dist/schema/coordination.js +0 -133
- package/dist/schema/ddl.d.ts +0 -97
- package/dist/schema/ddl.js +0 -491
- package/dist/schema/ddlLock.d.ts +0 -35
- package/dist/schema/ddlLock.js +0 -46
- package/dist/schema/diff.d.ts +0 -225
- package/dist/schema/diff.js +0 -289
- package/dist/schema/generate.d.ts +0 -19
- package/dist/schema/generate.js +0 -86
- package/dist/schema/index.d.ts +0 -42
- package/dist/schema/index.js +0 -80
- package/dist/schema/queries.d.ts +0 -201
- package/dist/schema/queries.js +0 -144
- package/dist/schema/select.d.ts +0 -40
- package/dist/schema/select.js +0 -90
- package/dist/schema/serialize.d.ts +0 -115
- package/dist/schema/serialize.js +0 -265
- package/dist/schema/sugar.d.ts +0 -109
- package/dist/schema/sugar.js +0 -83
- package/dist/schema/syncDeltaRow.d.ts +0 -6
- package/dist/schema/syncDeltaRow.js +0 -6
- package/dist/server/adapter.d.ts +0 -173
- package/dist/server/adapter.js +0 -18
- package/dist/server/commit.d.ts +0 -107
- package/dist/server/commit.js +0 -1
- package/dist/server/index.d.ts +0 -14
- package/dist/server/index.js +0 -2
- package/dist/server/readConfig.d.ts +0 -80
- package/dist/server/readConfig.js +0 -8
- package/dist/server/storageMode.d.ts +0 -23
- package/dist/server/storageMode.js +0 -17
- package/dist/source/adapter.d.ts +0 -83
- package/dist/source/adapter.js +0 -24
- package/dist/source/adapters/drizzle.d.ts +0 -48
- package/dist/source/adapters/drizzle.js +0 -219
- package/dist/source/adapters/kysely.d.ts +0 -42
- package/dist/source/adapters/kysely.js +0 -205
- package/dist/source/adapters/kyselyMutationCore.d.ts +0 -76
- package/dist/source/adapters/kyselyMutationCore.js +0 -125
- package/dist/source/adapters/memory.d.ts +0 -13
- package/dist/source/adapters/memory.js +0 -130
- package/dist/source/adapters/prisma.d.ts +0 -63
- package/dist/source/adapters/prisma.js +0 -202
- package/dist/source/conformance.d.ts +0 -37
- package/dist/source/conformance.js +0 -215
- package/dist/source/connector.d.ts +0 -95
- package/dist/source/connector.js +0 -266
- package/dist/source/connectorProtocol.d.ts +0 -154
- package/dist/source/connectorProtocol.js +0 -163
- package/dist/source/contract.d.ts +0 -195
- package/dist/source/contract.js +0 -164
- package/dist/source/factory.d.ts +0 -92
- package/dist/source/factory.js +0 -286
- package/dist/source/idempotency.d.ts +0 -61
- package/dist/source/idempotency.js +0 -144
- package/dist/source/index.d.ts +0 -23
- package/dist/source/index.js +0 -30
- package/dist/source/migrations.d.ts +0 -21
- package/dist/source/migrations.js +0 -103
- package/dist/source/next.d.ts +0 -32
- package/dist/source/next.js +0 -25
- package/dist/source/pushQueue.d.ts +0 -134
- package/dist/source/pushQueue.js +0 -256
- package/dist/source/signing.d.ts +0 -92
- package/dist/source/signing.js +0 -162
- package/dist/source/types.d.ts +0 -401
- package/dist/source/types.js +0 -59
- package/dist/storeContract.d.ts +0 -145
- package/dist/storeContract.js +0 -12
- package/dist/stores/DatabaseManager.d.ts +0 -107
- package/dist/stores/DatabaseManager.js +0 -388
- package/dist/stores/ObjectStore.d.ts +0 -115
- package/dist/stores/ObjectStore.js +0 -393
- package/dist/stores/ObjectStoreContract.d.ts +0 -38
- package/dist/stores/ObjectStoreContract.js +0 -1
- package/dist/stores/StoreManager.d.ts +0 -114
- package/dist/stores/StoreManager.js +0 -304
- package/dist/stores/SyncActionStore.d.ts +0 -99
- package/dist/stores/SyncActionStore.js +0 -506
- package/dist/stores/openIDBWithTimeout.d.ts +0 -65
- package/dist/stores/openIDBWithTimeout.js +0 -153
- package/dist/stores/syncAction.d.ts +0 -26
- package/dist/stores/syncAction.js +0 -16
- package/dist/surface.d.ts +0 -36
- package/dist/surface.js +0 -75
- package/dist/sync/BootstrapFetcher.d.ts +0 -284
- package/dist/sync/BootstrapFetcher.js +0 -964
- package/dist/sync/ConnectionManager.d.ts +0 -8
- package/dist/sync/ConnectionManager.js +0 -8
- package/dist/sync/OnDemandLoader.d.ts +0 -231
- package/dist/sync/OnDemandLoader.js +0 -743
- package/dist/sync/SubscriptionManager.d.ts +0 -159
- package/dist/sync/SubscriptionManager.js +0 -243
- package/dist/sync/SyncWebSocket.d.ts +0 -173
- package/dist/sync/SyncWebSocket.js +0 -438
- package/dist/sync/awaitClaimGrant.d.ts +0 -6
- package/dist/sync/awaitClaimGrant.js +0 -6
- package/dist/sync/bootstrapApply.d.ts +0 -73
- package/dist/sync/bootstrapApply.js +0 -73
- package/dist/sync/commitFrames.d.ts +0 -8
- package/dist/sync/commitFrames.js +0 -8
- package/dist/sync/contextPorts.d.ts +0 -18
- package/dist/sync/contextPorts.js +0 -31
- package/dist/sync/createClaimStream.d.ts +0 -7
- package/dist/sync/createClaimStream.js +0 -7
- package/dist/sync/createPresenceStream.d.ts +0 -69
- package/dist/sync/createPresenceStream.js +0 -200
- package/dist/sync/createSnapshot.d.ts +0 -29
- package/dist/sync/createSnapshot.js +0 -118
- package/dist/sync/credentialLifecycle.d.ts +0 -7
- package/dist/sync/credentialLifecycle.js +0 -7
- package/dist/sync/deltaPipeline.d.ts +0 -114
- package/dist/sync/deltaPipeline.js +0 -278
- package/dist/sync/groupChange.d.ts +0 -116
- package/dist/sync/groupChange.js +0 -244
- package/dist/sync/participants.d.ts +0 -132
- package/dist/sync/participants.js +0 -346
- package/dist/sync/persistedPrefix.d.ts +0 -12
- package/dist/sync/persistedPrefix.js +0 -22
- package/dist/sync/schemaDrift.d.ts +0 -55
- package/dist/sync/schemaDrift.js +0 -53
- package/dist/sync/schemas.d.ts +0 -71
- package/dist/sync/schemas.js +0 -94
- package/dist/sync/syncCursor.d.ts +0 -40
- package/dist/sync/syncCursor.js +0 -55
- package/dist/sync/syncPlan.d.ts +0 -54
- package/dist/sync/syncPlan.js +0 -50
- package/dist/sync/wsFrameHandlers.d.ts +0 -8
- package/dist/sync/wsFrameHandlers.js +0 -8
- package/dist/syncLog/contract.d.ts +0 -20
- package/dist/syncLog/contract.js +0 -19
- package/dist/syncLog/index.d.ts +0 -1
- package/dist/syncLog/index.js +0 -1
- package/dist/transaction/ablo.d.ts +0 -88
- package/dist/transaction/ablo.js +0 -33
- package/dist/transaction/auth/apiKey.d.ts +0 -152
- package/dist/transaction/auth/apiKey.js +0 -419
- package/dist/transaction/auth/bootstrapScope.d.ts +0 -15
- package/dist/transaction/auth/bootstrapScope.js +0 -1
- package/dist/transaction/auth/capability.d.ts +0 -212
- package/dist/transaction/auth/capability.js +0 -224
- package/dist/transaction/auth/credentialEndpoint.d.ts +0 -61
- package/dist/transaction/auth/credentialEndpoint.js +0 -86
- package/dist/transaction/auth/credentialPolicy.d.ts +0 -148
- package/dist/transaction/auth/credentialPolicy.js +0 -125
- package/dist/transaction/auth/credentialSource.d.ts +0 -30
- package/dist/transaction/auth/credentialSource.js +0 -55
- package/dist/transaction/auth/hostedEndpoints.d.ts +0 -21
- package/dist/transaction/auth/hostedEndpoints.js +0 -21
- package/dist/transaction/auth/identity.d.ts +0 -55
- package/dist/transaction/auth/identity.js +0 -210
- package/dist/transaction/auth/index.d.ts +0 -162
- package/dist/transaction/auth/index.js +0 -304
- package/dist/transaction/auth/schemas.d.ts +0 -59
- package/dist/transaction/auth/schemas.js +0 -85
- package/dist/transaction/auth/sessionMint.d.ts +0 -28
- package/dist/transaction/auth/sessionMint.js +0 -85
- package/dist/transaction/coordination/awaitClaimGrant.d.ts +0 -56
- package/dist/transaction/coordination/awaitClaimGrant.js +0 -124
- package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +0 -84
- package/dist/transaction/coordination/claimHeartbeatLoop.js +0 -108
- package/dist/transaction/coordination/claimMeta.d.ts +0 -49
- package/dist/transaction/coordination/claimMeta.js +0 -52
- package/dist/transaction/coordination/createClaimStream.d.ts +0 -64
- package/dist/transaction/coordination/createClaimStream.js +0 -475
- package/dist/transaction/coordination/events.d.ts +0 -74
- package/dist/transaction/coordination/events.js +0 -7
- package/dist/transaction/coordination/index.d.ts +0 -19
- package/dist/transaction/coordination/index.js +0 -45
- package/dist/transaction/coordination/locator.d.ts +0 -104
- package/dist/transaction/coordination/locator.js +0 -102
- package/dist/transaction/coordination/schema.d.ts +0 -1536
- package/dist/transaction/coordination/schema.js +0 -1177
- package/dist/transaction/coordination/targetConflict.d.ts +0 -2
- package/dist/transaction/coordination/targetConflict.js +0 -107
- package/dist/transaction/coordination/trace.d.ts +0 -78
- package/dist/transaction/coordination/trace.js +0 -138
- package/dist/transaction/durableWrites.d.ts +0 -62
- package/dist/transaction/durableWrites.js +0 -71
- package/dist/transaction/environment.d.ts +0 -105
- package/dist/transaction/environment.js +0 -108
- package/dist/transaction/errorCodes.d.ts +0 -403
- package/dist/transaction/errorCodes.js +0 -484
- package/dist/transaction/errors.d.ts +0 -428
- package/dist/transaction/errors.js +0 -686
- package/dist/transaction/footprint.d.ts +0 -111
- package/dist/transaction/footprint.js +0 -0
- package/dist/transaction/index.d.ts +0 -20
- package/dist/transaction/index.js +0 -20
- package/dist/transaction/keys/index.d.ts +0 -87
- package/dist/transaction/keys/index.js +0 -207
- package/dist/transaction/log/syncDeltaRow.d.ts +0 -158
- package/dist/transaction/log/syncDeltaRow.js +0 -95
- package/dist/transaction/logPosition.d.ts +0 -97
- package/dist/transaction/logPosition.js +0 -125
- package/dist/transaction/logger.d.ts +0 -16
- package/dist/transaction/logger.js +0 -7
- package/dist/transaction/observability.d.ts +0 -53
- package/dist/transaction/observability.js +0 -19
- package/dist/transaction/persistence.d.ts +0 -12
- package/dist/transaction/persistence.js +0 -11
- package/dist/transaction/plugin.d.ts +0 -285
- package/dist/transaction/plugin.js +0 -106
- package/dist/transaction/policy/types.d.ts +0 -217
- package/dist/transaction/policy/types.js +0 -126
- package/dist/transaction/resources/functionalUpdate.d.ts +0 -79
- package/dist/transaction/resources/functionalUpdate.js +0 -87
- package/dist/transaction/resources/httpResources.d.ts +0 -321
- package/dist/transaction/resources/httpResources.js +0 -7
- package/dist/transaction/resources/modelOperations.d.ts +0 -427
- package/dist/transaction/resources/modelOperations.js +0 -12
- package/dist/transaction/resources/mutationOptions.d.ts +0 -66
- package/dist/transaction/resources/mutationOptions.js +0 -9
- package/dist/transaction/resources/where.d.ts +0 -101
- package/dist/transaction/resources/where.js +0 -115
- package/dist/transaction/resources/writeOptionsSchema.d.ts +0 -47
- package/dist/transaction/resources/writeOptionsSchema.js +0 -73
- package/dist/transaction/schema/field.d.ts +0 -120
- package/dist/transaction/schema/field.js +0 -265
- package/dist/transaction/schema/fieldRef.d.ts +0 -38
- package/dist/transaction/schema/fieldRef.js +0 -11
- package/dist/transaction/schema/loadStrategy.d.ts +0 -45
- package/dist/transaction/schema/loadStrategy.js +0 -46
- package/dist/transaction/schema/model.d.ts +0 -379
- package/dist/transaction/schema/model.js +0 -123
- package/dist/transaction/schema/openapi.d.ts +0 -58
- package/dist/transaction/schema/openapi.js +0 -501
- package/dist/transaction/schema/relation.d.ts +0 -204
- package/dist/transaction/schema/relation.js +0 -104
- package/dist/transaction/schema/residency.d.ts +0 -29
- package/dist/transaction/schema/residency.js +0 -25
- package/dist/transaction/schema/roles.d.ts +0 -249
- package/dist/transaction/schema/roles.js +0 -230
- package/dist/transaction/schema/schema.d.ts +0 -351
- package/dist/transaction/schema/schema.js +0 -325
- package/dist/transaction/schema/tenancy.d.ts +0 -139
- package/dist/transaction/schema/tenancy.js +0 -190
- package/dist/transaction/transactionLayer.d.ts +0 -82
- package/dist/transaction/transactionLayer.js +0 -24
- package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +0 -143
- package/dist/transaction/transactions/settlement/commitEnvelope.js +0 -161
- package/dist/transaction/transactions/settlement/httpCommitEnvelope.d.ts +0 -53
- package/dist/transaction/transactions/settlement/httpCommitEnvelope.js +0 -207
- package/dist/transaction/transactions/settlement/idempotencyKey.d.ts +0 -10
- package/dist/transaction/transactions/settlement/idempotencyKey.js +0 -9
- package/dist/transaction/transactions/settlement/pendingWrite.d.ts +0 -112
- package/dist/transaction/transactions/settlement/pendingWrite.js +0 -20
- package/dist/transaction/transport/commitFrames.d.ts +0 -90
- package/dist/transaction/transport/commitFrames.js +0 -134
- package/dist/transaction/transport/connectionManager.d.ts +0 -215
- package/dist/transaction/transport/connectionManager.js +0 -673
- package/dist/transaction/transport/credentialLifecycle.d.ts +0 -177
- package/dist/transaction/transport/credentialLifecycle.js +0 -324
- package/dist/transaction/transport/heartbeat.d.ts +0 -65
- package/dist/transaction/transport/heartbeat.js +0 -93
- package/dist/transaction/transport/httpClient.d.ts +0 -131
- package/dist/transaction/transport/httpClient.js +0 -146
- package/dist/transaction/transport/httpOptions.d.ts +0 -33
- package/dist/transaction/transport/httpOptions.js +0 -12
- package/dist/transaction/transport/httpTransport.d.ts +0 -8
- package/dist/transaction/transport/httpTransport.js +0 -1388
- package/dist/transaction/transport/networkProbe.d.ts +0 -84
- package/dist/transaction/transport/networkProbe.js +0 -207
- package/dist/transaction/transport/wsFrameHandlers.d.ts +0 -128
- package/dist/transaction/transport/wsFrameHandlers.js +0 -429
- package/dist/transaction/transport/wsTransport.d.ts +0 -574
- package/dist/transaction/transport/wsTransport.js +0 -1023
- package/dist/transaction/types/assertExact.d.ts +0 -17
- package/dist/transaction/types/assertExact.js +0 -1
- package/dist/transaction/types/global.d.ts +0 -107
- package/dist/transaction/types/global.js +0 -40
- package/dist/transaction/types/index.d.ts +0 -205
- package/dist/transaction/types/index.js +0 -56
- package/dist/transaction/types/modelData.d.ts +0 -10
- package/dist/transaction/types/modelData.js +0 -9
- package/dist/transaction/types/participant.d.ts +0 -20
- package/dist/transaction/types/participant.js +0 -10
- package/dist/transaction/types/streams.d.ts +0 -550
- package/dist/transaction/types/streams.js +0 -11
- package/dist/transaction/utils/asyncIterator.d.ts +0 -34
- package/dist/transaction/utils/asyncIterator.js +0 -135
- package/dist/transaction/utils/duration.d.ts +0 -50
- package/dist/transaction/utils/duration.js +0 -77
- package/dist/transaction/utils/json.d.ts +0 -57
- package/dist/transaction/utils/json.js +0 -276
- package/dist/transaction/wire/accountResponses.d.ts +0 -420
- package/dist/transaction/wire/accountResponses.js +0 -290
- package/dist/transaction/wire/auth.d.ts +0 -56
- package/dist/transaction/wire/auth.js +0 -63
- package/dist/transaction/wire/bootstrapReason.d.ts +0 -9
- package/dist/transaction/wire/bootstrapReason.js +0 -8
- package/dist/transaction/wire/claimEvent.d.ts +0 -76
- package/dist/transaction/wire/claimEvent.js +0 -73
- package/dist/transaction/wire/claims.d.ts +0 -530
- package/dist/transaction/wire/claims.js +0 -327
- package/dist/transaction/wire/commit.d.ts +0 -603
- package/dist/transaction/wire/commit.js +0 -321
- package/dist/transaction/wire/delta.d.ts +0 -250
- package/dist/transaction/wire/delta.js +0 -147
- package/dist/transaction/wire/errorEnvelope.d.ts +0 -72
- package/dist/transaction/wire/errorEnvelope.js +0 -123
- package/dist/transaction/wire/feedCursor.d.ts +0 -60
- package/dist/transaction/wire/feedCursor.js +0 -82
- package/dist/transaction/wire/feedEvent.d.ts +0 -204
- package/dist/transaction/wire/feedEvent.js +0 -65
- package/dist/transaction/wire/frames.d.ts +0 -194
- package/dist/transaction/wire/frames.js +0 -50
- package/dist/transaction/wire/inboundFrames.d.ts +0 -562
- package/dist/transaction/wire/inboundFrames.js +0 -116
- package/dist/transaction/wire/index.d.ts +0 -54
- package/dist/transaction/wire/index.js +0 -83
- package/dist/transaction/wire/listEnvelope.d.ts +0 -37
- package/dist/transaction/wire/listEnvelope.js +0 -42
- package/dist/transaction/wire/modelMutations.d.ts +0 -31
- package/dist/transaction/wire/modelMutations.js +0 -52
- package/dist/transaction/wire/modelResponses.d.ts +0 -85
- package/dist/transaction/wire/modelResponses.js +0 -43
- package/dist/transaction/wire/modelShape.d.ts +0 -78
- package/dist/transaction/wire/modelShape.js +0 -74
- package/dist/transaction/wire/protocol.d.ts +0 -38
- package/dist/transaction/wire/protocol.js +0 -38
- package/dist/transaction/wire/protocolVersion.d.ts +0 -73
- package/dist/transaction/wire/protocolVersion.js +0 -83
- package/dist/transactions/mutations/MutationQueue.d.ts +0 -661
- package/dist/transactions/mutations/MutationQueue.js +0 -2807
- package/dist/transactions/mutations/MutationStore.d.ts +0 -20
- package/dist/transactions/mutations/MutationStore.js +0 -53
- package/dist/transactions/mutations/UnconfirmedWrites.d.ts +0 -82
- package/dist/transactions/mutations/UnconfirmedWrites.js +0 -104
- package/dist/transactions/mutations/coalesceRules.d.ts +0 -58
- package/dist/transactions/mutations/coalesceRules.js +0 -140
- package/dist/transactions/mutations/commitLatency.d.ts +0 -52
- package/dist/transactions/mutations/commitLatency.js +0 -130
- package/dist/transactions/mutations/commitOutboxStore.d.ts +0 -28
- package/dist/transactions/mutations/commitOutboxStore.js +0 -26
- package/dist/transactions/mutations/commitPayload.d.ts +0 -165
- package/dist/transactions/mutations/commitPayload.js +0 -152
- package/dist/transactions/mutations/deltaConfirmation.d.ts +0 -63
- package/dist/transactions/mutations/deltaConfirmation.js +0 -235
- package/dist/transactions/mutations/durableWriteStore.d.ts +0 -14
- package/dist/transactions/mutations/durableWriteStore.js +0 -12
- package/dist/transactions/mutations/optimisticApply.d.ts +0 -49
- package/dist/transactions/mutations/optimisticApply.js +0 -65
- package/dist/transactions/mutations/replayValidation.d.ts +0 -187
- package/dist/transactions/mutations/replayValidation.js +0 -164
- package/dist/utils/mobxSetup.d.ts +0 -53
- package/dist/utils/mobxSetup.js +0 -330
- package/dist/views/QueryView.d.ts +0 -79
- package/dist/views/QueryView.js +0 -218
- package/dist/views/ViewRegistry.d.ts +0 -20
- package/dist/views/ViewRegistry.js +0 -55
- package/dist/views/incrementalView.d.ts +0 -45
- package/dist/views/incrementalView.js +0 -69
- package/dist/webhooks/events.d.ts +0 -43
- package/dist/webhooks/events.js +0 -42
- package/dist/webhooks/index.d.ts +0 -8
- package/dist/webhooks/index.js +0 -8
- package/dist/wire/index.d.ts +0 -1
- package/dist/wire/index.js +0 -8
package/dist/source/factory.js
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Builds the request handler returned by `dataSource()`. Given your options —
|
|
3
|
-
* the schema, the API key, and either
|
|
4
|
-
* per-model handlers or an ORM adapter — the handler verifies each signed request,
|
|
5
|
-
* enforces the per-key scopes, and routes the four wire operations (`load`,
|
|
6
|
-
* `list`, `commit`, and `events`) to whichever handlers you configured.
|
|
7
|
-
*/
|
|
8
|
-
import { changeSetSchema } from './contract.js';
|
|
9
|
-
import { SourceSignatureError, verifyAbloSourceRequest, } from './signing.js';
|
|
10
|
-
function json(data, status = 200) {
|
|
11
|
-
return new Response(JSON.stringify(data), {
|
|
12
|
-
status,
|
|
13
|
-
headers: { 'Content-Type': 'application/json' },
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Serves one request from an ORM `adapter`, mapping each of the four operations to
|
|
18
|
-
* the adapter's `read`, `commit`, or `events` method and shaping the wire response.
|
|
19
|
-
* The adapter is the only dispatch point, so there is no per-model branching here.
|
|
20
|
-
*/
|
|
21
|
-
async function handleViaAdapter(adapter, body, scope) {
|
|
22
|
-
if (body.type === 'load') {
|
|
23
|
-
const rows = await adapter.read({
|
|
24
|
-
kind: 'load',
|
|
25
|
-
model: body.model,
|
|
26
|
-
id: body.id,
|
|
27
|
-
...(scope ? { scope } : {}),
|
|
28
|
-
});
|
|
29
|
-
return json({ row: rows[0] ?? null });
|
|
30
|
-
}
|
|
31
|
-
if (body.type === 'list') {
|
|
32
|
-
const rows = await adapter.read({
|
|
33
|
-
kind: 'list',
|
|
34
|
-
model: body.model,
|
|
35
|
-
...(body.query ? { query: body.query } : {}),
|
|
36
|
-
...(scope ? { scope } : {}),
|
|
37
|
-
});
|
|
38
|
-
return json({ rows });
|
|
39
|
-
}
|
|
40
|
-
if (body.type === 'commit') {
|
|
41
|
-
const correlationId = body.correlationId ?? body.clientTxId;
|
|
42
|
-
if (!correlationId) {
|
|
43
|
-
return json({
|
|
44
|
-
error: 'source_commit_requires_correlation_id',
|
|
45
|
-
message: 'commit requires a scoped correlationId for idempotency',
|
|
46
|
-
}, 400);
|
|
47
|
-
}
|
|
48
|
-
const parsed = changeSetSchema.safeParse({
|
|
49
|
-
operations: body.operations,
|
|
50
|
-
correlationId,
|
|
51
|
-
intentHash: body.intentHash,
|
|
52
|
-
echo: body.echo,
|
|
53
|
-
});
|
|
54
|
-
if (!parsed.success) {
|
|
55
|
-
return json({ error: 'source_commit_invalid', message: parsed.error.message }, 400);
|
|
56
|
-
}
|
|
57
|
-
if (parsed.data.echo?.kind === 'postgres-wal' &&
|
|
58
|
-
adapter.capabilities.postgresWalEcho !== true) {
|
|
59
|
-
return json({
|
|
60
|
-
error: 'source_commit_echo_not_supported',
|
|
61
|
-
message: 'This adapter cannot emit the required Postgres WAL commit echo',
|
|
62
|
-
}, 409);
|
|
63
|
-
}
|
|
64
|
-
const result = await adapter.commit(parsed.data);
|
|
65
|
-
return json({ rows: result.rows });
|
|
66
|
-
}
|
|
67
|
-
if (body.type === 'events') {
|
|
68
|
-
const page = await adapter.events(body.cursor ?? null, body.limit ?? 100);
|
|
69
|
-
return json({
|
|
70
|
-
events: page.events.map((event) => ({
|
|
71
|
-
id: event.id,
|
|
72
|
-
model: event.model,
|
|
73
|
-
entityId: event.entityId,
|
|
74
|
-
type: event.type,
|
|
75
|
-
...(event.data !== undefined && event.data !== null ? { data: event.data } : {}),
|
|
76
|
-
...(event.organizationId ? { organizationId: event.organizationId } : {}),
|
|
77
|
-
...(event.clientTxId ? { clientTxId: event.clientTxId } : {}),
|
|
78
|
-
...(event.correlationId ? { correlationId: event.correlationId } : {}),
|
|
79
|
-
...(event.transactionId ? { transactionId: event.transactionId } : {}),
|
|
80
|
-
...(event.occurredAt !== undefined && event.occurredAt !== null
|
|
81
|
-
? { occurredAt: event.occurredAt }
|
|
82
|
-
: {}),
|
|
83
|
-
})),
|
|
84
|
-
...(page.nextCursor !== null ? { nextCursor: page.nextCursor } : {}),
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return json({ error: 'unknown_source_request' }, 400);
|
|
88
|
-
}
|
|
89
|
-
async function readBody(request) {
|
|
90
|
-
if (typeof request.text === 'function') {
|
|
91
|
-
const rawBody = await request.text();
|
|
92
|
-
return { rawBody, body: JSON.parse(rawBody) };
|
|
93
|
-
}
|
|
94
|
-
const body = (await request.json());
|
|
95
|
-
return { rawBody: JSON.stringify(body), body };
|
|
96
|
-
}
|
|
97
|
-
async function resolveApiKey(apiKey, context) {
|
|
98
|
-
if (!apiKey)
|
|
99
|
-
return null;
|
|
100
|
-
return typeof apiKey === 'function' ? apiKey(context) : apiKey;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Maps a wire request to the single scope it requires. The mapping is exhaustive,
|
|
104
|
-
* so a new request type must be given its own scope, keeping the scope vocabulary
|
|
105
|
-
* in step with the set of operations.
|
|
106
|
-
*/
|
|
107
|
-
function scopeFor(body) {
|
|
108
|
-
switch (body.type) {
|
|
109
|
-
case 'load':
|
|
110
|
-
return 'load';
|
|
111
|
-
case 'list':
|
|
112
|
-
return 'list';
|
|
113
|
-
case 'commit':
|
|
114
|
-
return 'commit';
|
|
115
|
-
case 'events':
|
|
116
|
-
return 'events';
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
function normalizeListResult(result) {
|
|
120
|
-
if (Array.isArray(result)) {
|
|
121
|
-
return { rows: result };
|
|
122
|
-
}
|
|
123
|
-
const page = result;
|
|
124
|
-
return page.nextCursor !== undefined
|
|
125
|
-
? { rows: page.rows, nextCursor: page.nextCursor }
|
|
126
|
-
: { rows: page.rows };
|
|
127
|
-
}
|
|
128
|
-
function getModelHandlers(options, model) {
|
|
129
|
-
const grouped = options.models?.[model];
|
|
130
|
-
if (grouped)
|
|
131
|
-
return grouped;
|
|
132
|
-
const direct = options[model];
|
|
133
|
-
return direct;
|
|
134
|
-
}
|
|
135
|
-
function sameModel(operations) {
|
|
136
|
-
const first = operations[0]?.model;
|
|
137
|
-
if (!first)
|
|
138
|
-
return null;
|
|
139
|
-
return operations.every((op) => op.model === first) ? first : null;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Creates a Data Source endpoint you host in front of your own database.
|
|
143
|
-
*
|
|
144
|
-
* Your application code still reads and writes through Ablo, as in
|
|
145
|
-
* `ablo.files.load`, `.list`, and `.update`. This helper is for keeping the
|
|
146
|
-
* canonical rows in your database: Ablo calls a narrow, signed endpoint you
|
|
147
|
-
* control rather than holding your database credentials.
|
|
148
|
-
*/
|
|
149
|
-
export function dataSource(options) {
|
|
150
|
-
return async function handleDataSource(request) {
|
|
151
|
-
if (request.method !== 'POST') {
|
|
152
|
-
return json({ error: 'method_not_allowed' }, 405);
|
|
153
|
-
}
|
|
154
|
-
let body;
|
|
155
|
-
let rawBody;
|
|
156
|
-
try {
|
|
157
|
-
const parsed = await readBody(request);
|
|
158
|
-
body = parsed.body;
|
|
159
|
-
rawBody = parsed.rawBody;
|
|
160
|
-
}
|
|
161
|
-
catch {
|
|
162
|
-
return json({ error: 'invalid_json' }, 400);
|
|
163
|
-
}
|
|
164
|
-
let signature = null;
|
|
165
|
-
try {
|
|
166
|
-
const apiKey = await resolveApiKey(options.apiKey, {
|
|
167
|
-
request,
|
|
168
|
-
body,
|
|
169
|
-
rawBody,
|
|
170
|
-
});
|
|
171
|
-
if (!apiKey) {
|
|
172
|
-
return json({
|
|
173
|
-
error: 'source_api_key_missing',
|
|
174
|
-
message: 'Data Source apiKey is required',
|
|
175
|
-
}, 401);
|
|
176
|
-
}
|
|
177
|
-
signature = await verifyAbloSourceRequest({
|
|
178
|
-
request,
|
|
179
|
-
body: rawBody,
|
|
180
|
-
apiKey,
|
|
181
|
-
toleranceMs: options.signatureToleranceMs,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
catch (err) {
|
|
185
|
-
if (err instanceof SourceSignatureError) {
|
|
186
|
-
return json({ error: err.code, message: err.message }, 401);
|
|
187
|
-
}
|
|
188
|
-
throw err;
|
|
189
|
-
}
|
|
190
|
-
const auth = options.authorize
|
|
191
|
-
? await options.authorize({ request, body, rawBody })
|
|
192
|
-
: undefined;
|
|
193
|
-
// Enforce the per-key scope. When `resolveScopes` is set, it returns the
|
|
194
|
-
// operations this key may invoke, and we check the request against that set
|
|
195
|
-
// before any model handler runs.
|
|
196
|
-
if (options.resolveScopes) {
|
|
197
|
-
const required = scopeFor(body);
|
|
198
|
-
const granted = await options.resolveScopes({ auth, request, body });
|
|
199
|
-
const grantedSet = granted instanceof Set ? granted : new Set(granted);
|
|
200
|
-
if (!grantedSet.has(required)) {
|
|
201
|
-
return json({
|
|
202
|
-
error: 'source_forbidden',
|
|
203
|
-
required,
|
|
204
|
-
granted: Array.from(grantedSet),
|
|
205
|
-
}, 403);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
const context = {
|
|
209
|
-
auth,
|
|
210
|
-
request,
|
|
211
|
-
messageId: signature?.messageId,
|
|
212
|
-
signedAt: signature?.signedAt,
|
|
213
|
-
...(body.scope ? { scope: body.scope } : {}),
|
|
214
|
-
};
|
|
215
|
-
// When an ORM adapter is configured it serves every operation here, at the
|
|
216
|
-
// generic layer where rows are plain JSON, so there is no per-model handler
|
|
217
|
-
// lookup on this path.
|
|
218
|
-
if (options.adapter) {
|
|
219
|
-
return handleViaAdapter(options.adapter, body, context.scope);
|
|
220
|
-
}
|
|
221
|
-
if (body.type === 'load') {
|
|
222
|
-
const handlers = getModelHandlers(options, body.model);
|
|
223
|
-
if (!handlers?.load) {
|
|
224
|
-
return json({ error: 'source_load_not_configured', model: body.model }, 404);
|
|
225
|
-
}
|
|
226
|
-
const row = await handlers.load({ id: body.id, context });
|
|
227
|
-
return json({ row });
|
|
228
|
-
}
|
|
229
|
-
if (body.type === 'list') {
|
|
230
|
-
const handlers = getModelHandlers(options, body.model);
|
|
231
|
-
if (!handlers?.list) {
|
|
232
|
-
return json({ error: 'source_list_not_configured', model: body.model }, 404);
|
|
233
|
-
}
|
|
234
|
-
const result = await handlers.list({ query: body.query ?? {}, context });
|
|
235
|
-
const normalized = normalizeListResult(result);
|
|
236
|
-
return json(normalized);
|
|
237
|
-
}
|
|
238
|
-
if (body.type === 'commit') {
|
|
239
|
-
if (options.commit) {
|
|
240
|
-
const result = await options.commit({
|
|
241
|
-
operations: body.operations,
|
|
242
|
-
correlationId: body.correlationId ?? body.clientTxId,
|
|
243
|
-
clientTxId: body.clientTxId,
|
|
244
|
-
intentHash: body.intentHash,
|
|
245
|
-
echo: body.echo,
|
|
246
|
-
context,
|
|
247
|
-
});
|
|
248
|
-
return json(result);
|
|
249
|
-
}
|
|
250
|
-
const model = body.model ?? sameModel(body.operations);
|
|
251
|
-
if (!model) {
|
|
252
|
-
return json({ error: 'source_commit_requires_single_model' }, 400);
|
|
253
|
-
}
|
|
254
|
-
const handlers = getModelHandlers(options, model);
|
|
255
|
-
if (!handlers?.commit) {
|
|
256
|
-
return json({ error: 'source_commit_not_configured', model }, 404);
|
|
257
|
-
}
|
|
258
|
-
const result = await handlers.commit({
|
|
259
|
-
operations: body.operations,
|
|
260
|
-
correlationId: body.correlationId ?? body.clientTxId,
|
|
261
|
-
clientTxId: body.clientTxId,
|
|
262
|
-
intentHash: body.intentHash,
|
|
263
|
-
echo: body.echo,
|
|
264
|
-
context,
|
|
265
|
-
});
|
|
266
|
-
return json(result);
|
|
267
|
-
}
|
|
268
|
-
if (body.type === 'events') {
|
|
269
|
-
if (!options.events) {
|
|
270
|
-
return json({ error: 'source_events_not_configured' }, 404);
|
|
271
|
-
}
|
|
272
|
-
const result = await options.events({
|
|
273
|
-
cursor: body.cursor,
|
|
274
|
-
limit: body.limit,
|
|
275
|
-
context,
|
|
276
|
-
});
|
|
277
|
-
return json({
|
|
278
|
-
events: result.events,
|
|
279
|
-
...(result.nextCursor !== undefined
|
|
280
|
-
? { nextCursor: result.nextCursor }
|
|
281
|
-
: {}),
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
return json({ error: 'unknown_source_request' }, 400);
|
|
285
|
-
};
|
|
286
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Customer-side source idempotency helpers.
|
|
3
|
-
*
|
|
4
|
-
* Connected writes use a permanent, server-derived correlation key at the
|
|
5
|
-
* customer boundary. The matching intent hash must therefore also be
|
|
6
|
-
* permanent: replaying the key with a different request is a conflict, never a
|
|
7
|
-
* fresh execution. Ablo supplies the hash for signed source requests because
|
|
8
|
-
* it covers context/read guards that an adapter cannot reconstruct from the
|
|
9
|
-
* effective operation list alone. Direct adapter users get a canonical
|
|
10
|
-
* operations-only fallback.
|
|
11
|
-
*/
|
|
12
|
-
import { z } from 'zod';
|
|
13
|
-
import type { ChangeSet, Operation } from './contract.js';
|
|
14
|
-
/** Runtime shape recovered from the internal storage envelope. */
|
|
15
|
-
export declare const sourceEchoTransactionIdSchema: z.ZodObject<{
|
|
16
|
-
correlationId: z.ZodString;
|
|
17
|
-
transactionId: z.ZodString;
|
|
18
|
-
}, z.core.$strict>;
|
|
19
|
-
export type SourceEchoTransactionId = z.infer<typeof sourceEchoTransactionIdSchema>;
|
|
20
|
-
/**
|
|
21
|
-
* Store both source-batch identity and the originating optimistic-write id in
|
|
22
|
-
* the existing `sync_deltas.transaction_id` column. The database value is an
|
|
23
|
-
* internal envelope: the server unwraps it before broadcasting, so clients
|
|
24
|
-
* still receive the exact operation transaction id they authored.
|
|
25
|
-
*
|
|
26
|
-
* Keeping the opaque, authenticated-scope correlation in the stored value is
|
|
27
|
-
* load-bearing for crash recovery. A raw caller may choose or reuse an
|
|
28
|
-
* operation transaction id; that value alone must never be able to satisfy a
|
|
29
|
-
* different participant's queued receipt.
|
|
30
|
-
*/
|
|
31
|
-
export declare function encodeSourceEchoTransactionId(correlationId: string, transactionId: string): string;
|
|
32
|
-
/** Decode a source-WAL transaction envelope, or return null for normal rows. */
|
|
33
|
-
export declare function decodeSourceEchoTransactionId(value: string | null): SourceEchoTransactionId | null;
|
|
34
|
-
/** Canonical operations-only fallback for direct adapter use. */
|
|
35
|
-
export declare function sourceOperationsIntentHash(operations: readonly Operation[]): string;
|
|
36
|
-
/** Resolve the hash every newly-written customer ledger row must persist. */
|
|
37
|
-
export declare function sourceChangeIntentHash(change: ChangeSet): string;
|
|
38
|
-
/** Fail closed for changed intent and legacy rows that lack hash evidence. */
|
|
39
|
-
export declare function assertSourceIdempotencyIntent(cachedHash: unknown, requestHash: string): void;
|
|
40
|
-
/**
|
|
41
|
-
* How long a ledger row stays replayable, as a Postgres interval. New rows are
|
|
42
|
-
* written with `expires_at = now() + this`, so the customer can prune anything
|
|
43
|
-
* past it — the writer can't (it holds no DELETE, by design), so pruning is a
|
|
44
|
-
* job for their own admin/cron: `DELETE FROM ablo_idempotency WHERE expires_at <
|
|
45
|
-
* now()`.
|
|
46
|
-
*
|
|
47
|
-
* This is an ops/UX window, not a safety one: {@link assertSourceIdempotencyRetention}
|
|
48
|
-
* already refuses to replay an expired key (fail-closed), so an expired row can
|
|
49
|
-
* never be safely re-applied whether or not it has been pruned. The window only
|
|
50
|
-
* governs how late a retry can still collect its cached response before it's
|
|
51
|
-
* told to start over. 30 days comfortably covers an offline client's queued
|
|
52
|
-
* commits while keeping the table bounded.
|
|
53
|
-
*/
|
|
54
|
-
export declare const SOURCE_IDEMPOTENCY_RETENTION = "30 days";
|
|
55
|
-
/**
|
|
56
|
-
* Enforce the retention contract on replay. A row past its `expires_at` is
|
|
57
|
-
* refused (fail-closed) rather than re-applied, so pruning expired rows is
|
|
58
|
-
* always safe. Rows written before the column existed (`infinity`/null) are
|
|
59
|
-
* accepted — they predate bounded retention and never expire.
|
|
60
|
-
*/
|
|
61
|
-
export declare function assertSourceIdempotencyRetention(expiresAt: unknown, now?: number): void;
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Customer-side source idempotency helpers.
|
|
3
|
-
*
|
|
4
|
-
* Connected writes use a permanent, server-derived correlation key at the
|
|
5
|
-
* customer boundary. The matching intent hash must therefore also be
|
|
6
|
-
* permanent: replaying the key with a different request is a conflict, never a
|
|
7
|
-
* fresh execution. Ablo supplies the hash for signed source requests because
|
|
8
|
-
* it covers context/read guards that an adapter cannot reconstruct from the
|
|
9
|
-
* effective operation list alone. Direct adapter users get a canonical
|
|
10
|
-
* operations-only fallback.
|
|
11
|
-
*/
|
|
12
|
-
import { createHash } from 'node:crypto';
|
|
13
|
-
import { z } from 'zod';
|
|
14
|
-
import { AbloValidationError } from '../transaction/errors.js';
|
|
15
|
-
import { COMMIT_CORRELATION_ID_MAX_LENGTH, correlationIdSchema, } from '../transaction/wire/commit.js';
|
|
16
|
-
const SOURCE_ECHO_TRANSACTION_ID_PREFIX = 'ablo_echo_tx_v1:';
|
|
17
|
-
const sourceOperationTransactionIdSchema = z
|
|
18
|
-
.string()
|
|
19
|
-
.min(1)
|
|
20
|
-
.max(COMMIT_CORRELATION_ID_MAX_LENGTH);
|
|
21
|
-
/** Runtime shape recovered from the internal storage envelope. */
|
|
22
|
-
export const sourceEchoTransactionIdSchema = z.strictObject({
|
|
23
|
-
correlationId: correlationIdSchema,
|
|
24
|
-
transactionId: sourceOperationTransactionIdSchema,
|
|
25
|
-
});
|
|
26
|
-
const sourceEchoTransactionIdTupleSchema = z.tuple([
|
|
27
|
-
correlationIdSchema,
|
|
28
|
-
sourceOperationTransactionIdSchema,
|
|
29
|
-
]);
|
|
30
|
-
/**
|
|
31
|
-
* Store both source-batch identity and the originating optimistic-write id in
|
|
32
|
-
* the existing `sync_deltas.transaction_id` column. The database value is an
|
|
33
|
-
* internal envelope: the server unwraps it before broadcasting, so clients
|
|
34
|
-
* still receive the exact operation transaction id they authored.
|
|
35
|
-
*
|
|
36
|
-
* Keeping the opaque, authenticated-scope correlation in the stored value is
|
|
37
|
-
* load-bearing for crash recovery. A raw caller may choose or reuse an
|
|
38
|
-
* operation transaction id; that value alone must never be able to satisfy a
|
|
39
|
-
* different participant's queued receipt.
|
|
40
|
-
*/
|
|
41
|
-
export function encodeSourceEchoTransactionId(correlationId, transactionId) {
|
|
42
|
-
const tuple = sourceEchoTransactionIdTupleSchema.parse([
|
|
43
|
-
correlationId,
|
|
44
|
-
transactionId,
|
|
45
|
-
]);
|
|
46
|
-
return `${SOURCE_ECHO_TRANSACTION_ID_PREFIX}${JSON.stringify(tuple)}`;
|
|
47
|
-
}
|
|
48
|
-
/** Decode a source-WAL transaction envelope, or return null for normal rows. */
|
|
49
|
-
export function decodeSourceEchoTransactionId(value) {
|
|
50
|
-
if (!value?.startsWith(SOURCE_ECHO_TRANSACTION_ID_PREFIX))
|
|
51
|
-
return null;
|
|
52
|
-
try {
|
|
53
|
-
const parsed = JSON.parse(value.slice(SOURCE_ECHO_TRANSACTION_ID_PREFIX.length));
|
|
54
|
-
const tuple = sourceEchoTransactionIdTupleSchema.safeParse(parsed);
|
|
55
|
-
if (!tuple.success)
|
|
56
|
-
return null;
|
|
57
|
-
return sourceEchoTransactionIdSchema.parse({
|
|
58
|
-
correlationId: tuple.data[0],
|
|
59
|
-
transactionId: tuple.data[1],
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
function canonicalJson(value) {
|
|
67
|
-
if (value === null || typeof value !== 'object') {
|
|
68
|
-
const encoded = JSON.stringify(value);
|
|
69
|
-
return encoded ?? 'null';
|
|
70
|
-
}
|
|
71
|
-
if (Array.isArray(value)) {
|
|
72
|
-
return `[${value
|
|
73
|
-
.map((entry) => canonicalJson(entry === undefined ? null : entry))
|
|
74
|
-
.join(',')}]`;
|
|
75
|
-
}
|
|
76
|
-
const record = value;
|
|
77
|
-
return `{${Object.keys(record)
|
|
78
|
-
.filter((key) => record[key] !== undefined)
|
|
79
|
-
.sort()
|
|
80
|
-
.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`)
|
|
81
|
-
.join(',')}}`;
|
|
82
|
-
}
|
|
83
|
-
/** Canonical operations-only fallback for direct adapter use. */
|
|
84
|
-
export function sourceOperationsIntentHash(operations) {
|
|
85
|
-
return createHash('sha256')
|
|
86
|
-
.update(canonicalJson(operations))
|
|
87
|
-
.digest('hex');
|
|
88
|
-
}
|
|
89
|
-
/** Resolve the hash every newly-written customer ledger row must persist. */
|
|
90
|
-
export function sourceChangeIntentHash(change) {
|
|
91
|
-
if (change.echo && !change.intentHash) {
|
|
92
|
-
throw new AbloValidationError('A WAL-correlated source commit requires Ablo intentHash evidence', { code: 'idempotency_conflict' });
|
|
93
|
-
}
|
|
94
|
-
return change.intentHash ?? sourceOperationsIntentHash(change.operations);
|
|
95
|
-
}
|
|
96
|
-
/** Fail closed for changed intent and legacy rows that lack hash evidence. */
|
|
97
|
-
export function assertSourceIdempotencyIntent(cachedHash, requestHash) {
|
|
98
|
-
if (cachedHash !== requestHash) {
|
|
99
|
-
throw new AbloValidationError(cachedHash == null
|
|
100
|
-
? 'The source idempotency row predates intent hashing and cannot be replayed safely'
|
|
101
|
-
: 'The source idempotency key was already used with a different request intent', { code: 'idempotency_conflict' });
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* How long a ledger row stays replayable, as a Postgres interval. New rows are
|
|
106
|
-
* written with `expires_at = now() + this`, so the customer can prune anything
|
|
107
|
-
* past it — the writer can't (it holds no DELETE, by design), so pruning is a
|
|
108
|
-
* job for their own admin/cron: `DELETE FROM ablo_idempotency WHERE expires_at <
|
|
109
|
-
* now()`.
|
|
110
|
-
*
|
|
111
|
-
* This is an ops/UX window, not a safety one: {@link assertSourceIdempotencyRetention}
|
|
112
|
-
* already refuses to replay an expired key (fail-closed), so an expired row can
|
|
113
|
-
* never be safely re-applied whether or not it has been pruned. The window only
|
|
114
|
-
* governs how late a retry can still collect its cached response before it's
|
|
115
|
-
* told to start over. 30 days comfortably covers an offline client's queued
|
|
116
|
-
* commits while keeping the table bounded.
|
|
117
|
-
*/
|
|
118
|
-
export const SOURCE_IDEMPOTENCY_RETENTION = '30 days';
|
|
119
|
-
/**
|
|
120
|
-
* Enforce the retention contract on replay. A row past its `expires_at` is
|
|
121
|
-
* refused (fail-closed) rather than re-applied, so pruning expired rows is
|
|
122
|
-
* always safe. Rows written before the column existed (`infinity`/null) are
|
|
123
|
-
* accepted — they predate bounded retention and never expire.
|
|
124
|
-
*/
|
|
125
|
-
export function assertSourceIdempotencyRetention(expiresAt, now = Date.now()) {
|
|
126
|
-
if (expiresAt == null ||
|
|
127
|
-
expiresAt === 'infinity' ||
|
|
128
|
-
expiresAt === Infinity) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const timestamp = expiresAt instanceof Date
|
|
132
|
-
? expiresAt.getTime()
|
|
133
|
-
: typeof expiresAt === 'number'
|
|
134
|
-
? expiresAt
|
|
135
|
-
: typeof expiresAt === 'string'
|
|
136
|
-
? Date.parse(expiresAt)
|
|
137
|
-
: Number.NaN;
|
|
138
|
-
if (!Number.isFinite(timestamp)) {
|
|
139
|
-
throw new AbloValidationError('The source idempotency retention evidence is invalid', { code: 'idempotency_conflict' });
|
|
140
|
-
}
|
|
141
|
-
if (timestamp <= now) {
|
|
142
|
-
throw new AbloValidationError('The source idempotency key has expired and cannot be executed again safely', { code: 'idempotency_key_expired' });
|
|
143
|
-
}
|
|
144
|
-
}
|
package/dist/source/index.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The entry point for the Data Source API, re-exporting the pieces you need from
|
|
3
|
-
* their individual modules:
|
|
4
|
-
*
|
|
5
|
-
* - `types.ts` — the shared wire and handler types, plus `sourceEventForOperation`
|
|
6
|
-
* - `signing.ts` — request signing and verification
|
|
7
|
-
* - `factory.ts` — the `dataSource()` endpoint factory
|
|
8
|
-
*
|
|
9
|
-
* Import from here; the sibling modules import one another directly.
|
|
10
|
-
*/
|
|
11
|
-
export { sourceEventForOperation, ABLO_POSTGRES_COMMIT_ECHO_PREFIX, ABLO_SOURCE_CLIENT_TX_ID_MAX_LENGTH, ABLO_SOURCE_ECHO_MAX_OPERATIONS, ABLO_SOURCE_ECHO_MAX_PAYLOAD_BYTES, type SourcePrimitive, type SourceWhere, type SourceListQuery, type SourceListPage, type SourceListResult, type SourceRequestContext, type SourceOperation, type SourceDelta, type SourceEvent, type SourceEventForOperationOptions, type SourceCommitResult, type SourceCommitEcho, type SourceCommitEchoOperation, type SourceCommitEchoMarker, type SourceCommitParams, type SourceScope, type SourceEventsResult, type SourceEventsHandler, type SourceAuthorizeContext, type SourceHandlerContext, type SourceModelHandlers, type SourceCommitHandler, type SourceApiKey, type SourceLoadRequest, type SourceListRequest, type SourceCommitRequest, type SourceEventsRequest, type SourceRequest, type SourceResponse, } from './types.js';
|
|
12
|
-
export { ABLO_SOURCE_HEADERS, SourceSignatureError, signAbloSourceRequest, verifyAbloSourceRequest, type SourceSignatureOptions, type SourceSignatureVerificationOptions, type SourceSignatureVerificationResult, } from './signing.js';
|
|
13
|
-
export { dataSource, type DataSourceOptions, } from './factory.js';
|
|
14
|
-
export { createPushQueue, InMemoryPushQueueStorage, STANDARD_WEBHOOKS_RETRY_SCHEDULE, type PushQueue, type PushQueueItem, type PushQueueOptions, type PushQueueStorage, } from './pushQueue.js';
|
|
15
|
-
export { createSourceConnector, DEFAULT_RECONNECT_SCHEDULE, type SourceConnector, type SourceConnectorOptions, type ConnectorWebSocket, type ConnectorWebSocketFactory, type ConnectorStatus, } from './connector.js';
|
|
16
|
-
export { SOURCE_CONNECTOR_PROTOCOL_VERSION, SOURCE_CONNECTOR_WS_PATH, WS_SOURCE_SUBPROTOCOL, sourceConnectorSubprotocols, encodeFrame, decodeFrame, ConnectorProtocolError, connectorFrameSchema, type ConnectorFrame, type RegisterFrame, type ReadyFrame, type RequestFrame, type ResponseFrame, type ErrorFrame, } from './connectorProtocol.js';
|
|
17
|
-
export { type DataSourceAdapter, type MutationAdapter, type AdapterReadRequest, type AdapterCommitResult, type Row as AdapterRow, } from './adapter.js';
|
|
18
|
-
export { operationSchema, operationTypeSchema, sourceCommitEchoSchema, sourceCommitEchoOperationSchema, sourceCommitEchoMarkerSchema, changeSetSchema, outboxEventSchema, eventsPageSchema, migrationSchema, adapterCapabilitiesSchema, type Operation, type ChangeSet, type OutboxEvent, type EventsPage, type Migration, type AdapterCapabilities, type SourceCommitEchoMarkerWire, } from './contract.js';
|
|
19
|
-
export { prismaDataSource, type PrismaLike, type PrismaDataSourceOptions } from './adapters/prisma.js';
|
|
20
|
-
export { adapterTableMigrations, endpointOutboxMigrations, idempotencyLedgerMigrations, } from './migrations.js';
|
|
21
|
-
export { createKyselyMutationAdapter, createKyselyMutationCore, kyselyDataSource, kyselyDirectMutation, kyselyOperationRowId, type KyselyCompiledQuery, type KyselyDeleteBuilder, type KyselyInsertBuilder, type KyselyInsertValuesBuilder, type KyselyLike, type KyselyMutationCore, type KyselyReturningExecutable, type KyselySelectBuilder, type KyselyTransactionBuilder, type KyselyUpdateBuilder, type KyselyUpdateSetBuilder, } from './adapters/kysely.js';
|
|
22
|
-
export { sourceOperationsIntentHash, sourceChangeIntentHash, assertSourceIdempotencyIntent, assertSourceIdempotencyRetention, sourceEchoTransactionIdSchema, encodeSourceEchoTransactionId, decodeSourceEchoTransactionId, type SourceEchoTransactionId, } from './idempotency.js';
|
|
23
|
-
export { ABLO_FOOTPRINT, ABLO_PUBLICATION, ABLO_REPLICATION_SLOT, ABLO_REPLICATION_ROLE, ABLO_WRITE_ROLE, ABLO_IDEMPOTENCY_TABLE, ABLO_OUTBOX_TABLE, REPLICATION_SLOT_NAME, isValidReplicationSlotName, footprintNamesFor, type FootprintArtifact, type FootprintKind, type FootprintNames, type FootprintPlane, } from '../transaction/footprint.js';
|
package/dist/source/index.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The entry point for the Data Source API, re-exporting the pieces you need from
|
|
3
|
-
* their individual modules:
|
|
4
|
-
*
|
|
5
|
-
* - `types.ts` — the shared wire and handler types, plus `sourceEventForOperation`
|
|
6
|
-
* - `signing.ts` — request signing and verification
|
|
7
|
-
* - `factory.ts` — the `dataSource()` endpoint factory
|
|
8
|
-
*
|
|
9
|
-
* Import from here; the sibling modules import one another directly.
|
|
10
|
-
*/
|
|
11
|
-
export { sourceEventForOperation, ABLO_POSTGRES_COMMIT_ECHO_PREFIX, ABLO_SOURCE_CLIENT_TX_ID_MAX_LENGTH, ABLO_SOURCE_ECHO_MAX_OPERATIONS, ABLO_SOURCE_ECHO_MAX_PAYLOAD_BYTES, } from './types.js';
|
|
12
|
-
export { ABLO_SOURCE_HEADERS, SourceSignatureError, signAbloSourceRequest, verifyAbloSourceRequest, } from './signing.js';
|
|
13
|
-
export { dataSource, } from './factory.js';
|
|
14
|
-
export { createPushQueue, InMemoryPushQueueStorage, STANDARD_WEBHOOKS_RETRY_SCHEDULE, } from './pushQueue.js';
|
|
15
|
-
// The reverse-channel connector — an outbound transport for the load, list, and
|
|
16
|
-
// commit leg, and the dial-out counterpart to `createPushQueue`. It lets you serve
|
|
17
|
-
// a Data Source from localhost or a private network that has no public inbound
|
|
18
|
-
// URL. See `connectorProtocol.ts` for the frames it exchanges.
|
|
19
|
-
export { createSourceConnector, DEFAULT_RECONNECT_SCHEDULE, } from './connector.js';
|
|
20
|
-
export { SOURCE_CONNECTOR_PROTOCOL_VERSION, SOURCE_CONNECTOR_WS_PATH, WS_SOURCE_SUBPROTOCOL, sourceConnectorSubprotocols, encodeFrame, decodeFrame, ConnectorProtocolError, connectorFrameSchema, } from './connectorProtocol.js';
|
|
21
|
-
// The Data Source adapter interface and its Zod contract, with per-ORM implementations.
|
|
22
|
-
export {} from './adapter.js';
|
|
23
|
-
export { operationSchema, operationTypeSchema, sourceCommitEchoSchema, sourceCommitEchoOperationSchema, sourceCommitEchoMarkerSchema, changeSetSchema, outboxEventSchema, eventsPageSchema, migrationSchema, adapterCapabilitiesSchema, } from './contract.js';
|
|
24
|
-
export { prismaDataSource } from './adapters/prisma.js';
|
|
25
|
-
export { adapterTableMigrations, endpointOutboxMigrations, idempotencyLedgerMigrations, } from './migrations.js';
|
|
26
|
-
export { createKyselyMutationAdapter, createKyselyMutationCore, kyselyDataSource, kyselyDirectMutation, kyselyOperationRowId, } from './adapters/kysely.js';
|
|
27
|
-
export { sourceOperationsIntentHash, sourceChangeIntentHash, assertSourceIdempotencyIntent, assertSourceIdempotencyRetention, sourceEchoTransactionIdSchema, encodeSourceEchoTransactionId, decodeSourceEchoTransactionId, } from './idempotency.js';
|
|
28
|
-
// What Ablo leaves inside a customer's database, declared once — read by the
|
|
29
|
-
// setup SQL, the replication runtime, and the audit that reports it back.
|
|
30
|
-
export { ABLO_FOOTPRINT, ABLO_PUBLICATION, ABLO_REPLICATION_SLOT, ABLO_REPLICATION_ROLE, ABLO_WRITE_ROLE, ABLO_IDEMPOTENCY_TABLE, ABLO_OUTBOX_TABLE, REPLICATION_SLOT_NAME, isValidReplicationSlotName, footprintNamesFor, } from '../transaction/footprint.js';
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The table-creation SQL every ORM adapter ships for its own infrastructure
|
|
3
|
-
* tables: `ablo_idempotency`, whose legacy-named `client_tx_id` column stores the
|
|
4
|
-
* scoped server correlation, and (for endpoint wrappers only) `ablo_outbox`, the
|
|
5
|
-
* transactional outbox the `events()` feed reads. Direct wrappers install only
|
|
6
|
-
* the ledger migration because WAL is their authoritative feed.
|
|
7
|
-
*
|
|
8
|
-
* These are infrastructure tables, not model tables, and they exist only on your
|
|
9
|
-
* own database when you run a Data Source. Ablo's hosted storage does not use them;
|
|
10
|
-
* it records changes in its own `sync_deltas` log instead.
|
|
11
|
-
*/
|
|
12
|
-
import type { Migration } from './contract.js';
|
|
13
|
-
/** The idempotency ledger shared by direct and endpoint mutation wrappers. New
|
|
14
|
-
* rows carry a bounded `expires_at` (set by the adapter at write time) so the
|
|
15
|
-
* customer can prune them; the `infinity` column default is only a fallback for
|
|
16
|
-
* a row inserted without one. */
|
|
17
|
-
export declare function idempotencyLedgerMigrations(): readonly Migration[];
|
|
18
|
-
/** Endpoint-only transactional outbox and its correlation columns. */
|
|
19
|
-
export declare function endpointOutboxMigrations(): readonly Migration[];
|
|
20
|
-
/** Full endpoint adapter migrations (ledger + outbox). */
|
|
21
|
-
export declare function adapterTableMigrations(): readonly Migration[];
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The table-creation SQL every ORM adapter ships for its own infrastructure
|
|
3
|
-
* tables: `ablo_idempotency`, whose legacy-named `client_tx_id` column stores the
|
|
4
|
-
* scoped server correlation, and (for endpoint wrappers only) `ablo_outbox`, the
|
|
5
|
-
* transactional outbox the `events()` feed reads. Direct wrappers install only
|
|
6
|
-
* the ledger migration because WAL is their authoritative feed.
|
|
7
|
-
*
|
|
8
|
-
* These are infrastructure tables, not model tables, and they exist only on your
|
|
9
|
-
* own database when you run a Data Source. Ablo's hosted storage does not use them;
|
|
10
|
-
* it records changes in its own `sync_deltas` log instead.
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* Add a column to `ablo_idempotency` only when it is genuinely missing.
|
|
14
|
-
*
|
|
15
|
-
* `ADD COLUMN IF NOT EXISTS` performs its ownership check before the existence
|
|
16
|
-
* short-circuit, so on a ledger owned by another role the no-op re-run still
|
|
17
|
-
* errors "must be owner of table ablo_idempotency" — the setup's re-run promise
|
|
18
|
-
* breaks. `pg_attribute` is readable regardless of table ownership, so this DO
|
|
19
|
-
* block resolves the ledger through the search path and runs the `ALTER` only
|
|
20
|
-
* when the column is absent — a true no-op on a table that already has it.
|
|
21
|
-
*/
|
|
22
|
-
function addColumnIfAbsent(column, definition) {
|
|
23
|
-
return `DO $$
|
|
24
|
-
DECLARE ledger regclass := to_regclass('ablo_idempotency');
|
|
25
|
-
BEGIN
|
|
26
|
-
IF ledger IS NOT NULL AND NOT EXISTS (
|
|
27
|
-
SELECT 1 FROM pg_attribute
|
|
28
|
-
WHERE attrelid = ledger AND attname = '${column}' AND attnum > 0 AND NOT attisdropped
|
|
29
|
-
) THEN
|
|
30
|
-
ALTER TABLE ablo_idempotency ADD COLUMN ${column} ${definition};
|
|
31
|
-
END IF;
|
|
32
|
-
END $$;`;
|
|
33
|
-
}
|
|
34
|
-
/** The idempotency ledger shared by direct and endpoint mutation wrappers. New
|
|
35
|
-
* rows carry a bounded `expires_at` (set by the adapter at write time) so the
|
|
36
|
-
* customer can prune them; the `infinity` column default is only a fallback for
|
|
37
|
-
* a row inserted without one. */
|
|
38
|
-
export function idempotencyLedgerMigrations() {
|
|
39
|
-
return [
|
|
40
|
-
{
|
|
41
|
-
name: 'ablo_idempotency',
|
|
42
|
-
up: `CREATE TABLE IF NOT EXISTS ablo_idempotency (
|
|
43
|
-
client_tx_id TEXT PRIMARY KEY,
|
|
44
|
-
response JSONB NOT NULL,
|
|
45
|
-
request_hash TEXT,
|
|
46
|
-
expires_at TIMESTAMPTZ NOT NULL DEFAULT 'infinity',
|
|
47
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
48
|
-
);`,
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: 'ablo_idempotency_request_hash',
|
|
52
|
-
// Nullable only for rows created by older adapter versions. New writes
|
|
53
|
-
// always populate it; replaying a legacy NULL row fails closed because
|
|
54
|
-
// the adapter cannot prove that the intent matches.
|
|
55
|
-
//
|
|
56
|
-
// The column already exists on any current table (the CREATE above
|
|
57
|
-
// includes it), so this only matters when upgrading a pre-existing
|
|
58
|
-
// ledger. `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` checks ownership
|
|
59
|
-
// BEFORE it evaluates IF NOT EXISTS, so on a ledger that predates the
|
|
60
|
-
// setup — owned by another role — the no-op still errors "must be owner".
|
|
61
|
-
// Guard on the catalog (readable regardless of ownership) so the ALTER
|
|
62
|
-
// runs only when the column is genuinely absent, keeping re-runs safe.
|
|
63
|
-
up: addColumnIfAbsent('request_hash', 'TEXT'),
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: 'ablo_idempotency_permanent_retention',
|
|
67
|
-
up: addColumnIfAbsent('expires_at', `TIMESTAMPTZ NOT NULL DEFAULT 'infinity'`),
|
|
68
|
-
},
|
|
69
|
-
];
|
|
70
|
-
}
|
|
71
|
-
/** Endpoint-only transactional outbox and its correlation columns. */
|
|
72
|
-
export function endpointOutboxMigrations() {
|
|
73
|
-
return [
|
|
74
|
-
{
|
|
75
|
-
name: 'ablo_outbox',
|
|
76
|
-
up: `CREATE TABLE IF NOT EXISTS ablo_outbox (
|
|
77
|
-
cursor BIGSERIAL PRIMARY KEY,
|
|
78
|
-
id TEXT NOT NULL UNIQUE,
|
|
79
|
-
model TEXT NOT NULL,
|
|
80
|
-
entity_id TEXT NOT NULL,
|
|
81
|
-
type TEXT NOT NULL,
|
|
82
|
-
data JSONB,
|
|
83
|
-
organization_id TEXT,
|
|
84
|
-
client_tx_id TEXT,
|
|
85
|
-
correlation_id TEXT,
|
|
86
|
-
transaction_id TEXT,
|
|
87
|
-
occurred_at BIGINT,
|
|
88
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
89
|
-
);`,
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: 'ablo_outbox_correlation',
|
|
93
|
-
up: `ALTER TABLE ablo_outbox
|
|
94
|
-
ADD COLUMN IF NOT EXISTS correlation_id TEXT;
|
|
95
|
-
ALTER TABLE ablo_outbox
|
|
96
|
-
ADD COLUMN IF NOT EXISTS transaction_id TEXT;`,
|
|
97
|
-
},
|
|
98
|
-
];
|
|
99
|
-
}
|
|
100
|
-
/** Full endpoint adapter migrations (ledger + outbox). */
|
|
101
|
-
export function adapterTableMigrations() {
|
|
102
|
-
return [...idempotencyLedgerMigrations(), ...endpointOutboxMigrations()];
|
|
103
|
-
}
|