@toa.io/boot 1.0.0-alpha.3 → 1.0.0-alpha.300
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 +124 -0
- package/package.json +12 -11
- 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 +8 -9
- package/src/cascade.js +16 -10
- package/src/component.js +83 -25
- package/src/composition.js +104 -15
- package/src/context.js +7 -8
- package/src/contract.js +11 -12
- package/src/discovery.js +29 -18
- 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 +17 -0
- package/src/inbox.js +10 -0
- package/src/index.js +52 -32
- package/src/manifest.js +80 -34
- package/src/manifest.test.js +85 -8
- package/src/operation.js +25 -13
- package/src/outbox.js +22 -0
- package/src/rc.js +5 -0
- package/src/receivers.js +35 -21
- package/src/remote.js +38 -17
- package/src/span.js +19 -0
- package/src/storage.js +51 -32
- package/src/storage.test.js +57 -0
- package/src/workload.js +84 -0
- package/types/bindings.d.ts +6 -2
- package/types/index.d.ts +24 -10
- package/types/manifest.d.ts +5 -4
- package/src/exposition.js +0 -17
package/src/receivers.js
CHANGED
|
@@ -1,34 +1,51 @@
|
|
|
1
|
-
|
|
1
|
+
import { Receiver, Locator } from '@toa.io/core'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import * as boot from './index.js'
|
|
4
|
+
import * as extensions from './extensions/index.js'
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
-
const extensions = require('./extensions')
|
|
7
|
-
|
|
8
|
-
const receivers = async (manifest, runtime) => {
|
|
6
|
+
export const receivers = async (manifest, component) => {
|
|
9
7
|
if (manifest.receivers === undefined) return []
|
|
10
8
|
|
|
11
9
|
const receivers = []
|
|
12
|
-
const local = await boot.remote(manifest.locator, manifest)
|
|
10
|
+
const local = await boot.remote(manifest.locator, undefined, manifest)
|
|
13
11
|
|
|
14
12
|
for (const [label, definition] of Object.entries(manifest.receivers)) {
|
|
15
|
-
const bridge = definition.bridge !== undefined ? boot.bridge.receiver(definition.bridge, manifest.path, label) : undefined
|
|
16
|
-
const receiver = new Receiver(definition, local, bridge)
|
|
17
|
-
const decorator = extensions.receiver(receiver, manifest.locator)
|
|
18
|
-
|
|
19
13
|
const locator = Locator.parse(label)
|
|
20
|
-
const transport = definition.binding ?? await resolveBinding(locator, label)
|
|
21
14
|
const source = definition.source ? Locator.parse(definition.source) : locator
|
|
22
|
-
const
|
|
15
|
+
const event = label.split('.').pop()
|
|
16
|
+
const destination = `${source.id}.${event}`
|
|
17
|
+
|
|
18
|
+
// the origin of the calls this receiver makes to its local operation
|
|
19
|
+
const origin = { namespace: source.namespace, component: source.name, event }
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
const bridge =
|
|
22
|
+
definition.bridge !== undefined
|
|
23
|
+
? await boot.bridge.receiver(definition.bridge, manifest.path, label)
|
|
24
|
+
: undefined
|
|
25
|
+
const receiver = new Receiver(
|
|
26
|
+
{ ...definition, label, destination, origin },
|
|
27
|
+
local,
|
|
28
|
+
bridge
|
|
29
|
+
)
|
|
30
|
+
const decorator = extensions.receiver(receiver, manifest.locator)
|
|
31
|
+
|
|
32
|
+
const transport = definition.binding ?? (await resolveBinding(locator, label))
|
|
33
|
+
const binding = await boot.bindings.receive(
|
|
34
|
+
transport,
|
|
35
|
+
source,
|
|
36
|
+
label,
|
|
37
|
+
manifest.locator.id,
|
|
38
|
+
decorator
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
binding.depends(component)
|
|
25
42
|
receivers.push(binding)
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
return receivers
|
|
29
46
|
}
|
|
30
47
|
|
|
31
|
-
async function receive
|
|
48
|
+
export async function receive(label, group, callback) {
|
|
32
49
|
if (callback === undefined) {
|
|
33
50
|
callback = group
|
|
34
51
|
group = undefined
|
|
@@ -37,21 +54,18 @@ async function receive (label, group, callback) {
|
|
|
37
54
|
const locator = Locator.parse(label)
|
|
38
55
|
const transport = await resolveBinding(locator, label)
|
|
39
56
|
|
|
40
|
-
return boot.bindings.receive(transport, locator, label, group, callback)
|
|
57
|
+
return await boot.bindings.receive(transport, locator, label, group, callback)
|
|
41
58
|
}
|
|
42
59
|
|
|
43
60
|
/**
|
|
44
|
-
* @param {toa.core.Locator} locator
|
|
61
|
+
* @param {import('@toa.io/core').Locator} locator
|
|
45
62
|
* @param {string} label
|
|
46
63
|
* @return {Promise<string>}
|
|
47
64
|
*/
|
|
48
|
-
async function resolveBinding
|
|
65
|
+
async function resolveBinding(locator, label) {
|
|
49
66
|
const event = label.split('.').pop()
|
|
50
67
|
const discovery = await boot.discovery.discovery()
|
|
51
68
|
const { events } = await discovery.lookup(locator)
|
|
52
69
|
|
|
53
70
|
return events[event].binding
|
|
54
71
|
}
|
|
55
|
-
|
|
56
|
-
exports.receivers = receivers
|
|
57
|
-
exports.receive = receive
|
package/src/remote.js
CHANGED
|
@@ -1,25 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { console } from 'openspan'
|
|
2
|
+
import { Remote } from '@toa.io/core'
|
|
3
|
+
import { remap } from '@toa.io/generic'
|
|
4
|
+
|
|
5
|
+
import * as boot from './index.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {import('@toa.io/core').Locator} locator
|
|
9
|
+
* @param {import('@toa.io/core/types').Source} [source] the origin stamped on every call made through this remote
|
|
10
|
+
* @param {toa.norm.Component} [manifest] skips discovery when the manifest is already known
|
|
11
|
+
*/
|
|
12
|
+
export const remote = async (locator, source, manifest) => {
|
|
13
|
+
let discovery
|
|
14
|
+
|
|
15
|
+
if (manifest === undefined) {
|
|
16
|
+
console.debug('Lookup', { locator: locator.id })
|
|
17
|
+
|
|
18
|
+
discovery = await boot.discovery.discovery(locator)
|
|
19
|
+
manifest = await discovery.lookup(locator)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// a call binds its consumers, which are loaded rather than required
|
|
23
|
+
const calls =
|
|
24
|
+
manifest.operations === undefined
|
|
25
|
+
? {}
|
|
26
|
+
: await settle(
|
|
27
|
+
remap(manifest.operations, (definition, endpoint) =>
|
|
28
|
+
boot.call(locator, endpoint, definition, manifest.entity, source)
|
|
29
|
+
)
|
|
30
|
+
)
|
|
16
31
|
|
|
17
32
|
const remote = new Remote(locator, calls)
|
|
18
33
|
|
|
19
34
|
// ensure discovery shutdown
|
|
20
|
-
remote.depends(discovery)
|
|
35
|
+
if (discovery !== undefined) remote.depends(discovery)
|
|
21
36
|
|
|
22
37
|
return remote
|
|
23
38
|
}
|
|
24
39
|
|
|
25
|
-
|
|
40
|
+
/** An object whose values are promises, as an object of what they resolve to. */
|
|
41
|
+
async function settle(object) {
|
|
42
|
+
const entries = Object.entries(object)
|
|
43
|
+
const values = await Promise.all(entries.map(([, promise]) => promise))
|
|
44
|
+
|
|
45
|
+
return Object.fromEntries(entries.map(([key], index) => [key, values[index]]))
|
|
46
|
+
}
|
package/src/span.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { console, traces } from 'openspan'
|
|
2
|
+
import { environment } from '@toa.io/generic'
|
|
3
|
+
|
|
4
|
+
const enabled = environment.get('TOA_BOOT_TRACE') === '1'
|
|
5
|
+
|
|
6
|
+
// Tracing is off until an exporter is configured, and the CLI opens its own span before
|
|
7
|
+
// any extension gets to configure one — so asking for a boot trace turns the console
|
|
8
|
+
// exporter on here. Extensions keep it: see `development()` in the telemetry factory.
|
|
9
|
+
if (enabled) traces({ exporters: { console: {} } })
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a span if boot tracing is enabled (TOA_BOOT_TRACE=1), otherwise just runs the task
|
|
13
|
+
*
|
|
14
|
+
* @param {string | object} options
|
|
15
|
+
* @param {() => Promise<any>} task
|
|
16
|
+
* @returns {Promise<any>}
|
|
17
|
+
*/
|
|
18
|
+
export const span = async (options, task) =>
|
|
19
|
+
enabled ? console.span(options, task) : task()
|
package/src/storage.js
CHANGED
|
@@ -1,41 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
2
|
+
import { pathToFileURL } from 'node:url'
|
|
3
|
+
import * as extensions from './extensions/index.js'
|
|
4
|
+
|
|
5
|
+
// import.meta.resolve takes no paths, and the connector is resolved against the
|
|
6
|
+
// component that names it
|
|
7
|
+
const require = createRequire(import.meta.url)
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {toa.norm.Component} manifest
|
|
11
|
+
* @param {boolean} outbox whether this component publishes anything, and so needs a place to
|
|
12
|
+
* commit it with the entity
|
|
13
|
+
* @param {boolean} inbox whether any of its operations declares `once`, and so needs a place to
|
|
14
|
+
* record the call it commits
|
|
15
|
+
*/
|
|
16
|
+
export const storage = async (manifest, outbox, inbox) => {
|
|
7
17
|
if (manifest.entity === undefined) return
|
|
8
18
|
|
|
9
|
-
const
|
|
19
|
+
const Factory = await load(manifest)
|
|
10
20
|
|
|
11
|
-
/** @type {toa.core.storages.Factory} */
|
|
21
|
+
/** @type {import('@toa.io/core/types').storages.Factory} */
|
|
12
22
|
const factory = new Factory()
|
|
13
|
-
const storage = factory.storage(manifest.locator,
|
|
14
|
-
|
|
15
|
-
|
|
23
|
+
const storage = factory.storage(manifest.locator, manifest.entity, { outbox, inbox })
|
|
24
|
+
|
|
25
|
+
// a component whose structure nothing will make must not start with the structure it lacks;
|
|
26
|
+
// what it inherits was written for descendants that store, and one that stores nothing has
|
|
27
|
+
// nothing to convert
|
|
28
|
+
const own = manifest.entity.migrations?.some(
|
|
29
|
+
(migration) => migration.prototype === undefined
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if (own === true && storage.migrates !== true)
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Component '${manifest.locator.id}' declares migrations, ` +
|
|
35
|
+
`which storage '${manifest.entity.storage}' does not apply`
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* Refused here rather than degraded: a storage that cannot record a call would run every
|
|
40
|
+
* duplicate of it, which is what declaring `once` asked not to happen. Whether the deployment
|
|
41
|
+
* can commit one is the storage's own to refuse, once it is connected.
|
|
42
|
+
*/
|
|
43
|
+
if (inbox && storage.claims !== true)
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Component '${manifest.locator.id}' declares 'once', ` +
|
|
46
|
+
`which storage '${manifest.entity.storage}' does not provide`
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return extensions.storage(storage, manifest.locator)
|
|
16
50
|
}
|
|
17
51
|
|
|
18
|
-
function load
|
|
52
|
+
async function load(component) {
|
|
19
53
|
const reference = component.entity.storage
|
|
20
|
-
const path = require.resolve(reference, {
|
|
21
|
-
|
|
54
|
+
const path = require.resolve(reference, {
|
|
55
|
+
paths: [component.path, import.meta.dirname]
|
|
56
|
+
})
|
|
57
|
+
const { Factory } = await import(pathToFileURL(path).href)
|
|
22
58
|
|
|
23
|
-
|
|
24
|
-
const properties = pkg === null ? null : component.properties?.[pkg.name]
|
|
25
|
-
|
|
26
|
-
return [Factory, properties]
|
|
59
|
+
return Factory
|
|
27
60
|
}
|
|
28
|
-
|
|
29
|
-
function loadPackageJson (root, reference) {
|
|
30
|
-
const packageJson = join(reference, 'package.json')
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const path = require.resolve(packageJson, { paths: [root, __dirname] })
|
|
34
|
-
|
|
35
|
-
return require(path)
|
|
36
|
-
} catch (e) {
|
|
37
|
-
return null
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
exports.storage = storage
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { it } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
|
|
4
|
+
import { Locator } from '@toa.io/core'
|
|
5
|
+
|
|
6
|
+
import { storage } from './storage.js'
|
|
7
|
+
|
|
8
|
+
const manifest = (entity) => ({
|
|
9
|
+
locator: new Locator('one', 'test'),
|
|
10
|
+
path: import.meta.dirname,
|
|
11
|
+
entity
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const schema = { properties: {} }
|
|
15
|
+
|
|
16
|
+
it('should not create a storage for a component that stores nothing', async () => {
|
|
17
|
+
assert.equal(await storage(manifest(undefined), false), undefined)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should refuse migrations a storage does not apply', async () => {
|
|
21
|
+
const entity = {
|
|
22
|
+
schema,
|
|
23
|
+
storage: '@toa.io/storages.null',
|
|
24
|
+
migrations: [{ id: '0001', steps: [] }]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
await assert.rejects(
|
|
28
|
+
storage(manifest(entity), false),
|
|
29
|
+
/declares migrations, which storage '@toa.io\/storages.null' does not apply/
|
|
30
|
+
)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('should accept inherited migrations a storage does not apply', async () => {
|
|
34
|
+
const entity = {
|
|
35
|
+
schema,
|
|
36
|
+
storage: '@toa.io/storages.null',
|
|
37
|
+
migrations: [{ id: 'system:0001', steps: [], prototype: 'system' }]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
assert.notEqual(await storage(manifest(entity), false), undefined)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('should accept a storage with no migrations', async () => {
|
|
44
|
+
const entity = { schema, storage: '@toa.io/storages.null' }
|
|
45
|
+
|
|
46
|
+
assert.notEqual(await storage(manifest(entity), false), undefined)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('should accept migrations a storage applies', async () => {
|
|
50
|
+
const entity = {
|
|
51
|
+
schema,
|
|
52
|
+
storage: '@toa.io/storages.mongodb',
|
|
53
|
+
migrations: [{ id: '0001', steps: [] }]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
assert.notEqual(await storage(manifest(entity), false), undefined)
|
|
57
|
+
})
|
package/src/workload.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Connector } from '@toa.io/core'
|
|
2
|
+
import { PREDEFINED } from '@toa.io/definitions'
|
|
3
|
+
|
|
4
|
+
import { resolve } from './extensions/resolve.js'
|
|
5
|
+
import { host } from './host.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A process, as a connector.
|
|
9
|
+
*
|
|
10
|
+
* What it holds is in two parts. Its *residents* are what the extensions keep in every process
|
|
11
|
+
* whatever it runs — the readiness probe is the one there is — and they connect before
|
|
12
|
+
* everything else and go last. The rest is what the command built.
|
|
13
|
+
*
|
|
14
|
+
* Which is what a process had no name for before: `toa compose`, `toa serve` and `toa mono`
|
|
15
|
+
* each assembled a root out of a bare `Connector` and their own arithmetic, and an extension
|
|
16
|
+
* with something to put in a process had nowhere to put it.
|
|
17
|
+
*/
|
|
18
|
+
export class Workload extends Connector {
|
|
19
|
+
/** @type {(workload: Workload) => Promise<import('@toa.io/core').Connector>} */
|
|
20
|
+
#build
|
|
21
|
+
|
|
22
|
+
/** @type {import('@toa.io/core/types').extensions.Resident[]} */
|
|
23
|
+
#residents = []
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {(workload: Workload) => Promise<import('@toa.io/core').Connector>} build
|
|
27
|
+
* what the command runs, called once
|
|
28
|
+
*/
|
|
29
|
+
constructor(build) {
|
|
30
|
+
super()
|
|
31
|
+
|
|
32
|
+
this.#build = build
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async open() {
|
|
36
|
+
/*
|
|
37
|
+
* Connected here rather than declared as dependencies, because what they are is read from
|
|
38
|
+
* the extensions and a connector's dependencies are walked before `open` runs. The probe
|
|
39
|
+
* goes up before the build so that it answers while the build is still happening.
|
|
40
|
+
*/
|
|
41
|
+
this.#residents = await residents()
|
|
42
|
+
|
|
43
|
+
for (const resident of this.#residents) {
|
|
44
|
+
this.depends(resident)
|
|
45
|
+
|
|
46
|
+
await resident.connect()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const root = await this.#build(this)
|
|
50
|
+
|
|
51
|
+
this.depends(root)
|
|
52
|
+
|
|
53
|
+
await root.connect()
|
|
54
|
+
|
|
55
|
+
for (const resident of this.#residents) await resident.complete?.()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* What the extensions this process has loaded keep in it.
|
|
61
|
+
*
|
|
62
|
+
* The predefined ones are loaded here rather than left to whichever component happens to
|
|
63
|
+
* reference them: what a resident answers for is the process, and a process that runs no
|
|
64
|
+
* component of its own must have one all the same.
|
|
65
|
+
*
|
|
66
|
+
* @returns {Promise<import('@toa.io/core/types').extensions.Resident[]>}
|
|
67
|
+
*/
|
|
68
|
+
async function residents() {
|
|
69
|
+
const { instances } = await import('./extensions/instances.js')
|
|
70
|
+
|
|
71
|
+
await Promise.all(Object.keys(PREDEFINED).map(async (name) => await resolve(name)))
|
|
72
|
+
|
|
73
|
+
const residents = []
|
|
74
|
+
|
|
75
|
+
for (const factory of Object.values(instances)) {
|
|
76
|
+
if (factory.resident === undefined) continue
|
|
77
|
+
|
|
78
|
+
const resident = await factory.resident(host())
|
|
79
|
+
|
|
80
|
+
if (resident !== null && resident !== undefined) residents.push(resident)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return residents
|
|
84
|
+
}
|
package/types/bindings.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import type { bindings } from '@toa.io/core'
|
|
1
|
+
import type { bindings } from '@toa.io/core/types'
|
|
2
2
|
|
|
3
|
-
export function broadcast
|
|
3
|
+
export function broadcast<T>(
|
|
4
|
+
name: string,
|
|
5
|
+
group?: string,
|
|
6
|
+
binding?: string
|
|
7
|
+
): bindings.Broadcast<T>
|
package/types/index.d.ts
CHANGED
|
@@ -1,21 +1,35 @@
|
|
|
1
|
-
import * as core from '@toa.io/core'
|
|
2
|
-
import * as
|
|
1
|
+
import type * as core from '@toa.io/core'
|
|
2
|
+
import type * as types from '@toa.io/core/types'
|
|
3
|
+
import * as composition from './composition.js'
|
|
3
4
|
|
|
4
|
-
export * as bindings from './bindings'
|
|
5
|
+
export * as bindings from './bindings.js'
|
|
5
6
|
|
|
6
|
-
export async function composition
|
|
7
|
+
export async function composition(
|
|
8
|
+
paths: string[],
|
|
9
|
+
options?: composition.Options
|
|
10
|
+
): Promise<core.Connector>
|
|
7
11
|
|
|
8
|
-
export async function remote
|
|
12
|
+
export async function remote(
|
|
13
|
+
locator: core.Locator,
|
|
14
|
+
source?: types.Source
|
|
15
|
+
): Promise<core.Remote>
|
|
9
16
|
|
|
10
|
-
export async function receive<T = any>
|
|
17
|
+
export async function receive<T = any>(
|
|
11
18
|
label: string,
|
|
12
|
-
receiver: Receiver
|
|
19
|
+
receiver: Receiver
|
|
13
20
|
): Promise<core.Connector>
|
|
14
21
|
|
|
15
|
-
export async function receive<T = any>
|
|
22
|
+
export async function receive<T = any>(
|
|
16
23
|
label: string,
|
|
17
24
|
group: string | undefined,
|
|
18
|
-
receiver: Receiver
|
|
25
|
+
receiver: Receiver
|
|
19
26
|
): Promise<core.Connector>
|
|
20
27
|
|
|
21
|
-
type Receiver = { receive: (message:
|
|
28
|
+
type Receiver = { receive: (message: types.Message<T>) => void | Promise<void> }
|
|
29
|
+
|
|
30
|
+
export function host(): types.extensions.Host
|
|
31
|
+
|
|
32
|
+
/** A process, as a connector: what the command built, and what the extensions keep in one. */
|
|
33
|
+
export class Workload extends core.Connector {
|
|
34
|
+
constructor(build: (workload: Workload) => Promise<core.Connector>)
|
|
35
|
+
}
|
package/types/manifest.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as _norm from '@toa.io/norm/types'
|
|
2
|
-
import * as _composition from './composition'
|
|
2
|
+
import * as _composition from './composition.js'
|
|
3
3
|
|
|
4
4
|
declare namespace toa.boot {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
type Manifest = (
|
|
6
|
+
path: string,
|
|
7
|
+
options?: _composition.Options
|
|
8
|
+
) => Promise<_norm.Component>
|
|
8
9
|
}
|
package/src/exposition.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Exposition, Locator } = require('@toa.io/core')
|
|
4
|
-
|
|
5
|
-
const boot = require('./index')
|
|
6
|
-
|
|
7
|
-
const exposition = async (manifest) => {
|
|
8
|
-
const locator = new Locator('', '')
|
|
9
|
-
const exposition = new Exposition(locator, manifest)
|
|
10
|
-
const producers = boot.bindings.expose(exposition)
|
|
11
|
-
|
|
12
|
-
await Promise.all(producers.map((producer) => producer.connect()))
|
|
13
|
-
|
|
14
|
-
return producers
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
exports.exposition = exposition
|