@toa.io/boot 1.0.0-alpha.257 → 1.0.0-alpha.259

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 CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [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)
7
+
8
+
9
+ ### Features
10
+
11
+ * **runtime:** split component RC into preflight and settle ([0d648b3](https://github.com/toa-io/toa/commit/0d648b314e4aac226c254bf01a86affa04b59b34))
12
+
13
+
14
+
15
+
16
+
6
17
  # [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)
7
18
 
8
19
  **Note:** Version bump only for package @toa.io/boot
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/boot",
3
- "version": "1.0.0-alpha.257",
3
+ "version": "1.0.0-alpha.259",
4
4
  "description": "Toa Boot",
5
5
  "author": "temich <tema.gurtovoy@gmail.com>",
6
6
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -20,14 +20,14 @@
20
20
  "test": "echo \"Error: run tests from root\" && exit 1"
21
21
  },
22
22
  "dependencies": {
23
- "@toa.io/core": "1.0.0-alpha.257",
23
+ "@toa.io/core": "1.0.0-alpha.259",
24
24
  "@toa.io/filesystem": "1.0.0-alpha.254",
25
25
  "@toa.io/generic": "1.0.0-alpha.254",
26
- "@toa.io/norm": "1.0.0-alpha.257",
26
+ "@toa.io/norm": "1.0.0-alpha.259",
27
27
  "@toa.io/schemas": "1.0.0-alpha.254",
28
28
  "clone-deep": "4.0.1",
29
29
  "dotenv": "16.1.1",
30
30
  "openspan": "1.0.0-alpha.254"
31
31
  },
32
- "gitHead": "2db23a4e2ff6740a5f852208a9b896812ec6f819"
32
+ "gitHead": "3f557c2f855f078163128c317e7cb2f3629968aa"
33
33
  }
@@ -3,8 +3,21 @@
3
3
  const { LOOP } = require('./constants')
4
4
  const { factory } = require('./factory')
5
5
 
6
- const produce = (component, operations) => group(operations, (factory, endpoints) =>
7
- factory.producer(component.locator, endpoints, component))
6
+ const produce = (component, operations) => {
7
+ const local = []
8
+ const other = []
9
+
10
+ group(operations, (binding, endpoints) => {
11
+ const producer = factory(binding).producer(component.locator, endpoints, component)
12
+
13
+ if (require(binding).properties.local === true)
14
+ local.push(producer)
15
+ else
16
+ other.push(producer)
17
+ })
18
+
19
+ return { local, other }
20
+ }
8
21
 
9
22
  const group = (operations, callback) => {
10
23
  const map = {}
@@ -23,7 +36,8 @@ const group = (operations, callback) => {
23
36
  }
24
37
  }
25
38
 
26
- return Object.entries(map).map(([binding, endpoints]) => callback(factory(binding), endpoints))
39
+ for (const [binding, endpoints] of Object.entries(map))
40
+ callback(binding, endpoints)
27
41
  }
28
42
 
29
43
  exports.produce = produce
package/src/cascade.js CHANGED
@@ -4,7 +4,7 @@ const { Cascade } = require('@toa.io/core')
4
4
 
5
5
  const boot = require('./index')
6
6
 
7
- async function cascade (manifest, endpoint, definition, context, rc) {
7
+ async function cascade (manifest, endpoint, definition, context, preflight) {
8
8
  const bridges = []
9
9
 
10
10
  if (definition.forward) endpoint = definition.forward
@@ -27,7 +27,7 @@ async function cascade (manifest, endpoint, definition, context, rc) {
27
27
  bridges.unshift(bridge)
28
28
  }
29
29
 
30
- return new Cascade(bridges, rc)
30
+ return new Cascade(bridges, preflight)
31
31
  }
32
32
 
33
33
  exports.cascade = cascade
package/src/component.js CHANGED
@@ -28,24 +28,29 @@ const create = async (manifest, locator) => {
28
28
  state = new State(storage, entity, emission, manifest.entity.associated)
29
29
  }
30
30
 
31
- const rc = await boot.rc(manifest, context)
32
- const operations = await bootOperations(manifest, context, state, rc)
31
+ const phases = await boot.rc(manifest, context)
32
+ const operations = await bootOperations(manifest, context, state, phases?.preflight)
33
33
  const component = new Component(locator, operations)
34
34
 
35
35
  if (storage) component.depends(storage)
36
36
  if (emission) component.depends(emission)
37
37
 
38
- return boot.extensions.component(component)
38
+ const decorated = boot.extensions.component(component)
39
+
40
+ if (phases?.settle !== undefined)
41
+ decorated.settle = phases.settle
42
+
43
+ return decorated
39
44
  }
40
45
 
41
- async function bootOperations (manifest, context, state, rc) {
46
+ async function bootOperations (manifest, context, state, preflight) {
42
47
  if (manifest.operations === undefined)
43
48
  return {}
44
49
 
45
50
  const operations = {}
46
51
 
47
52
  for (const [endpoint, definition] of Object.entries(manifest.operations))
48
- operations[endpoint] = await boot.operation(manifest, endpoint, definition, context, state, rc)
53
+ operations[endpoint] = await boot.operation(manifest, endpoint, definition, context, state, preflight)
49
54
 
50
55
  return operations
51
56
  }
@@ -25,19 +25,48 @@ async function composition (paths, options) {
25
25
  const expositions = await span('expose discovery',
26
26
  async () => await Promise.all(manifests.map(boot.discovery.expose)))
27
27
 
28
- const components = await span('create components',
29
- async () => await Promise.all(manifests.map(boot.component)))
28
+ try {
29
+ const components = await span('create components',
30
+ async () => await Promise.all(manifests.map(boot.component)))
30
31
 
31
- const producers = components.map((component, index) =>
32
- boot.bindings.produce(component, manifests[index].operations))
32
+ const groups = components.map((component, index) =>
33
+ boot.bindings.produce(component, manifests[index].operations))
33
34
 
34
- const receivers = await span('create receivers',
35
- async () => await Promise.all(components.map((component, index) =>
36
- boot.receivers(manifests[index], component))))
35
+ const receivers = await span('create receivers',
36
+ async () => await Promise.all(components.map((component, index) =>
37
+ boot.receivers(manifests[index], component))))
37
38
 
38
- const composition = new Composition(expositions.flat(), producers.flat(), receivers.flat(), tenants.flat())
39
+ const producers = []
40
+ const settles = []
39
41
 
40
- return boot.extensions.manage(composition)
42
+ for (let i = 0; i < components.length; i++) {
43
+ const { local, other } = groups[i]
44
+ const settle = components[i].settle
45
+
46
+ producers.push(...local, ...other)
47
+
48
+ if (settle === undefined)
49
+ continue
50
+
51
+ if (local.length > 0)
52
+ settle.depends(local)
53
+
54
+ for (const producer of other)
55
+ producer.depends(settle)
56
+
57
+ for (const receiver of receivers[i])
58
+ receiver.depends(settle)
59
+
60
+ settles.push(settle)
61
+ }
62
+
63
+ const composition = new Composition(expositions.flat(), producers.concat(settles), receivers.flat(), tenants.flat())
64
+
65
+ return boot.extensions.manage(composition)
66
+ } catch (exception) {
67
+ await Promise.all(expositions.flat().map((connector) => connector.disconnect(true)))
68
+ throw exception
69
+ }
41
70
  })
42
71
  }
43
72
 
package/src/discovery.js CHANGED
@@ -29,7 +29,8 @@ const lookup = async (locator) => {
29
29
  const expose = async (manifest) => {
30
30
  const exposition = new Exposition(manifest.locator, manifest)
31
31
  const operations = { [ENDPOINT]: { bindings: BINDINGS } }
32
- const producers = boot.bindings.produce(exposition, operations)
32
+ const { local, other } = boot.bindings.produce(exposition, operations)
33
+ const producers = local.concat(other)
33
34
 
34
35
  await Promise.all(producers.map((producer) => producer.connect()))
35
36
 
package/src/operation.js CHANGED
@@ -12,8 +12,8 @@ const {
12
12
 
13
13
  const boot = require('./index')
14
14
 
15
- async function operation (manifest, endpoint, definition, context, scope, rc) {
16
- const cascade = await boot.cascade(manifest, endpoint, definition, context, rc)
15
+ async function operation (manifest, endpoint, definition, context, scope, preflight) {
16
+ const cascade = await boot.cascade(manifest, endpoint, definition, context, preflight)
17
17
  const reply = boot.contract.reply(definition.output, definition.error)
18
18
  const input = definition.input
19
19
  const request = boot.contract.request({ input }, manifest.entity)