@affectively/aeon 1.0.0 → 1.1.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.
Files changed (60) hide show
  1. package/README.md +10 -0
  2. package/dist/compression/index.cjs +580 -0
  3. package/dist/compression/index.cjs.map +1 -0
  4. package/dist/compression/index.d.cts +189 -0
  5. package/dist/compression/index.d.ts +189 -0
  6. package/dist/compression/index.js +573 -0
  7. package/dist/compression/index.js.map +1 -0
  8. package/dist/crypto/index.cjs +100 -0
  9. package/dist/crypto/index.cjs.map +1 -0
  10. package/dist/crypto/index.d.cts +407 -0
  11. package/dist/crypto/index.d.ts +407 -0
  12. package/dist/crypto/index.js +96 -0
  13. package/dist/crypto/index.js.map +1 -0
  14. package/dist/distributed/index.cjs +420 -23
  15. package/dist/distributed/index.cjs.map +1 -1
  16. package/dist/distributed/index.d.cts +901 -2
  17. package/dist/distributed/index.d.ts +901 -2
  18. package/dist/distributed/index.js +420 -23
  19. package/dist/distributed/index.js.map +1 -1
  20. package/dist/index.cjs +1071 -55
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +11 -811
  23. package/dist/index.d.ts +11 -811
  24. package/dist/index.js +1070 -56
  25. package/dist/index.js.map +1 -1
  26. package/dist/offline/index.cjs +419 -0
  27. package/dist/offline/index.cjs.map +1 -0
  28. package/dist/offline/index.d.cts +148 -0
  29. package/dist/offline/index.d.ts +148 -0
  30. package/dist/offline/index.js +415 -0
  31. package/dist/offline/index.js.map +1 -0
  32. package/dist/optimization/index.cjs +797 -0
  33. package/dist/optimization/index.cjs.map +1 -0
  34. package/dist/optimization/index.d.cts +347 -0
  35. package/dist/optimization/index.d.ts +347 -0
  36. package/dist/optimization/index.js +787 -0
  37. package/dist/optimization/index.js.map +1 -0
  38. package/dist/persistence/index.cjs +145 -0
  39. package/dist/persistence/index.cjs.map +1 -0
  40. package/dist/persistence/index.d.cts +63 -0
  41. package/dist/persistence/index.d.ts +63 -0
  42. package/dist/persistence/index.js +142 -0
  43. package/dist/persistence/index.js.map +1 -0
  44. package/dist/presence/index.cjs +338 -0
  45. package/dist/presence/index.cjs.map +1 -0
  46. package/dist/presence/index.d.cts +168 -0
  47. package/dist/presence/index.d.ts +168 -0
  48. package/dist/presence/index.js +334 -0
  49. package/dist/presence/index.js.map +1 -0
  50. package/dist/types-CMxO7QF0.d.cts +33 -0
  51. package/dist/types-CMxO7QF0.d.ts +33 -0
  52. package/dist/versioning/index.cjs +296 -14
  53. package/dist/versioning/index.cjs.map +1 -1
  54. package/dist/versioning/index.d.cts +66 -1
  55. package/dist/versioning/index.d.ts +66 -1
  56. package/dist/versioning/index.js +296 -14
  57. package/dist/versioning/index.js.map +1 -1
  58. package/package.json +51 -1
  59. package/dist/index-C_4CMV5c.d.cts +0 -1207
  60. package/dist/index-C_4CMV5c.d.ts +0 -1207
package/README.md CHANGED
@@ -22,6 +22,8 @@ In the Affectively framework, if "halos" are the users, then **Aeons are the col
22
22
  - **Conflict Resolution** - Multiple strategies for resolving divergent state
23
23
  - **Real-time Presence** - Track node health and status in real-time
24
24
 
25
+ Roadmap vision: see [ROADMAP.md](./ROADMAP.md).
26
+
25
27
  ## Installation
26
28
 
27
29
  ```bash
@@ -179,6 +181,14 @@ Shared types and utilities used across all modules.
179
181
  import type { Operation, VectorClock, PresenceInfo } from '@affectively/aeon/core';
180
182
  ```
181
183
 
184
+ ### Persistence (`@affectively/aeon/persistence`)
185
+
186
+ Optional persistence boundaries and adapters for durable Aeon state.
187
+
188
+ - `StorageAdapter` - runtime-agnostic adapter contract
189
+ - `InMemoryStorageAdapter` - reference adapter for tests/dev
190
+ - `DashStorageAdapter` - local-first adapter with optional debounced sync batching for D1/R2-backed resilience
191
+
182
192
  ### Offline (`@affectively/aeon/offline`)
183
193
 
184
194
  Offline-first operation management.
@@ -0,0 +1,580 @@
1
+ 'use strict';
2
+
3
+ // src/utils/logger.ts
4
+ var consoleLogger = {
5
+ debug: (...args) => {
6
+ console.debug("[AEON:DEBUG]", ...args);
7
+ },
8
+ info: (...args) => {
9
+ console.info("[AEON:INFO]", ...args);
10
+ },
11
+ warn: (...args) => {
12
+ console.warn("[AEON:WARN]", ...args);
13
+ },
14
+ error: (...args) => {
15
+ console.error("[AEON:ERROR]", ...args);
16
+ }
17
+ };
18
+ var currentLogger = consoleLogger;
19
+ function getLogger() {
20
+ return currentLogger;
21
+ }
22
+
23
+ // src/compression/CompressionEngine.ts
24
+ var logger = getLogger();
25
+ var CompressionEngine = class {
26
+ stats = {
27
+ totalCompressed: 0,
28
+ totalDecompressed: 0,
29
+ totalOriginalBytes: 0,
30
+ totalCompressedBytes: 0,
31
+ averageCompressionRatio: 0,
32
+ compressionTimeMs: 0,
33
+ decompressionTimeMs: 0
34
+ };
35
+ preferredAlgorithm = "gzip";
36
+ constructor(preferredAlgorithm = "gzip") {
37
+ this.preferredAlgorithm = preferredAlgorithm;
38
+ logger.debug("[CompressionEngine] Initialized", {
39
+ algorithm: preferredAlgorithm,
40
+ supportsNative: this.supportsNativeCompression()
41
+ });
42
+ }
43
+ /**
44
+ * Check if native compression is available
45
+ */
46
+ supportsNativeCompression() {
47
+ return typeof CompressionStream !== "undefined" && typeof DecompressionStream !== "undefined";
48
+ }
49
+ /**
50
+ * Compress data
51
+ */
52
+ async compress(data) {
53
+ const startTime = performance.now();
54
+ const inputData = typeof data === "string" ? new TextEncoder().encode(data) : data;
55
+ const originalSize = inputData.byteLength;
56
+ let compressed;
57
+ let algorithm = this.preferredAlgorithm;
58
+ if (this.supportsNativeCompression()) {
59
+ try {
60
+ compressed = await this.compressNative(
61
+ inputData,
62
+ this.preferredAlgorithm
63
+ );
64
+ } catch (error) {
65
+ logger.warn(
66
+ "[CompressionEngine] Native compression failed, using fallback",
67
+ error
68
+ );
69
+ compressed = inputData;
70
+ algorithm = "none";
71
+ }
72
+ } else {
73
+ compressed = inputData;
74
+ algorithm = "none";
75
+ }
76
+ const compressionRatio = originalSize > 0 ? 1 - compressed.byteLength / originalSize : 0;
77
+ const batch = {
78
+ id: `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`,
79
+ compressed,
80
+ originalSize,
81
+ compressedSize: compressed.byteLength,
82
+ compressionRatio,
83
+ algorithm,
84
+ timestamp: Date.now()
85
+ };
86
+ const elapsed = performance.now() - startTime;
87
+ this.stats.totalCompressed++;
88
+ this.stats.totalOriginalBytes += originalSize;
89
+ this.stats.totalCompressedBytes += compressed.byteLength;
90
+ this.stats.compressionTimeMs += elapsed;
91
+ this.updateAverageRatio();
92
+ logger.debug("[CompressionEngine] Compressed", {
93
+ original: originalSize,
94
+ compressed: compressed.byteLength,
95
+ ratio: (compressionRatio * 100).toFixed(1) + "%",
96
+ algorithm,
97
+ timeMs: elapsed.toFixed(2)
98
+ });
99
+ return batch;
100
+ }
101
+ /**
102
+ * Decompress data
103
+ */
104
+ async decompress(batch) {
105
+ const startTime = performance.now();
106
+ let decompressed;
107
+ if (batch.algorithm === "none") {
108
+ decompressed = batch.compressed;
109
+ } else if (this.supportsNativeCompression()) {
110
+ try {
111
+ decompressed = await this.decompressNative(
112
+ batch.compressed,
113
+ batch.algorithm
114
+ );
115
+ } catch (error) {
116
+ logger.warn("[CompressionEngine] Native decompression failed", error);
117
+ throw error;
118
+ }
119
+ } else {
120
+ throw new Error("Native decompression not available");
121
+ }
122
+ const elapsed = performance.now() - startTime;
123
+ this.stats.totalDecompressed++;
124
+ this.stats.decompressionTimeMs += elapsed;
125
+ logger.debug("[CompressionEngine] Decompressed", {
126
+ compressed: batch.compressedSize,
127
+ decompressed: decompressed.byteLength,
128
+ algorithm: batch.algorithm,
129
+ timeMs: elapsed.toFixed(2)
130
+ });
131
+ return decompressed;
132
+ }
133
+ /**
134
+ * Compress using native CompressionStream
135
+ */
136
+ async compressNative(data, algorithm) {
137
+ const stream = new CompressionStream(algorithm);
138
+ const writer = stream.writable.getWriter();
139
+ const reader = stream.readable.getReader();
140
+ writer.write(
141
+ new Uint8Array(
142
+ data.buffer,
143
+ data.byteOffset,
144
+ data.byteLength
145
+ )
146
+ );
147
+ writer.close();
148
+ const chunks = [];
149
+ let done = false;
150
+ while (!done) {
151
+ const result = await reader.read();
152
+ done = result.done;
153
+ if (result.value) {
154
+ chunks.push(result.value);
155
+ }
156
+ }
157
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
158
+ const combined = new Uint8Array(totalLength);
159
+ let offset = 0;
160
+ for (const chunk of chunks) {
161
+ combined.set(chunk, offset);
162
+ offset += chunk.length;
163
+ }
164
+ return combined;
165
+ }
166
+ /**
167
+ * Decompress using native DecompressionStream
168
+ */
169
+ async decompressNative(data, algorithm) {
170
+ const stream = new DecompressionStream(algorithm);
171
+ const writer = stream.writable.getWriter();
172
+ const reader = stream.readable.getReader();
173
+ writer.write(
174
+ new Uint8Array(
175
+ data.buffer,
176
+ data.byteOffset,
177
+ data.byteLength
178
+ )
179
+ );
180
+ writer.close();
181
+ const chunks = [];
182
+ let done = false;
183
+ while (!done) {
184
+ const result = await reader.read();
185
+ done = result.done;
186
+ if (result.value) {
187
+ chunks.push(result.value);
188
+ }
189
+ }
190
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
191
+ const combined = new Uint8Array(totalLength);
192
+ let offset = 0;
193
+ for (const chunk of chunks) {
194
+ combined.set(chunk, offset);
195
+ offset += chunk.length;
196
+ }
197
+ return combined;
198
+ }
199
+ /**
200
+ * Split compressed batch into chunks for transmission
201
+ */
202
+ splitIntoChunks(batch, chunkSize = 64 * 1024) {
203
+ const chunks = [];
204
+ const data = batch.compressed;
205
+ const total = Math.ceil(data.byteLength / chunkSize);
206
+ for (let i = 0; i < total; i++) {
207
+ const start = i * chunkSize;
208
+ const end = Math.min(start + chunkSize, data.byteLength);
209
+ const chunkData = data.slice(start, end);
210
+ chunks.push({
211
+ chunkId: `${batch.id}-chunk-${i}`,
212
+ batchId: batch.id,
213
+ data: chunkData,
214
+ index: i,
215
+ total,
216
+ checksum: this.simpleChecksum(chunkData)
217
+ });
218
+ }
219
+ return chunks;
220
+ }
221
+ /**
222
+ * Reassemble chunks into compressed batch
223
+ */
224
+ reassembleChunks(chunks) {
225
+ const sorted = [...chunks].sort((a, b) => a.index - b.index);
226
+ const total = sorted[0]?.total ?? 0;
227
+ if (sorted.length !== total) {
228
+ throw new Error(
229
+ `Missing chunks: got ${sorted.length}, expected ${total}`
230
+ );
231
+ }
232
+ const totalLength = sorted.reduce(
233
+ (sum, chunk) => sum + chunk.data.length,
234
+ 0
235
+ );
236
+ const combined = new Uint8Array(totalLength);
237
+ let offset = 0;
238
+ for (const chunk of sorted) {
239
+ combined.set(chunk.data, offset);
240
+ offset += chunk.data.length;
241
+ }
242
+ return combined;
243
+ }
244
+ /**
245
+ * Simple checksum for chunk verification
246
+ */
247
+ simpleChecksum(data) {
248
+ let hash = 0;
249
+ for (let i = 0; i < data.length; i++) {
250
+ hash = (hash << 5) - hash + data[i] | 0;
251
+ }
252
+ return hash.toString(16);
253
+ }
254
+ /**
255
+ * Update average compression ratio
256
+ */
257
+ updateAverageRatio() {
258
+ if (this.stats.totalOriginalBytes > 0) {
259
+ this.stats.averageCompressionRatio = 1 - this.stats.totalCompressedBytes / this.stats.totalOriginalBytes;
260
+ }
261
+ }
262
+ /**
263
+ * Get statistics
264
+ */
265
+ getStats() {
266
+ return { ...this.stats };
267
+ }
268
+ /**
269
+ * Reset statistics
270
+ */
271
+ resetStats() {
272
+ this.stats = {
273
+ totalCompressed: 0,
274
+ totalDecompressed: 0,
275
+ totalOriginalBytes: 0,
276
+ totalCompressedBytes: 0,
277
+ averageCompressionRatio: 0,
278
+ compressionTimeMs: 0,
279
+ decompressionTimeMs: 0
280
+ };
281
+ }
282
+ };
283
+ var compressionEngineInstance = null;
284
+ function getCompressionEngine() {
285
+ if (!compressionEngineInstance) {
286
+ compressionEngineInstance = new CompressionEngine();
287
+ }
288
+ return compressionEngineInstance;
289
+ }
290
+ function resetCompressionEngine() {
291
+ compressionEngineInstance = null;
292
+ }
293
+
294
+ // src/compression/DeltaSyncOptimizer.ts
295
+ var logger2 = getLogger();
296
+ var DeltaSyncOptimizer = class {
297
+ operationHistory = /* @__PURE__ */ new Map();
298
+ stats = {
299
+ totalOperations: 0,
300
+ totalFull: 0,
301
+ totalDelta: 0,
302
+ totalOriginalSize: 0,
303
+ totalDeltaSize: 0,
304
+ averageReductionPercent: 0,
305
+ lastSyncTime: 0,
306
+ fullOperationThreshold: 1e3
307
+ // Force full if delta > 1KB
308
+ };
309
+ constructor(fullOperationThreshold = 1e3) {
310
+ this.stats.fullOperationThreshold = fullOperationThreshold;
311
+ logger2.debug("[DeltaSyncOptimizer] Initialized", {
312
+ threshold: fullOperationThreshold
313
+ });
314
+ }
315
+ /**
316
+ * Compute delta for single operation
317
+ */
318
+ computeDelta(operation) {
319
+ const operationJson = JSON.stringify(operation);
320
+ const originalSize = new TextEncoder().encode(operationJson).byteLength;
321
+ const previous = this.operationHistory.get(operation.id);
322
+ if (!previous) {
323
+ const delta = {
324
+ id: `delta-${Date.now()}-${Math.random().toString(36).slice(2)}`,
325
+ type: "full",
326
+ operationId: operation.id,
327
+ operationType: operation.type,
328
+ sessionId: operation.sessionId,
329
+ timestamp: Date.now(),
330
+ fullData: operation.data,
331
+ priority: operation.priority
332
+ };
333
+ this.stats.totalOperations++;
334
+ this.stats.totalFull++;
335
+ this.stats.totalOriginalSize += originalSize;
336
+ const deltaSize2 = new TextEncoder().encode(
337
+ JSON.stringify(delta)
338
+ ).byteLength;
339
+ this.stats.totalDeltaSize += deltaSize2;
340
+ this.operationHistory.set(operation.id, operation);
341
+ return delta;
342
+ }
343
+ const changes = {};
344
+ const changeMask = [];
345
+ let hasMeaningfulChanges = false;
346
+ for (const [key, value] of Object.entries(operation.data)) {
347
+ const oldValue = previous.data[key];
348
+ if (!this.deepEqual(value, oldValue)) {
349
+ changes[key] = value;
350
+ changeMask.push(key);
351
+ hasMeaningfulChanges = true;
352
+ }
353
+ }
354
+ for (const key of Object.keys(previous.data)) {
355
+ if (!(key in operation.data)) {
356
+ changes[key] = null;
357
+ changeMask.push(`${key}:deleted`);
358
+ hasMeaningfulChanges = true;
359
+ }
360
+ }
361
+ const deltaData = {
362
+ id: `delta-${Date.now()}-${Math.random().toString(36).slice(2)}`,
363
+ type: "delta",
364
+ operationId: operation.id,
365
+ operationType: operation.type,
366
+ sessionId: operation.sessionId,
367
+ timestamp: Date.now(),
368
+ changes: hasMeaningfulChanges ? changes : void 0,
369
+ changeMask: hasMeaningfulChanges ? changeMask : void 0,
370
+ priority: operation.priority
371
+ };
372
+ const deltaSize = new TextEncoder().encode(
373
+ JSON.stringify(deltaData)
374
+ ).byteLength;
375
+ const finalDelta = deltaSize > this.stats.fullOperationThreshold ? {
376
+ ...deltaData,
377
+ type: "full",
378
+ fullData: operation.data,
379
+ changes: void 0,
380
+ changeMask: void 0
381
+ } : deltaData;
382
+ this.stats.totalOperations++;
383
+ if (finalDelta.type === "full") {
384
+ this.stats.totalFull++;
385
+ } else {
386
+ this.stats.totalDelta++;
387
+ }
388
+ this.stats.totalOriginalSize += originalSize;
389
+ this.stats.totalDeltaSize += deltaSize;
390
+ this.operationHistory.set(operation.id, operation);
391
+ return finalDelta;
392
+ }
393
+ /**
394
+ * Compute deltas for batch of operations
395
+ */
396
+ computeBatchDeltas(operations) {
397
+ const deltas = operations.map((op) => this.computeDelta(op));
398
+ const totalOriginalSize = operations.reduce(
399
+ (sum, op) => sum + new TextEncoder().encode(JSON.stringify(op)).byteLength,
400
+ 0
401
+ );
402
+ const totalDeltaSize = deltas.reduce(
403
+ (sum, delta) => sum + new TextEncoder().encode(JSON.stringify(delta)).byteLength,
404
+ 0
405
+ );
406
+ const reductionPercent = totalOriginalSize > 0 ? Math.round(
407
+ (totalOriginalSize - totalDeltaSize) / totalOriginalSize * 100
408
+ ) : 0;
409
+ const batch = {
410
+ batchId: `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`,
411
+ operations: deltas,
412
+ timestamp: Date.now(),
413
+ totalOriginalSize,
414
+ totalDeltaSize,
415
+ reductionPercent
416
+ };
417
+ logger2.debug("[DeltaSyncOptimizer] Batch computed", {
418
+ operations: operations.length,
419
+ reduction: reductionPercent,
420
+ size: totalDeltaSize
421
+ });
422
+ return batch;
423
+ }
424
+ /**
425
+ * Decompress delta operation back to full operation
426
+ */
427
+ decompressDelta(delta) {
428
+ if (delta.type === "full") {
429
+ return {
430
+ id: delta.operationId,
431
+ type: delta.operationType,
432
+ sessionId: delta.sessionId,
433
+ data: delta.fullData || {},
434
+ status: "pending",
435
+ createdAt: delta.timestamp
436
+ };
437
+ }
438
+ const previous = this.operationHistory.get(delta.operationId);
439
+ if (!previous) {
440
+ logger2.warn("[DeltaSyncOptimizer] Cannot decompress - no history", {
441
+ operationId: delta.operationId
442
+ });
443
+ return {
444
+ id: delta.operationId,
445
+ type: delta.operationType,
446
+ sessionId: delta.sessionId,
447
+ data: delta.changes || {},
448
+ status: "pending",
449
+ createdAt: delta.timestamp
450
+ };
451
+ }
452
+ const reconstructed = {
453
+ ...previous,
454
+ data: {
455
+ ...previous.data,
456
+ ...delta.changes || {}
457
+ }
458
+ };
459
+ if (delta.changes) {
460
+ for (const [key, value] of Object.entries(delta.changes)) {
461
+ if (value === null) {
462
+ delete reconstructed.data[key];
463
+ }
464
+ }
465
+ }
466
+ return reconstructed;
467
+ }
468
+ /**
469
+ * Update history after successful sync
470
+ */
471
+ updateHistory(operations) {
472
+ for (const op of operations) {
473
+ this.operationHistory.set(op.id, op);
474
+ }
475
+ logger2.debug("[DeltaSyncOptimizer] History updated", {
476
+ count: operations.length,
477
+ totalHistorySize: this.operationHistory.size
478
+ });
479
+ }
480
+ /**
481
+ * Clear history for specific operations
482
+ */
483
+ clearHistory(operationIds) {
484
+ for (const id of operationIds) {
485
+ this.operationHistory.delete(id);
486
+ }
487
+ logger2.debug("[DeltaSyncOptimizer] History cleared", {
488
+ cleared: operationIds.length,
489
+ remaining: this.operationHistory.size
490
+ });
491
+ }
492
+ /**
493
+ * Get current performance statistics
494
+ */
495
+ getStats() {
496
+ if (this.stats.totalOperations > 0) {
497
+ this.stats.averageReductionPercent = Math.round(
498
+ (this.stats.totalOriginalSize - this.stats.totalDeltaSize) / this.stats.totalOriginalSize * 100
499
+ );
500
+ }
501
+ return { ...this.stats };
502
+ }
503
+ /**
504
+ * Reset statistics
505
+ */
506
+ resetStats() {
507
+ this.stats = {
508
+ totalOperations: 0,
509
+ totalFull: 0,
510
+ totalDelta: 0,
511
+ totalOriginalSize: 0,
512
+ totalDeltaSize: 0,
513
+ averageReductionPercent: 0,
514
+ lastSyncTime: 0,
515
+ fullOperationThreshold: this.stats.fullOperationThreshold
516
+ };
517
+ logger2.debug("[DeltaSyncOptimizer] Stats reset");
518
+ }
519
+ /**
520
+ * Set the full operation threshold
521
+ */
522
+ setFullOperationThreshold(bytes) {
523
+ this.stats.fullOperationThreshold = bytes;
524
+ logger2.debug("[DeltaSyncOptimizer] Threshold updated", { bytes });
525
+ }
526
+ /**
527
+ * Get history size for memory monitoring
528
+ */
529
+ getHistorySize() {
530
+ return this.operationHistory.size;
531
+ }
532
+ /**
533
+ * Get memory footprint estimate
534
+ */
535
+ getMemoryEstimate() {
536
+ let totalBytes = 0;
537
+ for (const op of this.operationHistory.values()) {
538
+ totalBytes += new TextEncoder().encode(JSON.stringify(op)).byteLength;
539
+ }
540
+ return totalBytes;
541
+ }
542
+ /**
543
+ * Deep equality check for nested objects
544
+ */
545
+ deepEqual(a, b) {
546
+ if (a === b) return true;
547
+ if (a == null || b == null) return false;
548
+ if (typeof a !== "object" || typeof b !== "object") return false;
549
+ const aObj = a;
550
+ const bObj = b;
551
+ const aKeys = Object.keys(aObj);
552
+ const bKeys = Object.keys(bObj);
553
+ if (aKeys.length !== bKeys.length) return false;
554
+ for (const key of aKeys) {
555
+ if (!this.deepEqual(aObj[key], bObj[key])) {
556
+ return false;
557
+ }
558
+ }
559
+ return true;
560
+ }
561
+ };
562
+ var deltaSyncInstance = null;
563
+ function getDeltaSyncOptimizer(threshold) {
564
+ if (!deltaSyncInstance) {
565
+ deltaSyncInstance = new DeltaSyncOptimizer(threshold);
566
+ }
567
+ return deltaSyncInstance;
568
+ }
569
+ function resetDeltaSyncOptimizer() {
570
+ deltaSyncInstance = null;
571
+ }
572
+
573
+ exports.CompressionEngine = CompressionEngine;
574
+ exports.DeltaSyncOptimizer = DeltaSyncOptimizer;
575
+ exports.getCompressionEngine = getCompressionEngine;
576
+ exports.getDeltaSyncOptimizer = getDeltaSyncOptimizer;
577
+ exports.resetCompressionEngine = resetCompressionEngine;
578
+ exports.resetDeltaSyncOptimizer = resetDeltaSyncOptimizer;
579
+ //# sourceMappingURL=index.cjs.map
580
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/logger.ts","../../src/compression/CompressionEngine.ts","../../src/compression/DeltaSyncOptimizer.ts"],"names":["logger","deltaSize"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Aeon Logger Interface\n *\n * Provides a pluggable logging interface that can be configured\n * by consumers to integrate with their preferred logging solution.\n */\n\n/**\n * Logger interface that consumers can implement\n */\nexport interface Logger {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\n/**\n * Default console logger implementation\n */\nconst consoleLogger: Logger = {\n debug: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.debug('[AEON:DEBUG]', ...args);\n },\n info: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.info('[AEON:INFO]', ...args);\n },\n warn: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.warn('[AEON:WARN]', ...args);\n },\n error: (...args: unknown[]) => {\n // eslint-disable-next-line no-console\n console.error('[AEON:ERROR]', ...args);\n },\n};\n\n/**\n * No-op logger for production or when logging is disabled\n */\nconst noopLogger: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/**\n * Current logger instance\n */\nlet currentLogger: Logger = consoleLogger;\n\n/**\n * Get the current logger instance\n */\nexport function getLogger(): Logger {\n return currentLogger;\n}\n\n/**\n * Set a custom logger implementation\n */\nexport function setLogger(logger: Logger): void {\n currentLogger = logger;\n}\n\n/**\n * Reset to the default console logger\n */\nexport function resetLogger(): void {\n currentLogger = consoleLogger;\n}\n\n/**\n * Disable all logging\n */\nexport function disableLogging(): void {\n currentLogger = noopLogger;\n}\n\n/**\n * Create a namespaced logger\n */\nexport function createNamespacedLogger(namespace: string): Logger {\n const logger = getLogger();\n return {\n debug: (...args: unknown[]) => logger.debug(`[${namespace}]`, ...args),\n info: (...args: unknown[]) => logger.info(`[${namespace}]`, ...args),\n warn: (...args: unknown[]) => logger.warn(`[${namespace}]`, ...args),\n error: (...args: unknown[]) => logger.error(`[${namespace}]`, ...args),\n };\n}\n\n// Export default logger for convenience\nexport const logger: Logger = {\n debug: (...args: unknown[]) => getLogger().debug(...args),\n info: (...args: unknown[]) => getLogger().info(...args),\n warn: (...args: unknown[]) => getLogger().warn(...args),\n error: (...args: unknown[]) => getLogger().error(...args),\n};\n","/**\n * Compression Engine (Phase 12)\n *\n * Provides compression for delta operations using native CompressionStream API.\n * Falls back gracefully when native compression is unavailable.\n */\n\nimport { getLogger } from '../utils/logger';\n\nconst logger = getLogger();\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CompressedBatch {\n id: string;\n compressed: Uint8Array;\n originalSize: number;\n compressedSize: number;\n compressionRatio: number;\n algorithm: 'gzip' | 'deflate' | 'none';\n timestamp: number;\n}\n\nexport interface CompressedChunk {\n chunkId: string;\n batchId: string;\n data: Uint8Array;\n index: number;\n total: number;\n checksum: string;\n}\n\nexport interface CompressionStats {\n totalCompressed: number;\n totalDecompressed: number;\n totalOriginalBytes: number;\n totalCompressedBytes: number;\n averageCompressionRatio: number;\n compressionTimeMs: number;\n decompressionTimeMs: number;\n}\n\n// ============================================================================\n// Compression Engine\n// ============================================================================\n\nexport class CompressionEngine {\n private stats: CompressionStats = {\n totalCompressed: 0,\n totalDecompressed: 0,\n totalOriginalBytes: 0,\n totalCompressedBytes: 0,\n averageCompressionRatio: 0,\n compressionTimeMs: 0,\n decompressionTimeMs: 0,\n };\n private preferredAlgorithm: 'gzip' | 'deflate' = 'gzip';\n\n constructor(preferredAlgorithm: 'gzip' | 'deflate' = 'gzip') {\n this.preferredAlgorithm = preferredAlgorithm;\n logger.debug('[CompressionEngine] Initialized', {\n algorithm: preferredAlgorithm,\n supportsNative: this.supportsNativeCompression(),\n });\n }\n\n /**\n * Check if native compression is available\n */\n supportsNativeCompression(): boolean {\n return (\n typeof CompressionStream !== 'undefined' &&\n typeof DecompressionStream !== 'undefined'\n );\n }\n\n /**\n * Compress data\n */\n async compress(data: Uint8Array | string): Promise<CompressedBatch> {\n const startTime = performance.now();\n\n const inputData =\n typeof data === 'string' ? new TextEncoder().encode(data) : data;\n const originalSize = inputData.byteLength;\n\n let compressed: Uint8Array;\n let algorithm: 'gzip' | 'deflate' | 'none' = this.preferredAlgorithm;\n\n if (this.supportsNativeCompression()) {\n try {\n compressed = await this.compressNative(\n inputData,\n this.preferredAlgorithm,\n );\n } catch (error) {\n logger.warn(\n '[CompressionEngine] Native compression failed, using fallback',\n error,\n );\n compressed = inputData;\n algorithm = 'none';\n }\n } else {\n // No native compression - return uncompressed\n compressed = inputData;\n algorithm = 'none';\n }\n\n const compressionRatio =\n originalSize > 0 ? 1 - compressed.byteLength / originalSize : 0;\n\n const batch: CompressedBatch = {\n id: `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n compressed,\n originalSize,\n compressedSize: compressed.byteLength,\n compressionRatio,\n algorithm,\n timestamp: Date.now(),\n };\n\n // Update stats\n const elapsed = performance.now() - startTime;\n this.stats.totalCompressed++;\n this.stats.totalOriginalBytes += originalSize;\n this.stats.totalCompressedBytes += compressed.byteLength;\n this.stats.compressionTimeMs += elapsed;\n this.updateAverageRatio();\n\n logger.debug('[CompressionEngine] Compressed', {\n original: originalSize,\n compressed: compressed.byteLength,\n ratio: (compressionRatio * 100).toFixed(1) + '%',\n algorithm,\n timeMs: elapsed.toFixed(2),\n });\n\n return batch;\n }\n\n /**\n * Decompress data\n */\n async decompress(batch: CompressedBatch): Promise<Uint8Array> {\n const startTime = performance.now();\n\n let decompressed: Uint8Array;\n\n if (batch.algorithm === 'none') {\n decompressed = batch.compressed;\n } else if (this.supportsNativeCompression()) {\n try {\n decompressed = await this.decompressNative(\n batch.compressed,\n batch.algorithm,\n );\n } catch (error) {\n logger.warn('[CompressionEngine] Native decompression failed', error);\n throw error;\n }\n } else {\n throw new Error('Native decompression not available');\n }\n\n // Update stats\n const elapsed = performance.now() - startTime;\n this.stats.totalDecompressed++;\n this.stats.decompressionTimeMs += elapsed;\n\n logger.debug('[CompressionEngine] Decompressed', {\n compressed: batch.compressedSize,\n decompressed: decompressed.byteLength,\n algorithm: batch.algorithm,\n timeMs: elapsed.toFixed(2),\n });\n\n return decompressed;\n }\n\n /**\n * Compress using native CompressionStream\n */\n private async compressNative(\n data: Uint8Array,\n algorithm: 'gzip' | 'deflate',\n ): Promise<Uint8Array> {\n const stream = new CompressionStream(algorithm);\n const writer = stream.writable.getWriter();\n const reader = stream.readable.getReader();\n\n writer.write(\n new Uint8Array(\n data.buffer,\n data.byteOffset,\n data.byteLength,\n ) as BufferSource,\n );\n writer.close();\n\n const chunks: Uint8Array[] = [];\n let done = false;\n\n while (!done) {\n const result = await reader.read();\n done = result.done;\n if (result.value) {\n chunks.push(result.value);\n }\n }\n\n // Combine chunks\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n\n return combined;\n }\n\n /**\n * Decompress using native DecompressionStream\n */\n private async decompressNative(\n data: Uint8Array,\n algorithm: 'gzip' | 'deflate',\n ): Promise<Uint8Array> {\n const stream = new DecompressionStream(algorithm);\n const writer = stream.writable.getWriter();\n const reader = stream.readable.getReader();\n\n writer.write(\n new Uint8Array(\n data.buffer,\n data.byteOffset,\n data.byteLength,\n ) as BufferSource,\n );\n writer.close();\n\n const chunks: Uint8Array[] = [];\n let done = false;\n\n while (!done) {\n const result = await reader.read();\n done = result.done;\n if (result.value) {\n chunks.push(result.value);\n }\n }\n\n // Combine chunks\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n\n return combined;\n }\n\n /**\n * Split compressed batch into chunks for transmission\n */\n splitIntoChunks(\n batch: CompressedBatch,\n chunkSize = 64 * 1024,\n ): CompressedChunk[] {\n const chunks: CompressedChunk[] = [];\n const data = batch.compressed;\n const total = Math.ceil(data.byteLength / chunkSize);\n\n for (let i = 0; i < total; i++) {\n const start = i * chunkSize;\n const end = Math.min(start + chunkSize, data.byteLength);\n const chunkData = data.slice(start, end);\n\n chunks.push({\n chunkId: `${batch.id}-chunk-${i}`,\n batchId: batch.id,\n data: chunkData,\n index: i,\n total,\n checksum: this.simpleChecksum(chunkData),\n });\n }\n\n return chunks;\n }\n\n /**\n * Reassemble chunks into compressed batch\n */\n reassembleChunks(chunks: CompressedChunk[]): Uint8Array {\n // Sort by index\n const sorted = [...chunks].sort((a, b) => a.index - b.index);\n\n // Verify all chunks present\n const total = sorted[0]?.total ?? 0;\n if (sorted.length !== total) {\n throw new Error(\n `Missing chunks: got ${sorted.length}, expected ${total}`,\n );\n }\n\n // Combine\n const totalLength = sorted.reduce(\n (sum, chunk) => sum + chunk.data.length,\n 0,\n );\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n\n for (const chunk of sorted) {\n combined.set(chunk.data, offset);\n offset += chunk.data.length;\n }\n\n return combined;\n }\n\n /**\n * Simple checksum for chunk verification\n */\n private simpleChecksum(data: Uint8Array): string {\n let hash = 0;\n for (let i = 0; i < data.length; i++) {\n hash = ((hash << 5) - hash + data[i]) | 0;\n }\n return hash.toString(16);\n }\n\n /**\n * Update average compression ratio\n */\n private updateAverageRatio(): void {\n if (this.stats.totalOriginalBytes > 0) {\n this.stats.averageCompressionRatio =\n 1 - this.stats.totalCompressedBytes / this.stats.totalOriginalBytes;\n }\n }\n\n /**\n * Get statistics\n */\n getStats(): CompressionStats {\n return { ...this.stats };\n }\n\n /**\n * Reset statistics\n */\n resetStats(): void {\n this.stats = {\n totalCompressed: 0,\n totalDecompressed: 0,\n totalOriginalBytes: 0,\n totalCompressedBytes: 0,\n averageCompressionRatio: 0,\n compressionTimeMs: 0,\n decompressionTimeMs: 0,\n };\n }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet compressionEngineInstance: CompressionEngine | null = null;\n\nexport function getCompressionEngine(): CompressionEngine {\n if (!compressionEngineInstance) {\n compressionEngineInstance = new CompressionEngine();\n }\n return compressionEngineInstance;\n}\n\nexport function resetCompressionEngine(): void {\n compressionEngineInstance = null;\n}\n","/**\n * Delta Sync Optimizer (Phase 12)\n *\n * Implements field-level change detection to reduce payload size.\n * Computes delta between current and previous operation state.\n *\n * Performance Impact:\n * - Delta sync alone: 70-80% payload reduction\n * - Combined with compression: 80-90% total reduction\n */\n\nimport { getLogger } from '../utils/logger';\nimport type { Operation } from '../core/types';\n\nconst logger = getLogger();\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Delta operation - represents only changed fields\n */\nexport interface DeltaOperation {\n id: string;\n type: 'full' | 'delta';\n operationId: string;\n operationType: Operation['type'];\n sessionId: string;\n timestamp: number;\n changes?: Record<string, unknown>; // Only for delta type\n changeMask?: string[]; // Field names that changed\n fullData?: Record<string, unknown>; // Only for full type (new records)\n priority?: 'high' | 'normal' | 'low';\n}\n\n/**\n * Batch of delta operations\n */\nexport interface DeltaBatch {\n batchId: string;\n operations: DeltaOperation[];\n timestamp: number;\n totalOriginalSize: number;\n totalDeltaSize: number;\n reductionPercent: number;\n}\n\n/**\n * Statistics about delta sync performance\n */\nexport interface DeltaStats {\n totalOperations: number;\n totalFull: number;\n totalDelta: number;\n totalOriginalSize: number;\n totalDeltaSize: number;\n averageReductionPercent: number;\n lastSyncTime: number;\n fullOperationThreshold: number;\n}\n\n// ============================================================================\n// Delta Sync Optimizer\n// ============================================================================\n\nexport class DeltaSyncOptimizer {\n private operationHistory: Map<string, Operation> = new Map();\n private stats: DeltaStats = {\n totalOperations: 0,\n totalFull: 0,\n totalDelta: 0,\n totalOriginalSize: 0,\n totalDeltaSize: 0,\n averageReductionPercent: 0,\n lastSyncTime: 0,\n fullOperationThreshold: 1000, // Force full if delta > 1KB\n };\n\n constructor(fullOperationThreshold = 1000) {\n this.stats.fullOperationThreshold = fullOperationThreshold;\n logger.debug('[DeltaSyncOptimizer] Initialized', {\n threshold: fullOperationThreshold,\n });\n }\n\n /**\n * Compute delta for single operation\n */\n computeDelta(operation: Operation): DeltaOperation {\n const operationJson = JSON.stringify(operation);\n const originalSize = new TextEncoder().encode(operationJson).byteLength;\n\n // Check if we have historical state\n const previous = this.operationHistory.get(operation.id);\n\n if (!previous) {\n // New operation - return as full\n const delta: DeltaOperation = {\n id: `delta-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n type: 'full',\n operationId: operation.id,\n operationType: operation.type,\n sessionId: operation.sessionId,\n timestamp: Date.now(),\n fullData: operation.data,\n priority: operation.priority,\n };\n\n // Update stats\n this.stats.totalOperations++;\n this.stats.totalFull++;\n this.stats.totalOriginalSize += originalSize;\n\n const deltaSize = new TextEncoder().encode(\n JSON.stringify(delta),\n ).byteLength;\n this.stats.totalDeltaSize += deltaSize;\n\n // Store in history\n this.operationHistory.set(operation.id, operation);\n\n return delta;\n }\n\n // Compare with previous - extract changed fields\n const changes: Record<string, unknown> = {};\n const changeMask: string[] = [];\n let hasMeaningfulChanges = false;\n\n for (const [key, value] of Object.entries(operation.data)) {\n const oldValue = previous.data[key];\n\n if (!this.deepEqual(value, oldValue)) {\n changes[key] = value;\n changeMask.push(key);\n hasMeaningfulChanges = true;\n }\n }\n\n // Check for deleted fields\n for (const key of Object.keys(previous.data)) {\n if (!(key in operation.data)) {\n changes[key] = null;\n changeMask.push(`${key}:deleted`);\n hasMeaningfulChanges = true;\n }\n }\n\n // Build delta operation\n const deltaData: DeltaOperation = {\n id: `delta-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n type: 'delta',\n operationId: operation.id,\n operationType: operation.type,\n sessionId: operation.sessionId,\n timestamp: Date.now(),\n changes: hasMeaningfulChanges ? changes : undefined,\n changeMask: hasMeaningfulChanges ? changeMask : undefined,\n priority: operation.priority,\n };\n\n // If delta is too large, send as full instead\n const deltaSize = new TextEncoder().encode(\n JSON.stringify(deltaData),\n ).byteLength;\n\n const finalDelta =\n deltaSize > this.stats.fullOperationThreshold\n ? {\n ...deltaData,\n type: 'full' as const,\n fullData: operation.data,\n changes: undefined,\n changeMask: undefined,\n }\n : deltaData;\n\n // Update stats\n this.stats.totalOperations++;\n if (finalDelta.type === 'full') {\n this.stats.totalFull++;\n } else {\n this.stats.totalDelta++;\n }\n\n this.stats.totalOriginalSize += originalSize;\n this.stats.totalDeltaSize += deltaSize;\n\n // Update history\n this.operationHistory.set(operation.id, operation);\n\n return finalDelta;\n }\n\n /**\n * Compute deltas for batch of operations\n */\n computeBatchDeltas(operations: Operation[]): DeltaBatch {\n const deltas = operations.map((op) => this.computeDelta(op));\n\n const totalOriginalSize = operations.reduce(\n (sum, op) =>\n sum + new TextEncoder().encode(JSON.stringify(op)).byteLength,\n 0,\n );\n\n const totalDeltaSize = deltas.reduce(\n (sum, delta) =>\n sum + new TextEncoder().encode(JSON.stringify(delta)).byteLength,\n 0,\n );\n\n const reductionPercent =\n totalOriginalSize > 0\n ? Math.round(\n ((totalOriginalSize - totalDeltaSize) / totalOriginalSize) * 100,\n )\n : 0;\n\n const batch: DeltaBatch = {\n batchId: `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n operations: deltas,\n timestamp: Date.now(),\n totalOriginalSize,\n totalDeltaSize,\n reductionPercent,\n };\n\n logger.debug('[DeltaSyncOptimizer] Batch computed', {\n operations: operations.length,\n reduction: reductionPercent,\n size: totalDeltaSize,\n });\n\n return batch;\n }\n\n /**\n * Decompress delta operation back to full operation\n */\n decompressDelta(delta: DeltaOperation): Operation {\n if (delta.type === 'full') {\n return {\n id: delta.operationId,\n type: delta.operationType,\n sessionId: delta.sessionId,\n data: delta.fullData || {},\n status: 'pending',\n createdAt: delta.timestamp,\n };\n }\n\n const previous = this.operationHistory.get(delta.operationId);\n\n if (!previous) {\n logger.warn('[DeltaSyncOptimizer] Cannot decompress - no history', {\n operationId: delta.operationId,\n });\n\n return {\n id: delta.operationId,\n type: delta.operationType,\n sessionId: delta.sessionId,\n data: delta.changes || {},\n status: 'pending',\n createdAt: delta.timestamp,\n };\n }\n\n // Apply changes to historical state\n const reconstructed = {\n ...previous,\n data: {\n ...previous.data,\n ...(delta.changes || {}),\n },\n };\n\n // Remove null fields (marked as deleted)\n if (delta.changes) {\n for (const [key, value] of Object.entries(delta.changes)) {\n if (value === null) {\n delete reconstructed.data[key];\n }\n }\n }\n\n return reconstructed;\n }\n\n /**\n * Update history after successful sync\n */\n updateHistory(operations: Operation[]): void {\n for (const op of operations) {\n this.operationHistory.set(op.id, op);\n }\n\n logger.debug('[DeltaSyncOptimizer] History updated', {\n count: operations.length,\n totalHistorySize: this.operationHistory.size,\n });\n }\n\n /**\n * Clear history for specific operations\n */\n clearHistory(operationIds: string[]): void {\n for (const id of operationIds) {\n this.operationHistory.delete(id);\n }\n\n logger.debug('[DeltaSyncOptimizer] History cleared', {\n cleared: operationIds.length,\n remaining: this.operationHistory.size,\n });\n }\n\n /**\n * Get current performance statistics\n */\n getStats(): DeltaStats {\n if (this.stats.totalOperations > 0) {\n this.stats.averageReductionPercent = Math.round(\n ((this.stats.totalOriginalSize - this.stats.totalDeltaSize) /\n this.stats.totalOriginalSize) *\n 100,\n );\n }\n\n return { ...this.stats };\n }\n\n /**\n * Reset statistics\n */\n resetStats(): void {\n this.stats = {\n totalOperations: 0,\n totalFull: 0,\n totalDelta: 0,\n totalOriginalSize: 0,\n totalDeltaSize: 0,\n averageReductionPercent: 0,\n lastSyncTime: 0,\n fullOperationThreshold: this.stats.fullOperationThreshold,\n };\n\n logger.debug('[DeltaSyncOptimizer] Stats reset');\n }\n\n /**\n * Set the full operation threshold\n */\n setFullOperationThreshold(bytes: number): void {\n this.stats.fullOperationThreshold = bytes;\n logger.debug('[DeltaSyncOptimizer] Threshold updated', { bytes });\n }\n\n /**\n * Get history size for memory monitoring\n */\n getHistorySize(): number {\n return this.operationHistory.size;\n }\n\n /**\n * Get memory footprint estimate\n */\n getMemoryEstimate(): number {\n let totalBytes = 0;\n\n for (const op of this.operationHistory.values()) {\n totalBytes += new TextEncoder().encode(JSON.stringify(op)).byteLength;\n }\n\n return totalBytes;\n }\n\n /**\n * Deep equality check for nested objects\n */\n private deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a == null || b == null) return false;\n if (typeof a !== 'object' || typeof b !== 'object') return false;\n\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n\n if (aKeys.length !== bKeys.length) return false;\n\n for (const key of aKeys) {\n if (!this.deepEqual(aObj[key], bObj[key])) {\n return false;\n }\n }\n\n return true;\n }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet deltaSyncInstance: DeltaSyncOptimizer | null = null;\n\nexport function getDeltaSyncOptimizer(threshold?: number): DeltaSyncOptimizer {\n if (!deltaSyncInstance) {\n deltaSyncInstance = new DeltaSyncOptimizer(threshold);\n }\n return deltaSyncInstance;\n}\n\nexport function resetDeltaSyncOptimizer(): void {\n deltaSyncInstance = null;\n}\n"]}