@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.
Files changed (129) hide show
  1. package/example/components/echo/beacon/manifest.toa.yaml +9 -0
  2. package/example/components/echo/beacon/operations/signal.js +7 -0
  3. package/example/components/echo/beacon/samples/signal.yaml +7 -0
  4. package/example/components/math/calculations/manifest.toa.yaml +16 -0
  5. package/example/components/math/calculations/operations/add.js +7 -0
  6. package/example/components/math/calculations/operations/increment.js +15 -0
  7. package/example/components/math/calculations/samples/add.yaml +11 -0
  8. package/example/components/math/calculations/samples/increment.yaml +30 -0
  9. package/example/components/math/proxy/manifest.toa.yaml +11 -0
  10. package/example/components/math/proxy/operations/add.js +10 -0
  11. package/example/components/math/proxy/samples/add.yaml +11 -0
  12. package/example/components/tea/pots/manifest.toa.yaml +28 -0
  13. package/example/components/tea/pots/operations/same.js +13 -0
  14. package/example/components/tea/pots/receivers/store.orders.created.js +8 -0
  15. package/example/components/tea/pots/samples/messages/store.orders.created.yaml +37 -0
  16. package/example/components/tea/pots/samples/same.yaml +8 -0
  17. package/example/components/tea/pots/samples/transit.yaml +43 -0
  18. package/example/context.toa.yaml +3 -0
  19. package/example/samples/math.proxy.add.yaml +5 -0
  20. package/example/samples/messages/store.orders.created.yaml +8 -0
  21. package/example/stage/call.test.js +39 -0
  22. package/example/stage/events.test.js +48 -0
  23. package/example/stage/invoke.test.js +29 -0
  24. package/package.json +36 -0
  25. package/readme.md +9 -0
  26. package/samples/docs/sampling-dark.jpg +0 -0
  27. package/samples/docs/sampling-light.jpg +0 -0
  28. package/samples/notes.md +12 -0
  29. package/samples/package.json +5 -0
  30. package/samples/readme.md +66 -0
  31. package/samples/src/.replay/.suite/component.js +25 -0
  32. package/samples/src/.replay/.suite/index.js +7 -0
  33. package/samples/src/.replay/.suite/messages.js +39 -0
  34. package/samples/src/.replay/.suite/operation.js +28 -0
  35. package/samples/src/.replay/.suite/operations.js +18 -0
  36. package/samples/src/.replay/.suite/translate/.message/index.js +5 -0
  37. package/samples/src/.replay/.suite/translate/.message/request.js +31 -0
  38. package/samples/src/.replay/.suite/translate/.operation/calls.js +49 -0
  39. package/samples/src/.replay/.suite/translate/.operation/cleanup.js +16 -0
  40. package/samples/src/.replay/.suite/translate/.operation/events.js +16 -0
  41. package/samples/src/.replay/.suite/translate/.operation/index.js +11 -0
  42. package/samples/src/.replay/.suite/translate/.operation/prepare.js +14 -0
  43. package/samples/src/.replay/.suite/translate/.operation/specials/configuration.js +26 -0
  44. package/samples/src/.replay/.suite/translate/.operation/specials/index.js +5 -0
  45. package/samples/src/.replay/.suite/translate/index.js +7 -0
  46. package/samples/src/.replay/.suite/translate/message.js +26 -0
  47. package/samples/src/.replay/.suite/translate/operation.js +47 -0
  48. package/samples/src/.replay/.suite/translate/schemas/index.js +7 -0
  49. package/samples/src/.replay/.suite/translate/schemas/message.cos.yaml +10 -0
  50. package/samples/src/.replay/.suite/translate/schemas/operation.cos.yaml +23 -0
  51. package/samples/src/.replay/index.js +5 -0
  52. package/samples/src/.replay/suite.js +22 -0
  53. package/samples/src/.replay/test.js +17 -0
  54. package/samples/src/components.js +13 -0
  55. package/samples/src/context.js +18 -0
  56. package/samples/src/index.js +9 -0
  57. package/samples/src/replay.js +17 -0
  58. package/samples/src/suite/.read/index.js +7 -0
  59. package/samples/src/suite/.read/messages.js +35 -0
  60. package/samples/src/suite/.read/operations.js +45 -0
  61. package/samples/src/suite/.read/parse.js +24 -0
  62. package/samples/src/suite/components.js +28 -0
  63. package/samples/src/suite/context.js +19 -0
  64. package/samples/src/suite/index.js +7 -0
  65. package/samples/test/components.test.js +39 -0
  66. package/samples/test/context/components/ok/manifest.toa.yaml +2 -0
  67. package/samples/test/context/components/ok/samples/do.yaml +11 -0
  68. package/samples/test/context/components/ok/samples/dummies.dummy.do.yaml +11 -0
  69. package/samples/test/context/components/ok/samples/dummies.dummy.undo.yaml +7 -0
  70. package/samples/test/context/components/ok/samples/messages/somewhere.something.happened.yaml +6 -0
  71. package/samples/test/context/context.toa.yaml +3 -0
  72. package/samples/test/context/samples/dummies.dummy.observe.yaml +6 -0
  73. package/samples/test/context/samples/dummies.dummy.transit.yaml +10 -0
  74. package/samples/test/context/samples/messages/somewhere.something.happened.yaml +6 -0
  75. package/samples/test/context.fixtures.js +8 -0
  76. package/samples/test/context.test.js +78 -0
  77. package/samples/test/replay.fixtures.js +72 -0
  78. package/samples/test/replay.mock.js +7 -0
  79. package/samples/test/replay.test.js +116 -0
  80. package/samples/test/replay.translate.message.fixtures.js +24 -0
  81. package/samples/test/replay.translate.message.test.js +123 -0
  82. package/samples/test/replay.translate.mock.js +17 -0
  83. package/samples/test/replay.translate.operation.fixtures.js +107 -0
  84. package/samples/test/replay.translate.operation.test.js +68 -0
  85. package/samples/test/stage.mock.js +34 -0
  86. package/samples/test/suite.components.test.js +85 -0
  87. package/samples/test/suite.context.test.js +79 -0
  88. package/samples/test/suite.mock.js +10 -0
  89. package/samples/types/index.d.ts +8 -0
  90. package/samples/types/message.d.ts +24 -0
  91. package/samples/types/operation.d.ts +36 -0
  92. package/samples/types/replay.d.ts +13 -0
  93. package/samples/types/suite.d.ts +19 -0
  94. package/stage/package.json +5 -0
  95. package/stage/readme.md +41 -0
  96. package/stage/src/binding/binding.js +49 -0
  97. package/stage/src/binding/consumer.js +30 -0
  98. package/stage/src/binding/emitter.js +26 -0
  99. package/stage/src/binding/factory.js +49 -0
  100. package/stage/src/binding/index.js +10 -0
  101. package/stage/src/binding/label.js +12 -0
  102. package/stage/src/binding/producer.js +43 -0
  103. package/stage/src/binding/receiver.js +35 -0
  104. package/stage/src/component.js +18 -0
  105. package/stage/src/composition.js +19 -0
  106. package/stage/src/index.js +18 -0
  107. package/stage/src/manifest.js +12 -0
  108. package/stage/src/remote.js +22 -0
  109. package/stage/src/shutdown.js +19 -0
  110. package/stage/src/state.js +17 -0
  111. package/stage/test/binding/binding.test.js +15 -0
  112. package/stage/test/binding/consumer.test.js +52 -0
  113. package/stage/test/binding/emitter.test.js +54 -0
  114. package/stage/test/binding/producer.fixtures.js +10 -0
  115. package/stage/test/binding/producer.test.js +49 -0
  116. package/stage/test/binding/receiver.fixtures.js +7 -0
  117. package/stage/test/binding/receiver.test.js +54 -0
  118. package/stage/test/binding.mock.js +8 -0
  119. package/stage/test/boot.mock.js +16 -0
  120. package/stage/test/component.test.js +25 -0
  121. package/stage/test/composition.test.js +38 -0
  122. package/stage/test/manifest.test.js +24 -0
  123. package/stage/test/remote.test.js +32 -0
  124. package/stage/test/shutdown.test.js +66 -0
  125. package/stage/test/state.mock.js +8 -0
  126. package/stage/test/state.test.js +27 -0
  127. package/stage/types/binding.d.ts +20 -0
  128. package/stage/types/index.d.ts +28 -0
  129. package/stage/types/state.d.ts +14 -0
@@ -0,0 +1,34 @@
1
+ // noinspection JSCheckFunctionSignatures
2
+
3
+ 'use strict'
4
+
5
+ const { generate } = require('randomstring')
6
+ const { Locator } = require('@toa.io/core')
7
+
8
+ const locator = () => {
9
+ const name = generate()
10
+ const namespace = generate()
11
+
12
+ return new Locator(name, namespace)
13
+ }
14
+
15
+ // stage
16
+ const manifest = jest.fn(async (path) => ({ path, locator: locator() }))
17
+ const composition = jest.fn()
18
+ const shutdown = jest.fn()
19
+
20
+ const remote = jest.fn(async (id) => {
21
+ const [namespace, name] = id.split('.')
22
+ const locator = new Locator(name, namespace)
23
+ const invoke = jest.fn(async (operation, request) => request.reply)
24
+ const disconnect = jest.fn(async () => undefined)
25
+
26
+ return { locator, invoke, disconnect }
27
+ })
28
+
29
+ const emit = jest.fn()
30
+ const binding = { binding: { emit } }
31
+
32
+ const stage = { manifest, composition, remote, shutdown, binding }
33
+
34
+ exports.stage = stage
@@ -0,0 +1,85 @@
1
+ 'use strict'
2
+
3
+ const { resolve } = require('node:path')
4
+ const yaml = require('@toa.io/yaml')
5
+
6
+ const { components } = require('../src/suite')
7
+
8
+ it('should be', () => {
9
+ expect(components).toBeDefined()
10
+ })
11
+
12
+ const root = resolve(__dirname, 'context/components/ok')
13
+ const paths = [root]
14
+ const component = 'dummies.dummy'
15
+
16
+ /** @type {toa.samples.Suite} */
17
+ let suite
18
+
19
+ beforeAll(async () => {
20
+ suite = await components(paths)
21
+ })
22
+
23
+ it('should return object', () => {
24
+ expect(typeof suite).toStrictEqual('object')
25
+ })
26
+
27
+ it('should set title', async () => {
28
+ expect(suite.title).toStrictEqual('Component samples')
29
+ })
30
+
31
+ it('should define suite as autonomous', async () => {
32
+ expect(suite.autonomous).toStrictEqual(true)
33
+ })
34
+
35
+ it('should load component samples', async () => {
36
+ const expected = await operations()
37
+
38
+ expect(Object.keys(suite.operations)).toStrictEqual([component])
39
+
40
+ const set = suite.operations[component]
41
+
42
+ expect(Object.keys(set)).toStrictEqual(['do', 'undo'])
43
+
44
+ expect(set.do).toStrictEqual(expected.do)
45
+ expect(set.undo).toStrictEqual(expected.undo)
46
+ })
47
+
48
+ it('should load message samples', async () => {
49
+ const expected = await messages()
50
+
51
+ expect(suite.messages).toStrictEqual(expected)
52
+ })
53
+
54
+ /**
55
+ * @returns {Promise<toa.samples.operations.Set>}
56
+ */
57
+ const operations = async () => {
58
+ const path = resolve(root, 'samples')
59
+
60
+ /** @type {toa.samples.Operation[]} */
61
+ const do1 = (await yaml.load.all(resolve(path, 'do.yaml')))
62
+
63
+ /** @type {toa.samples.Operation[]} */
64
+ const do2 = (await yaml.load.all(resolve(path, 'dummies.dummy.do.yaml')))
65
+
66
+ /** @type {toa.samples.Operation[]} */
67
+ const undo = (await yaml.load.all(resolve(path, 'dummies.dummy.undo.yaml')))
68
+
69
+ return {
70
+ do: [...do1, ...do2], undo
71
+ }
72
+ }
73
+
74
+ /**
75
+ *
76
+ * @returns {Promise<toa.samples.messages.Set>}
77
+ */
78
+ const messages = async () => {
79
+ const label = 'somewhere.something.happened'
80
+ const file = resolve(root, 'samples/messages', label + '.yaml')
81
+ const declarations = await yaml.load.all(file)
82
+ const messages = declarations.map((sample) => ({ component, ...sample }))
83
+
84
+ return { [label]: messages }
85
+ }
@@ -0,0 +1,79 @@
1
+ 'use strict'
2
+
3
+ const { join } = require('node:path')
4
+ const yaml = require('@toa.io/yaml')
5
+
6
+ const { context } = require('../src/suite')
7
+
8
+ it('should be', async () => {
9
+ expect(context).toBeDefined()
10
+ })
11
+
12
+ const root = join(__dirname, 'context')
13
+
14
+ /** @type {toa.samples.Suite} */
15
+ let suite
16
+
17
+ beforeAll(async () => {
18
+ suite = await context(root)
19
+ })
20
+
21
+ it('should return object', async () => {
22
+ expect(typeof suite).toStrictEqual('object')
23
+ })
24
+
25
+ it('should set title', async () => {
26
+ expect(suite.title).toStrictEqual('Integration samples')
27
+ })
28
+
29
+ it('should define suite as non-autonomous', async () => {
30
+ expect(suite.autonomous).toStrictEqual(false)
31
+ })
32
+
33
+ it('should load operation samples', async () => {
34
+ const expected = await operations()
35
+
36
+ expect(suite.operations).toStrictEqual(expected)
37
+ })
38
+
39
+ it('should load message samples', async () => {
40
+ const expected = await messages()
41
+
42
+ expect(suite.messages).toStrictEqual(expected)
43
+ })
44
+
45
+ /**
46
+ * @returns {Promise<toa.samples.suite.Operations>}
47
+ */
48
+ const operations = async () => {
49
+ const path = join(root, 'samples')
50
+ const component = 'dummies.dummy'
51
+ const endpoints = ['transit', 'observe']
52
+
53
+ /** @type {toa.samples.suite.Operations} */
54
+ const operations = {}
55
+
56
+ /** @type {toa.samples.operations.Set} */
57
+ const set = operations[component] = {}
58
+
59
+ for (const endpoint of endpoints) {
60
+ const filename = component + '.' + endpoint + '.yaml'
61
+ const filepath = join(path, filename)
62
+
63
+ set[endpoint] = /** @type {toa.samples.Operation[]} */ await yaml.load.all(filepath)
64
+ }
65
+
66
+ return operations
67
+ }
68
+
69
+ /**
70
+ * @returns {Promise<toa.samples.messages.Set>}
71
+ */
72
+ const messages = async () => {
73
+ const label = 'somewhere.something.happened'
74
+ const file = label + '.yaml'
75
+ const path = join(root, 'samples/messages', file)
76
+ const samples = /** @type {toa.samples.Message[]} */ await yaml.load.all(path)
77
+
78
+ return { [label]: samples }
79
+ }
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+
3
+ const { generate } = require('randomstring')
4
+
5
+ const suite = {
6
+ components: jest.fn(async () => generate()),
7
+ context: jest.fn(async () => generate())
8
+ }
9
+
10
+ exports.suite = suite
@@ -0,0 +1,8 @@
1
+ import * as _replay from './replay'
2
+
3
+ export { Operation } from './operation'
4
+ export { Message } from './message'
5
+
6
+ export const context: _replay.context
7
+ export const components: _replay.components
8
+ export const replay: _replay.replay
@@ -0,0 +1,24 @@
1
+ import type * as _core from '@toa.io/core/types'
2
+ import type * as _operation from './operation'
3
+
4
+ declare namespace toa.samples {
5
+
6
+ namespace messages {
7
+
8
+ type Set = Record<string, Message[]>
9
+
10
+ }
11
+
12
+ type Message = {
13
+ title?: string
14
+ component: string
15
+ payload: Object
16
+ input?: any
17
+ query?: _core.Query
18
+ request?: _operation.Operation | null
19
+ }
20
+
21
+ }
22
+
23
+ export type Message = toa.samples.Message
24
+ export type Set = toa.samples.messages.Set
@@ -0,0 +1,36 @@
1
+ import * as _core from '@toa.io/core/types'
2
+ import * as _sampling from '@toa.io/extensions.sampling'
3
+
4
+ declare namespace toa.samples {
5
+
6
+ namespace operations {
7
+
8
+ type Call = {
9
+ input?: any
10
+ output?: any
11
+ }
12
+
13
+ type Calls = Record<string, Call[]>
14
+
15
+ type Events = Record<string, Object>
16
+
17
+ type Set = Record<string, Operation[]>
18
+
19
+ }
20
+
21
+ type Operation = {
22
+ title?: string
23
+ input?: any
24
+ output?: any
25
+ current?: _core.storages.Record
26
+ next?: _core.storages.Record
27
+ remote?: operations.Calls
28
+ local?: operations.Calls
29
+ events?: operations.Events
30
+ extensions?: _sampling.request.Extensions
31
+ }
32
+
33
+ }
34
+
35
+ export type Operation = toa.samples.Operation
36
+ export type Set = toa.samples.operations.Set
@@ -0,0 +1,13 @@
1
+ import * as _suite from "./suite";
2
+
3
+ declare namespace toa.samples.replay {
4
+
5
+ type components = (paths: string[]) => Promise<boolean>
6
+ type context = (path: string) => Promise<boolean>
7
+ type replay = (suite: _suite.Suite, paths: string[]) => Promise<boolean>
8
+
9
+ }
10
+
11
+ export type context = toa.samples.replay.context
12
+ export type components = toa.samples.replay.components
13
+ export type replay = toa.samples.replay.replay
@@ -0,0 +1,19 @@
1
+ import * as _operations from './operation'
2
+ import * as _messages from './message'
3
+
4
+ declare namespace toa.samples {
5
+
6
+ namespace suite {
7
+ type Operations = Record<string, _operations.Set>
8
+ }
9
+
10
+ type Suite = {
11
+ title: string
12
+ autonomous: boolean
13
+ operations?: suite.Operations
14
+ messages?: _messages.Set
15
+ }
16
+
17
+ }
18
+
19
+ export type Suite = toa.samples.Suite
@@ -0,0 +1,5 @@
1
+ {
2
+ "private": true,
3
+ "main": "src/index.js",
4
+ "types": "types/index.d.ts"
5
+ }
@@ -0,0 +1,41 @@
1
+ # Toa integration tests framework
2
+
3
+ ## TL;DR
4
+
5
+ ```javascript
6
+ const stage = require('@toa.io/userland/stage')
7
+
8
+ const component = await stage.component('dummies.dummy')
9
+ const reply = await component.invoke('do', { input: 'foo' })
10
+
11
+ await stage.shutdown()
12
+ ```
13
+
14
+ See [examples](../example/stage).
15
+
16
+ ## Component
17
+
18
+ `async component(path: string): toa.core.Component`
19
+
20
+ Boot the component.
21
+
22
+ > Components consuming events must be able to discover event sources, that is, either they must be
23
+ > booted after event sources are composed or within the same composition.
24
+
25
+ ## Composition
26
+
27
+ `async composition(paths: string[]): void`
28
+
29
+ Boot the composition.
30
+
31
+ ## Remote
32
+
33
+ `async remote(paths: string[]): toa.core.Component`
34
+
35
+ Connect the remote.
36
+
37
+ ## Shutdown
38
+
39
+ `async sutdown(): void`
40
+
41
+ Shutdown all components, compositions and services.
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * @implements {toa.stage.binding.Binding}
5
+ */
6
+ class Binding {
7
+ /** @type {Record<string, function[]>} */
8
+ #subs = {}
9
+
10
+ /** @type {Record<string, function>} */
11
+ #calls = {}
12
+
13
+ async subscribe (label, callback) {
14
+ if (this.#subs[label] === undefined) this.#subs[label] = []
15
+
16
+ this.#subs[label].push(callback)
17
+ }
18
+
19
+ async emit (label, message) {
20
+ const callbacks = this.#subs[label]
21
+
22
+ if (callbacks === undefined) return undefined
23
+
24
+ const promises = callbacks.map((callback) => callback(message))
25
+
26
+ await Promise.all(promises)
27
+ }
28
+
29
+ async reply (label, produce) {
30
+ if (this.#calls[label] !== undefined) throw new Error(`Label '${label}' is already bound`)
31
+
32
+ this.#calls[label] = produce
33
+ }
34
+
35
+ async request (label, request) {
36
+ if (this.#calls[label] === undefined) throw new Error(`Label '${label}' is not bound`)
37
+
38
+ return this.#calls[label](request)
39
+ }
40
+
41
+ reset () {
42
+ this.#subs = {}
43
+ this.#calls = {}
44
+ }
45
+ }
46
+
47
+ const binding = new Binding()
48
+
49
+ exports.binding = binding
@@ -0,0 +1,30 @@
1
+ 'use strict'
2
+
3
+ const { Connector } = require('@toa.io/core')
4
+
5
+ const { binding } = require('./binding')
6
+ const { label } = require('./label')
7
+
8
+ /**
9
+ * @implements {toa.core.bindings.Consumer}
10
+ */
11
+ class Consumer extends Connector {
12
+ /** @type {string} */
13
+ #label
14
+
15
+ /**
16
+ * @param {toa.core.Locator} locator
17
+ * @param {string} endpoint
18
+ */
19
+ constructor (locator, endpoint) {
20
+ super()
21
+
22
+ this.#label = label(locator, endpoint)
23
+ }
24
+
25
+ async request (request) {
26
+ return binding.request(this.#label, request)
27
+ }
28
+ }
29
+
30
+ exports.Consumer = Consumer
@@ -0,0 +1,26 @@
1
+ 'use strict'
2
+
3
+ const { Connector } = require('@toa.io/core')
4
+
5
+ const { binding } = require('./binding')
6
+ const { label } = require('./label')
7
+
8
+ /**
9
+ * @implements {toa.core.bindings.Emitter}
10
+ */
11
+ class Emitter extends Connector {
12
+ /** @type {string} */
13
+ #label
14
+
15
+ constructor (locator, endpoint) {
16
+ super()
17
+
18
+ this.#label = label(locator, endpoint)
19
+ }
20
+
21
+ async emit (message) {
22
+ return binding.emit(this.#label, message)
23
+ }
24
+ }
25
+
26
+ exports.Emitter = Emitter
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ const { Emitter } = require('./emitter')
4
+ const { Receiver } = require('./receiver')
5
+ const { Consumer } = require('./consumer')
6
+ const { Producer } = require('./producer')
7
+
8
+ class Factory {
9
+ /**
10
+ * @param {toa.core.Locator} locator
11
+ * @param {string} label
12
+ * @param {string} id
13
+ * @param {toa.core.Receiver} receiver
14
+ * @returns {toa.core.Connector}
15
+ */
16
+ receiver (locator, label, id, receiver) {
17
+ return new Receiver(locator, label, receiver)
18
+ }
19
+
20
+ /**
21
+ * @param {toa.core.Locator} locator
22
+ * @param {string} label
23
+ * @returns {toa.core.bindings.Emitter}
24
+ */
25
+ emitter (locator, label) {
26
+ return new Emitter(locator, label)
27
+ }
28
+
29
+ /**
30
+ * @param {toa.core.Locator} locator
31
+ * @param {string} endpoint
32
+ * @returns {toa.core.bindings.Consumer}
33
+ */
34
+ consumer (locator, endpoint) {
35
+ return new Consumer(locator, endpoint)
36
+ }
37
+
38
+ /**
39
+ * @param {toa.core.Locator} locator
40
+ * @param {string[]} endpoints
41
+ * @param {toa.core.Component} component
42
+ * @returns {toa.core.Connector}
43
+ */
44
+ producer (locator, endpoints, component) {
45
+ return new Producer(locator, endpoints, component)
46
+ }
47
+ }
48
+
49
+ exports.Factory = Factory
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+
3
+ const { Factory } = require('./factory')
4
+ const { binding } = require('./binding')
5
+
6
+ const properties = { async: true }
7
+
8
+ exports.properties = properties
9
+ exports.Factory = Factory
10
+ exports.binding = binding
@@ -0,0 +1,12 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * @param {toa.core.Locator} locator
5
+ * @param {string} endpoint
6
+ * @returns {string}
7
+ */
8
+ const label = (locator, endpoint) => {
9
+ return locator.id + '.' + endpoint
10
+ }
11
+
12
+ exports.label = label
@@ -0,0 +1,43 @@
1
+ 'use strict'
2
+
3
+ const { Connector } = require('@toa.io/core')
4
+
5
+ const { binding } = require('./binding')
6
+ const { label } = require('./label')
7
+
8
+ /**
9
+ * @implements {toa.core.Connector}
10
+ */
11
+ class Producer extends Connector {
12
+ /** @type {toa.core.Locator} */
13
+ #locator
14
+
15
+ /** @type {string[]} */
16
+ #endpoints
17
+
18
+ /** @type {toa.core.Component} */
19
+ #component
20
+
21
+ /**
22
+ * @param {toa.core.Locator} locator
23
+ * @param {string[]} endpoints
24
+ * @param {toa.core.Component} component
25
+ */
26
+ constructor (locator, endpoints, component) {
27
+ super()
28
+
29
+ this.#locator = locator
30
+ this.#endpoints = endpoints
31
+ this.#component = component
32
+ }
33
+
34
+ async connection () {
35
+ for (const endpoint of this.#endpoints) {
36
+ const command = label(this.#locator, endpoint)
37
+
38
+ await binding.reply(command, (request) => this.#component.invoke(endpoint, request))
39
+ }
40
+ }
41
+ }
42
+
43
+ exports.Producer = Producer
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ const { Connector } = require('@toa.io/core')
4
+
5
+ const { binding } = require('./binding')
6
+ const { label } = require('./label')
7
+
8
+ /**
9
+ * @implements {toa.core.Connector}
10
+ */
11
+ class Receiver extends Connector {
12
+ /** @type {string} */
13
+ #label
14
+
15
+ /** @type {toa.core.Receiver} */
16
+ #receiver
17
+
18
+ /**
19
+ * @param {toa.core.Locator} locator
20
+ * @param {string} endpoint
21
+ * @param {toa.core.Receiver} receiver
22
+ */
23
+ constructor (locator, endpoint, receiver) {
24
+ super()
25
+
26
+ this.#label = label(locator, endpoint)
27
+ this.#receiver = receiver
28
+ }
29
+
30
+ async connection () {
31
+ await binding.subscribe(this.#label, (message) => this.#receiver.receive(message))
32
+ }
33
+ }
34
+
35
+ exports.Receiver = Receiver
@@ -0,0 +1,18 @@
1
+ 'use strict'
2
+
3
+ const boot = require('@toa.io/boot')
4
+ const { state } = require('./state')
5
+
6
+ /** @type {toa.stage.Component} */
7
+ const component = async (path) => {
8
+ const manifest = await boot.manifest(path)
9
+ const component = await boot.component(manifest)
10
+
11
+ await component.connect()
12
+
13
+ state.components.push(component)
14
+
15
+ return component
16
+ }
17
+
18
+ exports.component = component
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const boot = require('@toa.io/boot')
4
+ const { state } = require('./state')
5
+
6
+ const binding = require.resolve('./binding')
7
+
8
+ /** @type {toa.stage.Composition} */
9
+ const composition = async (paths) => {
10
+ /** @type {toa.boot.composition.Options} */
11
+ const options = { bindings: [binding] }
12
+ const composition = await boot.composition(paths, options)
13
+
14
+ await composition.connect()
15
+
16
+ state.compositions.push(composition)
17
+ }
18
+
19
+ exports.composition = composition
@@ -0,0 +1,18 @@
1
+ 'use strict'
2
+
3
+ const { manifest } = require('./manifest')
4
+ const { component } = require('./component')
5
+ const { composition } = require('./composition')
6
+ const { remote } = require('./remote')
7
+ const { shutdown } = require('./shutdown')
8
+ const binding = require('./binding')
9
+
10
+ // staging always runs on local deployment environment
11
+ process.env.TOA_ENV = 'local'
12
+
13
+ exports.manifest = manifest
14
+ exports.component = component
15
+ exports.composition = composition
16
+ exports.remote = remote
17
+ exports.shutdown = shutdown
18
+ exports.binding = binding