@toa.io/userland 0.2.1-dev.3
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/example/components/echo/beacon/manifest.toa.yaml +9 -0
- package/example/components/echo/beacon/operations/signal.js +7 -0
- package/example/components/echo/beacon/samples/signal.yaml +7 -0
- package/example/components/math/calculations/manifest.toa.yaml +16 -0
- package/example/components/math/calculations/operations/add.js +7 -0
- package/example/components/math/calculations/operations/increment.js +15 -0
- package/example/components/math/calculations/samples/add.yaml +11 -0
- package/example/components/math/calculations/samples/increment.yaml +30 -0
- package/example/components/math/proxy/manifest.toa.yaml +11 -0
- package/example/components/math/proxy/operations/add.js +10 -0
- package/example/components/math/proxy/samples/add.yaml +11 -0
- package/example/components/tea/pots/manifest.toa.yaml +28 -0
- package/example/components/tea/pots/operations/same.js +13 -0
- package/example/components/tea/pots/receivers/store.orders.created.js +8 -0
- package/example/components/tea/pots/samples/messages/store.orders.created.yaml +37 -0
- package/example/components/tea/pots/samples/same.yaml +8 -0
- package/example/components/tea/pots/samples/transit.yaml +43 -0
- package/example/context.toa.yaml +3 -0
- package/example/samples/math.proxy.add.yaml +5 -0
- package/example/samples/messages/store.orders.created.yaml +8 -0
- package/example/stage/call.test.js +39 -0
- package/example/stage/events.test.js +48 -0
- package/example/stage/invoke.test.js +29 -0
- package/package.json +36 -0
- package/readme.md +9 -0
- package/samples/docs/sampling-dark.jpg +0 -0
- package/samples/docs/sampling-light.jpg +0 -0
- package/samples/notes.md +12 -0
- package/samples/package.json +5 -0
- package/samples/readme.md +66 -0
- package/samples/src/.replay/.suite/component.js +25 -0
- package/samples/src/.replay/.suite/index.js +7 -0
- package/samples/src/.replay/.suite/messages.js +39 -0
- package/samples/src/.replay/.suite/operation.js +28 -0
- package/samples/src/.replay/.suite/operations.js +18 -0
- package/samples/src/.replay/.suite/translate/.message/index.js +5 -0
- package/samples/src/.replay/.suite/translate/.message/request.js +31 -0
- package/samples/src/.replay/.suite/translate/.operation/calls.js +49 -0
- package/samples/src/.replay/.suite/translate/.operation/cleanup.js +16 -0
- package/samples/src/.replay/.suite/translate/.operation/events.js +16 -0
- package/samples/src/.replay/.suite/translate/.operation/index.js +11 -0
- package/samples/src/.replay/.suite/translate/.operation/prepare.js +14 -0
- package/samples/src/.replay/.suite/translate/.operation/specials/configuration.js +26 -0
- package/samples/src/.replay/.suite/translate/.operation/specials/index.js +5 -0
- package/samples/src/.replay/.suite/translate/index.js +7 -0
- package/samples/src/.replay/.suite/translate/message.js +26 -0
- package/samples/src/.replay/.suite/translate/operation.js +47 -0
- package/samples/src/.replay/.suite/translate/schemas/index.js +7 -0
- package/samples/src/.replay/.suite/translate/schemas/message.cos.yaml +10 -0
- package/samples/src/.replay/.suite/translate/schemas/operation.cos.yaml +23 -0
- package/samples/src/.replay/index.js +5 -0
- package/samples/src/.replay/suite.js +22 -0
- package/samples/src/.replay/test.js +17 -0
- package/samples/src/components.js +13 -0
- package/samples/src/context.js +18 -0
- package/samples/src/index.js +9 -0
- package/samples/src/replay.js +17 -0
- package/samples/src/suite/.read/index.js +7 -0
- package/samples/src/suite/.read/messages.js +35 -0
- package/samples/src/suite/.read/operations.js +45 -0
- package/samples/src/suite/.read/parse.js +24 -0
- package/samples/src/suite/components.js +28 -0
- package/samples/src/suite/context.js +19 -0
- package/samples/src/suite/index.js +7 -0
- package/samples/test/components.test.js +39 -0
- package/samples/test/context/components/ok/manifest.toa.yaml +2 -0
- package/samples/test/context/components/ok/samples/do.yaml +11 -0
- package/samples/test/context/components/ok/samples/dummies.dummy.do.yaml +11 -0
- package/samples/test/context/components/ok/samples/dummies.dummy.undo.yaml +7 -0
- package/samples/test/context/components/ok/samples/messages/somewhere.something.happened.yaml +6 -0
- package/samples/test/context/context.toa.yaml +3 -0
- package/samples/test/context/samples/dummies.dummy.observe.yaml +6 -0
- package/samples/test/context/samples/dummies.dummy.transit.yaml +10 -0
- package/samples/test/context/samples/messages/somewhere.something.happened.yaml +6 -0
- package/samples/test/context.fixtures.js +8 -0
- package/samples/test/context.test.js +78 -0
- package/samples/test/replay.fixtures.js +72 -0
- package/samples/test/replay.mock.js +7 -0
- package/samples/test/replay.test.js +116 -0
- package/samples/test/replay.translate.message.fixtures.js +24 -0
- package/samples/test/replay.translate.message.test.js +123 -0
- package/samples/test/replay.translate.mock.js +17 -0
- package/samples/test/replay.translate.operation.fixtures.js +107 -0
- package/samples/test/replay.translate.operation.test.js +68 -0
- package/samples/test/stage.mock.js +34 -0
- package/samples/test/suite.components.test.js +85 -0
- package/samples/test/suite.context.test.js +79 -0
- package/samples/test/suite.mock.js +10 -0
- package/samples/types/index.d.ts +8 -0
- package/samples/types/message.d.ts +24 -0
- package/samples/types/operation.d.ts +36 -0
- package/samples/types/replay.d.ts +13 -0
- package/samples/types/suite.d.ts +19 -0
- package/stage/package.json +5 -0
- package/stage/readme.md +41 -0
- package/stage/src/binding/binding.js +49 -0
- package/stage/src/binding/consumer.js +30 -0
- package/stage/src/binding/emitter.js +26 -0
- package/stage/src/binding/factory.js +49 -0
- package/stage/src/binding/index.js +10 -0
- package/stage/src/binding/label.js +12 -0
- package/stage/src/binding/producer.js +43 -0
- package/stage/src/binding/receiver.js +35 -0
- package/stage/src/component.js +18 -0
- package/stage/src/composition.js +19 -0
- package/stage/src/index.js +18 -0
- package/stage/src/manifest.js +12 -0
- package/stage/src/remote.js +22 -0
- package/stage/src/shutdown.js +19 -0
- package/stage/src/state.js +17 -0
- package/stage/test/binding/binding.test.js +15 -0
- package/stage/test/binding/consumer.test.js +52 -0
- package/stage/test/binding/emitter.test.js +54 -0
- package/stage/test/binding/producer.fixtures.js +10 -0
- package/stage/test/binding/producer.test.js +49 -0
- package/stage/test/binding/receiver.fixtures.js +7 -0
- package/stage/test/binding/receiver.test.js +54 -0
- package/stage/test/binding.mock.js +8 -0
- package/stage/test/boot.mock.js +16 -0
- package/stage/test/component.test.js +25 -0
- package/stage/test/composition.test.js +38 -0
- package/stage/test/manifest.test.js +24 -0
- package/stage/test/remote.test.js +32 -0
- package/stage/test/shutdown.test.js +66 -0
- package/stage/test/state.mock.js +8 -0
- package/stage/test/state.test.js +27 -0
- package/stage/types/binding.d.ts +20 -0
- package/stage/types/index.d.ts +28 -0
- package/stage/types/state.d.ts +14 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const boot = require('@toa.io/boot')
|
|
4
|
+
const { Locator } = require('@toa.io/core')
|
|
5
|
+
|
|
6
|
+
const { state } = require('./state')
|
|
7
|
+
|
|
8
|
+
/** @type {toa.stage.Remote} */
|
|
9
|
+
const remote = async (id) => {
|
|
10
|
+
const [namespace, name] = id.split('.')
|
|
11
|
+
const locator = new Locator(name, namespace)
|
|
12
|
+
|
|
13
|
+
const remote = await boot.remote(locator)
|
|
14
|
+
|
|
15
|
+
await remote.connect()
|
|
16
|
+
|
|
17
|
+
state.remotes.push(remote)
|
|
18
|
+
|
|
19
|
+
return remote
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.remote = remote
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { state } = require('./state')
|
|
4
|
+
const { binding } = require('./binding')
|
|
5
|
+
|
|
6
|
+
/** @type {toa.stage.Shutdown} */
|
|
7
|
+
const shutdown = async () => {
|
|
8
|
+
const components = state.components.map((component) => component.disconnect())
|
|
9
|
+
const compositions = state.compositions.map((composition) => composition.disconnect())
|
|
10
|
+
const remotes = state.remotes.map((remote) => remote.disconnect())
|
|
11
|
+
const disconnections = [...components, ...compositions, ...remotes]
|
|
12
|
+
|
|
13
|
+
await Promise.all(disconnections)
|
|
14
|
+
|
|
15
|
+
state.reset()
|
|
16
|
+
binding.reset()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
exports.shutdown = shutdown
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { properties, binding, Factory } = require('../../src').binding
|
|
4
|
+
|
|
5
|
+
it('should be async', async () => {
|
|
6
|
+
expect(properties.async).toStrictEqual(true)
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('should export Factory', async () => {
|
|
10
|
+
expect(Factory).toBeDefined()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('should export binding instance', async () => {
|
|
14
|
+
expect(binding).toBeDefined()
|
|
15
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
const { Connector, Locator } = require('@toa.io/core')
|
|
5
|
+
|
|
6
|
+
const { binding, Factory } = require('../../src/binding')
|
|
7
|
+
|
|
8
|
+
const factory = new Factory()
|
|
9
|
+
|
|
10
|
+
it('should expose consumers factory', async () => {
|
|
11
|
+
expect(factory.consumer).toBeDefined()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
/** @type {toa.core.bindings.Consumer} */
|
|
15
|
+
let consumer
|
|
16
|
+
|
|
17
|
+
/** @type {toa.core.Locator} */
|
|
18
|
+
let locator
|
|
19
|
+
|
|
20
|
+
/** @type {string} */
|
|
21
|
+
let label
|
|
22
|
+
|
|
23
|
+
const endpoint = generate()
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
jest.clearAllMocks()
|
|
27
|
+
binding.reset()
|
|
28
|
+
|
|
29
|
+
const namespace = generate()
|
|
30
|
+
const name = generate()
|
|
31
|
+
|
|
32
|
+
locator = new Locator(name, namespace)
|
|
33
|
+
label = locator.id + '.' + endpoint
|
|
34
|
+
consumer = factory.consumer(locator, endpoint)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should return Connector', async () => {
|
|
38
|
+
expect(consumer).toBeInstanceOf(Connector)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should return reply', async () => {
|
|
42
|
+
const request = generate()
|
|
43
|
+
const reply = generate()
|
|
44
|
+
const call = jest.fn(async () => reply)
|
|
45
|
+
|
|
46
|
+
await binding.reply(label, call)
|
|
47
|
+
|
|
48
|
+
const received = await consumer.request(request)
|
|
49
|
+
|
|
50
|
+
expect(call).toHaveBeenCalledWith(request)
|
|
51
|
+
expect(received).toStrictEqual(reply)
|
|
52
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
const { Locator, Connector } = require('@toa.io/core')
|
|
5
|
+
|
|
6
|
+
const { binding, Factory } = require('../../src/binding')
|
|
7
|
+
|
|
8
|
+
const factory = new Factory()
|
|
9
|
+
|
|
10
|
+
it('should expose emitters factory', async () => {
|
|
11
|
+
expect(factory.emitter).toBeDefined()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
/** @type {toa.core.bindings.Emitter} */
|
|
15
|
+
let emitter
|
|
16
|
+
|
|
17
|
+
/** @type {string} */
|
|
18
|
+
let label
|
|
19
|
+
|
|
20
|
+
/** @type {toa.core.Locator} */
|
|
21
|
+
let locator
|
|
22
|
+
|
|
23
|
+
const endpoint = generate()
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
jest.clearAllMocks()
|
|
27
|
+
binding.reset()
|
|
28
|
+
|
|
29
|
+
const namespace = generate()
|
|
30
|
+
const name = generate()
|
|
31
|
+
|
|
32
|
+
locator = new Locator(name, namespace)
|
|
33
|
+
label = locator.id + '.' + endpoint
|
|
34
|
+
emitter = factory.emitter(locator, endpoint)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should return Connector', async () => {
|
|
38
|
+
expect(emitter).toBeInstanceOf(Connector)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should call receiver', async () => {
|
|
42
|
+
const callback = jest.fn(async () => undefined)
|
|
43
|
+
|
|
44
|
+
await binding.subscribe(label, callback)
|
|
45
|
+
|
|
46
|
+
const payload = { [generate()]: generate() }
|
|
47
|
+
|
|
48
|
+
/** @type {toa.core.Message} */
|
|
49
|
+
const message = { payload }
|
|
50
|
+
|
|
51
|
+
await emitter.emit(message)
|
|
52
|
+
|
|
53
|
+
expect(callback).toHaveBeenCalledWith(message)
|
|
54
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const endpoints = [generate(), generate()]
|
|
6
|
+
const invoke = jest.fn(async () => generate())
|
|
7
|
+
const producer = /** @type {jest.MockedObject<toa.core.Component>} */ { invoke }
|
|
8
|
+
|
|
9
|
+
exports.endpoints = endpoints
|
|
10
|
+
exports.producer = producer
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
const { Locator, Connector } = require('@toa.io/core')
|
|
5
|
+
const { sample } = require('@toa.io/generic')
|
|
6
|
+
|
|
7
|
+
const fixtures = require('./producer.fixtures')
|
|
8
|
+
const { binding, Factory } = require('../../src/binding')
|
|
9
|
+
|
|
10
|
+
const factory = new Factory()
|
|
11
|
+
|
|
12
|
+
it('should expose producers factory', async () => {
|
|
13
|
+
expect(factory.producer).toBeDefined()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
/** @type {toa.core.Connector} */
|
|
17
|
+
let producer
|
|
18
|
+
|
|
19
|
+
/** @type {toa.core.Locator} */
|
|
20
|
+
let locator
|
|
21
|
+
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
jest.clearAllMocks()
|
|
24
|
+
binding.reset()
|
|
25
|
+
|
|
26
|
+
const namespace = generate()
|
|
27
|
+
const name = generate()
|
|
28
|
+
|
|
29
|
+
locator = new Locator(name, namespace)
|
|
30
|
+
producer = factory.producer(locator, fixtures.endpoints, fixtures.producer)
|
|
31
|
+
|
|
32
|
+
await producer.connect()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('should return Connector', async () => {
|
|
36
|
+
expect(producer).toBeInstanceOf(Connector)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('should return result', async () => {
|
|
40
|
+
const endpoint = sample(fixtures.endpoints)
|
|
41
|
+
const label = locator.id + '.' + endpoint
|
|
42
|
+
const request = { [generate()]: generate() }
|
|
43
|
+
|
|
44
|
+
const reply = await binding.request(label, request)
|
|
45
|
+
|
|
46
|
+
expect(fixtures.producer.invoke).toHaveBeenCalledWith(endpoint, request)
|
|
47
|
+
|
|
48
|
+
expect(reply).toStrictEqual(await fixtures.producer.invoke.mock.results[0].value)
|
|
49
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
const { Locator, Connector } = require('@toa.io/core')
|
|
5
|
+
|
|
6
|
+
const fixtures = require('./receiver.fixtures')
|
|
7
|
+
const { binding, Factory } = require('../../src/binding')
|
|
8
|
+
|
|
9
|
+
const factory = new Factory()
|
|
10
|
+
|
|
11
|
+
it('should expose receivers factory', async () => {
|
|
12
|
+
expect(factory.receiver).toBeDefined()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
/** @type {toa.core.Connector} */
|
|
16
|
+
let receiver
|
|
17
|
+
|
|
18
|
+
/** @type {toa.core.Locator} */
|
|
19
|
+
let locator
|
|
20
|
+
|
|
21
|
+
/** @type {string} */
|
|
22
|
+
let label
|
|
23
|
+
|
|
24
|
+
const id = generate()
|
|
25
|
+
const endpoint = generate()
|
|
26
|
+
|
|
27
|
+
beforeEach(async () => {
|
|
28
|
+
jest.clearAllMocks()
|
|
29
|
+
binding.reset()
|
|
30
|
+
|
|
31
|
+
const namespace = generate()
|
|
32
|
+
const name = generate()
|
|
33
|
+
|
|
34
|
+
locator = new Locator(name, namespace)
|
|
35
|
+
receiver = factory.receiver(locator, endpoint, id, fixtures.receiver)
|
|
36
|
+
label = locator.id + '.' + endpoint
|
|
37
|
+
|
|
38
|
+
await receiver.connect()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should return connector', async () => {
|
|
42
|
+
expect(receiver).toBeInstanceOf(Connector)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should call receiver', async () => {
|
|
46
|
+
const payload = { [generate()]: generate() }
|
|
47
|
+
|
|
48
|
+
/** @type {toa.core.Message} */
|
|
49
|
+
const message = { payload }
|
|
50
|
+
|
|
51
|
+
await binding.emit(label, message)
|
|
52
|
+
|
|
53
|
+
expect(fixtures.receiver.receive).toHaveBeenCalledWith(message)
|
|
54
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const connector = () => ({
|
|
6
|
+
connect: jest.fn(),
|
|
7
|
+
disconnect: jest.fn(),
|
|
8
|
+
link: jest.fn()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const manifest = jest.fn(async () => generate())
|
|
12
|
+
const component = jest.fn(async () => connector())
|
|
13
|
+
const composition = jest.fn(async () => connector())
|
|
14
|
+
const remote = jest.fn(async () => connector())
|
|
15
|
+
|
|
16
|
+
module.exports = { manifest, component, composition, remote }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const mock = {
|
|
6
|
+
boot: require('./boot.mock')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
jest.mock('@toa.io/boot', () => mock.boot)
|
|
10
|
+
|
|
11
|
+
const stage = require('../')
|
|
12
|
+
|
|
13
|
+
it('should be', () => {
|
|
14
|
+
expect(stage.component).toBeDefined()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should boot component', async () => {
|
|
18
|
+
const path = generate()
|
|
19
|
+
const component = await stage.component(path)
|
|
20
|
+
|
|
21
|
+
expect(mock.boot.manifest).toHaveBeenCalledWith(path)
|
|
22
|
+
expect(mock.boot.component).toHaveBeenCalledWith(await mock.boot.manifest.mock.results[0].value)
|
|
23
|
+
expect(component).toStrictEqual(await mock.boot.component.mock.results[0].value)
|
|
24
|
+
expect(component.connect).toHaveBeenCalled()
|
|
25
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const mock = {
|
|
6
|
+
boot: require('./boot.mock')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
jest.mock('@toa.io/boot', () => mock.boot)
|
|
10
|
+
|
|
11
|
+
const stage = require('../')
|
|
12
|
+
|
|
13
|
+
const paths = [generate(), generate()]
|
|
14
|
+
|
|
15
|
+
it('should be', () => {
|
|
16
|
+
expect(stage.composition).toBeDefined()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('should boot composition', async () => {
|
|
20
|
+
await stage.composition(paths)
|
|
21
|
+
|
|
22
|
+
expect(mock.boot.composition.mock.calls[0][0]).toStrictEqual(paths)
|
|
23
|
+
|
|
24
|
+
const composition = await mock.boot.composition.mock.results[0].value
|
|
25
|
+
|
|
26
|
+
expect(composition.connect).toHaveBeenCalled()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should override bindings', async () => {
|
|
30
|
+
await stage.composition(paths)
|
|
31
|
+
|
|
32
|
+
const path = require.resolve('../src/binding')
|
|
33
|
+
|
|
34
|
+
/** @type {toa.boot.composition.Options} */
|
|
35
|
+
const options = { bindings: [path] }
|
|
36
|
+
|
|
37
|
+
expect(mock.boot.composition.mock.calls[0][1]).toStrictEqual(options)
|
|
38
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const mock = {
|
|
6
|
+
boot: require('./boot.mock')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
jest.mock('@toa.io/boot', () => mock.boot)
|
|
10
|
+
|
|
11
|
+
const stage = require('../')
|
|
12
|
+
|
|
13
|
+
it('should be', () => {
|
|
14
|
+
expect(stage.manifest).toBeDefined()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should boot manifest', async () => {
|
|
18
|
+
const path = generate()
|
|
19
|
+
|
|
20
|
+
const manifest = await stage.manifest(path)
|
|
21
|
+
|
|
22
|
+
expect(mock.boot.manifest).toHaveBeenCalledWith(path)
|
|
23
|
+
expect(manifest).toStrictEqual(await mock.boot.manifest.mock.results[0].value)
|
|
24
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const mock = {
|
|
6
|
+
boot: require('./boot.mock')
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
jest.mock('@toa.io/boot', () => mock.boot)
|
|
10
|
+
|
|
11
|
+
const stage = require('../')
|
|
12
|
+
|
|
13
|
+
it('should be', () => {
|
|
14
|
+
expect(stage.remote).toBeDefined()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should connect remote', async () => {
|
|
18
|
+
const name = generate()
|
|
19
|
+
const namespace = generate()
|
|
20
|
+
const id = namespace + '.' + name
|
|
21
|
+
|
|
22
|
+
const remote = await stage.remote(id)
|
|
23
|
+
|
|
24
|
+
expect(mock.boot.remote).toHaveBeenCalled()
|
|
25
|
+
expect(remote).toStrictEqual(await mock.boot.remote.mock.results[0].value)
|
|
26
|
+
expect(remote.connect).toHaveBeenCalled()
|
|
27
|
+
|
|
28
|
+
const locator = mock.boot.remote.mock.calls[0][0]
|
|
29
|
+
|
|
30
|
+
expect(locator).toBeDefined()
|
|
31
|
+
expect(locator).toMatchObject({ name, namespace })
|
|
32
|
+
})
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const mock = {
|
|
6
|
+
boot: require('./boot.mock'),
|
|
7
|
+
state: require('./state.mock'),
|
|
8
|
+
binding: require('./binding.mock')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
jest.mock('@toa.io/boot', () => mock.boot)
|
|
12
|
+
jest.mock('../src/state', () => mock.state)
|
|
13
|
+
jest.mock('../src/binding', () => mock.binding)
|
|
14
|
+
|
|
15
|
+
const { state } = require('../src/state')
|
|
16
|
+
const { binding } = require('../src/binding')
|
|
17
|
+
const stage = require('../')
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.clearAllMocks()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should be', () => {
|
|
24
|
+
expect(stage.shutdown).toBeDefined()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should disconnect components', async () => {
|
|
28
|
+
const path = generate()
|
|
29
|
+
const component = await stage.component(path)
|
|
30
|
+
|
|
31
|
+
await stage.shutdown()
|
|
32
|
+
|
|
33
|
+
expect(component.disconnect).toHaveBeenCalled()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('should disconnect compositions', async () => {
|
|
37
|
+
const paths = [generate(), generate()]
|
|
38
|
+
|
|
39
|
+
await stage.composition(paths)
|
|
40
|
+
await stage.shutdown()
|
|
41
|
+
|
|
42
|
+
const composition = await mock.boot.composition.mock.results[0].value
|
|
43
|
+
|
|
44
|
+
expect(composition.disconnect).toHaveBeenCalled()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('should disconnect remotes', async () => {
|
|
48
|
+
const id = generate() + '.' + generate()
|
|
49
|
+
|
|
50
|
+
const remote = await stage.remote(id)
|
|
51
|
+
await stage.shutdown()
|
|
52
|
+
|
|
53
|
+
expect(remote.disconnect).toHaveBeenCalled()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('should reset state', async () => {
|
|
57
|
+
await stage.shutdown()
|
|
58
|
+
|
|
59
|
+
expect(state.reset).toHaveBeenCalled()
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('should reset binding', async () => {
|
|
63
|
+
await stage.shutdown()
|
|
64
|
+
|
|
65
|
+
expect(binding.reset).toHaveBeenCalled()
|
|
66
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { state } = require('../src/state')
|
|
4
|
+
|
|
5
|
+
it('should be', () => {
|
|
6
|
+
expect(state).toBeDefined()
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('should reset', () => {
|
|
10
|
+
const component = /** @type {toa.core.Component} */ 1
|
|
11
|
+
const composition = /** @type {toa.core.Connector} */ 2
|
|
12
|
+
const remote = /** @type {toa.core.Component} */ 3
|
|
13
|
+
|
|
14
|
+
expect(state.components.length).toStrictEqual(0)
|
|
15
|
+
expect(state.compositions.length).toStrictEqual(0)
|
|
16
|
+
expect(state.remotes.length).toStrictEqual(0)
|
|
17
|
+
|
|
18
|
+
state.components.push(component)
|
|
19
|
+
state.compositions.push(composition)
|
|
20
|
+
state.remotes.push(remote)
|
|
21
|
+
|
|
22
|
+
state.reset()
|
|
23
|
+
|
|
24
|
+
expect(state.components.length).toStrictEqual(0)
|
|
25
|
+
expect(state.compositions.length).toStrictEqual(0)
|
|
26
|
+
expect(state.remotes.length).toStrictEqual(0)
|
|
27
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as _core from '@toa.io/core/types'
|
|
2
|
+
|
|
3
|
+
declare namespace toa.stage.binding {
|
|
4
|
+
|
|
5
|
+
type Callback = (message: Object) => Promise<void>
|
|
6
|
+
type Call = (request: Object) => Promise<Object>
|
|
7
|
+
|
|
8
|
+
interface Binding {
|
|
9
|
+
subscribe(label: string, callback: Callback): Promise<void>
|
|
10
|
+
|
|
11
|
+
emit(label: string, message: Object): Promise<undefined>
|
|
12
|
+
|
|
13
|
+
reply(label, call: Call): Promise<Object>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type Factory = _core.bindings.Factory
|
|
19
|
+
export const binding: toa.stage.binding.Binding
|
|
20
|
+
export const properties: _core.bindings.Properties
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as _core from '@toa.io/core/types'
|
|
2
|
+
import * as _norm from '@toa.io/norm/types'
|
|
3
|
+
|
|
4
|
+
declare namespace toa.stage {
|
|
5
|
+
type Manifest = (path: string) => Promise<_norm.Component>
|
|
6
|
+
type Component = (path: string) => Promise<_core.Component>
|
|
7
|
+
type Composition = (paths: string[]) => Promise<void>
|
|
8
|
+
type Remote = (id: string) => Promise<_core.Component>
|
|
9
|
+
type Shutdown = () => Promise<void>
|
|
10
|
+
|
|
11
|
+
interface Stage {
|
|
12
|
+
manifest: toa.stage.Manifest
|
|
13
|
+
component: toa.stage.Component
|
|
14
|
+
composition: toa.stage.Composition
|
|
15
|
+
remote: toa.stage.Remote
|
|
16
|
+
shutdown: toa.stage.Shutdown
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type Stage = toa.stage.Stage
|
|
21
|
+
|
|
22
|
+
export const manifest: toa.stage.Manifest
|
|
23
|
+
export const component: toa.stage.Component
|
|
24
|
+
export const composition: toa.stage.Composition
|
|
25
|
+
export const remote: toa.stage.Remote
|
|
26
|
+
export const shutdown: toa.stage.Shutdown
|
|
27
|
+
|
|
28
|
+
export * as binding from './binding'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as _core from '@toa.io/core/types'
|
|
2
|
+
|
|
3
|
+
declare namespace toa.stage {
|
|
4
|
+
|
|
5
|
+
type State = {
|
|
6
|
+
reset: () => void
|
|
7
|
+
components: _core.Component[]
|
|
8
|
+
compositions: _core.Connector[]
|
|
9
|
+
remotes: _core.Component[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type State = toa.stage.State
|