@xyo-network/bridge-http 2.105.1 → 2.106.0-rc.2

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 (70) hide show
  1. package/dist/browser/HttpBridgeBase.d.cts +4 -1
  2. package/dist/browser/HttpBridgeBase.d.cts.map +1 -1
  3. package/dist/browser/HttpBridgeBase.d.mts +4 -1
  4. package/dist/browser/HttpBridgeBase.d.mts.map +1 -1
  5. package/dist/browser/HttpBridgeBase.d.ts +4 -1
  6. package/dist/browser/HttpBridgeBase.d.ts.map +1 -1
  7. package/dist/browser/HttpBridgeModuleResolver.d.cts +18 -2
  8. package/dist/browser/HttpBridgeModuleResolver.d.cts.map +1 -1
  9. package/dist/browser/HttpBridgeModuleResolver.d.mts +18 -2
  10. package/dist/browser/HttpBridgeModuleResolver.d.mts.map +1 -1
  11. package/dist/browser/HttpBridgeModuleResolver.d.ts +18 -2
  12. package/dist/browser/HttpBridgeModuleResolver.d.ts.map +1 -1
  13. package/dist/browser/ModuleProxy/ModuleProxy.d.cts +9 -1
  14. package/dist/browser/ModuleProxy/ModuleProxy.d.cts.map +1 -1
  15. package/dist/browser/ModuleProxy/ModuleProxy.d.mts +9 -1
  16. package/dist/browser/ModuleProxy/ModuleProxy.d.mts.map +1 -1
  17. package/dist/browser/ModuleProxy/ModuleProxy.d.ts +9 -1
  18. package/dist/browser/ModuleProxy/ModuleProxy.d.ts.map +1 -1
  19. package/dist/browser/index-browser.cjs +132 -60
  20. package/dist/browser/index-browser.cjs.map +1 -1
  21. package/dist/browser/index-browser.js +127 -55
  22. package/dist/browser/index-browser.js.map +1 -1
  23. package/dist/neutral/HttpBridgeBase.d.cts +4 -1
  24. package/dist/neutral/HttpBridgeBase.d.cts.map +1 -1
  25. package/dist/neutral/HttpBridgeBase.d.mts +4 -1
  26. package/dist/neutral/HttpBridgeBase.d.mts.map +1 -1
  27. package/dist/neutral/HttpBridgeBase.d.ts +4 -1
  28. package/dist/neutral/HttpBridgeBase.d.ts.map +1 -1
  29. package/dist/neutral/HttpBridgeModuleResolver.d.cts +18 -2
  30. package/dist/neutral/HttpBridgeModuleResolver.d.cts.map +1 -1
  31. package/dist/neutral/HttpBridgeModuleResolver.d.mts +18 -2
  32. package/dist/neutral/HttpBridgeModuleResolver.d.mts.map +1 -1
  33. package/dist/neutral/HttpBridgeModuleResolver.d.ts +18 -2
  34. package/dist/neutral/HttpBridgeModuleResolver.d.ts.map +1 -1
  35. package/dist/neutral/ModuleProxy/ModuleProxy.d.cts +9 -1
  36. package/dist/neutral/ModuleProxy/ModuleProxy.d.cts.map +1 -1
  37. package/dist/neutral/ModuleProxy/ModuleProxy.d.mts +9 -1
  38. package/dist/neutral/ModuleProxy/ModuleProxy.d.mts.map +1 -1
  39. package/dist/neutral/ModuleProxy/ModuleProxy.d.ts +9 -1
  40. package/dist/neutral/ModuleProxy/ModuleProxy.d.ts.map +1 -1
  41. package/dist/neutral/index-browser.cjs +132 -60
  42. package/dist/neutral/index-browser.cjs.map +1 -1
  43. package/dist/neutral/index-browser.js +127 -55
  44. package/dist/neutral/index-browser.js.map +1 -1
  45. package/dist/node/HttpBridgeBase.d.cts +4 -1
  46. package/dist/node/HttpBridgeBase.d.cts.map +1 -1
  47. package/dist/node/HttpBridgeBase.d.mts +4 -1
  48. package/dist/node/HttpBridgeBase.d.mts.map +1 -1
  49. package/dist/node/HttpBridgeBase.d.ts +4 -1
  50. package/dist/node/HttpBridgeBase.d.ts.map +1 -1
  51. package/dist/node/HttpBridgeModuleResolver.d.cts +18 -2
  52. package/dist/node/HttpBridgeModuleResolver.d.cts.map +1 -1
  53. package/dist/node/HttpBridgeModuleResolver.d.mts +18 -2
  54. package/dist/node/HttpBridgeModuleResolver.d.mts.map +1 -1
  55. package/dist/node/HttpBridgeModuleResolver.d.ts +18 -2
  56. package/dist/node/HttpBridgeModuleResolver.d.ts.map +1 -1
  57. package/dist/node/ModuleProxy/ModuleProxy.d.cts +9 -1
  58. package/dist/node/ModuleProxy/ModuleProxy.d.cts.map +1 -1
  59. package/dist/node/ModuleProxy/ModuleProxy.d.mts +9 -1
  60. package/dist/node/ModuleProxy/ModuleProxy.d.mts.map +1 -1
  61. package/dist/node/ModuleProxy/ModuleProxy.d.ts +9 -1
  62. package/dist/node/ModuleProxy/ModuleProxy.d.ts.map +1 -1
  63. package/dist/node/index.cjs +145 -72
  64. package/dist/node/index.cjs.map +1 -1
  65. package/dist/node/index.js +139 -66
  66. package/dist/node/index.js.map +1 -1
  67. package/package.json +24 -20
  68. package/src/HttpBridgeBase.ts +52 -5
  69. package/src/HttpBridgeModuleResolver.ts +42 -35
  70. package/src/ModuleProxy/ModuleProxy.ts +68 -2
@@ -16,15 +16,16 @@ import {
16
16
  QuerySendFinishedEventArgs,
17
17
  QuerySendStartedEventArgs,
18
18
  } from '@xyo-network/bridge-model'
19
- import { NodeManifestPayload, NodeManifestPayloadSchema } from '@xyo-network/manifest-model'
19
+ import { ModuleManifestPayload, NodeManifestPayload, NodeManifestPayloadSchema } from '@xyo-network/manifest-model'
20
20
  import {
21
21
  AnyConfigSchema,
22
22
  creatableModule,
23
+ ModuleIdentifier,
23
24
  ModuleInstance,
24
25
  ModuleQueryResult,
25
- ModuleResolverInstance,
26
26
  ModuleStateQuery,
27
27
  ModuleStateQuerySchema,
28
+ ResolveHelper,
28
29
  } from '@xyo-network/module-model'
29
30
  import { asAttachableNodeInstance } from '@xyo-network/node-model'
30
31
  import { isPayloadOfSchemaType, Payload, Schema, WithMeta } from '@xyo-network/payload-model'
@@ -103,6 +104,28 @@ export class HttpBridgeBase<TParams extends HttpBridgeParams> extends AbstractBr
103
104
  return this._resolver
104
105
  }
105
106
 
107
+ async connect(id: ModuleIdentifier): Promise<Address | undefined> {
108
+ const transformedId = assertEx(await ResolveHelper.transformModuleIdentifier(id), () => `Unable to transform module identifier: ${id}`)
109
+ //check if already connected
110
+ const existingInstance = await this.resolve<ModuleInstance>(transformedId)
111
+ if (existingInstance) {
112
+ return existingInstance.address
113
+ }
114
+
115
+ //use the resolver to create the proxy instance
116
+ const [instance] = await this.resolver.resolveHandler<ModuleInstance>(id)
117
+ return this.connectInstance(instance)
118
+ }
119
+
120
+ async disconnect(id: ModuleIdentifier): Promise<Address | undefined> {
121
+ const transformedId = assertEx(await ResolveHelper.transformModuleIdentifier(id), () => `Unable to transform module identifier: ${id}`)
122
+ const instance = await this.resolve<ModuleInstance>(transformedId)
123
+ if (instance) {
124
+ this.downResolver.remove(instance.address)
125
+ return instance.address
126
+ }
127
+ }
128
+
106
129
  override exposeHandler(_id: string, _options?: BridgeExposeOptions | undefined): Promisable<ModuleInstance[]> {
107
130
  throw new Error('Unsupported')
108
131
  }
@@ -178,6 +201,24 @@ export class HttpBridgeBase<TParams extends HttpBridgeParams> extends AbstractBr
178
201
  throw new Error('Unsupported')
179
202
  }
180
203
 
204
+ protected connectInstance(instance?: ModuleInstance): Address | undefined {
205
+ if (instance) {
206
+ this.downResolver.add(instance)
207
+ /*if (maxDepth > 0) {
208
+ const node = asNodeInstance(instance)
209
+ if (node) {
210
+ const state = await node.state()
211
+ const children = (state?.filter(isPayloadOfSchemaType<AddressPayload>(AddressSchema)).map((s) => s.address) ?? []).filter(
212
+ (a) => a !== instance.address,
213
+ )
214
+ await Promise.all(children.map((child) => this.connect(child, maxDepth - 1)))
215
+ }
216
+ }*/
217
+ this.logger?.log(`Connect: ${instance.id}`)
218
+ return instance.address
219
+ }
220
+ }
221
+
181
222
  private async getRootState() {
182
223
  const queryPayload: ModuleStateQuery = { schema: ModuleStateQuerySchema }
183
224
  const boundQuery = await this.bindQuery(queryPayload)
@@ -197,16 +238,22 @@ export class HttpBridgeBase<TParams extends HttpBridgeParams> extends AbstractBr
197
238
  }
198
239
  }
199
240
 
200
- private async resolveRootNode(nodeManifest: NodeManifestPayload): Promise<ModuleInstance[]> {
241
+ private async resolveRootNode(nodeManifest: ModuleManifestPayload): Promise<ModuleInstance[]> {
201
242
  const rootModule = assertEx(
202
- (await this.resolver.resolveHandler(assertEx(nodeManifest.status?.address, () => 'Root has no address'))).at(0),
243
+ (
244
+ await this.resolver.resolveHandler(
245
+ assertEx(nodeManifest.status?.address, () => 'Root has no address'),
246
+ undefined,
247
+ { manifest: nodeManifest },
248
+ )
249
+ ).at(0),
203
250
  () => `Root not found [${nodeManifest.status?.address}]`,
204
251
  )
205
252
  assertEx(rootModule.constructor.name !== 'HttpModuleProxy', () => 'rootModule is not a Wrapper')
206
253
  const rootNode = asAttachableNodeInstance(rootModule, 'Root modules is not a node')
207
254
  if (rootNode) {
208
255
  this.logger.debug(`rootNode: ${rootNode.id}`)
209
- this.downResolver.addResolver(rootNode as unknown as ModuleResolverInstance)
256
+ this.connectInstance(rootNode)
210
257
  return [rootNode]
211
258
  }
212
259
  return []
@@ -12,6 +12,8 @@ import {
12
12
  ModuleInstance,
13
13
  ResolveHelper,
14
14
  } from '@xyo-network/module-model'
15
+ import { Mutex } from 'async-mutex'
16
+ import { LRUCache } from 'lru-cache'
15
17
 
16
18
  import { BridgeQuerySender, HttpModuleProxy, HttpModuleProxyParams } from './ModuleProxy'
17
19
 
@@ -23,6 +25,9 @@ export interface HttpBridgeModuleResolverParams extends BridgeModuleResolverPara
23
25
  export class HttpBridgeModuleResolver<
24
26
  T extends HttpBridgeModuleResolverParams = HttpBridgeModuleResolverParams,
25
27
  > extends AbstractBridgeModuleResolver<T> {
28
+ protected _resolvedCache = new LRUCache<Address, ModuleInstance>({ max: 1000 })
29
+ protected _resolvedCacheMutex = new Mutex()
30
+
26
31
  get querySender() {
27
32
  return this.params.querySender
28
33
  }
@@ -31,37 +36,44 @@ export class HttpBridgeModuleResolver<
31
36
  return new URL(address, this.params.rootUrl)
32
37
  }
33
38
 
34
- override async resolveHandler<T extends ModuleInstance = ModuleInstance>(id: ModuleIdentifier, options?: ModuleFilterOptions<T>): Promise<T[]> {
39
+ override async resolveHandler<T extends ModuleInstance = ModuleInstance>(
40
+ id: ModuleIdentifier,
41
+ options?: ModuleFilterOptions<T>,
42
+ params?: Partial<HttpModuleProxyParams>,
43
+ ): Promise<T[]> {
35
44
  const parentResult = await super.resolveHandler(id, options)
36
45
  if (parentResult.length > 0) {
37
46
  return parentResult
38
47
  }
39
- if (id === '*') {
40
- return []
41
- }
42
48
  const idParts = id.split(':')
43
- const untransformedFirstPart = assertEx(idParts.shift(), () => `Invalid module identifier: ${id}`)
49
+ const untransformedFirstPart = assertEx(idParts.shift(), () => 'Missing module identifier')
44
50
  const firstPart = await ResolveHelper.transformModuleIdentifier(untransformedFirstPart)
45
- const moduleAddress = firstPart as Address
46
51
  assertEx(isAddress(firstPart), () => `Invalid module address: ${firstPart}`)
47
52
  const remainderParts = idParts.join(':')
48
- const params: HttpModuleProxyParams = {
49
- account: Account.randomSync(),
50
- additionalSigners: this.params.additionalSigners,
51
- archiving: this.params.archiving,
52
- config: { schema: ModuleConfigSchema },
53
- host: this,
54
- moduleAddress,
55
- onQuerySendFinished: this.params.onQuerySendFinished,
56
- onQuerySendStarted: this.params.onQuerySendStarted,
57
- querySender: this.querySender,
58
- }
53
+ const instance: T = await this._resolvedCacheMutex.runExclusive(async () => {
54
+ const cachedMod = this._resolvedCache.get(firstPart as Address)
55
+ if (cachedMod) {
56
+ const result = idParts.length <= 0 ? cachedMod : cachedMod.resolve(remainderParts, { ...options, maxDepth: (options?.maxDepth ?? 5) - 1 })
57
+ return result as T
58
+ }
59
+ const account = Account.randomSync()
60
+ const finalParams: HttpModuleProxyParams = {
61
+ account,
62
+ archiving: this.params.archiving,
63
+ config: { schema: ModuleConfigSchema },
64
+ host: this,
65
+ moduleAddress: firstPart as Address,
66
+ onQuerySendFinished: this.params.onQuerySendFinished,
67
+ onQuerySendStarted: this.params.onQuerySendStarted,
68
+ querySender: this.params.querySender,
69
+ ...params,
70
+ }
59
71
 
60
- this.logger?.debug(`creating HttpProxy [${moduleAddress}] ${id}`)
72
+ this.logger?.debug(`creating HttpProxy [${firstPart}] ${id}`)
73
+ console.log(`creating HttpProxy [${firstPart}] ${id}`)
74
+
75
+ const proxy = new HttpModuleProxy<T, HttpModuleProxyParams>(finalParams)
61
76
 
62
- const proxy = new HttpModuleProxy<T, HttpModuleProxyParams>(params)
63
- //calling state here to get the config
64
- if (proxy) {
65
77
  const state = await proxy.state()
66
78
  if (state) {
67
79
  const configSchema = (state.find((payload) => payload.schema === ConfigSchema) as ConfigPayload | undefined)?.config
@@ -71,21 +83,16 @@ export class HttpBridgeModuleResolver<
71
83
  ) as ModuleConfig
72
84
  proxy.setConfig(config)
73
85
  }
74
- }
75
-
76
- await proxy.start()
77
86
 
78
- const wrapped = assertEx(wrapModuleWithType(proxy, Account.randomSync()) as unknown as T, () => `Failed to wrapModuleWithType [${id}]`)
79
- const instance = assertEx(asModuleInstance<T>(wrapped, {}), () => `Failed to asModuleInstance [${id}]`)
80
- proxy.upResolver.add(instance)
81
- proxy.downResolver.add(instance)
82
-
83
- if (remainderParts.length > 0) {
84
- const result = await wrapped.resolve<T>(remainderParts, options)
85
- return result ? [result] : []
86
- }
87
+ console.log(`created HttpProxy [${firstPart}] ${proxy.id}`)
87
88
 
88
- //console.log(`resolved: ${proxy.address} [${wrapped.constructor.name}] [${as.constructor.name}]`)
89
- return [instance]
89
+ await proxy.start?.()
90
+ const wrapped = wrapModuleWithType(proxy, account) as unknown as T
91
+ assertEx(asModuleInstance<T>(wrapped, {}), () => `Failed to asModuleInstance [${id}]`)
92
+ this._resolvedCache.set(wrapped.address, wrapped)
93
+ return wrapped as ModuleInstance as T
94
+ })
95
+ const result = remainderParts.length > 0 ? await instance.resolve(remainderParts, options) : instance
96
+ return result ? [result] : []
90
97
  }
91
98
  }
@@ -1,8 +1,19 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { exists } from '@xylabs/exists'
1
3
  import { forget } from '@xylabs/forget'
2
- import { Address } from '@xylabs/hex'
4
+ import { Address, isAddress } from '@xylabs/hex'
3
5
  import { QueryBoundWitness } from '@xyo-network/boundwitness-model'
4
6
  import { AbstractModuleProxy, ModuleProxyParams } from '@xyo-network/bridge-abstract'
5
- import { AttachableModuleInstance, ModuleInstance, ModuleQueryResult } from '@xyo-network/module-model'
7
+ import {
8
+ AttachableModuleInstance,
9
+ ModuleFilter,
10
+ ModuleFilterOptions,
11
+ ModuleIdentifier,
12
+ ModuleInstance,
13
+ ModuleQueryResult,
14
+ ResolveHelper,
15
+ ResolveHelperConfig,
16
+ } from '@xyo-network/module-model'
6
17
  import { Payload } from '@xyo-network/payload-model'
7
18
 
8
19
  export interface BridgeQuerySender {
@@ -46,4 +57,59 @@ export class HttpModuleProxy<
46
57
  }
47
58
  return result
48
59
  }
60
+
61
+ override async publicChildren(): Promise<ModuleInstance[]> {
62
+ return (
63
+ await Promise.all(
64
+ Object.values(await this.childAddressMap())
65
+ .filter(exists)
66
+ .map((address) => this.resolve(address)),
67
+ )
68
+ ).filter(exists)
69
+ }
70
+
71
+ /** @deprecated do not pass undefined. If trying to get all, pass '*' */
72
+ override async resolve(): Promise<ModuleInstance[]>
73
+ override async resolve<T extends ModuleInstance = ModuleInstance>(all: '*', options?: ModuleFilterOptions<T>): Promise<T[]>
74
+ override async resolve<T extends ModuleInstance = ModuleInstance>(filter: ModuleFilter, options?: ModuleFilterOptions<T>): Promise<T[]>
75
+ override async resolve<T extends ModuleInstance = ModuleInstance>(id: ModuleIdentifier, options?: ModuleFilterOptions<T>): Promise<T | undefined>
76
+ /** @deprecated use '*' if trying to resolve all */
77
+ override async resolve<T extends ModuleInstance = ModuleInstance>(filter?: ModuleFilter, options?: ModuleFilterOptions<T>): Promise<T[]>
78
+ override async resolve<T extends ModuleInstance = ModuleInstance>(
79
+ idOrFilter: ModuleFilter<T> | ModuleIdentifier = '*',
80
+ options: ModuleFilterOptions<T> = {},
81
+ ): Promise<T | T[] | undefined> {
82
+ const config: ResolveHelperConfig = {
83
+ address: this.address,
84
+ dead: this.dead,
85
+ downResolver: this.downResolver,
86
+ logger: this.logger,
87
+ module: this,
88
+ transformers: this.moduleIdentifierTransformers,
89
+ upResolver: this.upResolver,
90
+ }
91
+ if (idOrFilter === '*') {
92
+ return (await this.publicChildren()) as T[]
93
+ }
94
+ switch (typeof idOrFilter) {
95
+ case 'string': {
96
+ const parts = idOrFilter.split(':')
97
+ const first = assertEx(parts.shift(), () => 'Missing first')
98
+ const remainingPath = parts.join(':')
99
+ const address =
100
+ isAddress(first) ? first
101
+ : this.id === first ? this.address
102
+ : this.childAddressByName(first)
103
+ if (!address) return undefined
104
+ const firstInstance = (await this.params.host.resolve(address)) as ModuleInstance | undefined
105
+ return (remainingPath ? await firstInstance?.resolve(remainingPath) : firstInstance) as T | undefined
106
+ }
107
+ case 'object': {
108
+ return (await ResolveHelper.resolve(config, idOrFilter, options)).filter((mod) => mod.address !== this.address)
109
+ }
110
+ default: {
111
+ return (await ResolveHelper.resolve(config, idOrFilter, options)).filter((mod) => mod.address !== this.address)
112
+ }
113
+ }
114
+ }
49
115
  }