holosphere 1.3.0-alpha0 → 1.3.0-alpha3

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * HoloSphere Bundle v1.3.0-alpha0
2
+ * HoloSphere Bundle v1.3.0-alpha3
3
3
  * Holonic Geospatial Communication Infrastructure
4
4
  *
5
5
  * Includes:
@@ -9,7 +9,7 @@
9
9
  * - Ajv (JSON schema validation)
10
10
  *
11
11
  * Usage:
12
- * <script src="https://unpkg.com/holosphere@1.3.0-alpha0/holosphere-bundle.js"></script>
12
+ * <script src="https://unpkg.com/holosphere@1.3.0-alpha3/holosphere-bundle.js"></script>
13
13
  * <script>
14
14
  * const hs = new HoloSphere('myapp');
15
15
  * </script>
@@ -7067,7 +7067,7 @@ var HoloSphere = (() => {
7067
7067
  constructor(opts = {}) {
7068
7068
  this.schemas = {};
7069
7069
  this.refs = {};
7070
- this.formats = {};
7070
+ this.formats = /* @__PURE__ */ Object.create(null);
7071
7071
  this._compilations = /* @__PURE__ */ new Set();
7072
7072
  this._loading = {};
7073
7073
  this._cache = /* @__PURE__ */ new Map();
@@ -7848,6 +7848,7 @@ var HoloSphere = (() => {
7848
7848
  "use strict";
7849
7849
  Object.defineProperty(exports, "__esModule", { value: true });
7850
7850
  var code_1 = require_code2();
7851
+ var util_1 = require_util();
7851
7852
  var codegen_1 = require_codegen();
7852
7853
  var error = {
7853
7854
  message: ({ schemaCode }) => (0, codegen_1.str)`must match pattern "${schemaCode}"`,
@@ -7860,10 +7861,18 @@ var HoloSphere = (() => {
7860
7861
  $data: true,
7861
7862
  error,
7862
7863
  code(cxt) {
7863
- const { data, $data, schema, schemaCode, it } = cxt;
7864
+ const { gen, data, $data, schema, schemaCode, it } = cxt;
7864
7865
  const u = it.opts.unicodeRegExp ? "u" : "";
7865
- const regExp = $data ? (0, codegen_1._)`(new RegExp(${schemaCode}, ${u}))` : (0, code_1.usePattern)(cxt, schema);
7866
- cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`);
7866
+ if ($data) {
7867
+ const { regExp } = it.opts.code;
7868
+ const regExpCode = regExp.code === "new RegExp" ? (0, codegen_1._)`new RegExp` : (0, util_1.useFunc)(gen, regExp);
7869
+ const valid = gen.let("valid");
7870
+ gen.try(() => gen.assign(valid, (0, codegen_1._)`${regExpCode}(${schemaCode}, ${u}).test(${data})`), () => gen.assign(valid, false));
7871
+ cxt.fail$data((0, codegen_1._)`!${valid}`);
7872
+ } else {
7873
+ const regExp = (0, code_1.usePattern)(cxt, schema);
7874
+ cxt.fail$data((0, codegen_1._)`!${regExp}.test(${data})`);
7875
+ }
7867
7876
  }
7868
7877
  };
7869
7878
  exports.default = def;
@@ -10074,7 +10083,7 @@ var HoloSphere = (() => {
10074
10083
  var discriminator_1 = require_discriminator();
10075
10084
  var json_schema_2019_09_1 = require_json_schema_2019_09();
10076
10085
  var META_SCHEMA_ID = "https://json-schema.org/draft/2019-09/schema";
10077
- var Ajv20193 = class extends core_1.default {
10086
+ var Ajv20192 = class extends core_1.default {
10078
10087
  constructor(opts = {}) {
10079
10088
  super({
10080
10089
  ...opts,
@@ -10104,11 +10113,11 @@ var HoloSphere = (() => {
10104
10113
  return this.opts.defaultMeta = super.defaultMeta() || (this.getSchema(META_SCHEMA_ID) ? META_SCHEMA_ID : void 0);
10105
10114
  }
10106
10115
  };
10107
- exports.Ajv2019 = Ajv20193;
10108
- module.exports = exports = Ajv20193;
10109
- module.exports.Ajv2019 = Ajv20193;
10116
+ exports.Ajv2019 = Ajv20192;
10117
+ module.exports = exports = Ajv20192;
10118
+ module.exports.Ajv2019 = Ajv20192;
10110
10119
  Object.defineProperty(exports, "__esModule", { value: true });
10111
- exports.default = Ajv20193;
10120
+ exports.default = Ajv20192;
10112
10121
  var validate_1 = require_validate();
10113
10122
  Object.defineProperty(exports, "KeywordCxt", { enumerable: true, get: function() {
10114
10123
  return validate_1.KeywordCxt;
@@ -24223,7 +24232,120 @@ var HoloSphere = (() => {
24223
24232
 
24224
24233
  // holosphere.js
24225
24234
  var import_gun = __toESM(require_browser(), 1);
24226
- var import__2 = __toESM(require__(), 1);
24235
+ var import__ = __toESM(require__(), 1);
24236
+
24237
+ // hologram.js
24238
+ function createHologram(holoInstance, holon, lens, data) {
24239
+ if (isHologram(data)) {
24240
+ return {
24241
+ id: data.id,
24242
+ soul: data.soul
24243
+ };
24244
+ }
24245
+ if (!holon || !lens || !data || !data.id) {
24246
+ throw new Error("createHologram: Missing required parameters for non-hologram data");
24247
+ }
24248
+ const soul = `${holoInstance.appname}/${holon}/${lens}/${data.id}`;
24249
+ return {
24250
+ id: data.id,
24251
+ soul
24252
+ };
24253
+ }
24254
+ function parseSoulPath(soul) {
24255
+ if (typeof soul !== "string") return null;
24256
+ const parts = soul.split("/");
24257
+ if (parts.length < 4) return null;
24258
+ const key = parts.slice(3).join("/");
24259
+ return {
24260
+ appname: parts[0],
24261
+ holon: parts[1],
24262
+ lens: parts[2],
24263
+ key
24264
+ };
24265
+ }
24266
+ function isHologram(data) {
24267
+ if (!data || typeof data !== "object") {
24268
+ return false;
24269
+ }
24270
+ if (data.id && typeof data.soul === "string" && data.soul.length > 0) {
24271
+ if (data.soul.includes("/")) {
24272
+ return true;
24273
+ }
24274
+ }
24275
+ return false;
24276
+ }
24277
+ function attachHologramMeta(originalData, hologramSoul) {
24278
+ const parts = parseSoulPath(hologramSoul);
24279
+ return {
24280
+ ...originalData,
24281
+ _hologram: {
24282
+ isHologram: true,
24283
+ soul: hologramSoul,
24284
+ sourceHolon: parts?.holon ?? null,
24285
+ sourceLens: parts?.lens ?? null,
24286
+ sourceKey: parts?.key ?? null,
24287
+ resolvedAt: Date.now()
24288
+ }
24289
+ };
24290
+ }
24291
+ async function resolveHologram(holoInstance, hologram, options = {}) {
24292
+ if (!isHologram(hologram)) {
24293
+ return hologram;
24294
+ }
24295
+ const {
24296
+ followHolograms = true,
24297
+ visited = /* @__PURE__ */ new Set(),
24298
+ maxDepth = 10,
24299
+ currentDepth = 0
24300
+ } = options;
24301
+ if (currentDepth >= maxDepth) {
24302
+ console.warn(`!!! Maximum resolution depth (${maxDepth}) reached for soul: ${hologram.soul}. Stopping resolution.`);
24303
+ return null;
24304
+ }
24305
+ if (hologram.soul && visited.has(hologram.soul)) {
24306
+ console.warn(`!!! CIRCULAR hologram detected for soul: ${hologram.soul}. Breaking loop.`);
24307
+ return null;
24308
+ }
24309
+ try {
24310
+ if (hologram.soul) {
24311
+ const soulInfo = parseSoulPath(hologram.soul);
24312
+ if (!soulInfo) {
24313
+ console.warn(`Invalid soul format: ${hologram.soul}`);
24314
+ return null;
24315
+ }
24316
+ const nextVisited = new Set(visited);
24317
+ nextVisited.add(hologram.soul);
24318
+ const originalData = await holoInstance.get(
24319
+ soulInfo.holon,
24320
+ soulInfo.lens,
24321
+ soulInfo.key,
24322
+ null,
24323
+ {
24324
+ resolveHolograms: followHolograms,
24325
+ visited: nextVisited,
24326
+ maxDepth,
24327
+ currentDepth: currentDepth + 1
24328
+ }
24329
+ );
24330
+ if (originalData && !originalData._invalidHologram) {
24331
+ return attachHologramMeta(originalData, hologram.soul);
24332
+ } else {
24333
+ console.warn(`!!! Original data NOT FOUND for soul: ${hologram.soul}. Removing broken hologram.`);
24334
+ return null;
24335
+ }
24336
+ } else {
24337
+ console.warn("!!! resolveHologram called with object missing soul:", hologram);
24338
+ return null;
24339
+ }
24340
+ } catch (error) {
24341
+ if (error.message?.startsWith("CIRCULAR_REFERENCE")) {
24342
+ console.warn(`!!! Circular reference detected during hologram resolution: ${error.message}`);
24343
+ return null;
24344
+ }
24345
+ console.error(`!!! Error resolving hologram: ${error.message}`, error);
24346
+ return null;
24347
+ }
24348
+ }
24227
24349
 
24228
24350
  // federation.js
24229
24351
  async function federate(holosphere, spaceId1, spaceId2, password1 = null, password2 = null, bidirectional = true, lensConfig = {}) {
@@ -24233,109 +24355,84 @@ var HoloSphere = (() => {
24233
24355
  if (spaceId1 === spaceId2) {
24234
24356
  throw new Error("Cannot federate a space with itself");
24235
24357
  }
24236
- const { federate: federate2 = [], notify = [] } = lensConfig;
24237
- if (!Array.isArray(federate2) || !Array.isArray(notify)) {
24238
- throw new Error("federate: lensConfig.federate and lensConfig.notify must be arrays");
24239
- }
24240
- const federateLenses = federate2;
24241
- const notifyLenses = notify;
24358
+ const { inbound = [], outbound = [] } = lensConfig;
24359
+ if (!Array.isArray(inbound) || !Array.isArray(outbound)) {
24360
+ throw new Error("federate: lensConfig.inbound and lensConfig.outbound must be arrays");
24361
+ }
24362
+ const applyDirection = (fedInfo, partnerId, partnerInbound, partnerOutbound) => {
24363
+ if (!fedInfo.federated) fedInfo.federated = [];
24364
+ if (!fedInfo.inbound) fedInfo.inbound = [];
24365
+ if (!fedInfo.outbound) fedInfo.outbound = [];
24366
+ if (!fedInfo.lensConfig) fedInfo.lensConfig = {};
24367
+ if (!fedInfo.federated.includes(partnerId)) {
24368
+ fedInfo.federated.push(partnerId);
24369
+ }
24370
+ const hasInbound = partnerInbound.length > 0;
24371
+ const hasOutbound = partnerOutbound.length > 0;
24372
+ if (hasInbound && !fedInfo.inbound.includes(partnerId)) {
24373
+ fedInfo.inbound.push(partnerId);
24374
+ } else if (!hasInbound) {
24375
+ fedInfo.inbound = fedInfo.inbound.filter((id) => id !== partnerId);
24376
+ }
24377
+ if (hasOutbound && !fedInfo.outbound.includes(partnerId)) {
24378
+ fedInfo.outbound.push(partnerId);
24379
+ } else if (!hasOutbound) {
24380
+ fedInfo.outbound = fedInfo.outbound.filter((id) => id !== partnerId);
24381
+ }
24382
+ fedInfo.lensConfig[partnerId] = {
24383
+ inbound: [...partnerInbound],
24384
+ outbound: [...partnerOutbound],
24385
+ timestamp: Date.now()
24386
+ };
24387
+ fedInfo.timestamp = Date.now();
24388
+ };
24242
24389
  try {
24243
24390
  let fedInfo1 = null;
24244
24391
  try {
24245
24392
  fedInfo1 = await holosphere.getGlobal("federation", spaceId1, password1);
24246
- } catch (error) {
24393
+ } catch {
24247
24394
  }
24248
24395
  if (fedInfo1 == null) {
24249
24396
  fedInfo1 = {
24250
24397
  id: spaceId1,
24251
24398
  name: spaceId1,
24252
- federation: [],
24253
- notify: [],
24399
+ federated: [],
24400
+ inbound: [],
24401
+ outbound: [],
24254
24402
  lensConfig: {},
24255
- // New field for lens-specific settings
24403
+ partnerNames: {},
24256
24404
  timestamp: Date.now()
24257
24405
  };
24258
24406
  }
24259
- if (!fedInfo1.federation) fedInfo1.federation = [];
24260
- if (!fedInfo1.notify) fedInfo1.notify = [];
24261
- if (!fedInfo1.lensConfig) fedInfo1.lensConfig = {};
24262
- if (!fedInfo1.federation.includes(spaceId2)) {
24263
- fedInfo1.federation.push(spaceId2);
24264
- }
24265
- if (!fedInfo1.notify.includes(spaceId2)) {
24266
- fedInfo1.notify.push(spaceId2);
24267
- }
24268
- const newLensConfigsForSpace1 = { ...fedInfo1.lensConfig || {} };
24269
- newLensConfigsForSpace1[spaceId2] = {
24270
- // Add/update config for the target spaceId2
24271
- federate: [...federateLenses],
24272
- // federateLenses & notifyLenses are from the main lensConfig parameter
24273
- notify: [...notifyLenses],
24274
- timestamp: Date.now()
24275
- };
24276
- fedInfo1.lensConfig = newLensConfigsForSpace1;
24277
- fedInfo1.timestamp = Date.now();
24407
+ applyDirection(fedInfo1, spaceId2, inbound, outbound);
24278
24408
  try {
24279
24409
  await holosphere.putGlobal("federation", fedInfo1, password1);
24280
24410
  } catch (error) {
24281
24411
  throw new Error(`Failed to create federation: ${error.message}`);
24282
24412
  }
24283
- {
24413
+ if (bidirectional) {
24284
24414
  let fedInfo2 = null;
24285
24415
  try {
24286
24416
  fedInfo2 = await holosphere.getGlobal("federation", spaceId2, password2);
24287
- } catch (error) {
24417
+ } catch {
24288
24418
  }
24289
24419
  if (fedInfo2 == null) {
24290
24420
  fedInfo2 = {
24291
24421
  id: spaceId2,
24292
24422
  name: spaceId2,
24293
- federation: [],
24294
- notify: [],
24423
+ federated: [],
24424
+ inbound: [],
24425
+ outbound: [],
24295
24426
  lensConfig: {},
24296
- // New field for lens-specific settings
24427
+ partnerNames: {},
24297
24428
  timestamp: Date.now()
24298
24429
  };
24299
24430
  }
24300
- if (!fedInfo2.federation) fedInfo2.federation = [];
24301
- if (!fedInfo2.notify) fedInfo2.notify = [];
24302
- if (!fedInfo2.lensConfig) fedInfo2.lensConfig = {};
24303
- if (bidirectional && !fedInfo2.federation.includes(spaceId1)) {
24304
- fedInfo2.federation.push(spaceId1);
24305
- }
24306
- if (!fedInfo2.notify.includes(spaceId1)) {
24307
- fedInfo2.notify.push(spaceId1);
24308
- }
24309
- fedInfo2.lensConfig[spaceId1] = {
24310
- federate: bidirectional ? [...federateLenses] : [],
24311
- // Create a copy of the array
24312
- notify: bidirectional ? [...notifyLenses] : [],
24313
- // Create a copy of the array
24314
- timestamp: Date.now()
24315
- };
24316
- fedInfo2.timestamp = Date.now();
24431
+ applyDirection(fedInfo2, spaceId1, outbound, inbound);
24317
24432
  try {
24318
24433
  await holosphere.putGlobal("federation", fedInfo2, password2);
24319
- } catch (error) {
24320
- }
24321
- }
24322
- const federationMeta = {
24323
- id: `${spaceId1}_${spaceId2}`,
24324
- space1: spaceId1,
24325
- space2: spaceId2,
24326
- created: Date.now(),
24327
- status: "active",
24328
- bidirectional,
24329
- lensConfig: {
24330
- federate: [...federateLenses],
24331
- // Create a copy of the array
24332
- notify: [...notifyLenses]
24333
- // Create a copy of the array
24434
+ } catch {
24334
24435
  }
24335
- };
24336
- try {
24337
- await holosphere.putGlobal("federationMeta", federationMeta);
24338
- } catch (error) {
24339
24436
  }
24340
24437
  return true;
24341
24438
  } catch (error) {
@@ -24353,8 +24450,8 @@ var HoloSphere = (() => {
24353
24450
  }
24354
24451
  const subscriptions2 = [];
24355
24452
  let lastNotificationTime = {};
24356
- if (fedInfo.federation && fedInfo.federation.length > 0) {
24357
- for (const federatedSpace of fedInfo.federation) {
24453
+ if (fedInfo.inbound && fedInfo.inbound.length > 0) {
24454
+ for (const federatedSpace of fedInfo.inbound) {
24358
24455
  for (const lens of lenses) {
24359
24456
  try {
24360
24457
  const sub = await holosphere.subscribe(federatedSpace, lens, async (data) => {
@@ -24416,8 +24513,8 @@ var HoloSphere = (() => {
24416
24513
  const fedInfo = await getFederation(holosphere, spaceId, password);
24417
24514
  if (fedInfo && fedInfo.lensConfig && fedInfo.lensConfig[targetSpaceId]) {
24418
24515
  return {
24419
- federate: fedInfo.lensConfig[targetSpaceId].federate || [],
24420
- notify: fedInfo.lensConfig[targetSpaceId].notify || []
24516
+ inbound: fedInfo.lensConfig[targetSpaceId].inbound || [],
24517
+ outbound: fedInfo.lensConfig[targetSpaceId].outbound || []
24421
24518
  };
24422
24519
  }
24423
24520
  return null;
@@ -24440,14 +24537,20 @@ var HoloSphere = (() => {
24440
24537
  if (!fedInfo1) {
24441
24538
  console.warn(`No federation info found for ${spaceId1}. Skipping its update.`);
24442
24539
  } else {
24443
- if (!fedInfo1.federation) fedInfo1.federation = [];
24444
- if (!fedInfo1.notify) fedInfo1.notify = [];
24445
- const originalFederationLength = fedInfo1.federation.length;
24446
- const originalNotifyLength = fedInfo1.notify.length;
24447
- fedInfo1.federation = fedInfo1.federation.filter((id) => id !== spaceId2);
24448
- fedInfo1.notify = fedInfo1.notify.filter((id) => id !== spaceId2);
24540
+ if (!fedInfo1.federated) fedInfo1.federated = [];
24541
+ if (!fedInfo1.inbound) fedInfo1.inbound = [];
24542
+ if (!fedInfo1.outbound) fedInfo1.outbound = [];
24543
+ if (!fedInfo1.lensConfig) fedInfo1.lensConfig = {};
24544
+ if (!fedInfo1.partnerNames) fedInfo1.partnerNames = {};
24545
+ const beforeIn = fedInfo1.inbound.length;
24546
+ const beforeOut = fedInfo1.outbound.length;
24547
+ fedInfo1.federated = fedInfo1.federated.filter((id) => id !== spaceId2);
24548
+ fedInfo1.inbound = fedInfo1.inbound.filter((id) => id !== spaceId2);
24549
+ fedInfo1.outbound = fedInfo1.outbound.filter((id) => id !== spaceId2);
24550
+ delete fedInfo1.lensConfig[spaceId2];
24551
+ delete fedInfo1.partnerNames[spaceId2];
24449
24552
  fedInfo1.timestamp = Date.now();
24450
- console.log(`Unfederate: Removed ${spaceId2} from ${spaceId1}: federation ${originalFederationLength} -> ${fedInfo1.federation.length}, notify ${originalNotifyLength} -> ${fedInfo1.notify.length}`);
24553
+ console.log(`Unfederate: removed ${spaceId2} from ${spaceId1}: inbound ${beforeIn} -> ${fedInfo1.inbound.length}, outbound ${beforeOut} -> ${fedInfo1.outbound.length}`);
24451
24554
  try {
24452
24555
  await holosphere.putGlobal("federation", fedInfo1, password1);
24453
24556
  } catch (error) {
@@ -24462,10 +24565,19 @@ var HoloSphere = (() => {
24462
24565
  } catch (error) {
24463
24566
  console.error(`Error getting fedInfo2 for ${spaceId2} during unfederate: ${error.message}`);
24464
24567
  }
24465
- if (!fedInfo2 || !fedInfo2.notify) {
24466
- console.warn(`No notify array found for ${spaceId2} or fedInfo2 is null. Skipping its update.`);
24568
+ if (!fedInfo2) {
24569
+ console.warn(`No federation info found for ${spaceId2}. Skipping its update.`);
24467
24570
  } else {
24468
- fedInfo2.notify = fedInfo2.notify.filter((id) => id !== spaceId1);
24571
+ if (!fedInfo2.federated) fedInfo2.federated = [];
24572
+ if (!fedInfo2.inbound) fedInfo2.inbound = [];
24573
+ if (!fedInfo2.outbound) fedInfo2.outbound = [];
24574
+ if (!fedInfo2.lensConfig) fedInfo2.lensConfig = {};
24575
+ if (!fedInfo2.partnerNames) fedInfo2.partnerNames = {};
24576
+ fedInfo2.federated = fedInfo2.federated.filter((id) => id !== spaceId1);
24577
+ fedInfo2.inbound = fedInfo2.inbound.filter((id) => id !== spaceId1);
24578
+ fedInfo2.outbound = fedInfo2.outbound.filter((id) => id !== spaceId1);
24579
+ delete fedInfo2.lensConfig[spaceId1];
24580
+ delete fedInfo2.partnerNames[spaceId1];
24469
24581
  fedInfo2.timestamp = Date.now();
24470
24582
  try {
24471
24583
  await holosphere.putGlobal("federation", fedInfo2, password2);
@@ -24498,19 +24610,19 @@ var HoloSphere = (() => {
24498
24610
  throw new Error("removeNotify: Missing required space IDs");
24499
24611
  }
24500
24612
  try {
24501
- let fedInfo = await holosphere.getGlobal("federation", spaceId1, password1);
24613
+ const fedInfo = await holosphere.getGlobal("federation", spaceId1, password1);
24502
24614
  if (!fedInfo) {
24503
24615
  throw new Error(`No federation info found for ${spaceId1}`);
24504
24616
  }
24505
- if (!fedInfo.notify) fedInfo.notify = [];
24506
- if (fedInfo.notify.includes(spaceId2)) {
24507
- fedInfo.notify = fedInfo.notify.filter((id) => id !== spaceId2);
24508
- fedInfo.timestamp = Date.now();
24509
- await holosphere.putGlobal("federation", fedInfo, password1);
24510
- return true;
24511
- } else {
24512
- return false;
24617
+ if (!fedInfo.outbound) fedInfo.outbound = [];
24618
+ if (!fedInfo.outbound.includes(spaceId2)) return false;
24619
+ fedInfo.outbound = fedInfo.outbound.filter((id) => id !== spaceId2);
24620
+ if (fedInfo.lensConfig?.[spaceId2]) {
24621
+ fedInfo.lensConfig[spaceId2].outbound = [];
24513
24622
  }
24623
+ fedInfo.timestamp = Date.now();
24624
+ await holosphere.putGlobal("federation", fedInfo, password1);
24625
+ return true;
24514
24626
  } catch (error) {
24515
24627
  throw error;
24516
24628
  }
@@ -24545,8 +24657,8 @@ var HoloSphere = (() => {
24545
24657
  if (includeLocal) {
24546
24658
  spacesToQuery.push(holon);
24547
24659
  }
24548
- if (includeFederated && fedInfo && fedInfo.federation && fedInfo.federation.length > 0) {
24549
- const federatedSpaces = maxFederatedSpaces === -1 ? fedInfo.federation : fedInfo.federation.slice(0, maxFederatedSpaces);
24660
+ if (includeFederated && fedInfo && fedInfo.inbound && fedInfo.inbound.length > 0) {
24661
+ const federatedSpaces = maxFederatedSpaces === -1 ? fedInfo.inbound : fedInfo.inbound.slice(0, maxFederatedSpaces);
24550
24662
  spacesToQuery = spacesToQuery.concat(federatedSpaces);
24551
24663
  }
24552
24664
  for (const currentSpace of spacesToQuery) {
@@ -24603,24 +24715,15 @@ var HoloSphere = (() => {
24603
24715
  );
24604
24716
  console.log(`Original data found via soul path:`, JSON.stringify(originalData));
24605
24717
  if (originalData) {
24606
- result[i] = {
24607
- ...originalData,
24608
- _federation: {
24609
- isReference: true,
24610
- resolved: true,
24611
- soul: item.soul,
24612
- timestamp: Date.now()
24613
- }
24614
- };
24718
+ result[i] = attachHologramMeta(originalData, item.soul);
24615
24719
  } else {
24616
24720
  result[i] = {
24617
24721
  id: item.id,
24618
- _federation: {
24619
- isReference: true,
24620
- resolved: false,
24722
+ _hologram: {
24723
+ isHologram: false,
24621
24724
  soul: item.soul,
24622
24725
  error: "Referenced data not found",
24623
- timestamp: Date.now()
24726
+ resolvedAt: Date.now()
24624
24727
  }
24625
24728
  };
24626
24729
  }
@@ -24628,55 +24731,25 @@ var HoloSphere = (() => {
24628
24731
  console.warn(`Soul doesn't match expected format: ${item.soul}`);
24629
24732
  result[i] = {
24630
24733
  id: item.id,
24631
- _federation: {
24632
- isReference: true,
24633
- resolved: false,
24734
+ _hologram: {
24735
+ isHologram: false,
24634
24736
  soul: item.soul,
24635
24737
  error: "Invalid soul format",
24636
- timestamp: Date.now()
24738
+ resolvedAt: Date.now()
24637
24739
  }
24638
24740
  };
24639
24741
  }
24640
24742
  } catch (refError) {
24641
24743
  result[i] = {
24642
24744
  id: item.id,
24643
- _federation: {
24644
- isReference: true,
24645
- resolved: false,
24745
+ _hologram: {
24746
+ isHologram: false,
24646
24747
  soul: item.soul,
24647
24748
  error: refError.message || "Error resolving reference",
24648
- timestamp: Date.now()
24749
+ resolvedAt: Date.now()
24649
24750
  }
24650
24751
  };
24651
24752
  }
24652
- } else if (item._federation && item._federation.isReference) {
24653
- console.log(`Found legacy reference: ${item._federation.origin}/${item._federation.lens}/${item[idField]}`);
24654
- try {
24655
- const reference = item._federation;
24656
- console.log(`Getting original data from ${reference.origin} / ${reference.lens} / ${item[idField]}`);
24657
- const originalData = await holosphere.get(
24658
- reference.origin,
24659
- reference.lens,
24660
- item[idField],
24661
- null,
24662
- { resolveReferences: false }
24663
- // Prevent infinite recursion
24664
- );
24665
- console.log(`Original data found:`, JSON.stringify(originalData));
24666
- if (originalData) {
24667
- result[i] = {
24668
- ...originalData,
24669
- _federation: {
24670
- ...reference,
24671
- resolved: true,
24672
- timestamp: Date.now()
24673
- }
24674
- };
24675
- } else {
24676
- console.warn(`Could not resolve legacy reference: original data not found`);
24677
- }
24678
- } catch (refError) {
24679
- }
24680
24753
  }
24681
24754
  }
24682
24755
  }
@@ -24743,8 +24816,8 @@ var HoloSphere = (() => {
24743
24816
  };
24744
24817
  try {
24745
24818
  const fedInfo = await getFederation(holosphere, holon, password);
24746
- if (fedInfo && fedInfo.federation && fedInfo.federation.length > 0 && fedInfo.notify && fedInfo.notify.length > 0) {
24747
- let spaces = fedInfo.notify;
24819
+ if (fedInfo && fedInfo.outbound && fedInfo.outbound.length > 0) {
24820
+ let spaces = fedInfo.outbound;
24748
24821
  if (targetSpaces && Array.isArray(targetSpaces) && targetSpaces.length > 0) {
24749
24822
  spaces = spaces.filter((space) => targetSpaces.includes(space));
24750
24823
  }
@@ -24756,11 +24829,10 @@ var HoloSphere = (() => {
24756
24829
  result.skipped++;
24757
24830
  return false;
24758
24831
  }
24759
- const federateLenses = Array.isArray(spaceConfig.federate) ? spaceConfig.federate : [];
24760
- const shouldFederate = federateLenses.includes("*") || federateLenses.includes(lens);
24761
- const shouldPropagate = shouldFederate;
24832
+ const outboundLenses = Array.isArray(spaceConfig.outbound) ? spaceConfig.outbound : [];
24833
+ const shouldPropagate = outboundLenses.includes("*") || outboundLenses.includes(lens);
24762
24834
  if (!shouldPropagate) {
24763
- result.messages.push(`Propagation of lens '${lens}' to target space ${targetSpace} skipped: lens not in 'federate' configuration.`);
24835
+ result.messages.push(`Propagation of lens '${lens}' to target space ${targetSpace} skipped: lens not in 'outbound' configuration.`);
24764
24836
  result.skipped++;
24765
24837
  }
24766
24838
  return shouldPropagate;
@@ -24989,60 +25061,64 @@ var HoloSphere = (() => {
24989
25061
  message: "No federation configuration found for this space"
24990
25062
  };
24991
25063
  }
24992
- result.federatedCount = fedInfo.federation?.length || 0;
24993
- result.notifyCount = fedInfo.notify?.length || 0;
25064
+ const allPartners = fedInfo.federated || [];
25065
+ result.federatedCount = allPartners.length;
25066
+ result.inboundCount = fedInfo.inbound?.length || 0;
25067
+ result.outboundCount = fedInfo.outbound?.length || 0;
24994
25068
  const emptyFedInfo = {
24995
25069
  id: spaceId,
24996
25070
  name: spaceName || spaceId,
24997
- federation: [],
24998
- notify: [],
25071
+ federated: [],
25072
+ inbound: [],
25073
+ outbound: [],
25074
+ lensConfig: {},
25075
+ partnerNames: {},
24999
25076
  timestamp: Date.now()
25000
25077
  };
25001
25078
  await holosphere.putGlobal("federation", emptyFedInfo, password);
25002
- if (notifyPartners && fedInfo.federation && fedInfo.federation.length > 0) {
25003
- const updatePromises = fedInfo.federation.map(async (partnerSpace) => {
25079
+ if (notifyPartners && allPartners.length > 0) {
25080
+ const updatePromises = allPartners.map(async (partnerSpace) => {
25004
25081
  try {
25005
25082
  const partnerFedInfo = await getFederation(holosphere, partnerSpace);
25006
- if (partnerFedInfo) {
25007
- if (partnerFedInfo.federation) {
25008
- partnerFedInfo.federation = partnerFedInfo.federation.filter(
25009
- (id) => id !== spaceId.toString()
25010
- );
25011
- }
25012
- if (partnerFedInfo.notify) {
25013
- partnerFedInfo.notify = partnerFedInfo.notify.filter(
25014
- (id) => id !== spaceId.toString()
25015
- );
25016
- }
25017
- partnerFedInfo.timestamp = Date.now();
25018
- await holosphere.putGlobal("federation", partnerFedInfo);
25019
- result.partnersNotified++;
25020
- return true;
25083
+ if (!partnerFedInfo) return false;
25084
+ const sid = spaceId.toString();
25085
+ if (partnerFedInfo.federated) {
25086
+ partnerFedInfo.federated = partnerFedInfo.federated.filter((id) => id !== sid);
25021
25087
  }
25022
- return false;
25088
+ if (partnerFedInfo.inbound) {
25089
+ partnerFedInfo.inbound = partnerFedInfo.inbound.filter((id) => id !== sid);
25090
+ }
25091
+ if (partnerFedInfo.outbound) {
25092
+ partnerFedInfo.outbound = partnerFedInfo.outbound.filter((id) => id !== sid);
25093
+ }
25094
+ if (partnerFedInfo.lensConfig) {
25095
+ delete partnerFedInfo.lensConfig[sid];
25096
+ }
25097
+ if (partnerFedInfo.partnerNames) {
25098
+ delete partnerFedInfo.partnerNames[sid];
25099
+ }
25100
+ partnerFedInfo.timestamp = Date.now();
25101
+ await holosphere.putGlobal("federation", partnerFedInfo);
25102
+ result.partnersNotified++;
25103
+ return true;
25023
25104
  } catch (error) {
25024
- result.errors.push({
25025
- partner: partnerSpace,
25026
- error: error.message
25027
- });
25105
+ result.errors.push({ partner: partnerSpace, error: error.message });
25028
25106
  return false;
25029
25107
  }
25030
25108
  });
25031
25109
  await Promise.all(updatePromises);
25032
25110
  }
25033
- if (fedInfo.federation && fedInfo.federation.length > 0) {
25034
- for (const partnerSpace of fedInfo.federation) {
25035
- try {
25036
- const metaId = `${spaceId}_${partnerSpace}`;
25037
- const altMetaId = `${partnerSpace}_${spaceId}`;
25038
- const meta = await holosphere.getGlobal("federationMeta", metaId) || await holosphere.getGlobal("federationMeta", altMetaId);
25039
- if (meta) {
25040
- meta.status = "inactive";
25041
- meta.endedAt = Date.now();
25042
- await holosphere.putGlobal("federationMeta", meta);
25043
- }
25044
- } catch (error) {
25111
+ for (const partnerSpace of allPartners) {
25112
+ try {
25113
+ const metaId = `${spaceId}_${partnerSpace}`;
25114
+ const altMetaId = `${partnerSpace}_${spaceId}`;
25115
+ const meta = await holosphere.getGlobal("federationMeta", metaId) || await holosphere.getGlobal("federationMeta", altMetaId);
25116
+ if (meta) {
25117
+ meta.status = "inactive";
25118
+ meta.endedAt = Date.now();
25119
+ await holosphere.putGlobal("federationMeta", meta);
25045
25120
  }
25121
+ } catch {
25046
25122
  }
25047
25123
  }
25048
25124
  result.success = true;
@@ -25057,7 +25133,6 @@ var HoloSphere = (() => {
25057
25133
  }
25058
25134
 
25059
25135
  // schema.js
25060
- var import__ = __toESM(require__(), 1);
25061
25136
  async function setSchema(holoInstance, lens, schema) {
25062
25137
  if (!lens || !schema) {
25063
25138
  throw new Error("setSchema: Missing required parameters");
@@ -25240,6 +25315,9 @@ var HoloSphere = (() => {
25240
25315
  if (dataToStore._meta !== void 0) {
25241
25316
  delete dataToStore._meta;
25242
25317
  }
25318
+ if (dataToStore._hologram !== void 0) {
25319
+ delete dataToStore._hologram;
25320
+ }
25243
25321
  const payload = JSON.stringify(dataToStore);
25244
25322
  const putCallback = async (ack) => {
25245
25323
  if (ack.err) {
@@ -25529,7 +25607,8 @@ var HoloSphere = (() => {
25529
25607
  const output = /* @__PURE__ */ new Map();
25530
25608
  const pendingProcessing = [];
25531
25609
  const dataPath = password ? user.get("private").get(lens) : holoInstance.gun.get(holoInstance.appname).get(holon).get(lens);
25532
- dataPath.once((data) => {
25610
+ const shallowOnce = () => new Promise((res) => dataPath.once((d) => res(d)));
25611
+ const processShallow = (data) => {
25533
25612
  if (!data) {
25534
25613
  resolve([]);
25535
25614
  return;
@@ -25546,72 +25625,75 @@ var HoloSphere = (() => {
25546
25625
  resolve([]);
25547
25626
  return;
25548
25627
  }
25549
- let receivedCount = 0;
25550
- dataPath.map().once(async (itemData, key) => {
25551
- if (!itemData || key === "_") {
25552
- receivedCount++;
25553
- if (receivedCount >= expectedCount) {
25554
- await Promise.all(pendingProcessing);
25555
- resolve(Array.from(output.values()));
25556
- }
25557
- return;
25558
- }
25559
- const processingPromise = (async () => {
25560
- try {
25561
- const parsed = await holoInstance.parse(itemData);
25562
- if (!parsed || !parsed.id) return;
25563
- if (holoInstance.isHologram(parsed)) {
25564
- try {
25565
- const resolved = await holoInstance.resolveHologram(parsed, {
25566
- followHolograms: true,
25567
- maxDepth: 10,
25568
- currentDepth: 0
25569
- });
25570
- if (resolved === null) {
25571
- console.warn(`Broken hologram detected in getAll for key ${key}. Removing it...`);
25572
- try {
25573
- await holoInstance.delete(holon, lens, key, password);
25574
- } catch (cleanupError) {
25575
- console.error(`Failed to remove broken hologram at ${holon}/${lens}/${key}:`, cleanupError);
25576
- }
25577
- return;
25628
+ const processItem = async (itemData, key) => {
25629
+ if (!itemData) return;
25630
+ try {
25631
+ const parsed = await holoInstance.parse(itemData);
25632
+ if (!parsed || !parsed.id) return;
25633
+ if (holoInstance.isHologram(parsed)) {
25634
+ try {
25635
+ const resolved = await holoInstance.resolveHologram(parsed, {
25636
+ followHolograms: true,
25637
+ maxDepth: 10,
25638
+ currentDepth: 0
25639
+ });
25640
+ if (resolved === null) {
25641
+ console.warn(`Broken hologram detected in getAll for key ${key}. Removing it...`);
25642
+ try {
25643
+ await holoInstance.delete(holon, lens, key, password);
25644
+ } catch (cleanupError) {
25645
+ console.error(`Failed to remove broken hologram at ${holon}/${lens}/${key}:`, cleanupError);
25578
25646
  }
25579
- if (resolved && resolved !== parsed) {
25580
- if (schema) {
25581
- const valid = holoInstance.validator.validate(schema, resolved);
25582
- if (valid || !holoInstance.strict) {
25583
- output.set(resolved.id, resolved);
25584
- }
25585
- } else {
25647
+ return;
25648
+ }
25649
+ if (resolved && resolved !== parsed) {
25650
+ if (schema) {
25651
+ const valid = holoInstance.validator.validate(schema, resolved);
25652
+ if (valid || !holoInstance.strict) {
25586
25653
  output.set(resolved.id, resolved);
25587
25654
  }
25588
- return;
25655
+ } else {
25656
+ output.set(resolved.id, resolved);
25589
25657
  }
25590
- } catch (hologramError) {
25591
- console.error(`Error resolving hologram for key ${key}:`, hologramError);
25592
25658
  return;
25593
25659
  }
25660
+ } catch (hologramError) {
25661
+ console.error(`Error resolving hologram for key ${key}:`, hologramError);
25662
+ return;
25594
25663
  }
25595
- if (schema) {
25596
- const valid = holoInstance.validator.validate(schema, parsed);
25597
- if (valid || !holoInstance.strict) {
25598
- output.set(parsed.id, parsed);
25599
- }
25600
- } else {
25664
+ }
25665
+ if (schema) {
25666
+ const valid = holoInstance.validator.validate(schema, parsed);
25667
+ if (valid || !holoInstance.strict) {
25601
25668
  output.set(parsed.id, parsed);
25602
25669
  }
25603
- } catch (error) {
25604
- console.error("Error processing data:", error);
25670
+ } else {
25671
+ output.set(parsed.id, parsed);
25605
25672
  }
25606
- })();
25607
- pendingProcessing.push(processingPromise);
25608
- receivedCount++;
25609
- if (receivedCount >= expectedCount) {
25610
- await Promise.all(pendingProcessing);
25611
- resolve(Array.from(output.values()));
25673
+ } catch (error) {
25674
+ console.error("Error processing data:", error);
25612
25675
  }
25613
- });
25614
- });
25676
+ };
25677
+ Promise.all(keys.map((key) => {
25678
+ const inline = data[key];
25679
+ if (typeof inline !== "object" || inline === null) {
25680
+ return processItem(inline, key);
25681
+ }
25682
+ return new Promise((resolveItem) => {
25683
+ dataPath.get(key).once((itemData) => {
25684
+ processItem(itemData, key).then(resolveItem, resolveItem);
25685
+ });
25686
+ });
25687
+ })).then(() => resolve(Array.from(output.values())));
25688
+ };
25689
+ (async () => {
25690
+ let data = await shallowOnce();
25691
+ if (!data) {
25692
+ await new Promise((r) => setTimeout(r, 1500));
25693
+ data = await shallowOnce();
25694
+ }
25695
+ processShallow(data);
25696
+ })();
25615
25697
  });
25616
25698
  } catch (error) {
25617
25699
  console.error("Error in getAll:", error);
@@ -26090,6 +26172,9 @@ var HoloSphere = (() => {
26090
26172
  if (dataToStore._meta !== void 0) {
26091
26173
  delete dataToStore._meta;
26092
26174
  }
26175
+ if (dataToStore._hologram !== void 0) {
26176
+ delete dataToStore._hologram;
26177
+ }
26093
26178
  const payload = JSON.stringify(dataToStore);
26094
26179
  const isHologram2 = holoInstance.isHologram(dataToStore);
26095
26180
  const dataPath = password ? user.get("private").get(tableName) : holoInstance.gun.get(holoInstance.appname).get(tableName);
@@ -26290,7 +26375,8 @@ var HoloSphere = (() => {
26290
26375
  const output = [];
26291
26376
  const pendingProcessing = [];
26292
26377
  const dataPath = password ? user.get("private").get(tableName) : holoInstance.gun.get(holoInstance.appname).get(tableName);
26293
- dataPath.once((data) => {
26378
+ const shallowOnce = () => new Promise((res) => dataPath.once((d) => res(d)));
26379
+ const processShallow = (data) => {
26294
26380
  if (!data) {
26295
26381
  resolve([]);
26296
26382
  return;
@@ -26307,52 +26393,55 @@ var HoloSphere = (() => {
26307
26393
  resolve([]);
26308
26394
  return;
26309
26395
  }
26310
- let receivedCount = 0;
26311
- dataPath.map().once(async (itemData, key) => {
26312
- if (!itemData || key === "_") {
26313
- receivedCount++;
26314
- if (receivedCount >= expectedCount) {
26315
- await Promise.all(pendingProcessing);
26316
- resolve(output);
26317
- }
26318
- return;
26319
- }
26320
- const processingPromise = (async () => {
26321
- try {
26322
- const parsed = await holoInstance.parse(itemData);
26323
- if (!parsed) return;
26324
- if (holoInstance.isHologram(parsed)) {
26325
- const resolved = await holoInstance.resolveHologram(parsed, {
26326
- followHolograms: true
26327
- });
26328
- if (resolved === null) {
26329
- try {
26330
- await holoInstance.deleteGlobal(tableName, key, password);
26331
- } catch (deleteError) {
26332
- console.error(`Failed to delete invalid global hologram at ${tableName}/${key}:`, deleteError);
26333
- }
26334
- return;
26335
- }
26336
- if (resolved !== parsed) {
26337
- output.push(resolved);
26338
- } else {
26339
- output.push(parsed);
26396
+ const processItem = async (itemData, key) => {
26397
+ if (!itemData) return;
26398
+ try {
26399
+ const parsed = await holoInstance.parse(itemData);
26400
+ if (!parsed) return;
26401
+ if (holoInstance.isHologram(parsed)) {
26402
+ const resolved = await holoInstance.resolveHologram(parsed, {
26403
+ followHolograms: true
26404
+ });
26405
+ if (resolved === null) {
26406
+ try {
26407
+ await holoInstance.deleteGlobal(tableName, key, password);
26408
+ } catch (deleteError) {
26409
+ console.error(`Failed to delete invalid global hologram at ${tableName}/${key}:`, deleteError);
26340
26410
  }
26411
+ return;
26412
+ }
26413
+ if (resolved !== parsed) {
26414
+ output.push(resolved);
26341
26415
  } else {
26342
26416
  output.push(parsed);
26343
26417
  }
26344
- } catch (error) {
26345
- console.error("Error parsing data:", error);
26418
+ } else {
26419
+ output.push(parsed);
26346
26420
  }
26347
- })();
26348
- pendingProcessing.push(processingPromise);
26349
- receivedCount++;
26350
- if (receivedCount >= expectedCount) {
26351
- await Promise.all(pendingProcessing);
26352
- resolve(output);
26421
+ } catch (error) {
26422
+ console.error("Error parsing data:", error);
26353
26423
  }
26354
- });
26355
- });
26424
+ };
26425
+ Promise.all(keys.map((key) => {
26426
+ const inline = data[key];
26427
+ if (typeof inline !== "object" || inline === null) {
26428
+ return processItem(inline, key);
26429
+ }
26430
+ return new Promise((resolveItem) => {
26431
+ dataPath.get(key).once((itemData) => {
26432
+ processItem(itemData, key).then(resolveItem, resolveItem);
26433
+ });
26434
+ });
26435
+ })).then(() => resolve(output));
26436
+ };
26437
+ (async () => {
26438
+ let data = await shallowOnce();
26439
+ if (!data) {
26440
+ await new Promise((r) => setTimeout(r, 1500));
26441
+ data = await shallowOnce();
26442
+ }
26443
+ processShallow(data);
26444
+ })();
26356
26445
  });
26357
26446
  } catch (error) {
26358
26447
  console.error("Error in getAllGlobal:", error);
@@ -26642,116 +26731,6 @@ var HoloSphere = (() => {
26642
26731
  };
26643
26732
  }
26644
26733
 
26645
- // hologram.js
26646
- function createHologram(holoInstance, holon, lens, data) {
26647
- if (isHologram(data)) {
26648
- return {
26649
- id: data.id,
26650
- soul: data.soul
26651
- };
26652
- }
26653
- if (!holon || !lens || !data || !data.id) {
26654
- throw new Error("createHologram: Missing required parameters for non-hologram data");
26655
- }
26656
- const soul = `${holoInstance.appname}/${holon}/${lens}/${data.id}`;
26657
- return {
26658
- id: data.id,
26659
- soul
26660
- };
26661
- }
26662
- function parseSoulPath(soul) {
26663
- if (typeof soul !== "string") return null;
26664
- const parts = soul.split("/");
26665
- if (parts.length < 4) return null;
26666
- const key = parts.slice(3).join("/");
26667
- return {
26668
- appname: parts[0],
26669
- holon: parts[1],
26670
- lens: parts[2],
26671
- key
26672
- };
26673
- }
26674
- function isHologram(data) {
26675
- if (!data || typeof data !== "object") {
26676
- return false;
26677
- }
26678
- if (data.id && typeof data.soul === "string" && data.soul.length > 0) {
26679
- if (data.soul.includes("/")) {
26680
- return true;
26681
- }
26682
- }
26683
- return false;
26684
- }
26685
- async function resolveHologram(holoInstance, hologram, options = {}) {
26686
- if (!isHologram(hologram)) {
26687
- return hologram;
26688
- }
26689
- const {
26690
- followHolograms = true,
26691
- visited = /* @__PURE__ */ new Set(),
26692
- maxDepth = 10,
26693
- currentDepth = 0
26694
- } = options;
26695
- if (currentDepth >= maxDepth) {
26696
- console.warn(`!!! Maximum resolution depth (${maxDepth}) reached for soul: ${hologram.soul}. Stopping resolution.`);
26697
- return null;
26698
- }
26699
- if (hologram.soul && visited.has(hologram.soul)) {
26700
- console.warn(`!!! CIRCULAR hologram detected for soul: ${hologram.soul}. Breaking loop.`);
26701
- return null;
26702
- }
26703
- try {
26704
- if (hologram.soul) {
26705
- const soulInfo = parseSoulPath(hologram.soul);
26706
- if (!soulInfo) {
26707
- console.warn(`Invalid soul format: ${hologram.soul}`);
26708
- return null;
26709
- }
26710
- const nextVisited = new Set(visited);
26711
- nextVisited.add(hologram.soul);
26712
- const originalData = await holoInstance.get(
26713
- soulInfo.holon,
26714
- soulInfo.lens,
26715
- soulInfo.key,
26716
- null,
26717
- {
26718
- resolveHolograms: followHolograms,
26719
- visited: nextVisited,
26720
- maxDepth,
26721
- currentDepth: currentDepth + 1
26722
- }
26723
- );
26724
- if (originalData && !originalData._invalidHologram) {
26725
- return {
26726
- ...originalData,
26727
- _meta: {
26728
- ...originalData._meta || {},
26729
- // Preserve original _meta
26730
- resolvedFromHologram: true,
26731
- // This is now the primary indicator
26732
- hologramSoul: hologram.soul,
26733
- // Clarified meta field
26734
- resolutionDepth: currentDepth
26735
- }
26736
- };
26737
- } else {
26738
- console.warn(`!!! Original data NOT FOUND for soul: ${hologram.soul}. Removing broken hologram.`);
26739
- return null;
26740
- }
26741
- } else {
26742
- console.warn("!!! resolveHologram called with object missing soul:", hologram);
26743
- return null;
26744
- }
26745
- } catch (error) {
26746
- if (error.message?.startsWith("CIRCULAR_REFERENCE")) {
26747
- console.warn(`!!! Circular reference detected during hologram resolution: ${error.message}`);
26748
- return null;
26749
- }
26750
- console.error(`!!! Error resolving hologram: ${error.message}`, error);
26751
- return null;
26752
- }
26753
- }
26754
-
26755
26734
  // compute.js
26756
26735
  async function computeHierarchy(holoInstance, holon, lens, options, maxLevels = 15, password = null) {
26757
26736
  let currentHolon = holon;
@@ -30225,7 +30204,7 @@ var HoloSphere = (() => {
30225
30204
  this._privateKey = null;
30226
30205
  }
30227
30206
  console.log("HoloSphere v" + HOLOSPHERE_VERSION);
30228
- this.validator = new import__2.default({
30207
+ this.validator = new import__.default({
30229
30208
  allErrors: true,
30230
30209
  strict: false,
30231
30210
  validateSchema: true
@@ -30377,6 +30356,9 @@ var HoloSphere = (() => {
30377
30356
  async resolveHologram(hologram, options = {}) {
30378
30357
  return resolveHologram(this, hologram, options);
30379
30358
  }
30359
+ attachHologramMeta(originalData, hologramSoul) {
30360
+ return attachHologramMeta(originalData, hologramSoul);
30361
+ }
30380
30362
  // ================================ COMPUTE FUNCTIONS ================================
30381
30363
  async computeHierarchy(holon, lens, options, maxLevels = 15, password = null) {
30382
30364
  return computeHierarchy(this, holon, lens, options, maxLevels, password);
@@ -30419,41 +30401,37 @@ var HoloSphere = (() => {
30419
30401
  return federate(this, holonId1, holonId2, password1, password2, bidirectional, lensConfig);
30420
30402
  }
30421
30403
  /**
30422
- * v2-compatible federation creation.
30423
- * Maps v2 options to v1 federate() call.
30404
+ * Convenience wrapper around federate() for the common bidirectional case.
30424
30405
  * @param {string} sourceHolon - Source holon ID
30425
30406
  * @param {string} targetHolon - Target holon ID
30426
30407
  * @param {object} [options] - Federation options
30427
- * @param {object} [options.lensConfig] - Lens configuration
30428
- * @param {string} [options.partnerName] - Name of the partner holon
30429
- * @param {boolean} [options.skipPropagation] - Skip data propagation
30408
+ * @param {object} [options.lensConfig] - Lens config from sourceHolon's perspective
30409
+ * @param {string[]} [options.lensConfig.inbound] - Lenses sourceHolon receives from targetHolon
30410
+ * @param {string[]} [options.lensConfig.outbound] - Lenses sourceHolon sends to targetHolon
30411
+ * @param {string} [options.partnerName] - Display name for the partner
30430
30412
  * @returns {Promise<boolean>}
30431
30413
  */
30432
30414
  async federateHolon(sourceHolon, targetHolon, options = {}) {
30433
30415
  const lensConfig = options.lensConfig || {};
30434
- const lenses = lensConfig.lenses || lensConfig.outbound || lensConfig.federate || [];
30435
- if (options.partnerName) {
30416
+ const inbound = Array.isArray(lensConfig.inbound) ? lensConfig.inbound : [];
30417
+ const outbound = Array.isArray(lensConfig.outbound) ? lensConfig.outbound : [];
30418
+ const ok = await federate(this, sourceHolon, targetHolon, null, null, true, {
30419
+ inbound,
30420
+ outbound
30421
+ });
30422
+ if (ok && options.partnerName) {
30436
30423
  try {
30437
- const fedInfo = await this.getFederation(sourceHolon) || {
30438
- id: sourceHolon,
30439
- name: sourceHolon,
30440
- federation: [],
30441
- notify: [],
30442
- lensConfig: {},
30443
- partnerNames: {},
30444
- timestamp: Date.now()
30445
- };
30446
- if (!fedInfo.partnerNames) fedInfo.partnerNames = {};
30447
- fedInfo.partnerNames[targetHolon] = options.partnerName;
30448
- await this.putGlobal("federation", fedInfo);
30424
+ const fedInfo = await this.getFederation(sourceHolon);
30425
+ if (fedInfo) {
30426
+ if (!fedInfo.partnerNames) fedInfo.partnerNames = {};
30427
+ fedInfo.partnerNames[targetHolon] = options.partnerName;
30428
+ await this.putGlobal("federation", fedInfo);
30429
+ }
30449
30430
  } catch (e) {
30450
30431
  console.warn("Failed to store partner name:", e.message);
30451
30432
  }
30452
30433
  }
30453
- return federate(this, sourceHolon, targetHolon, null, null, true, {
30454
- federate: lenses,
30455
- notify: lenses
30456
- });
30434
+ return ok;
30457
30435
  }
30458
30436
  /**
30459
30437
  * v2-compatible federation removal.