@affectively/aeon 1.2.0 → 1.3.1
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/LICENSE +21 -21
- package/README.md +342 -342
- package/dist/compression/index.cjs.map +1 -1
- package/dist/compression/index.js.map +1 -1
- package/dist/core/index.d.cts +213 -208
- package/dist/core/index.d.ts +213 -208
- package/dist/crypto/index.cjs.map +1 -1
- package/dist/crypto/index.d.cts +441 -402
- package/dist/crypto/index.d.ts +441 -402
- package/dist/crypto/index.js.map +1 -1
- package/dist/distributed/index.cjs +8 -2
- package/dist/distributed/index.cjs.map +1 -1
- package/dist/distributed/index.d.cts +1005 -890
- package/dist/distributed/index.d.ts +1005 -890
- package/dist/distributed/index.js +8 -2
- package/dist/distributed/index.js.map +1 -1
- package/dist/index.cjs +58 -733
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -5
- package/dist/index.d.ts +50 -5
- package/dist/index.js +55 -732
- package/dist/index.js.map +1 -1
- package/dist/offline/index.cjs.map +1 -1
- package/dist/offline/index.d.cts +148 -142
- package/dist/offline/index.d.ts +148 -142
- package/dist/offline/index.js.map +1 -1
- package/dist/optimization/index.cjs.map +1 -1
- package/dist/optimization/index.js.map +1 -1
- package/dist/persistence/index.cjs.map +1 -1
- package/dist/persistence/index.d.cts +57 -57
- package/dist/persistence/index.d.ts +57 -57
- package/dist/persistence/index.js.map +1 -1
- package/dist/presence/index.cjs.map +1 -1
- package/dist/presence/index.js.map +1 -1
- package/dist/{types-CMxO7QF0.d.cts → types-B7CxsoLh.d.cts} +30 -30
- package/dist/{types-CMxO7QF0.d.ts → types-B7CxsoLh.d.ts} +30 -30
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +35 -35
- package/dist/utils/index.d.ts +35 -35
- package/dist/utils/index.js.map +1 -1
- package/dist/versioning/index.cjs +18 -8
- package/dist/versioning/index.cjs.map +1 -1
- package/dist/versioning/index.d.cts +1 -1
- package/dist/versioning/index.d.ts +1 -1
- package/dist/versioning/index.js +18 -8
- package/dist/versioning/index.js.map +1 -1
- package/package.json +196 -192
package/dist/index.js
CHANGED
|
@@ -193,230 +193,6 @@ var InMemoryStorageAdapter = class {
|
|
|
193
193
|
}
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
-
// src/versioning/SchemaVersionManager.ts
|
|
197
|
-
var SchemaVersionManager = class {
|
|
198
|
-
versions = /* @__PURE__ */ new Map();
|
|
199
|
-
versionHistory = [];
|
|
200
|
-
compatibilityMatrix = /* @__PURE__ */ new Map();
|
|
201
|
-
currentVersion = null;
|
|
202
|
-
constructor() {
|
|
203
|
-
this.initializeDefaultVersions();
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Initialize default versions
|
|
207
|
-
*/
|
|
208
|
-
initializeDefaultVersions() {
|
|
209
|
-
const v1_0_0 = {
|
|
210
|
-
major: 1,
|
|
211
|
-
minor: 0,
|
|
212
|
-
patch: 0,
|
|
213
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
214
|
-
description: "Initial schema version",
|
|
215
|
-
breaking: false
|
|
216
|
-
};
|
|
217
|
-
this.registerVersion(v1_0_0);
|
|
218
|
-
this.currentVersion = v1_0_0;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Register a new schema version
|
|
222
|
-
*/
|
|
223
|
-
registerVersion(version) {
|
|
224
|
-
const versionString = this.versionToString(version);
|
|
225
|
-
this.versions.set(versionString, version);
|
|
226
|
-
this.versionHistory.push(version);
|
|
227
|
-
logger.debug("[SchemaVersionManager] Version registered", {
|
|
228
|
-
version: versionString,
|
|
229
|
-
breaking: version.breaking,
|
|
230
|
-
description: version.description
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Get current version
|
|
235
|
-
*/
|
|
236
|
-
getCurrentVersion() {
|
|
237
|
-
if (!this.currentVersion) {
|
|
238
|
-
throw new Error("No current version set");
|
|
239
|
-
}
|
|
240
|
-
return this.currentVersion;
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Set current version
|
|
244
|
-
*/
|
|
245
|
-
setCurrentVersion(version) {
|
|
246
|
-
if (!this.versions.has(this.versionToString(version))) {
|
|
247
|
-
throw new Error(
|
|
248
|
-
`Version ${this.versionToString(version)} not registered`
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
this.currentVersion = version;
|
|
252
|
-
logger.debug("[SchemaVersionManager] Current version set", {
|
|
253
|
-
version: this.versionToString(version)
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Get version history
|
|
258
|
-
*/
|
|
259
|
-
getVersionHistory() {
|
|
260
|
-
return [...this.versionHistory];
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Check if version exists
|
|
264
|
-
*/
|
|
265
|
-
hasVersion(version) {
|
|
266
|
-
return this.versions.has(this.versionToString(version));
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Get version by string (e.g., "1.2.3")
|
|
270
|
-
*/
|
|
271
|
-
getVersion(versionString) {
|
|
272
|
-
return this.versions.get(versionString);
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Register compatibility rule
|
|
276
|
-
*/
|
|
277
|
-
registerCompatibility(rule) {
|
|
278
|
-
if (!this.compatibilityMatrix.has(rule.from)) {
|
|
279
|
-
this.compatibilityMatrix.set(rule.from, []);
|
|
280
|
-
}
|
|
281
|
-
const rules = this.compatibilityMatrix.get(rule.from);
|
|
282
|
-
if (rules) {
|
|
283
|
-
rules.push(rule);
|
|
284
|
-
}
|
|
285
|
-
logger.debug("[SchemaVersionManager] Compatibility rule registered", {
|
|
286
|
-
from: rule.from,
|
|
287
|
-
to: rule.to,
|
|
288
|
-
compatible: rule.compatible,
|
|
289
|
-
requiresMigration: rule.requiresMigration
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Check if migration path exists
|
|
294
|
-
*/
|
|
295
|
-
canMigrate(fromVersion, toVersion) {
|
|
296
|
-
const fromStr = typeof fromVersion === "string" ? fromVersion : this.versionToString(fromVersion);
|
|
297
|
-
const toStr = typeof toVersion === "string" ? toVersion : this.versionToString(toVersion);
|
|
298
|
-
const rules = this.compatibilityMatrix.get(fromStr) || [];
|
|
299
|
-
return rules.some((r) => r.to === toStr && r.requiresMigration);
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Get migration path
|
|
303
|
-
*/
|
|
304
|
-
getMigrationPath(fromVersion, toVersion) {
|
|
305
|
-
const path = [];
|
|
306
|
-
let current = fromVersion;
|
|
307
|
-
const maxSteps = 100;
|
|
308
|
-
let steps = 0;
|
|
309
|
-
while (this.compareVersions(current, toVersion) !== 0 && steps < maxSteps) {
|
|
310
|
-
const fromStr = this.versionToString(current);
|
|
311
|
-
const rules = this.compatibilityMatrix.get(fromStr) || [];
|
|
312
|
-
let found = false;
|
|
313
|
-
for (const rule of rules) {
|
|
314
|
-
const nextVersion = this.getVersion(rule.to);
|
|
315
|
-
if (nextVersion) {
|
|
316
|
-
if (this.compareVersions(nextVersion, toVersion) <= 0 || this.compareVersions(current, nextVersion) < this.compareVersions(current, toVersion)) {
|
|
317
|
-
current = nextVersion;
|
|
318
|
-
path.push(current);
|
|
319
|
-
found = true;
|
|
320
|
-
break;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
if (!found) {
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
steps++;
|
|
328
|
-
}
|
|
329
|
-
return path;
|
|
330
|
-
}
|
|
331
|
-
/**
|
|
332
|
-
* Compare two versions
|
|
333
|
-
* Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
334
|
-
*/
|
|
335
|
-
compareVersions(v1, v2) {
|
|
336
|
-
const ver1 = typeof v1 === "string" ? this.parseVersion(v1) : v1;
|
|
337
|
-
const ver2 = typeof v2 === "string" ? this.parseVersion(v2) : v2;
|
|
338
|
-
if (ver1.major !== ver2.major) {
|
|
339
|
-
return ver1.major < ver2.major ? -1 : 1;
|
|
340
|
-
}
|
|
341
|
-
if (ver1.minor !== ver2.minor) {
|
|
342
|
-
return ver1.minor < ver2.minor ? -1 : 1;
|
|
343
|
-
}
|
|
344
|
-
if (ver1.patch !== ver2.patch) {
|
|
345
|
-
return ver1.patch < ver2.patch ? -1 : 1;
|
|
346
|
-
}
|
|
347
|
-
return 0;
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* Parse version string to SchemaVersion
|
|
351
|
-
*/
|
|
352
|
-
parseVersion(versionString) {
|
|
353
|
-
const parts = versionString.split(".").map(Number);
|
|
354
|
-
return {
|
|
355
|
-
major: parts[0] || 0,
|
|
356
|
-
minor: parts[1] || 0,
|
|
357
|
-
patch: parts[2] || 0,
|
|
358
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
359
|
-
description: "",
|
|
360
|
-
breaking: false
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* Create new version
|
|
365
|
-
*/
|
|
366
|
-
createVersion(major, minor, patch, description, breaking = false) {
|
|
367
|
-
return {
|
|
368
|
-
major,
|
|
369
|
-
minor,
|
|
370
|
-
patch,
|
|
371
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
372
|
-
description,
|
|
373
|
-
breaking
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Convert version to string
|
|
378
|
-
*/
|
|
379
|
-
versionToString(version) {
|
|
380
|
-
return `${version.major}.${version.minor}.${version.patch}`;
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Get version metadata
|
|
384
|
-
*/
|
|
385
|
-
getVersionMetadata(version) {
|
|
386
|
-
const history = this.versionHistory;
|
|
387
|
-
const currentIndex = history.findIndex(
|
|
388
|
-
(v) => this.versionToString(v) === this.versionToString(version)
|
|
389
|
-
);
|
|
390
|
-
return {
|
|
391
|
-
version,
|
|
392
|
-
previousVersion: currentIndex > 0 ? history[currentIndex - 1] : void 0,
|
|
393
|
-
changes: [version.description],
|
|
394
|
-
migrationsRequired: this.canMigrate(
|
|
395
|
-
this.currentVersion || version,
|
|
396
|
-
version
|
|
397
|
-
) ? [this.versionToString(version)] : [],
|
|
398
|
-
rollbackPossible: currentIndex > 0
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Get all registered versions
|
|
403
|
-
*/
|
|
404
|
-
getAllVersions() {
|
|
405
|
-
return Array.from(this.versions.values()).sort(
|
|
406
|
-
(a, b) => this.compareVersions(a, b)
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
/**
|
|
410
|
-
* Clear all versions (for testing)
|
|
411
|
-
*/
|
|
412
|
-
clear() {
|
|
413
|
-
this.versions.clear();
|
|
414
|
-
this.versionHistory = [];
|
|
415
|
-
this.compatibilityMatrix.clear();
|
|
416
|
-
this.currentVersion = null;
|
|
417
|
-
}
|
|
418
|
-
};
|
|
419
|
-
|
|
420
196
|
// src/versioning/MigrationEngine.ts
|
|
421
197
|
var MigrationEngine = class {
|
|
422
198
|
migrations = /* @__PURE__ */ new Map();
|
|
@@ -1086,11 +862,13 @@ var MigrationTracker = class _MigrationTracker {
|
|
|
1086
862
|
});
|
|
1087
863
|
previousHash = hash;
|
|
1088
864
|
}
|
|
1089
|
-
const persistedMigrations = normalizedMigrations.map(
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
865
|
+
const persistedMigrations = normalizedMigrations.map(
|
|
866
|
+
(migration, index) => ({
|
|
867
|
+
...migration,
|
|
868
|
+
previousHash: integrityEntries[index]?.previousHash,
|
|
869
|
+
integrityHash: integrityEntries[index]?.hash
|
|
870
|
+
})
|
|
871
|
+
);
|
|
1094
872
|
const data = {
|
|
1095
873
|
migrations: persistedMigrations,
|
|
1096
874
|
snapshots: Array.from(this.snapshots.entries()).map(
|
|
@@ -1113,7 +891,10 @@ var MigrationTracker = class _MigrationTracker {
|
|
|
1113
891
|
data
|
|
1114
892
|
};
|
|
1115
893
|
const serialize = this.persistence.serializer ?? ((value) => JSON.stringify(value));
|
|
1116
|
-
await this.persistence.adapter.setItem(
|
|
894
|
+
await this.persistence.adapter.setItem(
|
|
895
|
+
this.persistence.key,
|
|
896
|
+
serialize(envelope)
|
|
897
|
+
);
|
|
1117
898
|
}
|
|
1118
899
|
/**
|
|
1119
900
|
* Load tracker state and verify integrity chain.
|
|
@@ -1126,7 +907,9 @@ var MigrationTracker = class _MigrationTracker {
|
|
|
1126
907
|
if (!raw) {
|
|
1127
908
|
return { migrations: 0, snapshots: 0 };
|
|
1128
909
|
}
|
|
1129
|
-
const deserialize = this.persistence.deserializer ?? ((value) => JSON.parse(
|
|
910
|
+
const deserialize = this.persistence.deserializer ?? ((value) => JSON.parse(
|
|
911
|
+
value
|
|
912
|
+
));
|
|
1130
913
|
const envelope = deserialize(raw);
|
|
1131
914
|
if (envelope.version !== 1 || !envelope.data) {
|
|
1132
915
|
throw new Error("Invalid migration tracker persistence payload");
|
|
@@ -1189,7 +972,10 @@ var MigrationTracker = class _MigrationTracker {
|
|
|
1189
972
|
migrations: this.migrations.length,
|
|
1190
973
|
snapshots: this.snapshots.size
|
|
1191
974
|
});
|
|
1192
|
-
return {
|
|
975
|
+
return {
|
|
976
|
+
migrations: this.migrations.length,
|
|
977
|
+
snapshots: this.snapshots.size
|
|
978
|
+
};
|
|
1193
979
|
}
|
|
1194
980
|
/**
|
|
1195
981
|
* Remove persisted migration tracker state.
|
|
@@ -1311,489 +1097,6 @@ var MigrationTracker = class _MigrationTracker {
|
|
|
1311
1097
|
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
1312
1098
|
}
|
|
1313
1099
|
};
|
|
1314
|
-
var SyncCoordinator = class extends EventEmitter {
|
|
1315
|
-
nodes = /* @__PURE__ */ new Map();
|
|
1316
|
-
sessions = /* @__PURE__ */ new Map();
|
|
1317
|
-
syncEvents = [];
|
|
1318
|
-
nodeHeartbeats = /* @__PURE__ */ new Map();
|
|
1319
|
-
heartbeatInterval = null;
|
|
1320
|
-
// Crypto support
|
|
1321
|
-
cryptoProvider = null;
|
|
1322
|
-
nodesByDID = /* @__PURE__ */ new Map();
|
|
1323
|
-
// DID -> nodeId
|
|
1324
|
-
constructor() {
|
|
1325
|
-
super();
|
|
1326
|
-
}
|
|
1327
|
-
/**
|
|
1328
|
-
* Configure cryptographic provider for authenticated sync
|
|
1329
|
-
*/
|
|
1330
|
-
configureCrypto(provider) {
|
|
1331
|
-
this.cryptoProvider = provider;
|
|
1332
|
-
logger.debug("[SyncCoordinator] Crypto configured", {
|
|
1333
|
-
initialized: provider.isInitialized()
|
|
1334
|
-
});
|
|
1335
|
-
}
|
|
1336
|
-
/**
|
|
1337
|
-
* Check if crypto is configured
|
|
1338
|
-
*/
|
|
1339
|
-
isCryptoEnabled() {
|
|
1340
|
-
return this.cryptoProvider !== null && this.cryptoProvider.isInitialized();
|
|
1341
|
-
}
|
|
1342
|
-
/**
|
|
1343
|
-
* Register a node with DID-based identity
|
|
1344
|
-
*/
|
|
1345
|
-
async registerAuthenticatedNode(nodeInfo) {
|
|
1346
|
-
const node = {
|
|
1347
|
-
...nodeInfo
|
|
1348
|
-
};
|
|
1349
|
-
this.nodes.set(node.id, node);
|
|
1350
|
-
this.nodeHeartbeats.set(node.id, Date.now());
|
|
1351
|
-
this.nodesByDID.set(nodeInfo.did, node.id);
|
|
1352
|
-
if (this.cryptoProvider) {
|
|
1353
|
-
await this.cryptoProvider.registerRemoteNode({
|
|
1354
|
-
id: node.id,
|
|
1355
|
-
did: nodeInfo.did,
|
|
1356
|
-
publicSigningKey: nodeInfo.publicSigningKey,
|
|
1357
|
-
publicEncryptionKey: nodeInfo.publicEncryptionKey
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
|
-
const event = {
|
|
1361
|
-
type: "node-joined",
|
|
1362
|
-
nodeId: node.id,
|
|
1363
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1364
|
-
data: { did: nodeInfo.did, authenticated: true }
|
|
1365
|
-
};
|
|
1366
|
-
this.syncEvents.push(event);
|
|
1367
|
-
this.emit("node-joined", node);
|
|
1368
|
-
logger.debug("[SyncCoordinator] Authenticated node registered", {
|
|
1369
|
-
nodeId: node.id,
|
|
1370
|
-
did: nodeInfo.did,
|
|
1371
|
-
version: node.version
|
|
1372
|
-
});
|
|
1373
|
-
return node;
|
|
1374
|
-
}
|
|
1375
|
-
/**
|
|
1376
|
-
* Get node by DID
|
|
1377
|
-
*/
|
|
1378
|
-
getNodeByDID(did) {
|
|
1379
|
-
const nodeId = this.nodesByDID.get(did);
|
|
1380
|
-
if (!nodeId) return void 0;
|
|
1381
|
-
return this.nodes.get(nodeId);
|
|
1382
|
-
}
|
|
1383
|
-
/**
|
|
1384
|
-
* Get all authenticated nodes (nodes with DIDs)
|
|
1385
|
-
*/
|
|
1386
|
-
getAuthenticatedNodes() {
|
|
1387
|
-
return Array.from(this.nodes.values()).filter((n) => n.did);
|
|
1388
|
-
}
|
|
1389
|
-
/**
|
|
1390
|
-
* Create an authenticated sync session with UCAN-based authorization
|
|
1391
|
-
*/
|
|
1392
|
-
async createAuthenticatedSyncSession(initiatorDID, participantDIDs, options) {
|
|
1393
|
-
const initiatorNodeId = this.nodesByDID.get(initiatorDID);
|
|
1394
|
-
if (!initiatorNodeId) {
|
|
1395
|
-
throw new Error(`Initiator node with DID ${initiatorDID} not found`);
|
|
1396
|
-
}
|
|
1397
|
-
const participantIds = [];
|
|
1398
|
-
for (const did of participantDIDs) {
|
|
1399
|
-
const nodeId = this.nodesByDID.get(did);
|
|
1400
|
-
if (nodeId) {
|
|
1401
|
-
participantIds.push(nodeId);
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
let sessionToken;
|
|
1405
|
-
if (this.cryptoProvider && this.cryptoProvider.isInitialized()) {
|
|
1406
|
-
const capabilities = (options?.requiredCapabilities || ["aeon:sync:read", "aeon:sync:write"]).map((cap) => ({ can: cap, with: "*" }));
|
|
1407
|
-
if (participantDIDs.length > 0) {
|
|
1408
|
-
sessionToken = await this.cryptoProvider.createUCAN(
|
|
1409
|
-
participantDIDs[0],
|
|
1410
|
-
capabilities,
|
|
1411
|
-
{ expirationSeconds: 3600 }
|
|
1412
|
-
// 1 hour
|
|
1413
|
-
);
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
const session = {
|
|
1417
|
-
id: `sync-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
1418
|
-
initiatorId: initiatorNodeId,
|
|
1419
|
-
participantIds,
|
|
1420
|
-
status: "pending",
|
|
1421
|
-
startTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1422
|
-
itemsSynced: 0,
|
|
1423
|
-
itemsFailed: 0,
|
|
1424
|
-
conflictsDetected: 0,
|
|
1425
|
-
initiatorDID,
|
|
1426
|
-
participantDIDs,
|
|
1427
|
-
encryptionMode: options?.encryptionMode || "none",
|
|
1428
|
-
requiredCapabilities: options?.requiredCapabilities,
|
|
1429
|
-
sessionToken
|
|
1430
|
-
};
|
|
1431
|
-
this.sessions.set(session.id, session);
|
|
1432
|
-
const event = {
|
|
1433
|
-
type: "sync-started",
|
|
1434
|
-
sessionId: session.id,
|
|
1435
|
-
nodeId: initiatorNodeId,
|
|
1436
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1437
|
-
data: {
|
|
1438
|
-
authenticated: true,
|
|
1439
|
-
initiatorDID,
|
|
1440
|
-
participantCount: participantDIDs.length,
|
|
1441
|
-
encryptionMode: session.encryptionMode
|
|
1442
|
-
}
|
|
1443
|
-
};
|
|
1444
|
-
this.syncEvents.push(event);
|
|
1445
|
-
this.emit("sync-started", session);
|
|
1446
|
-
logger.debug("[SyncCoordinator] Authenticated sync session created", {
|
|
1447
|
-
sessionId: session.id,
|
|
1448
|
-
initiatorDID,
|
|
1449
|
-
participants: participantDIDs.length,
|
|
1450
|
-
encryptionMode: session.encryptionMode
|
|
1451
|
-
});
|
|
1452
|
-
return session;
|
|
1453
|
-
}
|
|
1454
|
-
/**
|
|
1455
|
-
* Verify a node's UCAN capabilities for a session
|
|
1456
|
-
*/
|
|
1457
|
-
async verifyNodeCapabilities(sessionId, nodeDID, token) {
|
|
1458
|
-
if (!this.cryptoProvider) {
|
|
1459
|
-
return { authorized: true };
|
|
1460
|
-
}
|
|
1461
|
-
const session = this.sessions.get(sessionId);
|
|
1462
|
-
if (!session) {
|
|
1463
|
-
return { authorized: false, error: `Session ${sessionId} not found` };
|
|
1464
|
-
}
|
|
1465
|
-
const result = await this.cryptoProvider.verifyUCAN(token, {
|
|
1466
|
-
requiredCapabilities: session.requiredCapabilities?.map((cap) => ({
|
|
1467
|
-
can: cap,
|
|
1468
|
-
with: "*"
|
|
1469
|
-
}))
|
|
1470
|
-
});
|
|
1471
|
-
if (!result.authorized) {
|
|
1472
|
-
logger.warn("[SyncCoordinator] Node capability verification failed", {
|
|
1473
|
-
sessionId,
|
|
1474
|
-
nodeDID,
|
|
1475
|
-
error: result.error
|
|
1476
|
-
});
|
|
1477
|
-
}
|
|
1478
|
-
return result;
|
|
1479
|
-
}
|
|
1480
|
-
/**
|
|
1481
|
-
* Register a node in the cluster
|
|
1482
|
-
*/
|
|
1483
|
-
registerNode(node) {
|
|
1484
|
-
this.nodes.set(node.id, node);
|
|
1485
|
-
this.nodeHeartbeats.set(node.id, Date.now());
|
|
1486
|
-
const event = {
|
|
1487
|
-
type: "node-joined",
|
|
1488
|
-
nodeId: node.id,
|
|
1489
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1490
|
-
};
|
|
1491
|
-
this.syncEvents.push(event);
|
|
1492
|
-
this.emit("node-joined", node);
|
|
1493
|
-
logger.debug("[SyncCoordinator] Node registered", {
|
|
1494
|
-
nodeId: node.id,
|
|
1495
|
-
address: node.address,
|
|
1496
|
-
version: node.version
|
|
1497
|
-
});
|
|
1498
|
-
}
|
|
1499
|
-
/**
|
|
1500
|
-
* Deregister a node from the cluster
|
|
1501
|
-
*/
|
|
1502
|
-
deregisterNode(nodeId) {
|
|
1503
|
-
const node = this.nodes.get(nodeId);
|
|
1504
|
-
if (!node) {
|
|
1505
|
-
throw new Error(`Node ${nodeId} not found`);
|
|
1506
|
-
}
|
|
1507
|
-
this.nodes.delete(nodeId);
|
|
1508
|
-
this.nodeHeartbeats.delete(nodeId);
|
|
1509
|
-
const event = {
|
|
1510
|
-
type: "node-left",
|
|
1511
|
-
nodeId,
|
|
1512
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1513
|
-
};
|
|
1514
|
-
this.syncEvents.push(event);
|
|
1515
|
-
this.emit("node-left", node);
|
|
1516
|
-
logger.debug("[SyncCoordinator] Node deregistered", { nodeId });
|
|
1517
|
-
}
|
|
1518
|
-
/**
|
|
1519
|
-
* Create a new sync session
|
|
1520
|
-
*/
|
|
1521
|
-
createSyncSession(initiatorId, participantIds) {
|
|
1522
|
-
const node = this.nodes.get(initiatorId);
|
|
1523
|
-
if (!node) {
|
|
1524
|
-
throw new Error(`Initiator node ${initiatorId} not found`);
|
|
1525
|
-
}
|
|
1526
|
-
const session = {
|
|
1527
|
-
id: `sync-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
1528
|
-
initiatorId,
|
|
1529
|
-
participantIds,
|
|
1530
|
-
status: "pending",
|
|
1531
|
-
startTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1532
|
-
itemsSynced: 0,
|
|
1533
|
-
itemsFailed: 0,
|
|
1534
|
-
conflictsDetected: 0
|
|
1535
|
-
};
|
|
1536
|
-
this.sessions.set(session.id, session);
|
|
1537
|
-
const event = {
|
|
1538
|
-
type: "sync-started",
|
|
1539
|
-
sessionId: session.id,
|
|
1540
|
-
nodeId: initiatorId,
|
|
1541
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1542
|
-
};
|
|
1543
|
-
this.syncEvents.push(event);
|
|
1544
|
-
this.emit("sync-started", session);
|
|
1545
|
-
logger.debug("[SyncCoordinator] Sync session created", {
|
|
1546
|
-
sessionId: session.id,
|
|
1547
|
-
initiator: initiatorId,
|
|
1548
|
-
participants: participantIds.length
|
|
1549
|
-
});
|
|
1550
|
-
return session;
|
|
1551
|
-
}
|
|
1552
|
-
/**
|
|
1553
|
-
* Update sync session
|
|
1554
|
-
*/
|
|
1555
|
-
updateSyncSession(sessionId, updates) {
|
|
1556
|
-
const session = this.sessions.get(sessionId);
|
|
1557
|
-
if (!session) {
|
|
1558
|
-
throw new Error(`Session ${sessionId} not found`);
|
|
1559
|
-
}
|
|
1560
|
-
Object.assign(session, updates);
|
|
1561
|
-
if (updates.status === "completed" || updates.status === "failed") {
|
|
1562
|
-
session.endTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
1563
|
-
const event = {
|
|
1564
|
-
type: "sync-completed",
|
|
1565
|
-
sessionId,
|
|
1566
|
-
nodeId: session.initiatorId,
|
|
1567
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1568
|
-
data: { status: updates.status, itemsSynced: session.itemsSynced }
|
|
1569
|
-
};
|
|
1570
|
-
this.syncEvents.push(event);
|
|
1571
|
-
this.emit("sync-completed", session);
|
|
1572
|
-
}
|
|
1573
|
-
logger.debug("[SyncCoordinator] Sync session updated", {
|
|
1574
|
-
sessionId,
|
|
1575
|
-
status: session.status,
|
|
1576
|
-
itemsSynced: session.itemsSynced
|
|
1577
|
-
});
|
|
1578
|
-
}
|
|
1579
|
-
/**
|
|
1580
|
-
* Record a conflict during sync
|
|
1581
|
-
*/
|
|
1582
|
-
recordConflict(sessionId, nodeId, conflictData) {
|
|
1583
|
-
const session = this.sessions.get(sessionId);
|
|
1584
|
-
if (session) {
|
|
1585
|
-
session.conflictsDetected++;
|
|
1586
|
-
const event = {
|
|
1587
|
-
type: "conflict-detected",
|
|
1588
|
-
sessionId,
|
|
1589
|
-
nodeId,
|
|
1590
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1591
|
-
data: conflictData
|
|
1592
|
-
};
|
|
1593
|
-
this.syncEvents.push(event);
|
|
1594
|
-
this.emit("conflict-detected", { session, nodeId, conflictData });
|
|
1595
|
-
logger.debug("[SyncCoordinator] Conflict recorded", {
|
|
1596
|
-
sessionId,
|
|
1597
|
-
nodeId,
|
|
1598
|
-
totalConflicts: session.conflictsDetected
|
|
1599
|
-
});
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
/**
|
|
1603
|
-
* Update node status
|
|
1604
|
-
*/
|
|
1605
|
-
updateNodeStatus(nodeId, status) {
|
|
1606
|
-
const node = this.nodes.get(nodeId);
|
|
1607
|
-
if (!node) {
|
|
1608
|
-
throw new Error(`Node ${nodeId} not found`);
|
|
1609
|
-
}
|
|
1610
|
-
node.status = status;
|
|
1611
|
-
this.nodeHeartbeats.set(nodeId, Date.now());
|
|
1612
|
-
logger.debug("[SyncCoordinator] Node status updated", {
|
|
1613
|
-
nodeId,
|
|
1614
|
-
status
|
|
1615
|
-
});
|
|
1616
|
-
}
|
|
1617
|
-
/**
|
|
1618
|
-
* Record heartbeat from node
|
|
1619
|
-
*/
|
|
1620
|
-
recordHeartbeat(nodeId) {
|
|
1621
|
-
const node = this.nodes.get(nodeId);
|
|
1622
|
-
if (!node) {
|
|
1623
|
-
return;
|
|
1624
|
-
}
|
|
1625
|
-
node.lastHeartbeat = (/* @__PURE__ */ new Date()).toISOString();
|
|
1626
|
-
this.nodeHeartbeats.set(nodeId, Date.now());
|
|
1627
|
-
}
|
|
1628
|
-
/**
|
|
1629
|
-
* Get all nodes
|
|
1630
|
-
*/
|
|
1631
|
-
getNodes() {
|
|
1632
|
-
return Array.from(this.nodes.values());
|
|
1633
|
-
}
|
|
1634
|
-
/**
|
|
1635
|
-
* Get node by ID
|
|
1636
|
-
*/
|
|
1637
|
-
getNode(nodeId) {
|
|
1638
|
-
return this.nodes.get(nodeId);
|
|
1639
|
-
}
|
|
1640
|
-
/**
|
|
1641
|
-
* Get online nodes
|
|
1642
|
-
*/
|
|
1643
|
-
getOnlineNodes() {
|
|
1644
|
-
return Array.from(this.nodes.values()).filter((n) => n.status === "online");
|
|
1645
|
-
}
|
|
1646
|
-
/**
|
|
1647
|
-
* Get nodes by capability
|
|
1648
|
-
*/
|
|
1649
|
-
getNodesByCapability(capability) {
|
|
1650
|
-
return Array.from(this.nodes.values()).filter(
|
|
1651
|
-
(n) => n.capabilities.includes(capability)
|
|
1652
|
-
);
|
|
1653
|
-
}
|
|
1654
|
-
/**
|
|
1655
|
-
* Get sync session
|
|
1656
|
-
*/
|
|
1657
|
-
getSyncSession(sessionId) {
|
|
1658
|
-
return this.sessions.get(sessionId);
|
|
1659
|
-
}
|
|
1660
|
-
/**
|
|
1661
|
-
* Get all sync sessions
|
|
1662
|
-
*/
|
|
1663
|
-
getAllSyncSessions() {
|
|
1664
|
-
return Array.from(this.sessions.values());
|
|
1665
|
-
}
|
|
1666
|
-
/**
|
|
1667
|
-
* Get active sync sessions
|
|
1668
|
-
*/
|
|
1669
|
-
getActiveSyncSessions() {
|
|
1670
|
-
return Array.from(this.sessions.values()).filter(
|
|
1671
|
-
(s) => s.status === "active"
|
|
1672
|
-
);
|
|
1673
|
-
}
|
|
1674
|
-
/**
|
|
1675
|
-
* Get sessions for a node
|
|
1676
|
-
*/
|
|
1677
|
-
getSessionsForNode(nodeId) {
|
|
1678
|
-
return Array.from(this.sessions.values()).filter(
|
|
1679
|
-
(s) => s.initiatorId === nodeId || s.participantIds.includes(nodeId)
|
|
1680
|
-
);
|
|
1681
|
-
}
|
|
1682
|
-
/**
|
|
1683
|
-
* Get sync statistics
|
|
1684
|
-
*/
|
|
1685
|
-
getStatistics() {
|
|
1686
|
-
const sessions = Array.from(this.sessions.values());
|
|
1687
|
-
const completed = sessions.filter((s) => s.status === "completed").length;
|
|
1688
|
-
const failed = sessions.filter((s) => s.status === "failed").length;
|
|
1689
|
-
const active = sessions.filter((s) => s.status === "active").length;
|
|
1690
|
-
const totalItemsSynced = sessions.reduce(
|
|
1691
|
-
(sum, s) => sum + s.itemsSynced,
|
|
1692
|
-
0
|
|
1693
|
-
);
|
|
1694
|
-
const totalConflicts = sessions.reduce(
|
|
1695
|
-
(sum, s) => sum + s.conflictsDetected,
|
|
1696
|
-
0
|
|
1697
|
-
);
|
|
1698
|
-
return {
|
|
1699
|
-
totalNodes: this.nodes.size,
|
|
1700
|
-
onlineNodes: this.getOnlineNodes().length,
|
|
1701
|
-
offlineNodes: this.nodes.size - this.getOnlineNodes().length,
|
|
1702
|
-
totalSessions: sessions.length,
|
|
1703
|
-
activeSessions: active,
|
|
1704
|
-
completedSessions: completed,
|
|
1705
|
-
failedSessions: failed,
|
|
1706
|
-
successRate: sessions.length > 0 ? completed / sessions.length * 100 : 0,
|
|
1707
|
-
totalItemsSynced,
|
|
1708
|
-
totalConflicts,
|
|
1709
|
-
averageConflictsPerSession: sessions.length > 0 ? totalConflicts / sessions.length : 0
|
|
1710
|
-
};
|
|
1711
|
-
}
|
|
1712
|
-
/**
|
|
1713
|
-
* Get sync events
|
|
1714
|
-
*/
|
|
1715
|
-
getSyncEvents(limit) {
|
|
1716
|
-
const events = [...this.syncEvents];
|
|
1717
|
-
if (limit) {
|
|
1718
|
-
return events.slice(-limit);
|
|
1719
|
-
}
|
|
1720
|
-
return events;
|
|
1721
|
-
}
|
|
1722
|
-
/**
|
|
1723
|
-
* Get sync events for session
|
|
1724
|
-
*/
|
|
1725
|
-
getSessionEvents(sessionId) {
|
|
1726
|
-
return this.syncEvents.filter((e) => e.sessionId === sessionId);
|
|
1727
|
-
}
|
|
1728
|
-
/**
|
|
1729
|
-
* Check node health
|
|
1730
|
-
*/
|
|
1731
|
-
getNodeHealth() {
|
|
1732
|
-
const health = {};
|
|
1733
|
-
for (const [nodeId, lastHeartbeat] of this.nodeHeartbeats) {
|
|
1734
|
-
const now = Date.now();
|
|
1735
|
-
const downtime = now - lastHeartbeat;
|
|
1736
|
-
const isHealthy = downtime < 3e4;
|
|
1737
|
-
health[nodeId] = {
|
|
1738
|
-
isHealthy,
|
|
1739
|
-
downtime
|
|
1740
|
-
};
|
|
1741
|
-
}
|
|
1742
|
-
return health;
|
|
1743
|
-
}
|
|
1744
|
-
/**
|
|
1745
|
-
* Start heartbeat monitoring
|
|
1746
|
-
*/
|
|
1747
|
-
startHeartbeatMonitoring(interval = 5e3) {
|
|
1748
|
-
if (this.heartbeatInterval) {
|
|
1749
|
-
return;
|
|
1750
|
-
}
|
|
1751
|
-
this.heartbeatInterval = setInterval(() => {
|
|
1752
|
-
const health = this.getNodeHealth();
|
|
1753
|
-
for (const [nodeId, { isHealthy }] of Object.entries(health)) {
|
|
1754
|
-
const node = this.nodes.get(nodeId);
|
|
1755
|
-
if (!node) {
|
|
1756
|
-
continue;
|
|
1757
|
-
}
|
|
1758
|
-
const newStatus = isHealthy ? "online" : "offline";
|
|
1759
|
-
if (node.status !== newStatus) {
|
|
1760
|
-
this.updateNodeStatus(nodeId, newStatus);
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
}, interval);
|
|
1764
|
-
logger.debug("[SyncCoordinator] Heartbeat monitoring started", {
|
|
1765
|
-
interval
|
|
1766
|
-
});
|
|
1767
|
-
}
|
|
1768
|
-
/**
|
|
1769
|
-
* Stop heartbeat monitoring
|
|
1770
|
-
*/
|
|
1771
|
-
stopHeartbeatMonitoring() {
|
|
1772
|
-
if (this.heartbeatInterval) {
|
|
1773
|
-
clearInterval(this.heartbeatInterval);
|
|
1774
|
-
this.heartbeatInterval = null;
|
|
1775
|
-
logger.debug("[SyncCoordinator] Heartbeat monitoring stopped");
|
|
1776
|
-
}
|
|
1777
|
-
}
|
|
1778
|
-
/**
|
|
1779
|
-
* Clear all state (for testing)
|
|
1780
|
-
*/
|
|
1781
|
-
clear() {
|
|
1782
|
-
this.nodes.clear();
|
|
1783
|
-
this.sessions.clear();
|
|
1784
|
-
this.syncEvents = [];
|
|
1785
|
-
this.nodeHeartbeats.clear();
|
|
1786
|
-
this.nodesByDID.clear();
|
|
1787
|
-
this.cryptoProvider = null;
|
|
1788
|
-
this.stopHeartbeatMonitoring();
|
|
1789
|
-
}
|
|
1790
|
-
/**
|
|
1791
|
-
* Get the crypto provider (for advanced usage)
|
|
1792
|
-
*/
|
|
1793
|
-
getCryptoProvider() {
|
|
1794
|
-
return this.cryptoProvider;
|
|
1795
|
-
}
|
|
1796
|
-
};
|
|
1797
1100
|
|
|
1798
1101
|
// src/distributed/ReplicationManager.ts
|
|
1799
1102
|
var ReplicationManager = class _ReplicationManager {
|
|
@@ -2275,7 +1578,10 @@ var ReplicationManager = class _ReplicationManager {
|
|
|
2275
1578
|
data
|
|
2276
1579
|
};
|
|
2277
1580
|
const serialize = this.persistence.serializer ?? ((value) => JSON.stringify(value));
|
|
2278
|
-
await this.persistence.adapter.setItem(
|
|
1581
|
+
await this.persistence.adapter.setItem(
|
|
1582
|
+
this.persistence.key,
|
|
1583
|
+
serialize(envelope)
|
|
1584
|
+
);
|
|
2279
1585
|
}
|
|
2280
1586
|
/**
|
|
2281
1587
|
* Load replication snapshot from persistence.
|
|
@@ -2988,7 +2294,10 @@ var SyncProtocol = class _SyncProtocol {
|
|
|
2988
2294
|
data
|
|
2989
2295
|
};
|
|
2990
2296
|
const serialize = this.persistence.serializer ?? ((value) => JSON.stringify(value));
|
|
2991
|
-
await this.persistence.adapter.setItem(
|
|
2297
|
+
await this.persistence.adapter.setItem(
|
|
2298
|
+
this.persistence.key,
|
|
2299
|
+
serialize(envelope)
|
|
2300
|
+
);
|
|
2992
2301
|
}
|
|
2993
2302
|
/**
|
|
2994
2303
|
* Load protocol state from persistence.
|
|
@@ -5232,15 +4541,7 @@ var AdaptiveCompressionOptimizer = class {
|
|
|
5232
4541
|
};
|
|
5233
4542
|
}
|
|
5234
4543
|
};
|
|
5235
|
-
var adaptiveOptimizerInstance = null;
|
|
5236
|
-
function getAdaptiveCompressionOptimizer() {
|
|
5237
|
-
if (!adaptiveOptimizerInstance) {
|
|
5238
|
-
adaptiveOptimizerInstance = new AdaptiveCompressionOptimizer();
|
|
5239
|
-
}
|
|
5240
|
-
return adaptiveOptimizerInstance;
|
|
5241
|
-
}
|
|
5242
4544
|
function resetAdaptiveCompressionOptimizer() {
|
|
5243
|
-
adaptiveOptimizerInstance = null;
|
|
5244
4545
|
}
|
|
5245
4546
|
var logger8 = getLogger();
|
|
5246
4547
|
var AgentPresenceManager = class extends EventEmitter {
|
|
@@ -5685,12 +4986,6 @@ var AgentPresenceManager = class extends EventEmitter {
|
|
|
5685
4986
|
}
|
|
5686
4987
|
};
|
|
5687
4988
|
var instances = /* @__PURE__ */ new Map();
|
|
5688
|
-
function getAgentPresenceManager(sessionId) {
|
|
5689
|
-
if (!instances.has(sessionId)) {
|
|
5690
|
-
instances.set(sessionId, new AgentPresenceManager(sessionId));
|
|
5691
|
-
}
|
|
5692
|
-
return instances.get(sessionId);
|
|
5693
|
-
}
|
|
5694
4989
|
function clearAgentPresenceManager(sessionId) {
|
|
5695
4990
|
const instance = instances.get(sessionId);
|
|
5696
4991
|
if (instance) {
|
|
@@ -5792,6 +5087,34 @@ var NullCryptoProvider = class {
|
|
|
5792
5087
|
}
|
|
5793
5088
|
};
|
|
5794
5089
|
|
|
5795
|
-
|
|
5090
|
+
// src/index.ts
|
|
5091
|
+
var Link = (() => {
|
|
5092
|
+
throw new Error(
|
|
5093
|
+
"Link: Stub called from @affectively/aeon. Import from @affectively/aeon-flux-react or mock in tests."
|
|
5094
|
+
);
|
|
5095
|
+
});
|
|
5096
|
+
var useAeonPage = (() => {
|
|
5097
|
+
throw new Error(
|
|
5098
|
+
"useAeonPage: Stub called from @affectively/aeon. Import from @affectively/aeon-flux-react or mock in tests."
|
|
5099
|
+
);
|
|
5100
|
+
});
|
|
5101
|
+
var getAdaptiveCompressionOptimizer = (() => {
|
|
5102
|
+
throw new Error("getAdaptiveCompressionOptimizer: Stub");
|
|
5103
|
+
});
|
|
5104
|
+
var SchemaVersionManager2 = class {
|
|
5105
|
+
constructor() {
|
|
5106
|
+
throw new Error("SchemaVersionManager: Stub");
|
|
5107
|
+
}
|
|
5108
|
+
};
|
|
5109
|
+
var getAgentPresenceManager = (() => {
|
|
5110
|
+
throw new Error("getAgentPresenceManager: Stub");
|
|
5111
|
+
});
|
|
5112
|
+
var SyncCoordinator2 = class {
|
|
5113
|
+
constructor() {
|
|
5114
|
+
throw new Error("SyncCoordinator: Stub");
|
|
5115
|
+
}
|
|
5116
|
+
};
|
|
5117
|
+
|
|
5118
|
+
export { AEON_CAPABILITIES, AdaptiveCompressionOptimizer, AgentPresenceManager, BatchTimingOptimizer, CompressionEngine, DEFAULT_CRYPTO_CONFIG, DashStorageAdapter, DataTransformer, DeltaSyncOptimizer, InMemoryStorageAdapter, Link, MigrationEngine, MigrationTracker, NullCryptoProvider, OfflineOperationQueue, PrefetchingEngine, ReplicationManager, SchemaVersionManager2 as SchemaVersionManager, StateReconciler, SyncCoordinator2 as SyncCoordinator, SyncProtocol, clearAgentPresenceManager, createNamespacedLogger, disableLogging, getAdaptiveCompressionOptimizer, getAgentPresenceManager, getBatchTimingOptimizer, getCompressionEngine, getDeltaSyncOptimizer, getLogger, getOfflineOperationQueue, getPrefetchingEngine, logger, resetAdaptiveCompressionOptimizer, resetBatchTimingOptimizer, resetCompressionEngine, resetDeltaSyncOptimizer, resetLogger, resetOfflineOperationQueue, resetPrefetchingEngine, setLogger, useAeonPage };
|
|
5796
5119
|
//# sourceMappingURL=index.js.map
|
|
5797
5120
|
//# sourceMappingURL=index.js.map
|