@abloatai/ablo 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +101 -85
- package/dist/BaseSyncedStore.d.ts +85 -88
- package/dist/BaseSyncedStore.js +131 -147
- package/dist/Database.d.ts +54 -68
- package/dist/Database.js +97 -113
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +12 -16
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +46 -61
- package/dist/ModelRegistry.d.ts +21 -19
- package/dist/ModelRegistry.js +23 -27
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +5 -6
- package/dist/SyncClient.d.ts +112 -112
- package/dist/SyncClient.js +165 -172
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +9 -9
- package/dist/adapters/inMemoryStorage.js +9 -9
- package/dist/agent/Agent.d.ts +27 -32
- package/dist/agent/Agent.js +18 -19
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +5 -5
- package/dist/agent/session.d.ts +47 -44
- package/dist/agent/session.js +37 -48
- package/dist/agent/types.d.ts +26 -31
- package/dist/agent/types.js +6 -7
- package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
- package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
- package/dist/ai-sdk/coordinationContext.d.ts +46 -0
- package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +6 -7
- package/dist/ai-sdk/wrap.js +1 -1
- package/dist/auth/credentialPolicy.d.ts +69 -74
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +6 -5
- package/dist/auth/credentialSource.js +9 -10
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +31 -37
- package/dist/auth/schemas.d.ts +5 -4
- package/dist/auth/schemas.js +5 -4
- package/dist/batching/index.d.ts +19 -21
- package/dist/batching/index.js +14 -17
- package/dist/cli.cjs +167 -119
- package/dist/client/Ablo.d.ts +73 -73
- package/dist/client/Ablo.js +125 -160
- package/dist/client/ApiClient.d.ts +30 -19
- package/dist/client/ApiClient.js +133 -38
- package/dist/client/auth.d.ts +47 -47
- package/dist/client/auth.js +108 -117
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +5 -6
- package/dist/client/consoleLogger.js +5 -6
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +25 -30
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +152 -122
- package/dist/client/credentialEndpoint.d.ts +40 -42
- package/dist/client/credentialEndpoint.js +35 -36
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +9 -12
- package/dist/client/hostedEndpoints.js +9 -12
- package/dist/client/httpClient.d.ts +57 -53
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +47 -58
- package/dist/client/modelRegistration.d.ts +5 -9
- package/dist/client/modelRegistration.js +67 -87
- package/dist/client/options.d.ts +134 -157
- package/dist/client/options.js +3 -7
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +64 -75
- package/dist/client/resourceTypes.js +4 -10
- package/dist/client/schemaConfig.d.ts +31 -43
- package/dist/client/schemaConfig.js +38 -50
- package/dist/client/sessionMint.d.ts +16 -12
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +8 -9
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +15 -20
- package/dist/client/wsMutationExecutor.js +17 -23
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -4
- package/dist/coordination/index.d.ts +10 -8
- package/dist/coordination/index.js +14 -12
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -10
- package/dist/coordination/trace.js +13 -14
- package/dist/core/DatabaseManager.d.ts +5 -7
- package/dist/core/DatabaseManager.js +15 -19
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +22 -28
- package/dist/core/QueryView.d.ts +8 -8
- package/dist/core/QueryView.js +2 -2
- package/dist/core/StoreManager.d.ts +12 -14
- package/dist/core/StoreManager.js +21 -24
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +17 -12
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +42 -43
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +63 -61
- package/dist/core/storeContract.js +8 -12
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +107 -99
- package/dist/errorCodes.js +131 -132
- package/dist/errors.d.ts +160 -166
- package/dist/errors.js +155 -158
- package/dist/index.d.ts +30 -27
- package/dist/index.js +89 -86
- package/dist/interfaces/index.d.ts +102 -113
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +41 -40
- package/dist/mutators/RecordingTransaction.d.ts +16 -16
- package/dist/mutators/RecordingTransaction.js +31 -37
- package/dist/mutators/Transaction.d.ts +18 -26
- package/dist/mutators/Transaction.js +14 -20
- package/dist/mutators/UndoManager.d.ts +122 -131
- package/dist/mutators/UndoManager.js +145 -156
- package/dist/mutators/defineMutators.d.ts +23 -34
- package/dist/mutators/defineMutators.js +14 -20
- package/dist/mutators/inverseOp.d.ts +12 -15
- package/dist/mutators/inverseOp.js +12 -15
- package/dist/mutators/mutateActions.d.ts +10 -9
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +9 -8
- package/dist/mutators/readerActions.js +2 -2
- package/dist/mutators/undoApply.d.ts +31 -27
- package/dist/mutators/undoApply.js +26 -24
- package/dist/policy/index.d.ts +5 -3
- package/dist/policy/index.js +5 -3
- package/dist/policy/types.d.ts +104 -100
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +28 -23
- package/dist/query/client.js +45 -43
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +1 -1
- package/dist/react/AbloProvider.js +2 -2
- package/dist/react/context.d.ts +25 -28
- package/dist/react/context.js +9 -10
- package/dist/react/index.d.ts +41 -42
- package/dist/react/index.js +37 -38
- package/dist/react/internalContext.d.ts +17 -19
- package/dist/react/useAblo.d.ts +23 -22
- package/dist/react/useAblo.js +16 -14
- package/dist/react/useCurrentUserId.d.ts +8 -7
- package/dist/react/useCurrentUserId.js +8 -7
- package/dist/react/useErrorListener.d.ts +7 -7
- package/dist/react/useErrorListener.js +10 -11
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +8 -8
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useReactive.js +2 -2
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +21 -25
- package/dist/schema/coordination.js +21 -25
- package/dist/schema/ddl.d.ts +43 -39
- package/dist/schema/ddl.js +75 -68
- package/dist/schema/ddlLock.d.ts +20 -24
- package/dist/schema/ddlLock.js +18 -23
- package/dist/schema/diff.d.ts +99 -61
- package/dist/schema/diff.js +43 -34
- package/dist/schema/field.d.ts +37 -42
- package/dist/schema/field.js +35 -48
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +21 -23
- package/dist/schema/model.d.ts +118 -143
- package/dist/schema/model.js +22 -33
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +5 -3
- package/dist/schema/queries.d.ts +29 -31
- package/dist/schema/queries.js +23 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +16 -13
- package/dist/schema/residency.js +16 -13
- package/dist/schema/roles.d.ts +36 -43
- package/dist/schema/roles.js +31 -37
- package/dist/schema/schema.d.ts +33 -42
- package/dist/schema/schema.js +31 -32
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +28 -31
- package/dist/schema/serialize.js +27 -31
- package/dist/schema/sugar.d.ts +17 -32
- package/dist/schema/sugar.js +14 -29
- package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
- package/dist/schema/syncDeltaRow.js +89 -0
- package/dist/schema/tenancy.d.ts +44 -46
- package/dist/schema/tenancy.js +46 -48
- package/dist/server/adapter.d.ts +58 -58
- package/dist/server/adapter.js +13 -14
- package/dist/server/commit.d.ts +60 -64
- package/dist/server/index.d.ts +9 -10
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +70 -0
- package/dist/server/readConfig.js +8 -0
- package/dist/server/storageMode.d.ts +23 -0
- package/dist/server/storageMode.js +17 -0
- package/dist/source/adapter.d.ts +30 -25
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +30 -25
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +24 -23
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +9 -8
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +22 -25
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +17 -11
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +28 -28
- package/dist/source/connectorProtocol.d.ts +160 -0
- package/dist/source/connectorProtocol.js +162 -0
- package/dist/source/contract.d.ts +26 -27
- package/dist/source/contract.js +28 -29
- package/dist/source/factory.d.ts +46 -58
- package/dist/source/factory.js +22 -27
- package/dist/source/index.d.ts +7 -9
- package/dist/source/index.js +12 -14
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +9 -10
- package/dist/source/next.js +6 -7
- package/dist/source/pushQueue.d.ts +69 -47
- package/dist/source/pushQueue.js +32 -28
- package/dist/source/signing.d.ts +46 -17
- package/dist/source/signing.js +28 -11
- package/dist/source/types.d.ts +121 -104
- package/dist/source/types.js +13 -14
- package/dist/stores/ObjectStore.d.ts +10 -11
- package/dist/stores/ObjectStore.js +11 -12
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +7 -11
- package/dist/stores/SyncActionStore.js +13 -17
- package/dist/surface.d.ts +27 -20
- package/dist/surface.js +27 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
- package/dist/sync/ConnectionManager.d.ts +39 -50
- package/dist/sync/ConnectionManager.js +55 -66
- package/dist/sync/NetworkProbe.d.ts +24 -29
- package/dist/sync/NetworkProbe.js +63 -69
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
- package/dist/sync/SyncWebSocket.d.ts +139 -165
- package/dist/sync/SyncWebSocket.js +191 -223
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +11 -11
- package/dist/sync/bootstrapApply.d.ts +34 -24
- package/dist/sync/bootstrapApply.js +27 -19
- package/dist/sync/commitFrames.d.ts +21 -20
- package/dist/sync/commitFrames.js +18 -18
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +105 -23
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +12 -14
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +104 -104
- package/dist/sync/credentialLifecycle.js +140 -147
- package/dist/sync/deltaPipeline.d.ts +36 -34
- package/dist/sync/deltaPipeline.js +64 -65
- package/dist/sync/groupChange.d.ts +63 -61
- package/dist/sync/groupChange.js +74 -78
- package/dist/sync/heartbeat.d.ts +34 -33
- package/dist/sync/heartbeat.js +31 -31
- package/dist/sync/participants.d.ts +19 -19
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +17 -21
- package/dist/sync/syncCursor.js +17 -21
- package/dist/sync/syncPlan.d.ts +28 -36
- package/dist/sync/syncPlan.js +18 -19
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +35 -36
- package/dist/sync/wsFrameHandlers.js +63 -67
- package/dist/testing/fixtures/bootstrap.d.ts +12 -6
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +30 -33
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +11 -10
- package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
- package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
- package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +2 -2
- package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
- package/dist/testing/mocks/MockMutationExecutor.js +15 -14
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
- package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
- package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
- package/dist/testing/mocks/MockSyncContext.js +15 -13
- package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +181 -176
- package/dist/transactions/TransactionQueue.js +338 -350
- package/dist/transactions/TransactionStore.d.ts +6 -4
- package/dist/transactions/TransactionStore.js +6 -4
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +41 -17
- package/dist/transactions/coalesceRules.js +40 -17
- package/dist/transactions/commitPayload.d.ts +48 -52
- package/dist/transactions/commitPayload.js +48 -57
- package/dist/transactions/deltaConfirmation.d.ts +20 -22
- package/dist/transactions/deltaConfirmation.js +37 -45
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
- package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +71 -77
- package/dist/types/index.js +22 -22
- package/dist/types/modelData.d.ts +6 -8
- package/dist/types/modelData.js +5 -7
- package/dist/types/participant.d.ts +10 -11
- package/dist/types/participant.js +6 -8
- package/dist/types/streams.d.ts +208 -195
- package/dist/types/streams.js +7 -7
- package/dist/utils/asyncIterator.d.ts +25 -32
- package/dist/utils/asyncIterator.js +25 -32
- package/dist/utils/duration.d.ts +12 -15
- package/dist/utils/duration.js +12 -15
- package/dist/utils/mobxSetup.d.ts +53 -0
- package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
- package/dist/webhooks/events.d.ts +21 -16
- package/dist/webhooks/events.js +10 -8
- package/dist/webhooks/index.d.ts +5 -7
- package/dist/webhooks/index.js +5 -7
- package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
- package/dist/wire/delta.js +114 -0
- package/dist/wire/errorEnvelope.d.ts +30 -31
- package/dist/wire/errorEnvelope.js +34 -40
- package/dist/wire/frames.d.ts +79 -86
- package/dist/wire/frames.js +26 -33
- package/dist/wire/index.d.ts +14 -12
- package/dist/wire/index.js +30 -26
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +25 -32
- package/dist/wire/protocol.js +25 -32
- package/dist/wire/protocolVersion.d.ts +44 -40
- package/dist/wire/protocolVersion.js +44 -40
- package/docs/coordination.md +59 -0
- package/package.json +11 -10
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/read-config.d.ts +0 -67
- package/dist/server/read-config.js +0 -8
- package/dist/server/storage-mode.d.ts +0 -8
- package/dist/server/storage-mode.js +0 -28
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/transactions/optimistic.d.ts +0 -24
- package/dist/transactions/optimistic.js +0 -45
- package/dist/utils/mobx-setup.d.ts +0 -42
package/dist/keys/index.d.ts
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* and the web control-plane (`generate-key.ts`) consume THIS module, so the
|
|
5
|
-
* format can no longer drift between the two mint sites (it used to live as
|
|
6
|
-
* a hand-copied twin kept in sync by a comment).
|
|
2
|
+
* The Ablo API-key format: how keys are minted, hashed, and validated, in one
|
|
3
|
+
* place so every component that issues or checks a key agrees on the format.
|
|
7
4
|
*
|
|
8
|
-
*
|
|
9
|
-
* subpath and
|
|
10
|
-
*
|
|
5
|
+
* This module uses `node:crypto` and is therefore Node-only. It is published on
|
|
6
|
+
* the `@abloatai/ablo/keys` subpath and kept off the main browser-facing entry
|
|
7
|
+
* so a browser bundle never pulls in `node:crypto`.
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* (
|
|
18
|
-
*
|
|
9
|
+
* A key looks like `<sk|rk|ek|pk>_<live|test>_<30 base62 chars><6-char base62
|
|
10
|
+
* CRC32 checksum>`. The middle segment is the stable environment prefix, mapped
|
|
11
|
+
* on parse to `production` or `sandbox`. The recognizable prefix lets secret
|
|
12
|
+
* scanners spot a leaked key, and the trailing checksum lets the format reject a
|
|
13
|
+
* mistyped or forged key locally, without a database round-trip. Older keys
|
|
14
|
+
* (roughly a 43-character base64url body with no checksum) still validate by hash
|
|
15
|
+
* and parse here with `checksummed: false`.
|
|
19
16
|
*/
|
|
20
17
|
import { z } from 'zod';
|
|
21
18
|
import { type Environment } from '../environment.js';
|
|
@@ -35,10 +32,10 @@ export interface ParsedApiKey {
|
|
|
35
32
|
checksummed: boolean;
|
|
36
33
|
}
|
|
37
34
|
/**
|
|
38
|
-
*
|
|
39
|
-
* {@link ParsedApiKey}
|
|
40
|
-
* rejected
|
|
41
|
-
* `checksummed: false` and
|
|
35
|
+
* The Zod schema for an Ablo API key. `parse` and `safeParse` return a typed
|
|
36
|
+
* {@link ParsedApiKey}. A checksummed-format key whose checksum does not match is
|
|
37
|
+
* rejected without any network call; an older key with no checksum parses with
|
|
38
|
+
* `checksummed: false` and is left for the server to validate by hash.
|
|
42
39
|
*/
|
|
43
40
|
export declare const apiKeySchema: z.ZodPipe<z.ZodString, z.ZodTransform<ParsedApiKey, string>>;
|
|
44
41
|
/** Parse + fully validate (incl. checksum). Returns null when invalid. */
|
|
@@ -57,21 +54,22 @@ export declare function generateApiKey(env?: ApiKeyEnv, kind?: ApiKeyKind): {
|
|
|
57
54
|
prefix: string;
|
|
58
55
|
};
|
|
59
56
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
57
|
+
* The stable SHA-256 hex digest of a plaintext key, computed both when a key is
|
|
58
|
+
* minted and when one is looked up. A fast hash is the right choice here rather
|
|
59
|
+
* than a password hash like bcrypt: API keys are long random strings, so there is
|
|
60
|
+
* no dictionary of guesses to slow down.
|
|
63
61
|
*/
|
|
64
62
|
export declare function hashApiKey(plaintext: string): string;
|
|
65
63
|
/** `whsec_` label prefix per the Standard Webhooks spec (not part of the key material). */
|
|
66
64
|
export declare const WEBHOOK_SECRET_PREFIX = "whsec_";
|
|
67
65
|
/**
|
|
68
|
-
*
|
|
69
|
-
* (https://www.standardwebhooks.com): a base64-encoded random key
|
|
70
|
-
* labelled with the `whsec_` prefix.
|
|
71
|
-
* inside
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* creation, and never
|
|
66
|
+
* Mints a webhook signing secret following the Standard Webhooks specification
|
|
67
|
+
* (https://www.standardwebhooks.com): a base64-encoded random key of 24–64 bytes,
|
|
68
|
+
* labelled with the `whsec_` prefix. This uses 32 bytes (256 bits), comfortably
|
|
69
|
+
* inside that range. Unlike an API key, a signing secret is not hashed at rest,
|
|
70
|
+
* because signing a request with {@link signAbloSourceRequest} needs the live
|
|
71
|
+
* value. It is therefore kept in a secret store, returned to the customer once at
|
|
72
|
+
* creation, and never shown again.
|
|
75
73
|
*/
|
|
76
74
|
export declare function generateWebhookSecret(): {
|
|
77
75
|
plaintext: string;
|
package/dist/keys/index.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* and the web control-plane (`generate-key.ts`) consume THIS module, so the
|
|
5
|
-
* format can no longer drift between the two mint sites (it used to live as
|
|
6
|
-
* a hand-copied twin kept in sync by a comment).
|
|
2
|
+
* The Ablo API-key format: how keys are minted, hashed, and validated, in one
|
|
3
|
+
* place so every component that issues or checks a key agrees on the format.
|
|
7
4
|
*
|
|
8
|
-
*
|
|
9
|
-
* subpath and
|
|
10
|
-
*
|
|
5
|
+
* This module uses `node:crypto` and is therefore Node-only. It is published on
|
|
6
|
+
* the `@abloatai/ablo/keys` subpath and kept off the main browser-facing entry
|
|
7
|
+
* so a browser bundle never pulls in `node:crypto`.
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* (
|
|
18
|
-
*
|
|
9
|
+
* A key looks like `<sk|rk|ek|pk>_<live|test>_<30 base62 chars><6-char base62
|
|
10
|
+
* CRC32 checksum>`. The middle segment is the stable environment prefix, mapped
|
|
11
|
+
* on parse to `production` or `sandbox`. The recognizable prefix lets secret
|
|
12
|
+
* scanners spot a leaked key, and the trailing checksum lets the format reject a
|
|
13
|
+
* mistyped or forged key locally, without a database round-trip. Older keys
|
|
14
|
+
* (roughly a 43-character base64url body with no checksum) still validate by hash
|
|
15
|
+
* and parse here with `checksummed: false`.
|
|
19
16
|
*/
|
|
20
17
|
import { createHash, randomBytes } from 'node:crypto';
|
|
21
18
|
import { z } from 'zod';
|
|
22
19
|
import { ENVIRONMENTS, environmentFromKeyPrefix, environmentToKeyPrefix, } from '../environment.js';
|
|
23
20
|
// ── Vocabulary ──────────────────────────────────────────────────────────
|
|
24
|
-
// The
|
|
25
|
-
// secret (sk_) — backend
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
21
|
+
// The four key kinds:
|
|
22
|
+
// secret (sk_) — backend and server-to-server use, including agents. Full
|
|
23
|
+
// authority; never expose one in a browser.
|
|
24
|
+
// restricted (rk_) — a scoped server key, such as an agent session token or a
|
|
25
|
+
// narrowed capability.
|
|
26
|
+
// ephemeral (ek_) — a short-lived, backend-minted session credential scoped to
|
|
27
|
+
// one user, safe to hand to that user's browser. Carries
|
|
28
|
+
// `participantKind: 'user'` and its baked-in sync groups.
|
|
29
|
+
// publishable (pk_) — a long-lived, browser-safe, organization-scoped read-only
|
|
30
|
+
// key. It is used directly as the bearer token — never
|
|
31
|
+
// exchanged, never expires, nothing to refresh. It grants
|
|
32
|
+
// read access to the organization's data and cannot write or
|
|
33
|
+
// reach any control-plane operation.
|
|
34
34
|
export const API_KEY_KINDS = ['secret', 'restricted', 'ephemeral', 'publishable'];
|
|
35
35
|
export const API_KEY_ENVS = ENVIRONMENTS;
|
|
36
36
|
const PREFIX_BY_KIND = {
|
|
@@ -52,7 +52,7 @@ const KEY_BODY_LEN = 30;
|
|
|
52
52
|
const CHECKSUM_LEN = 6;
|
|
53
53
|
/** A new checksummed body is exactly this long and pure base62. */
|
|
54
54
|
const CHECKSUMMED_BODY_LEN = KEY_BODY_LEN + CHECKSUM_LEN;
|
|
55
|
-
/** `<sk|rk|ek|pk>_<live|test>_<body>`; body charset covers base62
|
|
55
|
+
/** `<sk|rk|ek|pk>_<live|test>_<body>`; the body charset covers base62 as well as the legacy base64url form. */
|
|
56
56
|
const KEY_RE = /^(sk|rk|ek|pk)_(live|test)_([0-9A-Za-z\-_]+)$/;
|
|
57
57
|
const BASE62_RE = /^[0-9A-Za-z]+$/;
|
|
58
58
|
// ── Checksum (standard CRC-32, GitHub-compatible) ───────────────────────
|
|
@@ -102,10 +102,10 @@ function bodyIsChecksummed(body) {
|
|
|
102
102
|
return body.length === CHECKSUMMED_BODY_LEN && BASE62_RE.test(body);
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
106
|
-
* {@link ParsedApiKey}
|
|
107
|
-
* rejected
|
|
108
|
-
* `checksummed: false` and
|
|
105
|
+
* The Zod schema for an Ablo API key. `parse` and `safeParse` return a typed
|
|
106
|
+
* {@link ParsedApiKey}. A checksummed-format key whose checksum does not match is
|
|
107
|
+
* rejected without any network call; an older key with no checksum parses with
|
|
108
|
+
* `checksummed: false` and is left for the server to validate by hash.
|
|
109
109
|
*/
|
|
110
110
|
export const apiKeySchema = z.string().transform((raw, ctx) => {
|
|
111
111
|
const m = KEY_RE.exec(raw);
|
|
@@ -165,9 +165,10 @@ export function generateApiKey(env = 'production', kind = 'secret') {
|
|
|
165
165
|
return { plaintext, hash: hashApiKey(plaintext), prefix: plaintext.slice(0, 12) };
|
|
166
166
|
}
|
|
167
167
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
168
|
+
* The stable SHA-256 hex digest of a plaintext key, computed both when a key is
|
|
169
|
+
* minted and when one is looked up. A fast hash is the right choice here rather
|
|
170
|
+
* than a password hash like bcrypt: API keys are long random strings, so there is
|
|
171
|
+
* no dictionary of guesses to slow down.
|
|
171
172
|
*/
|
|
172
173
|
export function hashApiKey(plaintext) {
|
|
173
174
|
return createHash('sha256').update(plaintext).digest('hex');
|
|
@@ -175,13 +176,13 @@ export function hashApiKey(plaintext) {
|
|
|
175
176
|
/** `whsec_` label prefix per the Standard Webhooks spec (not part of the key material). */
|
|
176
177
|
export const WEBHOOK_SECRET_PREFIX = 'whsec_';
|
|
177
178
|
/**
|
|
178
|
-
*
|
|
179
|
-
* (https://www.standardwebhooks.com): a base64-encoded random key
|
|
180
|
-
* labelled with the `whsec_` prefix.
|
|
181
|
-
* inside
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* creation, and never
|
|
179
|
+
* Mints a webhook signing secret following the Standard Webhooks specification
|
|
180
|
+
* (https://www.standardwebhooks.com): a base64-encoded random key of 24–64 bytes,
|
|
181
|
+
* labelled with the `whsec_` prefix. This uses 32 bytes (256 bits), comfortably
|
|
182
|
+
* inside that range. Unlike an API key, a signing secret is not hashed at rest,
|
|
183
|
+
* because signing a request with {@link signAbloSourceRequest} needs the live
|
|
184
|
+
* value. It is therefore kept in a secret store, returned to the customer once at
|
|
185
|
+
* creation, and never shown again.
|
|
185
186
|
*/
|
|
186
187
|
export function generateWebhookSecret() {
|
|
187
188
|
const plaintext = `${WEBHOOK_SECRET_PREFIX}${randomBytes(32).toString('base64')}`;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Wraps a {@link Transaction} and records the inverse of every write so the
|
|
3
|
+
* change can be undone. Each write is observed just before it runs, to snapshot
|
|
4
|
+
* the previous state, and just after, to record the forward operation for redo.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
* pushes
|
|
6
|
+
* The mutator sees an ordinary `Transaction<S>` and is unaware it is being
|
|
7
|
+
* recorded. When the mutator returns, the caller reads
|
|
8
|
+
* {@link RecordingTransaction.getEntry} and pushes the result onto the active
|
|
9
|
+
* {@link UndoScope}.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* post-creation (schema generates UUIDs if caller omitted one).
|
|
11
|
+
* The snapshots are taken here rather than in the undo scope because they must
|
|
12
|
+
* exist before the write lands: the inverse of an update needs the field's
|
|
13
|
+
* previous values, and the inverse of a delete needs the full row. The inverse
|
|
14
|
+
* of a create is just a delete by id, but that id is known only after creation,
|
|
15
|
+
* since the schema generates one when the caller omits it.
|
|
16
16
|
*/
|
|
17
17
|
import type { Schema } from '../schema/schema.js';
|
|
18
18
|
import type { SyncStoreContract } from '../react/context.js';
|
|
@@ -28,9 +28,9 @@ export interface RecordingTransaction<S extends Schema> {
|
|
|
28
28
|
getEntry: (label?: string) => UndoEntry | null;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
31
|
+
* Builds a transaction that records the forward and inverse of each write as it
|
|
32
|
+
* runs. Use this only when the mutator should be undoable; a read-only or
|
|
33
|
+
* side-effect-only mutator should call {@link createTransaction} directly to skip
|
|
34
|
+
* the bookkeeping.
|
|
35
35
|
*/
|
|
36
36
|
export declare function createRecordingTransaction<S extends Schema>(schema: S, store: SyncStoreContract, organizationId: string): RecordingTransaction<S>;
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Wraps a {@link Transaction} and records the inverse of every write so the
|
|
3
|
+
* change can be undone. Each write is observed just before it runs, to snapshot
|
|
4
|
+
* the previous state, and just after, to record the forward operation for redo.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
* pushes
|
|
6
|
+
* The mutator sees an ordinary `Transaction<S>` and is unaware it is being
|
|
7
|
+
* recorded. When the mutator returns, the caller reads
|
|
8
|
+
* {@link RecordingTransaction.getEntry} and pushes the result onto the active
|
|
9
|
+
* {@link UndoScope}.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* post-creation (schema generates UUIDs if caller omitted one).
|
|
11
|
+
* The snapshots are taken here rather than in the undo scope because they must
|
|
12
|
+
* exist before the write lands: the inverse of an update needs the field's
|
|
13
|
+
* previous values, and the inverse of a delete needs the full row. The inverse
|
|
14
|
+
* of a create is just a delete by id, but that id is known only after creation,
|
|
15
|
+
* since the schema generates one when the caller omits it.
|
|
16
16
|
*/
|
|
17
17
|
import { createTransaction } from './Transaction.js';
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
19
|
+
* Builds a transaction that records the forward and inverse of each write as it
|
|
20
|
+
* runs. Use this only when the mutator should be undoable; a read-only or
|
|
21
|
+
* side-effect-only mutator should call {@link createTransaction} directly to skip
|
|
22
|
+
* the bookkeeping.
|
|
23
23
|
*/
|
|
24
24
|
export function createRecordingTransaction(schema, store, organizationId) {
|
|
25
25
|
const inverses = [];
|
|
@@ -42,8 +42,8 @@ export function createRecordingTransaction(schema, store, organizationId) {
|
|
|
42
42
|
getEntry: (label) => {
|
|
43
43
|
if (inverses.length === 0)
|
|
44
44
|
return null;
|
|
45
|
-
// Undo applies inverses in
|
|
46
|
-
//
|
|
45
|
+
// Undo applies the inverses in reverse order of the forward writes; redo
|
|
46
|
+
// applies the forwards in their original order.
|
|
47
47
|
return { label, inverses: [...inverses].reverse(), forwards: [...forwards] };
|
|
48
48
|
},
|
|
49
49
|
};
|
|
@@ -54,30 +54,24 @@ function wrapMutateForKey(modelKey, mutate, store, inverses, forwards) {
|
|
|
54
54
|
const model = store.pool.get(id);
|
|
55
55
|
if (!model)
|
|
56
56
|
return null;
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
// wider shape is exactly right.
|
|
57
|
+
// toJSON produces a plain object suitable for re-creating the row. The
|
|
58
|
+
// delete→create inverse needs every field, which is exactly what it returns.
|
|
60
59
|
return model.toJSON();
|
|
61
60
|
};
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
// a field that was neither pre-mutated nor in the original snapshot. (The
|
|
67
|
-
// stream path passes `false` so it can omit-and-drop instead — that flag is
|
|
68
|
-
// the one intentional difference between the two callers.)
|
|
61
|
+
// Captures the before-image for an undo inverse, delegating to the model's
|
|
62
|
+
// shared `capturePreviousValues`. `fallbackToLive` is enabled here so that a
|
|
63
|
+
// field that was neither pre-mutated nor present in the original snapshot falls
|
|
64
|
+
// back to its current value as a last resort.
|
|
69
65
|
const snapshotFields = (id, fieldNames) => {
|
|
70
66
|
const model = store.pool.get(id);
|
|
71
67
|
if (!model)
|
|
72
68
|
return null;
|
|
73
69
|
return model.capturePreviousValues(fieldNames, { fallbackToLive: true });
|
|
74
70
|
};
|
|
75
|
-
// After
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
// so this clear is safe for server rollback. Shared with the stream path via
|
|
80
|
-
// `Model.consumeModifiedFields`.
|
|
71
|
+
// After an update succeeds, clear the modified-field markers it was snapshotted
|
|
72
|
+
// from, so the next write to the same row sees this update's result as its
|
|
73
|
+
// baseline rather than the older pre-update value. The queue has already taken
|
|
74
|
+
// its own frozen copy, so clearing here is safe.
|
|
81
75
|
const consumeModifiedFields = (id, fieldNames) => {
|
|
82
76
|
store.pool.get(id)?.consumeModifiedFields(fieldNames);
|
|
83
77
|
};
|
|
@@ -110,9 +104,9 @@ function wrapMutateForKey(modelKey, mutate, store, inverses, forwards) {
|
|
|
110
104
|
}),
|
|
111
105
|
update: (async (patch) => {
|
|
112
106
|
if (Array.isArray(patch)) {
|
|
113
|
-
// Snapshot
|
|
114
|
-
// in the same list would corrupt
|
|
115
|
-
//
|
|
107
|
+
// Snapshot every row's previous values before applying any patch: later
|
|
108
|
+
// patches in the same list would corrupt an earlier one's inverse if the
|
|
109
|
+
// snapshots were taken lazily.
|
|
116
110
|
const prevPatches = [];
|
|
117
111
|
for (const p of patch) {
|
|
118
112
|
const fields = Object.keys(p).filter((k) => k !== 'id');
|
|
@@ -1,35 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The typed transaction object passed to a custom mutator. A mutator receives
|
|
3
|
+
* `{ tx, args }` and uses `tx.mutations.<modelKey>.*` to write and
|
|
4
|
+
* `tx.read.<modelKey>.*` to take synchronous snapshots of the current data.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* snapshots
|
|
6
|
+
* Writes are applied eagerly as they are called, with no buffering: if a mutator
|
|
7
|
+
* throws partway through, the writes it already made stand. Reads are synchronous
|
|
8
|
+
* snapshots and use a fast index lookup where one is available for the field.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* FK index fast path where available (O(1) on registered FK fields).
|
|
14
|
-
*
|
|
15
|
-
* The mutate surface is intentionally one-row-at-a-time
|
|
16
|
-
* (`create`/`update`/`delete`). For batches, mutator authors compose
|
|
17
|
-
* `Promise.all(rows.map((r) => tx.mutations.x.create(r)))` — every push
|
|
18
|
-
* stages in the same synchronous tick, the await happens once, and the
|
|
19
|
-
* microtask coalescer in `TransactionQueue` collapses N pushes into one
|
|
20
|
-
* wire commit. Same shape Zero uses: no `insertMany`, just an array map.
|
|
10
|
+
* The write surface deliberately works one row at a time. To write a batch,
|
|
11
|
+
* compose the calls yourself — `Promise.all(rows.map((r) => tx.mutations.x.create(r)))`.
|
|
12
|
+
* Every call stages its write in the same synchronous tick and the engine
|
|
13
|
+
* coalesces them into a single commit on the wire, so there is no separate
|
|
14
|
+
* bulk-insert method to learn.
|
|
21
15
|
*/
|
|
22
16
|
import type { Schema } from '../schema/schema.js';
|
|
23
17
|
import type { SyncStoreContract } from '../react/context.js';
|
|
24
18
|
import { type MutateActions } from './mutateActions.js';
|
|
25
19
|
import { type ReaderActions, type ReaderFindOptions } from './readerActions.js';
|
|
26
20
|
/**
|
|
27
|
-
* The full transaction surface
|
|
28
|
-
* `tx.read.<key>.*` for
|
|
29
|
-
*
|
|
30
|
-
* the React
|
|
31
|
-
*
|
|
32
|
-
* The name `mutations` (not `mutate`) matches the React hook naming.
|
|
21
|
+
* The full transaction surface: `tx.mutations.<key>.*` for writes and
|
|
22
|
+
* `tx.read.<key>.*` for reads. It also re-exports the read-options type so a
|
|
23
|
+
* mutator author can type a `where` payload without importing it separately. The
|
|
24
|
+
* property is named `mutations` to match the corresponding React hook.
|
|
33
25
|
*/
|
|
34
26
|
export interface Transaction<S extends Schema> {
|
|
35
27
|
mutations: {
|
|
@@ -41,8 +33,8 @@ export interface Transaction<S extends Schema> {
|
|
|
41
33
|
}
|
|
42
34
|
export type { ReaderFindOptions };
|
|
43
35
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
36
|
+
* Builds a {@link Transaction} for a single mutator invocation. The returned
|
|
37
|
+
* object creates each model's actions lazily on first access, so a mutator pays
|
|
38
|
+
* nothing for the models it never touches.
|
|
47
39
|
*/
|
|
48
40
|
export declare function createTransaction<S extends Schema>(schema: S, store: SyncStoreContract, organizationId: string): Transaction<S>;
|
|
@@ -1,31 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The typed transaction object passed to a custom mutator. A mutator receives
|
|
3
|
+
* `{ tx, args }` and uses `tx.mutations.<modelKey>.*` to write and
|
|
4
|
+
* `tx.read.<modelKey>.*` to take synchronous snapshots of the current data.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* snapshots
|
|
6
|
+
* Writes are applied eagerly as they are called, with no buffering: if a mutator
|
|
7
|
+
* throws partway through, the writes it already made stand. Reads are synchronous
|
|
8
|
+
* snapshots and use a fast index lookup where one is available for the field.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* FK index fast path where available (O(1) on registered FK fields).
|
|
14
|
-
*
|
|
15
|
-
* The mutate surface is intentionally one-row-at-a-time
|
|
16
|
-
* (`create`/`update`/`delete`). For batches, mutator authors compose
|
|
17
|
-
* `Promise.all(rows.map((r) => tx.mutations.x.create(r)))` — every push
|
|
18
|
-
* stages in the same synchronous tick, the await happens once, and the
|
|
19
|
-
* microtask coalescer in `TransactionQueue` collapses N pushes into one
|
|
20
|
-
* wire commit. Same shape Zero uses: no `insertMany`, just an array map.
|
|
10
|
+
* The write surface deliberately works one row at a time. To write a batch,
|
|
11
|
+
* compose the calls yourself — `Promise.all(rows.map((r) => tx.mutations.x.create(r)))`.
|
|
12
|
+
* Every call stages its write in the same synchronous tick and the engine
|
|
13
|
+
* coalesces them into a single commit on the wire, so there is no separate
|
|
14
|
+
* bulk-insert method to learn.
|
|
21
15
|
*/
|
|
22
16
|
import { createMutateActions } from './mutateActions.js';
|
|
23
17
|
import { createReaderActions } from './readerActions.js';
|
|
24
18
|
import { AbloValidationError } from '../errors.js';
|
|
25
19
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
20
|
+
* Builds a {@link Transaction} for a single mutator invocation. The returned
|
|
21
|
+
* object creates each model's actions lazily on first access, so a mutator pays
|
|
22
|
+
* nothing for the models it never touches.
|
|
29
23
|
*/
|
|
30
24
|
export function createTransaction(schema, store, organizationId) {
|
|
31
25
|
const mutateCache = new Map();
|