@xyo-network/node 4.2.1 → 5.0.0
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/package.json +25 -21
- package/src/spec/MemoryNode/Manifest.spec.ts +57 -0
- package/src/spec/MemoryNode/MemoryNode.spec.ts +434 -0
- package/src/spec/MemoryNode/WithArchivistAndDiviner.spec.ts +115 -0
- package/src/spec/MemoryNode/__snapshots__/MemoryNode.spec.ts.snap +68 -0
- package/src/spec/asModule.spec.ts +42 -0
- package/src/spec/isModule.spec.ts +42 -0
- package/xy.config.ts +0 -10
- package/xyo-config.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/node",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -28,29 +28,33 @@
|
|
|
28
28
|
},
|
|
29
29
|
"module": "dist/neutral/index.mjs",
|
|
30
30
|
"types": "dist/neutral/index.d.ts",
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"src"
|
|
34
|
+
],
|
|
31
35
|
"dependencies": {
|
|
32
|
-
"@xyo-network/node-model": "^
|
|
33
|
-
"@xyo-network/node-wrapper": "^
|
|
36
|
+
"@xyo-network/node-model": "^5.0.0",
|
|
37
|
+
"@xyo-network/node-wrapper": "^5.0.0"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
36
|
-
"@xylabs/delay": "^
|
|
37
|
-
"@xylabs/ts-scripts-yarn3": "^7.0.
|
|
38
|
-
"@xylabs/tsconfig": "^7.0.
|
|
39
|
-
"@xylabs/vitest-extended": "^
|
|
40
|
-
"@xylabs/vitest-matchers": "^
|
|
41
|
-
"@xyo-network/account": "^
|
|
42
|
-
"@xyo-network/account-model": "^
|
|
43
|
-
"@xyo-network/archivist-memory": "^
|
|
44
|
-
"@xyo-network/archivist-model": "^
|
|
45
|
-
"@xyo-network/diviner-archivist": "^
|
|
46
|
-
"@xyo-network/diviner-huri": "^
|
|
47
|
-
"@xyo-network/diviner-model": "^
|
|
48
|
-
"@xyo-network/manifest-model": "^
|
|
49
|
-
"@xyo-network/module-model": "^
|
|
50
|
-
"@xyo-network/node-memory": "^
|
|
51
|
-
"@xyo-network/payload": "^
|
|
52
|
-
"@xyo-network/wallet": "^
|
|
53
|
-
"@xyo-network/witness-adhoc": "^
|
|
40
|
+
"@xylabs/delay": "^5.0.0",
|
|
41
|
+
"@xylabs/ts-scripts-yarn3": "^7.0.2",
|
|
42
|
+
"@xylabs/tsconfig": "^7.0.2",
|
|
43
|
+
"@xylabs/vitest-extended": "^5.0.0",
|
|
44
|
+
"@xylabs/vitest-matchers": "^5.0.0",
|
|
45
|
+
"@xyo-network/account": "^5.0.0",
|
|
46
|
+
"@xyo-network/account-model": "^5.0.0",
|
|
47
|
+
"@xyo-network/archivist-memory": "^5.0.0",
|
|
48
|
+
"@xyo-network/archivist-model": "^5.0.0",
|
|
49
|
+
"@xyo-network/diviner-archivist": "^5.0.0",
|
|
50
|
+
"@xyo-network/diviner-huri": "^5.0.0",
|
|
51
|
+
"@xyo-network/diviner-model": "^5.0.0",
|
|
52
|
+
"@xyo-network/manifest-model": "^5.0.0",
|
|
53
|
+
"@xyo-network/module-model": "^5.0.0",
|
|
54
|
+
"@xyo-network/node-memory": "^5.0.0",
|
|
55
|
+
"@xyo-network/payload": "^5.0.0",
|
|
56
|
+
"@xyo-network/wallet": "^5.0.0",
|
|
57
|
+
"@xyo-network/witness-adhoc": "^5.0.0",
|
|
54
58
|
"typescript": "^5.8.3",
|
|
55
59
|
"vitest": "^3.2.4"
|
|
56
60
|
},
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import type { NodeManifestPayload } from '@xyo-network/manifest-model'
|
|
4
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
5
|
+
import { AdhocWitness, AdhocWitnessConfigSchema } from '@xyo-network/witness-adhoc'
|
|
6
|
+
import {
|
|
7
|
+
describe, expect, it,
|
|
8
|
+
} from 'vitest'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @group node
|
|
12
|
+
* @group module
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
describe('MemoryNode', () => {
|
|
16
|
+
// AbstractModule.defaultLogger = new ConsoleLogger(LogLevel.log)
|
|
17
|
+
it('Creates MemoryNode from Manifest', async () => {
|
|
18
|
+
const memoryNode = await MemoryNode.create({
|
|
19
|
+
account: 'random',
|
|
20
|
+
config: { name: 'MemoryNode', schema: 'network.xyo.node.config' },
|
|
21
|
+
})
|
|
22
|
+
const privateWitnesses = [
|
|
23
|
+
await AdhocWitness.create({ account: 'random', config: { name: 'PrivateWitness1', schema: AdhocWitnessConfigSchema } }),
|
|
24
|
+
await AdhocWitness.create({ account: 'random', config: { name: 'PrivateWitness2', schema: AdhocWitnessConfigSchema } }),
|
|
25
|
+
await AdhocWitness.create({ account: 'random', config: { name: 'PrivateWitness3', schema: AdhocWitnessConfigSchema } }),
|
|
26
|
+
]
|
|
27
|
+
const publicWitnesses = [
|
|
28
|
+
await AdhocWitness.create({ account: 'random', config: { name: 'PublicWitness1', schema: AdhocWitnessConfigSchema } }),
|
|
29
|
+
await AdhocWitness.create({ account: 'random', config: { name: 'PublicWitness2', schema: AdhocWitnessConfigSchema } }),
|
|
30
|
+
await AdhocWitness.create({ account: 'random', config: { name: 'PublicWitness3', schema: AdhocWitnessConfigSchema } }),
|
|
31
|
+
await AdhocWitness.create({ account: 'random', config: { name: 'PublicWitness4', schema: AdhocWitnessConfigSchema } }),
|
|
32
|
+
]
|
|
33
|
+
await Promise.all(
|
|
34
|
+
publicWitnesses.map(async (witness) => {
|
|
35
|
+
await memoryNode.register(witness)
|
|
36
|
+
await memoryNode.attach(witness.address, true)
|
|
37
|
+
}),
|
|
38
|
+
)
|
|
39
|
+
await Promise.all(
|
|
40
|
+
privateWitnesses.map(async (witness) => {
|
|
41
|
+
await memoryNode.register(witness)
|
|
42
|
+
await memoryNode.attach(witness.address, false)
|
|
43
|
+
}),
|
|
44
|
+
)
|
|
45
|
+
const publicModules = await memoryNode.resolve('*')
|
|
46
|
+
expect(publicModules).toBeArrayOfSize(8)
|
|
47
|
+
/* const privateModules = await memoryNode.resolve('*', { visibility: 'private' })
|
|
48
|
+
expect(privateModules).toBeArrayOfSize(3)
|
|
49
|
+
const allModules = await memoryNode.resolve('*', { visibility: 'all' })
|
|
50
|
+
expect(allModules).toBeArrayOfSize(8) */
|
|
51
|
+
|
|
52
|
+
const manifest = (await memoryNode.manifest()) as NodeManifestPayload
|
|
53
|
+
// console.log(`manifest: ${toSafeJsonString(manifest, 10)}`)
|
|
54
|
+
expect(manifest.modules?.public ?? []).toBeArrayOfSize(4)
|
|
55
|
+
// expect(manifest.modules?.private).toBeArrayOfSize(3)
|
|
56
|
+
})
|
|
57
|
+
})
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { delay } from '@xylabs/delay'
|
|
2
|
+
import { matchers } from '@xylabs/vitest-matchers'
|
|
3
|
+
import type { AccountInstance } from '@xyo-network/account-model'
|
|
4
|
+
import { MemoryArchivist } from '@xyo-network/archivist-memory'
|
|
5
|
+
import type { AttachableArchivistInstance } from '@xyo-network/archivist-model'
|
|
6
|
+
import type {
|
|
7
|
+
AddressPayload,
|
|
8
|
+
AttachableModuleInstance,
|
|
9
|
+
Module,
|
|
10
|
+
ModuleDescription,
|
|
11
|
+
ModuleDescriptionPayload,
|
|
12
|
+
} from '@xyo-network/module-model'
|
|
13
|
+
import {
|
|
14
|
+
AddressSchema,
|
|
15
|
+
ModuleDescriptionSchema,
|
|
16
|
+
} from '@xyo-network/module-model'
|
|
17
|
+
import { MemoryNode, MemoryNodeHelper } from '@xyo-network/node-memory'
|
|
18
|
+
import type { ModuleAttachedEventArgs } from '@xyo-network/node-model'
|
|
19
|
+
import { NodeConfigSchema } from '@xyo-network/node-model'
|
|
20
|
+
import type { Payload } from '@xyo-network/payload'
|
|
21
|
+
import { isPayloadOfSchemaType } from '@xyo-network/payload'
|
|
22
|
+
import { HDWallet } from '@xyo-network/wallet'
|
|
23
|
+
import {
|
|
24
|
+
beforeAll,
|
|
25
|
+
beforeEach,
|
|
26
|
+
describe, expect, it,
|
|
27
|
+
} from 'vitest'
|
|
28
|
+
|
|
29
|
+
expect.extend(matchers)
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @group node
|
|
33
|
+
* @group module
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
describe('MemoryNode', () => {
|
|
37
|
+
let testAccount1: AccountInstance
|
|
38
|
+
let testAccount2: AccountInstance
|
|
39
|
+
let testAccount3: AccountInstance
|
|
40
|
+
let testAccount4: AccountInstance
|
|
41
|
+
const archivistConfig = { schema: MemoryArchivist.defaultConfigSchema }
|
|
42
|
+
const nodeConfig = { schema: NodeConfigSchema }
|
|
43
|
+
let node: MemoryNode
|
|
44
|
+
beforeAll(async () => {
|
|
45
|
+
testAccount1 = await HDWallet.fromPhrase('cushion student broken thing poet mistake item dutch traffic gloom awful still')
|
|
46
|
+
testAccount2 = await HDWallet.fromPhrase('siren tenant achieve enough tone roof album champion tiny civil lottery hundred')
|
|
47
|
+
testAccount3 = await HDWallet.fromPhrase('person wheat floor tumble pond develop sauce attract neither toilet build enrich')
|
|
48
|
+
testAccount4 = await HDWallet.fromPhrase('kit sound script century margin into guilt region engine garment lab rifle')
|
|
49
|
+
})
|
|
50
|
+
beforeEach(async () => {
|
|
51
|
+
const nodeModule = await MemoryNode.create({ account: testAccount1, config: nodeConfig })
|
|
52
|
+
node = nodeModule
|
|
53
|
+
})
|
|
54
|
+
/* describe('create', () => {
|
|
55
|
+
describe('with autoAttachExternallyResolved true', () => {
|
|
56
|
+
it('attaches external modules to internal resolver', async () => {
|
|
57
|
+
// Arrange
|
|
58
|
+
// Create a MemoryNode with no modules in the internal
|
|
59
|
+
// resolver and one module in the external resolver
|
|
60
|
+
const resolver = new CompositeModuleResolver({})
|
|
61
|
+
const internalResolver = new CompositeModuleResolver({})
|
|
62
|
+
const params: MemoryNodeParams = {
|
|
63
|
+
config: { schema: NodeConfigSchema },
|
|
64
|
+
internalResolver,
|
|
65
|
+
resolver,
|
|
66
|
+
}
|
|
67
|
+
const module = await MemoryArchivist.create()
|
|
68
|
+
const filter = { address: [module.address] }
|
|
69
|
+
resolver.add(module)
|
|
70
|
+
// No modules exist in internal resolver
|
|
71
|
+
expect(await internalResolver.resolve(filter)).toBeArrayOfSize(0)
|
|
72
|
+
// Module exists in external resolver
|
|
73
|
+
expect(await resolver.resolve(filter)).toBeArrayOfSize(1)
|
|
74
|
+
const node = await MemoryNode.create(params)
|
|
75
|
+
// No modules are attached
|
|
76
|
+
expect(await node.attached()).toBeArrayOfSize(0)
|
|
77
|
+
|
|
78
|
+
// Act
|
|
79
|
+
// Query for unattached module (by address) that exists in
|
|
80
|
+
// external resolver
|
|
81
|
+
expect(await node.resolve(filter)).toBeArrayOfSize(1)
|
|
82
|
+
|
|
83
|
+
// Assert
|
|
84
|
+
// Module is now attached
|
|
85
|
+
expect(await node.attached()).toBeArrayOfSize(1)
|
|
86
|
+
// Module exists in internal resolver
|
|
87
|
+
expect(await internalResolver.resolve(filter)).toBeArrayOfSize(1)
|
|
88
|
+
// Module still exists in external resolver
|
|
89
|
+
expect(await resolver.resolve(filter)).toBeArrayOfSize(1)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
}) */
|
|
93
|
+
describe('register', () => {
|
|
94
|
+
it('registers module', async () => {
|
|
95
|
+
const mod = await MemoryArchivist.create({ account: 'random' })
|
|
96
|
+
await node.register(mod)
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
describe('registered', () => {
|
|
100
|
+
describe('with no modules registered', () => {
|
|
101
|
+
it('returns empty array', async () => {
|
|
102
|
+
const result = await node.registered()
|
|
103
|
+
expect(result).toBeArrayOfSize(0)
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
describe('with modules registered', () => {
|
|
107
|
+
let mod: AttachableModuleInstance
|
|
108
|
+
beforeEach(async () => {
|
|
109
|
+
mod = await MemoryArchivist.create({ account: 'random' })
|
|
110
|
+
await node.register(mod)
|
|
111
|
+
})
|
|
112
|
+
it('lists addresses of registered modules', async () => {
|
|
113
|
+
const result = await node.registered()
|
|
114
|
+
expect(result).toBeArrayOfSize(1)
|
|
115
|
+
expect(result).toEqual([mod.address])
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
describe('attach', () => {
|
|
120
|
+
let mod: AttachableModuleInstance
|
|
121
|
+
beforeEach(async () => {
|
|
122
|
+
mod = await MemoryArchivist.create({ account: 'random' })
|
|
123
|
+
await node.register(mod)
|
|
124
|
+
})
|
|
125
|
+
it('attaches module', async () => {
|
|
126
|
+
await node.attach(mod.address, true)
|
|
127
|
+
})
|
|
128
|
+
it('emits event on module attach', async () => {
|
|
129
|
+
let eventDone = false
|
|
130
|
+
return await new Promise<void>((resolve, reject) => {
|
|
131
|
+
node.on('moduleAttached', (args) => {
|
|
132
|
+
const { mod } = args as ModuleAttachedEventArgs
|
|
133
|
+
expect(mod).toBeObject()
|
|
134
|
+
expect(mod.address).toBe(mod.address)
|
|
135
|
+
expect(mod).toBe(mod)
|
|
136
|
+
eventDone = true
|
|
137
|
+
})
|
|
138
|
+
node
|
|
139
|
+
.attach(mod.address, true)
|
|
140
|
+
.then(async () => {
|
|
141
|
+
// wait for up to 5 seconds
|
|
142
|
+
let waitFrames = 50
|
|
143
|
+
while (waitFrames) {
|
|
144
|
+
if (eventDone) {
|
|
145
|
+
resolve()
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
await delay(100)
|
|
149
|
+
waitFrames--
|
|
150
|
+
}
|
|
151
|
+
reject('Event not fired [within 5 seconds]')
|
|
152
|
+
})
|
|
153
|
+
.catch(() => {
|
|
154
|
+
reject('Attach failed')
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
describe('attached', () => {
|
|
160
|
+
let mod: AttachableModuleInstance
|
|
161
|
+
beforeEach(async () => {
|
|
162
|
+
mod = await MemoryArchivist.create({ account: 'random' })
|
|
163
|
+
await node.register(mod)
|
|
164
|
+
})
|
|
165
|
+
describe('with no modules attached', () => {
|
|
166
|
+
it('returns empty array', async () => {
|
|
167
|
+
const result = await node.attached()
|
|
168
|
+
expect(result).toBeArrayOfSize(0)
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
describe('with modules attached', () => {
|
|
172
|
+
it('lists addresses of attached modules', async () => {
|
|
173
|
+
await node.attach(mod.address, true)
|
|
174
|
+
const result = await node.attached()
|
|
175
|
+
expect(result.length).toBe(1)
|
|
176
|
+
expect(result).toEqual([mod.address])
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
describe('detach', () => {
|
|
181
|
+
let mod: AttachableModuleInstance
|
|
182
|
+
beforeEach(async () => {
|
|
183
|
+
mod = await MemoryArchivist.create({ account: 'random' })
|
|
184
|
+
await node.register(mod)
|
|
185
|
+
await node.attach(mod.address, true)
|
|
186
|
+
})
|
|
187
|
+
it('deregisters existing module', async () => {
|
|
188
|
+
await node.detach(mod.address)
|
|
189
|
+
})
|
|
190
|
+
/* it('allows deregistering non-existent mod', () => {
|
|
191
|
+
node.detach('4a15a6c96665931b76c1d2a587ea1132dbfdc266')
|
|
192
|
+
}) */
|
|
193
|
+
})
|
|
194
|
+
describe('registeredModules', () => {
|
|
195
|
+
let mod: AttachableModuleInstance
|
|
196
|
+
beforeEach(async () => {
|
|
197
|
+
mod = await MemoryArchivist.create({ account: 'random' })
|
|
198
|
+
})
|
|
199
|
+
describe('with no mods registered', () => {
|
|
200
|
+
it('returns empty array', () => {
|
|
201
|
+
const mods = node.registeredModules()
|
|
202
|
+
expect(mods).toBeArrayOfSize(0)
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
describe('with modules registered', () => {
|
|
206
|
+
it('returns registered modules', async () => {
|
|
207
|
+
await node.register(mod)
|
|
208
|
+
const mods = node.registeredModules()
|
|
209
|
+
expect(mods).toBeArrayOfSize(1)
|
|
210
|
+
expect(mods).toContain(mod)
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
describe('unregister', () => {
|
|
215
|
+
it('un-registers module', async () => {
|
|
216
|
+
const mod = await MemoryArchivist.create({ account: 'random' })
|
|
217
|
+
await node.register(mod)
|
|
218
|
+
expect(node.registeredModules()).toContain(mod)
|
|
219
|
+
await node.unregister(mod)
|
|
220
|
+
expect(node.registeredModules()).not.toContain(mod)
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
describe('description', () => {
|
|
224
|
+
const validateModuleDescription = (description?: ModuleDescription) => {
|
|
225
|
+
expect(description).toBeObject()
|
|
226
|
+
expect(description?.address).toBeString()
|
|
227
|
+
expect(description?.queries).toBeArray()
|
|
228
|
+
description?.queries.map((query) => {
|
|
229
|
+
expect(query).toBeString()
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
describe('node without child modules', () => {
|
|
233
|
+
it('describes node alone', async () => {
|
|
234
|
+
const description = (await node.state()).find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
235
|
+
validateModuleDescription(description)
|
|
236
|
+
expect(description?.children).toBeArrayOfSize(0)
|
|
237
|
+
})
|
|
238
|
+
it('serializes to JSON consistently', async () => {
|
|
239
|
+
const description = (await node.state()).find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
240
|
+
expect(prettyPrintDescription(description)).toMatchSnapshot()
|
|
241
|
+
})
|
|
242
|
+
})
|
|
243
|
+
describe('node with child modules', () => {
|
|
244
|
+
beforeEach(async () => {
|
|
245
|
+
const mods = await Promise.all([
|
|
246
|
+
MemoryArchivist.create({ account: testAccount2, config: { ...archivistConfig, name: 'testAccount2' } }),
|
|
247
|
+
MemoryArchivist.create({ account: testAccount3, config: { ...archivistConfig, name: 'testAccount3' } }),
|
|
248
|
+
])
|
|
249
|
+
await Promise.all(
|
|
250
|
+
mods.map(async (mod) => {
|
|
251
|
+
await node.register(mod)
|
|
252
|
+
expect(await node.attach(mod.address, true)).toEqual(mod.address)
|
|
253
|
+
expect(await node.detach(mod.address)).toEqual(mod.address)
|
|
254
|
+
if (mod.modName) {
|
|
255
|
+
expect(await node.attach(mod.modName, true)).toEqual(mod.address)
|
|
256
|
+
expect(await node.detach(mod.modName)).toEqual(mod.address)
|
|
257
|
+
}
|
|
258
|
+
expect(await node.attach(mod.address, true)).toEqual(mod.address)
|
|
259
|
+
}),
|
|
260
|
+
)
|
|
261
|
+
})
|
|
262
|
+
it('describes node and child mods', async () => {
|
|
263
|
+
const description = (await node.state()).find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
264
|
+
validateModuleDescription(description)
|
|
265
|
+
expect(description?.children).toBeArrayOfSize(2)
|
|
266
|
+
// description.children?.map(validateModuleDescription)
|
|
267
|
+
})
|
|
268
|
+
it('serializes to JSON consistently', async () => {
|
|
269
|
+
const description = (await node.state()).find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
270
|
+
expect(prettyPrintDescription(description)).toMatchSnapshot()
|
|
271
|
+
})
|
|
272
|
+
})
|
|
273
|
+
describe('node with nested nodes and mods', () => {
|
|
274
|
+
beforeEach(async () => {
|
|
275
|
+
const nestedNode = await MemoryNode.create({ account: testAccount2, config: nodeConfig })
|
|
276
|
+
const nestedModules: AttachableArchivistInstance[] = [await MemoryArchivist.create({ account: testAccount3, config: archivistConfig })]
|
|
277
|
+
await Promise.all(
|
|
278
|
+
nestedModules.map(async (mod) => {
|
|
279
|
+
await nestedNode.register?.(mod)
|
|
280
|
+
await nestedNode.attach(mod.address, true)
|
|
281
|
+
}),
|
|
282
|
+
)
|
|
283
|
+
const rootModules: AttachableModuleInstance[] = [await MemoryArchivist.create({ account: testAccount4, config: archivistConfig })]
|
|
284
|
+
rootModules.push(nestedNode)
|
|
285
|
+
await Promise.all(
|
|
286
|
+
rootModules.map(async (mod) => {
|
|
287
|
+
await node.register(mod)
|
|
288
|
+
await node.attach(mod.address, true)
|
|
289
|
+
}),
|
|
290
|
+
)
|
|
291
|
+
})
|
|
292
|
+
it('describes node and all nested nodes and child modules', async () => {
|
|
293
|
+
const memoryNode = await MemoryNode.create({ account: 'random' })
|
|
294
|
+
const archivist1 = await MemoryArchivist.create({ account: 'random' })
|
|
295
|
+
const archivist2 = await MemoryArchivist.create({ account: 'random' })
|
|
296
|
+
await memoryNode.register(archivist1)
|
|
297
|
+
await memoryNode.attach(archivist1.address, true)
|
|
298
|
+
await memoryNode.register(archivist2)
|
|
299
|
+
await memoryNode.attach(archivist2.address, true)
|
|
300
|
+
console.log('status:', memoryNode.status)
|
|
301
|
+
const description = (await memoryNode.state()).find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
302
|
+
validateModuleDescription(description)
|
|
303
|
+
expect(description?.children).toBeArrayOfSize(2)
|
|
304
|
+
// description.children?.map(validateModuleDescription)
|
|
305
|
+
})
|
|
306
|
+
it('serializes to JSON consistently', async () => {
|
|
307
|
+
const description = (await node.state()).find(isPayloadOfSchemaType<ModuleDescriptionPayload>(ModuleDescriptionSchema))
|
|
308
|
+
expect(prettyPrintDescription(description)).toMatchSnapshot()
|
|
309
|
+
})
|
|
310
|
+
it('clone-all', async () => {
|
|
311
|
+
const newNode = await MemoryNodeHelper.attachToNewNode(node, '*')
|
|
312
|
+
const newNodeChildren = await newNode.publicChildren()
|
|
313
|
+
const nodeChildren = await node.publicChildren()
|
|
314
|
+
expect(newNodeChildren.length).toEqual(nodeChildren.length)
|
|
315
|
+
expect(newNodeChildren.includes(nodeChildren[0])).toBe(true)
|
|
316
|
+
})
|
|
317
|
+
it('clone-one (public)', async () => {
|
|
318
|
+
const mod = await MemoryArchivist.create({ account: 'random', config: { ...archivistConfig, name: 'CloneModule' } })
|
|
319
|
+
await node.register(mod)
|
|
320
|
+
await node.attach(mod.address, true)
|
|
321
|
+
|
|
322
|
+
const newNode = await MemoryNodeHelper.attachToNewNode(node, 'CloneModule')
|
|
323
|
+
const newNodeChild = await newNode.resolve('CloneModule')
|
|
324
|
+
const nodeChild = await node.resolve('CloneModule', { maxDepth: 1 })
|
|
325
|
+
expect(newNodeChild?.id).toEqual(nodeChild?.id)
|
|
326
|
+
expect(newNodeChild?.address).toEqual(nodeChild?.address)
|
|
327
|
+
expect(newNodeChild).toEqual(nodeChild)
|
|
328
|
+
})
|
|
329
|
+
it('clone-one (private)', async () => {
|
|
330
|
+
const mod = await MemoryArchivist.create({ account: 'random', config: { ...archivistConfig, name: 'CloneModulePrivate' } })
|
|
331
|
+
await node.register(mod)
|
|
332
|
+
await node.attach(mod.address)
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
// this should except
|
|
336
|
+
await MemoryNodeHelper.attachToNewNode(node, 'CloneModulePrivate')
|
|
337
|
+
expect(false).toBeTrue()
|
|
338
|
+
} catch (e) {
|
|
339
|
+
expect(e).toBeInstanceOf(Error)
|
|
340
|
+
}
|
|
341
|
+
})
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
describe('discover', () => {
|
|
345
|
+
const archivistConfig = { schema: MemoryArchivist.defaultConfigSchema }
|
|
346
|
+
const validateStateResponse = (mod: Module, response: Payload[]) => {
|
|
347
|
+
expect(response).toBeArray()
|
|
348
|
+
const address = response.find(p => p.schema === AddressSchema) as AddressPayload
|
|
349
|
+
expect(address).toBeObject()
|
|
350
|
+
expect(address.address).toEqual(mod.address)
|
|
351
|
+
const config = response.find(p => p.schema === mod.config.schema)
|
|
352
|
+
expect(config).toBeObject()
|
|
353
|
+
expect(config?.schema).toBe(mod.config.schema)
|
|
354
|
+
const queries = response.filter(p => mod.queries.includes(p.schema))
|
|
355
|
+
expect(queries.length).toBeGreaterThanOrEqual(0)
|
|
356
|
+
for (const query of queries) {
|
|
357
|
+
expect(query).toBeObject()
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
describe('node without child modules', () => {
|
|
361
|
+
it('describes node alone', async () => {
|
|
362
|
+
const state = await node.state()
|
|
363
|
+
validateStateResponse(node, state)
|
|
364
|
+
})
|
|
365
|
+
})
|
|
366
|
+
describe('node with child modules', () => {
|
|
367
|
+
it('describes node and child modules', async () => {
|
|
368
|
+
const memoryNode = await MemoryNode.create({ account: 'random' })
|
|
369
|
+
const modules = await Promise.all([
|
|
370
|
+
MemoryArchivist.create({ account: testAccount2, config: archivistConfig }),
|
|
371
|
+
MemoryArchivist.create({ account: testAccount3, config: archivistConfig }),
|
|
372
|
+
])
|
|
373
|
+
await Promise.all(
|
|
374
|
+
modules.map(async (mod) => {
|
|
375
|
+
await memoryNode.register(mod)
|
|
376
|
+
await memoryNode.attach(mod.address, true)
|
|
377
|
+
}),
|
|
378
|
+
)
|
|
379
|
+
const state = await memoryNode.state()
|
|
380
|
+
|
|
381
|
+
const address0 = state.find(p => p.schema === AddressSchema && (p as AddressPayload).address === modules[0].address) as AddressPayload
|
|
382
|
+
expect(address0).toBeObject()
|
|
383
|
+
const address1 = state.find(p => p.schema === AddressSchema && (p as AddressPayload).address === modules[1].address) as AddressPayload
|
|
384
|
+
expect(address1).toBeObject()
|
|
385
|
+
})
|
|
386
|
+
})
|
|
387
|
+
describe('node with nested nodes and modules', () => {
|
|
388
|
+
beforeEach(async () => {
|
|
389
|
+
node = await MemoryNode.create({ account: 'random' })
|
|
390
|
+
const attachEvents: Module[] = []
|
|
391
|
+
node.on('moduleAttached', (args) => {
|
|
392
|
+
const { mod } = args as ModuleAttachedEventArgs
|
|
393
|
+
attachEvents.push(mod)
|
|
394
|
+
})
|
|
395
|
+
const nestedNode = await MemoryNode.create({ account: testAccount2, config: nodeConfig })
|
|
396
|
+
const nestedModules = [await MemoryArchivist.create({ account: testAccount3, config: archivistConfig })]
|
|
397
|
+
await Promise.all(
|
|
398
|
+
nestedModules.map(async (mod) => {
|
|
399
|
+
await nestedNode.register(mod)
|
|
400
|
+
await nestedNode.attach(mod.address, true)
|
|
401
|
+
}),
|
|
402
|
+
)
|
|
403
|
+
const rootModules: AttachableModuleInstance[] = [await MemoryArchivist.create({ account: testAccount4, config: archivistConfig })]
|
|
404
|
+
rootModules.push(nestedNode)
|
|
405
|
+
await Promise.all(
|
|
406
|
+
rootModules.map(async (mod) => {
|
|
407
|
+
await node.register(mod)
|
|
408
|
+
await node.attach(mod.address, true)
|
|
409
|
+
}),
|
|
410
|
+
)
|
|
411
|
+
expect(attachEvents.includes(nestedNode)).toBeTrue()
|
|
412
|
+
expect(attachEvents.includes(node)).toBeFalse()
|
|
413
|
+
expect(nestedModules.length).toBe(1)
|
|
414
|
+
for (const nestedModule of nestedModules) {
|
|
415
|
+
expect(attachEvents.includes(nestedModule)).toBeTrue()
|
|
416
|
+
}
|
|
417
|
+
expect(rootModules.length).toBe(2)
|
|
418
|
+
for (const rootModule of rootModules) {
|
|
419
|
+
expect(attachEvents.includes(rootModule)).toBeTrue()
|
|
420
|
+
}
|
|
421
|
+
const eventAddresses = attachEvents.map(mod => mod.address)
|
|
422
|
+
expect(eventAddresses.length).toBe(3)
|
|
423
|
+
})
|
|
424
|
+
it('describes node and all nested nodes and child modules', async () => {
|
|
425
|
+
const state = await node.state()
|
|
426
|
+
validateStateResponse(node, state)
|
|
427
|
+
})
|
|
428
|
+
})
|
|
429
|
+
})
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
const prettyPrintDescription = (description?: ModuleDescription) => {
|
|
433
|
+
return JSON.stringify(description, null, 2)
|
|
434
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
import '@xylabs/vitest-extended'
|
|
3
|
+
|
|
4
|
+
import { MemoryArchivist, MemoryArchivistConfigSchema } from '@xyo-network/archivist-memory'
|
|
5
|
+
import { asArchivistInstance } from '@xyo-network/archivist-model'
|
|
6
|
+
import { ArchivistPayloadDiviner, ArchivistPayloadDivinerConfigSchema } from '@xyo-network/diviner-archivist'
|
|
7
|
+
import type { HuriPayload } from '@xyo-network/diviner-huri'
|
|
8
|
+
import { HuriSchema } from '@xyo-network/diviner-huri'
|
|
9
|
+
import { asDivinerInstance } from '@xyo-network/diviner-model'
|
|
10
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
11
|
+
import type { Payload } from '@xyo-network/payload'
|
|
12
|
+
import { PayloadBuilder, PayloadSchema } from '@xyo-network/payload'
|
|
13
|
+
import {
|
|
14
|
+
describe, expect,
|
|
15
|
+
it,
|
|
16
|
+
} from 'vitest'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @group node
|
|
20
|
+
* @group module
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
describe('MemoryNode', () => {
|
|
24
|
+
it('WithArchivistAndDiviner', async () => {
|
|
25
|
+
const node = await MemoryNode.create({ account: 'random' })
|
|
26
|
+
const archivist = await MemoryArchivist.create({
|
|
27
|
+
account: 'random',
|
|
28
|
+
config: { name: 'Archivist', schema: MemoryArchivistConfigSchema },
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
await node.register(archivist)
|
|
32
|
+
await node.attach(archivist.address, true)
|
|
33
|
+
|
|
34
|
+
const privateArchivist = await MemoryArchivist.create({
|
|
35
|
+
account: 'random',
|
|
36
|
+
config: { name: 'PrivateArchivist', schema: MemoryArchivistConfigSchema },
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
await node.register(privateArchivist)
|
|
40
|
+
await node.attach(privateArchivist.address, false)
|
|
41
|
+
|
|
42
|
+
const diviner = await ArchivistPayloadDiviner.create({
|
|
43
|
+
account: 'random',
|
|
44
|
+
config: { archivist: archivist.address, schema: ArchivistPayloadDivinerConfigSchema },
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
await node.register(diviner)
|
|
48
|
+
await node.attach(diviner.address, true)
|
|
49
|
+
|
|
50
|
+
expect(await node.registered()).toBeArrayOfSize(3)
|
|
51
|
+
expect(await node.attached()).toBeArrayOfSize(3)
|
|
52
|
+
|
|
53
|
+
const foundArchivist = asArchivistInstance(await node.resolve(archivist.address))
|
|
54
|
+
expect(foundArchivist).toBeDefined()
|
|
55
|
+
const foundNamedArchivist = asArchivistInstance(await node.resolve('Archivist'))
|
|
56
|
+
expect(foundNamedArchivist).toBeDefined()
|
|
57
|
+
expect(foundArchivist?.address).toBe(archivist.address)
|
|
58
|
+
const testPayload = new PayloadBuilder<Payload<{ schema: PayloadSchema; test: boolean }>>({ schema: PayloadSchema })
|
|
59
|
+
.fields({ test: true })
|
|
60
|
+
.build()
|
|
61
|
+
|
|
62
|
+
await foundArchivist?.insert([testPayload])
|
|
63
|
+
|
|
64
|
+
const payloads = await foundArchivist?.all?.()
|
|
65
|
+
expect(payloads?.length).toBe(1)
|
|
66
|
+
|
|
67
|
+
if (payloads && payloads[0]) {
|
|
68
|
+
const huri = await PayloadBuilder.dataHash(payloads[0])
|
|
69
|
+
const huriPayload: HuriPayload = { huri: [huri], schema: HuriSchema }
|
|
70
|
+
const mod = await node.resolve(diviner.address)
|
|
71
|
+
const foundDiviner = asDivinerInstance(mod)
|
|
72
|
+
expect(foundDiviner).toBeDefined()
|
|
73
|
+
if (foundDiviner) {
|
|
74
|
+
const payloads = await foundDiviner.divine([huriPayload])
|
|
75
|
+
expect(payloads?.length).toBe(1)
|
|
76
|
+
expect(payloads[0]).toBeDefined()
|
|
77
|
+
if (payloads?.length === 1 && payloads[0]) {
|
|
78
|
+
expect(await PayloadBuilder.dataHash(payloads[0])).toBe(huri)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
expect((await node.resolve('*', { direction: 'up' })).length).toBe(1)
|
|
84
|
+
expect((await node.resolve('*', { direction: 'up', maxDepth: 0 })).length).toBe(1)
|
|
85
|
+
expect((await node.resolve('*', { direction: 'up', maxDepth: 1 })).length).toBe(1)
|
|
86
|
+
|
|
87
|
+
const nodeDown = await node.resolve('*', { direction: 'down' })
|
|
88
|
+
expect(nodeDown.length).toBe(3)
|
|
89
|
+
expect(nodeDown.find(mod => mod.address === node.address)).toBeDefined()
|
|
90
|
+
expect(nodeDown.find(mod => mod.address === archivist.address)).toBeDefined()
|
|
91
|
+
expect(nodeDown.find(mod => mod.address === diviner.address)).toBeDefined()
|
|
92
|
+
|
|
93
|
+
expect((await node.resolvePrivate('*', { direction: 'down' })).length).toBe(1)
|
|
94
|
+
expect((await node.resolve('*', { direction: 'down', maxDepth: 0 })).length).toBe(1)
|
|
95
|
+
expect((await node.resolve('*', { direction: 'down', maxDepth: 1 })).length).toBe(3)
|
|
96
|
+
|
|
97
|
+
// this should be 3 here and not 4 since node is at the top and asking it to resolve its privates
|
|
98
|
+
// from outside should not include the private cousin
|
|
99
|
+
expect((await node.resolve('*', { direction: 'all' })).length).toBe(3)
|
|
100
|
+
|
|
101
|
+
const archivistUp = await archivist.resolve('*', { direction: 'up' })
|
|
102
|
+
|
|
103
|
+
expect(archivistUp.find(mod => mod.address === node.address)).toBeDefined()
|
|
104
|
+
expect(archivistUp.find(mod => mod.address === archivist.address)).toBeDefined()
|
|
105
|
+
expect(archivistUp.find(mod => mod.address === diviner.address)).toBeDefined()
|
|
106
|
+
// this is 4 here since it will include the one private cousin
|
|
107
|
+
expect(archivistUp.length).toBe(4)
|
|
108
|
+
|
|
109
|
+
expect((await archivist.resolve('*', { direction: 'up', maxDepth: 1 })).length).toBe(2)
|
|
110
|
+
expect((await archivist.resolve('*', { direction: 'down' })).length).toBe(1)
|
|
111
|
+
|
|
112
|
+
// this is 4 here since it will include the one private cousin
|
|
113
|
+
expect((await archivist.resolve('*', { direction: 'all' })).length).toBe(4)
|
|
114
|
+
})
|
|
115
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`MemoryNode > description > node with child modules > serializes to JSON consistently 1`] = `
|
|
4
|
+
"{
|
|
5
|
+
"address": "a1df01bbdaa05f2294cdd6fbd92aace3086fe408",
|
|
6
|
+
"queries": [
|
|
7
|
+
"network.xyo.query.node.attach",
|
|
8
|
+
"network.xyo.query.node.certify",
|
|
9
|
+
"network.xyo.query.node.detach",
|
|
10
|
+
"network.xyo.query.node.attached",
|
|
11
|
+
"network.xyo.query.node.registered",
|
|
12
|
+
"network.xyo.query.module.address",
|
|
13
|
+
"network.xyo.query.module.subscribe",
|
|
14
|
+
"network.xyo.query.module.manifest",
|
|
15
|
+
"network.xyo.query.module.state"
|
|
16
|
+
],
|
|
17
|
+
"schema": "network.xyo.module.description",
|
|
18
|
+
"name": "Unnamed MemoryNode",
|
|
19
|
+
"children": [
|
|
20
|
+
"e8cae43b8ef15e6e2166b7560b2df802ac28fe53",
|
|
21
|
+
"ee84477649f67bcda3c604ad361313bdd9976c0f"
|
|
22
|
+
]
|
|
23
|
+
}"
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
exports[`MemoryNode > description > node with nested nodes and mods > serializes to JSON consistently 1`] = `
|
|
27
|
+
"{
|
|
28
|
+
"address": "a1df01bbdaa05f2294cdd6fbd92aace3086fe408",
|
|
29
|
+
"queries": [
|
|
30
|
+
"network.xyo.query.node.attach",
|
|
31
|
+
"network.xyo.query.node.certify",
|
|
32
|
+
"network.xyo.query.node.detach",
|
|
33
|
+
"network.xyo.query.node.attached",
|
|
34
|
+
"network.xyo.query.node.registered",
|
|
35
|
+
"network.xyo.query.module.address",
|
|
36
|
+
"network.xyo.query.module.subscribe",
|
|
37
|
+
"network.xyo.query.module.manifest",
|
|
38
|
+
"network.xyo.query.module.state"
|
|
39
|
+
],
|
|
40
|
+
"schema": "network.xyo.module.description",
|
|
41
|
+
"name": "Unnamed MemoryNode",
|
|
42
|
+
"children": [
|
|
43
|
+
"4c3e913823664e68ce252e256b8c442172dbec4a",
|
|
44
|
+
"e8cae43b8ef15e6e2166b7560b2df802ac28fe53",
|
|
45
|
+
"ee84477649f67bcda3c604ad361313bdd9976c0f"
|
|
46
|
+
]
|
|
47
|
+
}"
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
exports[`MemoryNode > description > node without child modules > serializes to JSON consistently 1`] = `
|
|
51
|
+
"{
|
|
52
|
+
"address": "a1df01bbdaa05f2294cdd6fbd92aace3086fe408",
|
|
53
|
+
"queries": [
|
|
54
|
+
"network.xyo.query.node.attach",
|
|
55
|
+
"network.xyo.query.node.certify",
|
|
56
|
+
"network.xyo.query.node.detach",
|
|
57
|
+
"network.xyo.query.node.attached",
|
|
58
|
+
"network.xyo.query.node.registered",
|
|
59
|
+
"network.xyo.query.module.address",
|
|
60
|
+
"network.xyo.query.module.subscribe",
|
|
61
|
+
"network.xyo.query.module.manifest",
|
|
62
|
+
"network.xyo.query.module.state"
|
|
63
|
+
],
|
|
64
|
+
"schema": "network.xyo.module.description",
|
|
65
|
+
"name": "Unnamed MemoryNode",
|
|
66
|
+
"children": []
|
|
67
|
+
}"
|
|
68
|
+
`;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* eslint-disable unicorn/no-useless-undefined */
|
|
2
|
+
import '@xylabs/vitest-extended'
|
|
3
|
+
|
|
4
|
+
import { Account } from '@xyo-network/account'
|
|
5
|
+
import { asModuleInstance } from '@xyo-network/module-model'
|
|
6
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
7
|
+
import {
|
|
8
|
+
describe, expect, test,
|
|
9
|
+
} from 'vitest'
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line no-restricted-imports
|
|
12
|
+
import {
|
|
13
|
+
asNodeInstance, NodeConfigSchema, NodeWrapper,
|
|
14
|
+
} from '../index.ts'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @group node
|
|
18
|
+
* @group module
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
describe('identity check (as)', () => {
|
|
22
|
+
test('asModuleInstance', async () => {
|
|
23
|
+
const node = await MemoryNode.create({ account: 'random', config: { schema: NodeConfigSchema } })
|
|
24
|
+
expect(asModuleInstance(node)).toBeDefined()
|
|
25
|
+
expect(asModuleInstance(null)).toBeUndefined()
|
|
26
|
+
expect(asModuleInstance(undefined)).toBeUndefined()
|
|
27
|
+
expect(asModuleInstance({})).toBeUndefined()
|
|
28
|
+
|
|
29
|
+
const wrapper = NodeWrapper.wrap(node, await Account.random())
|
|
30
|
+
expect(asModuleInstance(wrapper)).toBeDefined()
|
|
31
|
+
})
|
|
32
|
+
test('isNodeInstance', async () => {
|
|
33
|
+
const node = await MemoryNode.create({ account: 'random', config: { schema: NodeConfigSchema } })
|
|
34
|
+
expect(asNodeInstance(node)).toBeDefined()
|
|
35
|
+
expect(asNodeInstance(null)).toBeUndefined()
|
|
36
|
+
expect(asNodeInstance(undefined)).toBeUndefined()
|
|
37
|
+
expect(asNodeInstance({})).toBeUndefined()
|
|
38
|
+
|
|
39
|
+
const wrapper = NodeWrapper.wrap(node, await Account.random())
|
|
40
|
+
expect(asNodeInstance(wrapper)).toBeDefined()
|
|
41
|
+
})
|
|
42
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* eslint-disable unicorn/no-useless-undefined */
|
|
2
|
+
import '@xylabs/vitest-extended'
|
|
3
|
+
|
|
4
|
+
import { Account } from '@xyo-network/account'
|
|
5
|
+
import { isModuleInstance } from '@xyo-network/module-model'
|
|
6
|
+
import { MemoryNode } from '@xyo-network/node-memory'
|
|
7
|
+
import {
|
|
8
|
+
describe, expect, test,
|
|
9
|
+
} from 'vitest'
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line no-restricted-imports
|
|
12
|
+
import {
|
|
13
|
+
isNodeInstance, NodeConfigSchema, NodeWrapper,
|
|
14
|
+
} from '../index.ts'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @group node
|
|
18
|
+
* @group module
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
describe('identity check (is)', () => {
|
|
22
|
+
test('isModuleInstance', async () => {
|
|
23
|
+
const node = await MemoryNode.create({ account: 'random', config: { schema: NodeConfigSchema } })
|
|
24
|
+
expect(isModuleInstance(node)).toBeTrue()
|
|
25
|
+
expect(isModuleInstance(null)).toBeFalse()
|
|
26
|
+
expect(isModuleInstance(undefined)).toBeFalse()
|
|
27
|
+
expect(isModuleInstance({})).toBeFalse()
|
|
28
|
+
|
|
29
|
+
const wrapper = NodeWrapper.wrap(node, await Account.random())
|
|
30
|
+
expect(isModuleInstance(wrapper)).toBeTrue()
|
|
31
|
+
})
|
|
32
|
+
test('isNodeInstance', async () => {
|
|
33
|
+
const node = await MemoryNode.create({ account: 'random', config: { schema: NodeConfigSchema } })
|
|
34
|
+
expect(isNodeInstance(node)).toBeTrue()
|
|
35
|
+
expect(isNodeInstance(null)).toBeFalse()
|
|
36
|
+
expect(isNodeInstance(undefined)).toBeFalse()
|
|
37
|
+
expect(isNodeInstance({})).toBeFalse()
|
|
38
|
+
|
|
39
|
+
const wrapper = NodeWrapper.wrap(node, await Account.random())
|
|
40
|
+
expect(isNodeInstance(wrapper)).toBeTrue()
|
|
41
|
+
})
|
|
42
|
+
})
|
package/xy.config.ts
DELETED
package/xyo-config.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = { version: 1 }
|