@toa.io/boot 1.0.0-alpha.28 → 1.0.0-alpha.282
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 +180 -0
- package/package.json +10 -8
- package/src/atom.js +37 -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 +5 -8
- package/src/bindings/emit.js +3 -6
- package/src/bindings/factory.js +5 -9
- package/src/bindings/index.js +5 -13
- package/src/bindings/produce.js +32 -19
- package/src/bindings/receive.js +3 -6
- package/src/bridge.js +23 -16
- package/src/call.js +6 -9
- package/src/cascade.js +6 -10
- package/src/component.js +56 -32
- package/src/composition.js +81 -16
- package/src/context.js +7 -8
- package/src/contract.js +9 -12
- package/src/discovery.js +7 -11
- package/src/emission.js +10 -14
- package/src/env.js +4 -5
- package/src/events.js +25 -0
- package/src/exposition.js +3 -7
- package/src/extensions/aspects.js +3 -7
- package/src/extensions/component.js +2 -6
- package/src/extensions/context.js +2 -6
- package/src/extensions/emitter.js +4 -7
- package/src/extensions/index.js +9 -19
- package/src/extensions/instances.js +1 -3
- package/src/extensions/load.js +6 -8
- package/src/extensions/manage.js +16 -0
- package/src/extensions/receiver.js +4 -7
- package/src/extensions/resolve.js +36 -11
- package/src/extensions/storage.js +2 -6
- package/src/extensions/tenants.js +4 -8
- package/src/guards.js +19 -0
- package/src/host.js +15 -0
- package/src/index.js +28 -32
- package/src/manifest.js +19 -14
- package/src/manifest.test.js +7 -7
- package/src/operation.js +7 -9
- package/src/outbox.js +17 -0
- package/src/rc.js +5 -0
- package/src/receivers.js +21 -18
- package/src/remote.js +28 -10
- package/src/span.js +17 -0
- package/src/storage.js +19 -13
- package/types/index.d.ts +7 -5
- package/types/manifest.d.ts +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
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.282](https://github.com/toa-io/toa/compare/v1.0.0-alpha.281...v1.0.0-alpha.282) (2026-09-03)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **boot:** declare host, and build extensions with it in the step definitions ([915d957](https://github.com/toa-io/toa/commit/915d9571823358f8fca6fe19ef3aabd1b62e5605))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* **core:** a Host for extensions ([6315eac](https://github.com/toa-io/toa/commit/6315eac1e9fb05be472272de06385c54ad5934ce))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [1.0.0-alpha.278](https://github.com/toa-io/toa/compare/v1.0.0-alpha.277...v1.0.0-alpha.278) (2026-09-03)
|
|
18
|
+
|
|
19
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# [1.0.0-alpha.277](https://github.com/toa-io/toa/compare/v1.0.0-alpha.276...v1.0.0-alpha.277) (2026-09-03)
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
* read a manifest the way js-yaml read one before ([fcea1b2](https://github.com/toa-io/toa/commit/fcea1b21996d6efa6c3198acbfc9f70f1ce0c35c))
|
|
30
|
+
* settle what the module loader made asynchronous ([d4ab9df](https://github.com/toa-io/toa/commit/d4ab9dfb09e382da311dba08f52214e7645f4a6c))
|
|
31
|
+
* what the loader resolves, and what it will not ([1b8a02f](https://github.com/toa-io/toa/commit/1b8a02ff0a5e0f18ee62e3f71bc81116f86f9af1))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# [1.0.0-alpha.274](https://github.com/toa-io/toa/compare/v1.0.0-alpha.273...v1.0.0-alpha.274) (2026-09-02)
|
|
35
|
+
|
|
36
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# [1.0.0-alpha.273](https://github.com/toa-io/toa/compare/v1.0.0-alpha.272...v1.0.0-alpha.273) (2026-09-02)
|
|
43
|
+
|
|
44
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# [1.0.0-alpha.272](https://github.com/toa-io/toa/compare/v1.0.0-alpha.271...v1.0.0-alpha.272) (2026-09-01)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Bug Fixes
|
|
54
|
+
|
|
55
|
+
* **amqp:** keep a receiver apart from the producers it delivers into ([4c2f43e](https://github.com/toa-io/toa/commit/4c2f43ebde68ba76a1fd277fe2a3305be1b622ef))
|
|
56
|
+
* **amqp:** tear a receiver down before its producers, and drop the split ([e6c1154](https://github.com/toa-io/toa/commit/e6c1154024df22f7a470c47c1a79bd170fe7e3b2))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
* refactor(atomicity)!: take the lock manager from the stash ([4fd91eb](https://github.com/toa-io/toa/commit/4fd91eb2fdb68f7b87aaf16d182794bbc567ba57))
|
|
60
|
+
* refactor(atomicity)!: make the connector a family, not a partitioner ([06fd63a](https://github.com/toa-io/toa/commit/06fd63ad6296b724ef83afccf4e4e25d0bcaf080))
|
|
61
|
+
* refactor(atomicity)!: rename the connector and free it of the outbox ([21f1a41](https://github.com/toa-io/toa/commit/21f1a41aceafcfd35c7620014062fe46b54afa95))
|
|
62
|
+
* feat(core)!: commit events with the state that produced them ([1eb68cc](https://github.com/toa-io/toa/commit/1eb68cc435dbfa03faa16009fceb866693d22e1a)), closes [#20](https://github.com/toa-io/toa/issues/20)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Features
|
|
66
|
+
|
|
67
|
+
* **core:** give every component an atom aspect ([b501b9c](https://github.com/toa-io/toa/commit/b501b9cd3d5f5408d9faa71213e953fe2792cf9f))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
### BREAKING CHANGES
|
|
71
|
+
|
|
72
|
+
* `context.stash.lock` is gone; lock through `context.atom` instead.
|
|
73
|
+
A stash pointer resolving to several addresses now uses the first.
|
|
74
|
+
|
|
75
|
+
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
76
|
+
* `Factory.partition(group)` is `Factory.atom(group)`, and the
|
|
77
|
+
`Partition` it returned is an `Atom`. `slots(total)` is unchanged.
|
|
78
|
+
|
|
79
|
+
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
80
|
+
* `@toa.io/partitions.redis` is now `@toa.io/atomicity`, and its
|
|
81
|
+
`lanes(total)` is `slots(total)`. Redis is declared as `atomicity` in the context
|
|
82
|
+
rather than `outbox.redis`, and read from `TOA_ATOMICITY_REDIS`.
|
|
83
|
+
`TOA_OUTBOX_PARTITION_INTERVAL` is `TOA_ATOMICITY_INTERVAL`.
|
|
84
|
+
|
|
85
|
+
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
86
|
+
* `event.changeset` is removed; use `origin` and `state`. `State`
|
|
87
|
+
takes an `Outbox` in place of an `Emission`. `difference` is dropped from
|
|
88
|
+
`@toa.io/generic` along with its last caller.
|
|
89
|
+
|
|
90
|
+
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# [1.0.0-alpha.270](https://github.com/toa-io/toa/compare/v1.0.0-alpha.269...v1.0.0-alpha.270) (2026-08-31)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
### Performance Improvements
|
|
100
|
+
|
|
101
|
+
* **boot:** stop paying for what a composition does not need to start ([1619c27](https://github.com/toa-io/toa/commit/1619c2743072f4706939ce72f3074e615d26a91e))
|
|
102
|
+
* **openspan:** create a span only when something records it ([a6efb0e](https://github.com/toa-io/toa/commit/a6efb0eed38393f4c169b067f23d7447f0169bca))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# [1.0.0-alpha.266](https://github.com/toa-io/toa/compare/v1.0.0-alpha.265...v1.0.0-alpha.266) (2026-08-29)
|
|
109
|
+
|
|
110
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# [1.0.0-alpha.265](https://github.com/toa-io/toa/compare/v1.0.0-alpha.264...v1.0.0-alpha.265) (2026-08-29)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
### Features
|
|
120
|
+
|
|
121
|
+
* **bridges.node:** add the dispose run command phase ([00df715](https://github.com/toa-io/toa/commit/00df7158f638b976ab09d4007102a4ead3c696c3))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# [1.0.0-alpha.264](https://github.com/toa-io/toa/compare/v1.0.0-alpha.263...v1.0.0-alpha.264) (2026-08-29)
|
|
128
|
+
|
|
129
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# [1.0.0-alpha.263](https://github.com/toa-io/toa/compare/v1.0.0-alpha.262...v1.0.0-alpha.263) (2026-08-29)
|
|
136
|
+
|
|
137
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# [1.0.0-alpha.262](https://github.com/toa-io/toa/compare/v1.0.0-alpha.261...v1.0.0-alpha.262) (2026-08-28)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
### Bug Fixes
|
|
147
|
+
|
|
148
|
+
* **boot:** let the composition own the process discovery ([2201e88](https://github.com/toa-io/toa/commit/2201e8852517fd1d2822c775c9b126eb60399580))
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
### Features
|
|
152
|
+
|
|
153
|
+
* **core:** identify the origin of a call with `request.source` ([9da6b66](https://github.com/toa-io/toa/commit/9da6b66df852690351a1e82c7b8cc176fd89774a))
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# [1.0.0-alpha.259](https://github.com/toa-io/toa/compare/v1.0.0-alpha.258...v1.0.0-alpha.259) (2026-08-24)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
### Features
|
|
163
|
+
|
|
164
|
+
* **runtime:** split component RC into preflight and settle ([0d648b3](https://github.com/toa-io/toa/commit/0d648b314e4aac226c254bf01a86affa04b59b34))
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# [1.0.0-alpha.257](https://github.com/toa-io/toa/compare/v1.0.0-alpha.256...v1.0.0-alpha.257) (2026-08-24)
|
|
171
|
+
|
|
172
|
+
**Note:** Version bump only for package @toa.io/boot
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# [1.0.0-alpha.256](https://github.com/toa-io/toa/compare/v1.0.0-alpha.255...v1.0.0-alpha.256) (2026-08-23)
|
|
179
|
+
|
|
180
|
+
**Note:** Version bump only for package @toa.io/boot
|
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.282",
|
|
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,14 @@
|
|
|
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/generic": "1.0.0-alpha.
|
|
26
|
-
"@toa.io/norm": "1.0.0-alpha.
|
|
27
|
-
"@toa.io/
|
|
24
|
+
"@toa.io/atomicity": "1.0.0-alpha.282",
|
|
25
|
+
"@toa.io/core": "1.0.0-alpha.282",
|
|
26
|
+
"@toa.io/generic": "1.0.0-alpha.282",
|
|
27
|
+
"@toa.io/norm": "1.0.0-alpha.282",
|
|
28
|
+
"@toa.io/schemas": "1.0.0-alpha.282",
|
|
28
29
|
"clone-deep": "4.0.1",
|
|
29
|
-
"dotenv": "
|
|
30
|
+
"dotenv": "17.4.2",
|
|
31
|
+
"openspan": "1.0.0-alpha.277"
|
|
30
32
|
},
|
|
31
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "4007c814725dd015d3bbebb9a28e28a247645c4f"
|
|
32
34
|
}
|
package/src/atom.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
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 {toa.core.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': return this.#atom.slots(...args)
|
|
29
|
+
case 'meter': return this.#atom.meter(...args)
|
|
30
|
+
case 'lock': return this.#atom.lock(...args)
|
|
31
|
+
default: throw new Error(`Atom aspect has no '${method}' method`)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @param {string} group */
|
|
37
|
+
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 {toa.core.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,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { LOOP } from './constants.js'
|
|
2
|
+
import { factory } from './factory.js'
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const consume = (locator, endpoint, bindings) =>
|
|
7
|
-
[LOOP].concat(bindings).map((binding) => factory(binding).consumer(locator, endpoint))
|
|
8
|
-
|
|
9
|
-
exports.consume = consume
|
|
4
|
+
export const consume = async (locator, endpoint, bindings) =>
|
|
5
|
+
await Promise.all([LOOP].concat(bindings).map(async (binding) =>
|
|
6
|
+
(await factory(binding)).consumer(locator, endpoint)))
|
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 = {})
|
package/src/bindings/index.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const { produce } = require('./produce')
|
|
7
|
-
const { receive } = require('./receive')
|
|
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 { produce } from './produce.js'
|
|
5
|
+
export { receive } from './receive.js'
|
package/src/bindings/produce.js
CHANGED
|
@@ -1,28 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
1
|
+
import { LOOP } from './constants.js'
|
|
2
|
+
import { factory } from './factory.js'
|
|
3
|
+
|
|
4
|
+
export const produce = async (component, operations) => {
|
|
5
|
+
const local = []
|
|
6
|
+
const other = []
|
|
7
|
+
|
|
8
|
+
for (const [binding, endpoints] of group(operations)) {
|
|
9
|
+
const made = await factory(binding)
|
|
10
|
+
const producer = made.producer(component.locator, endpoints, component)
|
|
11
|
+
const { properties } = await import(binding)
|
|
12
|
+
|
|
13
|
+
if (properties.local === true)
|
|
14
|
+
local.push(producer)
|
|
15
|
+
else
|
|
16
|
+
other.push(producer)
|
|
17
|
+
}
|
|
5
18
|
|
|
6
|
-
|
|
7
|
-
|
|
19
|
+
return { local, other }
|
|
20
|
+
}
|
|
8
21
|
|
|
9
|
-
|
|
22
|
+
/** The endpoints each binding carries, as entries. */
|
|
23
|
+
const group = (operations) => {
|
|
10
24
|
const map = {}
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
if (operations !== undefined)
|
|
27
|
+
for (const [endpoint, operation] of Object.entries(operations)) {
|
|
28
|
+
// noinspection JSUnresolvedVariable
|
|
29
|
+
const bindings = global.TOA_INTEGRATION_BINDINGS_LOOP_DISABLED
|
|
30
|
+
? operation.bindings
|
|
31
|
+
: [LOOP].concat(operation.bindings)
|
|
17
32
|
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
for (const binding of bindings) {
|
|
34
|
+
if (!map[binding]) map[binding] = []
|
|
20
35
|
|
|
21
|
-
|
|
36
|
+
map[binding].push(endpoint)
|
|
37
|
+
}
|
|
22
38
|
}
|
|
23
|
-
}
|
|
24
39
|
|
|
25
|
-
return Object.entries(map)
|
|
40
|
+
return Object.entries(map)
|
|
26
41
|
}
|
|
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,35 @@
|
|
|
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
|
-
|
|
22
|
+
if (factory.rc === undefined)
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
return factory.rc(path, context)
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const factories = {}
|
|
29
|
+
|
|
30
|
+
// the promise is what is remembered, so two boots cannot each make a factory
|
|
31
|
+
const resolve = async (bridge) => {
|
|
32
|
+
factories[bridge] ??= import(bridge).then(({ Factory }) => new Factory())
|
|
33
|
+
|
|
34
|
+
return await factories[bridge]
|
|
35
|
+
}
|
package/src/call.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { Call, 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
|
-
return new Call(transmission, contract)
|
|
11
|
+
return new Call(transmission, contract, source)
|
|
13
12
|
}
|
|
14
|
-
|
|
15
|
-
exports.call = call
|
package/src/cascade.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
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(definition.bridge, manifest.path, endpoint, context)
|
|
11
|
+
const bridge = await boot.bridge.algorithm(definition.bridge, manifest.path, endpoint, context)
|
|
14
12
|
|
|
15
13
|
bridges.unshift(bridge)
|
|
16
14
|
}
|
|
@@ -22,12 +20,10 @@ const cascade = (manifest, endpoint, definition, context) => {
|
|
|
22
20
|
|
|
23
21
|
if (operation === undefined) continue
|
|
24
22
|
|
|
25
|
-
const bridge = boot.bridge.algorithm(operation.bridge, prototype.path, endpoint, context)
|
|
23
|
+
const bridge = await boot.bridge.algorithm(operation.bridge, prototype.path, endpoint, context)
|
|
26
24
|
|
|
27
25
|
bridges.unshift(bridge)
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
return new Cascade(bridges)
|
|
28
|
+
return new Cascade(bridges, preflight)
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
exports.cascade = cascade
|
package/src/component.js
CHANGED
|
@@ -1,48 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { remap } = require('@toa.io/generic')
|
|
4
|
-
const {
|
|
5
|
-
Component,
|
|
6
|
-
Locator,
|
|
7
|
-
State,
|
|
8
|
-
entities
|
|
9
|
-
} = require('@toa.io/core')
|
|
10
|
-
const { Schema } = require('@toa.io/schema')
|
|
11
|
-
|
|
12
|
-
const boot = require('./index')
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param {toa.norm.Component} manifest
|
|
16
|
-
* @returns {Promise<toa.core.Component>}
|
|
17
|
-
*/
|
|
18
|
-
const component = async (manifest) => {
|
|
19
|
-
boot.extensions.load(manifest)
|
|
1
|
+
import { Component, Locator, State, entities } from '@toa.io/core'
|
|
2
|
+
import * as schemas from '@toa.io/schemas'
|
|
20
3
|
|
|
4
|
+
import * as boot from './index.js'
|
|
5
|
+
import { span } from './span.js'
|
|
6
|
+
|
|
7
|
+
export const component = async (manifest) => {
|
|
21
8
|
const locator = new Locator(manifest.name, manifest.namespace)
|
|
22
|
-
|
|
9
|
+
|
|
10
|
+
return span(`component ${locator.id}`, () => create(manifest, locator))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const create = async (manifest, locator) => {
|
|
14
|
+
await boot.extensions.load(manifest)
|
|
15
|
+
|
|
16
|
+
// the storage is told whether there will be an outbox, so the events come first
|
|
17
|
+
const events = boot.events(manifest)
|
|
18
|
+
const storage = await boot.storage(manifest, events !== undefined)
|
|
23
19
|
const context = await boot.context(manifest)
|
|
24
|
-
const emission = boot.emission(
|
|
20
|
+
const emission = await boot.emission(events, locator, context)
|
|
21
|
+
const outbox = boot.outbox(manifest, storage, emission)
|
|
25
22
|
|
|
26
23
|
let state
|
|
27
24
|
|
|
28
25
|
if (manifest.entity !== undefined) {
|
|
29
|
-
const schema =
|
|
30
|
-
const
|
|
26
|
+
const schema = schemas.schema(manifest.entity.schema)
|
|
27
|
+
const guards = await boot.guards(manifest, context)
|
|
28
|
+
const entity = new entities.Factory(schema, guards)
|
|
31
29
|
|
|
32
|
-
state = new State(storage, entity,
|
|
30
|
+
state = new State(storage, entity, outbox, manifest.entity.associated)
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
: remap(manifest.operations, (definition, endpoint) =>
|
|
38
|
-
boot.operation(manifest, endpoint, definition, context, state))
|
|
39
|
-
|
|
33
|
+
const phases = await boot.rc(manifest, context)
|
|
34
|
+
const operations = await bootOperations(manifest, context, state, phases?.preflight)
|
|
40
35
|
const component = new Component(locator, operations)
|
|
41
36
|
|
|
42
37
|
if (storage) component.depends(storage)
|
|
43
|
-
if (emission) component.depends(emission)
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
// the outbox owns the emission and the storage, so it drains before either goes down
|
|
40
|
+
if (outbox) component.depends(outbox)
|
|
41
|
+
else if (emission) component.depends(emission)
|
|
42
|
+
|
|
43
|
+
const decorated = boot.extensions.component(component)
|
|
44
|
+
|
|
45
|
+
if (phases?.settle !== undefined)
|
|
46
|
+
decorated.settle = phases.settle
|
|
47
|
+
|
|
48
|
+
// a dependency closes after its dependant, so the component is already closed
|
|
49
|
+
// when the RC releases what it opened
|
|
50
|
+
if (phases?.dispose !== undefined)
|
|
51
|
+
decorated.depends(phases.dispose)
|
|
52
|
+
|
|
53
|
+
return decorated
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
async function bootOperations (manifest, context, state, preflight) {
|
|
57
|
+
if (manifest.operations === undefined)
|
|
58
|
+
return {}
|
|
59
|
+
|
|
60
|
+
const entries = Object.entries(manifest.operations)
|
|
61
|
+
|
|
62
|
+
// each one loads its algorithm from disk and compiles its contracts
|
|
63
|
+
const booted = await Promise.all(entries.map(([endpoint, definition]) =>
|
|
64
|
+
boot.operation(manifest, endpoint, definition, context, state, preflight)))
|
|
65
|
+
|
|
66
|
+
const operations = {}
|
|
67
|
+
|
|
68
|
+
for (let i = 0; i < entries.length; i++)
|
|
69
|
+
operations[entries[i][0]] = booted[i]
|
|
70
|
+
|
|
71
|
+
return operations
|
|
72
|
+
}
|