@toa.io/boot 1.0.0-alpha.34 → 1.0.0-alpha.341
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 +475 -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 +18 -6
- 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 +62 -17
- package/src/bindings/receive.js +3 -6
- package/src/bridge.js +22 -16
- package/src/call.js +29 -9
- package/src/cascade.js +16 -10
- package/src/component.js +101 -32
- package/src/composition.js +115 -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 +62 -13
- 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 +12 -0
- package/src/index.js +29 -34
- package/src/manifest.js +80 -36
- package/src/manifest.test.js +91 -8
- package/src/map.js +108 -0
- package/src/operation.js +29 -14
- package/src/outbox.js +22 -0
- package/src/rc.js +5 -0
- package/src/receivers.js +53 -23
- package/src/regional.js +18 -0
- package/src/regional.test.js +28 -0
- package/src/remote.js +41 -22
- package/src/rendering.js +50 -0
- package/src/span.js +19 -0
- package/src/storage.js +50 -16
- package/src/storage.test.js +57 -0
- package/src/workload.js +283 -0
- package/src/workload.test.js +323 -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/src/env.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import dotenv from 'dotenv'
|
|
3
|
+
import { environment, findUp } from '@toa.io/generic'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
/*
|
|
6
|
+
* A local run reads what `toa env` wrote. What the file says goes to the environment store
|
|
7
|
+
* and never into `process.env`: a `.env` is where a local run keeps its secrets, and a
|
|
8
|
+
* component's code must not find them. A variable already set is left alone, as `dotenv`
|
|
9
|
+
* left it, so what the environment says still wins — and reading the file costs nothing
|
|
10
|
+
* where there is none: a deployment has no `.env` to find.
|
|
11
|
+
*
|
|
12
|
+
* It used to be read only where `TOA_ENV` was unset, taking that one variable as proof the
|
|
13
|
+
* environment had been injected. Setting it for any other reason then dropped the file
|
|
14
|
+
* whole, and every variable in it with it.
|
|
15
|
+
*/
|
|
16
|
+
export function load(path) {
|
|
17
|
+
environment.absorbEntries(dotenv.parse(readFileSync(path, 'utf8')))
|
|
9
18
|
}
|
|
10
19
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
})()
|
|
15
|
-
}
|
|
20
|
+
const path = findUp('.env')
|
|
21
|
+
|
|
22
|
+
if (path !== undefined) load(path)
|
package/src/events.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { environment } from '@toa.io/generic'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The events of this component that something consumes. An event nobody consumes is not
|
|
5
|
+
* published, so it gets no emitter and no exchange, and a component none of whose events are
|
|
6
|
+
* consumed gets no emission — and therefore no outbox and no transaction.
|
|
7
|
+
*
|
|
8
|
+
* The deployment computes this from the whole context. Without one — a local run, `toa mono`,
|
|
9
|
+
* a composition booted in a test — the variable is absent and every event is published.
|
|
10
|
+
*
|
|
11
|
+
* @param {toa.norm.Component} manifest
|
|
12
|
+
* @returns {toa.norm.Events | undefined}
|
|
13
|
+
*/
|
|
14
|
+
export const events = (manifest) => {
|
|
15
|
+
if (manifest.events === undefined) return
|
|
16
|
+
|
|
17
|
+
const value = environment.get(VARIABLE + manifest.locator.uppercase)
|
|
18
|
+
|
|
19
|
+
if (value === undefined) return manifest.events
|
|
20
|
+
|
|
21
|
+
const consumed = new Set(value.split(' ').filter(Boolean))
|
|
22
|
+
const entries = Object.entries(manifest.events).filter(([label]) => consumed.has(label))
|
|
23
|
+
|
|
24
|
+
return entries.length === 0 ? undefined : Object.fromEntries(entries)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const VARIABLE = 'TOA_EVENTS_'
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { resolve } = require('./resolve')
|
|
1
|
+
import { instance } from './resolve.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* @param {toa.norm.Component} manifest
|
|
7
|
-
* @returns {toa.core.extensions.Aspect[]}
|
|
5
|
+
* @returns {import('@toa.io/core/types').extensions.Aspect[]}
|
|
8
6
|
*/
|
|
9
|
-
const aspects = (manifest) => {
|
|
7
|
+
export const aspects = (manifest) => {
|
|
10
8
|
const aspects = []
|
|
11
9
|
|
|
12
10
|
if (manifest.extensions === undefined) return aspects
|
|
13
11
|
|
|
14
12
|
for (const [name, declaration] of Object.entries(manifest.extensions)) {
|
|
15
|
-
const factory =
|
|
13
|
+
const factory = instance(name, manifest.path)
|
|
16
14
|
|
|
17
15
|
if (factory.aspect === undefined) continue
|
|
18
16
|
|
|
@@ -24,5 +22,3 @@ const aspects = (manifest) => {
|
|
|
24
22
|
|
|
25
23
|
return aspects
|
|
26
24
|
}
|
|
27
|
-
|
|
28
|
-
exports.aspects = aspects
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { instances } = require('./instances')
|
|
1
|
+
import { instances } from './instances.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
* @param {toa.core.Component} component
|
|
7
|
-
* @returns {toa.core.Component}
|
|
4
|
+
* @param {import('@toa.io/core').Component} component
|
|
5
|
+
* @returns {import('@toa.io/core').Component}
|
|
8
6
|
*/
|
|
9
|
-
const component = (component) => {
|
|
7
|
+
export const component = (component) => {
|
|
10
8
|
let decorated = component
|
|
11
9
|
|
|
12
10
|
for (const factory of Object.values(instances)) {
|
|
@@ -15,5 +13,3 @@ const component = (component) => {
|
|
|
15
13
|
|
|
16
14
|
return decorated
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
exports.component = component
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { instances } = require('./instances')
|
|
1
|
+
import { instances } from './instances.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
* @param {toa.core.Context} component
|
|
7
|
-
* @returns {toa.core.Context}
|
|
4
|
+
* @param {import('@toa.io/core').Context} component
|
|
5
|
+
* @returns {import('@toa.io/core').Context}
|
|
8
6
|
*/
|
|
9
|
-
const context = (component) => {
|
|
7
|
+
export const context = (component) => {
|
|
10
8
|
let decorated = component
|
|
11
9
|
|
|
12
10
|
for (const factory of Object.values(instances)) {
|
|
@@ -15,5 +13,3 @@ const context = (component) => {
|
|
|
15
13
|
|
|
16
14
|
return decorated
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
exports.context = context
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { instance } from './resolve.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Where a committed state change of this component goes, beside its own events. An extension
|
|
5
|
+
* that contributes one gives the component an outbox whether or not it declares an event, so
|
|
6
|
+
* this is read before the storage is made.
|
|
7
|
+
*
|
|
8
|
+
* @param {toa.norm.Component} manifest
|
|
9
|
+
* @returns {Promise<import('@toa.io/core/types').outbox.Destination[]>}
|
|
10
|
+
*/
|
|
11
|
+
export const destinations = async (manifest) => {
|
|
12
|
+
const destinations = []
|
|
13
|
+
|
|
14
|
+
if (manifest.extensions === undefined) return destinations
|
|
15
|
+
|
|
16
|
+
for (const [name, declaration] of Object.entries(manifest.extensions)) {
|
|
17
|
+
const factory = instance(name, manifest.path)
|
|
18
|
+
|
|
19
|
+
if (factory.destination === undefined) continue
|
|
20
|
+
|
|
21
|
+
const destination = await factory.destination(manifest.locator, declaration, manifest)
|
|
22
|
+
|
|
23
|
+
if (destination !== undefined) destinations.push(destination)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return destinations
|
|
27
|
+
}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { instances } = require('./instances')
|
|
1
|
+
import { instances } from './instances.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
* @param {toa.core.bindings.Emitter} emitter
|
|
4
|
+
* @param {import('@toa.io/core/types').bindings.Emitter} emitter
|
|
7
5
|
* @param {string} label
|
|
8
|
-
* @
|
|
6
|
+
* @param {import('@toa.io/core').Locator} locator
|
|
7
|
+
* @returns {import('@toa.io/core/types').bindings.Emitter}
|
|
9
8
|
*/
|
|
10
|
-
const emitter = (emitter, label) => {
|
|
9
|
+
export const emitter = (emitter, label, locator) => {
|
|
11
10
|
let decorated = emitter
|
|
12
11
|
|
|
13
12
|
for (const factory of Object.values(instances)) {
|
|
14
|
-
if (factory.emitter !== undefined)
|
|
13
|
+
if (factory.emitter !== undefined)
|
|
14
|
+
decorated = factory.emitter(decorated, label, locator)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
return decorated
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
exports.emitter = emitter
|
package/src/extensions/index.js
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
exports.aspects = aspects
|
|
13
|
-
exports.component = component
|
|
14
|
-
exports.context = context
|
|
15
|
-
exports.emitter = emitter
|
|
16
|
-
exports.load = load
|
|
17
|
-
exports.receiver = receiver
|
|
18
|
-
exports.storage = storage
|
|
19
|
-
exports.tenants = tenants
|
|
1
|
+
export { aspects } from './aspects.js'
|
|
2
|
+
export { component } from './component.js'
|
|
3
|
+
export { context } from './context.js'
|
|
4
|
+
export { destinations } from './destinations.js'
|
|
5
|
+
export { emitter } from './emitter.js'
|
|
6
|
+
export { load } from './load.js'
|
|
7
|
+
export { manage } from './manage.js'
|
|
8
|
+
export { receiver } from './receiver.js'
|
|
9
|
+
export { storage } from './storage.js'
|
|
10
|
+
export { tenants } from './tenants.js'
|
package/src/extensions/load.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { resolve } = require('./resolve')
|
|
1
|
+
import { resolve } from './resolve.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* @param {toa.norm.Component} manifest
|
|
7
5
|
*/
|
|
8
|
-
const load = (manifest) => {
|
|
6
|
+
export const load = async (manifest) => {
|
|
9
7
|
if (manifest.extensions === undefined) return
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
await Promise.all(
|
|
10
|
+
Object.keys(manifest.extensions).map(
|
|
11
|
+
async (name) => await resolve(name, manifest.path)
|
|
12
|
+
)
|
|
13
|
+
)
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
exports.load = load
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { instances } from './instances.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {import('@toa.io/core').Connector} composition
|
|
5
|
+
* @returns {import('@toa.io/core').Connector}
|
|
6
|
+
*/
|
|
7
|
+
export const manage = (composition) => {
|
|
8
|
+
let managed = composition
|
|
9
|
+
|
|
10
|
+
for (const factory of Object.values(instances)) {
|
|
11
|
+
if (factory.manage !== undefined) managed = factory.manage(managed)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return managed
|
|
15
|
+
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { instances } = require('./instances')
|
|
1
|
+
import { instances } from './instances.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
* @param {toa.core.Receiver} receiver
|
|
7
|
-
* @param {toa.core.Locator} locator
|
|
8
|
-
* @returns {toa.core.Receiver}
|
|
4
|
+
* @param {import('@toa.io/core/types').Receiver} receiver
|
|
5
|
+
* @param {import('@toa.io/core').Locator} locator
|
|
6
|
+
* @returns {import('@toa.io/core/types').Receiver}
|
|
9
7
|
*/
|
|
10
|
-
const receiver = (receiver, locator) => {
|
|
8
|
+
export const receiver = (receiver, locator) => {
|
|
11
9
|
let decorated = receiver
|
|
12
10
|
|
|
13
11
|
for (const factory of Object.values(instances)) {
|
|
@@ -16,5 +14,3 @@ const receiver = (receiver, locator) => {
|
|
|
16
14
|
|
|
17
15
|
return decorated
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
exports.receiver = receiver
|
|
@@ -1,27 +1,76 @@
|
|
|
1
|
-
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
2
|
+
import { pathToFileURL } from 'node:url'
|
|
3
|
+
import { find } from '@toa.io/generic'
|
|
4
|
+
import * as boot from '../../src/index.js'
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
const boot = require('../..')
|
|
6
|
+
import { instances } from './instances.js'
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
// what `find` returns is a package directory, and a module is loaded by file
|
|
9
|
+
const require = createRequire(import.meta.url)
|
|
10
|
+
|
|
11
|
+
// an extension is loaded once, and what is remembered while it loads is the
|
|
12
|
+
// promise, so two components cannot each make a factory
|
|
13
|
+
const loading = {}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Loads an extension and remembers its factory.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} reference
|
|
19
|
+
* @param {string} base
|
|
20
|
+
* @returns {Promise<import('@toa.io/core/types').extensions.Factory>}
|
|
21
|
+
*/
|
|
22
|
+
export const resolve = async (reference, base = process.cwd()) => {
|
|
23
|
+
const path = find(pack(reference), base)
|
|
24
|
+
|
|
25
|
+
loading[path] ??= create(path)
|
|
26
|
+
instances[path] = await loading[path]
|
|
27
|
+
|
|
28
|
+
return keyed(instances[path], reference)
|
|
29
|
+
}
|
|
7
30
|
|
|
8
31
|
/**
|
|
32
|
+
* The factory of an extension already loaded. Everything that decorates what a
|
|
33
|
+
* component is made of runs after its extensions are loaded, and stays
|
|
34
|
+
* synchronous.
|
|
35
|
+
*
|
|
9
36
|
* @param {string} reference
|
|
10
37
|
* @param {string} base
|
|
11
|
-
* @returns {toa.core.extensions.Factory}
|
|
38
|
+
* @returns {import('@toa.io/core/types').extensions.Factory}
|
|
12
39
|
*/
|
|
13
|
-
const
|
|
14
|
-
const
|
|
40
|
+
export const instance = (reference, base = process.cwd()) => {
|
|
41
|
+
const factory = instances[find(pack(reference), base)]
|
|
15
42
|
|
|
16
|
-
if (
|
|
43
|
+
if (factory === undefined) throw new Error(`Extension '${reference}' is not loaded`)
|
|
17
44
|
|
|
18
|
-
return
|
|
45
|
+
return keyed(factory, reference)
|
|
19
46
|
}
|
|
20
47
|
|
|
21
|
-
|
|
22
|
-
|
|
48
|
+
/**
|
|
49
|
+
* `package#key` is a declaration a package claims beside its main one, and what the package's
|
|
50
|
+
* factory offers for that key answers for it — so a key is never taken for the package itself.
|
|
51
|
+
*
|
|
52
|
+
* @param {import('@toa.io/core/types').extensions.Factory} factory
|
|
53
|
+
* @param {string} reference
|
|
54
|
+
* @returns {import('@toa.io/core/types').extensions.Factory}
|
|
55
|
+
*/
|
|
56
|
+
const keyed = (factory, reference) => {
|
|
57
|
+
const key = reference.split('#')[1]
|
|
58
|
+
|
|
59
|
+
if (key === undefined) return factory
|
|
60
|
+
|
|
61
|
+
const claimed = factory.keys?.[key]
|
|
23
62
|
|
|
24
|
-
|
|
63
|
+
if (claimed === undefined)
|
|
64
|
+
throw new Error(`'${reference}' names a key its package does not claim`)
|
|
65
|
+
|
|
66
|
+
return claimed
|
|
25
67
|
}
|
|
26
68
|
|
|
27
|
-
|
|
69
|
+
/** The package a reference is of. */
|
|
70
|
+
const pack = (reference) => reference.split('#')[0]
|
|
71
|
+
|
|
72
|
+
const create = async (path) => {
|
|
73
|
+
const { Factory } = await import(pathToFileURL(require.resolve(path)).href)
|
|
74
|
+
|
|
75
|
+
return new Factory(boot.host())
|
|
76
|
+
}
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { instances } = require('./instances')
|
|
1
|
+
import { instances } from './instances.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
* @param {toa.core.Storage} storage
|
|
7
|
-
* @
|
|
4
|
+
* @param {import('@toa.io/core/types').storages.Storage} storage
|
|
5
|
+
* @param {import('@toa.io/core').Locator} locator whose storage it is
|
|
6
|
+
* @returns {import('@toa.io/core/types').storages.Storage}
|
|
8
7
|
*/
|
|
9
|
-
const storage = (storage) => {
|
|
8
|
+
export const storage = (storage, locator) => {
|
|
10
9
|
let decorated = storage
|
|
11
10
|
|
|
12
11
|
for (const factory of Object.values(instances)) {
|
|
13
|
-
if (factory.storage !== undefined) decorated = factory.storage(decorated)
|
|
12
|
+
if (factory.storage !== undefined) decorated = factory.storage(decorated, locator)
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
return decorated
|
|
17
16
|
}
|
|
18
|
-
|
|
19
|
-
exports.storage = storage
|
|
@@ -1,27 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { resolve } = require('./resolve')
|
|
1
|
+
import { resolve } from './resolve.js'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* @param {toa.norm.Component} manifest
|
|
7
|
-
* @returns {toa.core.Connector[]}
|
|
5
|
+
* @returns {import('@toa.io/core').Connector[]}
|
|
8
6
|
*/
|
|
9
|
-
const tenants = (manifest) => {
|
|
7
|
+
export const tenants = async (manifest) => {
|
|
10
8
|
const tenants = []
|
|
11
9
|
|
|
12
10
|
if (manifest.extensions === undefined) return tenants
|
|
13
11
|
|
|
14
12
|
for (const [name, declaration] of Object.entries(manifest.extensions)) {
|
|
15
|
-
const factory = resolve(name, manifest.path)
|
|
13
|
+
const factory = await resolve(name, manifest.path)
|
|
16
14
|
|
|
17
15
|
if (factory.tenant === undefined) continue
|
|
18
16
|
|
|
19
|
-
const tenant = factory.tenant(manifest.locator, declaration)
|
|
17
|
+
const tenant = await factory.tenant(manifest.locator, declaration, manifest)
|
|
20
18
|
|
|
21
19
|
tenants.push(tenant)
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
return tenants
|
|
25
23
|
}
|
|
26
|
-
|
|
27
|
-
exports.tenants = tenants
|
package/src/guards.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Guard } from '@toa.io/core'
|
|
2
|
+
import * as boot from './index.js'
|
|
3
|
+
|
|
4
|
+
export async function guards(manifest, context) {
|
|
5
|
+
if (manifest.guards === undefined) return
|
|
6
|
+
|
|
7
|
+
const entries = Object.entries(manifest.guards)
|
|
8
|
+
|
|
9
|
+
return await Promise.all(
|
|
10
|
+
entries.map(async ([name, guard]) => {
|
|
11
|
+
const bridge = await load(guard, name, context)
|
|
12
|
+
|
|
13
|
+
return new Guard(name, bridge)
|
|
14
|
+
})
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function load(guard, name, context) {
|
|
19
|
+
return await boot.bridge.guard(guard.bridge, guard.path, name, context)
|
|
20
|
+
}
|
package/src/host.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Gate } from '@toa.io/core'
|
|
2
|
+
|
|
3
|
+
import * as boot from './index.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {import('./workload.js').Workload} [workload] the process, where there is one
|
|
7
|
+
*
|
|
8
|
+
* What the process hosting an extension provides to it. The counterpart of a component's
|
|
9
|
+
* context: an extension reaches the core through this and through nothing else.
|
|
10
|
+
*
|
|
11
|
+
* @returns {import('@toa.io/core/types').extensions.Host}
|
|
12
|
+
*/
|
|
13
|
+
export const host = (workload) => ({
|
|
14
|
+
// an extension knows a version only where something told it one; see `Remotes` in exposition
|
|
15
|
+
remote: (locator, source, contract) => boot.remote(locator, source, { contract }),
|
|
16
|
+
broadcast: boot.bindings.broadcast,
|
|
17
|
+
composition: boot.composition,
|
|
18
|
+
receive: boot.receive,
|
|
19
|
+
atom: boot.atomicity,
|
|
20
|
+
outbound: boot.bindings.outbound,
|
|
21
|
+
inbound: boot.bindings.inbound,
|
|
22
|
+
|
|
23
|
+
// a composition booted outside a process — by a scenario, by `toa call` — has no workload, so
|
|
24
|
+
// its gates are ones nothing ever takes down and a halt asked of it is nobody's to perform
|
|
25
|
+
gate: (build) => workload?.gate(build) ?? new Gate(build),
|
|
26
|
+
quiesce: async () => await workload?.quiesce(),
|
|
27
|
+
cancel: async () => await workload?.cancel(),
|
|
28
|
+
stop: (seconds) => workload?.stop(seconds)
|
|
29
|
+
})
|
package/src/inbox.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether any operation of this component declares `once`, which is what decides that a place
|
|
3
|
+
* to record a call is made at all. Local to the manifest, unlike the events something consumes,
|
|
4
|
+
* so there is no variable a deployment computes.
|
|
5
|
+
*
|
|
6
|
+
* @param {toa.norm.Component} manifest
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
export const inbox = (manifest) =>
|
|
10
|
+
Object.values(manifest.operations ?? {}).some(
|
|
11
|
+
(definition) => definition.once === true || typeof definition.once === 'number'
|
|
12
|
+
)
|
package/src/index.js
CHANGED
|
@@ -1,36 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
// the environment is read at module scope elsewhere, so it is loaded first
|
|
2
|
+
export { load as env } from './env.js'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
export * as bindings from './bindings/index.js'
|
|
5
|
+
export * as bridge from './bridge.js'
|
|
6
|
+
export * as contract from './contract.js'
|
|
7
|
+
export * as extensions from './extensions/index.js'
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
exports.context = context
|
|
29
|
-
exports.emission = emission
|
|
30
|
-
exports.exposition = exposition
|
|
31
|
-
exports.manifest = manifest
|
|
32
|
-
exports.operation = operation
|
|
33
|
-
exports.receivers = receivers
|
|
34
|
-
exports.receive = receive
|
|
35
|
-
exports.remote = remote
|
|
36
|
-
exports.storage = storage
|
|
9
|
+
export { call } from './call.js'
|
|
10
|
+
export { cascade } from './cascade.js'
|
|
11
|
+
export { component } from './component.js'
|
|
12
|
+
export { composition } from './composition.js'
|
|
13
|
+
export { context } from './context.js'
|
|
14
|
+
export { emission } from './emission.js'
|
|
15
|
+
export { events } from './events.js'
|
|
16
|
+
export { inbox } from './inbox.js'
|
|
17
|
+
export { outbox } from './outbox.js'
|
|
18
|
+
export { atomicity } from './atomicity.js'
|
|
19
|
+
export { atom } from './atom.js'
|
|
20
|
+
export * as map from './map.js'
|
|
21
|
+
export { manifest } from './manifest.js'
|
|
22
|
+
export { operation } from './operation.js'
|
|
23
|
+
export { receivers, receive } from './receivers.js'
|
|
24
|
+
export { remote } from './remote.js'
|
|
25
|
+
export { rendering } from './rendering.js'
|
|
26
|
+
export { regional } from './regional.js'
|
|
27
|
+
export { storage } from './storage.js'
|
|
28
|
+
export { guards } from './guards.js'
|
|
29
|
+
export { host } from './host.js'
|
|
30
|
+
export { rc } from './rc.js'
|
|
31
|
+
export { Workload } from './workload.js'
|