@abloatai/ablo 0.25.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -3
- package/CHANGELOG.md +34 -0
- package/README.md +104 -88
- package/dist/BaseSyncedStore.d.ts +140 -266
- package/dist/BaseSyncedStore.js +338 -739
- package/dist/Database.d.ts +62 -77
- package/dist/Database.js +106 -127
- package/dist/{ObjectPool.d.ts → InstanceCache.d.ts} +10 -13
- package/dist/{ObjectPool.js → InstanceCache.js} +91 -83
- package/dist/LazyReferenceCollection.d.ts +11 -15
- package/dist/LazyReferenceCollection.js +16 -15
- package/dist/Model.d.ts +37 -52
- package/dist/Model.js +52 -69
- package/dist/ModelRegistry.d.ts +46 -25
- package/dist/ModelRegistry.js +32 -30
- package/dist/NetworkMonitor.d.ts +5 -6
- package/dist/NetworkMonitor.js +6 -7
- package/dist/SyncClient.d.ts +119 -109
- package/dist/SyncClient.js +303 -224
- package/dist/SyncEngineContext.d.ts +1 -3
- package/dist/SyncEngineContext.js +1 -2
- package/dist/adapters/alwaysOnline.d.ts +6 -8
- package/dist/adapters/alwaysOnline.js +6 -8
- package/dist/adapters/inMemoryStorage.d.ts +9 -9
- package/dist/adapters/inMemoryStorage.js +9 -9
- package/dist/agent/Agent.d.ts +39 -31
- package/dist/agent/Agent.js +35 -23
- package/dist/agent/index.d.ts +4 -4
- package/dist/agent/index.js +5 -5
- package/dist/agent/session.d.ts +47 -44
- package/dist/agent/session.js +37 -48
- package/dist/agent/types.d.ts +26 -31
- package/dist/agent/types.js +6 -7
- package/dist/ai-sdk/coordinatedTool.d.ts +108 -0
- package/dist/ai-sdk/{coordinated-tool.js → coordinatedTool.js} +44 -38
- package/dist/ai-sdk/coordinationContext.d.ts +46 -0
- package/dist/ai-sdk/{coordination-context.js → coordinationContext.js} +30 -31
- package/dist/ai-sdk/index.d.ts +25 -22
- package/dist/ai-sdk/index.js +25 -22
- package/dist/ai-sdk/wrap.d.ts +7 -8
- package/dist/ai-sdk/wrap.js +2 -2
- package/dist/auth/credentialPolicy.d.ts +74 -71
- package/dist/auth/credentialPolicy.js +51 -56
- package/dist/auth/credentialSource.d.ts +7 -18
- package/dist/auth/credentialSource.js +10 -18
- package/dist/auth/index.d.ts +59 -58
- package/dist/auth/index.js +34 -40
- package/dist/auth/schemas.d.ts +5 -4
- package/dist/auth/schemas.js +5 -4
- package/dist/batching/index.d.ts +19 -21
- package/dist/batching/index.js +14 -17
- package/dist/cli.cjs +483 -369
- package/dist/client/Ablo.d.ts +107 -836
- package/dist/client/Ablo.js +174 -833
- package/dist/client/ApiClient.d.ts +44 -20
- package/dist/client/ApiClient.js +193 -44
- package/dist/client/auth.d.ts +51 -60
- package/dist/client/auth.js +137 -110
- package/dist/client/claimHeartbeatLoop.d.ts +50 -0
- package/dist/client/claimHeartbeatLoop.js +88 -0
- package/dist/client/consoleLogger.d.ts +35 -0
- package/dist/client/consoleLogger.js +44 -0
- package/dist/client/createInternalComponents.d.ts +14 -17
- package/dist/client/createInternalComponents.js +26 -31
- package/dist/client/createModelProxy.d.ts +130 -120
- package/dist/client/createModelProxy.js +158 -124
- package/dist/client/credentialEndpoint.d.ts +61 -0
- package/dist/client/credentialEndpoint.js +86 -0
- package/dist/client/functionalUpdate.d.ts +29 -27
- package/dist/client/functionalUpdate.js +21 -21
- package/dist/client/hostedEndpoints.d.ts +21 -0
- package/dist/client/hostedEndpoints.js +21 -0
- package/dist/client/httpClient.d.ts +58 -54
- package/dist/client/httpClient.js +29 -31
- package/dist/client/identity.d.ts +15 -20
- package/dist/client/identity.js +49 -59
- package/dist/client/modelRegistration.d.ts +10 -0
- package/dist/client/modelRegistration.js +301 -0
- package/dist/client/options.d.ts +373 -0
- package/dist/client/options.js +6 -0
- package/dist/client/registerDataSource.d.ts +9 -9
- package/dist/client/registerDataSource.js +15 -16
- package/dist/client/resourceTypes.d.ts +333 -0
- package/dist/client/resourceTypes.js +7 -0
- package/dist/client/schemaConfig.d.ts +44 -0
- package/dist/client/schemaConfig.js +176 -0
- package/dist/client/sessionMint.d.ts +17 -13
- package/dist/client/sessionMint.js +26 -31
- package/dist/client/validateAbloOptions.d.ts +12 -14
- package/dist/client/validateAbloOptions.js +9 -10
- package/dist/client/writeOptionsSchema.d.ts +18 -16
- package/dist/client/writeOptionsSchema.js +23 -20
- package/dist/client/wsMutationExecutor.d.ts +28 -0
- package/dist/client/wsMutationExecutor.js +71 -0
- package/dist/context.d.ts +6 -4
- package/dist/context.js +6 -7
- package/dist/coordination/index.d.ts +13 -4
- package/dist/coordination/index.js +29 -4
- package/dist/coordination/schema.d.ts +176 -128
- package/dist/coordination/schema.js +197 -133
- package/dist/coordination/trace.d.ts +9 -11
- package/dist/coordination/trace.js +13 -15
- package/dist/core/DatabaseManager.d.ts +5 -8
- package/dist/core/DatabaseManager.js +38 -40
- package/dist/core/QueryProcessor.d.ts +7 -9
- package/dist/core/QueryProcessor.js +27 -34
- package/dist/core/QueryView.d.ts +17 -5
- package/dist/core/QueryView.js +6 -7
- package/dist/core/StoreManager.d.ts +14 -16
- package/dist/core/StoreManager.js +26 -25
- package/dist/core/ViewRegistry.d.ts +5 -5
- package/dist/core/ViewRegistry.js +4 -4
- package/dist/core/index.d.ts +18 -13
- package/dist/core/index.js +32 -26
- package/dist/core/openIDBWithTimeout.d.ts +38 -36
- package/dist/core/openIDBWithTimeout.js +57 -54
- package/dist/core/queryUtils.d.ts +45 -0
- package/dist/core/queryUtils.js +69 -0
- package/dist/core/storeContract.d.ts +145 -0
- package/dist/core/storeContract.js +12 -0
- package/dist/environment.d.ts +28 -0
- package/dist/environment.js +21 -0
- package/dist/errorCodes.d.ts +118 -101
- package/dist/errorCodes.js +277 -260
- package/dist/errors.d.ts +170 -165
- package/dist/errors.js +161 -151
- package/dist/index.d.ts +30 -27
- package/dist/index.js +90 -82
- package/dist/interfaces/index.d.ts +108 -133
- package/dist/interfaces/index.js +5 -4
- package/dist/keys/index.d.ts +27 -29
- package/dist/keys/index.js +59 -49
- package/dist/mutators/RecordingTransaction.d.ts +16 -16
- package/dist/mutators/RecordingTransaction.js +31 -37
- package/dist/mutators/Transaction.d.ts +18 -26
- package/dist/mutators/Transaction.js +14 -20
- package/dist/mutators/UndoManager.d.ts +122 -131
- package/dist/mutators/UndoManager.js +149 -155
- package/dist/mutators/defineMutators.d.ts +24 -37
- package/dist/mutators/defineMutators.js +14 -20
- package/dist/mutators/inverseOp.d.ts +12 -15
- package/dist/mutators/inverseOp.js +12 -15
- package/dist/mutators/mutateActions.d.ts +10 -9
- package/dist/mutators/mutateActions.js +1 -1
- package/dist/mutators/readerActions.d.ts +9 -8
- package/dist/mutators/readerActions.js +2 -2
- package/dist/mutators/undoApply.d.ts +31 -27
- package/dist/mutators/undoApply.js +26 -24
- package/dist/policy/index.d.ts +5 -3
- package/dist/policy/index.js +5 -3
- package/dist/policy/types.d.ts +105 -101
- package/dist/policy/types.js +67 -66
- package/dist/query/client.d.ts +32 -16
- package/dist/query/client.js +103 -72
- package/dist/query/types.d.ts +37 -60
- package/dist/query/types.js +13 -33
- package/dist/react/AbloProvider.d.ts +7 -11
- package/dist/react/AbloProvider.js +24 -17
- package/dist/react/context.d.ts +27 -146
- package/dist/react/context.js +9 -10
- package/dist/react/index.d.ts +41 -42
- package/dist/react/index.js +37 -38
- package/dist/react/internalContext.d.ts +17 -19
- package/dist/react/useAblo.d.ts +23 -22
- package/dist/react/useAblo.js +17 -15
- package/dist/react/useCurrentUserId.d.ts +8 -7
- package/dist/react/useCurrentUserId.js +8 -7
- package/dist/react/useErrorListener.d.ts +7 -7
- package/dist/react/useErrorListener.js +11 -12
- package/dist/react/useMutationFailureListener.d.ts +8 -8
- package/dist/react/useMutationFailureListener.js +9 -9
- package/dist/react/useMutators.d.ts +11 -11
- package/dist/react/useMutators.js +10 -4
- package/dist/react/useReactive.js +2 -3
- package/dist/react/useSyncStatus.d.ts +4 -6
- package/dist/react/useUndoScope.d.ts +7 -9
- package/dist/react/useUndoScope.js +3 -3
- package/dist/schema/coordination.d.ts +21 -25
- package/dist/schema/coordination.js +21 -25
- package/dist/schema/ddl.d.ts +43 -39
- package/dist/schema/ddl.js +75 -68
- package/dist/schema/ddlLock.d.ts +35 -0
- package/dist/schema/ddlLock.js +46 -0
- package/dist/schema/diff.d.ts +99 -61
- package/dist/schema/diff.js +43 -34
- package/dist/schema/field.d.ts +37 -42
- package/dist/schema/field.js +36 -49
- package/dist/schema/generate.d.ts +12 -12
- package/dist/schema/generate.js +12 -12
- package/dist/schema/index.d.ts +5 -4
- package/dist/schema/index.js +29 -21
- package/dist/schema/model.d.ts +121 -146
- package/dist/schema/model.js +24 -35
- package/dist/schema/openapi.d.ts +10 -9
- package/dist/schema/openapi.js +7 -1
- package/dist/schema/queries.d.ts +30 -32
- package/dist/schema/queries.js +24 -25
- package/dist/schema/relation.d.ts +89 -99
- package/dist/schema/relation.js +13 -13
- package/dist/schema/residency.d.ts +38 -0
- package/dist/schema/residency.js +30 -0
- package/dist/schema/roles.d.ts +45 -27
- package/dist/schema/roles.js +52 -21
- package/dist/schema/schema.d.ts +36 -45
- package/dist/schema/schema.js +42 -39
- package/dist/schema/select.d.ts +13 -13
- package/dist/schema/select.js +13 -13
- package/dist/schema/serialize.d.ts +36 -39
- package/dist/schema/serialize.js +27 -31
- package/dist/schema/sugar.d.ts +17 -32
- package/dist/schema/sugar.js +14 -29
- package/dist/schema/{sync-delta-row.d.ts → syncDeltaRow.d.ts} +27 -50
- package/dist/schema/syncDeltaRow.js +89 -0
- package/dist/schema/tenancy.d.ts +44 -46
- package/dist/schema/tenancy.js +46 -48
- package/dist/server/adapter.d.ts +58 -58
- package/dist/server/adapter.js +13 -14
- package/dist/server/commit.d.ts +60 -64
- package/dist/server/index.d.ts +9 -10
- package/dist/server/index.js +1 -1
- package/dist/server/readConfig.d.ts +70 -0
- package/dist/server/readConfig.js +8 -0
- package/dist/server/storageMode.d.ts +23 -0
- package/dist/server/storageMode.js +17 -0
- package/dist/source/adapter.d.ts +31 -26
- package/dist/source/adapter.js +10 -10
- package/dist/source/adapters/drizzle.d.ts +28 -23
- package/dist/source/adapters/drizzle.js +34 -28
- package/dist/source/adapters/kysely.d.ts +27 -25
- package/dist/source/adapters/kysely.js +28 -26
- package/dist/source/adapters/memory.d.ts +8 -7
- package/dist/source/adapters/memory.js +10 -9
- package/dist/source/adapters/prisma.d.ts +13 -12
- package/dist/source/adapters/prisma.js +27 -29
- package/dist/source/conformance.d.ts +18 -11
- package/dist/source/conformance.js +27 -19
- package/dist/source/connector.d.ts +31 -32
- package/dist/source/connector.js +30 -28
- package/dist/source/connectorProtocol.d.ts +160 -0
- package/dist/source/connectorProtocol.js +162 -0
- package/dist/source/contract.d.ts +26 -27
- package/dist/source/contract.js +28 -29
- package/dist/source/factory.d.ts +94 -0
- package/dist/source/factory.js +268 -0
- package/dist/source/index.d.ts +10 -462
- package/dist/source/index.js +17 -421
- package/dist/source/migrations.d.ts +9 -9
- package/dist/source/migrations.js +9 -9
- package/dist/source/next.d.ts +10 -11
- package/dist/source/next.js +7 -8
- package/dist/source/pushQueue.d.ts +70 -48
- package/dist/source/pushQueue.js +36 -29
- package/dist/source/signing.d.ts +88 -0
- package/dist/source/signing.js +159 -0
- package/dist/source/types.d.ts +351 -0
- package/dist/source/types.js +43 -0
- package/dist/stores/ObjectStore.d.ts +11 -12
- package/dist/stores/ObjectStore.js +34 -35
- package/dist/stores/ObjectStoreContract.d.ts +12 -15
- package/dist/stores/SyncActionStore.d.ts +8 -12
- package/dist/stores/SyncActionStore.js +77 -46
- package/dist/surface.d.ts +28 -21
- package/dist/surface.js +28 -20
- package/dist/sync/{BootstrapHelper.d.ts → BootstrapFetcher.d.ts} +37 -45
- package/dist/sync/{BootstrapHelper.js → BootstrapFetcher.js} +101 -80
- package/dist/sync/ConnectionManager.d.ts +47 -50
- package/dist/sync/ConnectionManager.js +74 -70
- package/dist/sync/NetworkProbe.d.ts +27 -31
- package/dist/sync/NetworkProbe.js +67 -72
- package/dist/sync/{HydrationCoordinator.d.ts → OnDemandLoader.d.ts} +49 -36
- package/dist/sync/{HydrationCoordinator.js → OnDemandLoader.js} +79 -54
- package/dist/sync/{AreaOfInterestManager.d.ts → SubscriptionManager.d.ts} +45 -59
- package/dist/sync/{AreaOfInterestManager.js → SubscriptionManager.js} +44 -52
- package/dist/sync/SyncWebSocket.d.ts +175 -250
- package/dist/sync/SyncWebSocket.js +431 -769
- package/dist/sync/awaitClaimGrant.d.ts +18 -18
- package/dist/sync/awaitClaimGrant.js +38 -30
- package/dist/sync/bootstrapApply.d.ts +70 -0
- package/dist/sync/bootstrapApply.js +73 -0
- package/dist/sync/commitFrames.d.ts +44 -0
- package/dist/sync/commitFrames.js +94 -0
- package/dist/sync/createClaimStream.d.ts +23 -22
- package/dist/sync/createClaimStream.js +108 -25
- package/dist/sync/createPresenceStream.d.ts +19 -18
- package/dist/sync/createPresenceStream.js +25 -26
- package/dist/sync/createSnapshot.d.ts +13 -17
- package/dist/sync/createSnapshot.js +20 -26
- package/dist/sync/credentialLifecycle.d.ts +175 -0
- package/dist/sync/credentialLifecycle.js +322 -0
- package/dist/sync/deltaPipeline.d.ts +113 -0
- package/dist/sync/deltaPipeline.js +261 -0
- package/dist/sync/groupChange.d.ts +113 -0
- package/dist/sync/groupChange.js +242 -0
- package/dist/sync/heartbeat.d.ts +63 -0
- package/dist/sync/heartbeat.js +91 -0
- package/dist/sync/participants.d.ts +27 -27
- package/dist/sync/schemas.d.ts +3 -2
- package/dist/sync/schemas.js +14 -10
- package/dist/sync/syncCursor.d.ts +40 -0
- package/dist/sync/syncCursor.js +55 -0
- package/dist/sync/syncPlan.d.ts +54 -0
- package/dist/sync/syncPlan.js +50 -0
- package/dist/sync/syncPosition.d.ts +54 -49
- package/dist/sync/syncPosition.js +57 -52
- package/dist/sync/wsFrameHandlers.d.ts +116 -0
- package/dist/sync/wsFrameHandlers.js +374 -0
- package/dist/testing/fixtures/bootstrap.d.ts +21 -17
- package/dist/testing/fixtures/bootstrap.js +12 -6
- package/dist/testing/fixtures/deltas.d.ts +31 -34
- package/dist/testing/fixtures/deltas.js +30 -33
- package/dist/testing/fixtures/models.d.ts +11 -10
- package/dist/testing/fixtures/models.js +12 -10
- package/dist/testing/helpers/{react-wrapper.d.ts → reactWrapper.d.ts} +13 -10
- package/dist/testing/helpers/{react-wrapper.js → reactWrapper.js} +15 -12
- package/dist/testing/helpers/{sync-engine-harness.d.ts → syncEngineHarness.d.ts} +17 -18
- package/dist/testing/helpers/{sync-engine-harness.js → syncEngineHarness.js} +14 -11
- package/dist/testing/helpers/wait.d.ts +13 -8
- package/dist/testing/helpers/wait.js +13 -8
- package/dist/testing/index.d.ts +4 -4
- package/dist/testing/index.js +3 -3
- package/dist/testing/mocks/MockMutationExecutor.d.ts +18 -17
- package/dist/testing/mocks/MockMutationExecutor.js +15 -14
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +8 -8
- package/dist/testing/mocks/MockNetworkMonitor.js +8 -8
- package/dist/testing/mocks/MockSyncContext.d.ts +21 -34
- package/dist/testing/mocks/MockSyncContext.js +16 -45
- package/dist/testing/mocks/MockSyncStore.d.ts +14 -14
- package/dist/testing/mocks/MockSyncStore.js +11 -11
- package/dist/testing/mocks/MockWebSocket.d.ts +28 -24
- package/dist/testing/mocks/MockWebSocket.js +22 -21
- package/dist/transactions/TransactionQueue.d.ts +190 -221
- package/dist/transactions/TransactionQueue.js +424 -822
- package/dist/transactions/TransactionStore.d.ts +20 -0
- package/dist/transactions/TransactionStore.js +53 -0
- package/dist/transactions/UnconfirmedWrites.d.ts +82 -0
- package/dist/transactions/UnconfirmedWrites.js +104 -0
- package/dist/transactions/coalesceRules.d.ts +58 -0
- package/dist/transactions/coalesceRules.js +140 -0
- package/dist/transactions/commitPayload.d.ts +130 -0
- package/dist/transactions/commitPayload.js +143 -0
- package/dist/transactions/deltaConfirmation.d.ts +58 -0
- package/dist/transactions/deltaConfirmation.js +215 -0
- package/dist/transactions/optimisticApply.d.ts +49 -0
- package/dist/transactions/optimisticApply.js +65 -0
- package/dist/transactions/replayValidation.d.ts +99 -0
- package/dist/transactions/replayValidation.js +111 -0
- package/dist/types/global.d.ts +46 -41
- package/dist/types/global.js +20 -19
- package/dist/types/index.d.ts +74 -80
- package/dist/types/index.js +22 -27
- package/dist/types/modelData.d.ts +10 -0
- package/dist/types/modelData.js +9 -0
- package/dist/types/participant.d.ts +20 -0
- package/dist/types/participant.js +10 -0
- package/dist/types/streams.d.ts +216 -209
- package/dist/types/streams.js +7 -7
- package/dist/utils/asyncIterator.d.ts +25 -32
- package/dist/utils/asyncIterator.js +25 -32
- package/dist/utils/duration.d.ts +12 -15
- package/dist/utils/duration.js +12 -15
- package/dist/utils/mobxSetup.d.ts +53 -0
- package/dist/utils/{mobx-setup.js → mobxSetup.js} +44 -100
- package/dist/webhooks/events.d.ts +21 -16
- package/dist/webhooks/events.js +10 -8
- package/dist/webhooks/index.d.ts +5 -7
- package/dist/webhooks/index.js +5 -7
- package/dist/{schema/sync-delta-wire.d.ts → wire/delta.d.ts} +58 -41
- package/dist/wire/delta.js +114 -0
- package/dist/wire/errorEnvelope.d.ts +35 -27
- package/dist/wire/errorEnvelope.js +38 -32
- package/dist/wire/frames.d.ts +150 -67
- package/dist/wire/frames.js +48 -1
- package/dist/wire/index.d.ts +18 -13
- package/dist/wire/index.js +36 -13
- package/dist/wire/listEnvelope.d.ts +16 -23
- package/dist/wire/listEnvelope.js +7 -6
- package/dist/wire/protocol.d.ts +38 -0
- package/dist/wire/protocol.js +38 -0
- package/dist/wire/protocolVersion.d.ts +60 -0
- package/dist/wire/protocolVersion.js +67 -0
- package/docs/api-keys.md +4 -3
- package/docs/coordination.md +59 -0
- package/docs/examples/existing-python-backend.md +3 -3
- package/docs/identity.md +4 -4
- package/docs/integration-guide.md +1 -1
- package/docs/react.md +1 -1
- package/docs/sessions.md +5 -7
- package/package.json +24 -21
- package/dist/ai-sdk/coordinated-tool.d.ts +0 -101
- package/dist/ai-sdk/coordination-context.d.ts +0 -52
- package/dist/client/index.d.ts +0 -36
- package/dist/client/index.js +0 -33
- package/dist/config/index.d.ts +0 -10
- package/dist/config/index.js +0 -12
- package/dist/core/query-utils.d.ts +0 -34
- package/dist/core/query-utils.js +0 -59
- package/dist/interfaces/headless.d.ts +0 -95
- package/dist/interfaces/headless.js +0 -41
- package/dist/query/index.d.ts +0 -6
- package/dist/query/index.js +0 -5
- package/dist/realtime/index.d.ts +0 -10
- package/dist/realtime/index.js +0 -9
- package/dist/schema/plane.d.ts +0 -23
- package/dist/schema/plane.js +0 -19
- package/dist/schema/sync-delta-row.js +0 -103
- package/dist/schema/sync-delta-wire.js +0 -102
- package/dist/server/next.d.ts +0 -51
- package/dist/server/next.js +0 -47
- package/dist/server/read-config.d.ts +0 -67
- package/dist/server/read-config.js +0 -8
- package/dist/server/storage-mode.d.ts +0 -1
- package/dist/server/storage-mode.js +0 -18
- package/dist/source/connector-protocol.d.ts +0 -159
- package/dist/source/connector-protocol.js +0 -161
- package/dist/sync/OfflineFlush.d.ts +0 -9
- package/dist/sync/OfflineFlush.js +0 -22
- package/dist/sync/OfflineTransactionStore.d.ts +0 -37
- package/dist/sync/OfflineTransactionStore.js +0 -263
- package/dist/transactions/OptimisticEchoTracker.d.ts +0 -82
- package/dist/transactions/OptimisticEchoTracker.js +0 -104
- package/dist/transactions/index.d.ts +0 -16
- package/dist/transactions/index.js +0 -7
- package/dist/transactions/mutation-error-handler.d.ts +0 -5
- package/dist/transactions/mutation-error-handler.js +0 -39
- package/dist/utils/mobx-setup.d.ts +0 -42
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* OfflineTransactionStore
|
|
3
|
-
* - IndexedDB-backed queue for GraphQL mutations and REST ops
|
|
4
|
-
* - AES-GCM encryption at rest (per-browser key)
|
|
5
|
-
* - Priority-aware ordering with simple topological sort
|
|
6
|
-
*/
|
|
7
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
|
-
import { openIDBWithTimeout } from '../core/openIDBWithTimeout.js';
|
|
9
|
-
import { AbloConnectionError } from '../errors.js';
|
|
10
|
-
export var Priority;
|
|
11
|
-
(function (Priority) {
|
|
12
|
-
Priority[Priority["CRITICAL"] = 0] = "CRITICAL";
|
|
13
|
-
Priority[Priority["HIGH"] = 1] = "HIGH";
|
|
14
|
-
Priority[Priority["NORMAL"] = 2] = "NORMAL";
|
|
15
|
-
Priority[Priority["LOW"] = 3] = "LOW";
|
|
16
|
-
})(Priority || (Priority = {}));
|
|
17
|
-
// Minimal IndexedDB helpers. Delegates to openIDBWithTimeout so the open
|
|
18
|
-
// request can't silently hang when another tab holds an older version
|
|
19
|
-
// (`onblocked`) or when storage is in a bad state (no event fires at all).
|
|
20
|
-
function openDB(name, version, upgrade) {
|
|
21
|
-
return openIDBWithTimeout(name, version, {
|
|
22
|
-
onUpgrade: (request) => upgrade(request.result),
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
function txStore(db, mode) {
|
|
26
|
-
const tx = db.transaction('transactions', mode);
|
|
27
|
-
const store = tx.objectStore('transactions');
|
|
28
|
-
return { tx, store };
|
|
29
|
-
}
|
|
30
|
-
function b64(bytes) {
|
|
31
|
-
// Buffer.from accepts ArrayBufferLike but the @types/node overloads
|
|
32
|
-
// don't all line up — wrap in Uint8Array (which Buffer DOES accept
|
|
33
|
-
// unambiguously) so the type system stays happy without a cast.
|
|
34
|
-
if (typeof Buffer !== 'undefined') {
|
|
35
|
-
return Buffer.from(new Uint8Array(bytes)).toString('base64');
|
|
36
|
-
}
|
|
37
|
-
let binary = '';
|
|
38
|
-
const arr = new Uint8Array(bytes);
|
|
39
|
-
for (let i = 0; i < arr.byteLength; i++)
|
|
40
|
-
binary += String.fromCharCode(arr[i]);
|
|
41
|
-
return btoa(binary);
|
|
42
|
-
}
|
|
43
|
-
function b64dec(text) {
|
|
44
|
-
if (typeof Buffer !== 'undefined') {
|
|
45
|
-
const buffer = Buffer.from(text, 'base64');
|
|
46
|
-
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
47
|
-
}
|
|
48
|
-
const binary = atob(text);
|
|
49
|
-
const bytes = new Uint8Array(binary.length);
|
|
50
|
-
for (let i = 0; i < binary.length; i++)
|
|
51
|
-
bytes[i] = binary.charCodeAt(i);
|
|
52
|
-
return bytes.buffer;
|
|
53
|
-
}
|
|
54
|
-
async function getOrCreateKey() {
|
|
55
|
-
try {
|
|
56
|
-
const storageKey = 'ablo:offline:key';
|
|
57
|
-
let raw = localStorage.getItem(storageKey);
|
|
58
|
-
if (!raw) {
|
|
59
|
-
const seed = crypto.getRandomValues(new Uint8Array(32));
|
|
60
|
-
raw = b64(seed.buffer);
|
|
61
|
-
localStorage.setItem(storageKey, raw);
|
|
62
|
-
}
|
|
63
|
-
const keyData = b64dec(raw);
|
|
64
|
-
return await crypto.subtle.importKey('raw', keyData, 'AES-GCM', false, ['encrypt', 'decrypt']);
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
return null; // no crypto in environment
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
async function encryptJSON(key, data) {
|
|
71
|
-
const plaintext = new TextEncoder().encode(JSON.stringify(data));
|
|
72
|
-
if (!key || !crypto?.subtle) {
|
|
73
|
-
return { iv: '', ciphertext: b64(plaintext.buffer) };
|
|
74
|
-
}
|
|
75
|
-
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
76
|
-
const ct = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintext);
|
|
77
|
-
return { iv: b64(iv.buffer), ciphertext: b64(ct) };
|
|
78
|
-
}
|
|
79
|
-
async function decryptJSON(key, record) {
|
|
80
|
-
if (!key || !record.iv) {
|
|
81
|
-
const buf = b64dec(record.ciphertext);
|
|
82
|
-
const text = new TextDecoder().decode(buf);
|
|
83
|
-
return JSON.parse(text);
|
|
84
|
-
}
|
|
85
|
-
const iv = new Uint8Array(b64dec(record.iv));
|
|
86
|
-
const ct = b64dec(record.ciphertext);
|
|
87
|
-
const pt = await crypto.subtle.decrypt({ name: 'AES-GCM', iv }, key, ct);
|
|
88
|
-
return JSON.parse(new TextDecoder().decode(pt));
|
|
89
|
-
}
|
|
90
|
-
export class OfflineTransactionStore {
|
|
91
|
-
db = null;
|
|
92
|
-
key = null;
|
|
93
|
-
async init() {
|
|
94
|
-
if (typeof indexedDB === 'undefined')
|
|
95
|
-
return;
|
|
96
|
-
this.key = await getOrCreateKey();
|
|
97
|
-
this.db = await openDB('ablo-sync', 1, (db) => {
|
|
98
|
-
if (!db.objectStoreNames.contains('transactions')) {
|
|
99
|
-
const store = db.createObjectStore('transactions', { keyPath: 'id' });
|
|
100
|
-
store.createIndex('priority_createdAt', ['priority', 'createdAt']);
|
|
101
|
-
store.createIndex('createdAt', 'createdAt');
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
async enqueue(tx) {
|
|
106
|
-
if (!this.db)
|
|
107
|
-
await this.init();
|
|
108
|
-
if (!this.db)
|
|
109
|
-
throw new AbloConnectionError('IndexedDB unavailable', {
|
|
110
|
-
code: 'idb_unavailable',
|
|
111
|
-
});
|
|
112
|
-
const full = { ...tx, createdAt: Date.now() };
|
|
113
|
-
const { iv, ciphertext } = await encryptJSON(this.key, full);
|
|
114
|
-
const rec = {
|
|
115
|
-
id: full.id,
|
|
116
|
-
priority: full.priority,
|
|
117
|
-
createdAt: full.createdAt,
|
|
118
|
-
dependsOn: full.dependsOn,
|
|
119
|
-
iv,
|
|
120
|
-
ciphertext,
|
|
121
|
-
};
|
|
122
|
-
const { tx: itx, store } = txStore(this.db, 'readwrite');
|
|
123
|
-
return new Promise((resolve, reject) => {
|
|
124
|
-
const req = store.put(rec);
|
|
125
|
-
req.onsuccess = () => {
|
|
126
|
-
resolve(full.id);
|
|
127
|
-
};
|
|
128
|
-
req.onerror = () => {
|
|
129
|
-
reject(req.error);
|
|
130
|
-
};
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
async listAll() {
|
|
134
|
-
if (!this.db)
|
|
135
|
-
await this.init();
|
|
136
|
-
if (!this.db)
|
|
137
|
-
return [];
|
|
138
|
-
const out = [];
|
|
139
|
-
const { store } = txStore(this.db, 'readonly');
|
|
140
|
-
const req = store.getAll();
|
|
141
|
-
return new Promise((resolve, reject) => {
|
|
142
|
-
req.onsuccess = async () => {
|
|
143
|
-
try {
|
|
144
|
-
for (const rec of req.result) {
|
|
145
|
-
out.push(await decryptJSON(this.key, rec));
|
|
146
|
-
}
|
|
147
|
-
resolve(out);
|
|
148
|
-
}
|
|
149
|
-
catch (e) {
|
|
150
|
-
reject(e);
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
req.onerror = () => reject(req.error);
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
async getOptimizedSyncOrder() {
|
|
157
|
-
// Collect all, sort by priority asc, then topologically by dependsOn
|
|
158
|
-
const items = await this.listAll();
|
|
159
|
-
items.sort((a, b) => {
|
|
160
|
-
if (a.priority !== b.priority)
|
|
161
|
-
return a.priority - b.priority;
|
|
162
|
-
return a.createdAt - b.createdAt;
|
|
163
|
-
});
|
|
164
|
-
// Topological sort
|
|
165
|
-
const byId = new Map();
|
|
166
|
-
const indeg = new Map();
|
|
167
|
-
const graph = new Map();
|
|
168
|
-
for (const it of items) {
|
|
169
|
-
byId.set(it.id, it);
|
|
170
|
-
indeg.set(it.id, 0);
|
|
171
|
-
graph.set(it.id, []);
|
|
172
|
-
}
|
|
173
|
-
for (const it of items) {
|
|
174
|
-
for (const dep of it.dependsOn || []) {
|
|
175
|
-
if (!byId.has(dep))
|
|
176
|
-
continue; // ignore external
|
|
177
|
-
indeg.set(it.id, (indeg.get(it.id) || 0) + 1);
|
|
178
|
-
graph.get(dep).push(it.id);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
const queue = [];
|
|
182
|
-
for (const [id, deg] of indeg)
|
|
183
|
-
if (deg === 0)
|
|
184
|
-
queue.push(id);
|
|
185
|
-
// Sort queue by priority so nodes at the same dependency level
|
|
186
|
-
// come out in priority order (lower number = higher priority)
|
|
187
|
-
const sortQueue = () => queue.sort((a, b) => {
|
|
188
|
-
const pa = byId.get(a)?.priority ?? 0;
|
|
189
|
-
const pb = byId.get(b)?.priority ?? 0;
|
|
190
|
-
if (pa !== pb)
|
|
191
|
-
return pa - pb;
|
|
192
|
-
return (byId.get(a)?.createdAt ?? 0) - (byId.get(b)?.createdAt ?? 0);
|
|
193
|
-
});
|
|
194
|
-
sortQueue();
|
|
195
|
-
const order = [];
|
|
196
|
-
while (queue.length) {
|
|
197
|
-
const id = queue.shift();
|
|
198
|
-
const node = byId.get(id);
|
|
199
|
-
if (node)
|
|
200
|
-
order.push(node);
|
|
201
|
-
for (const nxt of graph.get(id) || []) {
|
|
202
|
-
const d = (indeg.get(nxt) || 0) - 1;
|
|
203
|
-
indeg.set(nxt, d);
|
|
204
|
-
if (d === 0)
|
|
205
|
-
queue.push(nxt);
|
|
206
|
-
}
|
|
207
|
-
if (queue.length > 1)
|
|
208
|
-
sortQueue();
|
|
209
|
-
}
|
|
210
|
-
// Fallback: if cycles exist, append remaining by createdAt
|
|
211
|
-
if (order.length < items.length) {
|
|
212
|
-
const seen = new Set(order.map((x) => x.id));
|
|
213
|
-
for (const it of items)
|
|
214
|
-
if (!seen.has(it.id))
|
|
215
|
-
order.push(it);
|
|
216
|
-
}
|
|
217
|
-
return order;
|
|
218
|
-
}
|
|
219
|
-
async remove(id) {
|
|
220
|
-
if (!this.db)
|
|
221
|
-
await this.init();
|
|
222
|
-
if (!this.db)
|
|
223
|
-
return;
|
|
224
|
-
const { store } = txStore(this.db, 'readwrite');
|
|
225
|
-
await new Promise((resolve, reject) => {
|
|
226
|
-
const req = store.delete(id);
|
|
227
|
-
req.onsuccess = () => resolve();
|
|
228
|
-
req.onerror = () => reject(req.error);
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
async clear() {
|
|
232
|
-
if (!this.db)
|
|
233
|
-
await this.init();
|
|
234
|
-
if (!this.db)
|
|
235
|
-
return;
|
|
236
|
-
const { store } = txStore(this.db, 'readwrite');
|
|
237
|
-
await new Promise((resolve, reject) => {
|
|
238
|
-
const req = store.clear();
|
|
239
|
-
req.onsuccess = () => resolve();
|
|
240
|
-
req.onerror = () => reject(req.error);
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
// Flush with caller-provided network function
|
|
244
|
-
async flush(processor) {
|
|
245
|
-
const ordered = await this.getOptimizedSyncOrder();
|
|
246
|
-
let processed = 0;
|
|
247
|
-
let failed = 0;
|
|
248
|
-
for (const tx of ordered) {
|
|
249
|
-
try {
|
|
250
|
-
await processor(tx);
|
|
251
|
-
await this.remove(tx.id);
|
|
252
|
-
processed++;
|
|
253
|
-
}
|
|
254
|
-
catch (_err) {
|
|
255
|
-
// Stop on first failure to preserve order
|
|
256
|
-
failed++;
|
|
257
|
-
break;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return { processed, failed };
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
export const offlineTxStore = new OfflineTransactionStore();
|
|
@@ -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,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transaction types and exports (MVP)
|
|
3
|
-
*
|
|
4
|
-
* Simplified for MVP: only TransactionQueue exports
|
|
5
|
-
* Individual transaction classes removed in favor of simple transaction objects
|
|
6
|
-
*/
|
|
7
|
-
export { TransactionQueue } from './TransactionQueue.js';
|
|
8
|
-
export type TransactionType = 'create' | 'update' | 'delete';
|
|
9
|
-
export interface Transaction {
|
|
10
|
-
id: string;
|
|
11
|
-
type: TransactionType;
|
|
12
|
-
modelName: string;
|
|
13
|
-
modelId: string;
|
|
14
|
-
data?: any;
|
|
15
|
-
createdAt: number;
|
|
16
|
-
}
|
|
@@ -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,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 { PropertyMetadata, 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 {};
|