@abloatai/ablo 0.3.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 +208 -0
- package/LICENSE +201 -0
- package/NOTICE +12 -0
- package/README.md +230 -0
- package/dist/BaseSyncedStore.d.ts +709 -0
- package/dist/BaseSyncedStore.js +1843 -0
- package/dist/Database.d.ts +344 -0
- package/dist/Database.js +1259 -0
- package/dist/LazyReferenceCollection.d.ts +181 -0
- package/dist/LazyReferenceCollection.js +460 -0
- package/dist/Model.d.ts +339 -0
- package/dist/Model.js +715 -0
- package/dist/ModelRegistry.d.ts +200 -0
- package/dist/ModelRegistry.js +535 -0
- package/dist/NetworkMonitor.d.ts +27 -0
- package/dist/NetworkMonitor.js +73 -0
- package/dist/ObjectPool.d.ts +202 -0
- package/dist/ObjectPool.js +1106 -0
- package/dist/SyncClient.d.ts +489 -0
- package/dist/SyncClient.js +1555 -0
- package/dist/SyncEngineContext.d.ts +46 -0
- package/dist/SyncEngineContext.js +74 -0
- package/dist/adapters/alwaysOnline.d.ts +16 -0
- package/dist/adapters/alwaysOnline.js +19 -0
- package/dist/adapters/inMemoryStorage.d.ts +30 -0
- package/dist/adapters/inMemoryStorage.js +94 -0
- package/dist/agent/Agent.d.ts +358 -0
- package/dist/agent/Agent.js +500 -0
- package/dist/agent/index.d.ts +115 -0
- package/dist/agent/index.js +128 -0
- package/dist/agent/session.d.ts +90 -0
- package/dist/agent/session.js +156 -0
- package/dist/agent/types.d.ts +73 -0
- package/dist/agent/types.js +10 -0
- package/dist/ai-sdk/coordination-context.d.ts +51 -0
- package/dist/ai-sdk/coordination-context.js +107 -0
- package/dist/ai-sdk/index.d.ts +68 -0
- package/dist/ai-sdk/index.js +68 -0
- package/dist/ai-sdk/intent-broadcast.d.ts +77 -0
- package/dist/ai-sdk/intent-broadcast.js +72 -0
- package/dist/ai-sdk/wrap.d.ts +67 -0
- package/dist/ai-sdk/wrap.js +45 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.js +9 -0
- package/dist/auth/index.d.ts +137 -0
- package/dist/auth/index.js +246 -0
- package/dist/client/Ablo.d.ts +835 -0
- package/dist/client/Ablo.js +1440 -0
- package/dist/client/ApiClient.d.ts +200 -0
- package/dist/client/ApiClient.js +659 -0
- package/dist/client/auth.d.ts +79 -0
- package/dist/client/auth.js +81 -0
- package/dist/client/createInternalComponents.d.ts +44 -0
- package/dist/client/createInternalComponents.js +88 -0
- package/dist/client/createModelProxy.d.ts +152 -0
- package/dist/client/createModelProxy.js +199 -0
- package/dist/client/identity.d.ts +63 -0
- package/dist/client/identity.js +156 -0
- package/dist/client/index.d.ts +36 -0
- package/dist/client/index.js +33 -0
- package/dist/client/persistence.d.ts +7 -0
- package/dist/client/persistence.js +11 -0
- package/dist/client/validateAbloOptions.d.ts +42 -0
- package/dist/client/validateAbloOptions.js +43 -0
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.js +12 -0
- package/dist/context.d.ts +27 -0
- package/dist/context.js +58 -0
- package/dist/core/DatabaseManager.d.ts +108 -0
- package/dist/core/DatabaseManager.js +361 -0
- package/dist/core/QueryProcessor.d.ts +77 -0
- package/dist/core/QueryProcessor.js +262 -0
- package/dist/core/QueryView.d.ts +64 -0
- package/dist/core/QueryView.js +219 -0
- package/dist/core/StoreManager.d.ts +131 -0
- package/dist/core/StoreManager.js +334 -0
- package/dist/core/ViewRegistry.d.ts +20 -0
- package/dist/core/ViewRegistry.js +55 -0
- package/dist/core/index.d.ts +34 -0
- package/dist/core/index.js +59 -0
- package/dist/core/openIDBWithTimeout.d.ts +27 -0
- package/dist/core/openIDBWithTimeout.js +63 -0
- package/dist/core/query-utils.d.ts +37 -0
- package/dist/core/query-utils.js +60 -0
- package/dist/errors.d.ts +235 -0
- package/dist/errors.js +243 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +82 -0
- package/dist/interfaces/headless.d.ts +95 -0
- package/dist/interfaces/headless.js +41 -0
- package/dist/interfaces/index.d.ts +321 -0
- package/dist/interfaces/index.js +8 -0
- package/dist/mutators/RecordingTransaction.d.ts +36 -0
- package/dist/mutators/RecordingTransaction.js +216 -0
- package/dist/mutators/Transaction.d.ts +48 -0
- package/dist/mutators/Transaction.js +64 -0
- package/dist/mutators/UndoManager.d.ts +114 -0
- package/dist/mutators/UndoManager.js +143 -0
- package/dist/mutators/defineMutators.d.ts +55 -0
- package/dist/mutators/defineMutators.js +28 -0
- package/dist/policy/index.d.ts +19 -0
- package/dist/policy/index.js +18 -0
- package/dist/policy/types.d.ts +74 -0
- package/dist/policy/types.js +17 -0
- package/dist/principal.d.ts +44 -0
- package/dist/principal.js +49 -0
- package/dist/query/client.d.ts +43 -0
- package/dist/query/client.js +84 -0
- package/dist/query/index.d.ts +6 -0
- package/dist/query/index.js +5 -0
- package/dist/query/types.d.ts +143 -0
- package/dist/query/types.js +36 -0
- package/dist/react/AbloProvider.d.ts +205 -0
- package/dist/react/AbloProvider.js +398 -0
- package/dist/react/ClientSideSuspense.d.ts +36 -0
- package/dist/react/ClientSideSuspense.js +17 -0
- package/dist/react/DefaultFallback.d.ts +24 -0
- package/dist/react/DefaultFallback.js +43 -0
- package/dist/react/SyncGroupProvider.d.ts +19 -0
- package/dist/react/SyncGroupProvider.js +44 -0
- package/dist/react/context.d.ts +161 -0
- package/dist/react/context.js +35 -0
- package/dist/react/index.d.ts +64 -0
- package/dist/react/index.js +73 -0
- package/dist/react/internalContext.d.ts +35 -0
- package/dist/react/internalContext.js +3 -0
- package/dist/react/useAblo.d.ts +72 -0
- package/dist/react/useAblo.js +63 -0
- package/dist/react/useCurrentUserId.d.ts +21 -0
- package/dist/react/useCurrentUserId.js +33 -0
- package/dist/react/useErrorListener.d.ts +20 -0
- package/dist/react/useErrorListener.js +39 -0
- package/dist/react/useIntent.d.ts +29 -0
- package/dist/react/useIntent.js +42 -0
- package/dist/react/useMutate.d.ts +83 -0
- package/dist/react/useMutate.js +122 -0
- package/dist/react/useMutationFailureListener.d.ts +26 -0
- package/dist/react/useMutationFailureListener.js +38 -0
- package/dist/react/useMutators.d.ts +56 -0
- package/dist/react/useMutators.js +66 -0
- package/dist/react/usePresence.d.ts +32 -0
- package/dist/react/usePresence.js +41 -0
- package/dist/react/useQuery.d.ts +123 -0
- package/dist/react/useQuery.js +145 -0
- package/dist/react/useReactive.d.ts +35 -0
- package/dist/react/useReactive.js +111 -0
- package/dist/react/useReader.d.ts +69 -0
- package/dist/react/useReader.js +73 -0
- package/dist/react/useSyncStatus.d.ts +61 -0
- package/dist/react/useSyncStatus.js +76 -0
- package/dist/react/useUndoScope.d.ts +36 -0
- package/dist/react/useUndoScope.js +73 -0
- package/dist/realtime/index.d.ts +10 -0
- package/dist/realtime/index.js +9 -0
- package/dist/schema/field.d.ts +134 -0
- package/dist/schema/field.js +264 -0
- package/dist/schema/index.d.ts +29 -0
- package/dist/schema/index.js +38 -0
- package/dist/schema/model.d.ts +326 -0
- package/dist/schema/model.js +89 -0
- package/dist/schema/queries.d.ts +203 -0
- package/dist/schema/queries.js +145 -0
- package/dist/schema/relation.d.ts +172 -0
- package/dist/schema/relation.js +104 -0
- package/dist/schema/schema.d.ts +259 -0
- package/dist/schema/schema.js +188 -0
- package/dist/schema/sugar.d.ts +129 -0
- package/dist/schema/sugar.js +94 -0
- package/dist/source/index.d.ts +423 -0
- package/dist/source/index.js +320 -0
- package/dist/source/pushQueue.d.ts +112 -0
- package/dist/source/pushQueue.js +249 -0
- package/dist/stores/ObjectStore.d.ts +103 -0
- package/dist/stores/ObjectStore.js +371 -0
- package/dist/stores/ObjectStoreContract.d.ts +39 -0
- package/dist/stores/ObjectStoreContract.js +1 -0
- package/dist/stores/SyncActionStore.d.ts +101 -0
- package/dist/stores/SyncActionStore.js +481 -0
- package/dist/sync/BootstrapHelper.d.ts +127 -0
- package/dist/sync/BootstrapHelper.js +434 -0
- package/dist/sync/ConnectionManager.d.ts +136 -0
- package/dist/sync/ConnectionManager.js +465 -0
- package/dist/sync/HydrationCoordinator.d.ts +137 -0
- package/dist/sync/HydrationCoordinator.js +468 -0
- package/dist/sync/NetworkProbe.d.ts +43 -0
- package/dist/sync/NetworkProbe.js +113 -0
- package/dist/sync/OfflineFlush.d.ts +9 -0
- package/dist/sync/OfflineFlush.js +22 -0
- package/dist/sync/OfflineTransactionStore.d.ts +37 -0
- package/dist/sync/OfflineTransactionStore.js +263 -0
- package/dist/sync/SyncWebSocket.d.ts +663 -0
- package/dist/sync/SyncWebSocket.js +1336 -0
- package/dist/sync/createIntentStream.d.ts +33 -0
- package/dist/sync/createIntentStream.js +243 -0
- package/dist/sync/createPresenceStream.d.ts +46 -0
- package/dist/sync/createPresenceStream.js +192 -0
- package/dist/sync/createSnapshot.d.ts +33 -0
- package/dist/sync/createSnapshot.js +124 -0
- package/dist/sync/participants.d.ts +114 -0
- package/dist/sync/participants.js +336 -0
- package/dist/sync/schemas.d.ts +79 -0
- package/dist/sync/schemas.js +78 -0
- package/dist/testing/fixtures/bootstrap.d.ts +45 -0
- package/dist/testing/fixtures/bootstrap.js +53 -0
- package/dist/testing/fixtures/deltas.d.ts +86 -0
- package/dist/testing/fixtures/deltas.js +139 -0
- package/dist/testing/fixtures/models.d.ts +82 -0
- package/dist/testing/fixtures/models.js +270 -0
- package/dist/testing/helpers/react-wrapper.d.ts +66 -0
- package/dist/testing/helpers/react-wrapper.js +64 -0
- package/dist/testing/helpers/sync-engine-harness.d.ts +55 -0
- package/dist/testing/helpers/sync-engine-harness.js +70 -0
- package/dist/testing/helpers/wait.d.ts +25 -0
- package/dist/testing/helpers/wait.js +44 -0
- package/dist/testing/index.d.ts +21 -0
- package/dist/testing/index.js +32 -0
- package/dist/testing/mocks/MockMutationExecutor.d.ts +65 -0
- package/dist/testing/mocks/MockMutationExecutor.js +139 -0
- package/dist/testing/mocks/MockNetworkMonitor.d.ts +20 -0
- package/dist/testing/mocks/MockNetworkMonitor.js +46 -0
- package/dist/testing/mocks/MockSyncContext.d.ts +64 -0
- package/dist/testing/mocks/MockSyncContext.js +100 -0
- package/dist/testing/mocks/MockSyncStore.d.ts +88 -0
- package/dist/testing/mocks/MockSyncStore.js +171 -0
- package/dist/testing/mocks/MockWebSocket.d.ts +66 -0
- package/dist/testing/mocks/MockWebSocket.js +117 -0
- package/dist/transactions/OptimisticEchoTracker.d.ts +82 -0
- package/dist/transactions/OptimisticEchoTracker.js +104 -0
- package/dist/transactions/TransactionQueue.d.ts +499 -0
- package/dist/transactions/TransactionQueue.js +1895 -0
- package/dist/transactions/index.d.ts +16 -0
- package/dist/transactions/index.js +7 -0
- package/dist/transactions/mutation-error-handler.d.ts +5 -0
- package/dist/transactions/mutation-error-handler.js +39 -0
- package/dist/types/global.d.ts +107 -0
- package/dist/types/global.js +38 -0
- package/dist/types/index.d.ts +241 -0
- package/dist/types/index.js +70 -0
- package/dist/types/streams.d.ts +495 -0
- package/dist/types/streams.js +11 -0
- package/dist/utils/asyncIterator.d.ts +41 -0
- package/dist/utils/asyncIterator.js +142 -0
- package/dist/utils/duration.d.ts +28 -0
- package/dist/utils/duration.js +47 -0
- package/dist/utils/mobx-setup.d.ts +42 -0
- package/dist/utils/mobx-setup.js +381 -0
- package/docs/api-keys.md +24 -0
- package/docs/api.md +230 -0
- package/docs/audit.md +81 -0
- package/docs/capabilities.md +163 -0
- package/docs/client-behavior.md +202 -0
- package/docs/data-sources.md +214 -0
- package/docs/examples/agent-human.md +84 -0
- package/docs/examples/ai-sdk-tool.md +92 -0
- package/docs/examples/existing-python-backend.md +249 -0
- package/docs/examples/nextjs.md +88 -0
- package/docs/examples/server-agent.md +86 -0
- package/docs/guarantees.md +148 -0
- package/docs/index.md +97 -0
- package/docs/integration-guide.md +493 -0
- package/docs/interaction-model.md +140 -0
- package/docs/mcp/claude-code.md +43 -0
- package/docs/mcp/cursor.md +53 -0
- package/docs/mcp/windsurf.md +46 -0
- package/docs/mcp.md +59 -0
- package/docs/quickstart.md +152 -0
- package/docs/react.md +115 -0
- package/docs/roadmap.md +45 -0
- package/examples/README.md +54 -0
- package/examples/data-source/README.md +102 -0
- package/examples/data-source/ablo-driver.ts +89 -0
- package/examples/data-source/customer-server.ts +208 -0
- package/examples/data-source/run.ts +101 -0
- package/examples/data-source/schema.ts +25 -0
- package/examples/quickstart.ts +54 -0
- package/examples/tsconfig.json +16 -0
- package/llms.txt +143 -0
- package/package.json +147 -0
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TransactionQueue - Production-ready transaction management
|
|
3
|
+
*
|
|
4
|
+
* Key features:
|
|
5
|
+
* - Optimistic updates with rollback
|
|
6
|
+
* - Conflict resolution strategies
|
|
7
|
+
* - LINEAR-style microtask batching (transactions in same event loop share batchId)
|
|
8
|
+
* - Proper dependency injection (no singleton)
|
|
9
|
+
*/
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
import type { Database } from '../Database.js';
|
|
12
|
+
import { Model } from '../Model.js';
|
|
13
|
+
import type { MutationOptions } from '../interfaces/index.js';
|
|
14
|
+
export interface UserContext {
|
|
15
|
+
userId: string;
|
|
16
|
+
organizationId: string;
|
|
17
|
+
role?: string;
|
|
18
|
+
teamIds?: string[];
|
|
19
|
+
}
|
|
20
|
+
/** Wire-format mutation payload (post-projection). */
|
|
21
|
+
type MutationInput = Record<string, unknown>;
|
|
22
|
+
type TransactionWriteOptions = Pick<MutationOptions, 'readAt' | 'onStale'>;
|
|
23
|
+
export interface Transaction {
|
|
24
|
+
id: string;
|
|
25
|
+
type: 'create' | 'update' | 'delete' | 'archive' | 'unarchive';
|
|
26
|
+
modelName: string;
|
|
27
|
+
modelId: string;
|
|
28
|
+
modelKey: string;
|
|
29
|
+
data?: MutationInput;
|
|
30
|
+
previousData?: MutationInput | null;
|
|
31
|
+
context: UserContext;
|
|
32
|
+
status: 'pending' | 'executing' | 'awaiting_delta' | 'completed' | 'failed' | 'rolled_back';
|
|
33
|
+
createdAt: number;
|
|
34
|
+
attempts: number;
|
|
35
|
+
priority: 'normal' | 'high';
|
|
36
|
+
priorityScore: number;
|
|
37
|
+
writeOptions?: TransactionWriteOptions;
|
|
38
|
+
batchId?: string;
|
|
39
|
+
/** LINEAR PATTERN: syncId threshold - transaction confirms when delta.id >= this value */
|
|
40
|
+
syncIdNeededForCompletion?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Resolves when the server has confirmed this transaction (delta arrived
|
|
43
|
+
* or HTTP ack). Rejects with the originating error if the transaction is
|
|
44
|
+
* permanently rolled back. Name matches the queue's existing `'confirmed'`
|
|
45
|
+
* status vocabulary (`commits.create({wait:'confirmed'})`,
|
|
46
|
+
* `waitForConfirmation`) — gives call sites a single `await` point for
|
|
47
|
+
* "did my write land?", so failures surface at the source instead of
|
|
48
|
+
* leaking via silent pool rollback. The rejection error is the same
|
|
49
|
+
* `AbloError` recorded on the queue's `transaction:failed` event.
|
|
50
|
+
*/
|
|
51
|
+
confirmation?: Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A raw multi-op commit transaction queued via `ablo.commits.create()`.
|
|
55
|
+
*
|
|
56
|
+
* Distinct from the per-model `Transaction` above: operations are
|
|
57
|
+
* pre-built by the caller and the envelope is atomic — no coalescing,
|
|
58
|
+
* no FK reordering, no optimistic local apply. The lane shares the
|
|
59
|
+
* same `mutationExecutor.commit()` underneath as the model-proxy
|
|
60
|
+
* batch path, so reconnect-retry behavior is identical.
|
|
61
|
+
*/
|
|
62
|
+
interface CommitTransaction {
|
|
63
|
+
id: string;
|
|
64
|
+
kind: 'commit';
|
|
65
|
+
operations: Array<{
|
|
66
|
+
type: string;
|
|
67
|
+
model: string;
|
|
68
|
+
id: string;
|
|
69
|
+
input?: Record<string, unknown>;
|
|
70
|
+
transactionId?: string;
|
|
71
|
+
readAt?: number | null;
|
|
72
|
+
onStale?: 'reject' | 'force' | 'flag' | 'merge' | null;
|
|
73
|
+
}>;
|
|
74
|
+
causedByTaskId?: string | null;
|
|
75
|
+
status: 'pending' | 'executing' | 'completed' | 'failed';
|
|
76
|
+
createdAt: number;
|
|
77
|
+
attempts: number;
|
|
78
|
+
lastSyncId?: number;
|
|
79
|
+
error?: Error;
|
|
80
|
+
}
|
|
81
|
+
interface ConflictResolution {
|
|
82
|
+
strategy: 'last-write-wins' | 'merge' | 'reject' | 'custom';
|
|
83
|
+
resolver?: (local: MutationInput | undefined, remote: MutationInput) => MutationInput;
|
|
84
|
+
}
|
|
85
|
+
interface TransactionQueueConfig {
|
|
86
|
+
maxBatchSize: number;
|
|
87
|
+
batchDelay: number;
|
|
88
|
+
maxRetries: number;
|
|
89
|
+
conflictResolution: ConflictResolution;
|
|
90
|
+
enablePersistence: boolean;
|
|
91
|
+
enableOptimistic: boolean;
|
|
92
|
+
maxExecutingTransactions: number;
|
|
93
|
+
deltaConfirmationTimeout: number;
|
|
94
|
+
/**
|
|
95
|
+
* Exponential backoff for retryable server responses (HTTP 429/503).
|
|
96
|
+
* `baseMs` is the first retry delay; each subsequent attempt doubles
|
|
97
|
+
* up to `capMs`. Final delay = min(capMs, baseMs * 2^(attempt-1)) +
|
|
98
|
+
* up to 100ms of jitter. Defaults: 200ms / 1500ms.
|
|
99
|
+
*/
|
|
100
|
+
retryBackoff: {
|
|
101
|
+
baseMs: number;
|
|
102
|
+
capMs: number;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Grace window in ms before in-flight commit-lane transactions are
|
|
106
|
+
* failed with `AbloConnectionError` after the WebSocket transitions
|
|
107
|
+
* to `'disconnected'`. Brief disconnects (deploy rotations, mobile
|
|
108
|
+
* jitter) are absorbed transparently; only persistent disconnects
|
|
109
|
+
* surface as failures. Aligned with the 30s convention from the
|
|
110
|
+
* WebSocket reconnection guidance (websocket.org). Set lower for
|
|
111
|
+
* human-interactive consumers (e.g. 10s for chat) or higher for
|
|
112
|
+
* batch workers (e.g. 60s for agent-worker).
|
|
113
|
+
*
|
|
114
|
+
* Without this deadline, `commits.create({wait:'confirmed'})` waits
|
|
115
|
+
* forever when the WS dies mid-flight — see the 2026-05-15 wedge.
|
|
116
|
+
*/
|
|
117
|
+
commitOfflineGraceMs: number;
|
|
118
|
+
}
|
|
119
|
+
export declare class TransactionQueue extends EventEmitter {
|
|
120
|
+
private store;
|
|
121
|
+
private _mutationExecutor;
|
|
122
|
+
private get mutationExecutor();
|
|
123
|
+
private executionQueue;
|
|
124
|
+
private isProcessing;
|
|
125
|
+
private processTimer?;
|
|
126
|
+
private processScheduled;
|
|
127
|
+
private createdTransactions;
|
|
128
|
+
private commitScheduled;
|
|
129
|
+
private inFlightByModel;
|
|
130
|
+
private pendingMergeByModel;
|
|
131
|
+
private commitLane;
|
|
132
|
+
private commitStore;
|
|
133
|
+
private commitProcessing;
|
|
134
|
+
private computePriorityScore;
|
|
135
|
+
private ensureDerivedFields;
|
|
136
|
+
private mergeUpdateData;
|
|
137
|
+
private config;
|
|
138
|
+
private executingCount;
|
|
139
|
+
private optimisticUpdates;
|
|
140
|
+
private deltaConfirmationTimeouts;
|
|
141
|
+
private deltaConfirmationRetries;
|
|
142
|
+
private isConnectedFn;
|
|
143
|
+
private commitOfflineGraceTimer;
|
|
144
|
+
private lastSeenSyncId;
|
|
145
|
+
private static readonly DELTA_MAX_RETRIES;
|
|
146
|
+
private static readonly DELTA_INITIAL_TIMEOUT_MS;
|
|
147
|
+
private static readonly DELTA_MAX_TIMEOUT_MS;
|
|
148
|
+
private batchIndex;
|
|
149
|
+
/**
|
|
150
|
+
* Resolvers for per-transaction `confirmation` promises. Populated in
|
|
151
|
+
* `attachConfirmation` at staging time, consumed by the constructor-time
|
|
152
|
+
* listeners on `transaction:completed` / `transaction:failed`. Kept off
|
|
153
|
+
* the Transaction row so the store's iteration order stays plain-data
|
|
154
|
+
* and serialization-friendly.
|
|
155
|
+
*/
|
|
156
|
+
private confirmationResolvers;
|
|
157
|
+
constructor(config?: Partial<TransactionQueueConfig>);
|
|
158
|
+
/**
|
|
159
|
+
* Look up the in-flight `confirmation` promise for a (model, id) pair.
|
|
160
|
+
* Returns the promise from the most-recent live transaction matching
|
|
161
|
+
* the given model+id, or `Promise.resolve()` if none is open (which
|
|
162
|
+
* means either "already confirmed" or "never staged" — both safe
|
|
163
|
+
* outcomes for the routing-helper grace-window use case).
|
|
164
|
+
*
|
|
165
|
+
* Looks across `pending`, `executing`, and `awaiting_delta` — these
|
|
166
|
+
* are the three non-terminal statuses where rollback is still
|
|
167
|
+
* possible. Skips `completed` (already settled) and `failed` /
|
|
168
|
+
* `rolled_back` (already rejected; the call site missed the
|
|
169
|
+
* `confirmation` window and should rely on `onMutationFailure` toast
|
|
170
|
+
* instead).
|
|
171
|
+
*
|
|
172
|
+
* Distinct from `tx.confirmation` on a known transaction — used by
|
|
173
|
+
* call sites that hold a Model reference (returned by
|
|
174
|
+
* `ablo.<model>.create()`) but never see the underlying transaction.
|
|
175
|
+
*/
|
|
176
|
+
confirmationFor(modelName: string, modelId: string): Promise<void>;
|
|
177
|
+
/**
|
|
178
|
+
* Attach a hot `confirmation` promise to a freshly created transaction.
|
|
179
|
+
* Must be called BEFORE the transaction is staged so the call site can
|
|
180
|
+
* `await tx.confirmation` synchronously after the create/update/delete
|
|
181
|
+
* call returns. Idempotent: returns early if the tx already has one.
|
|
182
|
+
*
|
|
183
|
+
* The unhandled-rejection trap is mandatory — most call sites won't
|
|
184
|
+
* `await confirmation`, and Node/browser would otherwise crash on the
|
|
185
|
+
* rejection. Consumers who *do* want failure visibility just attach a
|
|
186
|
+
* `.then`/`.catch` and the trap becomes a no-op.
|
|
187
|
+
*/
|
|
188
|
+
private attachConfirmation;
|
|
189
|
+
/**
|
|
190
|
+
* Set connection state checker - prevents rollbacks during disconnection.
|
|
191
|
+
* When disconnected, timeouts re-schedule instead of rolling back.
|
|
192
|
+
*/
|
|
193
|
+
setConnectionChecker(fn: () => boolean): void;
|
|
194
|
+
/**
|
|
195
|
+
* Drive the offline-grace timer for in-flight commit-lane transactions.
|
|
196
|
+
*
|
|
197
|
+
* On `'disconnected'`: start a one-shot timer of
|
|
198
|
+
* `config.commitOfflineGraceMs`. If the timer fires (disconnect
|
|
199
|
+
* persisted past grace), iterate every commit-lane transaction with
|
|
200
|
+
* `status ∈ {'pending', 'executing'}` and emit
|
|
201
|
+
* `transaction:failed:${id}` with an `AbloConnectionError`. That
|
|
202
|
+
* lets `waitForCommitReceipt` reject in seconds instead of hanging
|
|
203
|
+
* forever — which is what wedged the 2026-05-15 subagent run.
|
|
204
|
+
*
|
|
205
|
+
* On `'connected'`: clear any pending grace timer. Brief blips are
|
|
206
|
+
* absorbed transparently; the existing reconnect-retry path in
|
|
207
|
+
* `processCommitLane` / `flushOfflineQueue` handles the resumption.
|
|
208
|
+
*
|
|
209
|
+
* Called from SyncClient's `setConnectionState` after the
|
|
210
|
+
* `'connection:disconnected'` / `'connection:established'` events.
|
|
211
|
+
*/
|
|
212
|
+
setConnectionState(state: 'connected' | 'disconnected'): void;
|
|
213
|
+
private failInFlightCommitsOnOffline;
|
|
214
|
+
/**
|
|
215
|
+
* Bind the executor for this queue instance. Called by the owning Ablo
|
|
216
|
+
* right after `BaseSyncedStore` is constructed so the executor's
|
|
217
|
+
* `storeHolder.store` closure resolves to *this* Ablo's WS — not whichever
|
|
218
|
+
* Ablo most recently called `initSyncEngine()`.
|
|
219
|
+
*/
|
|
220
|
+
setMutationExecutor(executor: import('../interfaces/index.js').MutationExecutor): void;
|
|
221
|
+
/**
|
|
222
|
+
* Stage a transaction for commit (Linear pattern)
|
|
223
|
+
* Transactions staged in the same event loop tick will be committed together
|
|
224
|
+
*/
|
|
225
|
+
private stageTransaction;
|
|
226
|
+
/**
|
|
227
|
+
* Schedule commit of staged transactions via microtask
|
|
228
|
+
* This ensures all synchronous transaction creates are batched together
|
|
229
|
+
*/
|
|
230
|
+
private scheduleCommit;
|
|
231
|
+
/**
|
|
232
|
+
* Commit all staged transactions to the execution queue (Linear pattern)
|
|
233
|
+
* All transactions get the same batchIndex for efficient batching
|
|
234
|
+
*/
|
|
235
|
+
private commitCreatedTransactions;
|
|
236
|
+
flushOfflineQueue(): Promise<void>;
|
|
237
|
+
/**
|
|
238
|
+
* Create operation with optimistic update
|
|
239
|
+
*/
|
|
240
|
+
create(model: Model, context: UserContext, writeOptions?: TransactionWriteOptions): Promise<Transaction>;
|
|
241
|
+
/**
|
|
242
|
+
* Update operation with conflict detection
|
|
243
|
+
* @param precomputedChanges - Optional pre-captured changes (avoids re-reading from model)
|
|
244
|
+
*/
|
|
245
|
+
update(model: Model, context: UserContext, precomputedChanges?: Record<string, unknown>, writeOptions?: TransactionWriteOptions): Promise<Transaction>;
|
|
246
|
+
/**
|
|
247
|
+
* Delete operation with cascade handling
|
|
248
|
+
*/
|
|
249
|
+
delete(model: Model, context: UserContext, writeOptions?: TransactionWriteOptions): Promise<Transaction>;
|
|
250
|
+
/**
|
|
251
|
+
* Upload attachment — delegates to attachment-uploader.ts
|
|
252
|
+
*/
|
|
253
|
+
uploadAttachment(_file: File, options: {
|
|
254
|
+
id: string;
|
|
255
|
+
[key: string]: unknown;
|
|
256
|
+
}, _context: UserContext): Promise<{
|
|
257
|
+
url: string;
|
|
258
|
+
} | null>;
|
|
259
|
+
/**
|
|
260
|
+
* Batch upload attachments — delegates to MutationExecutor
|
|
261
|
+
*/
|
|
262
|
+
batchUploadAttachments(_files: File[], items: Array<{
|
|
263
|
+
id: string;
|
|
264
|
+
[key: string]: unknown;
|
|
265
|
+
}>, _context: UserContext): Promise<Array<{
|
|
266
|
+
id: string;
|
|
267
|
+
url: string;
|
|
268
|
+
}>>;
|
|
269
|
+
/**
|
|
270
|
+
* Archive operation
|
|
271
|
+
*/
|
|
272
|
+
archive(model: Model, context: UserContext, writeOptions?: TransactionWriteOptions): Promise<Transaction>;
|
|
273
|
+
/**
|
|
274
|
+
* Unarchive operation
|
|
275
|
+
*/
|
|
276
|
+
unarchive(model: Model, context: UserContext): Promise<Transaction>;
|
|
277
|
+
/**
|
|
278
|
+
* Enqueue transaction for execution
|
|
279
|
+
*/
|
|
280
|
+
private enqueue;
|
|
281
|
+
private scheduleProcessing;
|
|
282
|
+
/**
|
|
283
|
+
* Process batch of transactions using LINEAR-style unified batch execution.
|
|
284
|
+
*
|
|
285
|
+
* Key optimization: Instead of making separate calls per operation type/model,
|
|
286
|
+
* we collect ALL batchable operations and send them in a SINGLE commit call.
|
|
287
|
+
* The sync-server handles mixed types atomically inside one transaction.
|
|
288
|
+
*
|
|
289
|
+
* This reduces N round-trips to 1, dramatically improving batch latency.
|
|
290
|
+
*/
|
|
291
|
+
private processBatch;
|
|
292
|
+
/**
|
|
293
|
+
* LINEAR PATTERN: Confirm all awaiting transactions when delta with syncId >= threshold arrives.
|
|
294
|
+
* This replaces clientMutationId echoing - transactions are confirmed by sync ID threshold.
|
|
295
|
+
* @param syncId - The sync ID of the received delta
|
|
296
|
+
*/
|
|
297
|
+
onDeltaReceived(syncId: number): void;
|
|
298
|
+
private scheduleDeltaConfirmationTimeout;
|
|
299
|
+
private cancelDeltaConfirmationTimeout;
|
|
300
|
+
/**
|
|
301
|
+
* Wait for a transaction to be confirmed via delta echo (Linear pattern)
|
|
302
|
+
* Reuses existing timeout mechanism from scheduleDeltaConfirmationTimeout
|
|
303
|
+
*/
|
|
304
|
+
waitForConfirmation(transactionId: string): Promise<void>;
|
|
305
|
+
hasClientMutationId(id: string): boolean;
|
|
306
|
+
/**
|
|
307
|
+
* Enqueue a raw multi-op atomic commit envelope (the `ablo.commits.create`
|
|
308
|
+
* path). Operations are pre-built by the caller; the queue's job is
|
|
309
|
+
* retry-on-reconnect + idempotent dedup, NOT optimistic apply or FK
|
|
310
|
+
* ordering. Same idempotency key (clientTxId) is dropped on the floor
|
|
311
|
+
* if already in flight — server-side `mutation_log` handles cross-session
|
|
312
|
+
* dedup; this guard handles same-session double-enqueue.
|
|
313
|
+
*/
|
|
314
|
+
enqueueCommit(clientTxId: string, operations: CommitTransaction['operations'], options?: {
|
|
315
|
+
causedByTaskId?: string | null;
|
|
316
|
+
}): void;
|
|
317
|
+
/**
|
|
318
|
+
* Drain pending commit-lane envelopes serially. Transient failures
|
|
319
|
+
* (network, ws_not_ready) leave the head-of-queue tx in `pending` and
|
|
320
|
+
* break — reconnect handler re-kicks via `flushOfflineQueue`.
|
|
321
|
+
* Permanent failures emit `transaction:failed:<id>` and drop the tx.
|
|
322
|
+
*/
|
|
323
|
+
private processCommitLane;
|
|
324
|
+
/**
|
|
325
|
+
* Promise-based confirmation for a commit-lane transaction. Resolves
|
|
326
|
+
* with the server-side `lastSyncId` once `mutation_result` lands;
|
|
327
|
+
* rejects on permanent failure. Backs the `wait: 'confirmed'` semantics
|
|
328
|
+
* of `ablo.commits.create()`.
|
|
329
|
+
*/
|
|
330
|
+
waitForCommitReceipt(clientTxId: string): Promise<{
|
|
331
|
+
lastSyncId: number;
|
|
332
|
+
}>;
|
|
333
|
+
private isReorderPayload;
|
|
334
|
+
/**
|
|
335
|
+
* Determine if an error is transient (retryable) vs permanent (non-retryable).
|
|
336
|
+
*
|
|
337
|
+
* IMPORTANT: Uses a BLOCKLIST approach for safety - only retry on known transient errors.
|
|
338
|
+
* Any unknown error type defaults to permanent (don't retry) to prevent infinite loops.
|
|
339
|
+
*
|
|
340
|
+
* Transient errors (will retry):
|
|
341
|
+
* - Network failures, connection errors, timeouts
|
|
342
|
+
* - Server errors (5xx status codes)
|
|
343
|
+
* - Rate limiting (429)
|
|
344
|
+
*
|
|
345
|
+
* Permanent errors (won't retry - includes but not limited to):
|
|
346
|
+
* - Validation errors, constraint violations
|
|
347
|
+
* - Not found, unauthorized, forbidden
|
|
348
|
+
* - Any other business logic error from the server
|
|
349
|
+
*/
|
|
350
|
+
private isPermanentError;
|
|
351
|
+
/**
|
|
352
|
+
* Handle transaction failure
|
|
353
|
+
*/
|
|
354
|
+
private handleFailure;
|
|
355
|
+
/**
|
|
356
|
+
* Conflict resolution
|
|
357
|
+
*/
|
|
358
|
+
handleConflict(transaction: Transaction, serverData: MutationInput): Promise<void>;
|
|
359
|
+
/**
|
|
360
|
+
* Optimistic updates
|
|
361
|
+
*/
|
|
362
|
+
private applyOptimisticCreate;
|
|
363
|
+
private applyOptimisticUpdate;
|
|
364
|
+
private applyOptimisticDelete;
|
|
365
|
+
private rollbackOptimistic;
|
|
366
|
+
/**
|
|
367
|
+
* Execute individual transaction via the unified commit path
|
|
368
|
+
*/
|
|
369
|
+
private executeTransaction;
|
|
370
|
+
/**
|
|
371
|
+
* Persistence
|
|
372
|
+
*/
|
|
373
|
+
loadPersistedTransactions(database: Database): Promise<void>;
|
|
374
|
+
private deserializeTransaction;
|
|
375
|
+
/**
|
|
376
|
+
* Cancel transactions for a specific model
|
|
377
|
+
*/
|
|
378
|
+
cancelTransactionsForModel(modelId: string, transactionType?: string): Transaction[];
|
|
379
|
+
/**
|
|
380
|
+
* LINEAR PATTERN: Cancel transactions for child entities by foreign key
|
|
381
|
+
*
|
|
382
|
+
* Used by SyncedStore for cascade cancellation when a parent is deleted.
|
|
383
|
+
* This keeps FK relationship knowledge in ModelRegistry/SyncedStore,
|
|
384
|
+
* while TransactionQueue just handles the cancellation mechanics.
|
|
385
|
+
*
|
|
386
|
+
* @param childModelName - The child model type (e.g., 'SlideLayer')
|
|
387
|
+
* @param foreignKey - The FK property name (e.g., 'slideId')
|
|
388
|
+
* @param parentId - The deleted parent's ID
|
|
389
|
+
* @returns Number of transactions cancelled
|
|
390
|
+
*/
|
|
391
|
+
cancelTransactionsByForeignKey(childModelName: string, foreignKey: string, parentId: string): number;
|
|
392
|
+
/**
|
|
393
|
+
* Get count of outstanding transactions
|
|
394
|
+
*/
|
|
395
|
+
getOutstandingTransactionCount(): number;
|
|
396
|
+
/**
|
|
397
|
+
* Utilities
|
|
398
|
+
*/
|
|
399
|
+
private generateId;
|
|
400
|
+
private mergeData;
|
|
401
|
+
private extractCreateData;
|
|
402
|
+
private mapChangesToInput;
|
|
403
|
+
private extractUpdateData;
|
|
404
|
+
private buildUpdateInput;
|
|
405
|
+
private extractPreviousData;
|
|
406
|
+
/**
|
|
407
|
+
* Public API
|
|
408
|
+
*/
|
|
409
|
+
getStats(): {
|
|
410
|
+
pending: number;
|
|
411
|
+
executing: number;
|
|
412
|
+
completed: number;
|
|
413
|
+
failed: number;
|
|
414
|
+
optimistic: number;
|
|
415
|
+
totalTransactions: number;
|
|
416
|
+
batchIndex: number;
|
|
417
|
+
config: {
|
|
418
|
+
maxBatchSize: number;
|
|
419
|
+
batchDelay: number;
|
|
420
|
+
maxRetries: number;
|
|
421
|
+
conflictResolution: ConflictResolution;
|
|
422
|
+
enablePersistence: boolean;
|
|
423
|
+
enableOptimistic: boolean;
|
|
424
|
+
maxExecutingTransactions: number;
|
|
425
|
+
deltaConfirmationTimeout: number;
|
|
426
|
+
/**
|
|
427
|
+
* Exponential backoff for retryable server responses (HTTP 429/503).
|
|
428
|
+
* `baseMs` is the first retry delay; each subsequent attempt doubles
|
|
429
|
+
* up to `capMs`. Final delay = min(capMs, baseMs * 2^(attempt-1)) +
|
|
430
|
+
* up to 100ms of jitter. Defaults: 200ms / 1500ms.
|
|
431
|
+
*/
|
|
432
|
+
retryBackoff: {
|
|
433
|
+
baseMs: number;
|
|
434
|
+
capMs: number;
|
|
435
|
+
};
|
|
436
|
+
/**
|
|
437
|
+
* Grace window in ms before in-flight commit-lane transactions are
|
|
438
|
+
* failed with `AbloConnectionError` after the WebSocket transitions
|
|
439
|
+
* to `'disconnected'`. Brief disconnects (deploy rotations, mobile
|
|
440
|
+
* jitter) are absorbed transparently; only persistent disconnects
|
|
441
|
+
* surface as failures. Aligned with the 30s convention from the
|
|
442
|
+
* WebSocket reconnection guidance (websocket.org). Set lower for
|
|
443
|
+
* human-interactive consumers (e.g. 10s for chat) or higher for
|
|
444
|
+
* batch workers (e.g. 60s for agent-worker).
|
|
445
|
+
*
|
|
446
|
+
* Without this deadline, `commits.create({wait:'confirmed'})` waits
|
|
447
|
+
* forever when the WS dies mid-flight — see the 2026-05-15 wedge.
|
|
448
|
+
*/
|
|
449
|
+
commitOfflineGraceMs: number;
|
|
450
|
+
};
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* Get detailed debug info for the sync debug page
|
|
454
|
+
* Exposes internal state that helps diagnose delta confirmation issues
|
|
455
|
+
*/
|
|
456
|
+
getDebugInfo(): {
|
|
457
|
+
lastSeenSyncId: number;
|
|
458
|
+
awaitingDeltaCount: number;
|
|
459
|
+
awaitingDeltaTransactions: {
|
|
460
|
+
id: string;
|
|
461
|
+
type: "update" | "create" | "delete" | "archive" | "unarchive";
|
|
462
|
+
modelName: string;
|
|
463
|
+
modelId: string;
|
|
464
|
+
syncIdNeeded: number | undefined;
|
|
465
|
+
createdAt: number;
|
|
466
|
+
age: number;
|
|
467
|
+
}[];
|
|
468
|
+
pendingTransactions: {
|
|
469
|
+
id: string;
|
|
470
|
+
type: "update" | "create" | "delete" | "archive" | "unarchive";
|
|
471
|
+
modelName: string;
|
|
472
|
+
modelId: string;
|
|
473
|
+
}[];
|
|
474
|
+
executingTransactions: {
|
|
475
|
+
id: string;
|
|
476
|
+
type: "update" | "create" | "delete" | "archive" | "unarchive";
|
|
477
|
+
modelName: string;
|
|
478
|
+
modelId: string;
|
|
479
|
+
}[];
|
|
480
|
+
};
|
|
481
|
+
/**
|
|
482
|
+
* Set configuration
|
|
483
|
+
*/
|
|
484
|
+
setConfig(config: Partial<TransactionQueueConfig>): void;
|
|
485
|
+
/**
|
|
486
|
+
* Handle incoming sync delta - simplified for permanent IDs
|
|
487
|
+
*/
|
|
488
|
+
handleSyncDelta(delta: {
|
|
489
|
+
id: string;
|
|
490
|
+
modelName: string;
|
|
491
|
+
action: string;
|
|
492
|
+
data: any;
|
|
493
|
+
}): boolean;
|
|
494
|
+
/**
|
|
495
|
+
* Cleanup and dispose resources
|
|
496
|
+
*/
|
|
497
|
+
dispose(): void;
|
|
498
|
+
}
|
|
499
|
+
export {};
|