@toa.io/boot 1.0.0-alpha.31 → 1.0.0-alpha.311
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/CHANGELOG.md +224 -0
- package/package.json +11 -8
- package/src/atom.js +41 -0
- package/src/atomicity.js +11 -0
- package/src/bindings/broadcast.js +3 -6
- package/src/bindings/constants.js +1 -3
- package/src/bindings/consume.js +8 -8
- package/src/bindings/emit.js +3 -6
- package/src/bindings/factory.js +5 -9
- package/src/bindings/inbound.js +11 -0
- package/src/bindings/index.js +7 -13
- package/src/bindings/outbound.js +10 -0
- package/src/bindings/produce.js +40 -18
- package/src/bindings/receive.js +3 -6
- package/src/bridge.js +22 -16
- package/src/call.js +22 -9
- package/src/cascade.js +16 -10
- package/src/component.js +94 -32
- package/src/composition.js +106 -15
- package/src/context.js +7 -8
- package/src/contract.js +11 -12
- package/src/emission.js +21 -14
- package/src/env.js +19 -12
- package/src/events.js +27 -0
- package/src/extensions/aspects.js +4 -8
- package/src/extensions/component.js +4 -8
- package/src/extensions/context.js +4 -8
- package/src/extensions/destinations.js +27 -0
- package/src/extensions/emitter.js +7 -9
- package/src/extensions/index.js +10 -19
- package/src/extensions/instances.js +2 -4
- package/src/extensions/load.js +7 -7
- package/src/extensions/manage.js +15 -0
- package/src/extensions/receiver.js +5 -9
- package/src/extensions/resolve.js +36 -11
- package/src/extensions/storage.js +6 -9
- package/src/extensions/tenants.js +5 -9
- package/src/guards.js +20 -0
- package/src/host.js +29 -0
- package/src/inbox.js +10 -0
- package/src/index.js +27 -34
- package/src/manifest.js +78 -36
- package/src/manifest.test.js +85 -8
- package/src/map.js +98 -0
- package/src/operation.js +25 -13
- package/src/outbox.js +22 -0
- package/src/rc.js +5 -0
- package/src/receivers.js +53 -23
- package/src/remote.js +37 -22
- package/src/span.js +19 -0
- package/src/storage.js +50 -16
- package/src/storage.test.js +57 -0
- package/src/workload.js +281 -0
- package/src/workload.test.js +321 -0
- package/types/bindings.d.ts +6 -2
- package/types/index.d.ts +62 -10
- package/types/manifest.d.ts +5 -4
- package/src/discovery.js +0 -43
- package/src/exposition.js +0 -17
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
# [1.0.0-alpha.311](https://github.com/toa-io/toa/compare/v1.0.0-alpha.310...v1.0.0-alpha.311) (2026-09-17)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* read the scope of a process once, as it boots ([0d65de5](https://github.com/toa-io/toa/commit/0d65de58ffc655ff872b8e66f95c5609ada3370a))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# [1.0.0-alpha.310](https://github.com/toa-io/toa/compare/v1.0.0-alpha.309...v1.0.0-alpha.310) (2026-09-16)
|
|
14
|
+
|
|
15
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# [1.0.0-alpha.309](https://github.com/toa-io/toa/compare/v1.0.0-alpha.308...v1.0.0-alpha.309) (2026-09-16)
|
|
22
|
+
|
|
23
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# [1.0.0-alpha.308](https://github.com/toa-io/toa/compare/v1.0.0-alpha.307...v1.0.0-alpha.308) (2026-09-15)
|
|
30
|
+
|
|
31
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# [1.0.0-alpha.307](https://github.com/toa-io/toa/compare/v1.0.0-alpha.306...v1.0.0-alpha.307) (2026-09-15)
|
|
38
|
+
|
|
39
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# [1.0.0-alpha.306](https://github.com/toa-io/toa/compare/v1.0.0-alpha.305...v1.0.0-alpha.306) (2026-09-14)
|
|
46
|
+
|
|
47
|
+
* refactor(core)!: name the quiesce hooks pause and unpause ([6e4e5f5](https://github.com/toa-io/toa/commit/6e4e5f55d43f03ea95ca8bbdaae57b949564dfa2))
|
|
48
|
+
* feat(boot)!: a process can be halted and come back ([7196fa5](https://github.com/toa-io/toa/commit/7196fa51a9c882e84c3767a4fdd329fd2df319f5))
|
|
49
|
+
|
|
50
|
+
### Bug Fixes
|
|
51
|
+
|
|
52
|
+
* **boot:** declare what a workload does with a quiesce ([0e1521d](https://github.com/toa-io/toa/commit/0e1521d7abae3a3860a29978d267927d814c1d3a))
|
|
53
|
+
* **boot:** keep a halted process alive until it comes back ([3d3cc23](https://github.com/toa-io/toa/commit/3d3cc23835f836f9f98b1d9a448090a2b0d473c8))
|
|
54
|
+
|
|
55
|
+
### Features
|
|
56
|
+
|
|
57
|
+
* **boot:** let a process go quiet and be let go again ([0fc3e66](https://github.com/toa-io/toa/commit/0fc3e66f217ab45e85f70271ab0768232b3fa088))
|
|
58
|
+
* **boot:** quiet a tree before taking it down ([7a339ca](https://github.com/toa-io/toa/commit/7a339caea4499509b55daf91061fc9836c0f6e68))
|
|
59
|
+
* **bridges.node:** let a component stop what it started and start it again ([d10d5d1](https://github.com/toa-io/toa/commit/d10d5d16fcd181e717d9d2cef4c7814ae8f2a93f))
|
|
60
|
+
|
|
61
|
+
### BREAKING CHANGES
|
|
62
|
+
|
|
63
|
+
* `Host.halt` is `Host.stop`.
|
|
64
|
+
* `Host` gains `gate` and `halt`, and `Factory.service` may answer a gate. An
|
|
65
|
+
extension that gates nothing keeps its connections through a halt.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# [1.0.0-alpha.305](https://github.com/toa-io/toa/compare/v1.0.0-alpha.304...v1.0.0-alpha.305) (2026-09-13)
|
|
69
|
+
|
|
70
|
+
### Features
|
|
71
|
+
|
|
72
|
+
* **core:** refuse a call that writes, made under a request that only reads ([92951d0](https://github.com/toa-io/toa/commit/92951d0f7b95bd5b838097dd6a42db5586968d0b))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# [1.0.0-alpha.304](https://github.com/toa-io/toa/compare/v1.0.0-alpha.303...v1.0.0-alpha.304) (2026-09-13)
|
|
76
|
+
|
|
77
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# [1.0.0-alpha.303](https://github.com/toa-io/toa/compare/v1.0.0-alpha.302...v1.0.0-alpha.303) (2026-09-12)
|
|
84
|
+
|
|
85
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# [1.0.0-alpha.302](https://github.com/toa-io/toa/compare/v1.0.0-alpha.301...v1.0.0-alpha.302) (2026-09-11)
|
|
92
|
+
|
|
93
|
+
### Features
|
|
94
|
+
|
|
95
|
+
* **boot:** a run command may wait until the component is served ([0f66bed](https://github.com/toa-io/toa/commit/0f66bedf7b54dc9c1397f7f32bbccbffde7288ca))
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# [1.0.0-alpha.301](https://github.com/toa-io/toa/compare/v1.0.0-alpha.300...v1.0.0-alpha.301) (2026-09-11)
|
|
99
|
+
|
|
100
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# [1.0.0-alpha.300](https://github.com/toa-io/toa/compare/v1.0.0-alpha.299...v1.0.0-alpha.300) (2026-09-11)
|
|
107
|
+
|
|
108
|
+
* feat(boot)!: a process is a thing, and an extension may keep something in one ([528d6cd](https://github.com/toa-io/toa/commit/528d6cdd307b45a6c30b6a184d7e06b3328cecf8))
|
|
109
|
+
* feat(core)!: an operation may ask to run once ([dca616c](https://github.com/toa-io/toa/commit/dca616cb380a7a389e277875d3bd5ca55a6e4d45))
|
|
110
|
+
|
|
111
|
+
### Features
|
|
112
|
+
|
|
113
|
+
* **core:** a call carries what it is, and a chain of them carries it down ([ebd7769](https://github.com/toa-io/toa/commit/ebd776984a79adb9bf4a97b680128be1efab856f))
|
|
114
|
+
* **core:** a call may name the process it goes to, and wait for a set time ([7d8adb2](https://github.com/toa-io/toa/commit/7d8adb2772a95ff45ae5374efdedfb5a857fbbe9))
|
|
115
|
+
|
|
116
|
+
### BREAKING CHANGES
|
|
117
|
+
|
|
118
|
+
* `Storage.store`, `.upsert` and `.ensure` take one more
|
|
119
|
+
argument, and `Storage` has two more members. A connector that ignores them
|
|
120
|
+
works exactly as it did; a component that asks it for `once` is refused at
|
|
121
|
+
boot. See migrations/299.md.
|
|
122
|
+
* a composition booted directly has no readiness probe. Readiness is
|
|
123
|
+
the process's, and a composition is not a process. `stage.workload` boots one where a
|
|
124
|
+
suite needs it.
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# [1.0.0-alpha.299](https://github.com/toa-io/toa/compare/v1.0.0-alpha.298...v1.0.0-alpha.299) (2026-09-10)
|
|
128
|
+
|
|
129
|
+
### Features
|
|
130
|
+
|
|
131
|
+
* **bindings.amqp:** a binding carries a channel, addressed by label ([17cf178](https://github.com/toa-io/toa/commit/17cf1782d1c47d033c02f99947b766eb9d45df75))
|
|
132
|
+
* **convergence:** deployments of one context converge ([8a70343](https://github.com/toa-io/toa/commit/8a70343cf6953aab58d4a25bac215508ff8d9a37))
|
|
133
|
+
* **core:** an outbox row is published to destinations ([cfb77b4](https://github.com/toa-io/toa/commit/cfb77b4826ff0f9560769a0996981e143d6525af))
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# [1.0.0-alpha.298](https://github.com/toa-io/toa/compare/v1.0.0-alpha.297...v1.0.0-alpha.298) (2026-09-08)
|
|
137
|
+
|
|
138
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# [1.0.0-alpha.297](https://github.com/toa-io/toa/compare/v1.0.0-alpha.296...v1.0.0-alpha.297) (2026-09-08)
|
|
145
|
+
|
|
146
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# [1.0.0-alpha.296](https://github.com/toa-io/toa/compare/v1.0.0-alpha.295...v1.0.0-alpha.296) (2026-09-08)
|
|
153
|
+
|
|
154
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# [1.0.0-alpha.295](https://github.com/toa-io/toa/compare/v1.0.0-alpha.294...v1.0.0-alpha.295) (2026-09-07)
|
|
161
|
+
|
|
162
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# [1.0.0-alpha.294](https://github.com/toa-io/toa/compare/v1.0.0-alpha.293...v1.0.0-alpha.294) (2026-09-07)
|
|
169
|
+
|
|
170
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# [1.0.0-alpha.293](https://github.com/toa-io/toa/compare/v1.0.0-alpha.292...v1.0.0-alpha.293) (2026-09-07)
|
|
177
|
+
|
|
178
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# [1.0.0-alpha.292](https://github.com/toa-io/toa/compare/v1.0.0-alpha.291...v1.0.0-alpha.292) (2026-09-07)
|
|
185
|
+
|
|
186
|
+
### Features
|
|
187
|
+
|
|
188
|
+
* **definitions:** the version of Toa is the definitions package's ([3d0272e](https://github.com/toa-io/toa/commit/3d0272ea0ab862f4b6c2e58a2f003f92d0f8a87f))
|
|
189
|
+
* **definitions:** what a package declares is read from one package ([7052341](https://github.com/toa-io/toa/commit/70523411b5d9e2b204c999aa02365173f3bb518d))
|
|
190
|
+
* **norm:** a package's definition is read by one resolver ([bffd41c](https://github.com/toa-io/toa/commit/bffd41c8d18c42786b0bf321623088b9dabc4724))
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
# [1.0.0-alpha.291](https://github.com/toa-io/toa/compare/v1.0.0-alpha.290...v1.0.0-alpha.291) (2026-09-07)
|
|
194
|
+
|
|
195
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# [1.0.0-alpha.289](https://github.com/toa-io/toa/compare/v1.0.0-alpha.288...v1.0.0-alpha.289) (2026-09-07)
|
|
202
|
+
|
|
203
|
+
* A deploy moves only what changed, and a component sees none of the runtime's environment (#1073) ([f38e3db](https://github.com/toa-io/toa/commit/f38e3db533f24db866c57bfa1ef294eff1eaf499)), closes [#1073](https://github.com/toa-io/toa/issues/1073) [#1064](https://github.com/toa-io/toa/issues/1064) [#1066](https://github.com/toa-io/toa/issues/1066) [#1067](https://github.com/toa-io/toa/issues/1067) [#1068](https://github.com/toa-io/toa/issues/1068) [#1069](https://github.com/toa-io/toa/issues/1069) [#1071](https://github.com/toa-io/toa/issues/1071) [#1070](https://github.com/toa-io/toa/issues/1070) [#1072](https://github.com/toa-io/toa/issues/1072)
|
|
204
|
+
|
|
205
|
+
### BREAKING CHANGES
|
|
206
|
+
|
|
207
|
+
* a component that read `process.env.TOA_*` reads `context` instead;
|
|
208
|
+
`echo(input)` no longer substitutes from the environment; a bash operation sees no
|
|
209
|
+
`TOA_*`; images no longer set `USER node` — see migrations/289.md.
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# [1.0.0-alpha.288](https://github.com/toa-io/toa/compare/v1.0.0-alpha.287...v1.0.0-alpha.288) (2026-09-06)
|
|
213
|
+
|
|
214
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
# [1.0.0-alpha.287](https://github.com/toa-io/toa/compare/v1.0.0-alpha.286...v1.0.0-alpha.287) (2026-09-06)
|
|
221
|
+
|
|
222
|
+
### Bug Fixes
|
|
223
|
+
|
|
224
|
+
* **boot:** a discovery belongs to the connection that made it ([48e1c8f](https://github.com/toa-io/toa/commit/48e1c8f668b1853134ae9fb2349c485e6da66c28))
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/boot",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.311",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Toa Boot",
|
|
5
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
7
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -20,13 +21,15 @@
|
|
|
20
21
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
23
|
-
"@toa.io/
|
|
24
|
-
"@toa.io/
|
|
25
|
-
"@toa.io/
|
|
26
|
-
"@toa.io/
|
|
27
|
-
"@toa.io/
|
|
24
|
+
"@toa.io/atomicity": "1.0.0-alpha.311",
|
|
25
|
+
"@toa.io/core": "1.0.0-alpha.311",
|
|
26
|
+
"@toa.io/definitions": "1.0.0-alpha.311",
|
|
27
|
+
"@toa.io/generic": "1.0.0-alpha.311",
|
|
28
|
+
"@toa.io/norm": "1.0.0-alpha.311",
|
|
29
|
+
"@toa.io/schemas": "1.0.0-alpha.311",
|
|
28
30
|
"clone-deep": "4.0.1",
|
|
29
|
-
"dotenv": "
|
|
31
|
+
"dotenv": "17.4.2",
|
|
32
|
+
"openspan": "1.0.0-alpha.305"
|
|
30
33
|
},
|
|
31
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "4f45061964e275296a27ff8ff39f757ce27d4008"
|
|
32
35
|
}
|
package/src/atom.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Connector } from '@toa.io/core'
|
|
2
|
+
|
|
3
|
+
import * as boot from './index.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The atom as a system aspect. Every component has `context.atom`, with nothing declared in its
|
|
7
|
+
* manifest and nothing of its own to configure.
|
|
8
|
+
*
|
|
9
|
+
* @implements {import('@toa.io/core/types').extensions.Aspect}
|
|
10
|
+
*/
|
|
11
|
+
class Aspect extends Connector {
|
|
12
|
+
name = 'atom'
|
|
13
|
+
|
|
14
|
+
#atom
|
|
15
|
+
|
|
16
|
+
constructor(atom) {
|
|
17
|
+
super()
|
|
18
|
+
|
|
19
|
+
this.#atom = atom
|
|
20
|
+
|
|
21
|
+
this.depends(atom)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// the methods are named rather than forwarded, so that the connector's lifecycle is not
|
|
25
|
+
// reachable from an algorithm
|
|
26
|
+
invoke(method, ...args) {
|
|
27
|
+
switch (method) {
|
|
28
|
+
case 'slots':
|
|
29
|
+
return this.#atom.slots(...args)
|
|
30
|
+
case 'meter':
|
|
31
|
+
return this.#atom.meter(...args)
|
|
32
|
+
case 'lock':
|
|
33
|
+
return this.#atom.lock(...args)
|
|
34
|
+
default:
|
|
35
|
+
throw new Error(`Atom aspect has no '${method}' method`)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** @param {string} group */
|
|
41
|
+
export const atom = (group) => new Aspect(boot.atomicity(group))
|
package/src/atomicity.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Factory } from '@toa.io/atomicity'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What the replicas of one group decide together. Every component has one, whether or not there
|
|
5
|
+
* is anything to coordinate through: without a Redis nothing is owned and nothing is metered —
|
|
6
|
+
* see the connector's readme.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} group
|
|
9
|
+
* @returns {import('@toa.io/core/types').atomicity.Atom}
|
|
10
|
+
*/
|
|
11
|
+
export const atomicity = (group) => new Factory().atom(group)
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { factory } from './factory.js'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const broadcast = (channel, group, binding = '@toa.io/bindings.amqp') => factory(binding).broadcast(channel, group)
|
|
6
|
-
|
|
7
|
-
exports.broadcast = broadcast
|
|
3
|
+
export const broadcast = async (channel, group, binding = '@toa.io/bindings.amqp') =>
|
|
4
|
+
(await factory(binding)).broadcast(channel, group)
|
package/src/bindings/consume.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { LOOP } from './constants.js'
|
|
2
|
+
import { factory } from './factory.js'
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
exports.consume = consume
|
|
4
|
+
export const consume = async (locator, endpoint, bindings) =>
|
|
5
|
+
await Promise.all(
|
|
6
|
+
[LOOP]
|
|
7
|
+
.concat(bindings)
|
|
8
|
+
.map(async (binding) => (await factory(binding)).consumer(locator, endpoint))
|
|
9
|
+
)
|
package/src/bindings/emit.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { factory } from './factory.js'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const emit = (binding, locator, label) => factory(binding).emitter(locator, label)
|
|
6
|
-
|
|
7
|
-
exports.emit = emit
|
|
3
|
+
export const emit = async (binding, locator, label) =>
|
|
4
|
+
(await factory(binding)).emitter(locator, label)
|
package/src/bindings/factory.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
let instances = {}
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
// the promise is what is remembered, so two components cannot each make a factory
|
|
4
|
+
export const factory = async (binding) => {
|
|
5
|
+
instances[binding] ??= import(binding).then(({ Factory }) => new Factory())
|
|
7
6
|
|
|
8
|
-
return instances[binding]
|
|
7
|
+
return await instances[binding]
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
// for testing purposes
|
|
12
|
-
const reset = () => (instances = {})
|
|
13
|
-
|
|
14
|
-
exports.factory = factory
|
|
15
|
-
exports.reset = reset
|
|
11
|
+
export const reset = () => (instances = {})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { factory } from './factory.js'
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line max-params
|
|
4
|
+
export const inbound = async (binding, channel, uris, label, sink) => {
|
|
5
|
+
const instance = await factory(binding)
|
|
6
|
+
|
|
7
|
+
if (instance.inbound === undefined)
|
|
8
|
+
throw new Error(`Binding '${binding}' does not consume a channel`)
|
|
9
|
+
|
|
10
|
+
return instance.inbound(channel, uris, label, sink)
|
|
11
|
+
}
|
package/src/bindings/index.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
exports.broadcast = broadcast
|
|
10
|
-
exports.consume = consume
|
|
11
|
-
exports.emit = emit
|
|
12
|
-
exports.produce = produce
|
|
13
|
-
exports.receive = receive
|
|
1
|
+
export { broadcast } from './broadcast.js'
|
|
2
|
+
export { consume } from './consume.js'
|
|
3
|
+
export { emit } from './emit.js'
|
|
4
|
+
export { inbound } from './inbound.js'
|
|
5
|
+
export { outbound } from './outbound.js'
|
|
6
|
+
export { produce } from './produce.js'
|
|
7
|
+
export { receive } from './receive.js'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { factory } from './factory.js'
|
|
2
|
+
|
|
3
|
+
export const outbound = async (binding, channel, uris) => {
|
|
4
|
+
const instance = await factory(binding)
|
|
5
|
+
|
|
6
|
+
if (instance.outbound === undefined)
|
|
7
|
+
throw new Error(`Binding '${binding}' does not publish a channel`)
|
|
8
|
+
|
|
9
|
+
return instance.outbound(channel, uris)
|
|
10
|
+
}
|
package/src/bindings/produce.js
CHANGED
|
@@ -1,28 +1,50 @@
|
|
|
1
|
-
|
|
1
|
+
import { definition } from '@toa.io/norm'
|
|
2
|
+
import { LOOP } from './constants.js'
|
|
3
|
+
import { factory } from './factory.js'
|
|
4
|
+
|
|
5
|
+
export const produce = async (component, operations) => {
|
|
6
|
+
const local = []
|
|
7
|
+
const other = []
|
|
8
|
+
const stateful = addressed(operations)
|
|
9
|
+
|
|
10
|
+
for (const [binding, endpoints] of group(operations)) {
|
|
11
|
+
const made = await factory(binding)
|
|
12
|
+
const carried = stateful.filter((endpoint) => endpoints.includes(endpoint))
|
|
13
|
+
const producer = made.producer(component.locator, endpoints, component, carried)
|
|
14
|
+
const { properties } = (await definition(binding)).module
|
|
15
|
+
|
|
16
|
+
if (properties.local === true) local.push(producer)
|
|
17
|
+
else other.push(producer)
|
|
18
|
+
}
|
|
2
19
|
|
|
3
|
-
|
|
4
|
-
|
|
20
|
+
return { local, other }
|
|
21
|
+
}
|
|
5
22
|
|
|
6
|
-
|
|
7
|
-
|
|
23
|
+
/** The endpoints that take addressed calls only. */
|
|
24
|
+
const addressed = (operations) =>
|
|
25
|
+
operations === undefined
|
|
26
|
+
? []
|
|
27
|
+
: Object.entries(operations)
|
|
28
|
+
.filter(([, operation]) => operation.stateful === true)
|
|
29
|
+
.map(([endpoint]) => endpoint)
|
|
8
30
|
|
|
9
|
-
|
|
31
|
+
/** The endpoints each binding carries, as entries. */
|
|
32
|
+
const group = (operations) => {
|
|
10
33
|
const map = {}
|
|
11
34
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
if (operations !== undefined)
|
|
36
|
+
for (const [endpoint, operation] of Object.entries(operations)) {
|
|
37
|
+
// noinspection JSUnresolvedVariable
|
|
38
|
+
const bindings = global.TOA_INTEGRATION_BINDINGS_LOOP_DISABLED
|
|
39
|
+
? operation.bindings
|
|
40
|
+
: [LOOP].concat(operation.bindings)
|
|
17
41
|
|
|
18
|
-
|
|
19
|
-
|
|
42
|
+
for (const binding of bindings) {
|
|
43
|
+
if (!map[binding]) map[binding] = []
|
|
20
44
|
|
|
21
|
-
|
|
45
|
+
map[binding].push(endpoint)
|
|
46
|
+
}
|
|
22
47
|
}
|
|
23
|
-
}
|
|
24
48
|
|
|
25
|
-
return Object.entries(map)
|
|
49
|
+
return Object.entries(map)
|
|
26
50
|
}
|
|
27
|
-
|
|
28
|
-
exports.produce = produce
|
package/src/bindings/receive.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { factory } from './factory.js'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const receive = (binding, locator, label, group, receiver) => factory(binding).receiver(locator, label, group, receiver)
|
|
6
|
-
|
|
7
|
-
exports.receive = receive
|
|
3
|
+
export const receive = async (binding, locator, label, group, receiver) =>
|
|
4
|
+
(await factory(binding)).receiver(locator, label, group, receiver)
|
package/src/bridge.js
CHANGED
|
@@ -1,28 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const algorithm = (
|
|
4
|
-
const algorithm = resolve(bridge).algorithm(path, endpoint, context)
|
|
1
|
+
export async function algorithm(bridge, path, endpoint, context) {
|
|
2
|
+
const factory = await resolve(bridge)
|
|
3
|
+
const algorithm = await factory.algorithm(path, endpoint, context)
|
|
5
4
|
|
|
6
5
|
algorithm.depends(context)
|
|
7
6
|
|
|
8
7
|
return algorithm
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
const event = (bridge, path, label, context) =>
|
|
12
|
-
|
|
10
|
+
export const event = async (bridge, path, label, context) =>
|
|
11
|
+
(await resolve(bridge)).event(path, label, context)
|
|
13
12
|
|
|
14
|
-
const
|
|
13
|
+
export const receiver = async (bridge, path, label) =>
|
|
14
|
+
(await resolve(bridge)).receiver(path, label)
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const { Factory } = require(bridge)
|
|
16
|
+
export const guard = async (bridge, path, label, context) =>
|
|
17
|
+
(await resolve(bridge)).guard(path, label, context)
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
export async function rc(bridge, path, context) {
|
|
20
|
+
const factory = await resolve(bridge)
|
|
22
21
|
|
|
23
|
-
return
|
|
22
|
+
if (factory.rc === undefined) return
|
|
23
|
+
|
|
24
|
+
return factory.rc(path, context)
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const factories = {}
|
|
28
|
+
|
|
29
|
+
// the promise is what is remembered, so two boots cannot each make a factory
|
|
30
|
+
const resolve = async (bridge) => {
|
|
31
|
+
factories[bridge] ??= import(bridge).then(({ Factory }) => new Factory())
|
|
32
|
+
|
|
33
|
+
return await factories[bridge]
|
|
34
|
+
}
|
package/src/call.js
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
import { Call, safe, Transmission } from '@toa.io/core'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import * as boot from './index.js'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const consumers = boot.bindings.consume(locator, endpoint, definition.bindings)
|
|
5
|
+
// eslint-disable-next-line max-params
|
|
6
|
+
export const call = async (locator, endpoint, definition, entity, source) => {
|
|
7
|
+
const consumers = await boot.bindings.consume(locator, endpoint, definition.bindings)
|
|
9
8
|
const transmission = new Transmission(consumers)
|
|
10
9
|
const contract = boot.contract.request(definition, entity)
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
}
|
|
11
|
+
const stateful = definition.stateful === true
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
/*
|
|
14
|
+
* An endpoint beginning with `.` is the runtime's own rather than an operation — a lookup, an
|
|
15
|
+
* exposition — so the safety of operations has nothing to say about it. `Component.invoke`
|
|
16
|
+
* counts it as no hop in a call chain for the same reason.
|
|
17
|
+
*/
|
|
18
|
+
const readable = endpoint[0] === '.' || safe(definition.type)
|
|
19
|
+
|
|
20
|
+
return new Call(
|
|
21
|
+
transmission,
|
|
22
|
+
contract,
|
|
23
|
+
`${locator.id}.${endpoint}`,
|
|
24
|
+
source,
|
|
25
|
+
stateful,
|
|
26
|
+
readable
|
|
27
|
+
)
|
|
28
|
+
}
|
package/src/cascade.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
import { Cascade } from '@toa.io/core'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import * as boot from './index.js'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const cascade = (manifest, endpoint, definition, context) => {
|
|
5
|
+
export async function cascade(manifest, endpoint, definition, context, preflight) {
|
|
8
6
|
const bridges = []
|
|
9
7
|
|
|
10
8
|
if (definition.forward) endpoint = definition.forward
|
|
11
9
|
|
|
12
10
|
if (definition.bridge) {
|
|
13
|
-
const bridge = boot.bridge.algorithm(
|
|
11
|
+
const bridge = await boot.bridge.algorithm(
|
|
12
|
+
definition.bridge,
|
|
13
|
+
manifest.path,
|
|
14
|
+
endpoint,
|
|
15
|
+
context
|
|
16
|
+
)
|
|
14
17
|
|
|
15
18
|
bridges.unshift(bridge)
|
|
16
19
|
}
|
|
@@ -22,12 +25,15 @@ const cascade = (manifest, endpoint, definition, context) => {
|
|
|
22
25
|
|
|
23
26
|
if (operation === undefined) continue
|
|
24
27
|
|
|
25
|
-
const bridge = boot.bridge.algorithm(
|
|
28
|
+
const bridge = await boot.bridge.algorithm(
|
|
29
|
+
operation.bridge,
|
|
30
|
+
prototype.path,
|
|
31
|
+
endpoint,
|
|
32
|
+
context
|
|
33
|
+
)
|
|
26
34
|
|
|
27
35
|
bridges.unshift(bridge)
|
|
28
36
|
}
|
|
29
37
|
|
|
30
|
-
return new Cascade(bridges)
|
|
38
|
+
return new Cascade(bridges, preflight)
|
|
31
39
|
}
|
|
32
|
-
|
|
33
|
-
exports.cascade = cascade
|