@abloatai/transaction 0.56.0 → 0.58.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/CONVENTIONS.md +54 -10
- package/README.md +3 -1
- package/dist/ai-sdk/modelTools.d.ts +3 -3
- package/dist/ai-sdk/modelTools.d.ts.map +1 -1
- package/dist/ai-sdk/modelTools.js +1 -1
- package/dist/ai-sdk/modelTools.js.map +1 -1
- package/dist/ai-sdk/updateTool.d.ts +5 -7
- package/dist/ai-sdk/updateTool.d.ts.map +1 -1
- package/dist/ai-sdk/updateTool.js +3 -5
- package/dist/ai-sdk/updateTool.js.map +1 -1
- package/dist/auth/capability.d.ts +5 -0
- package/dist/auth/capability.d.ts.map +1 -1
- package/dist/auth/capability.js +5 -0
- package/dist/auth/capability.js.map +1 -1
- package/dist/auth/capabilityLifecycle.d.ts +1 -1
- package/dist/auth/capabilityLifecycle.d.ts.map +1 -1
- package/dist/auth/credentialPolicy.d.ts +1 -1
- package/dist/auth/credentialPolicy.d.ts.map +1 -1
- package/dist/auth/identity.d.ts +3 -3
- package/dist/auth/identity.d.ts.map +1 -1
- package/dist/auth/identity.js +5 -5
- package/dist/auth/identity.js.map +1 -1
- package/dist/auth/index.d.ts +4 -208
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +4 -330
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/runtime.d.ts +218 -0
- package/dist/auth/runtime.d.ts.map +1 -0
- package/dist/auth/runtime.js +336 -0
- package/dist/auth/runtime.js.map +1 -0
- package/dist/auth/sessionMint.d.ts +1 -1
- package/dist/auth/sessionMint.d.ts.map +1 -1
- package/dist/auth/sessionMint.js +2 -1
- package/dist/auth/sessionMint.js.map +1 -1
- package/dist/branches.d.ts +25 -21
- package/dist/branches.d.ts.map +1 -1
- package/dist/branches.js +3 -0
- package/dist/branches.js.map +1 -1
- package/dist/{coordination/awaitClaimGrant.d.ts → claims/awaitGrant.d.ts} +1 -1
- package/dist/claims/awaitGrant.d.ts.map +1 -0
- package/dist/{coordination/awaitClaimGrant.js → claims/awaitGrant.js} +4 -4
- package/dist/claims/awaitGrant.js.map +1 -0
- package/dist/{wire/claims.d.ts → claims/contract.d.ts} +1 -1
- package/dist/claims/contract.d.ts.map +1 -0
- package/dist/{wire/claims.js → claims/contract.js} +2 -2
- package/dist/claims/contract.js.map +1 -0
- package/dist/{wire/claimEvent.d.ts → claims/eventContract.d.ts} +1 -1
- package/dist/claims/eventContract.d.ts.map +1 -0
- package/dist/{wire/claimEvent.js → claims/eventContract.js} +1 -1
- package/dist/claims/eventContract.js.map +1 -0
- package/dist/{coordination → claims}/events.d.ts +7 -11
- package/dist/claims/events.d.ts.map +1 -0
- package/dist/claims/events.js +8 -0
- package/dist/claims/events.js.map +1 -0
- package/dist/{coordination/claimHeartbeatLoop.d.ts → claims/heartbeat.d.ts} +1 -1
- package/dist/claims/heartbeat.d.ts.map +1 -0
- package/dist/{coordination/claimHeartbeatLoop.js → claims/heartbeat.js} +1 -1
- package/dist/claims/heartbeat.js.map +1 -0
- package/dist/claims/index.d.ts +17 -0
- package/dist/claims/index.d.ts.map +1 -0
- package/dist/claims/index.js +16 -0
- package/dist/claims/index.js.map +1 -0
- package/dist/claims/lifetime.d.ts +26 -0
- package/dist/claims/lifetime.d.ts.map +1 -0
- package/dist/claims/lifetime.js +62 -0
- package/dist/claims/lifetime.js.map +1 -0
- package/dist/{coordination → claims}/locator.d.ts +1 -1
- package/dist/claims/locator.d.ts.map +1 -0
- package/dist/{coordination → claims}/locator.js +2 -2
- package/dist/claims/locator.js.map +1 -0
- package/dist/{coordination/claimMeta.d.ts → claims/meta.d.ts} +1 -1
- package/dist/claims/meta.d.ts.map +1 -0
- package/dist/{coordination/claimMeta.js → claims/meta.js} +1 -1
- package/dist/claims/meta.js.map +1 -0
- package/dist/claims/routes.d.ts +59 -0
- package/dist/claims/routes.d.ts.map +1 -0
- package/dist/claims/routes.js +69 -0
- package/dist/claims/routes.js.map +1 -0
- package/dist/claims/targetConflict.d.ts.map +1 -0
- package/dist/claims/targetConflict.js.map +1 -0
- package/dist/{coordination → claims}/trace.d.ts +2 -2
- package/dist/claims/trace.d.ts.map +1 -0
- package/dist/{coordination → claims}/trace.js +5 -5
- package/dist/claims/trace.js.map +1 -0
- package/dist/{ablo.d.ts → client/ablo.d.ts} +6 -15
- package/dist/client/ablo.d.ts.map +1 -0
- package/dist/{ablo.js → client/ablo.js} +2 -2
- package/dist/client/ablo.js.map +1 -0
- package/dist/{transactionLayer.d.ts → client/contract.d.ts} +12 -14
- package/dist/client/contract.d.ts.map +1 -0
- package/dist/{transactionLayer.js → client/contract.js} +4 -5
- package/dist/client/contract.js.map +1 -0
- package/dist/{headlessClient.d.ts → client/headless.d.ts} +4 -4
- package/dist/client/headless.d.ts.map +1 -0
- package/dist/{headlessClient.js → client/headless.js} +8 -10
- package/dist/{headlessClient.js.map → client/headless.js.map} +1 -1
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +11 -0
- package/dist/client/index.js.map +1 -0
- package/dist/{resources → client/resources}/functionalUpdate.d.ts +4 -4
- package/dist/client/resources/functionalUpdate.d.ts.map +1 -0
- package/dist/{resources → client/resources}/functionalUpdate.js +3 -3
- package/dist/client/resources/functionalUpdate.js.map +1 -0
- package/dist/{resources → client/resources}/httpResources.d.ts +92 -77
- package/dist/client/resources/httpResources.d.ts.map +1 -0
- package/dist/client/resources/httpResources.js +94 -0
- package/dist/client/resources/httpResources.js.map +1 -0
- package/dist/client/resources/modelCreate.d.ts +21 -0
- package/dist/client/resources/modelCreate.d.ts.map +1 -0
- package/dist/client/resources/modelCreate.js +49 -0
- package/dist/client/resources/modelCreate.js.map +1 -0
- package/dist/{resources → client/resources}/modelOperations.d.ts +57 -51
- package/dist/client/resources/modelOperations.d.ts.map +1 -0
- package/dist/{resources → client/resources}/modelOperations.js +1 -1
- package/dist/client/resources/modelOperations.js.map +1 -0
- package/dist/{resources → client/resources}/mutationOptions.d.ts +4 -17
- package/dist/client/resources/mutationOptions.d.ts.map +1 -0
- package/dist/client/resources/mutationOptions.js.map +1 -0
- package/dist/client/resources/where.d.ts.map +1 -0
- package/dist/{resources → client/resources}/where.js +1 -1
- package/dist/client/resources/where.js.map +1 -0
- package/dist/{resources → client/resources}/writeOptionsSchema.d.ts +16 -35
- package/dist/client/resources/writeOptionsSchema.d.ts.map +1 -0
- package/dist/{resources → client/resources}/writeOptionsSchema.js +25 -18
- package/dist/client/resources/writeOptionsSchema.js.map +1 -0
- package/dist/{transactions → commit}/confirmation/commitEnvelope.d.ts +1 -37
- package/dist/commit/confirmation/commitEnvelope.d.ts.map +1 -0
- package/dist/{transactions → commit}/confirmation/commitEnvelope.js +2 -7
- package/dist/commit/confirmation/commitEnvelope.js.map +1 -0
- package/dist/commit/confirmation/httpCommitEnvelope.d.ts.map +1 -0
- package/dist/{transactions → commit}/confirmation/httpCommitEnvelope.js +1 -1
- package/dist/commit/confirmation/httpCommitEnvelope.js.map +1 -0
- package/dist/commit/confirmation/idempotencyKey.d.ts.map +1 -0
- package/dist/commit/confirmation/idempotencyKey.js.map +1 -0
- package/dist/{transactions → commit}/confirmation/pendingWrite.d.ts +2 -33
- package/dist/commit/confirmation/pendingWrite.d.ts.map +1 -0
- package/dist/{transactions → commit}/confirmation/pendingWrite.js +1 -1
- package/dist/commit/confirmation/pendingWrite.js.map +1 -0
- package/dist/commit/contract.d.ts +1404 -0
- package/dist/commit/contract.d.ts.map +1 -0
- package/dist/{wire/commit.js → commit/contract.js} +26 -21
- package/dist/commit/contract.js.map +1 -0
- package/dist/{durableWrites.d.ts → commit/durableWrites.d.ts} +6 -6
- package/dist/commit/durableWrites.d.ts.map +1 -0
- package/dist/{durableWrites.js → commit/durableWrites.js} +5 -5
- package/dist/commit/durableWrites.js.map +1 -0
- package/dist/commit/httpRequest.d.ts +45 -0
- package/dist/commit/httpRequest.d.ts.map +1 -0
- package/dist/commit/httpRequest.js +66 -0
- package/dist/commit/httpRequest.js.map +1 -0
- package/dist/commit/index.d.ts +17 -0
- package/dist/commit/index.d.ts.map +1 -0
- package/dist/commit/index.js +17 -0
- package/dist/commit/index.js.map +1 -0
- package/dist/{readSetContext.d.ts → commit/readSetContext.d.ts} +7 -15
- package/dist/commit/readSetContext.d.ts.map +1 -0
- package/dist/{readSetContext.js → commit/readSetContext.js} +18 -28
- package/dist/commit/readSetContext.js.map +1 -0
- package/dist/{commitRecordRuntime.d.ts → commit/recordRuntime.d.ts} +3 -5
- package/dist/commit/recordRuntime.d.ts.map +1 -0
- package/dist/{commitRecordRuntime.js → commit/recordRuntime.js} +13 -54
- package/dist/commit/recordRuntime.js.map +1 -0
- package/dist/coordination/index.d.ts +6 -8
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +3 -9
- package/dist/coordination/index.js.map +1 -1
- package/dist/coordination/schema.d.ts +11 -466
- package/dist/coordination/schema.d.ts.map +1 -1
- package/dist/coordination/schema.js +13 -265
- package/dist/coordination/schema.js.map +1 -1
- package/dist/errorCodes.d.ts +16 -9
- package/dist/errorCodes.d.ts.map +1 -1
- package/dist/errorCodes.js +14 -6
- package/dist/errorCodes.js.map +1 -1
- package/dist/errorObservation.d.ts +2 -2
- package/dist/errors.d.ts +3 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +27 -11
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/internal/read-set.d.ts +3 -3
- package/dist/internal/read-set.d.ts.map +1 -1
- package/dist/internal/read-set.js +2 -2
- package/dist/internal/read-set.js.map +1 -1
- package/dist/observability.d.ts +4 -4
- package/dist/observability.d.ts.map +1 -1
- package/dist/observability.js +2 -2
- package/dist/{wire/delta.d.ts → observation/contract.d.ts} +8 -8
- package/dist/observation/contract.d.ts.map +1 -0
- package/dist/{wire/delta.js → observation/contract.js} +3 -3
- package/dist/observation/contract.js.map +1 -0
- package/dist/{wire/feedCursor.d.ts → observation/cursor.d.ts} +1 -1
- package/dist/observation/cursor.d.ts.map +1 -0
- package/dist/{wire/feedCursor.js → observation/cursor.js} +1 -1
- package/dist/observation/cursor.js.map +1 -0
- package/dist/{wire/deltaDelivery.d.ts → observation/deliveryContract.d.ts} +1 -1
- package/dist/observation/deliveryContract.d.ts.map +1 -0
- package/dist/{wire/deltaDelivery.js → observation/deliveryContract.js} +1 -1
- package/dist/observation/deliveryContract.js.map +1 -0
- package/dist/{wire/feedEvent.d.ts → observation/feedContract.d.ts} +10 -10
- package/dist/observation/feedContract.d.ts.map +1 -0
- package/dist/{wire/feedEvent.js → observation/feedContract.js} +4 -4
- package/dist/observation/feedContract.js.map +1 -0
- package/dist/observation/httpFeed.d.ts +4 -0
- package/dist/observation/httpFeed.d.ts.map +1 -0
- package/dist/{transport → observation}/httpFeed.js +1 -1
- package/dist/{transport → observation}/httpFeed.js.map +1 -1
- package/dist/observation/index.d.ts +13 -0
- package/dist/observation/index.d.ts.map +1 -0
- package/dist/observation/index.js +13 -0
- package/dist/observation/index.js.map +1 -0
- package/dist/{log → observation/persistence}/syncDeltaRow.d.ts +8 -8
- package/dist/observation/persistence/syncDeltaRow.d.ts.map +1 -0
- package/dist/{log → observation/persistence}/syncDeltaRow.js +4 -4
- package/dist/observation/persistence/syncDeltaRow.js.map +1 -0
- package/dist/pricing.d.ts +20 -12
- package/dist/pricing.d.ts.map +1 -1
- package/dist/pricing.js +46 -26
- package/dist/pricing.js.map +1 -1
- package/dist/schema/audit.d.ts +15 -0
- package/dist/schema/audit.d.ts.map +1 -0
- package/dist/schema/audit.js +90 -0
- package/dist/schema/audit.js.map +1 -0
- package/dist/schema/ddl.d.ts.map +1 -1
- package/dist/schema/ddl.js +68 -1
- package/dist/schema/ddl.js.map +1 -1
- package/dist/schema/index.d.ts +7 -6
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +6 -7
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/model.d.ts +14 -27
- package/dist/schema/model.d.ts.map +1 -1
- package/dist/schema/model.js +2 -2
- package/dist/schema/model.js.map +1 -1
- package/dist/schema/openapi.d.ts.map +1 -1
- package/dist/schema/openapi.js +149 -8
- package/dist/schema/openapi.js.map +1 -1
- package/dist/schema/roles.d.ts +27 -0
- package/dist/schema/roles.d.ts.map +1 -1
- package/dist/schema/roles.js +40 -0
- package/dist/schema/roles.js.map +1 -1
- package/dist/schema/schema.d.ts +34 -7
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +39 -3
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/serialize.d.ts +5 -5
- package/dist/schema/serialize.d.ts.map +1 -1
- package/dist/schema/serialize.js +5 -5
- package/dist/schema/serialize.js.map +1 -1
- package/dist/schema/subject.d.ts +18 -0
- package/dist/schema/subject.d.ts.map +1 -0
- package/dist/schema/subject.js +27 -0
- package/dist/schema/subject.js.map +1 -0
- package/dist/schema/tenancy.d.ts +1 -1
- package/dist/server/adapter.d.ts +3 -1
- package/dist/server/adapter.d.ts.map +1 -1
- package/dist/server/commit.d.ts +6 -14
- package/dist/server/commit.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/readConfig.d.ts +3 -0
- package/dist/server/readConfig.d.ts.map +1 -1
- package/dist/server/readConfig.js +0 -21
- package/dist/server/readConfig.js.map +1 -1
- package/dist/server/storageMode.d.ts +1 -1
- package/dist/source/{adapter.d.ts → adapters/adapter.d.ts} +10 -4
- package/dist/source/adapters/adapter.d.ts.map +1 -0
- package/dist/source/adapters/adapter.js.map +1 -0
- package/dist/source/adapters/adapterFactory.d.ts.map +1 -0
- package/dist/source/{adapterFactory.js → adapters/adapterFactory.js} +1 -1
- package/dist/source/adapters/adapterFactory.js.map +1 -0
- package/dist/source/adapters/adapterProfile.d.ts.map +1 -0
- package/dist/source/adapters/adapterProfile.js.map +1 -0
- package/dist/source/{conformance.d.ts → adapters/conformance.d.ts} +1 -1
- package/dist/source/adapters/conformance.d.ts.map +1 -0
- package/dist/source/{conformance.js → adapters/conformance.js} +1 -1
- package/dist/source/adapters/conformance.js.map +1 -0
- package/dist/source/{contract.d.ts → adapters/contract.d.ts} +20 -75
- package/dist/source/adapters/contract.d.ts.map +1 -0
- package/dist/source/{contract.js → adapters/contract.js} +20 -55
- package/dist/source/adapters/contract.js.map +1 -0
- package/dist/source/adapters/drizzle.d.ts +1 -1
- package/dist/source/adapters/drizzle.d.ts.map +1 -1
- package/dist/source/adapters/drizzle.js +54 -25
- package/dist/source/adapters/drizzle.js.map +1 -1
- package/dist/source/adapters/idempotency.d.ts.map +1 -0
- package/dist/source/{idempotency.js → adapters/idempotency.js} +2 -2
- package/dist/source/adapters/idempotency.js.map +1 -0
- package/dist/source/adapters/index.d.ts +21 -0
- package/dist/source/adapters/index.d.ts.map +1 -0
- package/dist/source/adapters/index.js +21 -0
- package/dist/source/adapters/index.js.map +1 -0
- package/dist/source/adapters/kysely.d.ts +3 -1
- package/dist/source/adapters/kysely.d.ts.map +1 -1
- package/dist/source/adapters/kysely.js +49 -23
- package/dist/source/adapters/kysely.js.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.d.ts +6 -3
- package/dist/source/adapters/kyselyMutationCore.d.ts.map +1 -1
- package/dist/source/adapters/kyselyMutationCore.js +17 -8
- package/dist/source/adapters/kyselyMutationCore.js.map +1 -1
- package/dist/source/adapters/memory.d.ts +3 -3
- package/dist/source/adapters/memory.d.ts.map +1 -1
- package/dist/source/adapters/memory.js +20 -7
- package/dist/source/adapters/memory.js.map +1 -1
- package/dist/source/adapters/migration.d.ts +8 -0
- package/dist/source/adapters/migration.d.ts.map +1 -0
- package/dist/source/adapters/migration.js +9 -0
- package/dist/source/adapters/migration.js.map +1 -0
- package/dist/source/{migrations.d.ts → adapters/migrations.d.ts} +3 -4
- package/dist/source/adapters/migrations.d.ts.map +1 -0
- package/dist/source/{migrations.js → adapters/migrations.js} +4 -31
- package/dist/source/adapters/migrations.js.map +1 -0
- package/dist/source/adapters/prisma.d.ts +1 -1
- package/dist/source/adapters/prisma.d.ts.map +1 -1
- package/dist/source/adapters/prisma.js +75 -30
- package/dist/source/adapters/prisma.js.map +1 -1
- package/dist/source/adapters/subjectAuthorization.d.ts +16 -0
- package/dist/source/adapters/subjectAuthorization.d.ts.map +1 -0
- package/dist/source/adapters/subjectAuthorization.js +126 -0
- package/dist/source/adapters/subjectAuthorization.js.map +1 -0
- package/dist/source/{connector.d.ts → connector/client.d.ts} +6 -1
- package/dist/source/connector/client.d.ts.map +1 -0
- package/dist/source/{connector.js → connector/client.js} +28 -11
- package/dist/source/connector/client.js.map +1 -0
- package/dist/source/connector/index.d.ts +4 -0
- package/dist/source/connector/index.d.ts.map +1 -0
- package/dist/source/connector/index.js +4 -0
- package/dist/source/connector/index.js.map +1 -0
- package/dist/source/{connectorProtocol.d.ts → connector/protocol.d.ts} +8 -1
- package/dist/source/connector/protocol.d.ts.map +1 -0
- package/dist/source/{connectorProtocol.js → connector/protocol.js} +10 -3
- package/dist/source/connector/protocol.js.map +1 -0
- package/dist/source/delivery/index.d.ts +3 -0
- package/dist/source/delivery/index.d.ts.map +1 -0
- package/dist/source/delivery/index.js +3 -0
- package/dist/source/delivery/index.js.map +1 -0
- package/dist/source/{pushQueue.d.ts → delivery/pushQueue.d.ts} +1 -1
- package/dist/source/delivery/pushQueue.d.ts.map +1 -0
- package/dist/source/{pushQueue.js → delivery/pushQueue.js} +1 -1
- package/dist/source/delivery/pushQueue.js.map +1 -0
- package/dist/source/{factory.d.ts → endpoint/factory.d.ts} +9 -3
- package/dist/source/endpoint/factory.d.ts.map +1 -0
- package/dist/source/{factory.js → endpoint/factory.js} +122 -6
- package/dist/source/endpoint/factory.js.map +1 -0
- package/dist/source/endpoint/index.d.ts +5 -0
- package/dist/source/endpoint/index.d.ts.map +1 -0
- package/dist/source/endpoint/index.js +5 -0
- package/dist/source/endpoint/index.js.map +1 -0
- package/dist/source/{next.d.ts → endpoint/next.d.ts} +2 -2
- package/dist/source/endpoint/next.d.ts.map +1 -0
- package/dist/source/{next.js → endpoint/next.js} +1 -1
- package/dist/source/endpoint/next.js.map +1 -0
- package/dist/source/{signing.d.ts → endpoint/signing.d.ts} +1 -1
- package/dist/source/endpoint/signing.d.ts.map +1 -0
- package/dist/source/{signing.js → endpoint/signing.js} +1 -1
- package/dist/source/endpoint/signing.js.map +1 -0
- package/dist/source/index.d.ts +15 -12
- package/dist/source/index.d.ts.map +1 -1
- package/dist/source/index.js +13 -10
- package/dist/source/index.js.map +1 -1
- package/dist/source/outbox/contract.d.ts +50 -0
- package/dist/source/outbox/contract.d.ts.map +1 -0
- package/dist/source/outbox/contract.js +50 -0
- package/dist/source/outbox/contract.js.map +1 -0
- package/dist/source/outbox/envelope.d.ts +9 -0
- package/dist/source/outbox/envelope.d.ts.map +1 -0
- package/dist/source/outbox/envelope.js +36 -0
- package/dist/source/outbox/envelope.js.map +1 -0
- package/dist/source/outbox/index.d.ts +11 -0
- package/dist/source/outbox/index.d.ts.map +1 -0
- package/dist/source/outbox/index.js +11 -0
- package/dist/source/outbox/index.js.map +1 -0
- package/dist/source/outbox/migrations.d.ts +4 -0
- package/dist/source/outbox/migrations.d.ts.map +1 -0
- package/dist/source/outbox/migrations.js +67 -0
- package/dist/source/outbox/migrations.js.map +1 -0
- package/dist/source/outbox/retention.d.ts +3 -0
- package/dist/source/outbox/retention.d.ts.map +1 -0
- package/dist/source/outbox/retention.js +3 -0
- package/dist/source/outbox/retention.js.map +1 -0
- package/dist/source/types.d.ts +59 -10
- package/dist/source/types.d.ts.map +1 -1
- package/dist/source/types.js +2 -0
- package/dist/source/types.js.map +1 -1
- package/dist/syncLog/contract.d.ts +19 -8
- package/dist/syncLog/contract.d.ts.map +1 -1
- package/dist/syncLog/contract.js +19 -6
- package/dist/syncLog/contract.js.map +1 -1
- package/dist/testing/fixtures/httpResponses.d.ts +6 -0
- package/dist/testing/fixtures/httpResponses.d.ts.map +1 -1
- package/dist/testing/fixtures/httpResponses.js +1 -0
- package/dist/testing/fixtures/httpResponses.js.map +1 -1
- package/dist/transport/{credentialLifecycle.d.ts → connection/credentialLifecycle.d.ts} +3 -3
- package/dist/transport/connection/credentialLifecycle.d.ts.map +1 -0
- package/dist/transport/{credentialLifecycle.js → connection/credentialLifecycle.js} +2 -2
- package/dist/transport/connection/credentialLifecycle.js.map +1 -0
- package/dist/transport/connection/index.d.ts +5 -0
- package/dist/transport/connection/index.d.ts.map +1 -0
- package/dist/transport/connection/index.js +5 -0
- package/dist/transport/connection/index.js.map +1 -0
- package/dist/transport/{connectionManager.d.ts → connection/manager.d.ts} +13 -5
- package/dist/transport/connection/manager.d.ts.map +1 -0
- package/dist/transport/{connectionManager.js → connection/manager.js} +6 -4
- package/dist/transport/connection/manager.js.map +1 -0
- package/dist/transport/{networkProbe.d.ts → connection/networkProbe.d.ts} +2 -2
- package/dist/transport/connection/networkProbe.d.ts.map +1 -0
- package/dist/transport/{networkProbe.js → connection/networkProbe.js} +4 -4
- package/dist/transport/connection/networkProbe.js.map +1 -0
- package/dist/transport/{httpClient.d.ts → http/client.d.ts} +32 -44
- package/dist/transport/http/client.d.ts.map +1 -0
- package/dist/transport/{httpClient.js → http/client.js} +96 -105
- package/dist/transport/http/client.js.map +1 -0
- package/dist/transport/http/helpers.d.ts +10 -0
- package/dist/transport/http/helpers.d.ts.map +1 -0
- package/dist/transport/http/helpers.js +46 -0
- package/dist/transport/http/helpers.js.map +1 -0
- package/dist/transport/http/index.d.ts +6 -0
- package/dist/transport/http/index.d.ts.map +1 -0
- package/dist/transport/http/index.js +6 -0
- package/dist/transport/http/index.js.map +1 -0
- package/dist/transport/{httpOptions.d.ts → http/options.d.ts} +7 -7
- package/dist/transport/{httpOptions.d.ts.map → http/options.d.ts.map} +1 -1
- package/dist/transport/{httpOptions.js → http/options.js} +1 -1
- package/dist/transport/http/options.js.map +1 -0
- package/dist/transport/http/subscription.d.ts +16 -0
- package/dist/transport/http/subscription.d.ts.map +1 -0
- package/dist/transport/http/subscription.js +146 -0
- package/dist/transport/http/subscription.js.map +1 -0
- package/dist/transport/{httpTransport.d.ts → http/transport.d.ts} +9 -6
- package/dist/transport/http/transport.d.ts.map +1 -0
- package/dist/transport/{httpTransport.js → http/transport.js} +153 -188
- package/dist/transport/http/transport.js.map +1 -0
- package/dist/transport/index.d.ts +8 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +8 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/{commitFrames.d.ts → websocket/commitFrames.d.ts} +8 -20
- package/dist/transport/websocket/commitFrames.d.ts.map +1 -0
- package/dist/transport/{commitFrames.js → websocket/commitFrames.js} +6 -25
- package/dist/transport/websocket/commitFrames.js.map +1 -0
- package/dist/transport/{wsFrameHandlers.d.ts → websocket/frameHandlers.d.ts} +5 -5
- package/dist/transport/websocket/frameHandlers.d.ts.map +1 -0
- package/dist/transport/{wsFrameHandlers.js → websocket/frameHandlers.js} +10 -51
- package/dist/transport/websocket/frameHandlers.js.map +1 -0
- package/dist/transport/{heartbeat.d.ts → websocket/heartbeat.d.ts} +1 -1
- package/dist/transport/websocket/heartbeat.d.ts.map +1 -0
- package/dist/transport/{heartbeat.js → websocket/heartbeat.js} +2 -2
- package/dist/transport/websocket/heartbeat.js.map +1 -0
- package/dist/transport/websocket/index.d.ts +6 -0
- package/dist/transport/websocket/index.d.ts.map +1 -0
- package/dist/transport/websocket/index.js +6 -0
- package/dist/transport/websocket/index.js.map +1 -0
- package/dist/transport/{wsTransport.d.ts → websocket/transport.d.ts} +13 -25
- package/dist/transport/websocket/transport.d.ts.map +1 -0
- package/dist/transport/{wsTransport.js → websocket/transport.js} +14 -14
- package/dist/transport/websocket/transport.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/streams.d.ts +8 -48
- package/dist/types/streams.d.ts.map +1 -1
- package/dist/types/streams.js +2 -2
- package/dist/wire/accountResponses.d.ts +4 -72
- package/dist/wire/accountResponses.d.ts.map +1 -1
- package/dist/wire/accountResponses.js +2 -10
- package/dist/wire/accountResponses.js.map +1 -1
- package/dist/wire/apiLifecycle.d.ts +63 -0
- package/dist/wire/apiLifecycle.d.ts.map +1 -0
- package/dist/wire/apiLifecycle.js +89 -0
- package/dist/wire/apiLifecycle.js.map +1 -0
- package/dist/wire/frames.d.ts +6 -83
- package/dist/wire/frames.d.ts.map +1 -1
- package/dist/wire/frames.js +4 -11
- package/dist/wire/frames.js.map +1 -1
- package/dist/wire/inboundFrames.d.ts +6 -131
- package/dist/wire/inboundFrames.d.ts.map +1 -1
- package/dist/wire/inboundFrames.js +3 -3
- package/dist/wire/inboundFrames.js.map +1 -1
- package/dist/wire/index.d.ts +20 -15
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +22 -8
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/modelMutations.d.ts +1 -32
- package/dist/wire/modelMutations.d.ts.map +1 -1
- package/dist/wire/modelMutations.js +1 -8
- package/dist/wire/modelMutations.js.map +1 -1
- package/dist/wire/rateLimit.d.ts +82 -0
- package/dist/wire/rateLimit.d.ts.map +1 -0
- package/dist/wire/rateLimit.js +142 -0
- package/dist/wire/rateLimit.js.map +1 -0
- package/package.json +130 -10
- package/src/ai-sdk/modelTools.ts +5 -5
- package/src/ai-sdk/updateTool.ts +5 -7
- package/src/auth/capability.ts +5 -0
- package/src/auth/capabilityLifecycle.ts +1 -1
- package/src/auth/credentialPolicy.ts +1 -1
- package/src/auth/identity.ts +7 -7
- package/src/auth/index.ts +4 -663
- package/src/auth/runtime.ts +669 -0
- package/src/auth/sessionMint.ts +3 -2
- package/src/branches.ts +3 -0
- package/src/{coordination/awaitClaimGrant.ts → claims/awaitGrant.ts} +4 -4
- package/src/{wire/claims.ts → claims/contract.ts} +1 -1
- package/src/{coordination → claims}/events.ts +7 -11
- package/src/claims/index.ts +21 -0
- package/src/claims/lifetime.ts +78 -0
- package/src/{coordination → claims}/locator.ts +3 -3
- package/src/claims/routes.ts +81 -0
- package/src/{coordination → claims}/trace.ts +5 -5
- package/src/{ablo.ts → client/ablo.ts} +8 -20
- package/src/{transactionLayer.ts → client/contract.ts} +11 -13
- package/src/{headlessClient.ts → client/headless.ts} +13 -15
- package/src/client/index.ts +10 -0
- package/src/{resources → client/resources}/functionalUpdate.ts +4 -4
- package/src/{resources → client/resources}/httpResources.ts +163 -92
- package/src/client/resources/modelCreate.ts +73 -0
- package/src/{resources → client/resources}/modelOperations.ts +73 -55
- package/src/{resources → client/resources}/mutationOptions.ts +4 -17
- package/src/{resources → client/resources}/where.ts +1 -1
- package/src/{resources → client/resources}/writeOptionsSchema.ts +35 -27
- package/src/{transactions → commit}/confirmation/commitEnvelope.ts +2 -12
- package/src/{transactions → commit}/confirmation/httpCommitEnvelope.ts +1 -1
- package/src/{transactions → commit}/confirmation/pendingWrite.ts +1 -1
- package/src/{wire/commit.ts → commit/contract.ts} +27 -26
- package/src/{durableWrites.ts → commit/durableWrites.ts} +7 -7
- package/src/commit/httpRequest.ts +103 -0
- package/src/commit/index.ts +16 -0
- package/src/{readSetContext.ts → commit/readSetContext.ts} +24 -43
- package/src/{commitRecordRuntime.ts → commit/recordRuntime.ts} +12 -67
- package/src/coordination/index.ts +4 -54
- package/src/coordination/schema.ts +15 -309
- package/src/errorCodes.ts +62 -10
- package/src/errors.ts +32 -10
- package/src/index.ts +8 -8
- package/src/internal/read-set.ts +3 -6
- package/src/observability.ts +4 -4
- package/src/{wire/delta.ts → observation/contract.ts} +2 -2
- package/src/{wire/feedEvent.ts → observation/feedContract.ts} +3 -4
- package/src/{transport → observation}/httpFeed.ts +3 -3
- package/src/observation/index.ts +12 -0
- package/src/{log → observation/persistence}/syncDeltaRow.ts +6 -7
- package/src/pricing.ts +46 -25
- package/src/schema/audit.ts +121 -0
- package/src/schema/ddl.ts +71 -1
- package/src/schema/index.ts +20 -20
- package/src/schema/model.ts +17 -33
- package/src/schema/openapi.ts +170 -9
- package/src/schema/roles.ts +53 -0
- package/src/schema/schema.ts +91 -6
- package/src/schema/serialize.ts +8 -9
- package/src/schema/subject.ts +43 -0
- package/src/server/adapter.ts +3 -1
- package/src/server/commit.ts +6 -14
- package/src/server/index.ts +1 -1
- package/src/server/readConfig.ts +4 -0
- package/src/source/{adapter.ts → adapters/adapter.ts} +9 -5
- package/src/source/{adapterFactory.ts → adapters/adapterFactory.ts} +1 -1
- package/src/source/{conformance.ts → adapters/conformance.ts} +1 -1
- package/src/source/{contract.ts → adapters/contract.ts} +24 -61
- package/src/source/adapters/drizzle.ts +75 -29
- package/src/source/{idempotency.ts → adapters/idempotency.ts} +2 -2
- package/src/source/adapters/index.ts +20 -0
- package/src/source/adapters/kysely.ts +77 -27
- package/src/source/adapters/kyselyMutationCore.ts +23 -11
- package/src/source/adapters/memory.ts +26 -9
- package/src/source/adapters/migration.ts +11 -0
- package/src/source/{migrations.ts → adapters/migrations.ts} +6 -33
- package/src/source/adapters/prisma.ts +98 -34
- package/src/source/adapters/subjectAuthorization.ts +182 -0
- package/src/source/{connector.ts → connector/client.ts} +35 -12
- package/src/source/connector/index.ts +3 -0
- package/src/source/{connectorProtocol.ts → connector/protocol.ts} +10 -2
- package/src/source/delivery/index.ts +2 -0
- package/src/source/{pushQueue.ts → delivery/pushQueue.ts} +2 -2
- package/src/source/{factory.ts → endpoint/factory.ts} +150 -9
- package/src/source/endpoint/index.ts +4 -0
- package/src/source/{next.ts → endpoint/next.ts} +2 -2
- package/src/source/{signing.ts → endpoint/signing.ts} +1 -1
- package/src/source/index.ts +27 -18
- package/src/source/outbox/contract.ts +56 -0
- package/src/source/outbox/envelope.ts +47 -0
- package/src/source/outbox/index.ts +15 -0
- package/src/source/outbox/migrations.ts +71 -0
- package/src/source/outbox/retention.ts +2 -0
- package/src/source/types.ts +64 -10
- package/src/syncLog/contract.ts +19 -9
- package/src/testing/fixtures/httpResponses.ts +7 -0
- package/src/transport/{credentialLifecycle.ts → connection/credentialLifecycle.ts} +3 -3
- package/src/transport/connection/index.ts +4 -0
- package/src/transport/{connectionManager.ts → connection/manager.ts} +13 -4
- package/src/transport/{networkProbe.ts → connection/networkProbe.ts} +4 -4
- package/src/transport/{httpClient.ts → http/client.ts} +165 -184
- package/src/transport/http/helpers.ts +63 -0
- package/src/transport/http/index.ts +5 -0
- package/src/transport/{httpOptions.ts → http/options.ts} +6 -6
- package/src/transport/http/subscription.ts +174 -0
- package/src/transport/{httpTransport.ts → http/transport.ts} +210 -246
- package/src/transport/index.ts +7 -0
- package/src/transport/{commitFrames.ts → websocket/commitFrames.ts} +14 -46
- package/src/transport/{wsFrameHandlers.ts → websocket/frameHandlers.ts} +11 -54
- package/src/transport/{heartbeat.ts → websocket/heartbeat.ts} +2 -2
- package/src/transport/websocket/index.ts +5 -0
- package/src/transport/{wsTransport.ts → websocket/transport.ts} +16 -30
- package/src/types/index.ts +2 -6
- package/src/types/streams.ts +7 -61
- package/src/webhooks/events.ts +1 -1
- package/src/wire/accountResponses.ts +3 -12
- package/src/wire/apiLifecycle.ts +94 -0
- package/src/wire/frames.ts +5 -15
- package/src/wire/inboundFrames.ts +3 -3
- package/src/wire/index.ts +50 -15
- package/src/wire/modelMutations.ts +1 -14
- package/src/wire/rateLimit.ts +155 -0
- package/dist/ablo.d.ts.map +0 -1
- package/dist/ablo.js.map +0 -1
- package/dist/commitRecordRuntime.d.ts.map +0 -1
- package/dist/commitRecordRuntime.js.map +0 -1
- package/dist/coordination/awaitClaimGrant.d.ts.map +0 -1
- package/dist/coordination/awaitClaimGrant.js.map +0 -1
- package/dist/coordination/claimHeartbeatLoop.d.ts.map +0 -1
- package/dist/coordination/claimHeartbeatLoop.js.map +0 -1
- package/dist/coordination/claimMeta.d.ts.map +0 -1
- package/dist/coordination/claimMeta.js.map +0 -1
- package/dist/coordination/events.d.ts.map +0 -1
- package/dist/coordination/events.js +0 -8
- package/dist/coordination/events.js.map +0 -1
- package/dist/coordination/locator.d.ts.map +0 -1
- package/dist/coordination/locator.js.map +0 -1
- package/dist/coordination/targetConflict.d.ts.map +0 -1
- package/dist/coordination/targetConflict.js.map +0 -1
- package/dist/coordination/trace.d.ts.map +0 -1
- package/dist/coordination/trace.js.map +0 -1
- package/dist/durableWrites.d.ts.map +0 -1
- package/dist/durableWrites.js.map +0 -1
- package/dist/headlessClient.d.ts.map +0 -1
- package/dist/log/syncDeltaRow.d.ts.map +0 -1
- package/dist/log/syncDeltaRow.js.map +0 -1
- package/dist/policy/types.d.ts +0 -226
- package/dist/policy/types.d.ts.map +0 -1
- package/dist/policy/types.js +0 -127
- package/dist/policy/types.js.map +0 -1
- package/dist/readSetContext.d.ts.map +0 -1
- package/dist/readSetContext.js.map +0 -1
- package/dist/resources/functionalUpdate.d.ts.map +0 -1
- package/dist/resources/functionalUpdate.js.map +0 -1
- package/dist/resources/httpResources.d.ts.map +0 -1
- package/dist/resources/httpResources.js +0 -17
- package/dist/resources/httpResources.js.map +0 -1
- package/dist/resources/modelOperations.d.ts.map +0 -1
- package/dist/resources/modelOperations.js.map +0 -1
- package/dist/resources/mutationOptions.d.ts.map +0 -1
- package/dist/resources/mutationOptions.js.map +0 -1
- package/dist/resources/where.d.ts.map +0 -1
- package/dist/resources/where.js.map +0 -1
- package/dist/resources/writeOptionsSchema.d.ts.map +0 -1
- package/dist/resources/writeOptionsSchema.js.map +0 -1
- package/dist/schema/coordination.d.ts +0 -113
- package/dist/schema/coordination.d.ts.map +0 -1
- package/dist/schema/coordination.js +0 -134
- package/dist/schema/coordination.js.map +0 -1
- package/dist/source/adapter.d.ts.map +0 -1
- package/dist/source/adapter.js.map +0 -1
- package/dist/source/adapterFactory.d.ts.map +0 -1
- package/dist/source/adapterFactory.js.map +0 -1
- package/dist/source/adapterProfile.d.ts.map +0 -1
- package/dist/source/adapterProfile.js.map +0 -1
- package/dist/source/conformance.d.ts.map +0 -1
- package/dist/source/conformance.js.map +0 -1
- package/dist/source/connector.d.ts.map +0 -1
- package/dist/source/connector.js.map +0 -1
- package/dist/source/connectorProtocol.d.ts.map +0 -1
- package/dist/source/connectorProtocol.js.map +0 -1
- package/dist/source/contract.d.ts.map +0 -1
- package/dist/source/contract.js.map +0 -1
- package/dist/source/drizzle.d.ts +0 -2
- package/dist/source/drizzle.d.ts.map +0 -1
- package/dist/source/drizzle.js +0 -2
- package/dist/source/drizzle.js.map +0 -1
- package/dist/source/factory.d.ts.map +0 -1
- package/dist/source/factory.js.map +0 -1
- package/dist/source/idempotency.d.ts.map +0 -1
- package/dist/source/idempotency.js.map +0 -1
- package/dist/source/kysely.d.ts +0 -3
- package/dist/source/kysely.d.ts.map +0 -1
- package/dist/source/kysely.js +0 -3
- package/dist/source/kysely.js.map +0 -1
- package/dist/source/migrations.d.ts.map +0 -1
- package/dist/source/migrations.js.map +0 -1
- package/dist/source/next.d.ts.map +0 -1
- package/dist/source/next.js.map +0 -1
- package/dist/source/pushQueue.d.ts.map +0 -1
- package/dist/source/pushQueue.js.map +0 -1
- package/dist/source/signing.d.ts.map +0 -1
- package/dist/source/signing.js.map +0 -1
- package/dist/transactionLayer.d.ts.map +0 -1
- package/dist/transactionLayer.js.map +0 -1
- package/dist/transactions/confirmation/commitEnvelope.d.ts.map +0 -1
- package/dist/transactions/confirmation/commitEnvelope.js.map +0 -1
- package/dist/transactions/confirmation/httpCommitEnvelope.d.ts.map +0 -1
- package/dist/transactions/confirmation/httpCommitEnvelope.js.map +0 -1
- package/dist/transactions/confirmation/idempotencyKey.d.ts.map +0 -1
- package/dist/transactions/confirmation/idempotencyKey.js.map +0 -1
- package/dist/transactions/confirmation/pendingWrite.d.ts.map +0 -1
- package/dist/transactions/confirmation/pendingWrite.js.map +0 -1
- package/dist/transport/commitFrames.d.ts.map +0 -1
- package/dist/transport/commitFrames.js.map +0 -1
- package/dist/transport/connectionManager.d.ts.map +0 -1
- package/dist/transport/connectionManager.js.map +0 -1
- package/dist/transport/credentialLifecycle.d.ts.map +0 -1
- package/dist/transport/credentialLifecycle.js.map +0 -1
- package/dist/transport/heartbeat.d.ts.map +0 -1
- package/dist/transport/heartbeat.js.map +0 -1
- package/dist/transport/httpClient.d.ts.map +0 -1
- package/dist/transport/httpClient.js.map +0 -1
- package/dist/transport/httpFeed.d.ts +0 -4
- package/dist/transport/httpFeed.d.ts.map +0 -1
- package/dist/transport/httpOptions.js.map +0 -1
- package/dist/transport/httpTransport.d.ts.map +0 -1
- package/dist/transport/httpTransport.js.map +0 -1
- package/dist/transport/networkProbe.d.ts.map +0 -1
- package/dist/transport/networkProbe.js.map +0 -1
- package/dist/transport/wsFrameHandlers.d.ts.map +0 -1
- package/dist/transport/wsFrameHandlers.js.map +0 -1
- package/dist/transport/wsTransport.d.ts.map +0 -1
- package/dist/transport/wsTransport.js.map +0 -1
- package/dist/wire/claimEvent.d.ts.map +0 -1
- package/dist/wire/claimEvent.js.map +0 -1
- package/dist/wire/claims.d.ts.map +0 -1
- package/dist/wire/claims.js.map +0 -1
- package/dist/wire/commit.d.ts +0 -2801
- package/dist/wire/commit.d.ts.map +0 -1
- package/dist/wire/commit.js.map +0 -1
- package/dist/wire/delta.d.ts.map +0 -1
- package/dist/wire/delta.js.map +0 -1
- package/dist/wire/deltaDelivery.d.ts.map +0 -1
- package/dist/wire/deltaDelivery.js.map +0 -1
- package/dist/wire/feedCursor.d.ts.map +0 -1
- package/dist/wire/feedCursor.js.map +0 -1
- package/dist/wire/feedEvent.d.ts.map +0 -1
- package/dist/wire/feedEvent.js.map +0 -1
- package/src/policy/types.ts +0 -300
- package/src/schema/coordination.ts +0 -161
- package/src/source/drizzle.ts +0 -1
- package/src/source/kysely.ts +0 -2
- /package/dist/{coordination → claims}/targetConflict.d.ts +0 -0
- /package/dist/{coordination → claims}/targetConflict.js +0 -0
- /package/dist/{resources → client/resources}/mutationOptions.js +0 -0
- /package/dist/{resources → client/resources}/where.d.ts +0 -0
- /package/dist/{transactions → commit}/confirmation/httpCommitEnvelope.d.ts +0 -0
- /package/dist/{transactions → commit}/confirmation/idempotencyKey.d.ts +0 -0
- /package/dist/{transactions → commit}/confirmation/idempotencyKey.js +0 -0
- /package/dist/source/{adapter.js → adapters/adapter.js} +0 -0
- /package/dist/source/{adapterFactory.d.ts → adapters/adapterFactory.d.ts} +0 -0
- /package/dist/source/{adapterProfile.d.ts → adapters/adapterProfile.d.ts} +0 -0
- /package/dist/source/{adapterProfile.js → adapters/adapterProfile.js} +0 -0
- /package/dist/source/{idempotency.d.ts → adapters/idempotency.d.ts} +0 -0
- /package/src/{wire/claimEvent.ts → claims/eventContract.ts} +0 -0
- /package/src/{coordination/claimHeartbeatLoop.ts → claims/heartbeat.ts} +0 -0
- /package/src/{coordination/claimMeta.ts → claims/meta.ts} +0 -0
- /package/src/{coordination → claims}/targetConflict.ts +0 -0
- /package/src/{transactions → commit}/confirmation/idempotencyKey.ts +0 -0
- /package/src/{wire/feedCursor.ts → observation/cursor.ts} +0 -0
- /package/src/{wire/deltaDelivery.ts → observation/deliveryContract.ts} +0 -0
- /package/src/source/{adapterProfile.ts → adapters/adapterProfile.ts} +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { AbloPermissionError, AbloValidationError } from '../../errors.js';
|
|
2
|
+
import {
|
|
3
|
+
composeEntitySyncGroups,
|
|
4
|
+
syncGroupsForRow,
|
|
5
|
+
InvalidRecordSubjectError,
|
|
6
|
+
scopeKindOf,
|
|
7
|
+
subjectAuthorized,
|
|
8
|
+
type Schema,
|
|
9
|
+
type SchemaRecord,
|
|
10
|
+
type SubjectRule,
|
|
11
|
+
} from '../../schema/index.js';
|
|
12
|
+
import type { AdapterReadRequest, Row } from './adapter.js';
|
|
13
|
+
import type { ChangeSet, Operation } from './contract.js';
|
|
14
|
+
|
|
15
|
+
function sourceModelEntry<S extends SchemaRecord>(schema: Schema<S>, model: string) {
|
|
16
|
+
return Object.entries(schema.models).find(([key, def]) =>
|
|
17
|
+
key === model || key.toLowerCase() === model.toLowerCase() ||
|
|
18
|
+
def.typename === model || def.typename?.toLowerCase() === model.toLowerCase(),
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function deny(): never {
|
|
23
|
+
throw new AbloPermissionError('The resolved scope does not cover the requested row.', {
|
|
24
|
+
code: 'capability_scope_denied',
|
|
25
|
+
httpStatus: 403,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function sourceSubjectRule<S extends SchemaRecord>(
|
|
30
|
+
schema: Schema<S>,
|
|
31
|
+
model: string,
|
|
32
|
+
): SubjectRule | undefined {
|
|
33
|
+
const entry = sourceModelEntry(schema, model);
|
|
34
|
+
return entry?.[1].subject;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Derive the durable record routes while the row is transactionally visible. */
|
|
38
|
+
export function sourceSyncGroups<S extends SchemaRecord>(
|
|
39
|
+
schema: Schema<S>,
|
|
40
|
+
model: string,
|
|
41
|
+
row: Row,
|
|
42
|
+
): readonly string[] {
|
|
43
|
+
const entry = sourceModelEntry(schema, model);
|
|
44
|
+
if (!entry) return [];
|
|
45
|
+
const [key, definition] = entry;
|
|
46
|
+
const parents: { kind: string; field: string }[] = [];
|
|
47
|
+
const selfKind = scopeKindOf(definition, key);
|
|
48
|
+
for (const relation of Object.values(definition.relations ?? {})) {
|
|
49
|
+
if (relation.type !== 'belongsTo' || relation.options?.parent !== true) continue;
|
|
50
|
+
const target = schema.models[relation.target];
|
|
51
|
+
const kind = target && scopeKindOf(target, relation.target);
|
|
52
|
+
if (kind) parents.push({ kind, field: relation.foreignKey });
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
return syncGroupsForRow(
|
|
56
|
+
{
|
|
57
|
+
selfKind,
|
|
58
|
+
parents,
|
|
59
|
+
...(definition.subject
|
|
60
|
+
? { subject: { kind: definition.subject.group, field: definition.subject.field } }
|
|
61
|
+
: {}),
|
|
62
|
+
},
|
|
63
|
+
row,
|
|
64
|
+
composeEntitySyncGroups(row, definition),
|
|
65
|
+
);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (!(error instanceof InvalidRecordSubjectError)) throw error;
|
|
68
|
+
throw new AbloValidationError(
|
|
69
|
+
`Source row ${model}/${String(row.id ?? '')} lacks subject field "${error.field}".`,
|
|
70
|
+
{ code: 'source_event_invalid', cause: error },
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Subject values represented by a trusted group set, preserving group order. */
|
|
76
|
+
export function sourceSubjectValues(
|
|
77
|
+
rule: SubjectRule | undefined,
|
|
78
|
+
groups: readonly string[] | undefined,
|
|
79
|
+
): readonly string[] | undefined {
|
|
80
|
+
if (!rule) return undefined;
|
|
81
|
+
const prefix = `${rule.group}:`;
|
|
82
|
+
return [...new Set(
|
|
83
|
+
(groups ?? [])
|
|
84
|
+
.filter((group) => group.startsWith(prefix))
|
|
85
|
+
.map((group) => group.slice(prefix.length))
|
|
86
|
+
.filter((value) => value.length > 0),
|
|
87
|
+
)];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Stable absent-row lock keys for caller-selected subject-scoped CREATE ids.
|
|
92
|
+
* Adapters acquire these in sorted order before loading current rows, so two
|
|
93
|
+
* authorized writers cannot both observe an absent id. Database uniqueness is
|
|
94
|
+
* still the final boundary against external writers that ignore this lock.
|
|
95
|
+
*/
|
|
96
|
+
function sourceSubjectCreateLockOperations<S extends SchemaRecord>(
|
|
97
|
+
schema: Schema<S>,
|
|
98
|
+
change: ChangeSet,
|
|
99
|
+
): readonly Operation[] {
|
|
100
|
+
return change.operations
|
|
101
|
+
.filter((operation) =>
|
|
102
|
+
operation.type === 'CREATE' &&
|
|
103
|
+
typeof operation.id === 'string' &&
|
|
104
|
+
operation.id.length > 0 &&
|
|
105
|
+
sourceSubjectRule(schema, operation.model) !== undefined)
|
|
106
|
+
.sort((left, right) =>
|
|
107
|
+
`${left.model.toLowerCase()}\u0000${left.id}`.localeCompare(
|
|
108
|
+
`${right.model.toLowerCase()}\u0000${right.id}`,
|
|
109
|
+
));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function sourceSubjectCreateLockKey(operation: Operation): string {
|
|
113
|
+
return `ablo:subject-create:${operation.model.toLowerCase()}:${operation.id ?? ''}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Acquire every absent-key CREATE lock in canonical order. */
|
|
117
|
+
export async function lockSourceSubjectCreates<S extends SchemaRecord>(
|
|
118
|
+
schema: Schema<S>,
|
|
119
|
+
change: ChangeSet,
|
|
120
|
+
acquire: (operation: Operation, key: string) => Promise<void>,
|
|
121
|
+
): Promise<void> {
|
|
122
|
+
for (const operation of sourceSubjectCreateLockOperations(schema, change)) {
|
|
123
|
+
await acquire(operation, sourceSubjectCreateLockKey(operation));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function errorCode(error: unknown): unknown {
|
|
128
|
+
return error && typeof error === 'object' ? (error as { code?: unknown }).code : undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Translate ORM/driver primary-key conflicts without exposing the winning row. */
|
|
132
|
+
export function rethrowStrictCreateConflict(error: unknown, operation: Operation): never {
|
|
133
|
+
const code = errorCode(error) ?? errorCode(
|
|
134
|
+
error && typeof error === 'object' ? (error as { cause?: unknown }).cause : undefined,
|
|
135
|
+
);
|
|
136
|
+
if (code === '23505' || code === 'P2002') {
|
|
137
|
+
throw new AbloValidationError(
|
|
138
|
+
`A row already exists for ${operation.model}/${operation.id ?? ''}.`,
|
|
139
|
+
{ code: 'entity_already_exists', httpStatus: 409, cause: error },
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function authorizeSourceRead<S extends SchemaRecord>(
|
|
146
|
+
schema: Schema<S>,
|
|
147
|
+
req: AdapterReadRequest,
|
|
148
|
+
rows: readonly Row[],
|
|
149
|
+
): readonly Row[] {
|
|
150
|
+
const rule = sourceSubjectRule(schema, req.model);
|
|
151
|
+
if (!rule) return rows;
|
|
152
|
+
const groups = req.scope?.syncGroups;
|
|
153
|
+
const authorized = rows.filter((row) => subjectAuthorized(rule, row, groups));
|
|
154
|
+
if (req.kind === 'load' && rows.length > 0 && authorized.length === 0) deny();
|
|
155
|
+
return authorized;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function authorizePayload(rule: SubjectRule, row: Row, groups: readonly string[] | undefined): void {
|
|
159
|
+
if (!subjectAuthorized(rule, row, groups)) deny();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export async function authorizeSourceChange<S extends SchemaRecord>(
|
|
163
|
+
schema: Schema<S>,
|
|
164
|
+
change: ChangeSet,
|
|
165
|
+
load: (operation: Operation) => Promise<Row | null>,
|
|
166
|
+
): Promise<void> {
|
|
167
|
+
for (const operation of change.operations) {
|
|
168
|
+
const rule = sourceSubjectRule(schema, operation.model);
|
|
169
|
+
if (!rule) continue;
|
|
170
|
+
const current = operation.id ? await load(operation) : null;
|
|
171
|
+
if (current) authorizePayload(rule, current, change.scope?.syncGroups);
|
|
172
|
+
if (operation.type === 'CREATE') {
|
|
173
|
+
authorizePayload(rule, operation.input ?? {}, change.scope?.syncGroups);
|
|
174
|
+
} else if (!current) {
|
|
175
|
+
deny();
|
|
176
|
+
}
|
|
177
|
+
if (current && operation.input && Object.hasOwn(operation.input, rule.field) &&
|
|
178
|
+
!Object.is(current[rule.field], operation.input[rule.field])) {
|
|
179
|
+
deny();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
import {
|
|
28
28
|
SOURCE_CONNECTOR_PROTOCOL_VERSION,
|
|
29
|
+
SOURCE_CONNECTOR_SUPERSEDED_CLOSE_CODE,
|
|
29
30
|
SOURCE_CONNECTOR_WS_PATH,
|
|
30
31
|
sourceConnectorSubprotocols,
|
|
31
32
|
encodeFrame,
|
|
@@ -35,8 +36,8 @@ import {
|
|
|
35
36
|
type RequestFrame,
|
|
36
37
|
type ResponseFrame,
|
|
37
38
|
type ReadyFrame,
|
|
38
|
-
} from './
|
|
39
|
-
import { ABLO_HOSTED_HTTP_BASE_URL } from '
|
|
39
|
+
} from './protocol.js';
|
|
40
|
+
import { ABLO_HOSTED_HTTP_BASE_URL } from '../../auth/hostedEndpoints.js';
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
43
|
* The default Ablo base URL the connector dials, to which it appends
|
|
@@ -130,6 +131,20 @@ export interface SourceConnector {
|
|
|
130
131
|
run(signal: AbortSignal): Promise<void>;
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
/** The connector lost its source lease to a newer process and will not reconnect. */
|
|
135
|
+
export class SourceConnectorSupersededError extends Error {
|
|
136
|
+
readonly code = 'source_connector_superseded';
|
|
137
|
+
|
|
138
|
+
constructor() {
|
|
139
|
+
super(
|
|
140
|
+
'A newer local connector took ownership of this source; this connector has stopped.',
|
|
141
|
+
);
|
|
142
|
+
this.name = 'SourceConnectorSupersededError';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
type ConnectionOutcome = 'retry' | 'ready' | 'superseded';
|
|
147
|
+
|
|
133
148
|
export function createSourceConnector(
|
|
134
149
|
options: SourceConnectorOptions,
|
|
135
150
|
): SourceConnector {
|
|
@@ -148,7 +163,7 @@ export function createSourceConnector(
|
|
|
148
163
|
if (signal.aborted) return;
|
|
149
164
|
|
|
150
165
|
options.onStatus?.('connecting');
|
|
151
|
-
const
|
|
166
|
+
const outcome = await connectOnce({
|
|
152
167
|
url,
|
|
153
168
|
apiKey: options.apiKey,
|
|
154
169
|
handler: options.handler,
|
|
@@ -158,9 +173,10 @@ export function createSourceConnector(
|
|
|
158
173
|
onError: options.onError,
|
|
159
174
|
signal,
|
|
160
175
|
});
|
|
176
|
+
if (outcome === 'superseded') return;
|
|
161
177
|
// A connection that reached `ready` resets the backoff so the next
|
|
162
178
|
// drop reconnects immediately; one that never readied keeps escalating.
|
|
163
|
-
attempt =
|
|
179
|
+
attempt = outcome === 'ready' ? 0 : attempt + 1;
|
|
164
180
|
}
|
|
165
181
|
},
|
|
166
182
|
};
|
|
@@ -169,8 +185,10 @@ export function createSourceConnector(
|
|
|
169
185
|
/**
|
|
170
186
|
* Runs one connection: open the socket, register, then serve requests until the
|
|
171
187
|
* socket closes or `signal` aborts. Resolves to whether the connection reached the
|
|
172
|
-
* `ready` state, which the caller uses to reset the reconnect backoff
|
|
173
|
-
*
|
|
188
|
+
* `ready` state, which the caller uses to reset the reconnect backoff, or the
|
|
189
|
+
* terminal `superseded` fence, which stops this process from taking ownership
|
|
190
|
+
* back from its replacement. It never rejects because ordinary transport drops
|
|
191
|
+
* are expected and simply drive a reconnect.
|
|
174
192
|
*/
|
|
175
193
|
function connectOnce(params: {
|
|
176
194
|
readonly url: string;
|
|
@@ -181,8 +199,8 @@ function connectOnce(params: {
|
|
|
181
199
|
readonly onStatus: ((status: ConnectorStatus) => void) | undefined;
|
|
182
200
|
readonly onError: ((error: unknown) => void) | undefined;
|
|
183
201
|
readonly signal: AbortSignal;
|
|
184
|
-
}): Promise<
|
|
185
|
-
return new Promise<
|
|
202
|
+
}): Promise<ConnectionOutcome> {
|
|
203
|
+
return new Promise<ConnectionOutcome>((resolve) => {
|
|
186
204
|
let ws: ConnectorWebSocket;
|
|
187
205
|
try {
|
|
188
206
|
ws = params.factory(
|
|
@@ -191,18 +209,18 @@ function connectOnce(params: {
|
|
|
191
209
|
);
|
|
192
210
|
} catch (err) {
|
|
193
211
|
params.onError?.(err);
|
|
194
|
-
resolve(
|
|
212
|
+
resolve('retry');
|
|
195
213
|
return;
|
|
196
214
|
}
|
|
197
215
|
|
|
198
216
|
let ready = false;
|
|
199
217
|
let settled = false;
|
|
200
|
-
const finish = (): void => {
|
|
218
|
+
const finish = (outcome: ConnectionOutcome = ready ? 'ready' : 'retry'): void => {
|
|
201
219
|
if (settled) return;
|
|
202
220
|
settled = true;
|
|
203
221
|
params.signal.removeEventListener('abort', onAbort);
|
|
204
222
|
params.onStatus?.('disconnected');
|
|
205
|
-
resolve(
|
|
223
|
+
resolve(outcome);
|
|
206
224
|
};
|
|
207
225
|
|
|
208
226
|
const onAbort = (): void => {
|
|
@@ -243,7 +261,12 @@ function connectOnce(params: {
|
|
|
243
261
|
// `close` always follows `error`; finish() runs there.
|
|
244
262
|
});
|
|
245
263
|
|
|
246
|
-
ws.addEventListener('close', () => {
|
|
264
|
+
ws.addEventListener('close', (event) => {
|
|
265
|
+
if (event.code === SOURCE_CONNECTOR_SUPERSEDED_CLOSE_CODE) {
|
|
266
|
+
params.onError?.(new SourceConnectorSupersededError());
|
|
267
|
+
finish('superseded');
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
247
270
|
finish();
|
|
248
271
|
});
|
|
249
272
|
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
|
|
23
23
|
import { z } from 'zod';
|
|
24
24
|
|
|
25
|
-
import { environmentSchema } from '
|
|
26
|
-
import { WS_BEARER_SUBPROTOCOL_PREFIX } from '
|
|
25
|
+
import { environmentSchema } from '../../environment.js';
|
|
26
|
+
import { WS_BEARER_SUBPROTOCOL_PREFIX } from '../../auth/credentialSource.js';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* The wire-protocol version. It increases on any breaking change to a frame's
|
|
@@ -43,6 +43,14 @@ export const SOURCE_CONNECTOR_WS_PATH = '/v1/source/listen';
|
|
|
43
43
|
*/
|
|
44
44
|
export const WS_SOURCE_SUBPROTOCOL = 'ablo.source.v1';
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Private WebSocket close code used when a newer connector takes ownership of
|
|
48
|
+
* the same source. This is a fencing decision, not a transient disconnect: the
|
|
49
|
+
* superseded process must stop reconnecting or two `ablo dev --local`
|
|
50
|
+
* processes will continuously replace each other.
|
|
51
|
+
*/
|
|
52
|
+
export const SOURCE_CONNECTOR_SUPERSEDED_CLOSE_CODE = 4009;
|
|
53
|
+
|
|
46
54
|
/**
|
|
47
55
|
* Builds the `Sec-WebSocket-Protocol` list a connector offers during the
|
|
48
56
|
* handshake: the source subprotocol followed by the bearer credential, encoded as
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
* interface against your own outbox table for production durability.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { ABLO_SOURCE_HEADERS, signAbloSourceRequest } from '
|
|
27
|
-
import type { SourceEvent } from '
|
|
26
|
+
import { ABLO_SOURCE_HEADERS, signAbloSourceRequest } from '../endpoint/signing.js';
|
|
27
|
+
import type { SourceEvent } from '../types.js';
|
|
28
28
|
|
|
29
29
|
/** One queued delivery: a batch of source events plus its retry bookkeeping. */
|
|
30
30
|
export interface PushQueueItem {
|
|
@@ -10,9 +10,18 @@ import type {
|
|
|
10
10
|
Schema,
|
|
11
11
|
SchemaRecord,
|
|
12
12
|
InferCreate,
|
|
13
|
-
} from '
|
|
14
|
-
import type { DataSourceAdapter } from '
|
|
15
|
-
import {
|
|
13
|
+
} from '../../schema/schema.js';
|
|
14
|
+
import type { DataSourceAdapter } from '../adapters/adapter.js';
|
|
15
|
+
import type { AdapterReadRequest, Row } from '../adapters/adapter.js';
|
|
16
|
+
import { changeSetSchema } from '../adapters/contract.js';
|
|
17
|
+
import { AbloError, AbloPermissionError } from '../../errors.js';
|
|
18
|
+
import {
|
|
19
|
+
authorizeSourceChange,
|
|
20
|
+
authorizeSourceRead,
|
|
21
|
+
lockSourceSubjectCreates,
|
|
22
|
+
sourceSubjectRule,
|
|
23
|
+
sourceSubjectValues,
|
|
24
|
+
} from '../adapters/subjectAuthorization.js';
|
|
16
25
|
import {
|
|
17
26
|
SourceSignatureError,
|
|
18
27
|
verifyAbloSourceRequest,
|
|
@@ -31,7 +40,8 @@ import type {
|
|
|
31
40
|
SourceRequest,
|
|
32
41
|
SourceRequestContext,
|
|
33
42
|
SourceScope,
|
|
34
|
-
|
|
43
|
+
SourceSubjectTransactionHandler,
|
|
44
|
+
} from '../types.js';
|
|
35
45
|
|
|
36
46
|
type SourceModels<S extends SchemaRecord, TAuth> = Partial<{
|
|
37
47
|
readonly [K in keyof S & string]: SourceModelHandlers<
|
|
@@ -86,6 +96,12 @@ export type DataSourceOptions<S extends SchemaRecord, TAuth = unknown> = {
|
|
|
86
96
|
* run inside one transaction you control.
|
|
87
97
|
*/
|
|
88
98
|
readonly commit?: SourceCommitHandler<TAuth>;
|
|
99
|
+
/**
|
|
100
|
+
* Required for a hand-written commit touching any subject-scoped model.
|
|
101
|
+
* The hook owns one customer-database transaction and calls `run` with a
|
|
102
|
+
* locking row loader and the batch commit bound to that same transaction.
|
|
103
|
+
*/
|
|
104
|
+
readonly subjectTransaction?: SourceSubjectTransactionHandler<TAuth>;
|
|
89
105
|
/**
|
|
90
106
|
* Reports changes that happened outside the SDK — cron jobs, dashboard edits,
|
|
91
107
|
* batch imports — which Ablo polls for. Each event you return becomes a delta and
|
|
@@ -165,6 +181,7 @@ async function handleViaAdapter(
|
|
|
165
181
|
correlationId,
|
|
166
182
|
intentHash: body.intentHash,
|
|
167
183
|
echo: body.echo,
|
|
184
|
+
scope,
|
|
168
185
|
});
|
|
169
186
|
if (!parsed.success) {
|
|
170
187
|
return json({ error: 'source_commit_invalid', message: parsed.error.message }, 400);
|
|
@@ -187,14 +204,19 @@ async function handleViaAdapter(
|
|
|
187
204
|
}
|
|
188
205
|
|
|
189
206
|
if (body.type === 'events') {
|
|
207
|
+
if (body.acknowledgedThrough) {
|
|
208
|
+
await adapter.acknowledgeEvents(body.acknowledgedThrough);
|
|
209
|
+
}
|
|
190
210
|
const page = await adapter.events(body.cursor ?? null, body.limit ?? 100);
|
|
191
211
|
return json({
|
|
192
212
|
events: page.events.map((event) => ({
|
|
193
213
|
id: event.id,
|
|
214
|
+
version: event.version,
|
|
194
215
|
model: event.model,
|
|
195
216
|
entityId: event.entityId,
|
|
196
217
|
type: event.type,
|
|
197
218
|
...(event.data !== undefined && event.data !== null ? { data: event.data } : {}),
|
|
219
|
+
...(event.syncGroups ? { syncGroups: event.syncGroups } : {}),
|
|
198
220
|
...(event.organizationId ? { organizationId: event.organizationId } : {}),
|
|
199
221
|
...(event.clientTxId ? { clientTxId: event.clientTxId } : {}),
|
|
200
222
|
...(event.correlationId ? { correlationId: event.correlationId } : {}),
|
|
@@ -277,6 +299,34 @@ function sameModel(operations: readonly SourceOperation[]): string | null {
|
|
|
277
299
|
return operations.every((op) => op.model === first) ? first : null;
|
|
278
300
|
}
|
|
279
301
|
|
|
302
|
+
function subjectDenial(error: unknown): Response | null {
|
|
303
|
+
return error instanceof AbloPermissionError && error.code === 'capability_scope_denied'
|
|
304
|
+
? json({ error: error.code, message: error.message }, error.httpStatus ?? 403)
|
|
305
|
+
: null;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function typedSourceError(error: unknown): Response | null {
|
|
309
|
+
const denial = subjectDenial(error);
|
|
310
|
+
if (denial) return denial;
|
|
311
|
+
return error instanceof AbloError && error.code && error.httpStatus
|
|
312
|
+
? json({ error: error.code, message: error.message }, error.httpStatus)
|
|
313
|
+
: null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function parseHandWrittenChange<TAuth>(
|
|
317
|
+
body: Extract<SourceRequest, { type: 'commit' }>,
|
|
318
|
+
context: SourceHandlerContext<TAuth>,
|
|
319
|
+
) {
|
|
320
|
+
const correlationId = body.correlationId ?? body.clientTxId;
|
|
321
|
+
return changeSetSchema.safeParse({
|
|
322
|
+
operations: body.operations,
|
|
323
|
+
correlationId,
|
|
324
|
+
intentHash: body.intentHash,
|
|
325
|
+
echo: body.echo,
|
|
326
|
+
scope: context.scope,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
280
330
|
/**
|
|
281
331
|
* Creates a Data Source endpoint you host in front of your own database.
|
|
282
332
|
*
|
|
@@ -368,7 +418,13 @@ export function dataSource<const S extends SchemaRecord, TAuth = unknown>(
|
|
|
368
418
|
// generic layer where rows are plain JSON, so there is no per-model handler
|
|
369
419
|
// lookup on this path.
|
|
370
420
|
if (options.adapter) {
|
|
371
|
-
|
|
421
|
+
try {
|
|
422
|
+
return await handleViaAdapter(options.adapter, body, context.scope);
|
|
423
|
+
} catch (error) {
|
|
424
|
+
const typed = typedSourceError(error);
|
|
425
|
+
if (typed) return typed;
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
372
428
|
}
|
|
373
429
|
|
|
374
430
|
if (body.type === 'load') {
|
|
@@ -377,20 +433,104 @@ export function dataSource<const S extends SchemaRecord, TAuth = unknown>(
|
|
|
377
433
|
return json({ error: 'source_load_not_configured', model: body.model }, 404);
|
|
378
434
|
}
|
|
379
435
|
const row = await handlers.load({ id: body.id, context });
|
|
380
|
-
|
|
436
|
+
try {
|
|
437
|
+
const authorized = authorizeSourceRead(
|
|
438
|
+
options.schema,
|
|
439
|
+
{ kind: 'load', model: body.model, id: body.id, ...(context.scope ? { scope: context.scope } : {}) },
|
|
440
|
+
row ? [row as Row] : [],
|
|
441
|
+
);
|
|
442
|
+
return json({ row: authorized[0] ?? null });
|
|
443
|
+
} catch (error) {
|
|
444
|
+
const typed = typedSourceError(error);
|
|
445
|
+
if (typed) return typed;
|
|
446
|
+
throw error;
|
|
447
|
+
}
|
|
381
448
|
}
|
|
382
449
|
|
|
383
450
|
if (body.type === 'list') {
|
|
384
451
|
const handlers = getModelHandlers(options, body.model);
|
|
385
|
-
|
|
452
|
+
const rule = sourceSubjectRule(options.schema, body.model);
|
|
453
|
+
if (rule && !handlers?.subjectList) {
|
|
454
|
+
return json({
|
|
455
|
+
error: 'source_subject_list_not_configured',
|
|
456
|
+
message: `Subject-scoped model "${body.model}" requires subjectList() so filtering occurs before pagination.`,
|
|
457
|
+
}, 403);
|
|
458
|
+
}
|
|
459
|
+
if (!rule && !handlers?.list) {
|
|
386
460
|
return json({ error: 'source_list_not_configured', model: body.model }, 404);
|
|
387
461
|
}
|
|
388
|
-
const result =
|
|
462
|
+
const result = rule
|
|
463
|
+
? await handlers!.subjectList!({
|
|
464
|
+
query: body.query ?? {},
|
|
465
|
+
subject: {
|
|
466
|
+
field: rule.field,
|
|
467
|
+
values: sourceSubjectValues(rule, context.scope?.syncGroups) ?? [],
|
|
468
|
+
},
|
|
469
|
+
context,
|
|
470
|
+
})
|
|
471
|
+
: await handlers!.list!({ query: body.query ?? {}, context });
|
|
389
472
|
const normalized = normalizeListResult(result);
|
|
390
|
-
|
|
473
|
+
const request: AdapterReadRequest = {
|
|
474
|
+
kind: 'list',
|
|
475
|
+
model: body.model,
|
|
476
|
+
...(body.query ? { query: body.query } : {}),
|
|
477
|
+
...(context.scope ? { scope: context.scope } : {}),
|
|
478
|
+
};
|
|
479
|
+
return json({
|
|
480
|
+
...normalized,
|
|
481
|
+
rows: authorizeSourceRead(options.schema, request, normalized.rows as readonly Row[]),
|
|
482
|
+
});
|
|
391
483
|
}
|
|
392
484
|
|
|
393
485
|
if (body.type === 'commit') {
|
|
486
|
+
const hasSubject = body.operations.some((operation) =>
|
|
487
|
+
sourceSubjectRule(options.schema, operation.model));
|
|
488
|
+
if (hasSubject) {
|
|
489
|
+
if (!options.subjectTransaction) {
|
|
490
|
+
return json({
|
|
491
|
+
error: 'source_subject_transaction_required',
|
|
492
|
+
message: 'Subject-scoped custom commits require subjectTransaction() so authorization and mutation share one transaction.',
|
|
493
|
+
}, 403);
|
|
494
|
+
}
|
|
495
|
+
const parsed = parseHandWrittenChange(body, context);
|
|
496
|
+
if (!parsed.success) {
|
|
497
|
+
return json({ error: 'source_commit_invalid', message: parsed.error.message }, 400);
|
|
498
|
+
}
|
|
499
|
+
try {
|
|
500
|
+
let ranBoundary = false;
|
|
501
|
+
const result = await options.subjectTransaction(
|
|
502
|
+
{
|
|
503
|
+
operations: body.operations,
|
|
504
|
+
correlationId: body.correlationId ?? body.clientTxId,
|
|
505
|
+
clientTxId: body.clientTxId,
|
|
506
|
+
intentHash: body.intentHash,
|
|
507
|
+
echo: body.echo,
|
|
508
|
+
context,
|
|
509
|
+
},
|
|
510
|
+
async ({ lockCreate, load, commit }) => {
|
|
511
|
+
if (ranBoundary) {
|
|
512
|
+
throw new Error('subjectTransaction run() may be called only once');
|
|
513
|
+
}
|
|
514
|
+
ranBoundary = true;
|
|
515
|
+
await lockSourceSubjectCreates(
|
|
516
|
+
options.schema,
|
|
517
|
+
parsed.data,
|
|
518
|
+
(operation) => lockCreate(operation),
|
|
519
|
+
);
|
|
520
|
+
await authorizeSourceChange(options.schema, parsed.data, load);
|
|
521
|
+
return commit();
|
|
522
|
+
},
|
|
523
|
+
);
|
|
524
|
+
if (!ranBoundary) {
|
|
525
|
+
throw new Error('subjectTransaction must call run() inside its database transaction');
|
|
526
|
+
}
|
|
527
|
+
return json(result);
|
|
528
|
+
} catch (error) {
|
|
529
|
+
const typed = typedSourceError(error);
|
|
530
|
+
if (typed) return typed;
|
|
531
|
+
throw error;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
394
534
|
if (options.commit) {
|
|
395
535
|
const result = await options.commit({
|
|
396
536
|
operations: body.operations,
|
|
@@ -428,6 +568,7 @@ export function dataSource<const S extends SchemaRecord, TAuth = unknown>(
|
|
|
428
568
|
}
|
|
429
569
|
const result = await options.events({
|
|
430
570
|
cursor: body.cursor,
|
|
571
|
+
acknowledgedThrough: body.acknowledgedThrough,
|
|
431
572
|
limit: body.limit,
|
|
432
573
|
context,
|
|
433
574
|
});
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `POST` so your route file can export it in one line.
|
|
6
6
|
*
|
|
7
7
|
* // app/api/ablo/source/route.ts
|
|
8
|
-
* import { dataSourceNext } from '@abloatai/transaction/source/
|
|
8
|
+
* import { dataSourceNext } from '@abloatai/transaction/source/endpoint';
|
|
9
9
|
* import { prismaDataSource } from '@abloatai/transaction/source';
|
|
10
10
|
* import { schema } from '@/ablo/schema';
|
|
11
11
|
* import { prisma } from '@/lib/prisma';
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* directly and export its result however that framework expects.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import type { SchemaRecord } from '
|
|
23
|
+
import type { SchemaRecord } from '../../schema/schema.js';
|
|
24
24
|
import { dataSource, type DataSourceOptions } from './factory.js';
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Canonically signs and verifies source requests using the Standard Webhooks scheme.
|
|
2
|
+
* Canonically signs and verifies source endpoint requests using the Standard Webhooks scheme.
|
|
3
3
|
*
|
|
4
4
|
* Every request Ablo sends to a data source is signed with that source's API
|
|
5
5
|
* key, and the receiving endpoint verifies the signature before any handler
|