@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.
@@ -0,0 +1,866 @@
1
+ // src/utils/logger.ts
2
+ var consoleLogger = {
3
+ debug: (...args) => {
4
+ console.debug("[AEON:DEBUG]", ...args);
5
+ },
6
+ info: (...args) => {
7
+ console.info("[AEON:INFO]", ...args);
8
+ },
9
+ warn: (...args) => {
10
+ console.warn("[AEON:WARN]", ...args);
11
+ },
12
+ error: (...args) => {
13
+ console.error("[AEON:ERROR]", ...args);
14
+ }
15
+ };
16
+ var currentLogger = consoleLogger;
17
+ function getLogger() {
18
+ return currentLogger;
19
+ }
20
+ var logger = {
21
+ debug: (...args) => getLogger().debug(...args),
22
+ info: (...args) => getLogger().info(...args),
23
+ warn: (...args) => getLogger().warn(...args),
24
+ error: (...args) => getLogger().error(...args)
25
+ };
26
+
27
+ // src/versioning/SchemaVersionManager.ts
28
+ var SchemaVersionManager = class {
29
+ versions = /* @__PURE__ */ new Map();
30
+ versionHistory = [];
31
+ compatibilityMatrix = /* @__PURE__ */ new Map();
32
+ currentVersion = null;
33
+ constructor() {
34
+ this.initializeDefaultVersions();
35
+ }
36
+ /**
37
+ * Initialize default versions
38
+ */
39
+ initializeDefaultVersions() {
40
+ const v1_0_0 = {
41
+ major: 1,
42
+ minor: 0,
43
+ patch: 0,
44
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
45
+ description: "Initial schema version",
46
+ breaking: false
47
+ };
48
+ this.registerVersion(v1_0_0);
49
+ this.currentVersion = v1_0_0;
50
+ }
51
+ /**
52
+ * Register a new schema version
53
+ */
54
+ registerVersion(version) {
55
+ const versionString = this.versionToString(version);
56
+ this.versions.set(versionString, version);
57
+ this.versionHistory.push(version);
58
+ logger.debug("[SchemaVersionManager] Version registered", {
59
+ version: versionString,
60
+ breaking: version.breaking,
61
+ description: version.description
62
+ });
63
+ }
64
+ /**
65
+ * Get current version
66
+ */
67
+ getCurrentVersion() {
68
+ if (!this.currentVersion) {
69
+ throw new Error("No current version set");
70
+ }
71
+ return this.currentVersion;
72
+ }
73
+ /**
74
+ * Set current version
75
+ */
76
+ setCurrentVersion(version) {
77
+ if (!this.versions.has(this.versionToString(version))) {
78
+ throw new Error(`Version ${this.versionToString(version)} not registered`);
79
+ }
80
+ this.currentVersion = version;
81
+ logger.debug("[SchemaVersionManager] Current version set", {
82
+ version: this.versionToString(version)
83
+ });
84
+ }
85
+ /**
86
+ * Get version history
87
+ */
88
+ getVersionHistory() {
89
+ return [...this.versionHistory];
90
+ }
91
+ /**
92
+ * Check if version exists
93
+ */
94
+ hasVersion(version) {
95
+ return this.versions.has(this.versionToString(version));
96
+ }
97
+ /**
98
+ * Get version by string (e.g., "1.2.3")
99
+ */
100
+ getVersion(versionString) {
101
+ return this.versions.get(versionString);
102
+ }
103
+ /**
104
+ * Register compatibility rule
105
+ */
106
+ registerCompatibility(rule) {
107
+ if (!this.compatibilityMatrix.has(rule.from)) {
108
+ this.compatibilityMatrix.set(rule.from, []);
109
+ }
110
+ const rules = this.compatibilityMatrix.get(rule.from);
111
+ if (rules) {
112
+ rules.push(rule);
113
+ }
114
+ logger.debug("[SchemaVersionManager] Compatibility rule registered", {
115
+ from: rule.from,
116
+ to: rule.to,
117
+ compatible: rule.compatible,
118
+ requiresMigration: rule.requiresMigration
119
+ });
120
+ }
121
+ /**
122
+ * Check if migration path exists
123
+ */
124
+ canMigrate(fromVersion, toVersion) {
125
+ const fromStr = typeof fromVersion === "string" ? fromVersion : this.versionToString(fromVersion);
126
+ const toStr = typeof toVersion === "string" ? toVersion : this.versionToString(toVersion);
127
+ const rules = this.compatibilityMatrix.get(fromStr) || [];
128
+ return rules.some((r) => r.to === toStr && r.requiresMigration);
129
+ }
130
+ /**
131
+ * Get migration path
132
+ */
133
+ getMigrationPath(fromVersion, toVersion) {
134
+ const path = [];
135
+ let current = fromVersion;
136
+ const maxSteps = 100;
137
+ let steps = 0;
138
+ while (this.compareVersions(current, toVersion) !== 0 && steps < maxSteps) {
139
+ const fromStr = this.versionToString(current);
140
+ const rules = this.compatibilityMatrix.get(fromStr) || [];
141
+ let found = false;
142
+ for (const rule of rules) {
143
+ const nextVersion = this.getVersion(rule.to);
144
+ if (nextVersion) {
145
+ if (this.compareVersions(nextVersion, toVersion) <= 0 || this.compareVersions(current, nextVersion) < this.compareVersions(current, toVersion)) {
146
+ current = nextVersion;
147
+ path.push(current);
148
+ found = true;
149
+ break;
150
+ }
151
+ }
152
+ }
153
+ if (!found) {
154
+ break;
155
+ }
156
+ steps++;
157
+ }
158
+ return path;
159
+ }
160
+ /**
161
+ * Compare two versions
162
+ * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
163
+ */
164
+ compareVersions(v1, v2) {
165
+ const ver1 = typeof v1 === "string" ? this.parseVersion(v1) : v1;
166
+ const ver2 = typeof v2 === "string" ? this.parseVersion(v2) : v2;
167
+ if (ver1.major !== ver2.major) {
168
+ return ver1.major < ver2.major ? -1 : 1;
169
+ }
170
+ if (ver1.minor !== ver2.minor) {
171
+ return ver1.minor < ver2.minor ? -1 : 1;
172
+ }
173
+ if (ver1.patch !== ver2.patch) {
174
+ return ver1.patch < ver2.patch ? -1 : 1;
175
+ }
176
+ return 0;
177
+ }
178
+ /**
179
+ * Parse version string to SchemaVersion
180
+ */
181
+ parseVersion(versionString) {
182
+ const parts = versionString.split(".").map(Number);
183
+ return {
184
+ major: parts[0] || 0,
185
+ minor: parts[1] || 0,
186
+ patch: parts[2] || 0,
187
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
188
+ description: "",
189
+ breaking: false
190
+ };
191
+ }
192
+ /**
193
+ * Create new version
194
+ */
195
+ createVersion(major, minor, patch, description, breaking = false) {
196
+ return {
197
+ major,
198
+ minor,
199
+ patch,
200
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
201
+ description,
202
+ breaking
203
+ };
204
+ }
205
+ /**
206
+ * Convert version to string
207
+ */
208
+ versionToString(version) {
209
+ return `${version.major}.${version.minor}.${version.patch}`;
210
+ }
211
+ /**
212
+ * Get version metadata
213
+ */
214
+ getVersionMetadata(version) {
215
+ const history = this.versionHistory;
216
+ const currentIndex = history.findIndex(
217
+ (v) => this.versionToString(v) === this.versionToString(version)
218
+ );
219
+ return {
220
+ version,
221
+ previousVersion: currentIndex > 0 ? history[currentIndex - 1] : void 0,
222
+ changes: [version.description],
223
+ migrationsRequired: this.canMigrate(
224
+ this.currentVersion || version,
225
+ version
226
+ ) ? [this.versionToString(version)] : [],
227
+ rollbackPossible: currentIndex > 0
228
+ };
229
+ }
230
+ /**
231
+ * Get all registered versions
232
+ */
233
+ getAllVersions() {
234
+ return Array.from(this.versions.values()).sort(
235
+ (a, b) => this.compareVersions(a, b)
236
+ );
237
+ }
238
+ /**
239
+ * Clear all versions (for testing)
240
+ */
241
+ clear() {
242
+ this.versions.clear();
243
+ this.versionHistory = [];
244
+ this.compatibilityMatrix.clear();
245
+ this.currentVersion = null;
246
+ }
247
+ };
248
+
249
+ // src/versioning/MigrationEngine.ts
250
+ var MigrationEngine = class {
251
+ migrations = /* @__PURE__ */ new Map();
252
+ executedMigrations = [];
253
+ state = {
254
+ currentVersion: "1.0.0",
255
+ appliedMigrations: [],
256
+ failedMigrations: [],
257
+ lastMigrationTime: (/* @__PURE__ */ new Date()).toISOString(),
258
+ totalMigrationsRun: 0
259
+ };
260
+ /**
261
+ * Register a migration
262
+ */
263
+ registerMigration(migration) {
264
+ this.migrations.set(migration.id, migration);
265
+ logger.debug("[MigrationEngine] Migration registered", {
266
+ id: migration.id,
267
+ version: migration.version,
268
+ name: migration.name
269
+ });
270
+ }
271
+ /**
272
+ * Execute a migration
273
+ */
274
+ async executeMigration(migrationId, data) {
275
+ const migration = this.migrations.get(migrationId);
276
+ if (!migration) {
277
+ throw new Error(`Migration ${migrationId} not found`);
278
+ }
279
+ const startTime = Date.now();
280
+ const result = {
281
+ migrationId,
282
+ success: false,
283
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
284
+ duration: 0,
285
+ itemsAffected: 0,
286
+ errors: []
287
+ };
288
+ try {
289
+ logger.debug("[MigrationEngine] Executing migration", {
290
+ id: migrationId,
291
+ version: migration.version
292
+ });
293
+ migration.up(data);
294
+ result.success = true;
295
+ result.itemsAffected = Array.isArray(data) ? data.length : 1;
296
+ result.duration = Date.now() - startTime;
297
+ this.state.appliedMigrations.push(migrationId);
298
+ this.state.currentVersion = migration.version;
299
+ this.state.totalMigrationsRun++;
300
+ this.state.lastMigrationTime = result.timestamp;
301
+ this.executedMigrations.push(result);
302
+ logger.debug("[MigrationEngine] Migration executed successfully", {
303
+ id: migrationId,
304
+ duration: result.duration,
305
+ itemsAffected: result.itemsAffected
306
+ });
307
+ return result;
308
+ } catch (error) {
309
+ result.errors = [error instanceof Error ? error.message : String(error)];
310
+ this.state.failedMigrations.push(migrationId);
311
+ this.executedMigrations.push(result);
312
+ logger.error("[MigrationEngine] Migration failed", {
313
+ id: migrationId,
314
+ error: result.errors[0]
315
+ });
316
+ throw new Error(`Migration ${migrationId} failed: ${result.errors[0]}`);
317
+ }
318
+ }
319
+ /**
320
+ * Rollback a migration
321
+ */
322
+ async rollbackMigration(migrationId, data) {
323
+ const migration = this.migrations.get(migrationId);
324
+ if (!migration) {
325
+ throw new Error(`Migration ${migrationId} not found`);
326
+ }
327
+ if (!migration.down) {
328
+ throw new Error(`Migration ${migrationId} does not support rollback`);
329
+ }
330
+ const startTime = Date.now();
331
+ const result = {
332
+ migrationId,
333
+ success: false,
334
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
335
+ duration: 0,
336
+ itemsAffected: 0,
337
+ errors: []
338
+ };
339
+ try {
340
+ logger.debug("[MigrationEngine] Rolling back migration", {
341
+ id: migrationId,
342
+ version: migration.version
343
+ });
344
+ migration.down(data);
345
+ result.success = true;
346
+ result.itemsAffected = Array.isArray(data) ? data.length : 1;
347
+ result.duration = Date.now() - startTime;
348
+ this.state.appliedMigrations = this.state.appliedMigrations.filter(
349
+ (id) => id !== migrationId
350
+ );
351
+ this.executedMigrations.push(result);
352
+ logger.debug("[MigrationEngine] Migration rolled back", {
353
+ id: migrationId,
354
+ duration: result.duration
355
+ });
356
+ return result;
357
+ } catch (error) {
358
+ result.errors = [error instanceof Error ? error.message : String(error)];
359
+ this.executedMigrations.push(result);
360
+ logger.error("[MigrationEngine] Rollback failed", {
361
+ id: migrationId,
362
+ error: result.errors[0]
363
+ });
364
+ throw new Error(`Rollback for ${migrationId} failed: ${result.errors[0]}`);
365
+ }
366
+ }
367
+ /**
368
+ * Get migration state
369
+ */
370
+ getState() {
371
+ return { ...this.state };
372
+ }
373
+ /**
374
+ * Get migration execution history
375
+ */
376
+ getExecutionHistory() {
377
+ return [...this.executedMigrations];
378
+ }
379
+ /**
380
+ * Get migration by ID
381
+ */
382
+ getMigration(migrationId) {
383
+ return this.migrations.get(migrationId);
384
+ }
385
+ /**
386
+ * Get all registered migrations
387
+ */
388
+ getAllMigrations() {
389
+ return Array.from(this.migrations.values());
390
+ }
391
+ /**
392
+ * Get applied migrations
393
+ */
394
+ getAppliedMigrations() {
395
+ return [...this.state.appliedMigrations];
396
+ }
397
+ /**
398
+ * Get failed migrations
399
+ */
400
+ getFailedMigrations() {
401
+ return [...this.state.failedMigrations];
402
+ }
403
+ /**
404
+ * Get pending migrations
405
+ */
406
+ getPendingMigrations() {
407
+ return this.getAllMigrations().filter(
408
+ (m) => !this.state.appliedMigrations.includes(m.id)
409
+ );
410
+ }
411
+ /**
412
+ * Get migration statistics
413
+ */
414
+ getStatistics() {
415
+ const successful = this.executedMigrations.filter((m) => m.success).length;
416
+ const failed = this.executedMigrations.filter((m) => !m.success).length;
417
+ const totalDuration = this.executedMigrations.reduce((sum, m) => sum + m.duration, 0);
418
+ const totalAffected = this.executedMigrations.reduce((sum, m) => sum + m.itemsAffected, 0);
419
+ return {
420
+ totalExecuted: this.executedMigrations.length,
421
+ successful,
422
+ failed,
423
+ successRate: this.executedMigrations.length > 0 ? successful / this.executedMigrations.length * 100 : 0,
424
+ totalDurationMs: totalDuration,
425
+ averageDurationMs: this.executedMigrations.length > 0 ? totalDuration / this.executedMigrations.length : 0,
426
+ totalAffected
427
+ };
428
+ }
429
+ /**
430
+ * Clear history (for testing)
431
+ */
432
+ clear() {
433
+ this.migrations.clear();
434
+ this.executedMigrations = [];
435
+ this.state = {
436
+ currentVersion: "1.0.0",
437
+ appliedMigrations: [],
438
+ failedMigrations: [],
439
+ lastMigrationTime: (/* @__PURE__ */ new Date()).toISOString(),
440
+ totalMigrationsRun: 0
441
+ };
442
+ }
443
+ };
444
+
445
+ // src/versioning/DataTransformer.ts
446
+ var DataTransformer = class {
447
+ rules = /* @__PURE__ */ new Map();
448
+ transformationHistory = [];
449
+ /**
450
+ * Register a transformation rule
451
+ */
452
+ registerRule(rule) {
453
+ this.rules.set(rule.field, rule);
454
+ logger.debug("[DataTransformer] Rule registered", {
455
+ field: rule.field,
456
+ required: rule.required,
457
+ hasDefault: rule.defaultValue !== void 0
458
+ });
459
+ }
460
+ /**
461
+ * Transform a single field value
462
+ */
463
+ transformField(field, value) {
464
+ const rule = this.rules.get(field);
465
+ if (!rule) {
466
+ return value;
467
+ }
468
+ try {
469
+ return rule.transformer(value);
470
+ } catch (error) {
471
+ if (rule.required) {
472
+ throw new Error(`Failed to transform required field ${field}: ${error instanceof Error ? error.message : String(error)}`);
473
+ }
474
+ return rule.defaultValue !== void 0 ? rule.defaultValue : value;
475
+ }
476
+ }
477
+ /**
478
+ * Transform a single object
479
+ */
480
+ transformObject(data) {
481
+ const transformed = {};
482
+ for (const [key, value] of Object.entries(data)) {
483
+ try {
484
+ transformed[key] = this.transformField(key, value);
485
+ } catch (error) {
486
+ logger.warn("[DataTransformer] Field transformation failed", {
487
+ field: key,
488
+ error: error instanceof Error ? error.message : String(error)
489
+ });
490
+ const rule = this.rules.get(key);
491
+ if (!rule || !rule.required) {
492
+ transformed[key] = value;
493
+ }
494
+ }
495
+ }
496
+ return transformed;
497
+ }
498
+ /**
499
+ * Transform a collection of items
500
+ */
501
+ transformCollection(items) {
502
+ const startTime = Date.now();
503
+ const result = {
504
+ success: true,
505
+ itemsTransformed: 0,
506
+ itemsFailed: 0,
507
+ errors: [],
508
+ warnings: [],
509
+ duration: 0
510
+ };
511
+ for (let i = 0; i < items.length; i++) {
512
+ const item = items[i];
513
+ try {
514
+ if (typeof item === "object" && item !== null && !Array.isArray(item)) {
515
+ this.transformObject(item);
516
+ result.itemsTransformed++;
517
+ } else {
518
+ result.warnings.push(`Item ${i} is not a transformable object`);
519
+ }
520
+ } catch (error) {
521
+ result.errors.push({
522
+ item,
523
+ error: error instanceof Error ? error.message : String(error)
524
+ });
525
+ result.itemsFailed++;
526
+ }
527
+ }
528
+ result.duration = Date.now() - startTime;
529
+ result.success = result.itemsFailed === 0;
530
+ this.transformationHistory.push(result);
531
+ logger.debug("[DataTransformer] Collection transformed", {
532
+ total: items.length,
533
+ transformed: result.itemsTransformed,
534
+ failed: result.itemsFailed,
535
+ duration: result.duration
536
+ });
537
+ return result;
538
+ }
539
+ /**
540
+ * Validate transformed data
541
+ */
542
+ validateTransformation(original, transformed) {
543
+ const issues = [];
544
+ if (original.length !== transformed.length) {
545
+ issues.push(`Item count mismatch: ${original.length} -> ${transformed.length}`);
546
+ }
547
+ for (let i = 0; i < Math.min(original.length, transformed.length); i++) {
548
+ const orig = original[i];
549
+ const trans = transformed[i];
550
+ if (!this.validateItem(orig, trans)) {
551
+ issues.push(`Item ${i} validation failed`);
552
+ }
553
+ }
554
+ return {
555
+ valid: issues.length === 0,
556
+ issues
557
+ };
558
+ }
559
+ /**
560
+ * Validate a single item transformation
561
+ */
562
+ validateItem(original, transformed) {
563
+ if (original === null || original === void 0) {
564
+ return true;
565
+ }
566
+ if (typeof original === "object" && typeof transformed !== "object") {
567
+ return false;
568
+ }
569
+ return true;
570
+ }
571
+ /**
572
+ * Get transformation history
573
+ */
574
+ getTransformationHistory() {
575
+ return [...this.transformationHistory];
576
+ }
577
+ /**
578
+ * Get transformation statistics
579
+ */
580
+ getStatistics() {
581
+ const totalTransformed = this.transformationHistory.reduce(
582
+ (sum, r) => sum + r.itemsTransformed,
583
+ 0
584
+ );
585
+ const totalFailed = this.transformationHistory.reduce(
586
+ (sum, r) => sum + r.itemsFailed,
587
+ 0
588
+ );
589
+ const totalDuration = this.transformationHistory.reduce(
590
+ (sum, r) => sum + r.duration,
591
+ 0
592
+ );
593
+ return {
594
+ totalBatches: this.transformationHistory.length,
595
+ totalTransformed,
596
+ totalFailed,
597
+ successRate: totalTransformed + totalFailed > 0 ? totalTransformed / (totalTransformed + totalFailed) * 100 : 0,
598
+ totalDurationMs: totalDuration,
599
+ averageBatchDurationMs: this.transformationHistory.length > 0 ? totalDuration / this.transformationHistory.length : 0
600
+ };
601
+ }
602
+ /**
603
+ * Get registered rules
604
+ */
605
+ getRules() {
606
+ return Array.from(this.rules.values());
607
+ }
608
+ /**
609
+ * Get rule for field
610
+ */
611
+ getRule(field) {
612
+ return this.rules.get(field);
613
+ }
614
+ /**
615
+ * Clear all rules (for testing)
616
+ */
617
+ clearRules() {
618
+ this.rules.clear();
619
+ }
620
+ /**
621
+ * Clear history (for testing)
622
+ */
623
+ clearHistory() {
624
+ this.transformationHistory = [];
625
+ }
626
+ /**
627
+ * Clear all state (for testing)
628
+ */
629
+ clear() {
630
+ this.clearRules();
631
+ this.clearHistory();
632
+ }
633
+ };
634
+
635
+ // src/versioning/MigrationTracker.ts
636
+ var MigrationTracker = class {
637
+ migrations = [];
638
+ snapshots = /* @__PURE__ */ new Map();
639
+ /**
640
+ * Track a new migration
641
+ */
642
+ recordMigration(record) {
643
+ this.migrations.push({ ...record });
644
+ logger.debug("[MigrationTracker] Migration recorded", {
645
+ id: record.id,
646
+ migrationId: record.migrationId,
647
+ version: record.version,
648
+ status: record.status
649
+ });
650
+ }
651
+ /**
652
+ * Track migration with snapshot
653
+ */
654
+ trackMigration(migrationId, version, beforeHash, afterHash, itemCount, duration, itemsAffected, appliedBy = "system") {
655
+ const record = {
656
+ id: `${migrationId}-${Date.now()}`,
657
+ migrationId,
658
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
659
+ version,
660
+ direction: "up",
661
+ status: "applied",
662
+ duration,
663
+ itemsAffected,
664
+ dataSnapshot: {
665
+ beforeHash,
666
+ afterHash,
667
+ itemCount
668
+ },
669
+ appliedBy
670
+ };
671
+ this.recordMigration(record);
672
+ this.snapshots.set(record.id, {
673
+ beforeHash,
674
+ afterHash,
675
+ itemCount
676
+ });
677
+ }
678
+ /**
679
+ * Get all migration records
680
+ */
681
+ getMigrations() {
682
+ return this.migrations.map((m) => ({ ...m }));
683
+ }
684
+ /**
685
+ * Get migrations for a specific version
686
+ */
687
+ getMigrationsForVersion(version) {
688
+ return this.migrations.filter((m) => m.version === version);
689
+ }
690
+ /**
691
+ * Get migration by ID
692
+ */
693
+ getMigration(id) {
694
+ return this.migrations.find((m) => m.id === id);
695
+ }
696
+ /**
697
+ * Check if can rollback
698
+ */
699
+ canRollback(fromVersion, toVersion) {
700
+ const fromIndex = this.migrations.findIndex((m) => m.version === fromVersion);
701
+ const toIndex = this.migrations.findIndex((m) => m.version === toVersion);
702
+ if (fromIndex === -1 || toIndex === -1) {
703
+ return false;
704
+ }
705
+ if (toIndex >= fromIndex) {
706
+ return false;
707
+ }
708
+ for (let i = fromIndex; i > toIndex; i--) {
709
+ if (!this.migrations[i]?.dataSnapshot) {
710
+ return false;
711
+ }
712
+ }
713
+ return true;
714
+ }
715
+ /**
716
+ * Get rollback path
717
+ */
718
+ getRollbackPath(fromVersion, toVersion) {
719
+ const canRollback = this.canRollback(fromVersion, toVersion);
720
+ const path = [];
721
+ const affectedVersions = [];
722
+ let estimatedDuration = 0;
723
+ if (canRollback) {
724
+ const fromIndex = this.migrations.findIndex((m) => m.version === fromVersion);
725
+ const toIndex = this.migrations.findIndex((m) => m.version === toVersion);
726
+ for (let i = fromIndex; i > toIndex; i--) {
727
+ const migration = this.migrations[i];
728
+ if (migration) {
729
+ path.push(migration.migrationId);
730
+ affectedVersions.push(migration.version);
731
+ estimatedDuration += migration.duration;
732
+ }
733
+ }
734
+ }
735
+ return {
736
+ path,
737
+ canRollback,
738
+ affectedVersions,
739
+ estimatedDuration
740
+ };
741
+ }
742
+ /**
743
+ * Get applied migrations
744
+ */
745
+ getAppliedMigrations() {
746
+ return this.migrations.filter((m) => m.status === "applied");
747
+ }
748
+ /**
749
+ * Get failed migrations
750
+ */
751
+ getFailedMigrations() {
752
+ return this.migrations.filter((m) => m.status === "failed");
753
+ }
754
+ /**
755
+ * Get pending migrations
756
+ */
757
+ getPendingMigrations() {
758
+ return this.migrations.filter((m) => m.status === "pending");
759
+ }
760
+ /**
761
+ * Get latest migration
762
+ */
763
+ getLatestMigration() {
764
+ return this.migrations[this.migrations.length - 1];
765
+ }
766
+ /**
767
+ * Get migration timeline
768
+ */
769
+ getTimeline() {
770
+ return this.migrations.map((m) => ({
771
+ timestamp: m.timestamp,
772
+ version: m.version,
773
+ status: m.status
774
+ }));
775
+ }
776
+ /**
777
+ * Get migration statistics
778
+ */
779
+ getStatistics() {
780
+ const applied = this.migrations.filter((m) => m.status === "applied").length;
781
+ const failed = this.migrations.filter((m) => m.status === "failed").length;
782
+ const pending = this.migrations.filter((m) => m.status === "pending").length;
783
+ const rolledBack = this.migrations.filter((m) => m.status === "rolled-back").length;
784
+ const totalDuration = this.migrations.reduce((sum, m) => sum + m.duration, 0);
785
+ const totalAffected = this.migrations.reduce((sum, m) => sum + m.itemsAffected, 0);
786
+ return {
787
+ total: this.migrations.length,
788
+ applied,
789
+ failed,
790
+ pending,
791
+ rolledBack,
792
+ successRate: this.migrations.length > 0 ? applied / this.migrations.length * 100 : 0,
793
+ totalDurationMs: totalDuration,
794
+ averageDurationMs: this.migrations.length > 0 ? totalDuration / this.migrations.length : 0,
795
+ totalItemsAffected: totalAffected
796
+ };
797
+ }
798
+ /**
799
+ * Get audit trail
800
+ */
801
+ getAuditTrail(migrationId) {
802
+ const filtered = migrationId ? this.migrations.filter((m) => m.migrationId === migrationId) : this.migrations;
803
+ return filtered.map((m) => ({
804
+ id: m.id,
805
+ timestamp: m.timestamp,
806
+ migrationId: m.migrationId,
807
+ version: m.version,
808
+ status: m.status,
809
+ appliedBy: m.appliedBy,
810
+ duration: m.duration,
811
+ itemsAffected: m.itemsAffected,
812
+ error: m.errorMessage
813
+ }));
814
+ }
815
+ /**
816
+ * Get data snapshot for recovery
817
+ */
818
+ getSnapshot(recordId) {
819
+ return this.snapshots.get(recordId);
820
+ }
821
+ /**
822
+ * Update migration status
823
+ */
824
+ updateMigrationStatus(recordId, status, error) {
825
+ const migration = this.migrations.find((m) => m.id === recordId);
826
+ if (migration) {
827
+ migration.status = status;
828
+ if (error) {
829
+ migration.errorMessage = error;
830
+ }
831
+ logger.debug("[MigrationTracker] Migration status updated", {
832
+ recordId,
833
+ status,
834
+ hasError: !!error
835
+ });
836
+ }
837
+ }
838
+ /**
839
+ * Clear history (for testing)
840
+ */
841
+ clear() {
842
+ this.migrations = [];
843
+ this.snapshots.clear();
844
+ }
845
+ /**
846
+ * Get total migrations tracked
847
+ */
848
+ getTotalMigrations() {
849
+ return this.migrations.length;
850
+ }
851
+ /**
852
+ * Find migrations by time range
853
+ */
854
+ getMigrationsByTimeRange(startTime, endTime) {
855
+ const start = new Date(startTime).getTime();
856
+ const end = new Date(endTime).getTime();
857
+ return this.migrations.filter((m) => {
858
+ const time = new Date(m.timestamp).getTime();
859
+ return time >= start && time <= end;
860
+ });
861
+ }
862
+ };
863
+
864
+ export { DataTransformer, MigrationEngine, MigrationTracker, SchemaVersionManager };
865
+ //# sourceMappingURL=index.js.map
866
+ //# sourceMappingURL=index.js.map