@abloatai/ablo 0.26.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +101 -85
- package/dist/BaseSyncedStore.d.ts +85 -88
- package/dist/BaseSyncedStore.js +131 -147
- package/dist/Database.d.ts +54 -68
- package/dist/Database.js +97 -113
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +85 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +12 -16
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +46 -61
- package/dist/ModelRegistry.d.ts +21 -19
- package/dist/ModelRegistry.js +23 -27
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +5 -6
- package/dist/SyncClient.d.ts +112 -112
- package/dist/SyncClient.js +165 -172
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +9 -9
- package/dist/adapters/inMemoryStorage.js +9 -9
- package/dist/agent/Agent.d.ts +27 -32
- package/dist/agent/Agent.js +18 -19
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +5 -5
- package/dist/agent/session.d.ts +47 -44
- package/dist/agent/session.js +37 -48
- package/dist/agent/types.d.ts +26 -31
- package/dist/agent/types.js +6 -7
- package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
- package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
- package/dist/ai-sdk/coordinationContext.d.ts +46 -0
- package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +26 -33
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +6 -7
- package/dist/ai-sdk/wrap.js +1 -1
- package/dist/auth/credentialPolicy.d.ts +69 -74
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +6 -5
- package/dist/auth/credentialSource.js +9 -10
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +31 -37
- package/dist/auth/schemas.d.ts +5 -4
- package/dist/auth/schemas.js +5 -4
- package/dist/batching/index.d.ts +19 -21
- package/dist/batching/index.js +14 -17
- package/dist/cli.cjs +167 -119
- package/dist/client/Ablo.d.ts +73 -73
- package/dist/client/Ablo.js +125 -160
- package/dist/client/ApiClient.d.ts +30 -19
- package/dist/client/ApiClient.js +133 -38
- package/dist/client/auth.d.ts +47 -47
- package/dist/client/auth.js +108 -117
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +5 -6
- package/dist/client/consoleLogger.js +5 -6
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +25 -30
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +152 -122
- package/dist/client/credentialEndpoint.d.ts +40 -42
- package/dist/client/credentialEndpoint.js +35 -36
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +9 -12
- package/dist/client/hostedEndpoints.js +9 -12
- package/dist/client/httpClient.d.ts +57 -53
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +47 -58
- package/dist/client/modelRegistration.d.ts +5 -9
- package/dist/client/modelRegistration.js +67 -87
- package/dist/client/options.d.ts +134 -157
- package/dist/client/options.js +3 -7
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +64 -75
- package/dist/client/resourceTypes.js +4 -10
- package/dist/client/schemaConfig.d.ts +31 -43
- package/dist/client/schemaConfig.js +38 -50
- package/dist/client/sessionMint.d.ts +16 -12
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +8 -9
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +15 -20
- package/dist/client/wsMutationExecutor.js +17 -23
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -4
- package/dist/coordination/index.d.ts +10 -8
- package/dist/coordination/index.js +14 -12
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -10
- package/dist/coordination/trace.js +13 -14
- package/dist/core/DatabaseManager.d.ts +5 -7
- package/dist/core/DatabaseManager.js +15 -19
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +22 -28
- package/dist/core/QueryView.d.ts +8 -8
- package/dist/core/QueryView.js +2 -2
- package/dist/core/StoreManager.d.ts +12 -14
- package/dist/core/StoreManager.js +21 -24
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +17 -12
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +42 -43
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +63 -61
- package/dist/core/storeContract.js +8 -12
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +107 -99
- package/dist/errorCodes.js +131 -132
- package/dist/errors.d.ts +160 -166
- package/dist/errors.js +155 -158
- package/dist/index.d.ts +30 -27
- package/dist/index.js +89 -86
- package/dist/interfaces/index.d.ts +102 -113
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +41 -40
- package/dist/mutators/RecordingTransaction.d.ts +16 -16
- package/dist/mutators/RecordingTransaction.js +31 -37
- package/dist/mutators/Transaction.d.ts +18 -26
- package/dist/mutators/Transaction.js +14 -20
- package/dist/mutators/UndoManager.d.ts +122 -131
- package/dist/mutators/UndoManager.js +145 -156
- package/dist/mutators/defineMutators.d.ts +23 -34
- package/dist/mutators/defineMutators.js +14 -20
- package/dist/mutators/inverseOp.d.ts +12 -15
- package/dist/mutators/inverseOp.js +12 -15
- package/dist/mutators/mutateActions.d.ts +10 -9
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +9 -8
- package/dist/mutators/readerActions.js +2 -2
- package/dist/mutators/undoApply.d.ts +31 -27
- package/dist/mutators/undoApply.js +26 -24
- package/dist/policy/index.d.ts +5 -3
- package/dist/policy/index.js +5 -3
- package/dist/policy/types.d.ts +104 -100
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +28 -23
- package/dist/query/client.js +45 -43
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +1 -1
- package/dist/react/AbloProvider.js +2 -2
- package/dist/react/context.d.ts +25 -28
- package/dist/react/context.js +9 -10
- package/dist/react/index.d.ts +41 -42
- package/dist/react/index.js +37 -38
- package/dist/react/internalContext.d.ts +17 -19
- package/dist/react/useAblo.d.ts +23 -22
- package/dist/react/useAblo.js +16 -14
- package/dist/react/useCurrentUserId.d.ts +8 -7
- package/dist/react/useCurrentUserId.js +8 -7
- package/dist/react/useErrorListener.d.ts +7 -7
- package/dist/react/useErrorListener.js +10 -11
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +8 -8
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +3 -3
- package/dist/react/useReactive.js +2 -2
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +1 -1
- package/dist/schema/coordination.d.ts +21 -25
- package/dist/schema/coordination.js +21 -25
- package/dist/schema/ddl.d.ts +43 -39
- package/dist/schema/ddl.js +75 -68
- package/dist/schema/ddlLock.d.ts +20 -24
- package/dist/schema/ddlLock.js +18 -23
- package/dist/schema/diff.d.ts +99 -61
- package/dist/schema/diff.js +43 -34
- package/dist/schema/field.d.ts +37 -42
- package/dist/schema/field.js +35 -48
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +21 -23
- package/dist/schema/model.d.ts +118 -143
- package/dist/schema/model.js +22 -33
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +5 -3
- package/dist/schema/queries.d.ts +29 -31
- package/dist/schema/queries.js +23 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +16 -13
- package/dist/schema/residency.js +16 -13
- package/dist/schema/roles.d.ts +36 -43
- package/dist/schema/roles.js +31 -37
- package/dist/schema/schema.d.ts +33 -42
- package/dist/schema/schema.js +31 -32
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +28 -31
- package/dist/schema/serialize.js +27 -31
- package/dist/schema/sugar.d.ts +17 -32
- package/dist/schema/sugar.js +14 -29
- package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +26 -49
- package/dist/schema/syncDeltaRow.js +89 -0
- package/dist/schema/tenancy.d.ts +44 -46
- package/dist/schema/tenancy.js +46 -48
- package/dist/server/adapter.d.ts +58 -58
- package/dist/server/adapter.js +13 -14
- package/dist/server/commit.d.ts +60 -64
- package/dist/server/index.d.ts +9 -10
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +70 -0
- package/dist/server/readConfig.js +8 -0
- package/dist/server/storageMode.d.ts +23 -0
- package/dist/server/storageMode.js +17 -0
- package/dist/source/adapter.d.ts +30 -25
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +30 -25
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +24 -23
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +9 -8
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +22 -25
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +17 -11
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +28 -28
- package/dist/source/connectorProtocol.d.ts +160 -0
- package/dist/source/connectorProtocol.js +162 -0
- package/dist/source/contract.d.ts +26 -27
- package/dist/source/contract.js +28 -29
- package/dist/source/factory.d.ts +46 -58
- package/dist/source/factory.js +22 -27
- package/dist/source/index.d.ts +7 -9
- package/dist/source/index.js +12 -14
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +9 -10
- package/dist/source/next.js +6 -7
- package/dist/source/pushQueue.d.ts +69 -47
- package/dist/source/pushQueue.js +32 -28
- package/dist/source/signing.d.ts +46 -17
- package/dist/source/signing.js +28 -11
- package/dist/source/types.d.ts +121 -104
- package/dist/source/types.js +13 -14
- package/dist/stores/ObjectStore.d.ts +10 -11
- package/dist/stores/ObjectStore.js +11 -12
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +7 -11
- package/dist/stores/SyncActionStore.js +13 -17
- package/dist/surface.d.ts +27 -20
- package/dist/surface.js +27 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +36 -42
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +76 -76
- package/dist/sync/ConnectionManager.d.ts +39 -50
- package/dist/sync/ConnectionManager.js +55 -66
- package/dist/sync/NetworkProbe.d.ts +24 -29
- package/dist/sync/NetworkProbe.js +63 -69
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +42 -41
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +59 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +43 -57
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +43 -51
- package/dist/sync/SyncWebSocket.d.ts +139 -165
- package/dist/sync/SyncWebSocket.js +191 -223
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +11 -11
- package/dist/sync/bootstrapApply.d.ts +34 -24
- package/dist/sync/bootstrapApply.js +27 -19
- package/dist/sync/commitFrames.d.ts +21 -20
- package/dist/sync/commitFrames.js +18 -18
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +105 -23
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +12 -14
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +104 -104
- package/dist/sync/credentialLifecycle.js +140 -147
- package/dist/sync/deltaPipeline.d.ts +36 -34
- package/dist/sync/deltaPipeline.js +64 -65
- package/dist/sync/groupChange.d.ts +63 -61
- package/dist/sync/groupChange.js +74 -78
- package/dist/sync/heartbeat.d.ts +34 -33
- package/dist/sync/heartbeat.js +31 -31
- package/dist/sync/participants.d.ts +19 -19
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +17 -21
- package/dist/sync/syncCursor.js +17 -21
- package/dist/sync/syncPlan.d.ts +28 -36
- package/dist/sync/syncPlan.js +18 -19
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +35 -36
- package/dist/sync/wsFrameHandlers.js +63 -67
- package/dist/testing/fixtures/bootstrap.d.ts +12 -6
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +30 -33
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +11 -10
- package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
- package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
- package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -15
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +12 -10
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +2 -2
- package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
- package/dist/testing/mocks/MockMutationExecutor.js +15 -14
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
- package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
- package/dist/testing/mocks/MockSyncContext.d.ts +20 -17
- package/dist/testing/mocks/MockSyncContext.js +15 -13
- package/dist/testing/mocks/MockSyncStore.d.ts +10 -10
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +26 -22
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +181 -176
- package/dist/transactions/TransactionQueue.js +338 -350
- package/dist/transactions/TransactionStore.d.ts +6 -4
- package/dist/transactions/TransactionStore.js +6 -4
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +41 -17
- package/dist/transactions/coalesceRules.js +40 -17
- package/dist/transactions/commitPayload.d.ts +48 -52
- package/dist/transactions/commitPayload.js +48 -57
- package/dist/transactions/deltaConfirmation.d.ts +20 -22
- package/dist/transactions/deltaConfirmation.js +37 -45
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/{persistedReplay.d.ts → replayValidation.d.ts} +28 -22
- package/dist/transactions/{persistedReplay.js → replayValidation.js} +33 -27
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +71 -77
- package/dist/types/index.js +22 -22
- package/dist/types/modelData.d.ts +6 -8
- package/dist/types/modelData.js +5 -7
- package/dist/types/participant.d.ts +10 -11
- package/dist/types/participant.js +6 -8
- package/dist/types/streams.d.ts +208 -195
- package/dist/types/streams.js +7 -7
- package/dist/utils/asyncIterator.d.ts +25 -32
- package/dist/utils/asyncIterator.js +25 -32
- package/dist/utils/duration.d.ts +12 -15
- package/dist/utils/duration.js +12 -15
- package/dist/utils/mobxSetup.d.ts +53 -0
- package/dist/utils/{mobx-setup.js → mobxSetup.js} +42 -98
- package/dist/webhooks/events.d.ts +21 -16
- package/dist/webhooks/events.js +10 -8
- package/dist/webhooks/index.d.ts +5 -7
- package/dist/webhooks/index.js +5 -7
- package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
- package/dist/wire/delta.js +114 -0
- package/dist/wire/errorEnvelope.d.ts +30 -31
- package/dist/wire/errorEnvelope.js +34 -40
- package/dist/wire/frames.d.ts +79 -86
- package/dist/wire/frames.js +26 -33
- package/dist/wire/index.d.ts +14 -12
- package/dist/wire/index.js +30 -26
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +25 -32
- package/dist/wire/protocol.js +25 -32
- package/dist/wire/protocolVersion.d.ts +44 -40
- package/dist/wire/protocolVersion.js +44 -40
- package/docs/coordination.md +59 -0
- package/package.json +11 -10
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/read-config.d.ts +0 -67
- package/dist/server/read-config.js +0 -8
- package/dist/server/storage-mode.d.ts +0 -8
- package/dist/server/storage-mode.js +0 -28
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/transactions/optimistic.d.ts +0 -24
- package/dist/transactions/optimistic.js +0 -45
- package/dist/utils/mobx-setup.d.ts +0 -42
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Data Source reverse-channel wire protocol.
|
|
3
|
-
*
|
|
4
|
-
* The `commit`/`load`/`list` leg of Data Source mode is normally an INBOUND
|
|
5
|
-
* webhook (Ablo Cloud → your HTTPS endpoint). That requires a public URL, so it
|
|
6
|
-
* doesn't work on `localhost` or inside a locked-down VPC with no inbound path.
|
|
7
|
-
*
|
|
8
|
-
* The reverse channel inverts the direction: the customer's connector dials OUT
|
|
9
|
-
* to Ablo Cloud over a WebSocket and serves those same requests over the open
|
|
10
|
-
* socket — the Stripe-CLI `stripe listen` pattern. This module defines the
|
|
11
|
-
* frames that travel over that socket.
|
|
12
|
-
*
|
|
13
|
-
* Trust model is unchanged. A `request` frame carries the SAME Standard Webhooks
|
|
14
|
-
* signature headers (`webhook-id` / `webhook-timestamp` / `webhook-signature`)
|
|
15
|
-
* and the SAME raw body Ablo would have POSTed, so the connector verifies it
|
|
16
|
-
* through the unchanged `verifyAbloSourceRequest`. Only the transport differs.
|
|
17
|
-
*
|
|
18
|
-
* Frames are validated with zod at the boundary (matching `contract.ts`): a
|
|
19
|
-
* malformed frame is rejected at the edge, and every wire type is inferred from
|
|
20
|
-
* one schema so the two sides can never silently drift.
|
|
21
|
-
*/
|
|
22
|
-
import { z } from 'zod';
|
|
23
|
-
import { WS_BEARER_SUBPROTOCOL_PREFIX } from '../auth/credentialSource.js';
|
|
24
|
-
/**
|
|
25
|
-
* Wire-protocol version. Bumped on any breaking frame-shape change so an old
|
|
26
|
-
* connector talking to a new server (or vice-versa) fails fast at `register`
|
|
27
|
-
* instead of misparsing a frame mid-stream.
|
|
28
|
-
*/
|
|
29
|
-
export const SOURCE_CONNECTOR_PROTOCOL_VERSION = 1;
|
|
30
|
-
/** Path the connector dials. Appended to the connector's `baseURL`. */
|
|
31
|
-
export const SOURCE_CONNECTOR_WS_PATH = '/v1/source/listen';
|
|
32
|
-
/**
|
|
33
|
-
* Negotiated WebSocket subprotocol that marks a reverse-channel source
|
|
34
|
-
* connector (vs. the SDK sync client's `ablo.sync.v1`). The server selects and
|
|
35
|
-
* echoes back ONLY this value, never the token-bearing subprotocol — keeping the
|
|
36
|
-
* credential out of ALB / proxy logs exactly like the sync socket does.
|
|
37
|
-
*/
|
|
38
|
-
export const WS_SOURCE_SUBPROTOCOL = 'ablo.source.v1';
|
|
39
|
-
/**
|
|
40
|
-
* Build the `Sec-WebSocket-Protocol` list a connector offers: the source
|
|
41
|
-
* protocol plus the bearer credential (`ablo.bearer.<apiKey>`). Browsers can't
|
|
42
|
-
* set an `Authorization` header on a WebSocket, so the API key rides as a
|
|
43
|
-
* subprotocol — the same mechanism the SDK sync client uses, read server-side by
|
|
44
|
-
* the shared `extractBearer`.
|
|
45
|
-
*/
|
|
46
|
-
export function sourceConnectorSubprotocols(apiKey) {
|
|
47
|
-
return [WS_SOURCE_SUBPROTOCOL, `${WS_BEARER_SUBPROTOCOL_PREFIX}${apiKey}`];
|
|
48
|
-
}
|
|
49
|
-
const headerRecord = z.record(z.string(), z.string());
|
|
50
|
-
/**
|
|
51
|
-
* Connector → server, first frame after the socket opens and authenticates.
|
|
52
|
-
* Auth and source resolution happen at the WS handshake from the API key; this
|
|
53
|
-
* frame only carries protocol negotiation + advisory metadata.
|
|
54
|
-
*/
|
|
55
|
-
export const registerFrameSchema = z.object({
|
|
56
|
-
type: z.literal('register'),
|
|
57
|
-
protocolVersion: z.number().int(),
|
|
58
|
-
/**
|
|
59
|
-
* Advisory client identifier (e.g. `@abloatai/ablo@0.12.0`) for server-side
|
|
60
|
-
* logging. Not trusted for any decision.
|
|
61
|
-
*/
|
|
62
|
-
client: z.string().optional(),
|
|
63
|
-
});
|
|
64
|
-
/**
|
|
65
|
-
* Server → connector, acknowledges a successful `register`. Echoes the resolved
|
|
66
|
-
* source identity so the connector can log/verify which source it is serving.
|
|
67
|
-
*/
|
|
68
|
-
export const readyFrameSchema = z.object({
|
|
69
|
-
type: z.literal('ready'),
|
|
70
|
-
protocolVersion: z.number().int(),
|
|
71
|
-
sourceId: z.string().optional(),
|
|
72
|
-
organizationId: z.string().optional(),
|
|
73
|
-
environment: z.enum(['production', 'sandbox']).optional(),
|
|
74
|
-
});
|
|
75
|
-
/**
|
|
76
|
-
* Server → connector, one drained `commit`/`load`/`list` request. `headers` and
|
|
77
|
-
* `body` are byte-identical to what the inbound webhook path would have sent —
|
|
78
|
-
* the connector replays them into a synthesized `Request` so the unchanged
|
|
79
|
-
* handler verifies the signature exactly as in production.
|
|
80
|
-
*/
|
|
81
|
-
export const requestFrameSchema = z.object({
|
|
82
|
-
type: z.literal('request'),
|
|
83
|
-
/** Correlation id; the matching `response` frame carries the same value. */
|
|
84
|
-
id: z.string().min(1),
|
|
85
|
-
method: z.literal('POST'),
|
|
86
|
-
/** Synthetic absolute URL used only to construct the `Request` object. */
|
|
87
|
-
url: z.string().min(1),
|
|
88
|
-
/** Signed Standard Webhooks headers + `Content-Type`. */
|
|
89
|
-
headers: headerRecord,
|
|
90
|
-
/** Raw JSON request body — exactly the bytes that were signed. */
|
|
91
|
-
body: z.string(),
|
|
92
|
-
});
|
|
93
|
-
/**
|
|
94
|
-
* Connector → server, the handler's `Response` for one `request`. The server
|
|
95
|
-
* resolves the pending request keyed by `id` and feeds `status`/`body` back to
|
|
96
|
-
* the `SourceClient` as if an HTTP response had returned.
|
|
97
|
-
*/
|
|
98
|
-
export const responseFrameSchema = z.object({
|
|
99
|
-
type: z.literal('response'),
|
|
100
|
-
id: z.string().min(1),
|
|
101
|
-
status: z.number().int(),
|
|
102
|
-
headers: headerRecord.optional(),
|
|
103
|
-
/** Raw JSON response body. */
|
|
104
|
-
body: z.string(),
|
|
105
|
-
});
|
|
106
|
-
/**
|
|
107
|
-
* Either direction, out-of-band failure not tied to a single request body
|
|
108
|
-
* (auth rejected, unsupported protocol version, malformed frame). When `id` is
|
|
109
|
-
* present the error pertains to that pending request and fails it; otherwise it
|
|
110
|
-
* is a connection-level error.
|
|
111
|
-
*/
|
|
112
|
-
export const errorFrameSchema = z.object({
|
|
113
|
-
type: z.literal('error'),
|
|
114
|
-
id: z.string().min(1).optional(),
|
|
115
|
-
code: z.string().min(1),
|
|
116
|
-
message: z.string(),
|
|
117
|
-
});
|
|
118
|
-
export const connectorFrameSchema = z.discriminatedUnion('type', [
|
|
119
|
-
registerFrameSchema,
|
|
120
|
-
readyFrameSchema,
|
|
121
|
-
requestFrameSchema,
|
|
122
|
-
responseFrameSchema,
|
|
123
|
-
errorFrameSchema,
|
|
124
|
-
]);
|
|
125
|
-
/** Thrown when an incoming frame fails to parse or validate. */
|
|
126
|
-
export class ConnectorProtocolError extends Error {
|
|
127
|
-
code = 'source_connector_protocol_error';
|
|
128
|
-
constructor(message) {
|
|
129
|
-
super(message);
|
|
130
|
-
this.name = 'ConnectorProtocolError';
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
/** Serialize a frame for transmission. */
|
|
134
|
-
export function encodeFrame(frame) {
|
|
135
|
-
return JSON.stringify(frame);
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Parse + validate an incoming frame. Accepts the string or binary payloads the
|
|
139
|
-
* `ws` library / WebSocket `message` events deliver. Throws
|
|
140
|
-
* `ConnectorProtocolError` on any malformed or unknown frame so callers can
|
|
141
|
-
* reject the connection rather than act on garbage.
|
|
142
|
-
*/
|
|
143
|
-
export function decodeFrame(raw) {
|
|
144
|
-
const text = typeof raw === 'string' ? raw : decodeBinary(raw);
|
|
145
|
-
let parsed;
|
|
146
|
-
try {
|
|
147
|
-
parsed = JSON.parse(text);
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
throw new ConnectorProtocolError('Frame is not valid JSON');
|
|
151
|
-
}
|
|
152
|
-
const result = connectorFrameSchema.safeParse(parsed);
|
|
153
|
-
if (!result.success) {
|
|
154
|
-
throw new ConnectorProtocolError(`Invalid connector frame: ${result.error.message}`);
|
|
155
|
-
}
|
|
156
|
-
return result.data;
|
|
157
|
-
}
|
|
158
|
-
function decodeBinary(raw) {
|
|
159
|
-
const bytes = raw instanceof Uint8Array ? raw : new Uint8Array(raw);
|
|
160
|
-
return new TextDecoder().decode(bytes);
|
|
161
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OptimisticEchoTracker — receive-layer reconciliation primitive.
|
|
3
|
-
*
|
|
4
|
-
* Tracks the set of transaction ids the client has applied locally
|
|
5
|
-
* but the server has not yet confirmed. When a sync delta arrives
|
|
6
|
-
* carrying a `transactionId` the tracker recognizes, the pool
|
|
7
|
-
* mutation is suppressed (the optimistic write already reflects it).
|
|
8
|
-
* Drained when the matching delta echo lands or when the originating
|
|
9
|
-
* transaction is rolled back.
|
|
10
|
-
*
|
|
11
|
-
* Architectural framing: see
|
|
12
|
-
* `apps/sync-server/docs/OPTIMISTIC_RECONCILIATION.md`. This is the
|
|
13
|
-
* "discriminator at the apply layer" the doc names — without it the
|
|
14
|
-
* authoritative-layer apply path blindly re-applies confirmations on
|
|
15
|
-
* top of whatever optimistic state has since diverged, producing the
|
|
16
|
-
* chart-delete flicker.
|
|
17
|
-
*
|
|
18
|
-
* Bounded by `maxSize` to defend against runaway growth from a
|
|
19
|
-
* pathological "transactions never confirmed and never rolled back"
|
|
20
|
-
* loop. When the bound is hit, the OLDEST id is evicted (FIFO via
|
|
21
|
-
* insertion-ordered Map). Eviction means a future echo of that
|
|
22
|
-
* transaction will be applied as a foreign mutation — no correctness
|
|
23
|
-
* risk for the originating tab (the pool already reflects the local
|
|
24
|
-
* write); the worst case is a single redundant pool re-set.
|
|
25
|
-
*/
|
|
26
|
-
export interface OptimisticEchoTrackerOptions {
|
|
27
|
-
/**
|
|
28
|
-
* Hard upper bound on tracked ids. FIFO eviction beyond this. The
|
|
29
|
-
* default of 10_000 covers a 200-tab user mid-bulk-edit (each tab
|
|
30
|
-
* tracking dozens of unconfirmed transactions) with two orders of
|
|
31
|
-
* magnitude of headroom.
|
|
32
|
-
*/
|
|
33
|
-
maxSize?: number;
|
|
34
|
-
}
|
|
35
|
-
export interface OptimisticEchoMetrics {
|
|
36
|
-
/** Total ids currently tracked. */
|
|
37
|
-
size: number;
|
|
38
|
-
/** Cumulative ids ever added since construction. */
|
|
39
|
-
totalAdded: number;
|
|
40
|
-
/** Cumulative successful echo matches (delta arrived → drained). */
|
|
41
|
-
hits: number;
|
|
42
|
-
/** Cumulative explicit rollback drains (transaction never made it). */
|
|
43
|
-
rollbacks: number;
|
|
44
|
-
/** Cumulative ids evicted due to maxSize pressure. */
|
|
45
|
-
evictions: number;
|
|
46
|
-
}
|
|
47
|
-
export declare class OptimisticEchoTracker {
|
|
48
|
-
private readonly ids;
|
|
49
|
-
private readonly maxSize;
|
|
50
|
-
private _totalAdded;
|
|
51
|
-
private _hits;
|
|
52
|
-
private _rollbacks;
|
|
53
|
-
private _evictions;
|
|
54
|
-
constructor(options?: OptimisticEchoTrackerOptions);
|
|
55
|
-
/**
|
|
56
|
-
* Mark a transaction as locally-applied. The next sync delta with a
|
|
57
|
-
* matching `transactionId` will be recognized as the server's
|
|
58
|
-
* confirmation of this same write. Idempotent — repeated calls with
|
|
59
|
-
* the same id are no-ops.
|
|
60
|
-
*/
|
|
61
|
-
markPending(transactionId: string): void;
|
|
62
|
-
/**
|
|
63
|
-
* If the id is currently tracked, drain it and return true (signal
|
|
64
|
-
* to the caller: this is an echo, skip the pool mutation).
|
|
65
|
-
* Otherwise return false (foreign mutation, apply normally).
|
|
66
|
-
*
|
|
67
|
-
* Combined check+drain into one method to make the receive-path
|
|
68
|
-
* idiom hard to misuse: a separate `has` then `drain` would race
|
|
69
|
-
* if multiple deltas with the same id arrived in the same batch.
|
|
70
|
-
*/
|
|
71
|
-
consumeEcho(transactionId: string | null | undefined): boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Drain on rollback. The transaction was cancelled before a server
|
|
74
|
-
* confirmation arrived — no echo will ever come, so the pending
|
|
75
|
-
* entry would otherwise leak. Counts as a separate metric category
|
|
76
|
-
* so a spike of `rollbacks` (vs `hits`) signals network or
|
|
77
|
-
* server-side health issues.
|
|
78
|
-
*/
|
|
79
|
-
drainOnRollback(transactionId: string): void;
|
|
80
|
-
getMetrics(): Readonly<OptimisticEchoMetrics>;
|
|
81
|
-
clear(): void;
|
|
82
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OptimisticEchoTracker — receive-layer reconciliation primitive.
|
|
3
|
-
*
|
|
4
|
-
* Tracks the set of transaction ids the client has applied locally
|
|
5
|
-
* but the server has not yet confirmed. When a sync delta arrives
|
|
6
|
-
* carrying a `transactionId` the tracker recognizes, the pool
|
|
7
|
-
* mutation is suppressed (the optimistic write already reflects it).
|
|
8
|
-
* Drained when the matching delta echo lands or when the originating
|
|
9
|
-
* transaction is rolled back.
|
|
10
|
-
*
|
|
11
|
-
* Architectural framing: see
|
|
12
|
-
* `apps/sync-server/docs/OPTIMISTIC_RECONCILIATION.md`. This is the
|
|
13
|
-
* "discriminator at the apply layer" the doc names — without it the
|
|
14
|
-
* authoritative-layer apply path blindly re-applies confirmations on
|
|
15
|
-
* top of whatever optimistic state has since diverged, producing the
|
|
16
|
-
* chart-delete flicker.
|
|
17
|
-
*
|
|
18
|
-
* Bounded by `maxSize` to defend against runaway growth from a
|
|
19
|
-
* pathological "transactions never confirmed and never rolled back"
|
|
20
|
-
* loop. When the bound is hit, the OLDEST id is evicted (FIFO via
|
|
21
|
-
* insertion-ordered Map). Eviction means a future echo of that
|
|
22
|
-
* transaction will be applied as a foreign mutation — no correctness
|
|
23
|
-
* risk for the originating tab (the pool already reflects the local
|
|
24
|
-
* write); the worst case is a single redundant pool re-set.
|
|
25
|
-
*/
|
|
26
|
-
const DEFAULT_MAX_SIZE = 10_000;
|
|
27
|
-
export class OptimisticEchoTracker {
|
|
28
|
-
// Map (not Set) for O(1) FIFO eviction via insertion order.
|
|
29
|
-
// Value is unused; Map.keys() iterates in insertion order so
|
|
30
|
-
// `keys().next()` yields the oldest id.
|
|
31
|
-
ids = new Map();
|
|
32
|
-
maxSize;
|
|
33
|
-
// Metrics — internal counters; exposed via `getMetrics()`. Kept
|
|
34
|
-
// numeric (not BigInt) since cumulative-since-page-load fits well
|
|
35
|
-
// under Number.MAX_SAFE_INTEGER for any realistic session.
|
|
36
|
-
_totalAdded = 0;
|
|
37
|
-
_hits = 0;
|
|
38
|
-
_rollbacks = 0;
|
|
39
|
-
_evictions = 0;
|
|
40
|
-
constructor(options = {}) {
|
|
41
|
-
this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Mark a transaction as locally-applied. The next sync delta with a
|
|
45
|
-
* matching `transactionId` will be recognized as the server's
|
|
46
|
-
* confirmation of this same write. Idempotent — repeated calls with
|
|
47
|
-
* the same id are no-ops.
|
|
48
|
-
*/
|
|
49
|
-
markPending(transactionId) {
|
|
50
|
-
if (this.ids.has(transactionId))
|
|
51
|
-
return;
|
|
52
|
-
if (this.ids.size >= this.maxSize) {
|
|
53
|
-
const oldest = this.ids.keys().next().value;
|
|
54
|
-
if (oldest !== undefined) {
|
|
55
|
-
this.ids.delete(oldest);
|
|
56
|
-
this._evictions += 1;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
this.ids.set(transactionId, true);
|
|
60
|
-
this._totalAdded += 1;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* If the id is currently tracked, drain it and return true (signal
|
|
64
|
-
* to the caller: this is an echo, skip the pool mutation).
|
|
65
|
-
* Otherwise return false (foreign mutation, apply normally).
|
|
66
|
-
*
|
|
67
|
-
* Combined check+drain into one method to make the receive-path
|
|
68
|
-
* idiom hard to misuse: a separate `has` then `drain` would race
|
|
69
|
-
* if multiple deltas with the same id arrived in the same batch.
|
|
70
|
-
*/
|
|
71
|
-
consumeEcho(transactionId) {
|
|
72
|
-
if (!transactionId)
|
|
73
|
-
return false;
|
|
74
|
-
if (!this.ids.has(transactionId))
|
|
75
|
-
return false;
|
|
76
|
-
this.ids.delete(transactionId);
|
|
77
|
-
this._hits += 1;
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Drain on rollback. The transaction was cancelled before a server
|
|
82
|
-
* confirmation arrived — no echo will ever come, so the pending
|
|
83
|
-
* entry would otherwise leak. Counts as a separate metric category
|
|
84
|
-
* so a spike of `rollbacks` (vs `hits`) signals network or
|
|
85
|
-
* server-side health issues.
|
|
86
|
-
*/
|
|
87
|
-
drainOnRollback(transactionId) {
|
|
88
|
-
if (this.ids.delete(transactionId)) {
|
|
89
|
-
this._rollbacks += 1;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
getMetrics() {
|
|
93
|
-
return {
|
|
94
|
-
size: this.ids.size,
|
|
95
|
-
totalAdded: this._totalAdded,
|
|
96
|
-
hits: this._hits,
|
|
97
|
-
rollbacks: this._rollbacks,
|
|
98
|
-
evictions: this._evictions,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
clear() {
|
|
102
|
-
this.ids.clear();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { getContext } from "../context.js";
|
|
2
|
-
/**
|
|
3
|
-
* Shared error handler for mutation execution.
|
|
4
|
-
* Logs to SyncObservability (unless offline + network error), then re-throws.
|
|
5
|
-
*/
|
|
6
|
-
export function handleMutationError(error, context, schemaName, modelId) {
|
|
7
|
-
const errorInfo = { schemaName, modelId, rawError: error };
|
|
8
|
-
if (error instanceof Error) {
|
|
9
|
-
errorInfo.message = error.message;
|
|
10
|
-
errorInfo.name = error.name;
|
|
11
|
-
errorInfo.stack =
|
|
12
|
-
typeof error.stack === 'string' ? error.stack.split('\n').slice(0, 5) : undefined;
|
|
13
|
-
}
|
|
14
|
-
else if (error && typeof error === 'object') {
|
|
15
|
-
errorInfo.message =
|
|
16
|
-
error.message ??
|
|
17
|
-
error.error ??
|
|
18
|
-
'Unknown error';
|
|
19
|
-
errorInfo.code = error.code;
|
|
20
|
-
errorInfo.extensions = error.extensions;
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
errorInfo.message = String(error);
|
|
24
|
-
}
|
|
25
|
-
const isOffline = !getContext().onlineStatus.isOnline();
|
|
26
|
-
const msg = errorInfo.message;
|
|
27
|
-
const isNetworkError = msg?.includes('Failed to fetch') ||
|
|
28
|
-
msg?.includes('Network request failed') ||
|
|
29
|
-
msg?.includes('NetworkError');
|
|
30
|
-
if (!isOffline || !isNetworkError) {
|
|
31
|
-
getContext().observability.captureTransactionFailure({
|
|
32
|
-
context,
|
|
33
|
-
error: error instanceof Error ? error : String(errorInfo.message ?? error),
|
|
34
|
-
modelName: schemaName,
|
|
35
|
-
modelId,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
throw error;
|
|
39
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Optimistic apply/rollback — the queue's local-first bookkeeping, lifted out
|
|
3
|
-
* of `TransactionQueue.ts` as a pure leaf. The queue never mutates the pool
|
|
4
|
-
* itself: applying/rolling back records an entry in the host-owned ledger and
|
|
5
|
-
* emits `optimistic:*` events that the pool-side listeners act on. These
|
|
6
|
-
* functions take that ledger plus a minimal emitter interface (never the host
|
|
7
|
-
* class type), so the rules stay cycle-free and testable in isolation.
|
|
8
|
-
*/
|
|
9
|
-
import type { Model } from '../Model.js';
|
|
10
|
-
import type { MutationInput, Transaction } from './commitPayload.js';
|
|
11
|
-
/** One tracked optimistic mutation: the live model + its pre-image. */
|
|
12
|
-
export interface OptimisticUpdateEntry {
|
|
13
|
-
model: Model;
|
|
14
|
-
previousState: MutationInput | null | undefined;
|
|
15
|
-
transaction: Transaction;
|
|
16
|
-
}
|
|
17
|
-
/** The host's event surface — the only queue capability these rules need. */
|
|
18
|
-
export interface OptimisticEmitter {
|
|
19
|
-
emit(event: string, payload: unknown): void;
|
|
20
|
-
}
|
|
21
|
-
export declare function applyOptimisticCreate(optimisticUpdates: Map<string, OptimisticUpdateEntry>, emitter: OptimisticEmitter, model: Model, transaction: Transaction): void;
|
|
22
|
-
export declare function applyOptimisticUpdate(optimisticUpdates: Map<string, OptimisticUpdateEntry>, emitter: OptimisticEmitter, model: Model, transaction: Transaction): void;
|
|
23
|
-
export declare function applyOptimisticDelete(optimisticUpdates: Map<string, OptimisticUpdateEntry>, emitter: OptimisticEmitter, model: Model, transaction: Transaction): void;
|
|
24
|
-
export declare function rollbackOptimistic(optimisticUpdates: Map<string, OptimisticUpdateEntry>, emitter: OptimisticEmitter, transaction: Transaction, reason?: string, error?: Error): Promise<void>;
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Optimistic apply/rollback — the queue's local-first bookkeeping, lifted out
|
|
3
|
-
* of `TransactionQueue.ts` as a pure leaf. The queue never mutates the pool
|
|
4
|
-
* itself: applying/rolling back records an entry in the host-owned ledger and
|
|
5
|
-
* emits `optimistic:*` events that the pool-side listeners act on. These
|
|
6
|
-
* functions take that ledger plus a minimal emitter interface (never the host
|
|
7
|
-
* class type), so the rules stay cycle-free and testable in isolation.
|
|
8
|
-
*/
|
|
9
|
-
export function applyOptimisticCreate(optimisticUpdates, emitter, model, transaction) {
|
|
10
|
-
optimisticUpdates.set(transaction.id, {
|
|
11
|
-
model,
|
|
12
|
-
previousState: null,
|
|
13
|
-
transaction,
|
|
14
|
-
});
|
|
15
|
-
emitter.emit('optimistic:create', { model, transaction });
|
|
16
|
-
}
|
|
17
|
-
export function applyOptimisticUpdate(optimisticUpdates, emitter, model, transaction) {
|
|
18
|
-
optimisticUpdates.set(transaction.id, {
|
|
19
|
-
model,
|
|
20
|
-
previousState: transaction.previousData,
|
|
21
|
-
transaction,
|
|
22
|
-
});
|
|
23
|
-
emitter.emit('optimistic:update', { model, transaction });
|
|
24
|
-
}
|
|
25
|
-
export function applyOptimisticDelete(optimisticUpdates, emitter, model, transaction) {
|
|
26
|
-
optimisticUpdates.set(transaction.id, {
|
|
27
|
-
model,
|
|
28
|
-
previousState: transaction.previousData,
|
|
29
|
-
transaction,
|
|
30
|
-
});
|
|
31
|
-
emitter.emit('optimistic:delete', { model, transaction });
|
|
32
|
-
}
|
|
33
|
-
export async function rollbackOptimistic(optimisticUpdates, emitter, transaction, reason, error) {
|
|
34
|
-
const optimistic = optimisticUpdates.get(transaction.id);
|
|
35
|
-
if (!optimistic)
|
|
36
|
-
return;
|
|
37
|
-
emitter.emit('optimistic:rollback', {
|
|
38
|
-
model: optimistic.model,
|
|
39
|
-
previousState: optimistic.previousState,
|
|
40
|
-
transaction,
|
|
41
|
-
reason: reason ?? 'unknown',
|
|
42
|
-
error,
|
|
43
|
-
});
|
|
44
|
-
optimisticUpdates.delete(transaction.id);
|
|
45
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* M1 Helper - Simplified MobX Setup
|
|
3
|
-
*
|
|
4
|
-
* Fixed version that doesn't conflict with existing getters/setters
|
|
5
|
-
*/
|
|
6
|
-
import { type AnnotationMapEntry } from 'mobx';
|
|
7
|
-
import { type PropertyMetadata, type ReferenceMetadata } from '../types/index.js';
|
|
8
|
-
/**
|
|
9
|
-
* The internal contract M1 relies on. Models invoke M1 from inside
|
|
10
|
-
* their constructor, where these fields are guaranteed to exist on
|
|
11
|
-
* `this`. Declared here as the bound on M1's generic so the body can
|
|
12
|
-
* reference them without `as any` casts. Each field is optional so a
|
|
13
|
-
* partial Model implementation (e.g., a test fixture) still satisfies
|
|
14
|
-
* the bound.
|
|
15
|
-
*/
|
|
16
|
-
interface M1Target {
|
|
17
|
-
_hasCustomObservability?: boolean;
|
|
18
|
-
_isConstructing?: boolean;
|
|
19
|
-
_extraMobxAnnotations?: Record<string, AnnotationMapEntry>;
|
|
20
|
-
setupObservability?(): void;
|
|
21
|
-
propertyChanged?(name: string, oldValue: unknown, newValue: unknown): void;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* M1 - Make properties observable with proper MobX setup
|
|
25
|
-
*
|
|
26
|
-
* Simplified version that respects existing getters/setters
|
|
27
|
-
*/
|
|
28
|
-
export declare function M1<T extends M1Target>(target: T, propertyMetadata: Map<string, PropertyMetadata>, referenceMetadata?: Map<string, ReferenceMetadata>): void;
|
|
29
|
-
/**
|
|
30
|
-
* Helper to make a class observable
|
|
31
|
-
* For classes that don't have custom observability
|
|
32
|
-
*/
|
|
33
|
-
export declare function makeModelObservable(modelClass: any, propertyMetadata: Map<string, PropertyMetadata>, referenceMetadata?: Map<string, any>): any;
|
|
34
|
-
/**
|
|
35
|
-
* Utility to check if a property is observable
|
|
36
|
-
*/
|
|
37
|
-
export declare function isObservableProperty(target: any, propName: string, propertyMetadata: Map<string, PropertyMetadata>): boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Utility to get computed properties
|
|
40
|
-
*/
|
|
41
|
-
export declare function getComputedProperties(propertyMetadata: Map<string, PropertyMetadata>): string[];
|
|
42
|
-
export {};
|