@affectively/aeon 1.0.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/index.cjs ADDED
@@ -0,0 +1,4671 @@
1
+ 'use strict';
2
+
3
+ var eventemitter3 = require('eventemitter3');
4
+
5
+ // src/utils/logger.ts
6
+ var consoleLogger = {
7
+ debug: (...args) => {
8
+ console.debug("[AEON:DEBUG]", ...args);
9
+ },
10
+ info: (...args) => {
11
+ console.info("[AEON:INFO]", ...args);
12
+ },
13
+ warn: (...args) => {
14
+ console.warn("[AEON:WARN]", ...args);
15
+ },
16
+ error: (...args) => {
17
+ console.error("[AEON:ERROR]", ...args);
18
+ }
19
+ };
20
+ var noopLogger = {
21
+ debug: () => {
22
+ },
23
+ info: () => {
24
+ },
25
+ warn: () => {
26
+ },
27
+ error: () => {
28
+ }
29
+ };
30
+ var currentLogger = consoleLogger;
31
+ function getLogger() {
32
+ return currentLogger;
33
+ }
34
+ function setLogger(logger9) {
35
+ currentLogger = logger9;
36
+ }
37
+ function resetLogger() {
38
+ currentLogger = consoleLogger;
39
+ }
40
+ function disableLogging() {
41
+ currentLogger = noopLogger;
42
+ }
43
+ function createNamespacedLogger(namespace) {
44
+ const logger9 = getLogger();
45
+ return {
46
+ debug: (...args) => logger9.debug(`[${namespace}]`, ...args),
47
+ info: (...args) => logger9.info(`[${namespace}]`, ...args),
48
+ warn: (...args) => logger9.warn(`[${namespace}]`, ...args),
49
+ error: (...args) => logger9.error(`[${namespace}]`, ...args)
50
+ };
51
+ }
52
+ var logger = {
53
+ debug: (...args) => getLogger().debug(...args),
54
+ info: (...args) => getLogger().info(...args),
55
+ warn: (...args) => getLogger().warn(...args),
56
+ error: (...args) => getLogger().error(...args)
57
+ };
58
+
59
+ // src/versioning/SchemaVersionManager.ts
60
+ var SchemaVersionManager = class {
61
+ versions = /* @__PURE__ */ new Map();
62
+ versionHistory = [];
63
+ compatibilityMatrix = /* @__PURE__ */ new Map();
64
+ currentVersion = null;
65
+ constructor() {
66
+ this.initializeDefaultVersions();
67
+ }
68
+ /**
69
+ * Initialize default versions
70
+ */
71
+ initializeDefaultVersions() {
72
+ const v1_0_0 = {
73
+ major: 1,
74
+ minor: 0,
75
+ patch: 0,
76
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
77
+ description: "Initial schema version",
78
+ breaking: false
79
+ };
80
+ this.registerVersion(v1_0_0);
81
+ this.currentVersion = v1_0_0;
82
+ }
83
+ /**
84
+ * Register a new schema version
85
+ */
86
+ registerVersion(version) {
87
+ const versionString = this.versionToString(version);
88
+ this.versions.set(versionString, version);
89
+ this.versionHistory.push(version);
90
+ logger.debug("[SchemaVersionManager] Version registered", {
91
+ version: versionString,
92
+ breaking: version.breaking,
93
+ description: version.description
94
+ });
95
+ }
96
+ /**
97
+ * Get current version
98
+ */
99
+ getCurrentVersion() {
100
+ if (!this.currentVersion) {
101
+ throw new Error("No current version set");
102
+ }
103
+ return this.currentVersion;
104
+ }
105
+ /**
106
+ * Set current version
107
+ */
108
+ setCurrentVersion(version) {
109
+ if (!this.versions.has(this.versionToString(version))) {
110
+ throw new Error(`Version ${this.versionToString(version)} not registered`);
111
+ }
112
+ this.currentVersion = version;
113
+ logger.debug("[SchemaVersionManager] Current version set", {
114
+ version: this.versionToString(version)
115
+ });
116
+ }
117
+ /**
118
+ * Get version history
119
+ */
120
+ getVersionHistory() {
121
+ return [...this.versionHistory];
122
+ }
123
+ /**
124
+ * Check if version exists
125
+ */
126
+ hasVersion(version) {
127
+ return this.versions.has(this.versionToString(version));
128
+ }
129
+ /**
130
+ * Get version by string (e.g., "1.2.3")
131
+ */
132
+ getVersion(versionString) {
133
+ return this.versions.get(versionString);
134
+ }
135
+ /**
136
+ * Register compatibility rule
137
+ */
138
+ registerCompatibility(rule) {
139
+ if (!this.compatibilityMatrix.has(rule.from)) {
140
+ this.compatibilityMatrix.set(rule.from, []);
141
+ }
142
+ const rules = this.compatibilityMatrix.get(rule.from);
143
+ if (rules) {
144
+ rules.push(rule);
145
+ }
146
+ logger.debug("[SchemaVersionManager] Compatibility rule registered", {
147
+ from: rule.from,
148
+ to: rule.to,
149
+ compatible: rule.compatible,
150
+ requiresMigration: rule.requiresMigration
151
+ });
152
+ }
153
+ /**
154
+ * Check if migration path exists
155
+ */
156
+ canMigrate(fromVersion, toVersion) {
157
+ const fromStr = typeof fromVersion === "string" ? fromVersion : this.versionToString(fromVersion);
158
+ const toStr = typeof toVersion === "string" ? toVersion : this.versionToString(toVersion);
159
+ const rules = this.compatibilityMatrix.get(fromStr) || [];
160
+ return rules.some((r) => r.to === toStr && r.requiresMigration);
161
+ }
162
+ /**
163
+ * Get migration path
164
+ */
165
+ getMigrationPath(fromVersion, toVersion) {
166
+ const path = [];
167
+ let current = fromVersion;
168
+ const maxSteps = 100;
169
+ let steps = 0;
170
+ while (this.compareVersions(current, toVersion) !== 0 && steps < maxSteps) {
171
+ const fromStr = this.versionToString(current);
172
+ const rules = this.compatibilityMatrix.get(fromStr) || [];
173
+ let found = false;
174
+ for (const rule of rules) {
175
+ const nextVersion = this.getVersion(rule.to);
176
+ if (nextVersion) {
177
+ if (this.compareVersions(nextVersion, toVersion) <= 0 || this.compareVersions(current, nextVersion) < this.compareVersions(current, toVersion)) {
178
+ current = nextVersion;
179
+ path.push(current);
180
+ found = true;
181
+ break;
182
+ }
183
+ }
184
+ }
185
+ if (!found) {
186
+ break;
187
+ }
188
+ steps++;
189
+ }
190
+ return path;
191
+ }
192
+ /**
193
+ * Compare two versions
194
+ * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
195
+ */
196
+ compareVersions(v1, v2) {
197
+ const ver1 = typeof v1 === "string" ? this.parseVersion(v1) : v1;
198
+ const ver2 = typeof v2 === "string" ? this.parseVersion(v2) : v2;
199
+ if (ver1.major !== ver2.major) {
200
+ return ver1.major < ver2.major ? -1 : 1;
201
+ }
202
+ if (ver1.minor !== ver2.minor) {
203
+ return ver1.minor < ver2.minor ? -1 : 1;
204
+ }
205
+ if (ver1.patch !== ver2.patch) {
206
+ return ver1.patch < ver2.patch ? -1 : 1;
207
+ }
208
+ return 0;
209
+ }
210
+ /**
211
+ * Parse version string to SchemaVersion
212
+ */
213
+ parseVersion(versionString) {
214
+ const parts = versionString.split(".").map(Number);
215
+ return {
216
+ major: parts[0] || 0,
217
+ minor: parts[1] || 0,
218
+ patch: parts[2] || 0,
219
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
220
+ description: "",
221
+ breaking: false
222
+ };
223
+ }
224
+ /**
225
+ * Create new version
226
+ */
227
+ createVersion(major, minor, patch, description, breaking = false) {
228
+ return {
229
+ major,
230
+ minor,
231
+ patch,
232
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
233
+ description,
234
+ breaking
235
+ };
236
+ }
237
+ /**
238
+ * Convert version to string
239
+ */
240
+ versionToString(version) {
241
+ return `${version.major}.${version.minor}.${version.patch}`;
242
+ }
243
+ /**
244
+ * Get version metadata
245
+ */
246
+ getVersionMetadata(version) {
247
+ const history = this.versionHistory;
248
+ const currentIndex = history.findIndex(
249
+ (v) => this.versionToString(v) === this.versionToString(version)
250
+ );
251
+ return {
252
+ version,
253
+ previousVersion: currentIndex > 0 ? history[currentIndex - 1] : void 0,
254
+ changes: [version.description],
255
+ migrationsRequired: this.canMigrate(
256
+ this.currentVersion || version,
257
+ version
258
+ ) ? [this.versionToString(version)] : [],
259
+ rollbackPossible: currentIndex > 0
260
+ };
261
+ }
262
+ /**
263
+ * Get all registered versions
264
+ */
265
+ getAllVersions() {
266
+ return Array.from(this.versions.values()).sort(
267
+ (a, b) => this.compareVersions(a, b)
268
+ );
269
+ }
270
+ /**
271
+ * Clear all versions (for testing)
272
+ */
273
+ clear() {
274
+ this.versions.clear();
275
+ this.versionHistory = [];
276
+ this.compatibilityMatrix.clear();
277
+ this.currentVersion = null;
278
+ }
279
+ };
280
+
281
+ // src/versioning/MigrationEngine.ts
282
+ var MigrationEngine = class {
283
+ migrations = /* @__PURE__ */ new Map();
284
+ executedMigrations = [];
285
+ state = {
286
+ currentVersion: "1.0.0",
287
+ appliedMigrations: [],
288
+ failedMigrations: [],
289
+ lastMigrationTime: (/* @__PURE__ */ new Date()).toISOString(),
290
+ totalMigrationsRun: 0
291
+ };
292
+ /**
293
+ * Register a migration
294
+ */
295
+ registerMigration(migration) {
296
+ this.migrations.set(migration.id, migration);
297
+ logger.debug("[MigrationEngine] Migration registered", {
298
+ id: migration.id,
299
+ version: migration.version,
300
+ name: migration.name
301
+ });
302
+ }
303
+ /**
304
+ * Execute a migration
305
+ */
306
+ async executeMigration(migrationId, data) {
307
+ const migration = this.migrations.get(migrationId);
308
+ if (!migration) {
309
+ throw new Error(`Migration ${migrationId} not found`);
310
+ }
311
+ const startTime = Date.now();
312
+ const result = {
313
+ migrationId,
314
+ success: false,
315
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
316
+ duration: 0,
317
+ itemsAffected: 0,
318
+ errors: []
319
+ };
320
+ try {
321
+ logger.debug("[MigrationEngine] Executing migration", {
322
+ id: migrationId,
323
+ version: migration.version
324
+ });
325
+ migration.up(data);
326
+ result.success = true;
327
+ result.itemsAffected = Array.isArray(data) ? data.length : 1;
328
+ result.duration = Date.now() - startTime;
329
+ this.state.appliedMigrations.push(migrationId);
330
+ this.state.currentVersion = migration.version;
331
+ this.state.totalMigrationsRun++;
332
+ this.state.lastMigrationTime = result.timestamp;
333
+ this.executedMigrations.push(result);
334
+ logger.debug("[MigrationEngine] Migration executed successfully", {
335
+ id: migrationId,
336
+ duration: result.duration,
337
+ itemsAffected: result.itemsAffected
338
+ });
339
+ return result;
340
+ } catch (error) {
341
+ result.errors = [error instanceof Error ? error.message : String(error)];
342
+ this.state.failedMigrations.push(migrationId);
343
+ this.executedMigrations.push(result);
344
+ logger.error("[MigrationEngine] Migration failed", {
345
+ id: migrationId,
346
+ error: result.errors[0]
347
+ });
348
+ throw new Error(`Migration ${migrationId} failed: ${result.errors[0]}`);
349
+ }
350
+ }
351
+ /**
352
+ * Rollback a migration
353
+ */
354
+ async rollbackMigration(migrationId, data) {
355
+ const migration = this.migrations.get(migrationId);
356
+ if (!migration) {
357
+ throw new Error(`Migration ${migrationId} not found`);
358
+ }
359
+ if (!migration.down) {
360
+ throw new Error(`Migration ${migrationId} does not support rollback`);
361
+ }
362
+ const startTime = Date.now();
363
+ const result = {
364
+ migrationId,
365
+ success: false,
366
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
367
+ duration: 0,
368
+ itemsAffected: 0,
369
+ errors: []
370
+ };
371
+ try {
372
+ logger.debug("[MigrationEngine] Rolling back migration", {
373
+ id: migrationId,
374
+ version: migration.version
375
+ });
376
+ migration.down(data);
377
+ result.success = true;
378
+ result.itemsAffected = Array.isArray(data) ? data.length : 1;
379
+ result.duration = Date.now() - startTime;
380
+ this.state.appliedMigrations = this.state.appliedMigrations.filter(
381
+ (id) => id !== migrationId
382
+ );
383
+ this.executedMigrations.push(result);
384
+ logger.debug("[MigrationEngine] Migration rolled back", {
385
+ id: migrationId,
386
+ duration: result.duration
387
+ });
388
+ return result;
389
+ } catch (error) {
390
+ result.errors = [error instanceof Error ? error.message : String(error)];
391
+ this.executedMigrations.push(result);
392
+ logger.error("[MigrationEngine] Rollback failed", {
393
+ id: migrationId,
394
+ error: result.errors[0]
395
+ });
396
+ throw new Error(`Rollback for ${migrationId} failed: ${result.errors[0]}`);
397
+ }
398
+ }
399
+ /**
400
+ * Get migration state
401
+ */
402
+ getState() {
403
+ return { ...this.state };
404
+ }
405
+ /**
406
+ * Get migration execution history
407
+ */
408
+ getExecutionHistory() {
409
+ return [...this.executedMigrations];
410
+ }
411
+ /**
412
+ * Get migration by ID
413
+ */
414
+ getMigration(migrationId) {
415
+ return this.migrations.get(migrationId);
416
+ }
417
+ /**
418
+ * Get all registered migrations
419
+ */
420
+ getAllMigrations() {
421
+ return Array.from(this.migrations.values());
422
+ }
423
+ /**
424
+ * Get applied migrations
425
+ */
426
+ getAppliedMigrations() {
427
+ return [...this.state.appliedMigrations];
428
+ }
429
+ /**
430
+ * Get failed migrations
431
+ */
432
+ getFailedMigrations() {
433
+ return [...this.state.failedMigrations];
434
+ }
435
+ /**
436
+ * Get pending migrations
437
+ */
438
+ getPendingMigrations() {
439
+ return this.getAllMigrations().filter(
440
+ (m) => !this.state.appliedMigrations.includes(m.id)
441
+ );
442
+ }
443
+ /**
444
+ * Get migration statistics
445
+ */
446
+ getStatistics() {
447
+ const successful = this.executedMigrations.filter((m) => m.success).length;
448
+ const failed = this.executedMigrations.filter((m) => !m.success).length;
449
+ const totalDuration = this.executedMigrations.reduce((sum, m) => sum + m.duration, 0);
450
+ const totalAffected = this.executedMigrations.reduce((sum, m) => sum + m.itemsAffected, 0);
451
+ return {
452
+ totalExecuted: this.executedMigrations.length,
453
+ successful,
454
+ failed,
455
+ successRate: this.executedMigrations.length > 0 ? successful / this.executedMigrations.length * 100 : 0,
456
+ totalDurationMs: totalDuration,
457
+ averageDurationMs: this.executedMigrations.length > 0 ? totalDuration / this.executedMigrations.length : 0,
458
+ totalAffected
459
+ };
460
+ }
461
+ /**
462
+ * Clear history (for testing)
463
+ */
464
+ clear() {
465
+ this.migrations.clear();
466
+ this.executedMigrations = [];
467
+ this.state = {
468
+ currentVersion: "1.0.0",
469
+ appliedMigrations: [],
470
+ failedMigrations: [],
471
+ lastMigrationTime: (/* @__PURE__ */ new Date()).toISOString(),
472
+ totalMigrationsRun: 0
473
+ };
474
+ }
475
+ };
476
+
477
+ // src/versioning/DataTransformer.ts
478
+ var DataTransformer = class {
479
+ rules = /* @__PURE__ */ new Map();
480
+ transformationHistory = [];
481
+ /**
482
+ * Register a transformation rule
483
+ */
484
+ registerRule(rule) {
485
+ this.rules.set(rule.field, rule);
486
+ logger.debug("[DataTransformer] Rule registered", {
487
+ field: rule.field,
488
+ required: rule.required,
489
+ hasDefault: rule.defaultValue !== void 0
490
+ });
491
+ }
492
+ /**
493
+ * Transform a single field value
494
+ */
495
+ transformField(field, value) {
496
+ const rule = this.rules.get(field);
497
+ if (!rule) {
498
+ return value;
499
+ }
500
+ try {
501
+ return rule.transformer(value);
502
+ } catch (error) {
503
+ if (rule.required) {
504
+ throw new Error(`Failed to transform required field ${field}: ${error instanceof Error ? error.message : String(error)}`);
505
+ }
506
+ return rule.defaultValue !== void 0 ? rule.defaultValue : value;
507
+ }
508
+ }
509
+ /**
510
+ * Transform a single object
511
+ */
512
+ transformObject(data) {
513
+ const transformed = {};
514
+ for (const [key, value] of Object.entries(data)) {
515
+ try {
516
+ transformed[key] = this.transformField(key, value);
517
+ } catch (error) {
518
+ logger.warn("[DataTransformer] Field transformation failed", {
519
+ field: key,
520
+ error: error instanceof Error ? error.message : String(error)
521
+ });
522
+ const rule = this.rules.get(key);
523
+ if (!rule || !rule.required) {
524
+ transformed[key] = value;
525
+ }
526
+ }
527
+ }
528
+ return transformed;
529
+ }
530
+ /**
531
+ * Transform a collection of items
532
+ */
533
+ transformCollection(items) {
534
+ const startTime = Date.now();
535
+ const result = {
536
+ success: true,
537
+ itemsTransformed: 0,
538
+ itemsFailed: 0,
539
+ errors: [],
540
+ warnings: [],
541
+ duration: 0
542
+ };
543
+ for (let i = 0; i < items.length; i++) {
544
+ const item = items[i];
545
+ try {
546
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
547
+ this.transformObject(item);
548
+ result.itemsTransformed++;
549
+ } else {
550
+ result.warnings.push(`Item ${i} is not a transformable object`);
551
+ }
552
+ } catch (error) {
553
+ result.errors.push({
554
+ item,
555
+ error: error instanceof Error ? error.message : String(error)
556
+ });
557
+ result.itemsFailed++;
558
+ }
559
+ }
560
+ result.duration = Date.now() - startTime;
561
+ result.success = result.itemsFailed === 0;
562
+ this.transformationHistory.push(result);
563
+ logger.debug("[DataTransformer] Collection transformed", {
564
+ total: items.length,
565
+ transformed: result.itemsTransformed,
566
+ failed: result.itemsFailed,
567
+ duration: result.duration
568
+ });
569
+ return result;
570
+ }
571
+ /**
572
+ * Validate transformed data
573
+ */
574
+ validateTransformation(original, transformed) {
575
+ const issues = [];
576
+ if (original.length !== transformed.length) {
577
+ issues.push(`Item count mismatch: ${original.length} -> ${transformed.length}`);
578
+ }
579
+ for (let i = 0; i < Math.min(original.length, transformed.length); i++) {
580
+ const orig = original[i];
581
+ const trans = transformed[i];
582
+ if (!this.validateItem(orig, trans)) {
583
+ issues.push(`Item ${i} validation failed`);
584
+ }
585
+ }
586
+ return {
587
+ valid: issues.length === 0,
588
+ issues
589
+ };
590
+ }
591
+ /**
592
+ * Validate a single item transformation
593
+ */
594
+ validateItem(original, transformed) {
595
+ if (original === null || original === void 0) {
596
+ return true;
597
+ }
598
+ if (typeof original === "object" && typeof transformed !== "object") {
599
+ return false;
600
+ }
601
+ return true;
602
+ }
603
+ /**
604
+ * Get transformation history
605
+ */
606
+ getTransformationHistory() {
607
+ return [...this.transformationHistory];
608
+ }
609
+ /**
610
+ * Get transformation statistics
611
+ */
612
+ getStatistics() {
613
+ const totalTransformed = this.transformationHistory.reduce(
614
+ (sum, r) => sum + r.itemsTransformed,
615
+ 0
616
+ );
617
+ const totalFailed = this.transformationHistory.reduce(
618
+ (sum, r) => sum + r.itemsFailed,
619
+ 0
620
+ );
621
+ const totalDuration = this.transformationHistory.reduce(
622
+ (sum, r) => sum + r.duration,
623
+ 0
624
+ );
625
+ return {
626
+ totalBatches: this.transformationHistory.length,
627
+ totalTransformed,
628
+ totalFailed,
629
+ successRate: totalTransformed + totalFailed > 0 ? totalTransformed / (totalTransformed + totalFailed) * 100 : 0,
630
+ totalDurationMs: totalDuration,
631
+ averageBatchDurationMs: this.transformationHistory.length > 0 ? totalDuration / this.transformationHistory.length : 0
632
+ };
633
+ }
634
+ /**
635
+ * Get registered rules
636
+ */
637
+ getRules() {
638
+ return Array.from(this.rules.values());
639
+ }
640
+ /**
641
+ * Get rule for field
642
+ */
643
+ getRule(field) {
644
+ return this.rules.get(field);
645
+ }
646
+ /**
647
+ * Clear all rules (for testing)
648
+ */
649
+ clearRules() {
650
+ this.rules.clear();
651
+ }
652
+ /**
653
+ * Clear history (for testing)
654
+ */
655
+ clearHistory() {
656
+ this.transformationHistory = [];
657
+ }
658
+ /**
659
+ * Clear all state (for testing)
660
+ */
661
+ clear() {
662
+ this.clearRules();
663
+ this.clearHistory();
664
+ }
665
+ };
666
+
667
+ // src/versioning/MigrationTracker.ts
668
+ var MigrationTracker = class {
669
+ migrations = [];
670
+ snapshots = /* @__PURE__ */ new Map();
671
+ /**
672
+ * Track a new migration
673
+ */
674
+ recordMigration(record) {
675
+ this.migrations.push({ ...record });
676
+ logger.debug("[MigrationTracker] Migration recorded", {
677
+ id: record.id,
678
+ migrationId: record.migrationId,
679
+ version: record.version,
680
+ status: record.status
681
+ });
682
+ }
683
+ /**
684
+ * Track migration with snapshot
685
+ */
686
+ trackMigration(migrationId, version, beforeHash, afterHash, itemCount, duration, itemsAffected, appliedBy = "system") {
687
+ const record = {
688
+ id: `${migrationId}-${Date.now()}`,
689
+ migrationId,
690
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
691
+ version,
692
+ direction: "up",
693
+ status: "applied",
694
+ duration,
695
+ itemsAffected,
696
+ dataSnapshot: {
697
+ beforeHash,
698
+ afterHash,
699
+ itemCount
700
+ },
701
+ appliedBy
702
+ };
703
+ this.recordMigration(record);
704
+ this.snapshots.set(record.id, {
705
+ beforeHash,
706
+ afterHash,
707
+ itemCount
708
+ });
709
+ }
710
+ /**
711
+ * Get all migration records
712
+ */
713
+ getMigrations() {
714
+ return this.migrations.map((m) => ({ ...m }));
715
+ }
716
+ /**
717
+ * Get migrations for a specific version
718
+ */
719
+ getMigrationsForVersion(version) {
720
+ return this.migrations.filter((m) => m.version === version);
721
+ }
722
+ /**
723
+ * Get migration by ID
724
+ */
725
+ getMigration(id) {
726
+ return this.migrations.find((m) => m.id === id);
727
+ }
728
+ /**
729
+ * Check if can rollback
730
+ */
731
+ canRollback(fromVersion, toVersion) {
732
+ const fromIndex = this.migrations.findIndex((m) => m.version === fromVersion);
733
+ const toIndex = this.migrations.findIndex((m) => m.version === toVersion);
734
+ if (fromIndex === -1 || toIndex === -1) {
735
+ return false;
736
+ }
737
+ if (toIndex >= fromIndex) {
738
+ return false;
739
+ }
740
+ for (let i = fromIndex; i > toIndex; i--) {
741
+ if (!this.migrations[i]?.dataSnapshot) {
742
+ return false;
743
+ }
744
+ }
745
+ return true;
746
+ }
747
+ /**
748
+ * Get rollback path
749
+ */
750
+ getRollbackPath(fromVersion, toVersion) {
751
+ const canRollback = this.canRollback(fromVersion, toVersion);
752
+ const path = [];
753
+ const affectedVersions = [];
754
+ let estimatedDuration = 0;
755
+ if (canRollback) {
756
+ const fromIndex = this.migrations.findIndex((m) => m.version === fromVersion);
757
+ const toIndex = this.migrations.findIndex((m) => m.version === toVersion);
758
+ for (let i = fromIndex; i > toIndex; i--) {
759
+ const migration = this.migrations[i];
760
+ if (migration) {
761
+ path.push(migration.migrationId);
762
+ affectedVersions.push(migration.version);
763
+ estimatedDuration += migration.duration;
764
+ }
765
+ }
766
+ }
767
+ return {
768
+ path,
769
+ canRollback,
770
+ affectedVersions,
771
+ estimatedDuration
772
+ };
773
+ }
774
+ /**
775
+ * Get applied migrations
776
+ */
777
+ getAppliedMigrations() {
778
+ return this.migrations.filter((m) => m.status === "applied");
779
+ }
780
+ /**
781
+ * Get failed migrations
782
+ */
783
+ getFailedMigrations() {
784
+ return this.migrations.filter((m) => m.status === "failed");
785
+ }
786
+ /**
787
+ * Get pending migrations
788
+ */
789
+ getPendingMigrations() {
790
+ return this.migrations.filter((m) => m.status === "pending");
791
+ }
792
+ /**
793
+ * Get latest migration
794
+ */
795
+ getLatestMigration() {
796
+ return this.migrations[this.migrations.length - 1];
797
+ }
798
+ /**
799
+ * Get migration timeline
800
+ */
801
+ getTimeline() {
802
+ return this.migrations.map((m) => ({
803
+ timestamp: m.timestamp,
804
+ version: m.version,
805
+ status: m.status
806
+ }));
807
+ }
808
+ /**
809
+ * Get migration statistics
810
+ */
811
+ getStatistics() {
812
+ const applied = this.migrations.filter((m) => m.status === "applied").length;
813
+ const failed = this.migrations.filter((m) => m.status === "failed").length;
814
+ const pending = this.migrations.filter((m) => m.status === "pending").length;
815
+ const rolledBack = this.migrations.filter((m) => m.status === "rolled-back").length;
816
+ const totalDuration = this.migrations.reduce((sum, m) => sum + m.duration, 0);
817
+ const totalAffected = this.migrations.reduce((sum, m) => sum + m.itemsAffected, 0);
818
+ return {
819
+ total: this.migrations.length,
820
+ applied,
821
+ failed,
822
+ pending,
823
+ rolledBack,
824
+ successRate: this.migrations.length > 0 ? applied / this.migrations.length * 100 : 0,
825
+ totalDurationMs: totalDuration,
826
+ averageDurationMs: this.migrations.length > 0 ? totalDuration / this.migrations.length : 0,
827
+ totalItemsAffected: totalAffected
828
+ };
829
+ }
830
+ /**
831
+ * Get audit trail
832
+ */
833
+ getAuditTrail(migrationId) {
834
+ const filtered = migrationId ? this.migrations.filter((m) => m.migrationId === migrationId) : this.migrations;
835
+ return filtered.map((m) => ({
836
+ id: m.id,
837
+ timestamp: m.timestamp,
838
+ migrationId: m.migrationId,
839
+ version: m.version,
840
+ status: m.status,
841
+ appliedBy: m.appliedBy,
842
+ duration: m.duration,
843
+ itemsAffected: m.itemsAffected,
844
+ error: m.errorMessage
845
+ }));
846
+ }
847
+ /**
848
+ * Get data snapshot for recovery
849
+ */
850
+ getSnapshot(recordId) {
851
+ return this.snapshots.get(recordId);
852
+ }
853
+ /**
854
+ * Update migration status
855
+ */
856
+ updateMigrationStatus(recordId, status, error) {
857
+ const migration = this.migrations.find((m) => m.id === recordId);
858
+ if (migration) {
859
+ migration.status = status;
860
+ if (error) {
861
+ migration.errorMessage = error;
862
+ }
863
+ logger.debug("[MigrationTracker] Migration status updated", {
864
+ recordId,
865
+ status,
866
+ hasError: !!error
867
+ });
868
+ }
869
+ }
870
+ /**
871
+ * Clear history (for testing)
872
+ */
873
+ clear() {
874
+ this.migrations = [];
875
+ this.snapshots.clear();
876
+ }
877
+ /**
878
+ * Get total migrations tracked
879
+ */
880
+ getTotalMigrations() {
881
+ return this.migrations.length;
882
+ }
883
+ /**
884
+ * Find migrations by time range
885
+ */
886
+ getMigrationsByTimeRange(startTime, endTime) {
887
+ const start = new Date(startTime).getTime();
888
+ const end = new Date(endTime).getTime();
889
+ return this.migrations.filter((m) => {
890
+ const time = new Date(m.timestamp).getTime();
891
+ return time >= start && time <= end;
892
+ });
893
+ }
894
+ };
895
+ var SyncCoordinator = class extends eventemitter3.EventEmitter {
896
+ nodes = /* @__PURE__ */ new Map();
897
+ sessions = /* @__PURE__ */ new Map();
898
+ syncEvents = [];
899
+ nodeHeartbeats = /* @__PURE__ */ new Map();
900
+ heartbeatInterval = null;
901
+ // Crypto support
902
+ cryptoProvider = null;
903
+ nodesByDID = /* @__PURE__ */ new Map();
904
+ // DID -> nodeId
905
+ constructor() {
906
+ super();
907
+ }
908
+ /**
909
+ * Configure cryptographic provider for authenticated sync
910
+ */
911
+ configureCrypto(provider) {
912
+ this.cryptoProvider = provider;
913
+ logger.debug("[SyncCoordinator] Crypto configured", {
914
+ initialized: provider.isInitialized()
915
+ });
916
+ }
917
+ /**
918
+ * Check if crypto is configured
919
+ */
920
+ isCryptoEnabled() {
921
+ return this.cryptoProvider !== null && this.cryptoProvider.isInitialized();
922
+ }
923
+ /**
924
+ * Register a node with DID-based identity
925
+ */
926
+ async registerAuthenticatedNode(nodeInfo) {
927
+ const node = {
928
+ ...nodeInfo
929
+ };
930
+ this.nodes.set(node.id, node);
931
+ this.nodeHeartbeats.set(node.id, Date.now());
932
+ this.nodesByDID.set(nodeInfo.did, node.id);
933
+ if (this.cryptoProvider) {
934
+ await this.cryptoProvider.registerRemoteNode({
935
+ id: node.id,
936
+ did: nodeInfo.did,
937
+ publicSigningKey: nodeInfo.publicSigningKey,
938
+ publicEncryptionKey: nodeInfo.publicEncryptionKey
939
+ });
940
+ }
941
+ const event = {
942
+ type: "node-joined",
943
+ nodeId: node.id,
944
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
945
+ data: { did: nodeInfo.did, authenticated: true }
946
+ };
947
+ this.syncEvents.push(event);
948
+ this.emit("node-joined", node);
949
+ logger.debug("[SyncCoordinator] Authenticated node registered", {
950
+ nodeId: node.id,
951
+ did: nodeInfo.did,
952
+ version: node.version
953
+ });
954
+ return node;
955
+ }
956
+ /**
957
+ * Get node by DID
958
+ */
959
+ getNodeByDID(did) {
960
+ const nodeId = this.nodesByDID.get(did);
961
+ if (!nodeId) return void 0;
962
+ return this.nodes.get(nodeId);
963
+ }
964
+ /**
965
+ * Get all authenticated nodes (nodes with DIDs)
966
+ */
967
+ getAuthenticatedNodes() {
968
+ return Array.from(this.nodes.values()).filter((n) => n.did);
969
+ }
970
+ /**
971
+ * Create an authenticated sync session with UCAN-based authorization
972
+ */
973
+ async createAuthenticatedSyncSession(initiatorDID, participantDIDs, options) {
974
+ const initiatorNodeId = this.nodesByDID.get(initiatorDID);
975
+ if (!initiatorNodeId) {
976
+ throw new Error(`Initiator node with DID ${initiatorDID} not found`);
977
+ }
978
+ const participantIds = [];
979
+ for (const did of participantDIDs) {
980
+ const nodeId = this.nodesByDID.get(did);
981
+ if (nodeId) {
982
+ participantIds.push(nodeId);
983
+ }
984
+ }
985
+ let sessionToken;
986
+ if (this.cryptoProvider && this.cryptoProvider.isInitialized()) {
987
+ const capabilities = (options?.requiredCapabilities || ["aeon:sync:read", "aeon:sync:write"]).map((cap) => ({ can: cap, with: "*" }));
988
+ if (participantDIDs.length > 0) {
989
+ sessionToken = await this.cryptoProvider.createUCAN(
990
+ participantDIDs[0],
991
+ capabilities,
992
+ { expirationSeconds: 3600 }
993
+ // 1 hour
994
+ );
995
+ }
996
+ }
997
+ const session = {
998
+ id: `sync-${Date.now()}-${Math.random().toString(36).slice(2)}`,
999
+ initiatorId: initiatorNodeId,
1000
+ participantIds,
1001
+ status: "pending",
1002
+ startTime: (/* @__PURE__ */ new Date()).toISOString(),
1003
+ itemsSynced: 0,
1004
+ itemsFailed: 0,
1005
+ conflictsDetected: 0,
1006
+ initiatorDID,
1007
+ participantDIDs,
1008
+ encryptionMode: options?.encryptionMode || "none",
1009
+ requiredCapabilities: options?.requiredCapabilities,
1010
+ sessionToken
1011
+ };
1012
+ this.sessions.set(session.id, session);
1013
+ const event = {
1014
+ type: "sync-started",
1015
+ sessionId: session.id,
1016
+ nodeId: initiatorNodeId,
1017
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1018
+ data: {
1019
+ authenticated: true,
1020
+ initiatorDID,
1021
+ participantCount: participantDIDs.length,
1022
+ encryptionMode: session.encryptionMode
1023
+ }
1024
+ };
1025
+ this.syncEvents.push(event);
1026
+ this.emit("sync-started", session);
1027
+ logger.debug("[SyncCoordinator] Authenticated sync session created", {
1028
+ sessionId: session.id,
1029
+ initiatorDID,
1030
+ participants: participantDIDs.length,
1031
+ encryptionMode: session.encryptionMode
1032
+ });
1033
+ return session;
1034
+ }
1035
+ /**
1036
+ * Verify a node's UCAN capabilities for a session
1037
+ */
1038
+ async verifyNodeCapabilities(sessionId, nodeDID, token) {
1039
+ if (!this.cryptoProvider) {
1040
+ return { authorized: true };
1041
+ }
1042
+ const session = this.sessions.get(sessionId);
1043
+ if (!session) {
1044
+ return { authorized: false, error: `Session ${sessionId} not found` };
1045
+ }
1046
+ const result = await this.cryptoProvider.verifyUCAN(token, {
1047
+ requiredCapabilities: session.requiredCapabilities?.map((cap) => ({
1048
+ can: cap,
1049
+ with: "*"
1050
+ }))
1051
+ });
1052
+ if (!result.authorized) {
1053
+ logger.warn("[SyncCoordinator] Node capability verification failed", {
1054
+ sessionId,
1055
+ nodeDID,
1056
+ error: result.error
1057
+ });
1058
+ }
1059
+ return result;
1060
+ }
1061
+ /**
1062
+ * Register a node in the cluster
1063
+ */
1064
+ registerNode(node) {
1065
+ this.nodes.set(node.id, node);
1066
+ this.nodeHeartbeats.set(node.id, Date.now());
1067
+ const event = {
1068
+ type: "node-joined",
1069
+ nodeId: node.id,
1070
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1071
+ };
1072
+ this.syncEvents.push(event);
1073
+ this.emit("node-joined", node);
1074
+ logger.debug("[SyncCoordinator] Node registered", {
1075
+ nodeId: node.id,
1076
+ address: node.address,
1077
+ version: node.version
1078
+ });
1079
+ }
1080
+ /**
1081
+ * Deregister a node from the cluster
1082
+ */
1083
+ deregisterNode(nodeId) {
1084
+ const node = this.nodes.get(nodeId);
1085
+ if (!node) {
1086
+ throw new Error(`Node ${nodeId} not found`);
1087
+ }
1088
+ this.nodes.delete(nodeId);
1089
+ this.nodeHeartbeats.delete(nodeId);
1090
+ const event = {
1091
+ type: "node-left",
1092
+ nodeId,
1093
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1094
+ };
1095
+ this.syncEvents.push(event);
1096
+ this.emit("node-left", node);
1097
+ logger.debug("[SyncCoordinator] Node deregistered", { nodeId });
1098
+ }
1099
+ /**
1100
+ * Create a new sync session
1101
+ */
1102
+ createSyncSession(initiatorId, participantIds) {
1103
+ const node = this.nodes.get(initiatorId);
1104
+ if (!node) {
1105
+ throw new Error(`Initiator node ${initiatorId} not found`);
1106
+ }
1107
+ const session = {
1108
+ id: `sync-${Date.now()}-${Math.random().toString(36).slice(2)}`,
1109
+ initiatorId,
1110
+ participantIds,
1111
+ status: "pending",
1112
+ startTime: (/* @__PURE__ */ new Date()).toISOString(),
1113
+ itemsSynced: 0,
1114
+ itemsFailed: 0,
1115
+ conflictsDetected: 0
1116
+ };
1117
+ this.sessions.set(session.id, session);
1118
+ const event = {
1119
+ type: "sync-started",
1120
+ sessionId: session.id,
1121
+ nodeId: initiatorId,
1122
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1123
+ };
1124
+ this.syncEvents.push(event);
1125
+ this.emit("sync-started", session);
1126
+ logger.debug("[SyncCoordinator] Sync session created", {
1127
+ sessionId: session.id,
1128
+ initiator: initiatorId,
1129
+ participants: participantIds.length
1130
+ });
1131
+ return session;
1132
+ }
1133
+ /**
1134
+ * Update sync session
1135
+ */
1136
+ updateSyncSession(sessionId, updates) {
1137
+ const session = this.sessions.get(sessionId);
1138
+ if (!session) {
1139
+ throw new Error(`Session ${sessionId} not found`);
1140
+ }
1141
+ Object.assign(session, updates);
1142
+ if (updates.status === "completed" || updates.status === "failed") {
1143
+ session.endTime = (/* @__PURE__ */ new Date()).toISOString();
1144
+ const event = {
1145
+ type: "sync-completed",
1146
+ sessionId,
1147
+ nodeId: session.initiatorId,
1148
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1149
+ data: { status: updates.status, itemsSynced: session.itemsSynced }
1150
+ };
1151
+ this.syncEvents.push(event);
1152
+ this.emit("sync-completed", session);
1153
+ }
1154
+ logger.debug("[SyncCoordinator] Sync session updated", {
1155
+ sessionId,
1156
+ status: session.status,
1157
+ itemsSynced: session.itemsSynced
1158
+ });
1159
+ }
1160
+ /**
1161
+ * Record a conflict during sync
1162
+ */
1163
+ recordConflict(sessionId, nodeId, conflictData) {
1164
+ const session = this.sessions.get(sessionId);
1165
+ if (session) {
1166
+ session.conflictsDetected++;
1167
+ const event = {
1168
+ type: "conflict-detected",
1169
+ sessionId,
1170
+ nodeId,
1171
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1172
+ data: conflictData
1173
+ };
1174
+ this.syncEvents.push(event);
1175
+ this.emit("conflict-detected", { session, nodeId, conflictData });
1176
+ logger.debug("[SyncCoordinator] Conflict recorded", {
1177
+ sessionId,
1178
+ nodeId,
1179
+ totalConflicts: session.conflictsDetected
1180
+ });
1181
+ }
1182
+ }
1183
+ /**
1184
+ * Update node status
1185
+ */
1186
+ updateNodeStatus(nodeId, status) {
1187
+ const node = this.nodes.get(nodeId);
1188
+ if (!node) {
1189
+ throw new Error(`Node ${nodeId} not found`);
1190
+ }
1191
+ node.status = status;
1192
+ this.nodeHeartbeats.set(nodeId, Date.now());
1193
+ logger.debug("[SyncCoordinator] Node status updated", {
1194
+ nodeId,
1195
+ status
1196
+ });
1197
+ }
1198
+ /**
1199
+ * Record heartbeat from node
1200
+ */
1201
+ recordHeartbeat(nodeId) {
1202
+ const node = this.nodes.get(nodeId);
1203
+ if (!node) {
1204
+ return;
1205
+ }
1206
+ node.lastHeartbeat = (/* @__PURE__ */ new Date()).toISOString();
1207
+ this.nodeHeartbeats.set(nodeId, Date.now());
1208
+ }
1209
+ /**
1210
+ * Get all nodes
1211
+ */
1212
+ getNodes() {
1213
+ return Array.from(this.nodes.values());
1214
+ }
1215
+ /**
1216
+ * Get node by ID
1217
+ */
1218
+ getNode(nodeId) {
1219
+ return this.nodes.get(nodeId);
1220
+ }
1221
+ /**
1222
+ * Get online nodes
1223
+ */
1224
+ getOnlineNodes() {
1225
+ return Array.from(this.nodes.values()).filter((n) => n.status === "online");
1226
+ }
1227
+ /**
1228
+ * Get nodes by capability
1229
+ */
1230
+ getNodesByCapability(capability) {
1231
+ return Array.from(this.nodes.values()).filter(
1232
+ (n) => n.capabilities.includes(capability)
1233
+ );
1234
+ }
1235
+ /**
1236
+ * Get sync session
1237
+ */
1238
+ getSyncSession(sessionId) {
1239
+ return this.sessions.get(sessionId);
1240
+ }
1241
+ /**
1242
+ * Get all sync sessions
1243
+ */
1244
+ getAllSyncSessions() {
1245
+ return Array.from(this.sessions.values());
1246
+ }
1247
+ /**
1248
+ * Get active sync sessions
1249
+ */
1250
+ getActiveSyncSessions() {
1251
+ return Array.from(this.sessions.values()).filter((s) => s.status === "active");
1252
+ }
1253
+ /**
1254
+ * Get sessions for a node
1255
+ */
1256
+ getSessionsForNode(nodeId) {
1257
+ return Array.from(this.sessions.values()).filter(
1258
+ (s) => s.initiatorId === nodeId || s.participantIds.includes(nodeId)
1259
+ );
1260
+ }
1261
+ /**
1262
+ * Get sync statistics
1263
+ */
1264
+ getStatistics() {
1265
+ const sessions = Array.from(this.sessions.values());
1266
+ const completed = sessions.filter((s) => s.status === "completed").length;
1267
+ const failed = sessions.filter((s) => s.status === "failed").length;
1268
+ const active = sessions.filter((s) => s.status === "active").length;
1269
+ const totalItemsSynced = sessions.reduce((sum, s) => sum + s.itemsSynced, 0);
1270
+ const totalConflicts = sessions.reduce((sum, s) => sum + s.conflictsDetected, 0);
1271
+ return {
1272
+ totalNodes: this.nodes.size,
1273
+ onlineNodes: this.getOnlineNodes().length,
1274
+ offlineNodes: this.nodes.size - this.getOnlineNodes().length,
1275
+ totalSessions: sessions.length,
1276
+ activeSessions: active,
1277
+ completedSessions: completed,
1278
+ failedSessions: failed,
1279
+ successRate: sessions.length > 0 ? completed / sessions.length * 100 : 0,
1280
+ totalItemsSynced,
1281
+ totalConflicts,
1282
+ averageConflictsPerSession: sessions.length > 0 ? totalConflicts / sessions.length : 0
1283
+ };
1284
+ }
1285
+ /**
1286
+ * Get sync events
1287
+ */
1288
+ getSyncEvents(limit) {
1289
+ const events = [...this.syncEvents];
1290
+ if (limit) {
1291
+ return events.slice(-limit);
1292
+ }
1293
+ return events;
1294
+ }
1295
+ /**
1296
+ * Get sync events for session
1297
+ */
1298
+ getSessionEvents(sessionId) {
1299
+ return this.syncEvents.filter((e) => e.sessionId === sessionId);
1300
+ }
1301
+ /**
1302
+ * Check node health
1303
+ */
1304
+ getNodeHealth() {
1305
+ const health = {};
1306
+ for (const [nodeId, lastHeartbeat] of this.nodeHeartbeats) {
1307
+ const now = Date.now();
1308
+ const downtime = now - lastHeartbeat;
1309
+ const isHealthy = downtime < 3e4;
1310
+ health[nodeId] = {
1311
+ isHealthy,
1312
+ downtime
1313
+ };
1314
+ }
1315
+ return health;
1316
+ }
1317
+ /**
1318
+ * Start heartbeat monitoring
1319
+ */
1320
+ startHeartbeatMonitoring(interval = 5e3) {
1321
+ if (this.heartbeatInterval) {
1322
+ return;
1323
+ }
1324
+ this.heartbeatInterval = setInterval(() => {
1325
+ const health = this.getNodeHealth();
1326
+ for (const [nodeId, { isHealthy }] of Object.entries(health)) {
1327
+ const node = this.nodes.get(nodeId);
1328
+ if (!node) {
1329
+ continue;
1330
+ }
1331
+ const newStatus = isHealthy ? "online" : "offline";
1332
+ if (node.status !== newStatus) {
1333
+ this.updateNodeStatus(nodeId, newStatus);
1334
+ }
1335
+ }
1336
+ }, interval);
1337
+ logger.debug("[SyncCoordinator] Heartbeat monitoring started", { interval });
1338
+ }
1339
+ /**
1340
+ * Stop heartbeat monitoring
1341
+ */
1342
+ stopHeartbeatMonitoring() {
1343
+ if (this.heartbeatInterval) {
1344
+ clearInterval(this.heartbeatInterval);
1345
+ this.heartbeatInterval = null;
1346
+ logger.debug("[SyncCoordinator] Heartbeat monitoring stopped");
1347
+ }
1348
+ }
1349
+ /**
1350
+ * Clear all state (for testing)
1351
+ */
1352
+ clear() {
1353
+ this.nodes.clear();
1354
+ this.sessions.clear();
1355
+ this.syncEvents = [];
1356
+ this.nodeHeartbeats.clear();
1357
+ this.nodesByDID.clear();
1358
+ this.cryptoProvider = null;
1359
+ this.stopHeartbeatMonitoring();
1360
+ }
1361
+ /**
1362
+ * Get the crypto provider (for advanced usage)
1363
+ */
1364
+ getCryptoProvider() {
1365
+ return this.cryptoProvider;
1366
+ }
1367
+ };
1368
+
1369
+ // src/distributed/ReplicationManager.ts
1370
+ var ReplicationManager = class {
1371
+ replicas = /* @__PURE__ */ new Map();
1372
+ policies = /* @__PURE__ */ new Map();
1373
+ replicationEvents = [];
1374
+ syncStatus = /* @__PURE__ */ new Map();
1375
+ // Crypto support
1376
+ cryptoProvider = null;
1377
+ replicasByDID = /* @__PURE__ */ new Map();
1378
+ // DID -> replicaId
1379
+ /**
1380
+ * Configure cryptographic provider for encrypted replication
1381
+ */
1382
+ configureCrypto(provider) {
1383
+ this.cryptoProvider = provider;
1384
+ logger.debug("[ReplicationManager] Crypto configured", {
1385
+ initialized: provider.isInitialized()
1386
+ });
1387
+ }
1388
+ /**
1389
+ * Check if crypto is configured
1390
+ */
1391
+ isCryptoEnabled() {
1392
+ return this.cryptoProvider !== null && this.cryptoProvider.isInitialized();
1393
+ }
1394
+ /**
1395
+ * Register an authenticated replica with DID
1396
+ */
1397
+ async registerAuthenticatedReplica(replica, encrypted = false) {
1398
+ const authenticatedReplica = {
1399
+ ...replica,
1400
+ encrypted
1401
+ };
1402
+ this.replicas.set(replica.id, authenticatedReplica);
1403
+ this.replicasByDID.set(replica.did, replica.id);
1404
+ if (!this.syncStatus.has(replica.nodeId)) {
1405
+ this.syncStatus.set(replica.nodeId, { synced: 0, failed: 0 });
1406
+ }
1407
+ if (this.cryptoProvider && replica.publicSigningKey) {
1408
+ await this.cryptoProvider.registerRemoteNode({
1409
+ id: replica.nodeId,
1410
+ did: replica.did,
1411
+ publicSigningKey: replica.publicSigningKey,
1412
+ publicEncryptionKey: replica.publicEncryptionKey
1413
+ });
1414
+ }
1415
+ const event = {
1416
+ type: "replica-added",
1417
+ replicaId: replica.id,
1418
+ nodeId: replica.nodeId,
1419
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1420
+ details: { did: replica.did, encrypted, authenticated: true }
1421
+ };
1422
+ this.replicationEvents.push(event);
1423
+ logger.debug("[ReplicationManager] Authenticated replica registered", {
1424
+ replicaId: replica.id,
1425
+ did: replica.did,
1426
+ encrypted
1427
+ });
1428
+ return authenticatedReplica;
1429
+ }
1430
+ /**
1431
+ * Get replica by DID
1432
+ */
1433
+ getReplicaByDID(did) {
1434
+ const replicaId = this.replicasByDID.get(did);
1435
+ if (!replicaId) return void 0;
1436
+ return this.replicas.get(replicaId);
1437
+ }
1438
+ /**
1439
+ * Get all encrypted replicas
1440
+ */
1441
+ getEncryptedReplicas() {
1442
+ return Array.from(this.replicas.values()).filter((r) => r.encrypted);
1443
+ }
1444
+ /**
1445
+ * Encrypt data for replication to a specific replica
1446
+ */
1447
+ async encryptForReplica(data, targetReplicaDID) {
1448
+ if (!this.cryptoProvider || !this.cryptoProvider.isInitialized()) {
1449
+ throw new Error("Crypto provider not initialized");
1450
+ }
1451
+ const dataBytes = new TextEncoder().encode(JSON.stringify(data));
1452
+ const encrypted = await this.cryptoProvider.encrypt(dataBytes, targetReplicaDID);
1453
+ const localDID = this.cryptoProvider.getLocalDID();
1454
+ return {
1455
+ ct: encrypted.ct,
1456
+ iv: encrypted.iv,
1457
+ tag: encrypted.tag,
1458
+ epk: encrypted.epk,
1459
+ senderDID: localDID || void 0,
1460
+ targetDID: targetReplicaDID,
1461
+ encryptedAt: encrypted.encryptedAt
1462
+ };
1463
+ }
1464
+ /**
1465
+ * Decrypt data received from replication
1466
+ */
1467
+ async decryptReplicationData(encrypted) {
1468
+ if (!this.cryptoProvider || !this.cryptoProvider.isInitialized()) {
1469
+ throw new Error("Crypto provider not initialized");
1470
+ }
1471
+ const decrypted = await this.cryptoProvider.decrypt(
1472
+ {
1473
+ alg: "ECIES-P256",
1474
+ ct: encrypted.ct,
1475
+ iv: encrypted.iv,
1476
+ tag: encrypted.tag,
1477
+ epk: encrypted.epk
1478
+ },
1479
+ encrypted.senderDID
1480
+ );
1481
+ return JSON.parse(new TextDecoder().decode(decrypted));
1482
+ }
1483
+ /**
1484
+ * Create an encrypted replication policy
1485
+ */
1486
+ createEncryptedPolicy(name, replicationFactor, consistencyLevel, encryptionMode, options) {
1487
+ const policy = {
1488
+ id: `policy-${Date.now()}-${Math.random().toString(36).slice(2)}`,
1489
+ name,
1490
+ replicationFactor,
1491
+ consistencyLevel,
1492
+ syncInterval: options?.syncInterval || 1e3,
1493
+ maxReplicationLag: options?.maxReplicationLag || 1e4,
1494
+ encryptionMode,
1495
+ requiredCapabilities: options?.requiredCapabilities
1496
+ };
1497
+ this.policies.set(policy.id, policy);
1498
+ logger.debug("[ReplicationManager] Encrypted policy created", {
1499
+ policyId: policy.id,
1500
+ name,
1501
+ replicationFactor,
1502
+ encryptionMode
1503
+ });
1504
+ return policy;
1505
+ }
1506
+ /**
1507
+ * Verify a replica's capabilities via UCAN
1508
+ */
1509
+ async verifyReplicaCapabilities(replicaDID, token, policyId) {
1510
+ if (!this.cryptoProvider) {
1511
+ return { authorized: true };
1512
+ }
1513
+ const policy = policyId ? this.policies.get(policyId) : void 0;
1514
+ const result = await this.cryptoProvider.verifyUCAN(token, {
1515
+ requiredCapabilities: policy?.requiredCapabilities?.map((cap) => ({
1516
+ can: cap,
1517
+ with: "*"
1518
+ }))
1519
+ });
1520
+ if (!result.authorized) {
1521
+ logger.warn("[ReplicationManager] Replica capability verification failed", {
1522
+ replicaDID,
1523
+ error: result.error
1524
+ });
1525
+ }
1526
+ return result;
1527
+ }
1528
+ /**
1529
+ * Register a replica
1530
+ */
1531
+ registerReplica(replica) {
1532
+ this.replicas.set(replica.id, replica);
1533
+ if (!this.syncStatus.has(replica.nodeId)) {
1534
+ this.syncStatus.set(replica.nodeId, { synced: 0, failed: 0 });
1535
+ }
1536
+ const event = {
1537
+ type: "replica-added",
1538
+ replicaId: replica.id,
1539
+ nodeId: replica.nodeId,
1540
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1541
+ };
1542
+ this.replicationEvents.push(event);
1543
+ logger.debug("[ReplicationManager] Replica registered", {
1544
+ replicaId: replica.id,
1545
+ nodeId: replica.nodeId,
1546
+ status: replica.status
1547
+ });
1548
+ }
1549
+ /**
1550
+ * Remove a replica
1551
+ */
1552
+ removeReplica(replicaId) {
1553
+ const replica = this.replicas.get(replicaId);
1554
+ if (!replica) {
1555
+ throw new Error(`Replica ${replicaId} not found`);
1556
+ }
1557
+ this.replicas.delete(replicaId);
1558
+ const event = {
1559
+ type: "replica-removed",
1560
+ replicaId,
1561
+ nodeId: replica.nodeId,
1562
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1563
+ };
1564
+ this.replicationEvents.push(event);
1565
+ logger.debug("[ReplicationManager] Replica removed", { replicaId });
1566
+ }
1567
+ /**
1568
+ * Create a replication policy
1569
+ */
1570
+ createPolicy(name, replicationFactor, consistencyLevel, syncInterval = 1e3, maxReplicationLag = 1e4) {
1571
+ const policy = {
1572
+ id: `policy-${Date.now()}-${Math.random().toString(36).slice(2)}`,
1573
+ name,
1574
+ replicationFactor,
1575
+ consistencyLevel,
1576
+ syncInterval,
1577
+ maxReplicationLag
1578
+ };
1579
+ this.policies.set(policy.id, policy);
1580
+ logger.debug("[ReplicationManager] Policy created", {
1581
+ policyId: policy.id,
1582
+ name,
1583
+ replicationFactor,
1584
+ consistencyLevel
1585
+ });
1586
+ return policy;
1587
+ }
1588
+ /**
1589
+ * Update replica status
1590
+ */
1591
+ updateReplicaStatus(replicaId, status, lagBytes = 0, lagMillis = 0) {
1592
+ const replica = this.replicas.get(replicaId);
1593
+ if (!replica) {
1594
+ throw new Error(`Replica ${replicaId} not found`);
1595
+ }
1596
+ replica.status = status;
1597
+ replica.lagBytes = lagBytes;
1598
+ replica.lagMillis = lagMillis;
1599
+ replica.lastSyncTime = (/* @__PURE__ */ new Date()).toISOString();
1600
+ const event = {
1601
+ type: status === "syncing" ? "replica-synced" : "sync-failed",
1602
+ replicaId,
1603
+ nodeId: replica.nodeId,
1604
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1605
+ details: { status, lagBytes, lagMillis }
1606
+ };
1607
+ this.replicationEvents.push(event);
1608
+ const syncStatus = this.syncStatus.get(replica.nodeId);
1609
+ if (syncStatus) {
1610
+ if (status === "syncing" || status === "secondary") {
1611
+ syncStatus.synced++;
1612
+ } else if (status === "failed") {
1613
+ syncStatus.failed++;
1614
+ }
1615
+ }
1616
+ logger.debug("[ReplicationManager] Replica status updated", {
1617
+ replicaId,
1618
+ status,
1619
+ lagBytes,
1620
+ lagMillis
1621
+ });
1622
+ }
1623
+ /**
1624
+ * Get replicas for node
1625
+ */
1626
+ getReplicasForNode(nodeId) {
1627
+ return Array.from(this.replicas.values()).filter((r) => r.nodeId === nodeId);
1628
+ }
1629
+ /**
1630
+ * Get healthy replicas
1631
+ */
1632
+ getHealthyReplicas() {
1633
+ return Array.from(this.replicas.values()).filter(
1634
+ (r) => r.status === "secondary" || r.status === "primary"
1635
+ );
1636
+ }
1637
+ /**
1638
+ * Get syncing replicas
1639
+ */
1640
+ getSyncingReplicas() {
1641
+ return Array.from(this.replicas.values()).filter((r) => r.status === "syncing");
1642
+ }
1643
+ /**
1644
+ * Get failed replicas
1645
+ */
1646
+ getFailedReplicas() {
1647
+ return Array.from(this.replicas.values()).filter((r) => r.status === "failed");
1648
+ }
1649
+ /**
1650
+ * Check replication health for policy
1651
+ */
1652
+ checkReplicationHealth(policyId) {
1653
+ const policy = this.policies.get(policyId);
1654
+ if (!policy) {
1655
+ throw new Error(`Policy ${policyId} not found`);
1656
+ }
1657
+ const healthy = this.getHealthyReplicas();
1658
+ const maxLag = Math.max(0, ...healthy.map((r) => r.lagMillis));
1659
+ return {
1660
+ healthy: healthy.length >= policy.replicationFactor && maxLag <= policy.maxReplicationLag,
1661
+ replicasInPolicy: policy.replicationFactor,
1662
+ healthyReplicas: healthy.length,
1663
+ replicationLag: maxLag
1664
+ };
1665
+ }
1666
+ /**
1667
+ * Get consistency level
1668
+ */
1669
+ getConsistencyLevel(policyId) {
1670
+ const policy = this.policies.get(policyId);
1671
+ if (!policy) {
1672
+ return "eventual";
1673
+ }
1674
+ return policy.consistencyLevel;
1675
+ }
1676
+ /**
1677
+ * Get replica
1678
+ */
1679
+ getReplica(replicaId) {
1680
+ return this.replicas.get(replicaId);
1681
+ }
1682
+ /**
1683
+ * Get all replicas
1684
+ */
1685
+ getAllReplicas() {
1686
+ return Array.from(this.replicas.values());
1687
+ }
1688
+ /**
1689
+ * Get policy
1690
+ */
1691
+ getPolicy(policyId) {
1692
+ return this.policies.get(policyId);
1693
+ }
1694
+ /**
1695
+ * Get all policies
1696
+ */
1697
+ getAllPolicies() {
1698
+ return Array.from(this.policies.values());
1699
+ }
1700
+ /**
1701
+ * Get replication statistics
1702
+ */
1703
+ getStatistics() {
1704
+ const healthy = this.getHealthyReplicas().length;
1705
+ const syncing = this.getSyncingReplicas().length;
1706
+ const failed = this.getFailedReplicas().length;
1707
+ const total = this.replicas.size;
1708
+ const replicationLags = Array.from(this.replicas.values()).map((r) => r.lagMillis);
1709
+ const avgLag = replicationLags.length > 0 ? replicationLags.reduce((a, b) => a + b) / replicationLags.length : 0;
1710
+ const maxLag = replicationLags.length > 0 ? Math.max(...replicationLags) : 0;
1711
+ return {
1712
+ totalReplicas: total,
1713
+ healthyReplicas: healthy,
1714
+ syncingReplicas: syncing,
1715
+ failedReplicas: failed,
1716
+ healthiness: total > 0 ? healthy / total * 100 : 0,
1717
+ averageReplicationLagMs: avgLag,
1718
+ maxReplicationLagMs: maxLag,
1719
+ totalPolicies: this.policies.size
1720
+ };
1721
+ }
1722
+ /**
1723
+ * Get replication events
1724
+ */
1725
+ getReplicationEvents(limit) {
1726
+ const events = [...this.replicationEvents];
1727
+ if (limit) {
1728
+ return events.slice(-limit);
1729
+ }
1730
+ return events;
1731
+ }
1732
+ /**
1733
+ * Get sync status for node
1734
+ */
1735
+ getSyncStatus(nodeId) {
1736
+ return this.syncStatus.get(nodeId) || { synced: 0, failed: 0 };
1737
+ }
1738
+ /**
1739
+ * Get replication lag distribution
1740
+ */
1741
+ getReplicationLagDistribution() {
1742
+ const distribution = {
1743
+ "0-100ms": 0,
1744
+ "100-500ms": 0,
1745
+ "500-1000ms": 0,
1746
+ "1000+ms": 0
1747
+ };
1748
+ for (const replica of this.replicas.values()) {
1749
+ if (replica.lagMillis <= 100) {
1750
+ distribution["0-100ms"]++;
1751
+ } else if (replica.lagMillis <= 500) {
1752
+ distribution["100-500ms"]++;
1753
+ } else if (replica.lagMillis <= 1e3) {
1754
+ distribution["500-1000ms"]++;
1755
+ } else {
1756
+ distribution["1000+ms"]++;
1757
+ }
1758
+ }
1759
+ return distribution;
1760
+ }
1761
+ /**
1762
+ * Check if can satisfy consistency level
1763
+ */
1764
+ canSatisfyConsistency(policyId, _requiredAcks) {
1765
+ const policy = this.policies.get(policyId);
1766
+ if (!policy) {
1767
+ return false;
1768
+ }
1769
+ const healthyCount = this.getHealthyReplicas().length;
1770
+ switch (policy.consistencyLevel) {
1771
+ case "eventual":
1772
+ return true;
1773
+ // Always achievable
1774
+ case "read-after-write":
1775
+ return healthyCount >= 1;
1776
+ case "strong":
1777
+ return healthyCount >= policy.replicationFactor;
1778
+ default:
1779
+ return false;
1780
+ }
1781
+ }
1782
+ /**
1783
+ * Clear all state (for testing)
1784
+ */
1785
+ clear() {
1786
+ this.replicas.clear();
1787
+ this.policies.clear();
1788
+ this.replicationEvents = [];
1789
+ this.syncStatus.clear();
1790
+ this.replicasByDID.clear();
1791
+ this.cryptoProvider = null;
1792
+ }
1793
+ /**
1794
+ * Get the crypto provider (for advanced usage)
1795
+ */
1796
+ getCryptoProvider() {
1797
+ return this.cryptoProvider;
1798
+ }
1799
+ };
1800
+
1801
+ // src/distributed/SyncProtocol.ts
1802
+ var SyncProtocol = class {
1803
+ version = "1.0.0";
1804
+ messageQueue = [];
1805
+ messageMap = /* @__PURE__ */ new Map();
1806
+ handshakes = /* @__PURE__ */ new Map();
1807
+ protocolErrors = [];
1808
+ messageCounter = 0;
1809
+ // Crypto support
1810
+ cryptoProvider = null;
1811
+ cryptoConfig = null;
1812
+ /**
1813
+ * Configure cryptographic provider for authenticated/encrypted messages
1814
+ */
1815
+ configureCrypto(provider, config) {
1816
+ this.cryptoProvider = provider;
1817
+ this.cryptoConfig = {
1818
+ encryptionMode: config?.encryptionMode ?? "none",
1819
+ requireSignatures: config?.requireSignatures ?? false,
1820
+ requireCapabilities: config?.requireCapabilities ?? false,
1821
+ requiredCapabilities: config?.requiredCapabilities
1822
+ };
1823
+ logger.debug("[SyncProtocol] Crypto configured", {
1824
+ encryptionMode: this.cryptoConfig.encryptionMode,
1825
+ requireSignatures: this.cryptoConfig.requireSignatures,
1826
+ requireCapabilities: this.cryptoConfig.requireCapabilities
1827
+ });
1828
+ }
1829
+ /**
1830
+ * Check if crypto is configured
1831
+ */
1832
+ isCryptoEnabled() {
1833
+ return this.cryptoProvider !== null && this.cryptoProvider.isInitialized();
1834
+ }
1835
+ /**
1836
+ * Get crypto configuration
1837
+ */
1838
+ getCryptoConfig() {
1839
+ return this.cryptoConfig ? { ...this.cryptoConfig } : null;
1840
+ }
1841
+ /**
1842
+ * Get protocol version
1843
+ */
1844
+ getVersion() {
1845
+ return this.version;
1846
+ }
1847
+ /**
1848
+ * Create authenticated handshake message with DID and keys
1849
+ */
1850
+ async createAuthenticatedHandshake(capabilities, targetDID) {
1851
+ if (!this.cryptoProvider || !this.cryptoProvider.isInitialized()) {
1852
+ throw new Error("Crypto provider not initialized");
1853
+ }
1854
+ const localDID = this.cryptoProvider.getLocalDID();
1855
+ if (!localDID) {
1856
+ throw new Error("Local DID not available");
1857
+ }
1858
+ const publicInfo = await this.cryptoProvider.exportPublicIdentity();
1859
+ if (!publicInfo) {
1860
+ throw new Error("Cannot export public identity");
1861
+ }
1862
+ let ucan;
1863
+ if (targetDID && this.cryptoConfig?.requireCapabilities) {
1864
+ const caps = this.cryptoConfig.requiredCapabilities || [
1865
+ { can: "aeon:sync:read", with: "*" },
1866
+ { can: "aeon:sync:write", with: "*" }
1867
+ ];
1868
+ ucan = await this.cryptoProvider.createUCAN(targetDID, caps);
1869
+ }
1870
+ const handshakePayload = {
1871
+ protocolVersion: this.version,
1872
+ nodeId: localDID,
1873
+ capabilities,
1874
+ state: "initiating",
1875
+ did: localDID,
1876
+ publicSigningKey: publicInfo.publicSigningKey,
1877
+ publicEncryptionKey: publicInfo.publicEncryptionKey,
1878
+ ucan
1879
+ };
1880
+ const message = {
1881
+ type: "handshake",
1882
+ version: this.version,
1883
+ sender: localDID,
1884
+ receiver: targetDID || "",
1885
+ messageId: this.generateMessageId(),
1886
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1887
+ payload: handshakePayload
1888
+ };
1889
+ if (this.cryptoConfig?.requireSignatures) {
1890
+ const signed = await this.cryptoProvider.signData(handshakePayload);
1891
+ message.auth = {
1892
+ senderDID: localDID,
1893
+ receiverDID: targetDID,
1894
+ signature: signed.signature
1895
+ };
1896
+ }
1897
+ this.messageMap.set(message.messageId, message);
1898
+ this.messageQueue.push(message);
1899
+ logger.debug("[SyncProtocol] Authenticated handshake created", {
1900
+ messageId: message.messageId,
1901
+ did: localDID,
1902
+ capabilities: capabilities.length,
1903
+ hasUCAN: !!ucan
1904
+ });
1905
+ return message;
1906
+ }
1907
+ /**
1908
+ * Verify and process an authenticated handshake
1909
+ */
1910
+ async verifyAuthenticatedHandshake(message) {
1911
+ if (message.type !== "handshake") {
1912
+ return { valid: false, error: "Message is not a handshake" };
1913
+ }
1914
+ const handshake = message.payload;
1915
+ if (!this.cryptoProvider || !this.cryptoConfig) {
1916
+ this.handshakes.set(message.sender, handshake);
1917
+ return { valid: true, handshake };
1918
+ }
1919
+ if (handshake.did && handshake.publicSigningKey) {
1920
+ await this.cryptoProvider.registerRemoteNode({
1921
+ id: handshake.nodeId,
1922
+ did: handshake.did,
1923
+ publicSigningKey: handshake.publicSigningKey,
1924
+ publicEncryptionKey: handshake.publicEncryptionKey
1925
+ });
1926
+ }
1927
+ if (this.cryptoConfig.requireSignatures && message.auth?.signature) {
1928
+ const signed = {
1929
+ payload: handshake,
1930
+ signature: message.auth.signature,
1931
+ signer: message.auth.senderDID || message.sender,
1932
+ algorithm: "ES256",
1933
+ signedAt: Date.now()
1934
+ };
1935
+ const isValid = await this.cryptoProvider.verifySignedData(signed);
1936
+ if (!isValid) {
1937
+ logger.warn("[SyncProtocol] Handshake signature verification failed", {
1938
+ messageId: message.messageId,
1939
+ sender: message.sender
1940
+ });
1941
+ return { valid: false, error: "Invalid signature" };
1942
+ }
1943
+ }
1944
+ if (this.cryptoConfig.requireCapabilities && handshake.ucan) {
1945
+ const localDID = this.cryptoProvider.getLocalDID();
1946
+ const result = await this.cryptoProvider.verifyUCAN(handshake.ucan, {
1947
+ expectedAudience: localDID || void 0,
1948
+ requiredCapabilities: this.cryptoConfig.requiredCapabilities
1949
+ });
1950
+ if (!result.authorized) {
1951
+ logger.warn("[SyncProtocol] Handshake UCAN verification failed", {
1952
+ messageId: message.messageId,
1953
+ error: result.error
1954
+ });
1955
+ return { valid: false, error: result.error || "Unauthorized" };
1956
+ }
1957
+ }
1958
+ this.handshakes.set(message.sender, handshake);
1959
+ logger.debug("[SyncProtocol] Authenticated handshake verified", {
1960
+ messageId: message.messageId,
1961
+ did: handshake.did
1962
+ });
1963
+ return { valid: true, handshake };
1964
+ }
1965
+ /**
1966
+ * Sign and optionally encrypt a message payload
1967
+ */
1968
+ async signMessage(message, payload, encrypt = false) {
1969
+ if (!this.cryptoProvider || !this.cryptoProvider.isInitialized()) {
1970
+ throw new Error("Crypto provider not initialized");
1971
+ }
1972
+ const localDID = this.cryptoProvider.getLocalDID();
1973
+ const signed = await this.cryptoProvider.signData(payload);
1974
+ message.auth = {
1975
+ senderDID: localDID || void 0,
1976
+ receiverDID: message.receiver || void 0,
1977
+ signature: signed.signature,
1978
+ encrypted: false
1979
+ };
1980
+ if (encrypt && message.receiver && this.cryptoConfig?.encryptionMode !== "none") {
1981
+ const payloadBytes = new TextEncoder().encode(JSON.stringify(payload));
1982
+ const encrypted = await this.cryptoProvider.encrypt(payloadBytes, message.receiver);
1983
+ message.payload = encrypted;
1984
+ message.auth.encrypted = true;
1985
+ logger.debug("[SyncProtocol] Message encrypted", {
1986
+ messageId: message.messageId,
1987
+ recipient: message.receiver
1988
+ });
1989
+ } else {
1990
+ message.payload = payload;
1991
+ }
1992
+ return message;
1993
+ }
1994
+ /**
1995
+ * Verify signature and optionally decrypt a message
1996
+ */
1997
+ async verifyMessage(message) {
1998
+ if (!this.cryptoProvider || !message.auth) {
1999
+ return { valid: true, payload: message.payload };
2000
+ }
2001
+ let payload = message.payload;
2002
+ if (message.auth.encrypted && message.payload) {
2003
+ try {
2004
+ const encrypted = message.payload;
2005
+ const decrypted = await this.cryptoProvider.decrypt(
2006
+ encrypted,
2007
+ message.auth.senderDID
2008
+ );
2009
+ payload = JSON.parse(new TextDecoder().decode(decrypted));
2010
+ logger.debug("[SyncProtocol] Message decrypted", {
2011
+ messageId: message.messageId
2012
+ });
2013
+ } catch (error) {
2014
+ return {
2015
+ valid: false,
2016
+ error: `Decryption failed: ${error instanceof Error ? error.message : String(error)}`
2017
+ };
2018
+ }
2019
+ }
2020
+ if (message.auth.signature && message.auth.senderDID) {
2021
+ const signed = {
2022
+ payload,
2023
+ signature: message.auth.signature,
2024
+ signer: message.auth.senderDID,
2025
+ algorithm: "ES256",
2026
+ signedAt: Date.now()
2027
+ };
2028
+ const isValid = await this.cryptoProvider.verifySignedData(signed);
2029
+ if (!isValid) {
2030
+ return { valid: false, error: "Invalid signature" };
2031
+ }
2032
+ }
2033
+ return { valid: true, payload };
2034
+ }
2035
+ /**
2036
+ * Create handshake message
2037
+ */
2038
+ createHandshakeMessage(nodeId, capabilities) {
2039
+ const message = {
2040
+ type: "handshake",
2041
+ version: this.version,
2042
+ sender: nodeId,
2043
+ receiver: "",
2044
+ messageId: this.generateMessageId(),
2045
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2046
+ payload: {
2047
+ protocolVersion: this.version,
2048
+ nodeId,
2049
+ capabilities,
2050
+ state: "initiating"
2051
+ }
2052
+ };
2053
+ this.messageMap.set(message.messageId, message);
2054
+ this.messageQueue.push(message);
2055
+ logger.debug("[SyncProtocol] Handshake message created", {
2056
+ messageId: message.messageId,
2057
+ nodeId,
2058
+ capabilities: capabilities.length
2059
+ });
2060
+ return message;
2061
+ }
2062
+ /**
2063
+ * Create sync request message
2064
+ */
2065
+ createSyncRequestMessage(sender, receiver, sessionId, fromVersion, toVersion, filter) {
2066
+ const message = {
2067
+ type: "sync-request",
2068
+ version: this.version,
2069
+ sender,
2070
+ receiver,
2071
+ messageId: this.generateMessageId(),
2072
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2073
+ payload: {
2074
+ sessionId,
2075
+ fromVersion,
2076
+ toVersion,
2077
+ filter
2078
+ }
2079
+ };
2080
+ this.messageMap.set(message.messageId, message);
2081
+ this.messageQueue.push(message);
2082
+ logger.debug("[SyncProtocol] Sync request created", {
2083
+ messageId: message.messageId,
2084
+ sessionId,
2085
+ fromVersion,
2086
+ toVersion
2087
+ });
2088
+ return message;
2089
+ }
2090
+ /**
2091
+ * Create sync response message
2092
+ */
2093
+ createSyncResponseMessage(sender, receiver, sessionId, fromVersion, toVersion, data, hasMore = false, offset = 0) {
2094
+ const message = {
2095
+ type: "sync-response",
2096
+ version: this.version,
2097
+ sender,
2098
+ receiver,
2099
+ messageId: this.generateMessageId(),
2100
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2101
+ payload: {
2102
+ sessionId,
2103
+ fromVersion,
2104
+ toVersion,
2105
+ data,
2106
+ hasMore,
2107
+ offset
2108
+ }
2109
+ };
2110
+ this.messageMap.set(message.messageId, message);
2111
+ this.messageQueue.push(message);
2112
+ logger.debug("[SyncProtocol] Sync response created", {
2113
+ messageId: message.messageId,
2114
+ sessionId,
2115
+ itemCount: data.length,
2116
+ hasMore
2117
+ });
2118
+ return message;
2119
+ }
2120
+ /**
2121
+ * Create acknowledgement message
2122
+ */
2123
+ createAckMessage(sender, receiver, messageId) {
2124
+ const message = {
2125
+ type: "ack",
2126
+ version: this.version,
2127
+ sender,
2128
+ receiver,
2129
+ messageId: this.generateMessageId(),
2130
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2131
+ payload: { acknowledgedMessageId: messageId }
2132
+ };
2133
+ this.messageMap.set(message.messageId, message);
2134
+ this.messageQueue.push(message);
2135
+ return message;
2136
+ }
2137
+ /**
2138
+ * Create error message
2139
+ */
2140
+ createErrorMessage(sender, receiver, error, relatedMessageId) {
2141
+ const message = {
2142
+ type: "error",
2143
+ version: this.version,
2144
+ sender,
2145
+ receiver,
2146
+ messageId: this.generateMessageId(),
2147
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2148
+ payload: {
2149
+ error,
2150
+ relatedMessageId
2151
+ }
2152
+ };
2153
+ this.messageMap.set(message.messageId, message);
2154
+ this.messageQueue.push(message);
2155
+ this.protocolErrors.push({
2156
+ error,
2157
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2158
+ });
2159
+ logger.error("[SyncProtocol] Error message created", {
2160
+ messageId: message.messageId,
2161
+ errorCode: error.code,
2162
+ recoverable: error.recoverable
2163
+ });
2164
+ return message;
2165
+ }
2166
+ /**
2167
+ * Validate message
2168
+ */
2169
+ validateMessage(message) {
2170
+ const errors = [];
2171
+ if (!message.type) {
2172
+ errors.push("Message type is required");
2173
+ }
2174
+ if (!message.sender) {
2175
+ errors.push("Sender is required");
2176
+ }
2177
+ if (!message.messageId) {
2178
+ errors.push("Message ID is required");
2179
+ }
2180
+ if (!message.timestamp) {
2181
+ errors.push("Timestamp is required");
2182
+ }
2183
+ try {
2184
+ new Date(message.timestamp);
2185
+ } catch {
2186
+ errors.push("Invalid timestamp format");
2187
+ }
2188
+ return {
2189
+ valid: errors.length === 0,
2190
+ errors
2191
+ };
2192
+ }
2193
+ /**
2194
+ * Serialize message
2195
+ */
2196
+ serializeMessage(message) {
2197
+ try {
2198
+ return JSON.stringify(message);
2199
+ } catch (error) {
2200
+ logger.error("[SyncProtocol] Message serialization failed", {
2201
+ messageId: message.messageId,
2202
+ error: error instanceof Error ? error.message : String(error)
2203
+ });
2204
+ throw new Error(`Failed to serialize message: ${error instanceof Error ? error.message : String(error)}`);
2205
+ }
2206
+ }
2207
+ /**
2208
+ * Deserialize message
2209
+ */
2210
+ deserializeMessage(data) {
2211
+ try {
2212
+ const message = JSON.parse(data);
2213
+ const validation = this.validateMessage(message);
2214
+ if (!validation.valid) {
2215
+ throw new Error(`Invalid message: ${validation.errors.join(", ")}`);
2216
+ }
2217
+ return message;
2218
+ } catch (error) {
2219
+ logger.error("[SyncProtocol] Message deserialization failed", {
2220
+ error: error instanceof Error ? error.message : String(error)
2221
+ });
2222
+ throw new Error(`Failed to deserialize message: ${error instanceof Error ? error.message : String(error)}`);
2223
+ }
2224
+ }
2225
+ /**
2226
+ * Process handshake
2227
+ */
2228
+ processHandshake(message) {
2229
+ if (message.type !== "handshake") {
2230
+ throw new Error("Message is not a handshake");
2231
+ }
2232
+ const handshake = message.payload;
2233
+ const nodeId = message.sender;
2234
+ this.handshakes.set(nodeId, handshake);
2235
+ logger.debug("[SyncProtocol] Handshake processed", {
2236
+ nodeId,
2237
+ protocolVersion: handshake.protocolVersion,
2238
+ capabilities: handshake.capabilities.length
2239
+ });
2240
+ return handshake;
2241
+ }
2242
+ /**
2243
+ * Get message
2244
+ */
2245
+ getMessage(messageId) {
2246
+ return this.messageMap.get(messageId);
2247
+ }
2248
+ /**
2249
+ * Get all messages
2250
+ */
2251
+ getAllMessages() {
2252
+ return [...this.messageQueue];
2253
+ }
2254
+ /**
2255
+ * Get messages by type
2256
+ */
2257
+ getMessagesByType(type) {
2258
+ return this.messageQueue.filter((m) => m.type === type);
2259
+ }
2260
+ /**
2261
+ * Get messages from sender
2262
+ */
2263
+ getMessagesFromSender(sender) {
2264
+ return this.messageQueue.filter((m) => m.sender === sender);
2265
+ }
2266
+ /**
2267
+ * Get pending messages
2268
+ */
2269
+ getPendingMessages(receiver) {
2270
+ return this.messageQueue.filter((m) => m.receiver === receiver);
2271
+ }
2272
+ /**
2273
+ * Get handshakes
2274
+ */
2275
+ getHandshakes() {
2276
+ return new Map(this.handshakes);
2277
+ }
2278
+ /**
2279
+ * Get protocol statistics
2280
+ */
2281
+ getStatistics() {
2282
+ const messagesByType = {};
2283
+ for (const message of this.messageQueue) {
2284
+ messagesByType[message.type] = (messagesByType[message.type] || 0) + 1;
2285
+ }
2286
+ const errorCount = this.protocolErrors.length;
2287
+ const recoverableErrors = this.protocolErrors.filter((e) => e.error.recoverable).length;
2288
+ return {
2289
+ totalMessages: this.messageQueue.length,
2290
+ messagesByType,
2291
+ totalHandshakes: this.handshakes.size,
2292
+ totalErrors: errorCount,
2293
+ recoverableErrors,
2294
+ unrecoverableErrors: errorCount - recoverableErrors
2295
+ };
2296
+ }
2297
+ /**
2298
+ * Get protocol errors
2299
+ */
2300
+ getErrors() {
2301
+ return [...this.protocolErrors];
2302
+ }
2303
+ /**
2304
+ * Generate message ID
2305
+ */
2306
+ generateMessageId() {
2307
+ this.messageCounter++;
2308
+ return `msg-${Date.now()}-${this.messageCounter}`;
2309
+ }
2310
+ /**
2311
+ * Clear all state (for testing)
2312
+ */
2313
+ clear() {
2314
+ this.messageQueue = [];
2315
+ this.messageMap.clear();
2316
+ this.handshakes.clear();
2317
+ this.protocolErrors = [];
2318
+ this.messageCounter = 0;
2319
+ this.cryptoProvider = null;
2320
+ this.cryptoConfig = null;
2321
+ }
2322
+ /**
2323
+ * Get the crypto provider (for advanced usage)
2324
+ */
2325
+ getCryptoProvider() {
2326
+ return this.cryptoProvider;
2327
+ }
2328
+ };
2329
+
2330
+ // src/distributed/StateReconciler.ts
2331
+ var StateReconciler = class {
2332
+ stateVersions = /* @__PURE__ */ new Map();
2333
+ reconciliationHistory = [];
2334
+ cryptoProvider = null;
2335
+ requireSignedVersions = false;
2336
+ /**
2337
+ * Configure cryptographic provider for signed state versions
2338
+ */
2339
+ configureCrypto(provider, requireSigned = false) {
2340
+ this.cryptoProvider = provider;
2341
+ this.requireSignedVersions = requireSigned;
2342
+ logger.debug("[StateReconciler] Crypto configured", {
2343
+ initialized: provider.isInitialized(),
2344
+ requireSigned
2345
+ });
2346
+ }
2347
+ /**
2348
+ * Check if crypto is configured
2349
+ */
2350
+ isCryptoEnabled() {
2351
+ return this.cryptoProvider !== null && this.cryptoProvider.isInitialized();
2352
+ }
2353
+ /**
2354
+ * Record a signed state version with cryptographic verification
2355
+ */
2356
+ async recordSignedStateVersion(key, version, data) {
2357
+ if (!this.cryptoProvider || !this.cryptoProvider.isInitialized()) {
2358
+ throw new Error("Crypto provider not initialized");
2359
+ }
2360
+ const localDID = this.cryptoProvider.getLocalDID();
2361
+ if (!localDID) {
2362
+ throw new Error("Local DID not available");
2363
+ }
2364
+ const dataBytes = new TextEncoder().encode(JSON.stringify(data));
2365
+ const hashBytes = await this.cryptoProvider.hash(dataBytes);
2366
+ const hash = Array.from(hashBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2367
+ const versionData = { version, data, hash };
2368
+ const signed = await this.cryptoProvider.signData(versionData);
2369
+ const stateVersion = {
2370
+ version,
2371
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2372
+ nodeId: localDID,
2373
+ hash,
2374
+ data,
2375
+ signerDID: localDID,
2376
+ signature: signed.signature,
2377
+ signedAt: signed.signedAt
2378
+ };
2379
+ if (!this.stateVersions.has(key)) {
2380
+ this.stateVersions.set(key, []);
2381
+ }
2382
+ this.stateVersions.get(key).push(stateVersion);
2383
+ logger.debug("[StateReconciler] Signed state version recorded", {
2384
+ key,
2385
+ version,
2386
+ signerDID: localDID,
2387
+ hash: hash.slice(0, 16) + "..."
2388
+ });
2389
+ return stateVersion;
2390
+ }
2391
+ /**
2392
+ * Verify a state version's signature
2393
+ */
2394
+ async verifyStateVersion(version) {
2395
+ if (!version.signature || !version.signerDID) {
2396
+ if (this.requireSignedVersions) {
2397
+ return { valid: false, error: "Signature required but not present" };
2398
+ }
2399
+ const dataBytes = new TextEncoder().encode(JSON.stringify(version.data));
2400
+ if (this.cryptoProvider) {
2401
+ const hashBytes = await this.cryptoProvider.hash(dataBytes);
2402
+ const computedHash = Array.from(hashBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
2403
+ if (computedHash !== version.hash) {
2404
+ return { valid: false, error: "Hash mismatch" };
2405
+ }
2406
+ }
2407
+ return { valid: true };
2408
+ }
2409
+ if (!this.cryptoProvider) {
2410
+ return { valid: false, error: "Crypto provider not configured" };
2411
+ }
2412
+ const versionData = {
2413
+ version: version.version,
2414
+ data: version.data,
2415
+ hash: version.hash
2416
+ };
2417
+ const signed = {
2418
+ payload: versionData,
2419
+ signature: version.signature,
2420
+ signer: version.signerDID,
2421
+ algorithm: "ES256",
2422
+ signedAt: version.signedAt || Date.now()
2423
+ };
2424
+ const isValid = await this.cryptoProvider.verifySignedData(signed);
2425
+ if (!isValid) {
2426
+ return { valid: false, error: "Invalid signature" };
2427
+ }
2428
+ return { valid: true };
2429
+ }
2430
+ /**
2431
+ * Reconcile with verification - only accept verified versions
2432
+ */
2433
+ async reconcileWithVerification(key, strategy = "last-write-wins") {
2434
+ const versions = this.stateVersions.get(key) || [];
2435
+ const verifiedVersions = [];
2436
+ const verificationErrors = [];
2437
+ for (const version of versions) {
2438
+ const result2 = await this.verifyStateVersion(version);
2439
+ if (result2.valid) {
2440
+ verifiedVersions.push(version);
2441
+ } else {
2442
+ verificationErrors.push(
2443
+ `Version ${version.version} from ${version.nodeId}: ${result2.error}`
2444
+ );
2445
+ logger.warn("[StateReconciler] Version verification failed", {
2446
+ version: version.version,
2447
+ nodeId: version.nodeId,
2448
+ error: result2.error
2449
+ });
2450
+ }
2451
+ }
2452
+ if (verifiedVersions.length === 0) {
2453
+ return {
2454
+ success: false,
2455
+ mergedState: null,
2456
+ conflictsResolved: 0,
2457
+ strategy,
2458
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2459
+ verificationErrors
2460
+ };
2461
+ }
2462
+ let result;
2463
+ switch (strategy) {
2464
+ case "last-write-wins":
2465
+ result = this.reconcileLastWriteWins(verifiedVersions);
2466
+ break;
2467
+ case "vector-clock":
2468
+ result = this.reconcileVectorClock(verifiedVersions);
2469
+ break;
2470
+ case "majority-vote":
2471
+ result = this.reconcileMajorityVote(verifiedVersions);
2472
+ break;
2473
+ default:
2474
+ result = this.reconcileLastWriteWins(verifiedVersions);
2475
+ }
2476
+ return { ...result, verificationErrors };
2477
+ }
2478
+ /**
2479
+ * Record a state version
2480
+ */
2481
+ recordStateVersion(key, version, timestamp, nodeId, hash, data) {
2482
+ if (!this.stateVersions.has(key)) {
2483
+ this.stateVersions.set(key, []);
2484
+ }
2485
+ const versions = this.stateVersions.get(key);
2486
+ versions.push({
2487
+ version,
2488
+ timestamp,
2489
+ nodeId,
2490
+ hash,
2491
+ data
2492
+ });
2493
+ logger.debug("[StateReconciler] State version recorded", {
2494
+ key,
2495
+ version,
2496
+ nodeId,
2497
+ hash
2498
+ });
2499
+ }
2500
+ /**
2501
+ * Detect conflicts in state versions
2502
+ */
2503
+ detectConflicts(key) {
2504
+ const versions = this.stateVersions.get(key);
2505
+ if (!versions || versions.length <= 1) {
2506
+ return false;
2507
+ }
2508
+ const hashes = new Set(versions.map((v) => v.hash));
2509
+ return hashes.size > 1;
2510
+ }
2511
+ /**
2512
+ * Compare two states and generate diff
2513
+ */
2514
+ compareStates(state1, state2) {
2515
+ const diff = {
2516
+ added: {},
2517
+ modified: {},
2518
+ removed: [],
2519
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2520
+ };
2521
+ for (const [key, value] of Object.entries(state2)) {
2522
+ if (!(key in state1)) {
2523
+ diff.added[key] = value;
2524
+ } else if (JSON.stringify(state1[key]) !== JSON.stringify(value)) {
2525
+ diff.modified[key] = { old: state1[key], new: value };
2526
+ }
2527
+ }
2528
+ for (const key of Object.keys(state1)) {
2529
+ if (!(key in state2)) {
2530
+ diff.removed.push(key);
2531
+ }
2532
+ }
2533
+ return diff;
2534
+ }
2535
+ /**
2536
+ * Reconcile states using last-write-wins strategy
2537
+ */
2538
+ reconcileLastWriteWins(versions) {
2539
+ if (versions.length === 0) {
2540
+ throw new Error("No versions to reconcile");
2541
+ }
2542
+ const sorted = [...versions].sort(
2543
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
2544
+ );
2545
+ const latest = sorted[0];
2546
+ const conflictsResolved = versions.length - 1;
2547
+ const result = {
2548
+ success: true,
2549
+ mergedState: latest.data,
2550
+ conflictsResolved,
2551
+ strategy: "last-write-wins",
2552
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2553
+ };
2554
+ this.reconciliationHistory.push(result);
2555
+ logger.debug("[StateReconciler] State reconciled (last-write-wins)", {
2556
+ winnerNode: latest.nodeId,
2557
+ conflictsResolved
2558
+ });
2559
+ return result;
2560
+ }
2561
+ /**
2562
+ * Reconcile states using vector clock strategy
2563
+ */
2564
+ reconcileVectorClock(versions) {
2565
+ if (versions.length === 0) {
2566
+ throw new Error("No versions to reconcile");
2567
+ }
2568
+ const sorted = [...versions].sort(
2569
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
2570
+ );
2571
+ const latest = sorted[0];
2572
+ let conflictsResolved = 0;
2573
+ for (const v of versions) {
2574
+ const timeDiff = Math.abs(
2575
+ new Date(v.timestamp).getTime() - new Date(latest.timestamp).getTime()
2576
+ );
2577
+ if (timeDiff > 100) {
2578
+ conflictsResolved++;
2579
+ }
2580
+ }
2581
+ const result = {
2582
+ success: true,
2583
+ mergedState: latest.data,
2584
+ conflictsResolved,
2585
+ strategy: "vector-clock",
2586
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2587
+ };
2588
+ this.reconciliationHistory.push(result);
2589
+ logger.debug("[StateReconciler] State reconciled (vector-clock)", {
2590
+ winnerVersion: latest.version,
2591
+ conflictsResolved
2592
+ });
2593
+ return result;
2594
+ }
2595
+ /**
2596
+ * Reconcile states using majority vote strategy
2597
+ */
2598
+ reconcileMajorityVote(versions) {
2599
+ if (versions.length === 0) {
2600
+ throw new Error("No versions to reconcile");
2601
+ }
2602
+ const hashGroups = /* @__PURE__ */ new Map();
2603
+ for (const version of versions) {
2604
+ if (!hashGroups.has(version.hash)) {
2605
+ hashGroups.set(version.hash, []);
2606
+ }
2607
+ hashGroups.get(version.hash).push(version);
2608
+ }
2609
+ let majorityVersion = null;
2610
+ let maxCount = 0;
2611
+ for (const [, versionGroup] of hashGroups) {
2612
+ if (versionGroup.length > maxCount) {
2613
+ maxCount = versionGroup.length;
2614
+ majorityVersion = versionGroup[0];
2615
+ }
2616
+ }
2617
+ if (!majorityVersion) {
2618
+ majorityVersion = versions[0];
2619
+ }
2620
+ const conflictsResolved = versions.length - maxCount;
2621
+ const result = {
2622
+ success: true,
2623
+ mergedState: majorityVersion.data,
2624
+ conflictsResolved,
2625
+ strategy: "majority-vote",
2626
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2627
+ };
2628
+ this.reconciliationHistory.push(result);
2629
+ logger.debug("[StateReconciler] State reconciled (majority-vote)", {
2630
+ majorityCount: maxCount,
2631
+ conflictsResolved
2632
+ });
2633
+ return result;
2634
+ }
2635
+ /**
2636
+ * Merge multiple states
2637
+ */
2638
+ mergeStates(states) {
2639
+ if (states.length === 0) {
2640
+ return {};
2641
+ }
2642
+ if (states.length === 1) {
2643
+ return states[0];
2644
+ }
2645
+ const merged = {};
2646
+ for (const state of states) {
2647
+ if (typeof state === "object" && state !== null) {
2648
+ Object.assign(merged, state);
2649
+ }
2650
+ }
2651
+ return merged;
2652
+ }
2653
+ /**
2654
+ * Validate state after reconciliation
2655
+ */
2656
+ validateState(state) {
2657
+ const errors = [];
2658
+ if (state === null) {
2659
+ errors.push("State is null");
2660
+ } else if (state === void 0) {
2661
+ errors.push("State is undefined");
2662
+ } else if (typeof state !== "object") {
2663
+ errors.push("State is not an object");
2664
+ }
2665
+ return {
2666
+ valid: errors.length === 0,
2667
+ errors
2668
+ };
2669
+ }
2670
+ /**
2671
+ * Get state versions for a key
2672
+ */
2673
+ getStateVersions(key) {
2674
+ return this.stateVersions.get(key) || [];
2675
+ }
2676
+ /**
2677
+ * Get all state versions
2678
+ */
2679
+ getAllStateVersions() {
2680
+ const result = {};
2681
+ for (const [key, versions] of this.stateVersions) {
2682
+ result[key] = [...versions];
2683
+ }
2684
+ return result;
2685
+ }
2686
+ /**
2687
+ * Get reconciliation history
2688
+ */
2689
+ getReconciliationHistory() {
2690
+ return [...this.reconciliationHistory];
2691
+ }
2692
+ /**
2693
+ * Get reconciliation statistics
2694
+ */
2695
+ getStatistics() {
2696
+ const resolvedConflicts = this.reconciliationHistory.reduce(
2697
+ (sum, r) => sum + r.conflictsResolved,
2698
+ 0
2699
+ );
2700
+ const strategyUsage = {};
2701
+ for (const result of this.reconciliationHistory) {
2702
+ strategyUsage[result.strategy] = (strategyUsage[result.strategy] || 0) + 1;
2703
+ }
2704
+ return {
2705
+ totalReconciliations: this.reconciliationHistory.length,
2706
+ successfulReconciliations: this.reconciliationHistory.filter((r) => r.success).length,
2707
+ totalConflictsResolved: resolvedConflicts,
2708
+ averageConflictsPerReconciliation: this.reconciliationHistory.length > 0 ? resolvedConflicts / this.reconciliationHistory.length : 0,
2709
+ strategyUsage,
2710
+ trackedKeys: this.stateVersions.size
2711
+ };
2712
+ }
2713
+ /**
2714
+ * Clear all state (for testing)
2715
+ */
2716
+ clear() {
2717
+ this.stateVersions.clear();
2718
+ this.reconciliationHistory = [];
2719
+ this.cryptoProvider = null;
2720
+ this.requireSignedVersions = false;
2721
+ }
2722
+ /**
2723
+ * Get the crypto provider (for advanced usage)
2724
+ */
2725
+ getCryptoProvider() {
2726
+ return this.cryptoProvider;
2727
+ }
2728
+ };
2729
+ var logger2 = getLogger();
2730
+ var OfflineOperationQueue = class extends eventemitter3.EventEmitter {
2731
+ queue = /* @__PURE__ */ new Map();
2732
+ syncingIds = /* @__PURE__ */ new Set();
2733
+ maxQueueSize = 1e3;
2734
+ defaultMaxRetries = 3;
2735
+ constructor(maxQueueSize = 1e3, defaultMaxRetries = 3) {
2736
+ super();
2737
+ this.maxQueueSize = maxQueueSize;
2738
+ this.defaultMaxRetries = defaultMaxRetries;
2739
+ logger2.debug("[OfflineOperationQueue] Initialized", {
2740
+ maxQueueSize,
2741
+ defaultMaxRetries
2742
+ });
2743
+ }
2744
+ /**
2745
+ * Add operation to the queue
2746
+ */
2747
+ enqueue(type, data, sessionId, priority = "normal", maxRetries) {
2748
+ if (this.queue.size >= this.maxQueueSize) {
2749
+ const oldest = this.findOldestLowPriority();
2750
+ if (oldest) {
2751
+ this.queue.delete(oldest.id);
2752
+ logger2.warn("[OfflineOperationQueue] Queue full, removed oldest", {
2753
+ removedId: oldest.id
2754
+ });
2755
+ }
2756
+ }
2757
+ const operation = {
2758
+ id: `op-${Date.now()}-${Math.random().toString(36).slice(2)}`,
2759
+ type,
2760
+ data,
2761
+ sessionId,
2762
+ priority,
2763
+ createdAt: Date.now(),
2764
+ retryCount: 0,
2765
+ maxRetries: maxRetries ?? this.defaultMaxRetries,
2766
+ status: "pending"
2767
+ };
2768
+ this.queue.set(operation.id, operation);
2769
+ this.emit("operation-added", operation);
2770
+ logger2.debug("[OfflineOperationQueue] Operation enqueued", {
2771
+ id: operation.id,
2772
+ type,
2773
+ priority,
2774
+ queueSize: this.queue.size
2775
+ });
2776
+ return operation;
2777
+ }
2778
+ /**
2779
+ * Get next operations to sync (by priority)
2780
+ */
2781
+ getNextBatch(batchSize = 10) {
2782
+ const pending = Array.from(this.queue.values()).filter((op) => op.status === "pending" && !this.syncingIds.has(op.id)).sort((a, b) => {
2783
+ const priorityOrder = { high: 0, normal: 1, low: 2 };
2784
+ const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
2785
+ if (priorityDiff !== 0) return priorityDiff;
2786
+ return a.createdAt - b.createdAt;
2787
+ });
2788
+ return pending.slice(0, batchSize);
2789
+ }
2790
+ /**
2791
+ * Mark operations as syncing
2792
+ */
2793
+ markSyncing(operationIds) {
2794
+ for (const id of operationIds) {
2795
+ const op = this.queue.get(id);
2796
+ if (op) {
2797
+ op.status = "syncing";
2798
+ this.syncingIds.add(id);
2799
+ }
2800
+ }
2801
+ }
2802
+ /**
2803
+ * Mark operation as synced
2804
+ */
2805
+ markSynced(operationId) {
2806
+ const op = this.queue.get(operationId);
2807
+ if (op) {
2808
+ op.status = "synced";
2809
+ this.syncingIds.delete(operationId);
2810
+ this.emit("operation-synced", op);
2811
+ setTimeout(() => {
2812
+ this.queue.delete(operationId);
2813
+ if (this.getPendingCount() === 0) {
2814
+ this.emit("queue-empty");
2815
+ }
2816
+ }, 1e3);
2817
+ }
2818
+ }
2819
+ /**
2820
+ * Mark operation as failed
2821
+ */
2822
+ markFailed(operationId, error) {
2823
+ const op = this.queue.get(operationId);
2824
+ if (op) {
2825
+ op.retryCount++;
2826
+ op.lastError = error.message;
2827
+ this.syncingIds.delete(operationId);
2828
+ if (op.retryCount >= op.maxRetries) {
2829
+ op.status = "failed";
2830
+ this.emit("operation-failed", op, error);
2831
+ logger2.error("[OfflineOperationQueue] Operation permanently failed", {
2832
+ id: operationId,
2833
+ retries: op.retryCount,
2834
+ error: error.message
2835
+ });
2836
+ } else {
2837
+ op.status = "pending";
2838
+ logger2.warn("[OfflineOperationQueue] Operation failed, will retry", {
2839
+ id: operationId,
2840
+ retryCount: op.retryCount,
2841
+ maxRetries: op.maxRetries
2842
+ });
2843
+ }
2844
+ }
2845
+ }
2846
+ /**
2847
+ * Get operation by ID
2848
+ */
2849
+ getOperation(operationId) {
2850
+ return this.queue.get(operationId);
2851
+ }
2852
+ /**
2853
+ * Get all pending operations
2854
+ */
2855
+ getPendingOperations() {
2856
+ return Array.from(this.queue.values()).filter(
2857
+ (op) => op.status === "pending"
2858
+ );
2859
+ }
2860
+ /**
2861
+ * Get pending count
2862
+ */
2863
+ getPendingCount() {
2864
+ return Array.from(this.queue.values()).filter(
2865
+ (op) => op.status === "pending"
2866
+ ).length;
2867
+ }
2868
+ /**
2869
+ * Get queue statistics
2870
+ */
2871
+ getStats() {
2872
+ const operations = Array.from(this.queue.values());
2873
+ const pending = operations.filter((op) => op.status === "pending").length;
2874
+ const syncing = operations.filter((op) => op.status === "syncing").length;
2875
+ const failed = operations.filter((op) => op.status === "failed").length;
2876
+ const synced = operations.filter((op) => op.status === "synced").length;
2877
+ const pendingOps = operations.filter((op) => op.status === "pending");
2878
+ const oldestPendingMs = pendingOps.length > 0 ? Date.now() - Math.min(...pendingOps.map((op) => op.createdAt)) : 0;
2879
+ const averageRetries = operations.length > 0 ? operations.reduce((sum, op) => sum + op.retryCount, 0) / operations.length : 0;
2880
+ return {
2881
+ pending,
2882
+ syncing,
2883
+ failed,
2884
+ synced,
2885
+ totalOperations: operations.length,
2886
+ oldestPendingMs,
2887
+ averageRetries
2888
+ };
2889
+ }
2890
+ /**
2891
+ * Clear all operations
2892
+ */
2893
+ clear() {
2894
+ this.queue.clear();
2895
+ this.syncingIds.clear();
2896
+ logger2.debug("[OfflineOperationQueue] Queue cleared");
2897
+ }
2898
+ /**
2899
+ * Clear failed operations
2900
+ */
2901
+ clearFailed() {
2902
+ for (const [id, op] of this.queue.entries()) {
2903
+ if (op.status === "failed") {
2904
+ this.queue.delete(id);
2905
+ }
2906
+ }
2907
+ }
2908
+ /**
2909
+ * Retry failed operations
2910
+ */
2911
+ retryFailed() {
2912
+ for (const op of this.queue.values()) {
2913
+ if (op.status === "failed") {
2914
+ op.status = "pending";
2915
+ op.retryCount = 0;
2916
+ }
2917
+ }
2918
+ }
2919
+ /**
2920
+ * Find oldest low-priority operation
2921
+ */
2922
+ findOldestLowPriority() {
2923
+ const lowPriority = Array.from(this.queue.values()).filter((op) => op.priority === "low" && op.status === "pending").sort((a, b) => a.createdAt - b.createdAt);
2924
+ return lowPriority[0] ?? null;
2925
+ }
2926
+ /**
2927
+ * Export queue for persistence
2928
+ */
2929
+ export() {
2930
+ return Array.from(this.queue.values());
2931
+ }
2932
+ /**
2933
+ * Import queue from persistence
2934
+ */
2935
+ import(operations) {
2936
+ for (const op of operations) {
2937
+ this.queue.set(op.id, op);
2938
+ }
2939
+ logger2.debug("[OfflineOperationQueue] Imported operations", {
2940
+ count: operations.length
2941
+ });
2942
+ }
2943
+ };
2944
+ var offlineQueueInstance = null;
2945
+ function getOfflineOperationQueue() {
2946
+ if (!offlineQueueInstance) {
2947
+ offlineQueueInstance = new OfflineOperationQueue();
2948
+ }
2949
+ return offlineQueueInstance;
2950
+ }
2951
+ function resetOfflineOperationQueue() {
2952
+ offlineQueueInstance = null;
2953
+ }
2954
+
2955
+ // src/compression/CompressionEngine.ts
2956
+ var logger3 = getLogger();
2957
+ var CompressionEngine = class {
2958
+ stats = {
2959
+ totalCompressed: 0,
2960
+ totalDecompressed: 0,
2961
+ totalOriginalBytes: 0,
2962
+ totalCompressedBytes: 0,
2963
+ averageCompressionRatio: 0,
2964
+ compressionTimeMs: 0,
2965
+ decompressionTimeMs: 0
2966
+ };
2967
+ preferredAlgorithm = "gzip";
2968
+ constructor(preferredAlgorithm = "gzip") {
2969
+ this.preferredAlgorithm = preferredAlgorithm;
2970
+ logger3.debug("[CompressionEngine] Initialized", {
2971
+ algorithm: preferredAlgorithm,
2972
+ supportsNative: this.supportsNativeCompression()
2973
+ });
2974
+ }
2975
+ /**
2976
+ * Check if native compression is available
2977
+ */
2978
+ supportsNativeCompression() {
2979
+ return typeof CompressionStream !== "undefined" && typeof DecompressionStream !== "undefined";
2980
+ }
2981
+ /**
2982
+ * Compress data
2983
+ */
2984
+ async compress(data) {
2985
+ const startTime = performance.now();
2986
+ const inputData = typeof data === "string" ? new TextEncoder().encode(data) : data;
2987
+ const originalSize = inputData.byteLength;
2988
+ let compressed;
2989
+ let algorithm = this.preferredAlgorithm;
2990
+ if (this.supportsNativeCompression()) {
2991
+ try {
2992
+ compressed = await this.compressNative(inputData, this.preferredAlgorithm);
2993
+ } catch (error) {
2994
+ logger3.warn("[CompressionEngine] Native compression failed, using fallback", error);
2995
+ compressed = inputData;
2996
+ algorithm = "none";
2997
+ }
2998
+ } else {
2999
+ compressed = inputData;
3000
+ algorithm = "none";
3001
+ }
3002
+ const compressionRatio = originalSize > 0 ? 1 - compressed.byteLength / originalSize : 0;
3003
+ const batch = {
3004
+ id: `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`,
3005
+ compressed,
3006
+ originalSize,
3007
+ compressedSize: compressed.byteLength,
3008
+ compressionRatio,
3009
+ algorithm,
3010
+ timestamp: Date.now()
3011
+ };
3012
+ const elapsed = performance.now() - startTime;
3013
+ this.stats.totalCompressed++;
3014
+ this.stats.totalOriginalBytes += originalSize;
3015
+ this.stats.totalCompressedBytes += compressed.byteLength;
3016
+ this.stats.compressionTimeMs += elapsed;
3017
+ this.updateAverageRatio();
3018
+ logger3.debug("[CompressionEngine] Compressed", {
3019
+ original: originalSize,
3020
+ compressed: compressed.byteLength,
3021
+ ratio: (compressionRatio * 100).toFixed(1) + "%",
3022
+ algorithm,
3023
+ timeMs: elapsed.toFixed(2)
3024
+ });
3025
+ return batch;
3026
+ }
3027
+ /**
3028
+ * Decompress data
3029
+ */
3030
+ async decompress(batch) {
3031
+ const startTime = performance.now();
3032
+ let decompressed;
3033
+ if (batch.algorithm === "none") {
3034
+ decompressed = batch.compressed;
3035
+ } else if (this.supportsNativeCompression()) {
3036
+ try {
3037
+ decompressed = await this.decompressNative(
3038
+ batch.compressed,
3039
+ batch.algorithm
3040
+ );
3041
+ } catch (error) {
3042
+ logger3.warn("[CompressionEngine] Native decompression failed", error);
3043
+ throw error;
3044
+ }
3045
+ } else {
3046
+ throw new Error("Native decompression not available");
3047
+ }
3048
+ const elapsed = performance.now() - startTime;
3049
+ this.stats.totalDecompressed++;
3050
+ this.stats.decompressionTimeMs += elapsed;
3051
+ logger3.debug("[CompressionEngine] Decompressed", {
3052
+ compressed: batch.compressedSize,
3053
+ decompressed: decompressed.byteLength,
3054
+ algorithm: batch.algorithm,
3055
+ timeMs: elapsed.toFixed(2)
3056
+ });
3057
+ return decompressed;
3058
+ }
3059
+ /**
3060
+ * Compress using native CompressionStream
3061
+ */
3062
+ async compressNative(data, algorithm) {
3063
+ const stream = new CompressionStream(algorithm);
3064
+ const writer = stream.writable.getWriter();
3065
+ const reader = stream.readable.getReader();
3066
+ writer.write(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
3067
+ writer.close();
3068
+ const chunks = [];
3069
+ let done = false;
3070
+ while (!done) {
3071
+ const result = await reader.read();
3072
+ done = result.done;
3073
+ if (result.value) {
3074
+ chunks.push(result.value);
3075
+ }
3076
+ }
3077
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
3078
+ const combined = new Uint8Array(totalLength);
3079
+ let offset = 0;
3080
+ for (const chunk of chunks) {
3081
+ combined.set(chunk, offset);
3082
+ offset += chunk.length;
3083
+ }
3084
+ return combined;
3085
+ }
3086
+ /**
3087
+ * Decompress using native DecompressionStream
3088
+ */
3089
+ async decompressNative(data, algorithm) {
3090
+ const stream = new DecompressionStream(algorithm);
3091
+ const writer = stream.writable.getWriter();
3092
+ const reader = stream.readable.getReader();
3093
+ writer.write(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
3094
+ writer.close();
3095
+ const chunks = [];
3096
+ let done = false;
3097
+ while (!done) {
3098
+ const result = await reader.read();
3099
+ done = result.done;
3100
+ if (result.value) {
3101
+ chunks.push(result.value);
3102
+ }
3103
+ }
3104
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
3105
+ const combined = new Uint8Array(totalLength);
3106
+ let offset = 0;
3107
+ for (const chunk of chunks) {
3108
+ combined.set(chunk, offset);
3109
+ offset += chunk.length;
3110
+ }
3111
+ return combined;
3112
+ }
3113
+ /**
3114
+ * Split compressed batch into chunks for transmission
3115
+ */
3116
+ splitIntoChunks(batch, chunkSize = 64 * 1024) {
3117
+ const chunks = [];
3118
+ const data = batch.compressed;
3119
+ const total = Math.ceil(data.byteLength / chunkSize);
3120
+ for (let i = 0; i < total; i++) {
3121
+ const start = i * chunkSize;
3122
+ const end = Math.min(start + chunkSize, data.byteLength);
3123
+ const chunkData = data.slice(start, end);
3124
+ chunks.push({
3125
+ chunkId: `${batch.id}-chunk-${i}`,
3126
+ batchId: batch.id,
3127
+ data: chunkData,
3128
+ index: i,
3129
+ total,
3130
+ checksum: this.simpleChecksum(chunkData)
3131
+ });
3132
+ }
3133
+ return chunks;
3134
+ }
3135
+ /**
3136
+ * Reassemble chunks into compressed batch
3137
+ */
3138
+ reassembleChunks(chunks) {
3139
+ const sorted = [...chunks].sort((a, b) => a.index - b.index);
3140
+ const total = sorted[0]?.total ?? 0;
3141
+ if (sorted.length !== total) {
3142
+ throw new Error(`Missing chunks: got ${sorted.length}, expected ${total}`);
3143
+ }
3144
+ const totalLength = sorted.reduce((sum, chunk) => sum + chunk.data.length, 0);
3145
+ const combined = new Uint8Array(totalLength);
3146
+ let offset = 0;
3147
+ for (const chunk of sorted) {
3148
+ combined.set(chunk.data, offset);
3149
+ offset += chunk.data.length;
3150
+ }
3151
+ return combined;
3152
+ }
3153
+ /**
3154
+ * Simple checksum for chunk verification
3155
+ */
3156
+ simpleChecksum(data) {
3157
+ let hash = 0;
3158
+ for (let i = 0; i < data.length; i++) {
3159
+ hash = (hash << 5) - hash + data[i] | 0;
3160
+ }
3161
+ return hash.toString(16);
3162
+ }
3163
+ /**
3164
+ * Update average compression ratio
3165
+ */
3166
+ updateAverageRatio() {
3167
+ if (this.stats.totalOriginalBytes > 0) {
3168
+ this.stats.averageCompressionRatio = 1 - this.stats.totalCompressedBytes / this.stats.totalOriginalBytes;
3169
+ }
3170
+ }
3171
+ /**
3172
+ * Get statistics
3173
+ */
3174
+ getStats() {
3175
+ return { ...this.stats };
3176
+ }
3177
+ /**
3178
+ * Reset statistics
3179
+ */
3180
+ resetStats() {
3181
+ this.stats = {
3182
+ totalCompressed: 0,
3183
+ totalDecompressed: 0,
3184
+ totalOriginalBytes: 0,
3185
+ totalCompressedBytes: 0,
3186
+ averageCompressionRatio: 0,
3187
+ compressionTimeMs: 0,
3188
+ decompressionTimeMs: 0
3189
+ };
3190
+ }
3191
+ };
3192
+ var compressionEngineInstance = null;
3193
+ function getCompressionEngine() {
3194
+ if (!compressionEngineInstance) {
3195
+ compressionEngineInstance = new CompressionEngine();
3196
+ }
3197
+ return compressionEngineInstance;
3198
+ }
3199
+ function resetCompressionEngine() {
3200
+ compressionEngineInstance = null;
3201
+ }
3202
+
3203
+ // src/compression/DeltaSyncOptimizer.ts
3204
+ var logger4 = getLogger();
3205
+ var DeltaSyncOptimizer = class {
3206
+ operationHistory = /* @__PURE__ */ new Map();
3207
+ stats = {
3208
+ totalOperations: 0,
3209
+ totalFull: 0,
3210
+ totalDelta: 0,
3211
+ totalOriginalSize: 0,
3212
+ totalDeltaSize: 0,
3213
+ averageReductionPercent: 0,
3214
+ lastSyncTime: 0,
3215
+ fullOperationThreshold: 1e3
3216
+ // Force full if delta > 1KB
3217
+ };
3218
+ constructor(fullOperationThreshold = 1e3) {
3219
+ this.stats.fullOperationThreshold = fullOperationThreshold;
3220
+ logger4.debug("[DeltaSyncOptimizer] Initialized", {
3221
+ threshold: fullOperationThreshold
3222
+ });
3223
+ }
3224
+ /**
3225
+ * Compute delta for single operation
3226
+ */
3227
+ computeDelta(operation) {
3228
+ const operationJson = JSON.stringify(operation);
3229
+ const originalSize = new TextEncoder().encode(operationJson).byteLength;
3230
+ const previous = this.operationHistory.get(operation.id);
3231
+ if (!previous) {
3232
+ const delta = {
3233
+ id: `delta-${Date.now()}-${Math.random().toString(36).slice(2)}`,
3234
+ type: "full",
3235
+ operationId: operation.id,
3236
+ operationType: operation.type,
3237
+ sessionId: operation.sessionId,
3238
+ timestamp: Date.now(),
3239
+ fullData: operation.data,
3240
+ priority: operation.priority
3241
+ };
3242
+ this.stats.totalOperations++;
3243
+ this.stats.totalFull++;
3244
+ this.stats.totalOriginalSize += originalSize;
3245
+ const deltaSize2 = new TextEncoder().encode(
3246
+ JSON.stringify(delta)
3247
+ ).byteLength;
3248
+ this.stats.totalDeltaSize += deltaSize2;
3249
+ this.operationHistory.set(operation.id, operation);
3250
+ return delta;
3251
+ }
3252
+ const changes = {};
3253
+ const changeMask = [];
3254
+ let hasMeaningfulChanges = false;
3255
+ for (const [key, value] of Object.entries(operation.data)) {
3256
+ const oldValue = previous.data[key];
3257
+ if (!this.deepEqual(value, oldValue)) {
3258
+ changes[key] = value;
3259
+ changeMask.push(key);
3260
+ hasMeaningfulChanges = true;
3261
+ }
3262
+ }
3263
+ for (const key of Object.keys(previous.data)) {
3264
+ if (!(key in operation.data)) {
3265
+ changes[key] = null;
3266
+ changeMask.push(`${key}:deleted`);
3267
+ hasMeaningfulChanges = true;
3268
+ }
3269
+ }
3270
+ const deltaData = {
3271
+ id: `delta-${Date.now()}-${Math.random().toString(36).slice(2)}`,
3272
+ type: "delta",
3273
+ operationId: operation.id,
3274
+ operationType: operation.type,
3275
+ sessionId: operation.sessionId,
3276
+ timestamp: Date.now(),
3277
+ changes: hasMeaningfulChanges ? changes : void 0,
3278
+ changeMask: hasMeaningfulChanges ? changeMask : void 0,
3279
+ priority: operation.priority
3280
+ };
3281
+ const deltaSize = new TextEncoder().encode(
3282
+ JSON.stringify(deltaData)
3283
+ ).byteLength;
3284
+ const finalDelta = deltaSize > this.stats.fullOperationThreshold ? {
3285
+ ...deltaData,
3286
+ type: "full",
3287
+ fullData: operation.data,
3288
+ changes: void 0,
3289
+ changeMask: void 0
3290
+ } : deltaData;
3291
+ this.stats.totalOperations++;
3292
+ if (finalDelta.type === "full") {
3293
+ this.stats.totalFull++;
3294
+ } else {
3295
+ this.stats.totalDelta++;
3296
+ }
3297
+ this.stats.totalOriginalSize += originalSize;
3298
+ this.stats.totalDeltaSize += deltaSize;
3299
+ this.operationHistory.set(operation.id, operation);
3300
+ return finalDelta;
3301
+ }
3302
+ /**
3303
+ * Compute deltas for batch of operations
3304
+ */
3305
+ computeBatchDeltas(operations) {
3306
+ const deltas = operations.map((op) => this.computeDelta(op));
3307
+ const totalOriginalSize = operations.reduce(
3308
+ (sum, op) => sum + new TextEncoder().encode(JSON.stringify(op)).byteLength,
3309
+ 0
3310
+ );
3311
+ const totalDeltaSize = deltas.reduce(
3312
+ (sum, delta) => sum + new TextEncoder().encode(JSON.stringify(delta)).byteLength,
3313
+ 0
3314
+ );
3315
+ const reductionPercent = totalOriginalSize > 0 ? Math.round(
3316
+ (totalOriginalSize - totalDeltaSize) / totalOriginalSize * 100
3317
+ ) : 0;
3318
+ const batch = {
3319
+ batchId: `batch-${Date.now()}-${Math.random().toString(36).slice(2)}`,
3320
+ operations: deltas,
3321
+ timestamp: Date.now(),
3322
+ totalOriginalSize,
3323
+ totalDeltaSize,
3324
+ reductionPercent
3325
+ };
3326
+ logger4.debug("[DeltaSyncOptimizer] Batch computed", {
3327
+ operations: operations.length,
3328
+ reduction: reductionPercent,
3329
+ size: totalDeltaSize
3330
+ });
3331
+ return batch;
3332
+ }
3333
+ /**
3334
+ * Decompress delta operation back to full operation
3335
+ */
3336
+ decompressDelta(delta) {
3337
+ if (delta.type === "full") {
3338
+ return {
3339
+ id: delta.operationId,
3340
+ type: delta.operationType,
3341
+ sessionId: delta.sessionId,
3342
+ data: delta.fullData || {},
3343
+ status: "pending",
3344
+ createdAt: delta.timestamp
3345
+ };
3346
+ }
3347
+ const previous = this.operationHistory.get(delta.operationId);
3348
+ if (!previous) {
3349
+ logger4.warn("[DeltaSyncOptimizer] Cannot decompress - no history", {
3350
+ operationId: delta.operationId
3351
+ });
3352
+ return {
3353
+ id: delta.operationId,
3354
+ type: delta.operationType,
3355
+ sessionId: delta.sessionId,
3356
+ data: delta.changes || {},
3357
+ status: "pending",
3358
+ createdAt: delta.timestamp
3359
+ };
3360
+ }
3361
+ const reconstructed = {
3362
+ ...previous,
3363
+ data: {
3364
+ ...previous.data,
3365
+ ...delta.changes || {}
3366
+ }
3367
+ };
3368
+ if (delta.changes) {
3369
+ for (const [key, value] of Object.entries(delta.changes)) {
3370
+ if (value === null) {
3371
+ delete reconstructed.data[key];
3372
+ }
3373
+ }
3374
+ }
3375
+ return reconstructed;
3376
+ }
3377
+ /**
3378
+ * Update history after successful sync
3379
+ */
3380
+ updateHistory(operations) {
3381
+ for (const op of operations) {
3382
+ this.operationHistory.set(op.id, op);
3383
+ }
3384
+ logger4.debug("[DeltaSyncOptimizer] History updated", {
3385
+ count: operations.length,
3386
+ totalHistorySize: this.operationHistory.size
3387
+ });
3388
+ }
3389
+ /**
3390
+ * Clear history for specific operations
3391
+ */
3392
+ clearHistory(operationIds) {
3393
+ for (const id of operationIds) {
3394
+ this.operationHistory.delete(id);
3395
+ }
3396
+ logger4.debug("[DeltaSyncOptimizer] History cleared", {
3397
+ cleared: operationIds.length,
3398
+ remaining: this.operationHistory.size
3399
+ });
3400
+ }
3401
+ /**
3402
+ * Get current performance statistics
3403
+ */
3404
+ getStats() {
3405
+ if (this.stats.totalOperations > 0) {
3406
+ this.stats.averageReductionPercent = Math.round(
3407
+ (this.stats.totalOriginalSize - this.stats.totalDeltaSize) / this.stats.totalOriginalSize * 100
3408
+ );
3409
+ }
3410
+ return { ...this.stats };
3411
+ }
3412
+ /**
3413
+ * Reset statistics
3414
+ */
3415
+ resetStats() {
3416
+ this.stats = {
3417
+ totalOperations: 0,
3418
+ totalFull: 0,
3419
+ totalDelta: 0,
3420
+ totalOriginalSize: 0,
3421
+ totalDeltaSize: 0,
3422
+ averageReductionPercent: 0,
3423
+ lastSyncTime: 0,
3424
+ fullOperationThreshold: this.stats.fullOperationThreshold
3425
+ };
3426
+ logger4.debug("[DeltaSyncOptimizer] Stats reset");
3427
+ }
3428
+ /**
3429
+ * Set the full operation threshold
3430
+ */
3431
+ setFullOperationThreshold(bytes) {
3432
+ this.stats.fullOperationThreshold = bytes;
3433
+ logger4.debug("[DeltaSyncOptimizer] Threshold updated", { bytes });
3434
+ }
3435
+ /**
3436
+ * Get history size for memory monitoring
3437
+ */
3438
+ getHistorySize() {
3439
+ return this.operationHistory.size;
3440
+ }
3441
+ /**
3442
+ * Get memory footprint estimate
3443
+ */
3444
+ getMemoryEstimate() {
3445
+ let totalBytes = 0;
3446
+ for (const op of this.operationHistory.values()) {
3447
+ totalBytes += new TextEncoder().encode(JSON.stringify(op)).byteLength;
3448
+ }
3449
+ return totalBytes;
3450
+ }
3451
+ /**
3452
+ * Deep equality check for nested objects
3453
+ */
3454
+ deepEqual(a, b) {
3455
+ if (a === b) return true;
3456
+ if (a == null || b == null) return false;
3457
+ if (typeof a !== "object" || typeof b !== "object") return false;
3458
+ const aObj = a;
3459
+ const bObj = b;
3460
+ const aKeys = Object.keys(aObj);
3461
+ const bKeys = Object.keys(bObj);
3462
+ if (aKeys.length !== bKeys.length) return false;
3463
+ for (const key of aKeys) {
3464
+ if (!this.deepEqual(aObj[key], bObj[key])) {
3465
+ return false;
3466
+ }
3467
+ }
3468
+ return true;
3469
+ }
3470
+ };
3471
+ var deltaSyncInstance = null;
3472
+ function getDeltaSyncOptimizer(threshold) {
3473
+ if (!deltaSyncInstance) {
3474
+ deltaSyncInstance = new DeltaSyncOptimizer(threshold);
3475
+ }
3476
+ return deltaSyncInstance;
3477
+ }
3478
+ function resetDeltaSyncOptimizer() {
3479
+ deltaSyncInstance = null;
3480
+ }
3481
+
3482
+ // src/optimization/PrefetchingEngine.ts
3483
+ var logger5 = getLogger();
3484
+ var PrefetchingEngine = class {
3485
+ operationHistory = [];
3486
+ patterns = /* @__PURE__ */ new Map();
3487
+ prefetchCache = /* @__PURE__ */ new Map();
3488
+ maxHistoryEntries = 1e3;
3489
+ maxCachePerType = 5;
3490
+ prefetchTTL = 5 * 60 * 1e3;
3491
+ // 5 minutes
3492
+ predictionThreshold = 0.3;
3493
+ stats = {
3494
+ totalPrefetched: 0,
3495
+ totalHits: 0,
3496
+ totalMisses: 0,
3497
+ totalOverwrites: 0,
3498
+ hitRatio: 0,
3499
+ bandwidthSaved: 0,
3500
+ patternsDetected: 0,
3501
+ predictionAccuracy: 0
3502
+ };
3503
+ lastPredictionTime = 0;
3504
+ predictionInterval = 30 * 1e3;
3505
+ constructor() {
3506
+ logger5.debug("[PrefetchingEngine] Initialized", {
3507
+ ttl: this.prefetchTTL,
3508
+ threshold: this.predictionThreshold
3509
+ });
3510
+ }
3511
+ /**
3512
+ * Record operation for pattern analysis
3513
+ */
3514
+ recordOperation(operationType, size) {
3515
+ const now = Date.now();
3516
+ this.operationHistory.push({
3517
+ type: operationType,
3518
+ timestamp: now,
3519
+ size
3520
+ });
3521
+ if (this.operationHistory.length > this.maxHistoryEntries) {
3522
+ this.operationHistory.shift();
3523
+ }
3524
+ if (Math.random() < 0.1) {
3525
+ this.cleanExpiredPrefetches();
3526
+ }
3527
+ logger5.debug("[PrefetchingEngine] Operation recorded", {
3528
+ type: operationType,
3529
+ size,
3530
+ historySize: this.operationHistory.length
3531
+ });
3532
+ }
3533
+ /**
3534
+ * Analyze patterns in operation history
3535
+ */
3536
+ analyzePatterns() {
3537
+ if (this.operationHistory.length < 5) {
3538
+ return;
3539
+ }
3540
+ const patterns = /* @__PURE__ */ new Map();
3541
+ for (let length = 2; length <= 3; length++) {
3542
+ for (let i = 0; i < this.operationHistory.length - length; i++) {
3543
+ const sequence = this.operationHistory.slice(i, i + length).map((op) => op.type);
3544
+ const key = sequence.join(" \u2192 ");
3545
+ if (!patterns.has(key)) {
3546
+ patterns.set(key, {
3547
+ sequence,
3548
+ frequency: 0,
3549
+ probability: 0,
3550
+ lastOccurred: 0,
3551
+ avgIntervalMs: 0
3552
+ });
3553
+ }
3554
+ const pattern = patterns.get(key);
3555
+ pattern.frequency++;
3556
+ pattern.lastOccurred = Date.now();
3557
+ }
3558
+ }
3559
+ const totalSequences = this.operationHistory.length;
3560
+ for (const [key, pattern] of patterns.entries()) {
3561
+ pattern.probability = Math.min(1, pattern.frequency / totalSequences);
3562
+ }
3563
+ this.patterns = patterns;
3564
+ this.stats.patternsDetected = patterns.size;
3565
+ logger5.debug("[PrefetchingEngine] Patterns analyzed", {
3566
+ patternsFound: patterns.size
3567
+ });
3568
+ }
3569
+ /**
3570
+ * Predict next operations
3571
+ */
3572
+ predictNextOperations(recentOperations) {
3573
+ const now = Date.now();
3574
+ if (now - this.lastPredictionTime > this.predictionInterval) {
3575
+ this.analyzePatterns();
3576
+ this.lastPredictionTime = now;
3577
+ }
3578
+ if (this.patterns.size === 0) {
3579
+ return [];
3580
+ }
3581
+ const predictions = [];
3582
+ const recentTypeSequence = recentOperations.slice(-3).map((op) => op.type).join(" \u2192 ");
3583
+ for (const [key, pattern] of this.patterns.entries()) {
3584
+ if (key.includes(recentTypeSequence)) {
3585
+ const nextType = pattern.sequence[pattern.sequence.length - 1];
3586
+ const prediction = {
3587
+ operationType: nextType,
3588
+ probability: pattern.probability,
3589
+ reason: `Detected pattern: ${key}`,
3590
+ shouldPrefetch: pattern.probability > this.predictionThreshold,
3591
+ estimatedTimeMs: pattern.avgIntervalMs
3592
+ };
3593
+ predictions.push(prediction);
3594
+ }
3595
+ }
3596
+ const deduped = Array.from(
3597
+ new Map(predictions.map((p) => [p.operationType, p])).values()
3598
+ ).sort((a, b) => b.probability - a.probability);
3599
+ logger5.debug("[PrefetchingEngine] Predictions", {
3600
+ predictions: deduped.slice(0, 3).map((p) => ({
3601
+ type: p.operationType,
3602
+ probability: (p.probability * 100).toFixed(1) + "%"
3603
+ }))
3604
+ });
3605
+ return deduped;
3606
+ }
3607
+ /**
3608
+ * Add prefetched batch
3609
+ */
3610
+ addPrefetchedBatch(operationType, compressed, originalSize) {
3611
+ if (!this.prefetchCache.has(operationType)) {
3612
+ this.prefetchCache.set(operationType, []);
3613
+ }
3614
+ const cache = this.prefetchCache.get(operationType);
3615
+ if (cache.length >= this.maxCachePerType) {
3616
+ const oldest = cache.shift();
3617
+ if (oldest.hitCount === 0) {
3618
+ this.stats.totalMisses++;
3619
+ } else {
3620
+ this.stats.totalOverwrites++;
3621
+ }
3622
+ }
3623
+ const batch = {
3624
+ id: `prefetch-${operationType}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
3625
+ operationType,
3626
+ compressed,
3627
+ compressedSize: compressed.length,
3628
+ originalSize,
3629
+ compressionRatio: 1 - compressed.length / originalSize,
3630
+ compressed_at: Date.now(),
3631
+ created_at: Date.now(),
3632
+ ttl: this.prefetchTTL,
3633
+ expiresAt: Date.now() + this.prefetchTTL,
3634
+ hitCount: 0,
3635
+ missCount: 0
3636
+ };
3637
+ cache.push(batch);
3638
+ this.stats.totalPrefetched++;
3639
+ this.stats.bandwidthSaved += originalSize - compressed.length;
3640
+ logger5.debug("[PrefetchingEngine] Prefetched batch added", {
3641
+ type: operationType,
3642
+ id: batch.id,
3643
+ ratio: (batch.compressionRatio * 100).toFixed(1) + "%"
3644
+ });
3645
+ return batch;
3646
+ }
3647
+ /**
3648
+ * Try to use prefetched batch
3649
+ */
3650
+ getPrefetchedBatch(operationType) {
3651
+ const cache = this.prefetchCache.get(operationType);
3652
+ if (!cache || cache.length === 0) {
3653
+ return null;
3654
+ }
3655
+ const now = Date.now();
3656
+ for (let i = 0; i < cache.length; i++) {
3657
+ const batch = cache[i];
3658
+ if (batch.expiresAt > now) {
3659
+ batch.hitCount++;
3660
+ this.stats.totalHits++;
3661
+ this.updatePredictionAccuracy(true);
3662
+ logger5.debug("[PrefetchingEngine] Prefetch hit", {
3663
+ type: operationType,
3664
+ id: batch.id
3665
+ });
3666
+ return batch;
3667
+ } else {
3668
+ cache.splice(i, 1);
3669
+ i--;
3670
+ batch.missCount++;
3671
+ this.stats.totalMisses++;
3672
+ this.updatePredictionAccuracy(false);
3673
+ }
3674
+ }
3675
+ return null;
3676
+ }
3677
+ /**
3678
+ * Update prediction accuracy metric
3679
+ */
3680
+ updatePredictionAccuracy(hit) {
3681
+ const total = this.stats.totalHits + this.stats.totalMisses;
3682
+ if (total === 0) return;
3683
+ this.stats.predictionAccuracy = this.stats.totalHits / total;
3684
+ }
3685
+ /**
3686
+ * Clean expired prefetches
3687
+ */
3688
+ cleanExpiredPrefetches() {
3689
+ const now = Date.now();
3690
+ let cleanedCount = 0;
3691
+ for (const [type, cache] of this.prefetchCache.entries()) {
3692
+ for (let i = cache.length - 1; i >= 0; i--) {
3693
+ if (cache[i].expiresAt < now) {
3694
+ const batch = cache.splice(i, 1)[0];
3695
+ if (batch.hitCount === 0) {
3696
+ this.stats.totalMisses++;
3697
+ }
3698
+ cleanedCount++;
3699
+ }
3700
+ }
3701
+ if (cache.length === 0) {
3702
+ this.prefetchCache.delete(type);
3703
+ }
3704
+ }
3705
+ if (cleanedCount > 0) {
3706
+ logger5.debug("[PrefetchingEngine] Cleaned expired prefetches", {
3707
+ count: cleanedCount
3708
+ });
3709
+ }
3710
+ }
3711
+ /**
3712
+ * Get statistics
3713
+ */
3714
+ getStats() {
3715
+ const total = this.stats.totalHits + this.stats.totalMisses;
3716
+ this.stats.hitRatio = total > 0 ? this.stats.totalHits / total : 0;
3717
+ return { ...this.stats };
3718
+ }
3719
+ /**
3720
+ * Clear all caches
3721
+ */
3722
+ clear() {
3723
+ this.operationHistory = [];
3724
+ this.patterns.clear();
3725
+ this.prefetchCache.clear();
3726
+ this.stats = {
3727
+ totalPrefetched: 0,
3728
+ totalHits: 0,
3729
+ totalMisses: 0,
3730
+ totalOverwrites: 0,
3731
+ hitRatio: 0,
3732
+ bandwidthSaved: 0,
3733
+ patternsDetected: 0,
3734
+ predictionAccuracy: 0
3735
+ };
3736
+ logger5.debug("[PrefetchingEngine] Cleared all caches");
3737
+ }
3738
+ };
3739
+ var prefetchingEngineInstance = null;
3740
+ function getPrefetchingEngine() {
3741
+ if (!prefetchingEngineInstance) {
3742
+ prefetchingEngineInstance = new PrefetchingEngine();
3743
+ }
3744
+ return prefetchingEngineInstance;
3745
+ }
3746
+ function resetPrefetchingEngine() {
3747
+ prefetchingEngineInstance = null;
3748
+ }
3749
+
3750
+ // src/optimization/BatchTimingOptimizer.ts
3751
+ var logger6 = getLogger();
3752
+ var BatchTimingOptimizer = class {
3753
+ networkHistory = [];
3754
+ activityHistory = [];
3755
+ stats = {
3756
+ totalBatches: 0,
3757
+ immediateDeliveries: 0,
3758
+ deferredBatches: 0,
3759
+ averageWaitTimeMs: 0,
3760
+ averageDeliveryTimeMs: 0,
3761
+ networkWindowsUsed: 0,
3762
+ congestionAvoided: 0,
3763
+ userFocusedOptimizations: 0
3764
+ };
3765
+ lastActivityTime = Date.now();
3766
+ isUserActive = true;
3767
+ congestionDetectionWindow = 60 * 1e3;
3768
+ optimalBatchSize = 50 * 1024;
3769
+ constructor() {
3770
+ logger6.debug("[BatchTimingOptimizer] Initialized", {
3771
+ congestionWindow: this.congestionDetectionWindow,
3772
+ optimalBatchSize: this.optimalBatchSize
3773
+ });
3774
+ }
3775
+ /**
3776
+ * Record network measurement
3777
+ */
3778
+ recordNetworkMeasurement(latencyMs, bandwidthMbps) {
3779
+ const quality = this.assessNetworkQuality(latencyMs, bandwidthMbps);
3780
+ this.networkHistory.push({
3781
+ latencyMs,
3782
+ bandwidthMbps,
3783
+ timestamp: Date.now(),
3784
+ quality
3785
+ });
3786
+ if (this.networkHistory.length > 100) {
3787
+ this.networkHistory.shift();
3788
+ }
3789
+ this.stats.networkWindowsUsed++;
3790
+ logger6.debug("[BatchTimingOptimizer] Network measured", {
3791
+ latency: latencyMs + "ms",
3792
+ bandwidth: bandwidthMbps.toFixed(1) + " Mbps",
3793
+ quality
3794
+ });
3795
+ }
3796
+ /**
3797
+ * Assess network quality
3798
+ */
3799
+ assessNetworkQuality(latencyMs, bandwidthMbps) {
3800
+ if (latencyMs < 20 && bandwidthMbps > 10) return "excellent";
3801
+ if (latencyMs < 50 && bandwidthMbps > 5) return "good";
3802
+ if (latencyMs < 100 && bandwidthMbps > 2) return "fair";
3803
+ return "poor";
3804
+ }
3805
+ /**
3806
+ * Detect congestion in network
3807
+ */
3808
+ detectCongestion() {
3809
+ const recentMeasurements = this.networkHistory.filter(
3810
+ (m) => Date.now() - m.timestamp < this.congestionDetectionWindow
3811
+ );
3812
+ if (recentMeasurements.length < 3) {
3813
+ return 0;
3814
+ }
3815
+ const poorCount = recentMeasurements.filter(
3816
+ (m) => m.quality === "poor"
3817
+ ).length;
3818
+ return poorCount / recentMeasurements.length;
3819
+ }
3820
+ /**
3821
+ * Find next optimal network window
3822
+ */
3823
+ findOptimalWindow() {
3824
+ const now = Date.now();
3825
+ const recentMeasurements = this.networkHistory.slice(-20);
3826
+ if (recentMeasurements.length === 0) {
3827
+ return {
3828
+ startTime: now,
3829
+ endTime: now + 1e3,
3830
+ expectedDurationMs: 1e3,
3831
+ latencyMs: 50,
3832
+ bandwidthMbps: 5,
3833
+ quality: "good",
3834
+ isStable: true,
3835
+ congestionLevel: 0,
3836
+ recommendedBatchSize: this.optimalBatchSize
3837
+ };
3838
+ }
3839
+ const avgLatency = recentMeasurements.reduce((sum, m) => sum + m.latencyMs, 0) / recentMeasurements.length;
3840
+ const avgBandwidth = recentMeasurements.reduce((sum, m) => sum + m.bandwidthMbps, 0) / recentMeasurements.length;
3841
+ const latencyVariance = Math.sqrt(
3842
+ recentMeasurements.reduce(
3843
+ (sum, m) => sum + Math.pow(m.latencyMs - avgLatency, 2),
3844
+ 0
3845
+ ) / recentMeasurements.length
3846
+ ) / avgLatency;
3847
+ const isStable = latencyVariance < 0.2;
3848
+ const congestionLevel = this.detectCongestion();
3849
+ const quality = this.assessNetworkQuality(avgLatency, avgBandwidth);
3850
+ const recommendedBatchSize = Math.max(
3851
+ 10 * 1024,
3852
+ Math.min(500 * 1024, avgBandwidth * 1024 * 100 / 8)
3853
+ );
3854
+ return {
3855
+ startTime: now,
3856
+ endTime: now + (isStable ? 30 * 1e3 : 10 * 1e3),
3857
+ expectedDurationMs: isStable ? 30 * 1e3 : 10 * 1e3,
3858
+ latencyMs: avgLatency,
3859
+ bandwidthMbps: avgBandwidth,
3860
+ quality,
3861
+ isStable,
3862
+ congestionLevel,
3863
+ recommendedBatchSize
3864
+ };
3865
+ }
3866
+ /**
3867
+ * Get scheduling decision for a batch
3868
+ */
3869
+ getSchedulingDecision(batchSize, batchPriority = "normal", isUserTriggered = false) {
3870
+ const now = Date.now();
3871
+ const currentWindow = this.findOptimalWindow();
3872
+ const congestionLevel = this.detectCongestion();
3873
+ let shouldSendNow = false;
3874
+ let recommendedDelay = 0;
3875
+ let reason = "";
3876
+ let priority = batchPriority;
3877
+ if (priority === "critical") {
3878
+ shouldSendNow = true;
3879
+ reason = "Critical operation (bypass optimization)";
3880
+ } else if (isUserTriggered && this.isUserActive) {
3881
+ shouldSendNow = true;
3882
+ reason = "User-triggered operation";
3883
+ priority = "high";
3884
+ } else if (currentWindow.quality === "excellent" || currentWindow.quality === "good") {
3885
+ if (congestionLevel < 0.3) {
3886
+ shouldSendNow = true;
3887
+ reason = "Good network conditions";
3888
+ } else {
3889
+ shouldSendNow = true;
3890
+ reason = "Good network despite some congestion";
3891
+ recommendedDelay = 1e3 + Math.random() * 2e3;
3892
+ }
3893
+ } else if (currentWindow.quality === "fair") {
3894
+ if (priority === "high") {
3895
+ shouldSendNow = true;
3896
+ reason = "High priority despite fair network";
3897
+ } else {
3898
+ shouldSendNow = false;
3899
+ reason = "Fair network: waiting for better window";
3900
+ recommendedDelay = 30 * 1e3 + Math.random() * 30 * 1e3;
3901
+ }
3902
+ } else {
3903
+ shouldSendNow = false;
3904
+ reason = "Poor network conditions: deferring";
3905
+ if (priority === "high") {
3906
+ recommendedDelay = 60 * 1e3 + Math.random() * 30 * 1e3;
3907
+ } else {
3908
+ recommendedDelay = 120 * 1e3 + Math.random() * 60 * 1e3;
3909
+ }
3910
+ }
3911
+ const estimatedDeliveryMs = batchSize / (currentWindow.bandwidthMbps * 1024 * 1024 / 8) * 1e3 + currentWindow.latencyMs + recommendedDelay;
3912
+ const decision = {
3913
+ shouldSendNow,
3914
+ nextOptimalWindowMs: now + recommendedDelay,
3915
+ recommendedDelay,
3916
+ reason,
3917
+ priority,
3918
+ estimatedDeliveryMs
3919
+ };
3920
+ logger6.debug("[BatchTimingOptimizer] Scheduling decision", {
3921
+ size: (batchSize / 1024).toFixed(1) + " KB",
3922
+ shouldSendNow,
3923
+ delay: recommendedDelay + "ms",
3924
+ reason
3925
+ });
3926
+ return decision;
3927
+ }
3928
+ /**
3929
+ * Apply scheduling and update stats
3930
+ */
3931
+ applyScheduling(batchSize, sendNow, actualDelay) {
3932
+ this.stats.totalBatches++;
3933
+ if (sendNow) {
3934
+ this.stats.immediateDeliveries++;
3935
+ } else {
3936
+ this.stats.deferredBatches++;
3937
+ }
3938
+ const totalWait = this.stats.averageWaitTimeMs * (this.stats.totalBatches - 1) + actualDelay;
3939
+ this.stats.averageWaitTimeMs = totalWait / this.stats.totalBatches;
3940
+ if (this.detectCongestion() > 0.3 && !sendNow) {
3941
+ this.stats.congestionAvoided++;
3942
+ }
3943
+ if (this.isUserActive) {
3944
+ this.stats.userFocusedOptimizations++;
3945
+ }
3946
+ this.stats.networkWindowsUsed++;
3947
+ }
3948
+ /**
3949
+ * Get optimal batch size recommendation
3950
+ */
3951
+ getOptimalBatchSize() {
3952
+ const window = this.findOptimalWindow();
3953
+ return window.recommendedBatchSize;
3954
+ }
3955
+ /**
3956
+ * Get current network window
3957
+ */
3958
+ getCurrentNetworkWindow() {
3959
+ return this.findOptimalWindow();
3960
+ }
3961
+ /**
3962
+ * Set user activity state
3963
+ */
3964
+ setUserActive(active) {
3965
+ this.isUserActive = active;
3966
+ if (active) {
3967
+ this.lastActivityTime = Date.now();
3968
+ }
3969
+ }
3970
+ /**
3971
+ * Get statistics
3972
+ */
3973
+ getStats() {
3974
+ return { ...this.stats };
3975
+ }
3976
+ /**
3977
+ * Clear history
3978
+ */
3979
+ clear() {
3980
+ this.networkHistory = [];
3981
+ this.activityHistory = [];
3982
+ this.stats = {
3983
+ totalBatches: 0,
3984
+ immediateDeliveries: 0,
3985
+ deferredBatches: 0,
3986
+ averageWaitTimeMs: 0,
3987
+ averageDeliveryTimeMs: 0,
3988
+ networkWindowsUsed: 0,
3989
+ congestionAvoided: 0,
3990
+ userFocusedOptimizations: 0
3991
+ };
3992
+ }
3993
+ };
3994
+ var batchTimingOptimizerInstance = null;
3995
+ function getBatchTimingOptimizer() {
3996
+ if (!batchTimingOptimizerInstance) {
3997
+ batchTimingOptimizerInstance = new BatchTimingOptimizer();
3998
+ }
3999
+ return batchTimingOptimizerInstance;
4000
+ }
4001
+ function resetBatchTimingOptimizer() {
4002
+ batchTimingOptimizerInstance = null;
4003
+ }
4004
+
4005
+ // src/optimization/AdaptiveCompressionOptimizer.ts
4006
+ var logger7 = getLogger();
4007
+ var AdaptiveCompressionOptimizer = class {
4008
+ currentLevel = 6;
4009
+ networkProfile = {
4010
+ estimatedSpeedKbps: 5e3,
4011
+ latencyMs: 50,
4012
+ isOnline: true,
4013
+ isWifi: false,
4014
+ isFast: true,
4015
+ isSlow: false,
4016
+ isEmpty: false
4017
+ };
4018
+ deviceProfile = {
4019
+ cpuCores: 4,
4020
+ cpuUtilization: 0.3,
4021
+ memoryAvailableMB: 512,
4022
+ memoryTotalMB: 1024,
4023
+ isConstrained: false,
4024
+ isPremium: false,
4025
+ supportsWebWorkers: true,
4026
+ supportsWebAssembly: true
4027
+ };
4028
+ compressionHistory = [];
4029
+ stats = {
4030
+ currentLevel: 6,
4031
+ averageCompressionMs: 10,
4032
+ averageRatio: 0.85,
4033
+ levelsUsed: /* @__PURE__ */ new Set([6]),
4034
+ adjustmentCount: 0,
4035
+ totalBatches: 0,
4036
+ networkCondition: "normal"
4037
+ };
4038
+ constructor() {
4039
+ logger7.debug("[AdaptiveCompressionOptimizer] Initialized", {
4040
+ level: this.currentLevel
4041
+ });
4042
+ }
4043
+ /**
4044
+ * Update network conditions
4045
+ */
4046
+ updateNetworkConditions(speedKbps, latencyMs, isOnline) {
4047
+ this.networkProfile.estimatedSpeedKbps = speedKbps;
4048
+ if (latencyMs !== void 0) {
4049
+ this.networkProfile.latencyMs = latencyMs;
4050
+ }
4051
+ if (isOnline !== void 0) {
4052
+ this.networkProfile.isOnline = isOnline;
4053
+ }
4054
+ this.networkProfile.isFast = speedKbps > 5e3;
4055
+ this.networkProfile.isSlow = speedKbps < 1e3;
4056
+ this.networkProfile.isEmpty = speedKbps < 100;
4057
+ if (isOnline === false) {
4058
+ this.stats.networkCondition = "offline";
4059
+ } else if (this.networkProfile.isSlow) {
4060
+ this.stats.networkCondition = "slow";
4061
+ } else if (this.networkProfile.isFast) {
4062
+ this.stats.networkCondition = "fast";
4063
+ } else {
4064
+ this.stats.networkCondition = "normal";
4065
+ }
4066
+ logger7.debug("[AdaptiveCompressionOptimizer] Network updated", {
4067
+ speedKbps,
4068
+ condition: this.stats.networkCondition
4069
+ });
4070
+ }
4071
+ /**
4072
+ * Update device resource usage
4073
+ */
4074
+ updateDeviceResources(cpuUtilization, memoryAvailableMB) {
4075
+ this.deviceProfile.cpuUtilization = Math.max(0, Math.min(1, cpuUtilization));
4076
+ this.deviceProfile.memoryAvailableMB = memoryAvailableMB;
4077
+ this.deviceProfile.isConstrained = memoryAvailableMB < 512;
4078
+ this.deviceProfile.isPremium = memoryAvailableMB > 2048;
4079
+ logger7.debug("[AdaptiveCompressionOptimizer] Device resources updated", {
4080
+ cpuUtilization: (cpuUtilization * 100).toFixed(1) + "%",
4081
+ memoryAvailableMB
4082
+ });
4083
+ }
4084
+ /**
4085
+ * Record compression performance
4086
+ */
4087
+ recordCompressionPerformance(level, compressionMs, ratio) {
4088
+ this.compressionHistory.push({
4089
+ level,
4090
+ ratio,
4091
+ timeMs: compressionMs,
4092
+ timestamp: Date.now()
4093
+ });
4094
+ if (this.compressionHistory.length > 100) {
4095
+ this.compressionHistory.shift();
4096
+ }
4097
+ this.stats.totalBatches++;
4098
+ this.stats.averageCompressionMs = this.compressionHistory.reduce((sum, h) => sum + h.timeMs, 0) / this.compressionHistory.length;
4099
+ this.stats.averageRatio = this.compressionHistory.reduce((sum, h) => sum + h.ratio, 0) / this.compressionHistory.length;
4100
+ }
4101
+ /**
4102
+ * Get compression recommendation based on conditions
4103
+ */
4104
+ getRecommendedLevel() {
4105
+ const networkFactor = this.calculateNetworkFactor();
4106
+ const deviceFactor = this.calculateDeviceFactor();
4107
+ const combinedFactor = (networkFactor + deviceFactor) / 2;
4108
+ const recommendedLevel = Math.max(
4109
+ 1,
4110
+ Math.min(9, Math.round(combinedFactor * 9))
4111
+ );
4112
+ const estimatedCompressionMs = this.estimateCompressionTime(recommendedLevel);
4113
+ const estimatedRatio = this.estimateCompressionRatio(recommendedLevel);
4114
+ let reason = "";
4115
+ if (networkFactor < 0.3 && deviceFactor < 0.3) {
4116
+ reason = "Slow network + constrained device: using level 1-2 (fast)";
4117
+ } else if (networkFactor > 0.7 && deviceFactor > 0.7) {
4118
+ reason = "Fast network + premium device: using level 8-9 (best compression)";
4119
+ } else if (networkFactor > 0.7) {
4120
+ reason = "Fast network: prioritizing compression ratio";
4121
+ } else if (deviceFactor < 0.3) {
4122
+ reason = "Constrained device: prioritizing speed";
4123
+ } else {
4124
+ reason = "Normal conditions: balanced compression level";
4125
+ }
4126
+ const recommendation = {
4127
+ recommendedLevel,
4128
+ reason,
4129
+ confidence: this.compressionHistory.length > 10 ? 0.9 : 0.5,
4130
+ estimatedCompressionMs,
4131
+ estimatedRatio,
4132
+ networkFactor,
4133
+ deviceFactor
4134
+ };
4135
+ logger7.debug("[AdaptiveCompressionOptimizer] Recommendation", recommendation);
4136
+ return recommendation;
4137
+ }
4138
+ /**
4139
+ * Calculate network factor (0-1)
4140
+ */
4141
+ calculateNetworkFactor() {
4142
+ if (!this.networkProfile.isOnline) return 0;
4143
+ const speedMbps = this.networkProfile.estimatedSpeedKbps / 1e3;
4144
+ if (speedMbps < 0.1) return 0;
4145
+ if (speedMbps < 1) return 0.1 + speedMbps / 1 * 0.2;
4146
+ if (speedMbps < 5) return 0.3 + (speedMbps - 1) / 4 * 0.3;
4147
+ if (speedMbps < 20) return 0.6 + (speedMbps - 5) / 15 * 0.3;
4148
+ return Math.min(1, 0.9 + (speedMbps - 20) / 200);
4149
+ }
4150
+ /**
4151
+ * Calculate device factor (0-1)
4152
+ */
4153
+ calculateDeviceFactor() {
4154
+ let factor = 0.5;
4155
+ if (this.deviceProfile.isPremium) {
4156
+ factor = 0.8;
4157
+ } else if (this.deviceProfile.isConstrained) {
4158
+ factor = 0.2;
4159
+ }
4160
+ if (this.deviceProfile.cpuUtilization > 0.8) {
4161
+ factor *= 0.7;
4162
+ } else if (this.deviceProfile.cpuUtilization < 0.2) {
4163
+ factor *= 1.1;
4164
+ }
4165
+ if (this.deviceProfile.supportsWebAssembly) {
4166
+ factor = Math.min(1, factor + 0.1);
4167
+ }
4168
+ return Math.max(0, Math.min(1, factor));
4169
+ }
4170
+ /**
4171
+ * Estimate compression time for a level (in ms)
4172
+ */
4173
+ estimateCompressionTime(level) {
4174
+ return Math.max(1, level * 2.5);
4175
+ }
4176
+ /**
4177
+ * Estimate compression ratio for a level
4178
+ */
4179
+ estimateCompressionRatio(level) {
4180
+ return 0.6 + level / 9 * 0.3;
4181
+ }
4182
+ /**
4183
+ * Apply recommendation and get new level
4184
+ */
4185
+ applyRecommendation() {
4186
+ const recommendation = this.getRecommendedLevel();
4187
+ const oldLevel = this.currentLevel;
4188
+ const shouldChange = recommendation.confidence > 0.7 || Math.abs(recommendation.recommendedLevel - oldLevel) > 2;
4189
+ if (shouldChange) {
4190
+ this.currentLevel = recommendation.recommendedLevel;
4191
+ this.stats.levelsUsed.add(this.currentLevel);
4192
+ if (oldLevel !== this.currentLevel) {
4193
+ this.stats.adjustmentCount++;
4194
+ logger7.debug("[AdaptiveCompressionOptimizer] Level adjusted", {
4195
+ from: oldLevel,
4196
+ to: this.currentLevel,
4197
+ reason: recommendation.reason
4198
+ });
4199
+ }
4200
+ }
4201
+ this.stats.currentLevel = this.currentLevel;
4202
+ return this.currentLevel;
4203
+ }
4204
+ /**
4205
+ * Get current level
4206
+ */
4207
+ getCurrentLevel() {
4208
+ return this.currentLevel;
4209
+ }
4210
+ /**
4211
+ * Get statistics
4212
+ */
4213
+ getStats() {
4214
+ return { ...this.stats };
4215
+ }
4216
+ /**
4217
+ * Get detailed analysis
4218
+ */
4219
+ getDetailedAnalysis() {
4220
+ return {
4221
+ stats: this.stats,
4222
+ network: this.networkProfile,
4223
+ device: this.deviceProfile,
4224
+ recommendation: this.getRecommendedLevel(),
4225
+ history: this.compressionHistory.slice(-20)
4226
+ };
4227
+ }
4228
+ };
4229
+ var adaptiveOptimizerInstance = null;
4230
+ function getAdaptiveCompressionOptimizer() {
4231
+ if (!adaptiveOptimizerInstance) {
4232
+ adaptiveOptimizerInstance = new AdaptiveCompressionOptimizer();
4233
+ }
4234
+ return adaptiveOptimizerInstance;
4235
+ }
4236
+ function resetAdaptiveCompressionOptimizer() {
4237
+ adaptiveOptimizerInstance = null;
4238
+ }
4239
+ var logger8 = getLogger();
4240
+ var AgentPresenceManager = class extends eventemitter3.EventEmitter {
4241
+ presences = /* @__PURE__ */ new Map();
4242
+ sessionId;
4243
+ heartbeatInterval = null;
4244
+ heartbeatTimeout = 3e4;
4245
+ inactivityThreshold = 6e4;
4246
+ constructor(sessionId) {
4247
+ super();
4248
+ this.sessionId = sessionId;
4249
+ this.startHeartbeatCheck();
4250
+ logger8.debug("[AgentPresenceManager] Initialized", { sessionId });
4251
+ }
4252
+ /**
4253
+ * Add or update agent presence
4254
+ */
4255
+ updatePresence(agentId, presence) {
4256
+ const existing = this.presences.get(agentId);
4257
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4258
+ const updated = {
4259
+ ...existing,
4260
+ ...presence,
4261
+ agentId,
4262
+ joinedAt: existing?.joinedAt ?? now,
4263
+ lastSeen: now
4264
+ };
4265
+ this.presences.set(agentId, updated);
4266
+ this.emit("presence_updated", {
4267
+ agentId,
4268
+ presence: updated
4269
+ });
4270
+ }
4271
+ /**
4272
+ * Agent joined
4273
+ */
4274
+ agentJoined(agentId, name, role = "user", metadata) {
4275
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4276
+ const presence = {
4277
+ agentId,
4278
+ name,
4279
+ role,
4280
+ status: "online",
4281
+ joinedAt: now,
4282
+ lastSeen: now,
4283
+ metadata
4284
+ };
4285
+ this.presences.set(agentId, presence);
4286
+ this.emit("agent_joined", { agentId, presence });
4287
+ logger8.debug("[AgentPresenceManager] Agent joined", { agentId, name, role });
4288
+ }
4289
+ /**
4290
+ * Agent left
4291
+ */
4292
+ agentLeft(agentId) {
4293
+ const presence = this.presences.get(agentId);
4294
+ if (presence) {
4295
+ presence.status = "offline";
4296
+ presence.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
4297
+ this.presences.set(agentId, presence);
4298
+ this.emit("agent_left", { agentId, presence });
4299
+ logger8.debug("[AgentPresenceManager] Agent left", { agentId });
4300
+ }
4301
+ }
4302
+ /**
4303
+ * Update cursor position
4304
+ */
4305
+ updateCursor(agentId, x, y, path) {
4306
+ const presence = this.presences.get(agentId);
4307
+ if (presence) {
4308
+ presence.cursorPosition = { x, y, path };
4309
+ presence.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
4310
+ this.presences.set(agentId, presence);
4311
+ this.emit("cursor_updated", {
4312
+ agentId,
4313
+ cursorPosition: presence.cursorPosition
4314
+ });
4315
+ }
4316
+ }
4317
+ /**
4318
+ * Update active section
4319
+ */
4320
+ updateActiveSection(agentId, section) {
4321
+ const presence = this.presences.get(agentId);
4322
+ if (presence) {
4323
+ presence.activeSection = section;
4324
+ presence.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
4325
+ this.presences.set(agentId, presence);
4326
+ this.emit("section_updated", {
4327
+ agentId,
4328
+ activeSection: section
4329
+ });
4330
+ }
4331
+ }
4332
+ /**
4333
+ * Update status
4334
+ */
4335
+ updateStatus(agentId, status) {
4336
+ const presence = this.presences.get(agentId);
4337
+ if (presence) {
4338
+ presence.status = status;
4339
+ presence.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
4340
+ this.presences.set(agentId, presence);
4341
+ this.emit("status_updated", { agentId, status });
4342
+ }
4343
+ }
4344
+ /**
4345
+ * Heartbeat from agent (keeps them online)
4346
+ */
4347
+ heartbeat(agentId) {
4348
+ const presence = this.presences.get(agentId);
4349
+ if (presence) {
4350
+ if (presence.status === "reconnecting") {
4351
+ presence.status = "online";
4352
+ this.emit("status_updated", { agentId, status: "online" });
4353
+ }
4354
+ presence.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
4355
+ this.presences.set(agentId, presence);
4356
+ }
4357
+ }
4358
+ /**
4359
+ * Get presence for agent
4360
+ */
4361
+ getPresence(agentId) {
4362
+ return this.presences.get(agentId);
4363
+ }
4364
+ /**
4365
+ * Get all online agents
4366
+ */
4367
+ getOnlineAgents() {
4368
+ return Array.from(this.presences.values()).filter(
4369
+ (p) => p.status === "online"
4370
+ );
4371
+ }
4372
+ /**
4373
+ * Get all agents
4374
+ */
4375
+ getAllAgents() {
4376
+ return Array.from(this.presences.values());
4377
+ }
4378
+ /**
4379
+ * Get all presences
4380
+ */
4381
+ getAllPresences() {
4382
+ return Array.from(this.presences.values());
4383
+ }
4384
+ /**
4385
+ * Get agent count
4386
+ */
4387
+ getAgentCount() {
4388
+ const counts = {
4389
+ online: 0,
4390
+ away: 0,
4391
+ offline: 0,
4392
+ reconnecting: 0
4393
+ };
4394
+ this.presences.forEach((p) => {
4395
+ counts[p.status]++;
4396
+ });
4397
+ return counts;
4398
+ }
4399
+ /**
4400
+ * Get statistics
4401
+ */
4402
+ getStats() {
4403
+ return {
4404
+ totalAgents: this.presences.size,
4405
+ onlineAgents: Array.from(this.presences.values()).filter(
4406
+ (p) => p.status === "online"
4407
+ ).length,
4408
+ offlineAgents: Array.from(this.presences.values()).filter(
4409
+ (p) => p.status === "offline"
4410
+ ).length,
4411
+ awayAgents: Array.from(this.presences.values()).filter(
4412
+ (p) => p.status === "away"
4413
+ ).length,
4414
+ reconnectingAgents: Array.from(this.presences.values()).filter(
4415
+ (p) => p.status === "reconnecting"
4416
+ ).length
4417
+ };
4418
+ }
4419
+ /**
4420
+ * Clear expired presences
4421
+ */
4422
+ clearExpiredPresences(maxAgeMs) {
4423
+ const now = Date.now();
4424
+ const toRemove = [];
4425
+ this.presences.forEach((presence, agentId) => {
4426
+ const lastSeenTime = new Date(presence.lastSeen).getTime();
4427
+ const ageMs = now - lastSeenTime;
4428
+ if (ageMs > maxAgeMs && presence.status === "offline") {
4429
+ toRemove.push(agentId);
4430
+ }
4431
+ });
4432
+ toRemove.forEach((agentId) => {
4433
+ this.presences.delete(agentId);
4434
+ });
4435
+ if (toRemove.length > 0) {
4436
+ logger8.debug("[AgentPresenceManager] Cleared expired presences", {
4437
+ count: toRemove.length
4438
+ });
4439
+ }
4440
+ }
4441
+ /**
4442
+ * Get agents by role
4443
+ */
4444
+ getByRole(role) {
4445
+ return Array.from(this.presences.values()).filter((p) => p.role === role);
4446
+ }
4447
+ /**
4448
+ * Get agents in active section
4449
+ */
4450
+ getInSection(section) {
4451
+ return Array.from(this.presences.values()).filter(
4452
+ (p) => p.activeSection === section && p.status === "online"
4453
+ );
4454
+ }
4455
+ /**
4456
+ * Get presence timeline
4457
+ */
4458
+ getPresenceStats() {
4459
+ const stats = {
4460
+ total: this.presences.size,
4461
+ online: 0,
4462
+ away: 0,
4463
+ offline: 0,
4464
+ reconnecting: 0,
4465
+ byRole: {}
4466
+ };
4467
+ this.presences.forEach((p) => {
4468
+ stats[p.status]++;
4469
+ stats.byRole[p.role] = (stats.byRole[p.role] ?? 0) + 1;
4470
+ });
4471
+ return stats;
4472
+ }
4473
+ /**
4474
+ * Start heartbeat check (mark inactive agents as away)
4475
+ */
4476
+ startHeartbeatCheck() {
4477
+ this.heartbeatInterval = setInterval(() => {
4478
+ const now = Date.now();
4479
+ this.presences.forEach((presence) => {
4480
+ const lastSeenTime = new Date(presence.lastSeen).getTime();
4481
+ const timeSinceLastSeen = now - lastSeenTime;
4482
+ if (timeSinceLastSeen > this.inactivityThreshold && presence.status === "online") {
4483
+ presence.status = "away";
4484
+ this.emit("status_updated", {
4485
+ agentId: presence.agentId,
4486
+ status: "away"
4487
+ });
4488
+ }
4489
+ if (timeSinceLastSeen > this.heartbeatTimeout && presence.status !== "offline") {
4490
+ presence.status = "reconnecting";
4491
+ this.emit("status_updated", {
4492
+ agentId: presence.agentId,
4493
+ status: "reconnecting"
4494
+ });
4495
+ }
4496
+ });
4497
+ }, 1e4);
4498
+ }
4499
+ /**
4500
+ * Stop heartbeat monitoring
4501
+ */
4502
+ stopHeartbeatMonitoring() {
4503
+ if (this.heartbeatInterval) {
4504
+ clearInterval(this.heartbeatInterval);
4505
+ this.heartbeatInterval = null;
4506
+ }
4507
+ }
4508
+ /**
4509
+ * Clear all presences
4510
+ */
4511
+ clear() {
4512
+ this.presences.clear();
4513
+ }
4514
+ /**
4515
+ * Destroy the manager
4516
+ */
4517
+ destroy() {
4518
+ this.stopHeartbeatMonitoring();
4519
+ this.presences.clear();
4520
+ this.removeAllListeners();
4521
+ logger8.debug("[AgentPresenceManager] Destroyed", { sessionId: this.sessionId });
4522
+ }
4523
+ };
4524
+ var instances = /* @__PURE__ */ new Map();
4525
+ function getAgentPresenceManager(sessionId) {
4526
+ if (!instances.has(sessionId)) {
4527
+ instances.set(sessionId, new AgentPresenceManager(sessionId));
4528
+ }
4529
+ return instances.get(sessionId);
4530
+ }
4531
+ function clearAgentPresenceManager(sessionId) {
4532
+ const instance = instances.get(sessionId);
4533
+ if (instance) {
4534
+ instance.destroy();
4535
+ instances.delete(sessionId);
4536
+ }
4537
+ }
4538
+
4539
+ // src/crypto/types.ts
4540
+ var AEON_CAPABILITIES = {
4541
+ // Basic sync operations
4542
+ SYNC_READ: "aeon:sync:read",
4543
+ SYNC_WRITE: "aeon:sync:write",
4544
+ SYNC_ADMIN: "aeon:sync:admin",
4545
+ // Node operations
4546
+ NODE_REGISTER: "aeon:node:register",
4547
+ NODE_HEARTBEAT: "aeon:node:heartbeat",
4548
+ // Replication operations
4549
+ REPLICATE_READ: "aeon:replicate:read",
4550
+ REPLICATE_WRITE: "aeon:replicate:write",
4551
+ // State operations
4552
+ STATE_READ: "aeon:state:read",
4553
+ STATE_WRITE: "aeon:state:write",
4554
+ STATE_RECONCILE: "aeon:state:reconcile"
4555
+ };
4556
+ var DEFAULT_CRYPTO_CONFIG = {
4557
+ defaultEncryptionMode: "none",
4558
+ requireSignatures: false,
4559
+ requireCapabilities: false,
4560
+ allowedSignatureAlgorithms: ["ES256", "Ed25519"],
4561
+ allowedEncryptionAlgorithms: ["ECIES-P256", "AES-256-GCM"],
4562
+ sessionKeyExpiration: 24 * 60 * 60 * 1e3
4563
+ // 24 hours
4564
+ };
4565
+
4566
+ // src/crypto/CryptoProvider.ts
4567
+ var NullCryptoProvider = class {
4568
+ notConfiguredError() {
4569
+ return new Error("Crypto provider not configured");
4570
+ }
4571
+ async generateIdentity() {
4572
+ throw this.notConfiguredError();
4573
+ }
4574
+ getLocalDID() {
4575
+ return null;
4576
+ }
4577
+ async exportPublicIdentity() {
4578
+ return null;
4579
+ }
4580
+ async registerRemoteNode() {
4581
+ }
4582
+ async getRemotePublicKey() {
4583
+ return null;
4584
+ }
4585
+ async sign() {
4586
+ throw this.notConfiguredError();
4587
+ }
4588
+ async signData(_data) {
4589
+ throw this.notConfiguredError();
4590
+ }
4591
+ async verify() {
4592
+ return true;
4593
+ }
4594
+ async verifySignedData() {
4595
+ return true;
4596
+ }
4597
+ async encrypt() {
4598
+ throw this.notConfiguredError();
4599
+ }
4600
+ async decrypt() {
4601
+ throw this.notConfiguredError();
4602
+ }
4603
+ async getSessionKey() {
4604
+ throw this.notConfiguredError();
4605
+ }
4606
+ async encryptWithSessionKey() {
4607
+ throw this.notConfiguredError();
4608
+ }
4609
+ async decryptWithSessionKey() {
4610
+ throw this.notConfiguredError();
4611
+ }
4612
+ async createUCAN() {
4613
+ throw this.notConfiguredError();
4614
+ }
4615
+ async verifyUCAN() {
4616
+ return { authorized: true };
4617
+ }
4618
+ async delegateCapabilities() {
4619
+ throw this.notConfiguredError();
4620
+ }
4621
+ async hash() {
4622
+ throw this.notConfiguredError();
4623
+ }
4624
+ randomBytes(length) {
4625
+ return crypto.getRandomValues(new Uint8Array(length));
4626
+ }
4627
+ isInitialized() {
4628
+ return false;
4629
+ }
4630
+ };
4631
+
4632
+ exports.AEON_CAPABILITIES = AEON_CAPABILITIES;
4633
+ exports.AdaptiveCompressionOptimizer = AdaptiveCompressionOptimizer;
4634
+ exports.AgentPresenceManager = AgentPresenceManager;
4635
+ exports.BatchTimingOptimizer = BatchTimingOptimizer;
4636
+ exports.CompressionEngine = CompressionEngine;
4637
+ exports.DEFAULT_CRYPTO_CONFIG = DEFAULT_CRYPTO_CONFIG;
4638
+ exports.DataTransformer = DataTransformer;
4639
+ exports.DeltaSyncOptimizer = DeltaSyncOptimizer;
4640
+ exports.MigrationEngine = MigrationEngine;
4641
+ exports.MigrationTracker = MigrationTracker;
4642
+ exports.NullCryptoProvider = NullCryptoProvider;
4643
+ exports.OfflineOperationQueue = OfflineOperationQueue;
4644
+ exports.PrefetchingEngine = PrefetchingEngine;
4645
+ exports.ReplicationManager = ReplicationManager;
4646
+ exports.SchemaVersionManager = SchemaVersionManager;
4647
+ exports.StateReconciler = StateReconciler;
4648
+ exports.SyncCoordinator = SyncCoordinator;
4649
+ exports.SyncProtocol = SyncProtocol;
4650
+ exports.clearAgentPresenceManager = clearAgentPresenceManager;
4651
+ exports.createNamespacedLogger = createNamespacedLogger;
4652
+ exports.disableLogging = disableLogging;
4653
+ exports.getAdaptiveCompressionOptimizer = getAdaptiveCompressionOptimizer;
4654
+ exports.getAgentPresenceManager = getAgentPresenceManager;
4655
+ exports.getBatchTimingOptimizer = getBatchTimingOptimizer;
4656
+ exports.getCompressionEngine = getCompressionEngine;
4657
+ exports.getDeltaSyncOptimizer = getDeltaSyncOptimizer;
4658
+ exports.getLogger = getLogger;
4659
+ exports.getOfflineOperationQueue = getOfflineOperationQueue;
4660
+ exports.getPrefetchingEngine = getPrefetchingEngine;
4661
+ exports.logger = logger;
4662
+ exports.resetAdaptiveCompressionOptimizer = resetAdaptiveCompressionOptimizer;
4663
+ exports.resetBatchTimingOptimizer = resetBatchTimingOptimizer;
4664
+ exports.resetCompressionEngine = resetCompressionEngine;
4665
+ exports.resetDeltaSyncOptimizer = resetDeltaSyncOptimizer;
4666
+ exports.resetLogger = resetLogger;
4667
+ exports.resetOfflineOperationQueue = resetOfflineOperationQueue;
4668
+ exports.resetPrefetchingEngine = resetPrefetchingEngine;
4669
+ exports.setLogger = setLogger;
4670
+ //# sourceMappingURL=index.cjs.map
4671
+ //# sourceMappingURL=index.cjs.map