@korajs/store 0.4.0 → 0.5.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/dist/adapters/better-sqlite3.d.cts +1 -1
- package/dist/adapters/better-sqlite3.d.ts +1 -1
- package/dist/adapters/indexeddb.cjs +410 -17
- package/dist/adapters/indexeddb.cjs.map +1 -1
- package/dist/adapters/indexeddb.d.cts +23 -5
- package/dist/adapters/indexeddb.d.ts +23 -5
- package/dist/adapters/indexeddb.js +163 -18
- package/dist/adapters/indexeddb.js.map +1 -1
- package/dist/adapters/sqlite-wasm-shared-host.cjs +68 -0
- package/dist/adapters/sqlite-wasm-shared-host.cjs.map +1 -0
- package/dist/adapters/sqlite-wasm-shared-host.d.cts +2 -0
- package/dist/adapters/sqlite-wasm-shared-host.d.ts +2 -0
- package/dist/adapters/sqlite-wasm-shared-host.js +66 -0
- package/dist/adapters/sqlite-wasm-shared-host.js.map +1 -0
- package/dist/adapters/sqlite-wasm-worker.cjs +34 -5
- package/dist/adapters/sqlite-wasm-worker.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm-worker.js +34 -5
- package/dist/adapters/sqlite-wasm-worker.js.map +1 -1
- package/dist/adapters/sqlite-wasm.cjs +249 -2
- package/dist/adapters/sqlite-wasm.cjs.map +1 -1
- package/dist/adapters/sqlite-wasm.d.cts +15 -3
- package/dist/adapters/sqlite-wasm.d.ts +15 -3
- package/dist/adapters/sqlite-wasm.js +2 -2
- package/dist/audit-trace-store-AM4EWQNZ.js +15 -0
- package/dist/backup-JN3LB4YT.js +14 -0
- package/dist/backup-JN3LB4YT.js.map +1 -0
- package/dist/chunk-56LL4XP6.js +205 -0
- package/dist/chunk-56LL4XP6.js.map +1 -0
- package/dist/chunk-6AHYGQQT.js +425 -0
- package/dist/chunk-6AHYGQQT.js.map +1 -0
- package/dist/chunk-7BPETY5Y.js +570 -0
- package/dist/chunk-7BPETY5Y.js.map +1 -0
- package/dist/chunk-AGN3CIPB.js +188 -0
- package/dist/chunk-AGN3CIPB.js.map +1 -0
- package/dist/chunk-EZSTD2XC.js +380 -0
- package/dist/chunk-EZSTD2XC.js.map +1 -0
- package/dist/chunk-MYSJN3DF.js +117 -0
- package/dist/chunk-MYSJN3DF.js.map +1 -0
- package/dist/{chunk-DXKLAQ6P.js → chunk-XO4LMPAH.js} +1 -1
- package/dist/chunk-XO4LMPAH.js.map +1 -0
- package/dist/export-audit-5GV6VRDZ.js +15 -0
- package/dist/export-audit-5GV6VRDZ.js.map +1 -0
- package/dist/index.cjs +2183 -587
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +423 -187
- package/dist/index.d.ts +423 -187
- package/dist/index.js +886 -726
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +789 -0
- package/dist/internal.cjs.map +1 -0
- package/dist/internal.d.cts +154 -0
- package/dist/internal.d.ts +154 -0
- package/dist/internal.js +48 -0
- package/dist/internal.js.map +1 -0
- package/dist/{sqlite-wasm-channel-46AOWNPM.js → sqlite-wasm-channel-HDDW6UBH.js} +2 -2
- package/dist/sqlite-wasm-channel-HDDW6UBH.js.map +1 -0
- package/dist/{sqlite-wasm-channel-Lakjuk2E.d.cts → sqlite-wasm-channel-I9y_jObg.d.cts} +1 -0
- package/dist/{sqlite-wasm-channel-Lakjuk2E.d.ts → sqlite-wasm-channel-I9y_jObg.d.ts} +1 -0
- package/dist/types-BMyHmwvn.d.ts +163 -0
- package/dist/types-CTr00g_d.d.cts +163 -0
- package/dist/types-DepnRDk_.d.cts +212 -0
- package/dist/types-DepnRDk_.d.ts +212 -0
- package/package.json +23 -2
- package/dist/chunk-DXKLAQ6P.js.map +0 -1
- package/dist/chunk-ZP5AXQ3Z.js +0 -179
- package/dist/chunk-ZP5AXQ3Z.js.map +0 -1
- package/dist/types-DF-KDSK1.d.cts +0 -106
- package/dist/types-DF-KDSK1.d.ts +0 -106
- /package/dist/{sqlite-wasm-channel-46AOWNPM.js.map → audit-trace-store-AM4EWQNZ.js.map} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { M as MigrationPlan,
|
|
3
|
-
import {
|
|
1
|
+
import { C as CollectionRecord, S as StorageAdapter, Q as QueryDescriptor, c as SubscriptionCallback, W as WhereClause, d as OrderByDirection, L as LocalMutationHandler, e as StoreConfig, A as ApplyRemoteOptions, f as MaterializedRowSnapshot } from './types-DepnRDk_.js';
|
|
2
|
+
export { M as MigrationPlan, g as OrderByClause, h as StoreIsolation, T as Transaction, i as TransactionBufferedEntry, j as TransactionCommitBatch, k as TransactionCommitResult, l as WhereOperators } from './types-DepnRDk_.js';
|
|
3
|
+
import { Operation, KoraError, VersionVector, SchemaDefinition, MergeTrace, CollectionDefinition, SequenceConfig, HybridLogicalClock, CausalTracker, OperationLog, ApplyResult, StateMachineDefinition, KoraEvent } from '@korajs/core';
|
|
4
|
+
export { ApplyResult } from '@korajs/core';
|
|
5
|
+
import { R as RelationEnforcer, L as LocalMutationContext } from './types-BMyHmwvn.js';
|
|
6
|
+
export { C as Collection } from './types-BMyHmwvn.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* In-memory materialized state at a causal cut in the operation log.
|
|
10
|
+
* Read-only — does not mutate the live store.
|
|
11
|
+
*/
|
|
12
|
+
interface ReplaySnapshot {
|
|
13
|
+
/** The operation whose causal past was replayed (inclusive). */
|
|
14
|
+
targetOperation: Operation;
|
|
15
|
+
/** Operations applied in causal order (ancestors + target). */
|
|
16
|
+
operationsApplied: Operation[];
|
|
17
|
+
/** Non-deleted records per collection after replay. */
|
|
18
|
+
collections: Record<string, CollectionRecord[]>;
|
|
19
|
+
/** Look up a single record at the replay cut. Returns null if deleted or missing. */
|
|
20
|
+
findRecord(collection: string, recordId: string): CollectionRecord | null;
|
|
21
|
+
}
|
|
4
22
|
|
|
5
23
|
/**
|
|
6
24
|
* Thrown when a query is invalid (bad field names, invalid operators, etc.).
|
|
@@ -45,6 +63,205 @@ declare class PersistenceError extends KoraError {
|
|
|
45
63
|
constructor(message: string, context?: Record<string, unknown>);
|
|
46
64
|
}
|
|
47
65
|
|
|
66
|
+
/**
|
|
67
|
+
* How the local operation log may be compacted.
|
|
68
|
+
* Materialized collection rows are always kept as the convergence baseline.
|
|
69
|
+
*/
|
|
70
|
+
type CompactionStrategy = {
|
|
71
|
+
mode: 'never';
|
|
72
|
+
} | {
|
|
73
|
+
mode: 'after-ack';
|
|
74
|
+
/** Server version vector; defaults to persisted last-acked vector on the store. */
|
|
75
|
+
serverVector?: VersionVector;
|
|
76
|
+
} | {
|
|
77
|
+
mode: 'after-days';
|
|
78
|
+
/** Delete only ops older than this many days (still requires ack watermark). */
|
|
79
|
+
days: number;
|
|
80
|
+
serverVector?: VersionVector;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Result of a compaction run.
|
|
84
|
+
*/
|
|
85
|
+
interface CompactionResult {
|
|
86
|
+
/** Number of operation log rows removed. */
|
|
87
|
+
deletedCount: number;
|
|
88
|
+
/** Per-node sequence ceiling used for deletion (from server ack vector). */
|
|
89
|
+
watermark: VersionVector;
|
|
90
|
+
}
|
|
91
|
+
declare const COMPACTION_BASELINE_META_KEY = "compaction_baseline_at";
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Compute per-node sequence watermarks safe to compact (server has acknowledged these ops).
|
|
95
|
+
*/
|
|
96
|
+
declare function computeAckCompactionWatermark(serverVector: VersionVector): VersionVector;
|
|
97
|
+
/**
|
|
98
|
+
* Remove acknowledged, materialized operation log entries from `_kora_ops_*` tables.
|
|
99
|
+
* Does not modify collection rows — they are the compaction baseline snapshot.
|
|
100
|
+
*/
|
|
101
|
+
declare function compactOperationLog(adapter: StorageAdapter, schema: SchemaDefinition, strategy: CompactionStrategy, serverVector: VersionVector): Promise<CompactionResult>;
|
|
102
|
+
|
|
103
|
+
declare const LAST_ACKED_SERVER_VECTOR_META_KEY = "last_acked_server_vector";
|
|
104
|
+
/**
|
|
105
|
+
* Serialize a version vector for `_kora_meta` storage.
|
|
106
|
+
*/
|
|
107
|
+
declare function serializeVersionVectorToMeta(vector: VersionVector): string;
|
|
108
|
+
/**
|
|
109
|
+
* Deserialize a version vector from `_kora_meta`.
|
|
110
|
+
*/
|
|
111
|
+
declare function deserializeVersionVectorFromMeta(value: string): VersionVector;
|
|
112
|
+
/**
|
|
113
|
+
* Merge two version vectors, keeping the maximum sequence per node.
|
|
114
|
+
*/
|
|
115
|
+
declare function mergeVersionVectors(a: VersionVector, b: VersionVector): VersionVector;
|
|
116
|
+
/**
|
|
117
|
+
* Operations present locally but not yet on the server (per server version vector).
|
|
118
|
+
*/
|
|
119
|
+
declare function collectOperationsAheadOfServer(localVector: VersionVector, serverVector: VersionVector, fetchRange: (nodeId: string, fromSeq: number, toSeq: number) => Promise<Operation[]>): Promise<Operation[]>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* A merge or constraint decision persisted for enterprise audit export.
|
|
123
|
+
*/
|
|
124
|
+
interface PersistedAuditTrace {
|
|
125
|
+
/** Unique row id (UUID v7). */
|
|
126
|
+
id: string;
|
|
127
|
+
/** Wall-clock time when the trace was recorded (epoch ms). */
|
|
128
|
+
recordedAt: number;
|
|
129
|
+
/** Source event type from the Kora event bus. */
|
|
130
|
+
eventType: 'merge:completed' | 'merge:conflict' | 'constraint:violated';
|
|
131
|
+
/** Constraint name when {@link eventType} is `constraint:violated`. */
|
|
132
|
+
constraint?: string;
|
|
133
|
+
/** Full merge trace including conflicting operations and resolution details. */
|
|
134
|
+
trace: MergeTrace;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Manifest embedded in audit export files.
|
|
138
|
+
*/
|
|
139
|
+
interface AuditExportManifest {
|
|
140
|
+
/** Audit export format version */
|
|
141
|
+
version: 1;
|
|
142
|
+
/** When the export was created (epoch ms) */
|
|
143
|
+
exportedAt: number;
|
|
144
|
+
/** Node ID of the originating device */
|
|
145
|
+
nodeId: string;
|
|
146
|
+
/** Schema version at export time */
|
|
147
|
+
schemaVersion: number;
|
|
148
|
+
/** Number of operations included */
|
|
149
|
+
operationCount: number;
|
|
150
|
+
/** Number of merge traces included */
|
|
151
|
+
mergeTraceCount: number;
|
|
152
|
+
/** SHA-256 hex checksum of content sections */
|
|
153
|
+
checksum: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Decoded audit export payload.
|
|
157
|
+
*/
|
|
158
|
+
interface AuditExportPayload {
|
|
159
|
+
manifest: AuditExportManifest;
|
|
160
|
+
operations: Operation[];
|
|
161
|
+
mergeTraces: PersistedAuditTrace[];
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Progress reported during audit export.
|
|
165
|
+
*/
|
|
166
|
+
interface AuditExportProgress {
|
|
167
|
+
phase: 'reading' | 'writing' | 'verifying';
|
|
168
|
+
/** 0-1 progress ratio */
|
|
169
|
+
progress: number;
|
|
170
|
+
message: string;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Options for {@link exportAudit}.
|
|
174
|
+
*/
|
|
175
|
+
interface AuditExportOptions {
|
|
176
|
+
/** Subset of collections for operations and traces. All if omitted. */
|
|
177
|
+
collections?: string[];
|
|
178
|
+
/** Include only traces recorded at or after this timestamp (epoch ms). */
|
|
179
|
+
since?: number;
|
|
180
|
+
/** Include only traces recorded at or before this timestamp (epoch ms). */
|
|
181
|
+
until?: number;
|
|
182
|
+
/** Progress callback */
|
|
183
|
+
onProgress?: (progress: AuditExportProgress) => void;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Query filters for reading persisted audit traces.
|
|
187
|
+
*/
|
|
188
|
+
interface AuditTraceQuery {
|
|
189
|
+
collections?: string[];
|
|
190
|
+
since?: number;
|
|
191
|
+
until?: number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Manifest embedded in every backup file.
|
|
196
|
+
*/
|
|
197
|
+
interface BackupManifest {
|
|
198
|
+
/** Backup format version */
|
|
199
|
+
version: 1;
|
|
200
|
+
/** When the backup was created (epoch ms) */
|
|
201
|
+
createdAt: number;
|
|
202
|
+
/** Node ID of the originating device */
|
|
203
|
+
nodeId: string;
|
|
204
|
+
/** Schema version at backup time */
|
|
205
|
+
schemaVersion: number;
|
|
206
|
+
/** Total number of operations in the backup */
|
|
207
|
+
operationCount: number;
|
|
208
|
+
/** Collection names included in the backup */
|
|
209
|
+
collections: string[];
|
|
210
|
+
/** Whether materialized records are included */
|
|
211
|
+
includesRecords: boolean;
|
|
212
|
+
/** SHA-256 hex checksum of all content sections */
|
|
213
|
+
checksum: string;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Progress reported during backup/restore operations.
|
|
217
|
+
*/
|
|
218
|
+
interface BackupProgress {
|
|
219
|
+
phase: 'reading' | 'writing' | 'verifying' | 'restoring';
|
|
220
|
+
/** 0-1 progress ratio */
|
|
221
|
+
progress: number;
|
|
222
|
+
message: string;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Result of a restore operation.
|
|
226
|
+
*/
|
|
227
|
+
interface RestoreResult {
|
|
228
|
+
/** Number of operations restored */
|
|
229
|
+
operationsRestored: number;
|
|
230
|
+
/** Number of records restored */
|
|
231
|
+
recordsRestored: number;
|
|
232
|
+
/** Whether the restore completed successfully */
|
|
233
|
+
success: boolean;
|
|
234
|
+
/** Error message if failed */
|
|
235
|
+
error?: string;
|
|
236
|
+
/** Duration in ms */
|
|
237
|
+
duration: number;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Options for exporting a backup.
|
|
241
|
+
*/
|
|
242
|
+
interface BackupOptions {
|
|
243
|
+
/** Include materialized record snapshots (default: true) */
|
|
244
|
+
includeRecords?: boolean;
|
|
245
|
+
/** Subset of collections to backup. All if omitted. */
|
|
246
|
+
collections?: string[];
|
|
247
|
+
/** Progress callback */
|
|
248
|
+
onProgress?: (progress: BackupProgress) => void;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Options for restoring from a backup.
|
|
252
|
+
*/
|
|
253
|
+
interface RestoreOptions {
|
|
254
|
+
/** Subset of collections to restore. All if omitted. */
|
|
255
|
+
collections?: string[];
|
|
256
|
+
/** Progress callback */
|
|
257
|
+
onProgress?: (progress: BackupProgress) => void;
|
|
258
|
+
/**
|
|
259
|
+
* If true, merge operations with existing data (replay through applyRemoteOperation).
|
|
260
|
+
* If false, clear and replace all data (default: false).
|
|
261
|
+
*/
|
|
262
|
+
merge?: boolean;
|
|
263
|
+
}
|
|
264
|
+
|
|
48
265
|
/**
|
|
49
266
|
* Configuration options for the SubscriptionManager.
|
|
50
267
|
*/
|
|
@@ -66,6 +283,8 @@ interface SubscriptionManagerOptions {
|
|
|
66
283
|
* @default 0.01
|
|
67
284
|
*/
|
|
68
285
|
bloomFalsePositiveRate?: number;
|
|
286
|
+
/** Called when a query subscription is registered (e.g. to register sync query subsets). */
|
|
287
|
+
onQuerySubscribed?: (descriptor: QueryDescriptor) => () => void;
|
|
69
288
|
}
|
|
70
289
|
/**
|
|
71
290
|
* Performance statistics for monitoring subscription checking efficiency.
|
|
@@ -106,6 +325,7 @@ declare class SubscriptionManager {
|
|
|
106
325
|
private subscriptions;
|
|
107
326
|
private pendingCollections;
|
|
108
327
|
private flushScheduled;
|
|
328
|
+
private readonly onQuerySubscribed?;
|
|
109
329
|
private bloomFilter;
|
|
110
330
|
private bloomDirty;
|
|
111
331
|
private readonly bloomThreshold;
|
|
@@ -179,8 +399,9 @@ declare class SubscriptionManager {
|
|
|
179
399
|
private rebuildBloomFilter;
|
|
180
400
|
private scheduleFlush;
|
|
181
401
|
/**
|
|
182
|
-
* Compare two result sets. Uses
|
|
183
|
-
*
|
|
402
|
+
* Compare two result sets. Uses ID-based comparison first (same length, same IDs),
|
|
403
|
+
* then deep comparison of remaining fields when IDs match.
|
|
404
|
+
* Avoids JSON.stringify which is O(n) and fragile to field ordering differences.
|
|
184
405
|
*/
|
|
185
406
|
private resultsEqual;
|
|
186
407
|
}
|
|
@@ -334,6 +555,20 @@ declare class SequenceManager {
|
|
|
334
555
|
}): Promise<void>;
|
|
335
556
|
}
|
|
336
557
|
|
|
558
|
+
/**
|
|
559
|
+
* Allocates monotonic sequence numbers for a single open transaction.
|
|
560
|
+
* Loads the current DB watermark once, then increments in memory until commit.
|
|
561
|
+
*/
|
|
562
|
+
declare class TransactionSequenceAllocator {
|
|
563
|
+
private readonly adapter;
|
|
564
|
+
private readonly nodeId;
|
|
565
|
+
private loaded;
|
|
566
|
+
private watermark;
|
|
567
|
+
constructor(adapter: StorageAdapter, nodeId: string);
|
|
568
|
+
allocate(): Promise<number>;
|
|
569
|
+
getHighWaterMark(): number;
|
|
570
|
+
}
|
|
571
|
+
|
|
337
572
|
/**
|
|
338
573
|
* Internal configuration for creating a TransactionContext.
|
|
339
574
|
* Passed from Store to avoid exposing Store internals publicly.
|
|
@@ -343,7 +578,10 @@ interface TransactionContextConfig {
|
|
|
343
578
|
adapter: StorageAdapter;
|
|
344
579
|
clock: HybridLogicalClock;
|
|
345
580
|
nodeId: string;
|
|
346
|
-
|
|
581
|
+
sequenceAllocator: TransactionSequenceAllocator;
|
|
582
|
+
relationEnforcer: RelationEnforcer | null;
|
|
583
|
+
causalTracker: CausalTracker | null;
|
|
584
|
+
localMutationHandler: LocalMutationHandler | null;
|
|
347
585
|
}
|
|
348
586
|
/**
|
|
349
587
|
* A collection accessor within a transaction.
|
|
@@ -447,7 +685,12 @@ declare class Store implements OperationLog {
|
|
|
447
685
|
private readonly schema;
|
|
448
686
|
private readonly adapter;
|
|
449
687
|
private readonly configNodeId;
|
|
688
|
+
private readonly dbName;
|
|
689
|
+
private readonly isolation;
|
|
450
690
|
private readonly emitter;
|
|
691
|
+
private localMutationHandler;
|
|
692
|
+
private relationEnforcer;
|
|
693
|
+
private causalTracker;
|
|
451
694
|
constructor(config: StoreConfig);
|
|
452
695
|
/**
|
|
453
696
|
* Open the store: initialize the database, load or generate a node ID,
|
|
@@ -477,20 +720,101 @@ declare class Store implements OperationLog {
|
|
|
477
720
|
* Checks for duplicates, applies to the data table, persists the operation,
|
|
478
721
|
* and updates the version vector.
|
|
479
722
|
*/
|
|
480
|
-
applyRemoteOperation(op: Operation): Promise<ApplyResult>;
|
|
723
|
+
applyRemoteOperation(op: Operation, options?: ApplyRemoteOptions): Promise<ApplyResult>;
|
|
481
724
|
/**
|
|
482
725
|
* Get operations from a node within a sequence number range.
|
|
483
726
|
* Implements the OperationLog interface for computeDelta.
|
|
484
727
|
*/
|
|
485
|
-
getRange(nodeId: string, fromSeq: number, toSeq: number): Operation[]
|
|
728
|
+
getRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]>;
|
|
486
729
|
/**
|
|
487
|
-
*
|
|
730
|
+
* Get operations from a node within a sequence number range.
|
|
488
731
|
*/
|
|
489
732
|
getOperationRange(nodeId: string, fromSeq: number, toSeq: number): Promise<Operation[]>;
|
|
733
|
+
/**
|
|
734
|
+
* Load every operation from the local append-only log across all collections.
|
|
735
|
+
* Used by sync delta computation, backup export, and time-travel replay.
|
|
736
|
+
*/
|
|
737
|
+
getAllOperations(): Promise<Operation[]>;
|
|
738
|
+
/**
|
|
739
|
+
* Rebuild an in-memory snapshot of materialized state at a causal cut in the op log.
|
|
740
|
+
* Does not mutate the live store — intended for DevTools time-travel inspection.
|
|
741
|
+
*
|
|
742
|
+
* @param operationId - Content-addressed id of the operation to replay through (inclusive)
|
|
743
|
+
* @throws {OperationError} When the operation id is not present in the local log
|
|
744
|
+
*/
|
|
745
|
+
replayTo(operationId: string): Promise<ReplaySnapshot>;
|
|
746
|
+
/**
|
|
747
|
+
* Persist a merge trace to the durable audit log.
|
|
748
|
+
*/
|
|
749
|
+
appendAuditTrace(trace: PersistedAuditTrace): Promise<void>;
|
|
750
|
+
/**
|
|
751
|
+
* Read persisted audit traces with optional filters.
|
|
752
|
+
*/
|
|
753
|
+
getAuditTraces(query?: AuditTraceQuery): Promise<PersistedAuditTrace[]>;
|
|
754
|
+
/**
|
|
755
|
+
* Export operations and merge traces as a portable audit bundle.
|
|
756
|
+
*/
|
|
757
|
+
exportAudit(options?: AuditExportOptions): Promise<Uint8Array>;
|
|
490
758
|
/**
|
|
491
759
|
* Get the schema definition.
|
|
492
760
|
*/
|
|
493
761
|
getSchema(): SchemaDefinition;
|
|
762
|
+
/**
|
|
763
|
+
* Route local CRUD through the unified apply pipeline (korajs ApplyPipeline).
|
|
764
|
+
*/
|
|
765
|
+
setLocalMutationHandler(handler: LocalMutationHandler | null): void;
|
|
766
|
+
/**
|
|
767
|
+
* Build mutation context for a collection (used by ApplyPipeline side effects).
|
|
768
|
+
*/
|
|
769
|
+
createMutationContext(collection: string, options?: {
|
|
770
|
+
inTransaction?: boolean;
|
|
771
|
+
extraCausalDeps?: string[];
|
|
772
|
+
}): LocalMutationContext;
|
|
773
|
+
/**
|
|
774
|
+
* Load a materialized row by ID, including soft-deleted tombstones.
|
|
775
|
+
*/
|
|
776
|
+
findMaterializedRow(collection: string, recordId: string): Promise<MaterializedRowSnapshot | null>;
|
|
777
|
+
/**
|
|
778
|
+
* Latest operation from this device for a record (used for delete-vs-update merge on sync).
|
|
779
|
+
*/
|
|
780
|
+
/**
|
|
781
|
+
* Load the last server version vector acknowledged by this client (persisted in `_kora_meta`).
|
|
782
|
+
*/
|
|
783
|
+
loadLastAckedServerVector(): Promise<VersionVector>;
|
|
784
|
+
/**
|
|
785
|
+
* Persist the last server version vector this client believes the server has applied.
|
|
786
|
+
*/
|
|
787
|
+
saveLastAckedServerVector(vector: VersionVector): Promise<void>;
|
|
788
|
+
/**
|
|
789
|
+
* Load persisted delta cursor for resuming paginated initial sync.
|
|
790
|
+
*/
|
|
791
|
+
loadDeltaCursor(): Promise<string | null>;
|
|
792
|
+
/**
|
|
793
|
+
* Persist or clear the delta cursor for paginated initial sync resume.
|
|
794
|
+
*/
|
|
795
|
+
saveDeltaCursor(cursor: string | null): Promise<void>;
|
|
796
|
+
/**
|
|
797
|
+
* Local operations not yet reflected on the server version vector.
|
|
798
|
+
*/
|
|
799
|
+
getUnsyncedOperations(serverVector: VersionVector): Promise<Operation[]>;
|
|
800
|
+
/**
|
|
801
|
+
* Count of local operations ahead of the server version vector.
|
|
802
|
+
*/
|
|
803
|
+
countUnsyncedOperations(serverVector: VersionVector): Promise<number>;
|
|
804
|
+
/**
|
|
805
|
+
* Compact the local operation log using materialized rows as the baseline.
|
|
806
|
+
* Only removes ops the server has acknowledged (per {@link CompactionStrategy}).
|
|
807
|
+
*/
|
|
808
|
+
compact(strategy: CompactionStrategy): Promise<CompactionResult>;
|
|
809
|
+
/**
|
|
810
|
+
* Merge session remote vector with persisted last-acked vector (max per node).
|
|
811
|
+
*/
|
|
812
|
+
mergeServerVectors(sessionVector: VersionVector, persistedVector: VersionVector): VersionVector;
|
|
813
|
+
getLatestLocalOperationForRecord(collection: string, recordId: string): Promise<Operation | null>;
|
|
814
|
+
/**
|
|
815
|
+
* Latest operation for a record from any node (for 3-way merge when local op log is empty).
|
|
816
|
+
*/
|
|
817
|
+
getLatestOperationForRecord(collection: string, recordId: string): Promise<Operation | null>;
|
|
494
818
|
/** Expose the subscription manager for direct access (e.g., by QueryBuilder) */
|
|
495
819
|
getSubscriptionManager(): SubscriptionManager;
|
|
496
820
|
/**
|
|
@@ -517,7 +841,31 @@ declare class Store implements OperationLog {
|
|
|
517
841
|
* @returns The operations that were committed
|
|
518
842
|
*/
|
|
519
843
|
transaction(fn: (tx: TransactionContext) => Promise<void>): Promise<Operation[]>;
|
|
520
|
-
|
|
844
|
+
/**
|
|
845
|
+
* Export all data as a portable backup binary.
|
|
846
|
+
* Includes operations, version vector, metadata, and optionally materialized records.
|
|
847
|
+
*
|
|
848
|
+
* @param options - Backup options (includeRecords, collections, onProgress)
|
|
849
|
+
* @returns Backup as a Uint8Array
|
|
850
|
+
*/
|
|
851
|
+
exportBackup(options?: BackupOptions): Promise<Uint8Array>;
|
|
852
|
+
/**
|
|
853
|
+
* Restore data from a backup binary.
|
|
854
|
+
*
|
|
855
|
+
* @param data - The backup data
|
|
856
|
+
* @param options - Restore options (merge, collections, onProgress)
|
|
857
|
+
* @returns Result of the restore operation
|
|
858
|
+
*/
|
|
859
|
+
importBackup(data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult>;
|
|
860
|
+
/**
|
|
861
|
+
* Read backup manifest without loading the entire backup.
|
|
862
|
+
*
|
|
863
|
+
* @param data - The raw backup data
|
|
864
|
+
* @returns The backup manifest
|
|
865
|
+
*/
|
|
866
|
+
static readBackupManifest(data: Uint8Array): BackupManifest;
|
|
867
|
+
private recordOperationSequence;
|
|
868
|
+
private allocateSequenceNumber;
|
|
521
869
|
/**
|
|
522
870
|
* Check the stored schema version and run any pending migrations.
|
|
523
871
|
* Migrations are applied in version order within a transaction.
|
|
@@ -638,182 +986,6 @@ declare class SubscriptionBloomFilter {
|
|
|
638
986
|
private getPositions;
|
|
639
987
|
}
|
|
640
988
|
|
|
641
|
-
/**
|
|
642
|
-
* A resolved relation reference: describes a relation that points TO a given collection.
|
|
643
|
-
* When a record in `targetCollection` is deleted, we must handle records in
|
|
644
|
-
* `sourceCollection` that reference it via `foreignKeyField`.
|
|
645
|
-
*/
|
|
646
|
-
interface IncomingRelation {
|
|
647
|
-
/** Name of the relation in the schema */
|
|
648
|
-
relationName: string;
|
|
649
|
-
/** Collection that holds the foreign key (the "from" side) */
|
|
650
|
-
sourceCollection: string;
|
|
651
|
-
/** Field in the source collection that references the target */
|
|
652
|
-
foreignKeyField: string;
|
|
653
|
-
/** What to do when the referenced record is deleted */
|
|
654
|
-
onDelete: OnDeleteAction;
|
|
655
|
-
/** The full relation definition */
|
|
656
|
-
relation: RelationDefinition;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
/**
|
|
660
|
-
* Configuration for the RelationEnforcer.
|
|
661
|
-
*/
|
|
662
|
-
interface RelationEnforcerConfig {
|
|
663
|
-
schema: SchemaDefinition;
|
|
664
|
-
adapter: StorageAdapter;
|
|
665
|
-
clock: HybridLogicalClock;
|
|
666
|
-
nodeId: string;
|
|
667
|
-
getSequenceNumber: () => number;
|
|
668
|
-
}
|
|
669
|
-
/**
|
|
670
|
-
* Result of enforcing referential integrity on a delete operation.
|
|
671
|
-
* Contains all additional operations that were created as side effects
|
|
672
|
-
* (cascaded deletes and set-null updates).
|
|
673
|
-
*/
|
|
674
|
-
interface EnforcementResult {
|
|
675
|
-
/** Additional operations created by cascading deletes and set-null updates */
|
|
676
|
-
operations: Operation[];
|
|
677
|
-
}
|
|
678
|
-
/**
|
|
679
|
-
* Enforces referential integrity constraints during local delete operations.
|
|
680
|
-
*
|
|
681
|
-
* When a record is deleted, this enforcer checks all relations that reference
|
|
682
|
-
* the deleted record's collection and applies the appropriate onDelete policy:
|
|
683
|
-
*
|
|
684
|
-
* - **cascade**: Recursively deletes all referencing records
|
|
685
|
-
* - **set-null**: Sets the foreign key to null on all referencing records
|
|
686
|
-
* - **restrict**: Throws a ReferentialIntegrityError if any references exist
|
|
687
|
-
* - **no-action**: Does nothing (the foreign key is left dangling)
|
|
688
|
-
*
|
|
689
|
-
* The enforcer operates within a provided transaction to ensure atomicity.
|
|
690
|
-
* All generated operations (cascaded deletes, set-null updates) share a
|
|
691
|
-
* causal dependency chain through the original delete operation.
|
|
692
|
-
*
|
|
693
|
-
* @example
|
|
694
|
-
* ```typescript
|
|
695
|
-
* const enforcer = new RelationEnforcer({
|
|
696
|
-
* schema, adapter, clock, nodeId,
|
|
697
|
-
* getSequenceNumber: () => ++seq,
|
|
698
|
-
* })
|
|
699
|
-
* const result = await enforcer.enforceDelete(
|
|
700
|
-
* 'projects', 'proj-1', tx, ['delete-op-id']
|
|
701
|
-
* )
|
|
702
|
-
* // result.operations contains any cascaded delete/update ops
|
|
703
|
-
* ```
|
|
704
|
-
*/
|
|
705
|
-
declare class RelationEnforcer {
|
|
706
|
-
private readonly lookup;
|
|
707
|
-
private readonly schema;
|
|
708
|
-
private readonly adapter;
|
|
709
|
-
private readonly clock;
|
|
710
|
-
private readonly nodeId;
|
|
711
|
-
private readonly getSequenceNumber;
|
|
712
|
-
constructor(config: RelationEnforcerConfig);
|
|
713
|
-
/**
|
|
714
|
-
* Enforce referential integrity after deleting a record.
|
|
715
|
-
*
|
|
716
|
-
* Must be called within a transaction. The transaction handle is used
|
|
717
|
-
* for all cascaded writes to ensure atomicity.
|
|
718
|
-
*
|
|
719
|
-
* @param collection - The collection the deleted record belongs to
|
|
720
|
-
* @param recordId - The ID of the deleted record
|
|
721
|
-
* @param tx - The active transaction handle
|
|
722
|
-
* @param causalDeps - Causal dependencies for generated operations
|
|
723
|
-
* @returns All additional operations created as side effects
|
|
724
|
-
* @throws {ReferentialIntegrityError} If a 'restrict' policy is violated
|
|
725
|
-
*/
|
|
726
|
-
enforceDelete(collection: string, recordId: string, tx: Transaction, causalDeps: string[]): Promise<EnforcementResult>;
|
|
727
|
-
/**
|
|
728
|
-
* Enforce a single relation's onDelete policy.
|
|
729
|
-
*/
|
|
730
|
-
private enforceRelation;
|
|
731
|
-
/**
|
|
732
|
-
* Cascade: delete all records in the source collection that reference
|
|
733
|
-
* the deleted record, then recursively cascade those deletes.
|
|
734
|
-
*/
|
|
735
|
-
private enforceCascade;
|
|
736
|
-
/**
|
|
737
|
-
* Set-null: update all referencing records to set the foreign key to null.
|
|
738
|
-
*/
|
|
739
|
-
private enforceSetNull;
|
|
740
|
-
/**
|
|
741
|
-
* Restrict: refuse the delete if any referencing records exist.
|
|
742
|
-
*/
|
|
743
|
-
private enforceRestrict;
|
|
744
|
-
/**
|
|
745
|
-
* Get the relation lookup map for external use (e.g., by the merge engine).
|
|
746
|
-
*/
|
|
747
|
-
getRelationLookup(): Map<string, IncomingRelation[]>;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
/**
|
|
751
|
-
* Callback invoked after a mutation so the Store can notify subscriptions.
|
|
752
|
-
*/
|
|
753
|
-
type MutationCallback = (collection: string, operation: Operation) => void;
|
|
754
|
-
/**
|
|
755
|
-
* Collection provides CRUD operations on a single schema collection.
|
|
756
|
-
* Each mutation creates an Operation and persists both the data and the operation atomically.
|
|
757
|
-
*
|
|
758
|
-
* When a RelationEnforcer is provided, delete operations enforce referential integrity
|
|
759
|
-
* policies (cascade, set-null, restrict) defined in the schema's relations.
|
|
760
|
-
*/
|
|
761
|
-
declare class Collection {
|
|
762
|
-
private readonly name;
|
|
763
|
-
private readonly definition;
|
|
764
|
-
private readonly schema;
|
|
765
|
-
private readonly adapter;
|
|
766
|
-
private readonly clock;
|
|
767
|
-
private readonly nodeId;
|
|
768
|
-
private readonly getSequenceNumber;
|
|
769
|
-
private readonly onMutation;
|
|
770
|
-
private readonly relationEnforcer;
|
|
771
|
-
constructor(name: string, definition: CollectionDefinition, schema: SchemaDefinition, adapter: StorageAdapter, clock: HybridLogicalClock, nodeId: string, getSequenceNumber: () => number, onMutation: MutationCallback, relationEnforcer?: RelationEnforcer);
|
|
772
|
-
/**
|
|
773
|
-
* Insert a new record into the collection.
|
|
774
|
-
* Generates a UUID v7 for the id, validates data, and persists atomically.
|
|
775
|
-
*
|
|
776
|
-
* @param data - The record data (auto fields and defaults are applied automatically)
|
|
777
|
-
* @returns The inserted record with id, createdAt, updatedAt
|
|
778
|
-
*/
|
|
779
|
-
insert(data: Record<string, unknown>): Promise<CollectionRecord>;
|
|
780
|
-
/**
|
|
781
|
-
* Find a record by its ID. Returns null if not found or soft-deleted.
|
|
782
|
-
*/
|
|
783
|
-
findById(id: string): Promise<CollectionRecord | null>;
|
|
784
|
-
/**
|
|
785
|
-
* Update an existing record. Only the provided fields are changed.
|
|
786
|
-
*
|
|
787
|
-
* @param id - The record ID to update
|
|
788
|
-
* @param data - Partial data with only the fields to change
|
|
789
|
-
* @returns The updated record
|
|
790
|
-
* @throws {RecordNotFoundError} If the record doesn't exist or is deleted
|
|
791
|
-
*/
|
|
792
|
-
update(id: string, data: Record<string, unknown>): Promise<CollectionRecord>;
|
|
793
|
-
/**
|
|
794
|
-
* Soft-delete a record by its ID.
|
|
795
|
-
*
|
|
796
|
-
* When a RelationEnforcer is configured, referential integrity policies
|
|
797
|
-
* are enforced within the same transaction:
|
|
798
|
-
* - **cascade**: Recursively deletes all referencing records
|
|
799
|
-
* - **set-null**: Sets foreign keys to null on referencing records
|
|
800
|
-
* - **restrict**: Throws ReferentialIntegrityError if references exist
|
|
801
|
-
* - **no-action**: Does nothing (dangling references are left)
|
|
802
|
-
*
|
|
803
|
-
* All cascaded operations are created atomically within the same transaction
|
|
804
|
-
* and share causal dependencies with the original delete.
|
|
805
|
-
*
|
|
806
|
-
* @param id - The record ID to delete
|
|
807
|
-
* @throws {RecordNotFoundError} If the record doesn't exist or is already deleted
|
|
808
|
-
* @throws {ReferentialIntegrityError} If a 'restrict' policy is violated
|
|
809
|
-
*/
|
|
810
|
-
delete(id: string): Promise<void>;
|
|
811
|
-
/** Get the collection name */
|
|
812
|
-
getName(): string;
|
|
813
|
-
/** Get the collection definition */
|
|
814
|
-
getDefinition(): CollectionDefinition;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
989
|
/**
|
|
818
990
|
* Error thrown when a local mutation attempts an invalid state transition.
|
|
819
991
|
*
|
|
@@ -881,6 +1053,11 @@ declare function decodeRichtext(value: unknown): Uint8Array | null;
|
|
|
881
1053
|
* Reads plain text from a richtext Yjs state update.
|
|
882
1054
|
*/
|
|
883
1055
|
declare function richtextToPlainText(value: RichtextInput): string;
|
|
1056
|
+
/**
|
|
1057
|
+
* Compares two richtext values by decoded plain text.
|
|
1058
|
+
* Yjs update bytes are not stable across separate encodes of the same string.
|
|
1059
|
+
*/
|
|
1060
|
+
declare function richtextStatesEqual(a: unknown, b: unknown): boolean;
|
|
884
1061
|
|
|
885
1062
|
/**
|
|
886
1063
|
* Minimal pluralization/singularization utilities for relation name resolution.
|
|
@@ -909,4 +1086,63 @@ declare function pluralize(word: string): string;
|
|
|
909
1086
|
*/
|
|
910
1087
|
declare function singularize(word: string): string;
|
|
911
1088
|
|
|
912
|
-
|
|
1089
|
+
/**
|
|
1090
|
+
* Export a backup from a store.
|
|
1091
|
+
*
|
|
1092
|
+
* Reads all data via the adapter and produces a portable binary backup.
|
|
1093
|
+
*
|
|
1094
|
+
* @param adapter - The storage adapter
|
|
1095
|
+
* @param schema - The schema definition
|
|
1096
|
+
* @param nodeId - Current node ID
|
|
1097
|
+
* @param schemaVersion - Schema version
|
|
1098
|
+
* @param options - Backup options
|
|
1099
|
+
* @returns Backup as a Uint8Array
|
|
1100
|
+
*/
|
|
1101
|
+
declare function exportBackup(adapter: StorageAdapter, schema: SchemaDefinition, nodeId: string, schemaVersion: number, options?: BackupOptions): Promise<Uint8Array>;
|
|
1102
|
+
/**
|
|
1103
|
+
* Read backup manifest without loading the entire backup.
|
|
1104
|
+
* Parses only the first section (which is always the manifest).
|
|
1105
|
+
*
|
|
1106
|
+
* @param data - The raw backup data
|
|
1107
|
+
* @returns The backup manifest
|
|
1108
|
+
*/
|
|
1109
|
+
declare function readBackupManifest(data: Uint8Array): BackupManifest;
|
|
1110
|
+
/**
|
|
1111
|
+
* Validate the backup checksum.
|
|
1112
|
+
*
|
|
1113
|
+
* @param data - The raw backup data
|
|
1114
|
+
* @returns True if the checksum is valid
|
|
1115
|
+
*/
|
|
1116
|
+
declare function verifyBackupChecksum(data: Uint8Array): Promise<boolean>;
|
|
1117
|
+
/**
|
|
1118
|
+
* Restore a backup into a store.
|
|
1119
|
+
*
|
|
1120
|
+
* @param adapter - The storage adapter
|
|
1121
|
+
* @param schema - The schema definition
|
|
1122
|
+
* @param data - The backup data
|
|
1123
|
+
* @param options - Restore options
|
|
1124
|
+
* @returns Result of the restore operation
|
|
1125
|
+
*/
|
|
1126
|
+
declare function restoreBackup(adapter: StorageAdapter, schema: SchemaDefinition, data: Uint8Array, options?: RestoreOptions): Promise<RestoreResult>;
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* Build a {@link PersistedAuditTrace} from a merge-related Kora event.
|
|
1130
|
+
*/
|
|
1131
|
+
declare function persistedAuditTraceFromEvent(event: Extract<KoraEvent, {
|
|
1132
|
+
type: 'merge:completed' | 'merge:conflict' | 'constraint:violated';
|
|
1133
|
+
}>): PersistedAuditTrace;
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* Decode an audit export binary into structured data.
|
|
1137
|
+
*/
|
|
1138
|
+
declare function decodeAuditExport(data: Uint8Array): AuditExportPayload;
|
|
1139
|
+
/**
|
|
1140
|
+
* Read only the manifest from an audit export without decoding all sections.
|
|
1141
|
+
*/
|
|
1142
|
+
declare function readAuditExportManifest(data: Uint8Array): AuditExportManifest;
|
|
1143
|
+
/**
|
|
1144
|
+
* Verify the checksum of an audit export file.
|
|
1145
|
+
*/
|
|
1146
|
+
declare function verifyAuditExportChecksum(data: Uint8Array): Promise<boolean>;
|
|
1147
|
+
|
|
1148
|
+
export { AdapterError, ApplyRemoteOptions, type AuditExportManifest, type AuditExportOptions, type AuditExportPayload, type AuditExportProgress, type AuditTraceQuery, type BackupManifest, type BackupOptions, type BackupProgress, COMPACTION_BASELINE_META_KEY, type CollectionAccessor, CollectionRecord, type CompactionResult, type CompactionStrategy, InvalidStateTransitionError, LAST_ACKED_SERVER_VECTOR_META_KEY, LocalMutationHandler, MaterializedRowSnapshot, OrderByDirection, type PersistedAuditTrace, PersistenceError, QueryBuilder, QueryDescriptor, QueryError, RecordNotFoundError, type ReplaySnapshot, type RestoreOptions, type RestoreResult, SequenceManager, StorageAdapter, Store, StoreConfig, StoreNotOpenError, SubscriptionBloomFilter, SubscriptionCallback, SubscriptionManager, type SubscriptionManagerOptions, type SubscriptionStats, type TransactionCollectionAccessor, TransactionContext, type TransactionContextConfig, WhereClause, WorkerInitError, WorkerTimeoutError, collectOperationsAheadOfServer, compactOperationLog, computeAckCompactionWatermark, decodeAuditExport, decodeRichtext, deserializeVersionVectorFromMeta, encodeRichtext, exportBackup, mergeVersionVectors, persistedAuditTraceFromEvent, pluralize, readAuditExportManifest, readBackupManifest, restoreBackup, richtextStatesEqual, richtextToPlainText, serializeVersionVectorToMeta, singularize, validateStateTransition, validateUpdateStateMachine, verifyAuditExportChecksum, verifyBackupChecksum };
|