@xyo-network/node 2.70.3 → 2.70.5

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/src/MemoryNode.ts DELETED
@@ -1,209 +0,0 @@
1
- import { assertEx } from '@xylabs/assert'
2
- import { AnyConfigSchema, CompositeModuleResolver, EventListener, Module, ModuleInstance, ModuleResolver } from '@xyo-network/module'
3
- import { isNodeModule, NodeConfig, NodeConfigSchema, NodeInstance, NodeModuleEventData, NodeModuleParams } from '@xyo-network/node-model'
4
- import compact from 'lodash/compact'
5
-
6
- import { AbstractNode } from './AbstractNode'
7
-
8
- export type MemoryNodeParams = NodeModuleParams<AnyConfigSchema<NodeConfig>>
9
-
10
- export class MemoryNode<TParams extends MemoryNodeParams = MemoryNodeParams, TEventData extends NodeModuleEventData = NodeModuleEventData>
11
- extends AbstractNode<TParams, TEventData>
12
- implements NodeInstance
13
- {
14
- static override configSchemas = [NodeConfigSchema]
15
-
16
- private registeredModuleMap: Record<string, ModuleInstance> = {}
17
-
18
- override async attach(nameOrAddress: string, external?: boolean) {
19
- await this.started('throw')
20
- return (await this.attachUsingAddress(nameOrAddress, external)) ?? (await this.attachUsingName(nameOrAddress, external))
21
- }
22
-
23
- override async detach(nameOrAddress: string) {
24
- await this.started('throw')
25
- return (await this.detachUsingAddress(nameOrAddress)) ?? (await this.detachUsingName(nameOrAddress))
26
- }
27
-
28
- override async register(module: ModuleInstance) {
29
- await this.started('throw')
30
- assertEx(!this.registeredModuleMap[module.address], `Module already registered at that address[${module.address}]`)
31
- this.registeredModuleMap[module.address] = module
32
- const args = { module, name: module.config.name }
33
- await this.emit('moduleRegistered', args)
34
- }
35
-
36
- override registered() {
37
- return Object.keys(this.registeredModuleMap).map((key) => {
38
- return key
39
- })
40
- }
41
-
42
- override registeredModules() {
43
- return Object.values(this.registeredModuleMap).map((value) => {
44
- return value
45
- })
46
- }
47
-
48
- override async unregister(module: ModuleInstance) {
49
- await this.started('throw')
50
- await this.detach(module.address)
51
- delete this.registeredModuleMap[module.address]
52
- const args = { module, name: module.config.name }
53
- await this.emit('moduleUnregistered', args)
54
- return this
55
- }
56
-
57
- protected override startHandler() {
58
- return super.startHandler()
59
- }
60
-
61
- private async attachUsingAddress(address: string, external?: boolean) {
62
- const existingModule = (await this.resolve({ address: [address] })).pop()
63
- assertEx(!existingModule, `Module [${existingModule?.config.name ?? existingModule?.address}] already attached at address [${address}]`)
64
- const module = this.registeredModuleMap[address]
65
-
66
- if (!module) {
67
- return
68
- }
69
-
70
- const notifiedAddresses: string[] = []
71
-
72
- const getModulesToNotifyAbout = async (node: ModuleInstance) => {
73
- //send attach events for all existing attached modules
74
- const childModules = await node.resolve(undefined, { direction: 'down' })
75
- return compact(
76
- childModules.map((child) => {
77
- //don't report self
78
- if (node.address === child.address) {
79
- return
80
- }
81
-
82
- //prevent loop
83
- if (notifiedAddresses.includes(child.address)) {
84
- return
85
- }
86
-
87
- notifiedAddresses.push(child.address)
88
-
89
- return child
90
- }),
91
- )
92
- }
93
-
94
- const notificationList = await getModulesToNotifyAbout(module)
95
-
96
- //give it private access
97
- module.upResolver.addResolver?.(this.privateResolver)
98
-
99
- //give it public access
100
- module.upResolver.addResolver?.(this.downResolver as CompositeModuleResolver)
101
-
102
- //give it outside access
103
- module.upResolver.addResolver?.(this.upResolver)
104
-
105
- if (external) {
106
- //expose it externally
107
- this.downResolver.addResolver(module.downResolver as ModuleResolver)
108
- } else {
109
- this.privateResolver.addResolver(module.downResolver as ModuleResolver)
110
- }
111
-
112
- const args = { module, name: module.config.name }
113
- await this.emit('moduleAttached', args)
114
-
115
- if (isNodeModule(module)) {
116
- if (external) {
117
- const attachedListener: EventListener<TEventData['moduleAttached']> = async (args: TEventData['moduleAttached']) =>
118
- await this.emit('moduleAttached', args)
119
-
120
- const detachedListener: EventListener<TEventData['moduleDetached']> = async (args: TEventData['moduleDetached']) =>
121
- await this.emit('moduleDetached', args)
122
-
123
- module.on('moduleAttached', attachedListener)
124
- module.on('moduleDetached', detachedListener)
125
- }
126
- }
127
-
128
- const notifyOfExistingModules = async (childModules: Module[]) => {
129
- await Promise.all(
130
- childModules.map(async (child) => {
131
- const args = { module: child, name: child.config.name }
132
- await this.emit('moduleAttached', args)
133
- }),
134
- )
135
- }
136
-
137
- await notifyOfExistingModules(notificationList)
138
-
139
- return address
140
- }
141
-
142
- private async attachUsingName(name: string, external?: boolean) {
143
- const address = this.moduleAddressFromName(name)
144
- if (address) {
145
- return await this.attachUsingAddress(address, external)
146
- }
147
- }
148
-
149
- private async detachUsingAddress(address: string) {
150
- const module = this.registeredModuleMap[address]
151
-
152
- if (!module) {
153
- return
154
- }
155
-
156
- //remove inside access
157
- module.upResolver?.removeResolver?.(this.privateResolver)
158
-
159
- //remove outside access
160
- module.upResolver?.removeResolver?.(this.upResolver)
161
-
162
- //remove external exposure
163
- this.downResolver.removeResolver(module.downResolver as ModuleResolver)
164
-
165
- const args = { module, name: module.config.name }
166
- await this.emit('moduleDetached', args)
167
-
168
- //notify of all sub node children detach
169
- const notifiedAddresses: string[] = []
170
- if (isNodeModule(module)) {
171
- const notifyOfExistingModules = async (node: ModuleInstance) => {
172
- //send attach events for all existing attached modules
173
- const childModules = await node.resolve(undefined, { direction: 'down' })
174
- await Promise.all(
175
- childModules.map(async (child) => {
176
- //don't report self
177
- if (node.address === child.address) {
178
- return
179
- }
180
-
181
- //prevent loop
182
- if (notifiedAddresses.includes(child.address)) {
183
- return
184
- }
185
- notifiedAddresses.push(child.address)
186
- await this.emit('moduleDetached', { module: child })
187
- }),
188
- )
189
- }
190
- await notifyOfExistingModules(module)
191
- }
192
- return address
193
- }
194
-
195
- private async detachUsingName(name: string) {
196
- const address = this.moduleAddressFromName(name)
197
- if (address) {
198
- return await this.detachUsingAddress(address)
199
- }
200
- return
201
- }
202
-
203
- private moduleAddressFromName(name: string) {
204
- const address = Object.values(this.registeredModuleMap).find((value) => {
205
- return value.config.name === name
206
- }, undefined)?.address
207
- return address
208
- }
209
- }