@xyo-network/bridge-pub-sub 2.94.15 → 2.94.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/browser/AsyncQueryBus/AsyncQueryBusBase.d.cts +7 -68
  2. package/dist/browser/AsyncQueryBus/AsyncQueryBusBase.d.cts.map +1 -1
  3. package/dist/browser/AsyncQueryBus/AsyncQueryBusBase.d.mts +7 -68
  4. package/dist/browser/AsyncQueryBus/AsyncQueryBusBase.d.mts.map +1 -1
  5. package/dist/browser/AsyncQueryBus/AsyncQueryBusBase.d.ts +7 -68
  6. package/dist/browser/AsyncQueryBus/AsyncQueryBusBase.d.ts.map +1 -1
  7. package/dist/browser/AsyncQueryBus/AsyncQueryBusHost.d.cts +24 -3
  8. package/dist/browser/AsyncQueryBus/AsyncQueryBusHost.d.cts.map +1 -1
  9. package/dist/browser/AsyncQueryBus/AsyncQueryBusHost.d.mts +24 -3
  10. package/dist/browser/AsyncQueryBus/AsyncQueryBusHost.d.mts.map +1 -1
  11. package/dist/browser/AsyncQueryBus/AsyncQueryBusHost.d.ts +24 -3
  12. package/dist/browser/AsyncQueryBus/AsyncQueryBusHost.d.ts.map +1 -1
  13. package/dist/browser/PubSubBridge.d.cts.map +1 -1
  14. package/dist/browser/PubSubBridge.d.mts.map +1 -1
  15. package/dist/browser/PubSubBridge.d.ts.map +1 -1
  16. package/dist/browser/index.cjs +106 -132
  17. package/dist/browser/index.cjs.map +1 -1
  18. package/dist/browser/index.js +103 -129
  19. package/dist/browser/index.js.map +1 -1
  20. package/dist/node/AsyncQueryBus/AsyncQueryBusBase.d.cts +7 -68
  21. package/dist/node/AsyncQueryBus/AsyncQueryBusBase.d.cts.map +1 -1
  22. package/dist/node/AsyncQueryBus/AsyncQueryBusBase.d.mts +7 -68
  23. package/dist/node/AsyncQueryBus/AsyncQueryBusBase.d.mts.map +1 -1
  24. package/dist/node/AsyncQueryBus/AsyncQueryBusBase.d.ts +7 -68
  25. package/dist/node/AsyncQueryBus/AsyncQueryBusBase.d.ts.map +1 -1
  26. package/dist/node/AsyncQueryBus/AsyncQueryBusHost.d.cts +24 -3
  27. package/dist/node/AsyncQueryBus/AsyncQueryBusHost.d.cts.map +1 -1
  28. package/dist/node/AsyncQueryBus/AsyncQueryBusHost.d.mts +24 -3
  29. package/dist/node/AsyncQueryBus/AsyncQueryBusHost.d.mts.map +1 -1
  30. package/dist/node/AsyncQueryBus/AsyncQueryBusHost.d.ts +24 -3
  31. package/dist/node/AsyncQueryBus/AsyncQueryBusHost.d.ts.map +1 -1
  32. package/dist/node/PubSubBridge.d.cts.map +1 -1
  33. package/dist/node/PubSubBridge.d.mts.map +1 -1
  34. package/dist/node/PubSubBridge.d.ts.map +1 -1
  35. package/dist/node/index.cjs +111 -136
  36. package/dist/node/index.cjs.map +1 -1
  37. package/dist/node/index.js +108 -133
  38. package/dist/node/index.js.map +1 -1
  39. package/package.json +19 -18
  40. package/src/AsyncQueryBus/AsyncQueryBusBase.ts +59 -89
  41. package/src/AsyncQueryBus/AsyncQueryBusHost.ts +29 -14
  42. package/src/PubSubBridge.ts +21 -20
@@ -10,7 +10,7 @@ var AbstractModuleHost = class extends Base {
10
10
  };
11
11
 
12
12
  // src/AsyncQueryBus/AsyncQueryBusClient.ts
13
- import { assertEx } from "@xylabs/assert";
13
+ import { assertEx as assertEx2 } from "@xylabs/assert";
14
14
  import { delay } from "@xylabs/delay";
15
15
  import { forget } from "@xylabs/forget";
16
16
  import { clearTimeoutEx, setTimeoutEx } from "@xylabs/timer";
@@ -20,9 +20,12 @@ import { PayloadBuilder } from "@xyo-network/payload-builder";
20
20
  import { LRUCache as LRUCache2 } from "lru-cache";
21
21
 
22
22
  // src/AsyncQueryBus/AsyncQueryBusBase.ts
23
- import { Base as Base2, toJsonString } from "@xylabs/object";
24
- import { asArchivistInstance } from "@xyo-network/archivist-model";
25
- import { asDivinerInstance } from "@xyo-network/diviner-model";
23
+ import { assertEx } from "@xylabs/assert";
24
+ import { Base as Base2 } from "@xylabs/object";
25
+ import { isArchivistInstance } from "@xyo-network/archivist-model";
26
+ import { isDivinerInstance } from "@xyo-network/diviner-model";
27
+ import { traceModuleIdentifier } from "@xyo-network/module-model";
28
+ import { Mutex } from "async-mutex";
26
29
  import { LRUCache } from "lru-cache";
27
30
  var AsyncQueryBusBase = class extends Base2 {
28
31
  static {
@@ -31,13 +34,11 @@ var AsyncQueryBusBase = class extends Base2 {
31
34
  _lastState;
32
35
  _targetConfigs = {};
33
36
  _targetQueries = {};
34
- _lastQueriesArchivistAttempt;
35
- _lastQueriesDivinerAttempt;
36
- _lastResponsesArchivistAttempt;
37
- _lastResponsesDivinerAttempt;
37
+ _lastResolveAttempt = {};
38
38
  _queriesArchivist;
39
39
  _queriesDiviner;
40
- _reResolveDelay = 5e4;
40
+ _reResolveDelay = 1e3 * 5;
41
+ _resolveMutex = new Mutex();
41
42
  _responsesArchivist;
42
43
  _responsesDiviner;
43
44
  constructor(params) {
@@ -64,84 +65,20 @@ var AsyncQueryBusBase = class extends Base2 {
64
65
  return this._lastState;
65
66
  }
66
67
  async queriesArchivist() {
67
- if (this._queriesArchivist) {
68
- return this._queriesArchivist;
69
- }
70
- if (Date.now() - (this._lastQueriesArchivistAttempt ?? 0) < this._reResolveDelay) {
71
- return;
72
- }
73
- this._lastQueriesArchivistAttempt = Date.now();
74
- const resolved = await this.resolver.resolve(this.config?.intersect?.queries?.archivist);
75
- if (resolved) {
76
- const typedResolve = asArchivistInstance(resolved);
77
- if (typedResolve) {
78
- return typedResolve;
79
- } else {
80
- this.logger?.warn(`Unable to resolve queriesArchivist as correct type [${this.config?.intersect?.queries?.archivist}][${resolved?.constructor?.name}]: ${toJsonString(resolved)}`);
81
- }
82
- } else {
83
- this.logger?.log(`Unable to resolve queriesArchivist [${this.config?.intersect?.queries?.archivist}]`);
84
- }
68
+ this._queriesArchivist = this._queriesArchivist ?? await this.resolve(assertEx(this.config?.intersect?.queries?.archivist, () => "No queries Archivist defined"), isArchivistInstance);
69
+ return this._queriesArchivist;
85
70
  }
86
71
  async queriesDiviner() {
87
- if (this._queriesDiviner) {
88
- return this._queriesDiviner;
89
- }
90
- if (Date.now() - (this._lastQueriesDivinerAttempt ?? 0) < this._reResolveDelay) {
91
- return;
92
- }
93
- this._lastQueriesDivinerAttempt = Date.now();
94
- const resolved = await this.resolver.resolve(this.config?.intersect?.queries?.boundWitnessDiviner);
95
- if (resolved) {
96
- const typedResolve = asDivinerInstance(resolved);
97
- if (typedResolve) {
98
- return typedResolve;
99
- } else {
100
- this.logger?.warn(`Unable to resolve queriesDiviner as correct type [${this.config?.intersect?.queries?.boundWitnessDiviner}][${resolved?.constructor?.name}]: ${toJsonString(resolved)}`);
101
- }
102
- } else {
103
- this.logger?.log(`Unable to resolve queriesDiviner [${this.config?.intersect?.queries?.boundWitnessDiviner}]`);
104
- }
72
+ this._queriesDiviner = this._queriesDiviner ?? await this.resolve(assertEx(this.config?.intersect?.queries?.boundWitnessDiviner, () => "No queries Diviner defined"), isDivinerInstance);
73
+ return this._queriesDiviner;
105
74
  }
106
75
  async responsesArchivist() {
107
- if (this._responsesArchivist) {
108
- return this._responsesArchivist;
109
- }
110
- if (Date.now() - (this._lastResponsesArchivistAttempt ?? 0) < this._reResolveDelay) {
111
- return;
112
- }
113
- this._lastResponsesArchivistAttempt = Date.now();
114
- const resolved = await this.resolver.resolve(this.config?.intersect?.responses?.archivist);
115
- if (resolved) {
116
- const typedResolve = asArchivistInstance(resolved);
117
- if (typedResolve) {
118
- return typedResolve;
119
- } else {
120
- this.logger?.warn(`Unable to resolve responseArchivist as correct type [${this.config?.intersect?.responses?.archivist}][${resolved?.constructor?.name}]: ${toJsonString(resolved)}`);
121
- }
122
- } else {
123
- this.logger?.log(`Unable to resolve responseArchivist [${this.config?.intersect?.responses?.archivist}]`);
124
- }
76
+ this._responsesArchivist = this._responsesArchivist ?? await this.resolve(assertEx(this.config?.intersect?.responses?.archivist, () => "No responses Archivist defined"), isArchivistInstance);
77
+ return this._responsesArchivist;
125
78
  }
126
79
  async responsesDiviner() {
127
- if (this._responsesDiviner) {
128
- return this._responsesDiviner;
129
- }
130
- if (Date.now() - (this._lastResponsesDivinerAttempt ?? 0) < this._reResolveDelay) {
131
- return;
132
- }
133
- this._lastResponsesDivinerAttempt = Date.now();
134
- const resolved = await this.resolver.resolve(this.config?.intersect?.responses?.boundWitnessDiviner);
135
- if (resolved) {
136
- const typedResolve = asDivinerInstance(resolved);
137
- if (typedResolve) {
138
- return typedResolve;
139
- } else {
140
- this.logger?.warn(`Unable to resolve responsesDiviner as correct type [${this.config?.intersect?.responses?.boundWitnessDiviner}][${resolved?.constructor?.name}]: ${toJsonString(resolved)}`);
141
- }
142
- } else {
143
- this.logger?.log(`Unable to resolve responsesDiviner [${this.config?.intersect?.responses?.boundWitnessDiviner}]`);
144
- }
80
+ this._responsesDiviner = this._responsesDiviner ?? await this.resolve(assertEx(this.config?.intersect?.responses?.boundWitnessDiviner, () => "No responses Diviner defined"), isDivinerInstance);
81
+ return this._responsesDiviner;
145
82
  }
146
83
  /**
147
84
  * Commit the internal state of the process. This is similar
@@ -173,6 +110,27 @@ var AsyncQueryBusBase = class extends Base2 {
173
110
  return state;
174
111
  }
175
112
  }
113
+ async resolve(id, typeCheck) {
114
+ return await this._resolveMutex.runExclusive(async () => {
115
+ if (this._queriesArchivist) {
116
+ return this._queriesArchivist;
117
+ }
118
+ if (Date.now() - (this._lastResolveAttempt[id] ?? 0) < this._reResolveDelay) {
119
+ return;
120
+ }
121
+ this._lastResolveAttempt[id] = Date.now();
122
+ const resolved = await this.resolver.resolve(id);
123
+ if (resolved) {
124
+ if (typeCheck(resolved)) {
125
+ return resolved;
126
+ } else {
127
+ this.logger?.warn(`Unable to resolve responsesDiviner as correct type [${id}][${resolved?.constructor?.name}]: ${resolved.id}`);
128
+ }
129
+ } else {
130
+ this.logger?.log(`Unable to resolve queriesArchivist [${id}] [${await traceModuleIdentifier(this.resolver, id)}]`);
131
+ }
132
+ });
133
+ }
176
134
  };
177
135
 
178
136
  // src/AsyncQueryBus/model/QueryStatus.ts
@@ -230,7 +188,7 @@ var AsyncQueryBusClient = class extends AsyncQueryBusBase {
230
188
  ...query,
231
189
  $meta
232
190
  });
233
- const queryArchivist = assertEx(await this.queriesArchivist(), () => `Unable to contact queriesArchivist [${this.config?.intersect?.queries?.archivist}]`);
191
+ const queryArchivist = assertEx2(await this.queriesArchivist(), () => `Unable to contact queriesArchivist [${this.config?.intersect?.queries?.archivist}]`);
234
192
  const routedQueryHash = (
235
193
  // Trust the signed hash if it's there
236
194
  routedQuery?.$hash ?? // TODO: What is the right way to find the dataHash
@@ -358,7 +316,7 @@ var AsyncQueryBusClient = class extends AsyncQueryBusBase {
358
316
 
359
317
  // src/AsyncQueryBus/AsyncQueryBusHost.ts
360
318
  import { containsAll } from "@xylabs/array";
361
- import { assertEx as assertEx2 } from "@xylabs/assert";
319
+ import { assertEx as assertEx3 } from "@xylabs/assert";
362
320
  import { clearTimeoutEx as clearTimeoutEx2, setTimeoutEx as setTimeoutEx2 } from "@xylabs/timer";
363
321
  import { isQueryBoundWitnessWithMeta } from "@xyo-network/boundwitness-model";
364
322
  import { BoundWitnessDivinerQuerySchema as BoundWitnessDivinerQuerySchema2 } from "@xyo-network/diviner-boundwitness-model";
@@ -383,21 +341,32 @@ var AsyncQueryBusHost = class extends AsyncQueryBusBase {
383
341
  get started() {
384
342
  return !!this._pollId;
385
343
  }
386
- expose(address, options = {}) {
387
- const { failOnAlreadyExposed } = options;
388
- assertEx2(!failOnAlreadyExposed || !this._exposedAddresses.has(address), () => `Address already exposed [${address}]`);
389
- this._exposedAddresses.add(address);
390
- this._exposeOptions[address] = {
391
- ...options
392
- };
393
- this.logger?.debug(`${address} exposed`);
344
+ async expose(id, options) {
345
+ const { failOnAlreadyExposed, required = true } = options ?? {};
346
+ const module = asModuleInstance(await this.resolver.resolve(id, {
347
+ maxDepth: 10
348
+ }));
349
+ if (!module && required) {
350
+ throw new Error(`Unable to resolve module to expose [${id}]`);
351
+ }
352
+ if (module) {
353
+ assertEx3(!failOnAlreadyExposed || !this._exposedAddresses.has(module.address), () => `Address already exposed: ${id} [${module.address}]`);
354
+ this._exposedAddresses.add(module.address);
355
+ this._exposeOptions[module.address] = {
356
+ ...options
357
+ };
358
+ this.logger?.debug(`${id} exposed [${module.address}]`);
359
+ return module;
360
+ }
394
361
  }
395
362
  async listeningModules() {
396
363
  const exposedModules = [
397
364
  ...this.config?.listeningModules ?? [],
398
365
  ...this.exposedAddresses.values()
399
366
  ];
400
- const mods = await Promise.all(exposedModules.map(async (listeningModule) => assertEx2(asModuleInstance(await this.resolver.resolve(listeningModule)), () => `Unable to resolve listeningModule [${listeningModule}]`)));
367
+ const mods = await Promise.all(exposedModules.map(async (exposedModule) => assertEx3(asModuleInstance(await this.resolver.resolve(exposedModule, {
368
+ maxDepth: 10
369
+ })), () => `Unable to resolve listeningModule [${exposedModule}]`)));
401
370
  return mods;
402
371
  }
403
372
  start() {
@@ -414,16 +383,22 @@ var AsyncQueryBusHost = class extends AsyncQueryBusBase {
414
383
  clearTimeoutEx2(this._pollId);
415
384
  this._pollId = void 0;
416
385
  }
417
- unexpose(address, validate = true) {
418
- assertEx2(!validate || this._exposedAddresses.has(address), () => `Address not exposed [${address}]`);
419
- this._exposedAddresses.delete(address);
420
- delete this._exposeOptions[address];
421
- this.logger?.debug(`${address} unexposed`);
386
+ async unexpose(id, validate = true) {
387
+ const module = asModuleInstance(await this.resolver.resolve(id, {
388
+ maxDepth: 10
389
+ }));
390
+ if (module) {
391
+ assertEx3(!validate || this._exposedAddresses.has(module.address), () => `Address not exposed [${module.address}][${module.id}]`);
392
+ this._exposedAddresses.delete(module.address);
393
+ delete this._exposeOptions[module.address];
394
+ this.logger?.debug(`${module.address} [${module.id}] unexposed`);
395
+ }
396
+ return module;
422
397
  }
423
398
  callLocalModule = async (localModule, query) => {
424
399
  const localModuleName = localModule.config.name ?? localModule.address;
425
- const queryArchivist = assertEx2(await this.queriesArchivist(), () => `Unable to contact queriesArchivist [${this.config?.intersect?.queries?.archivist}]`);
426
- const responsesArchivist = assertEx2(await this.responsesArchivist(), () => `Unable to contact responsesArchivist [${this.config?.intersect?.queries?.archivist}]`);
400
+ const queryArchivist = assertEx3(await this.queriesArchivist(), () => `Unable to contact queriesArchivist [${this.config?.intersect?.queries?.archivist}]`);
401
+ const responsesArchivist = assertEx3(await this.responsesArchivist(), () => `Unable to contact responsesArchivist [${this.config?.intersect?.queries?.archivist}]`);
427
402
  const queryDestination = query.$meta?.destination;
428
403
  if (queryDestination && queryDestination?.includes(localModule.address)) {
429
404
  const queryIndex = query.payload_hashes.indexOf(query.query);
@@ -586,13 +561,13 @@ var PubSubBridgeSchema = "network.xyo.bridge.pubsub";
586
561
  var PubSubBridgeConfigSchema = `${PubSubBridgeSchema}.config`;
587
562
 
588
563
  // src/PubSubBridge.ts
589
- import { assertEx as assertEx4 } from "@xylabs/assert";
564
+ import { assertEx as assertEx5 } from "@xylabs/assert";
590
565
  import { exists } from "@xylabs/exists";
591
566
  import { AbstractBridge } from "@xyo-network/abstract-bridge";
592
567
  import { creatableModule } from "@xyo-network/module-model";
593
568
 
594
569
  // src/PubSubBridgeModuleResolver.ts
595
- import { assertEx as assertEx3 } from "@xylabs/assert";
570
+ import { assertEx as assertEx4 } from "@xylabs/assert";
596
571
  import { isAddress } from "@xylabs/hex";
597
572
  import { AbstractBridgeModuleResolver, wrapModuleWithType } from "@xyo-network/abstract-bridge";
598
573
  import { Account } from "@xyo-network/account";
@@ -609,7 +584,7 @@ var PubSubBridgeModuleResolver = class extends AbstractBridgeModuleResolver {
609
584
  }
610
585
  const idParts = id.split(":");
611
586
  const firstPart = idParts.shift();
612
- assertEx3(isAddress(firstPart), () => `Invalid module address: ${firstPart}`);
587
+ assertEx4(isAddress(firstPart), () => `Invalid module address: ${firstPart}`);
613
588
  const remainderParts = idParts.join(":");
614
589
  const account = Account.randomSync();
615
590
  const params = {
@@ -626,13 +601,13 @@ var PubSubBridgeModuleResolver = class extends AbstractBridgeModuleResolver {
626
601
  const state = await proxy.state();
627
602
  if (state) {
628
603
  const configSchema = state.find((payload) => payload.schema === ConfigSchema)?.config;
629
- const config = assertEx3(state.find((payload) => payload.schema === configSchema), () => "Unable to locate config");
604
+ const config = assertEx4(state.find((payload) => payload.schema === configSchema), () => "Unable to locate config");
630
605
  proxy.setConfig(config);
631
606
  }
632
607
  }
633
608
  await proxy.start?.();
634
609
  const wrapped = wrapModuleWithType(proxy, account);
635
- const as = assertEx3(asModuleInstance2(wrapped, {}), () => `Failed to asModuleInstance [${id}]`);
610
+ const as = assertEx4(asModuleInstance2(wrapped, {}), () => `Failed to asModuleInstance [${id}]`);
636
611
  proxy.upResolver.add(as);
637
612
  proxy.downResolver.add(as);
638
613
  this.add(as);
@@ -671,7 +646,7 @@ var PubSubBridge = class extends AbstractBridge {
671
646
  get resolver() {
672
647
  this._resolver = this._resolver ?? new PubSubBridgeModuleResolver({
673
648
  bridge: this,
674
- busClient: assertEx4(this.busClient(), () => "busClient not configured"),
649
+ busClient: assertEx5(this.busClient(), () => "busClient not configured"),
675
650
  wrapperAccount: this.account
676
651
  });
677
652
  return this._resolver;
@@ -680,7 +655,7 @@ var PubSubBridge = class extends AbstractBridge {
680
655
  return `${this.config.name ?? moduleName}`;
681
656
  }
682
657
  get roots() {
683
- return assertEx4(this.config.roots, () => "roots not configured");
658
+ return assertEx5(this.config.roots, () => "roots not configured");
684
659
  }
685
660
  async discoverRoots() {
686
661
  const rootInstances = (await Promise.all(this.roots.map(async (root) => await this.resolver.resolve(root)))).filter(exists);
@@ -690,22 +665,24 @@ var PubSubBridge = class extends AbstractBridge {
690
665
  return rootInstances;
691
666
  }
692
667
  async exposeHandler(id, options) {
693
- const { maxDepth = 2, direction = "all" } = options ?? {};
694
- const module = assertEx4(await super.resolve(id), () => `Expose failed to locate module [${id}]`);
668
+ const { maxDepth = 2, direction = "all", required = true } = options ?? {};
669
+ const host = assertEx5(this.busHost(), () => "Not configured as a host");
670
+ const module = await host.expose(id, {
671
+ required
672
+ });
695
673
  if (module) {
696
- const host = assertEx4(this.busHost(), () => "Not configured as a host");
697
- host.expose(module.address);
698
- const children = await module.resolve("*", {
674
+ const children = maxDepth > 0 ? await module.resolve("*", {
699
675
  direction,
700
676
  maxDepth,
701
677
  visibility: "public"
702
- });
703
- for (const child of children) {
704
- host.expose(child.address);
705
- }
678
+ }) : [];
679
+ const exposedChildren = (await Promise.all(children.map((child) => this.exposeHandler(child.address, {
680
+ maxDepth: maxDepth - 1,
681
+ required: false
682
+ })))).flat().filter(exists);
706
683
  return [
707
684
  module,
708
- ...children
685
+ ...exposedChildren
709
686
  ];
710
687
  }
711
688
  return [];
@@ -721,25 +698,22 @@ var PubSubBridge = class extends AbstractBridge {
721
698
  return await super.startHandler();
722
699
  }
723
700
  async unexposeHandler(id, options) {
724
- const { maxDepth = 10, direction } = options ?? {};
725
- const filterOptions = {
726
- direction
727
- };
728
- const module = await super.resolve(id, filterOptions);
701
+ const { maxDepth = 2, direction = "all", required = true } = options ?? {};
702
+ const host = assertEx5(this.busHost(), () => "Not configured as a host");
703
+ const module = await host.unexpose(id, required);
729
704
  if (module) {
730
- const host = assertEx4(this.busHost(), () => "Not configured as a host");
731
- host.unexpose(module.address);
732
- const children = await module.resolve("*", {
705
+ const children = maxDepth > 0 ? await module.resolve("*", {
733
706
  direction,
734
707
  maxDepth,
735
708
  visibility: "public"
736
- });
737
- for (const child of children) {
738
- host.unexpose(child.address);
739
- }
709
+ }) : [];
710
+ const exposedChildren = (await Promise.all(children.map((child) => this.unexposeHandler(child.address, {
711
+ maxDepth: maxDepth - 1,
712
+ required: false
713
+ })))).flat().filter(exists);
740
714
  return [
741
715
  module,
742
- ...children
716
+ ...exposedChildren
743
717
  ];
744
718
  }
745
719
  return [];