@toa.io/core 1.0.0-alpha.287 → 1.0.0-alpha.289
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 +19 -0
- package/package.json +4 -4
- package/source/connector.ts +50 -4
- package/source/context.ts +3 -2
- package/source/contract/request.ts +56 -1
- package/source/operation.ts +2 -1
- package/source/outbox/outbox.ts +3 -2
- package/source/types/storages.ts +6 -1
- package/test/connector.fixtures.js +14 -0
- package/test/connector.test.js +56 -0
- package/transpiled/connector.js +53 -11
- package/transpiled/connector.js.map +1 -1
- package/transpiled/context.js +3 -2
- package/transpiled/context.js.map +1 -1
- package/transpiled/contract/request.d.ts +6 -1
- package/transpiled/contract/request.js +45 -1
- package/transpiled/contract/request.js.map +1 -1
- package/transpiled/operation.js +2 -1
- package/transpiled/operation.js.map +1 -1
- package/transpiled/outbox/outbox.js +3 -2
- package/transpiled/outbox/outbox.js.map +1 -1
- package/transpiled/types/storages.d.ts +6 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
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.289](https://github.com/toa-io/toa/compare/v1.0.0-alpha.288...v1.0.0-alpha.289) (2026-09-07)
|
|
7
|
+
|
|
8
|
+
* 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)
|
|
9
|
+
|
|
10
|
+
### BREAKING CHANGES
|
|
11
|
+
|
|
12
|
+
* a component that read `process.env.TOA_*` reads `context` instead;
|
|
13
|
+
`echo(input)` no longer substitutes from the environment; a bash operation sees no
|
|
14
|
+
`TOA_*`; images no longer set `USER node` — see migrations/289.md.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [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)
|
|
18
|
+
|
|
19
|
+
**Note:** Version bump only for package @toa.io/core
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
6
25
|
# [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)
|
|
7
26
|
|
|
8
27
|
**Note:** Version bump only for package @toa.io/core
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/core",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.289",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Toa Core",
|
|
6
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@rsql/parser": "1.6.0",
|
|
37
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
38
|
-
"@toa.io/schemas": "1.0.0-alpha.
|
|
37
|
+
"@toa.io/generic": "1.0.0-alpha.289",
|
|
38
|
+
"@toa.io/schemas": "1.0.0-alpha.289",
|
|
39
39
|
"openspan": "1.0.0-alpha.286",
|
|
40
40
|
"uuid": "14.0.2"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "4fcb482beac5896305d8084cdbc1d5fcf372d108"
|
|
43
43
|
}
|
package/source/connector.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { console } from 'openspan'
|
|
2
|
+
import { environment } from '@toa.io/generic'
|
|
2
3
|
import type { Locator } from './locator.js'
|
|
3
4
|
|
|
4
5
|
/** Abstract connections hierarchy */
|
|
@@ -7,6 +8,7 @@ export class Connector {
|
|
|
7
8
|
#links: Connector[] = []
|
|
8
9
|
#connecting: Promise<void> | undefined
|
|
9
10
|
#disconnecting: Promise<void> | undefined
|
|
11
|
+
#discarded: boolean = false
|
|
10
12
|
|
|
11
13
|
public readonly id: string
|
|
12
14
|
public connected: boolean = false
|
|
@@ -40,9 +42,30 @@ export class Connector {
|
|
|
40
42
|
this.#dependencies.push(next)
|
|
41
43
|
next.link(this)
|
|
42
44
|
|
|
45
|
+
// See .#discard()
|
|
46
|
+
if (this.#disconnecting !== undefined) next.#discard()
|
|
47
|
+
|
|
43
48
|
return next
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Disconnects, now and again if a connection is still to land.
|
|
53
|
+
*
|
|
54
|
+
* A dependency taken on after its dependant was disconnected — a lookup that returns
|
|
55
|
+
* once the teardown walk has gone by — is one nothing is left to take down, as the
|
|
56
|
+
* walk that would have reached it is over. One that stays connected holds open
|
|
57
|
+
* everything it depends on with it: a dependency reads `connected` of every dependant
|
|
58
|
+
* before it closes, and a dependant that is connected for good is a dependency that
|
|
59
|
+
* never closes.
|
|
60
|
+
*/
|
|
61
|
+
#discard(): void {
|
|
62
|
+
this.#discarded = true
|
|
63
|
+
|
|
64
|
+
// one that is up already, or on its way, is taken down here; one that is not is
|
|
65
|
+
// taken down by the connection when it comes, and until then there is nothing to do
|
|
66
|
+
if (this.#connecting !== undefined) void this.#drop()
|
|
67
|
+
}
|
|
68
|
+
|
|
46
69
|
/**
|
|
47
70
|
* Creates a backlink to another Connector
|
|
48
71
|
*
|
|
@@ -72,7 +95,7 @@ export class Connector {
|
|
|
72
95
|
}
|
|
73
96
|
|
|
74
97
|
// anonymous grouping nodes are not worth a span
|
|
75
|
-
|
|
98
|
+
const connecting =
|
|
76
99
|
TRACE_BOOT && this.constructor.name !== 'Connector'
|
|
77
100
|
? console.span(
|
|
78
101
|
{
|
|
@@ -84,13 +107,36 @@ export class Connector {
|
|
|
84
107
|
)
|
|
85
108
|
: work()
|
|
86
109
|
|
|
110
|
+
this.#connecting = connecting
|
|
111
|
+
|
|
87
112
|
try {
|
|
88
|
-
await
|
|
89
|
-
|
|
113
|
+
await connecting
|
|
114
|
+
|
|
115
|
+
/*
|
|
116
|
+
* A disconnection that did not wait for this connection emptied `#connecting` to
|
|
117
|
+
* say so. Reporting `connected` now would report it of a connector nothing takes
|
|
118
|
+
* down again — its `#disconnecting` has settled, so a later call returns at once —
|
|
119
|
+
* and what it depends on reads that of every dependant before it closes.
|
|
120
|
+
*/
|
|
121
|
+
if (this.#connecting === connecting) this.connected = true
|
|
90
122
|
} catch (e) {
|
|
91
123
|
await this.disconnect(true)
|
|
92
124
|
throw e
|
|
93
125
|
}
|
|
126
|
+
|
|
127
|
+
// a connection asked for before this one was discarded, landing after. See .#discard()
|
|
128
|
+
if (this.#discarded) await this.#drop()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Disconnects a discarded connector, saying so rather than throwing at whoever is not waiting. */
|
|
132
|
+
async #drop(): Promise<void> {
|
|
133
|
+
this.#discarded = false
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
await this.disconnect()
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('Discarded connector failed to disconnect', { id: this.id, error })
|
|
139
|
+
}
|
|
94
140
|
}
|
|
95
141
|
|
|
96
142
|
/**
|
|
@@ -168,4 +214,4 @@ export class Connector {
|
|
|
168
214
|
}
|
|
169
215
|
|
|
170
216
|
const DELAY = 5000
|
|
171
|
-
const TRACE_BOOT =
|
|
217
|
+
const TRACE_BOOT = environment.get('TOA_BOOT_TRACE') === '1'
|
package/source/context.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Connector } from './connector.js'
|
|
2
|
+
import { environment } from '@toa.io/generic'
|
|
2
3
|
import type { Locator } from './locator.js'
|
|
3
4
|
import type { Component } from './component.js'
|
|
4
5
|
import type { Remote } from './remote.js'
|
|
@@ -20,8 +21,8 @@ export class Context extends Connector {
|
|
|
20
21
|
public constructor(local: Component, discover: Discover, aspects: Aspect[] = []) {
|
|
21
22
|
super()
|
|
22
23
|
|
|
23
|
-
this.env =
|
|
24
|
-
this.name =
|
|
24
|
+
this.env = environment.get('TOA_ENV')
|
|
25
|
+
this.name = environment.get('TOA_CONTEXT')
|
|
25
26
|
this.aspects = aspects
|
|
26
27
|
this.locator = local?.locator
|
|
27
28
|
|
|
@@ -19,18 +19,37 @@ export interface Definition extends Explanation {
|
|
|
19
19
|
query?: boolean
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/** What the operation works on, as the manifest declares it. */
|
|
23
|
+
export interface Entity {
|
|
24
|
+
properties: Record<string, JSONSchema>
|
|
25
|
+
required?: string[]
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
export class Request extends Contract {
|
|
23
29
|
public readonly discovery: Explanation = {}
|
|
24
30
|
|
|
25
31
|
public static override Exception: Refusal =
|
|
26
32
|
RequestContractException as unknown as Refusal
|
|
27
33
|
|
|
28
|
-
public constructor(schema: Schema, definition: Definition) {
|
|
34
|
+
public constructor(schema: Schema, definition: Definition, entity?: Entity) {
|
|
29
35
|
super(schema)
|
|
30
36
|
|
|
31
37
|
for (const key of ['description', 'input', 'output', 'errors'] as const)
|
|
32
38
|
if (definition[key] !== undefined)
|
|
33
39
|
(this.discovery as Record<string, unknown>)[key] = definition[key]
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* An operation that states no output states an empty schema, which every reply fits —
|
|
43
|
+
* and which says nothing to whoever reads it. What its type answers does, so that is
|
|
44
|
+
* said here instead. Here and not in the definition, because the definition is what a
|
|
45
|
+
* reply is held to: a projection is a lawful answer, and describing one is not the same
|
|
46
|
+
* as requiring it.
|
|
47
|
+
*/
|
|
48
|
+
if (empty(this.discovery.output)) {
|
|
49
|
+
const answered = answers(definition, entity)
|
|
50
|
+
|
|
51
|
+
if (answered !== undefined) this.discovery.output = answered
|
|
52
|
+
}
|
|
34
53
|
}
|
|
35
54
|
|
|
36
55
|
public static schema(
|
|
@@ -83,3 +102,39 @@ export class Request extends Contract {
|
|
|
83
102
|
return schema
|
|
84
103
|
}
|
|
85
104
|
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* What an operation of this type answers, where it did not say.
|
|
108
|
+
*
|
|
109
|
+
* A transition, an observation and an assignment work on the Entity Object, so that is what
|
|
110
|
+
* they answer — a set of them where the scope is a set. A computation neither uses the scope
|
|
111
|
+
* nor produces one, and an effect answers whatever it computed, so neither is guessed at.
|
|
112
|
+
* A stream is not a value with a schema, and is not one either.
|
|
113
|
+
*
|
|
114
|
+
* What the entity requires is said as well. It is a description and nothing is held to it —
|
|
115
|
+
* an operation answering a projection says so by declaring its own output — and a shape
|
|
116
|
+
* whose every property reads as optional says less than it knows.
|
|
117
|
+
*/
|
|
118
|
+
function answers(definition: Definition, entity?: Entity): JSONSchema | undefined {
|
|
119
|
+
if (entity === undefined || !ENTITY.has(definition.type as string)) return undefined
|
|
120
|
+
|
|
121
|
+
const object: JSONSchema = {
|
|
122
|
+
type: 'object',
|
|
123
|
+
properties: entity.properties,
|
|
124
|
+
...(entity.required === undefined ? {} : { required: entity.required })
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (definition.scope === 'objects') return { type: 'array', items: object } as JSONSchema
|
|
128
|
+
|
|
129
|
+
return definition.scope === 'object' || definition.scope === 'changeset'
|
|
130
|
+
? object
|
|
131
|
+
: undefined
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** The types whose subject is the Entity Object; see `documentation/design.md`. */
|
|
135
|
+
const ENTITY = new Set(['transition', 'observation', 'assignment'])
|
|
136
|
+
|
|
137
|
+
/** A schema that states nothing, which is what an operation saying nothing normalizes to. */
|
|
138
|
+
function empty(schema: JSONSchema | null | undefined): boolean {
|
|
139
|
+
return schema === undefined || schema === null || Object.keys(schema).length === 0
|
|
140
|
+
}
|
package/source/operation.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Readable } from 'node:stream'
|
|
2
2
|
import { Connector } from './connector.js'
|
|
3
3
|
import { SystemException, RequestContractException } from './exceptions.js'
|
|
4
|
+
import { environment } from '@toa.io/generic'
|
|
4
5
|
import type { Cascade } from './cascade.js'
|
|
5
6
|
import type { State } from './state.js'
|
|
6
7
|
import type { Query as Translator } from './query.js'
|
|
@@ -116,7 +117,7 @@ export class Operation extends Connector {
|
|
|
116
117
|
const reply = await this.#cascade.run(request.input, state)
|
|
117
118
|
|
|
118
119
|
// validate reply only on local environments
|
|
119
|
-
if (
|
|
120
|
+
if (environment.get('TOA_ENV') === 'local' && !(reply instanceof Readable))
|
|
120
121
|
this.#contracts.reply.fit(reply)
|
|
121
122
|
|
|
122
123
|
store.reply = reply
|
package/source/outbox/outbox.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { console } from 'openspan'
|
|
2
2
|
import { Connector } from '../connector.js'
|
|
3
3
|
import { newid } from '../entities/newid.js'
|
|
4
|
+
import { environment } from '@toa.io/generic'
|
|
4
5
|
import type { Emission } from '../emission.js'
|
|
5
6
|
import type { Atom } from '../types/atomicity.js'
|
|
6
7
|
import type { Storage } from '../types/storages.js'
|
|
@@ -64,7 +65,7 @@ export class Outbox extends Connector {
|
|
|
64
65
|
this.#interval = number('TOA_OUTBOX_INTERVAL', options.interval, INTERVAL)
|
|
65
66
|
this.#batch = number('TOA_OUTBOX_BATCH', options.batch, BATCH)
|
|
66
67
|
this.#gap = options.gap ?? this.#interval * K
|
|
67
|
-
this.#defer =
|
|
68
|
+
this.#defer = environment.get('TOA_OUTBOX_DEFER') === '1'
|
|
68
69
|
|
|
69
70
|
this.depends(emission)
|
|
70
71
|
this.depends(atom)
|
|
@@ -304,7 +305,7 @@ function number(
|
|
|
304
305
|
): number {
|
|
305
306
|
if (declared !== undefined) return declared
|
|
306
307
|
|
|
307
|
-
const value = Number(
|
|
308
|
+
const value = Number(environment.get(variable))
|
|
308
309
|
|
|
309
310
|
return Number.isNaN(value) || value <= 0 ? fallback : value
|
|
310
311
|
}
|
package/source/types/storages.ts
CHANGED
|
@@ -113,10 +113,15 @@ export interface Entity {
|
|
|
113
113
|
migrations?: Migration[]
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* One file of a `migrations` directory, named after it — the component's own, or a prototype's,
|
|
118
|
+
* which every descendant applies to its collection ahead of its own.
|
|
119
|
+
*/
|
|
117
120
|
export interface Migration {
|
|
118
121
|
id: string
|
|
119
122
|
steps: unknown[]
|
|
123
|
+
/** the prototype it is inherited from; absent on the component's own */
|
|
124
|
+
prototype?: string
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
export interface StorageOptions {
|
|
@@ -34,6 +34,20 @@ export class FailingConnector extends Connector {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/** Stands for a connector whose connection lands once it has been disconnected. */
|
|
38
|
+
export class LateConnector extends Connector {
|
|
39
|
+
#arrive
|
|
40
|
+
|
|
41
|
+
async open() {
|
|
42
|
+
await new Promise((resolve) => (this.#arrive = resolve))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Lets the connection land. */
|
|
46
|
+
arrive() {
|
|
47
|
+
this.#arrive()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
37
51
|
/** Stands for a connector waiting for something that never arrives. */
|
|
38
52
|
export class StuckConnector extends Connector {
|
|
39
53
|
async open() {
|
package/test/connector.test.js
CHANGED
|
@@ -180,6 +180,62 @@ describe('dependencies', () => {
|
|
|
180
180
|
assert.deepStrictEqual(sequence, ['+b', '-b', '*b', '*a'])
|
|
181
181
|
})
|
|
182
182
|
|
|
183
|
+
it('should disconnect a dependency taken on after disconnection', async () => {
|
|
184
|
+
a.depends(b)
|
|
185
|
+
|
|
186
|
+
await a.connect()
|
|
187
|
+
await a.disconnect()
|
|
188
|
+
|
|
189
|
+
// what a lookup that returns once the teardown walk has gone by amounts to
|
|
190
|
+
a.depends(c)
|
|
191
|
+
|
|
192
|
+
await c.connect()
|
|
193
|
+
|
|
194
|
+
assert.strictEqual(c.connected, false)
|
|
195
|
+
assert.ok(sequence.indexOf('*c') > sequence.indexOf('*a'))
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('should disconnect a connected dependency taken on after disconnection', async () => {
|
|
199
|
+
a.depends(b)
|
|
200
|
+
|
|
201
|
+
await a.connect()
|
|
202
|
+
await a.disconnect()
|
|
203
|
+
await c.connect()
|
|
204
|
+
|
|
205
|
+
a.depends(c)
|
|
206
|
+
|
|
207
|
+
// the discarding is not something the caller waits for
|
|
208
|
+
for (let i = 0; c.connected && i < 100; i++) await timeout(1)
|
|
209
|
+
|
|
210
|
+
assert.strictEqual(c.connected, false)
|
|
211
|
+
assert.ok(sequence.includes('*c'))
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
it('should not connect what was disconnected while connecting', async () => {
|
|
215
|
+
const late = new fixtures.LateConnector()
|
|
216
|
+
|
|
217
|
+
late.depends(c)
|
|
218
|
+
b.depends(c)
|
|
219
|
+
|
|
220
|
+
await b.connect()
|
|
221
|
+
|
|
222
|
+
const connecting = late.connect()
|
|
223
|
+
|
|
224
|
+
await late.disconnect()
|
|
225
|
+
|
|
226
|
+
late.arrive()
|
|
227
|
+
|
|
228
|
+
await connecting
|
|
229
|
+
|
|
230
|
+
// the connection landed after the disconnection, and nothing is left to say it again
|
|
231
|
+
assert.strictEqual(late.connected, false)
|
|
232
|
+
|
|
233
|
+
await b.disconnect()
|
|
234
|
+
|
|
235
|
+
assert.strictEqual(c.connected, false)
|
|
236
|
+
assert.ok(sequence.includes('*c'))
|
|
237
|
+
})
|
|
238
|
+
|
|
183
239
|
describe('errors', () => {
|
|
184
240
|
let f
|
|
185
241
|
|
package/transpiled/connector.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { console } from 'openspan';
|
|
2
|
+
import { environment } from '@toa.io/generic';
|
|
2
3
|
/** Abstract connections hierarchy */
|
|
3
4
|
export class Connector {
|
|
4
5
|
#dependencies = [];
|
|
5
6
|
#links = [];
|
|
6
7
|
#connecting;
|
|
7
8
|
#disconnecting;
|
|
9
|
+
#discarded = false;
|
|
8
10
|
id;
|
|
9
11
|
connected = false;
|
|
10
12
|
constructor() {
|
|
@@ -35,8 +37,28 @@ export class Connector {
|
|
|
35
37
|
next = connector;
|
|
36
38
|
this.#dependencies.push(next);
|
|
37
39
|
next.link(this);
|
|
40
|
+
// See .#discard()
|
|
41
|
+
if (this.#disconnecting !== undefined)
|
|
42
|
+
next.#discard();
|
|
38
43
|
return next;
|
|
39
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Disconnects, now and again if a connection is still to land.
|
|
47
|
+
*
|
|
48
|
+
* A dependency taken on after its dependant was disconnected — a lookup that returns
|
|
49
|
+
* once the teardown walk has gone by — is one nothing is left to take down, as the
|
|
50
|
+
* walk that would have reached it is over. One that stays connected holds open
|
|
51
|
+
* everything it depends on with it: a dependency reads `connected` of every dependant
|
|
52
|
+
* before it closes, and a dependant that is connected for good is a dependency that
|
|
53
|
+
* never closes.
|
|
54
|
+
*/
|
|
55
|
+
#discard() {
|
|
56
|
+
this.#discarded = true;
|
|
57
|
+
// one that is up already, or on its way, is taken down here; one that is not is
|
|
58
|
+
// taken down by the connection when it comes, and until then there is nothing to do
|
|
59
|
+
if (this.#connecting !== undefined)
|
|
60
|
+
void this.#drop();
|
|
61
|
+
}
|
|
40
62
|
/**
|
|
41
63
|
* Creates a backlink to another Connector
|
|
42
64
|
*
|
|
@@ -63,22 +85,42 @@ export class Connector {
|
|
|
63
85
|
await this.open();
|
|
64
86
|
};
|
|
65
87
|
// anonymous grouping nodes are not worth a span
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
88
|
+
const connecting = TRACE_BOOT && this.constructor.name !== 'Connector'
|
|
89
|
+
? console.span({
|
|
90
|
+
name: `connect ${this.constructor.name}`,
|
|
91
|
+
// a connector that has a locator is named by it; a grouping node has none
|
|
92
|
+
attributes: { id: this.locator?.id ?? this.id }
|
|
93
|
+
}, work)
|
|
94
|
+
: work();
|
|
95
|
+
this.#connecting = connecting;
|
|
74
96
|
try {
|
|
75
|
-
await
|
|
76
|
-
|
|
97
|
+
await connecting;
|
|
98
|
+
/*
|
|
99
|
+
* A disconnection that did not wait for this connection emptied `#connecting` to
|
|
100
|
+
* say so. Reporting `connected` now would report it of a connector nothing takes
|
|
101
|
+
* down again — its `#disconnecting` has settled, so a later call returns at once —
|
|
102
|
+
* and what it depends on reads that of every dependant before it closes.
|
|
103
|
+
*/
|
|
104
|
+
if (this.#connecting === connecting)
|
|
105
|
+
this.connected = true;
|
|
77
106
|
}
|
|
78
107
|
catch (e) {
|
|
79
108
|
await this.disconnect(true);
|
|
80
109
|
throw e;
|
|
81
110
|
}
|
|
111
|
+
// a connection asked for before this one was discarded, landing after. See .#discard()
|
|
112
|
+
if (this.#discarded)
|
|
113
|
+
await this.#drop();
|
|
114
|
+
}
|
|
115
|
+
/** Disconnects a discarded connector, saying so rather than throwing at whoever is not waiting. */
|
|
116
|
+
async #drop() {
|
|
117
|
+
this.#discarded = false;
|
|
118
|
+
try {
|
|
119
|
+
await this.disconnect();
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.error('Discarded connector failed to disconnect', { id: this.id, error });
|
|
123
|
+
}
|
|
82
124
|
}
|
|
83
125
|
/**
|
|
84
126
|
* Disconnects self then dependants
|
|
@@ -139,5 +181,5 @@ export class Connector {
|
|
|
139
181
|
dispose() { }
|
|
140
182
|
}
|
|
141
183
|
const DELAY = 5000;
|
|
142
|
-
const TRACE_BOOT =
|
|
184
|
+
const TRACE_BOOT = environment.get('TOA_BOOT_TRACE') === '1';
|
|
143
185
|
//# sourceMappingURL=connector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../source/connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../source/connector.ts"],"names":[],"mappings":"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"}
|
package/transpiled/context.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Connector } from './connector.js';
|
|
2
|
+
import { environment } from '@toa.io/generic';
|
|
2
3
|
export class Context extends Connector {
|
|
3
4
|
env;
|
|
4
5
|
name;
|
|
@@ -9,8 +10,8 @@ export class Context extends Connector {
|
|
|
9
10
|
#remotes = {};
|
|
10
11
|
constructor(local, discover, aspects = []) {
|
|
11
12
|
super();
|
|
12
|
-
this.env =
|
|
13
|
-
this.name =
|
|
13
|
+
this.env = environment.get('TOA_ENV');
|
|
14
|
+
this.name = environment.get('TOA_CONTEXT');
|
|
14
15
|
this.aspects = aspects;
|
|
15
16
|
this.locator = local?.locator;
|
|
16
17
|
this.#local = local;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../source/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../source/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAS7C,MAAM,OAAO,OAAQ,SAAQ,SAAS;IACpB,GAAG,CAAoB;IACvB,IAAI,CAAoB;IACxB,OAAO,CAAU;IACjB,OAAO,CAAS;IAEvB,MAAM,CAAW;IACjB,SAAS,CAAU;IACnB,QAAQ,GAAoC,EAAE,CAAA;IAEvD,YAAmB,KAAgB,EAAE,QAAkB,EAAE,OAAO,GAAa,EAAE;QAC7E,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACrC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,KAAK,EAAE,OAAO,CAAA;QAE7B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;QAEzB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAEnB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/C,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,OAAgB;QACnD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;IAED,sCAAsC;IAC/B,KAAK,CAAC,IAAI,CACf,SAAiB,EACjB,IAAY,EACZ,QAAgB,EAChB,OAAgB;QAEhB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAElD,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACzC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAiB,EAAE,IAAY;QAC3C,MAAM,GAAG,GAAG,SAAS,GAAG,GAAG,GAAG,IAAI,CAAA;QAElC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAErD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,IAAY;QAC5C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QAEpD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAEpB,OAAO,MAAM,CAAA;IACf,CAAC;CACF"}
|
|
@@ -14,10 +14,15 @@ export interface Definition extends Explanation {
|
|
|
14
14
|
scope?: string;
|
|
15
15
|
query?: boolean;
|
|
16
16
|
}
|
|
17
|
+
/** What the operation works on, as the manifest declares it. */
|
|
18
|
+
export interface Entity {
|
|
19
|
+
properties: Record<string, JSONSchema>;
|
|
20
|
+
required?: string[];
|
|
21
|
+
}
|
|
17
22
|
export declare class Request extends Contract {
|
|
18
23
|
readonly discovery: Explanation;
|
|
19
24
|
static Exception: Refusal;
|
|
20
|
-
constructor(schema: Schema, definition: Definition);
|
|
25
|
+
constructor(schema: Schema, definition: Definition, entity?: Entity);
|
|
21
26
|
static schema(definition: Definition, entity?: {
|
|
22
27
|
properties: Record<string, JSONSchema>;
|
|
23
28
|
}): JSONSchema;
|
|
@@ -4,11 +4,23 @@ import { Contract } from './contract.js';
|
|
|
4
4
|
export class Request extends Contract {
|
|
5
5
|
discovery = {};
|
|
6
6
|
static Exception = RequestContractException;
|
|
7
|
-
constructor(schema, definition) {
|
|
7
|
+
constructor(schema, definition, entity) {
|
|
8
8
|
super(schema);
|
|
9
9
|
for (const key of ['description', 'input', 'output', 'errors'])
|
|
10
10
|
if (definition[key] !== undefined)
|
|
11
11
|
this.discovery[key] = definition[key];
|
|
12
|
+
/*
|
|
13
|
+
* An operation that states no output states an empty schema, which every reply fits —
|
|
14
|
+
* and which says nothing to whoever reads it. What its type answers does, so that is
|
|
15
|
+
* said here instead. Here and not in the definition, because the definition is what a
|
|
16
|
+
* reply is held to: a projection is a lawful answer, and describing one is not the same
|
|
17
|
+
* as requiring it.
|
|
18
|
+
*/
|
|
19
|
+
if (empty(this.discovery.output)) {
|
|
20
|
+
const answered = answers(definition, entity);
|
|
21
|
+
if (answered !== undefined)
|
|
22
|
+
this.discovery.output = answered;
|
|
23
|
+
}
|
|
12
24
|
}
|
|
13
25
|
static schema(definition, entity) {
|
|
14
26
|
// `source` is not among these: the framework stamps it and whoever reads it takes the keys
|
|
@@ -56,4 +68,36 @@ export class Request extends Contract {
|
|
|
56
68
|
return schema;
|
|
57
69
|
}
|
|
58
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* What an operation of this type answers, where it did not say.
|
|
73
|
+
*
|
|
74
|
+
* A transition, an observation and an assignment work on the Entity Object, so that is what
|
|
75
|
+
* they answer — a set of them where the scope is a set. A computation neither uses the scope
|
|
76
|
+
* nor produces one, and an effect answers whatever it computed, so neither is guessed at.
|
|
77
|
+
* A stream is not a value with a schema, and is not one either.
|
|
78
|
+
*
|
|
79
|
+
* What the entity requires is said as well. It is a description and nothing is held to it —
|
|
80
|
+
* an operation answering a projection says so by declaring its own output — and a shape
|
|
81
|
+
* whose every property reads as optional says less than it knows.
|
|
82
|
+
*/
|
|
83
|
+
function answers(definition, entity) {
|
|
84
|
+
if (entity === undefined || !ENTITY.has(definition.type))
|
|
85
|
+
return undefined;
|
|
86
|
+
const object = {
|
|
87
|
+
type: 'object',
|
|
88
|
+
properties: entity.properties,
|
|
89
|
+
...(entity.required === undefined ? {} : { required: entity.required })
|
|
90
|
+
};
|
|
91
|
+
if (definition.scope === 'objects')
|
|
92
|
+
return { type: 'array', items: object };
|
|
93
|
+
return definition.scope === 'object' || definition.scope === 'changeset'
|
|
94
|
+
? object
|
|
95
|
+
: undefined;
|
|
96
|
+
}
|
|
97
|
+
/** The types whose subject is the Entity Object; see `documentation/design.md`. */
|
|
98
|
+
const ENTITY = new Set(['transition', 'observation', 'assignment']);
|
|
99
|
+
/** A schema that states nothing, which is what an operation saying nothing normalizes to. */
|
|
100
|
+
function empty(schema) {
|
|
101
|
+
return schema === undefined || schema === null || Object.keys(schema).length === 0;
|
|
102
|
+
}
|
|
59
103
|
//# sourceMappingURL=request.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../source/contract/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../source/contract/request.ts"],"names":[],"mappings":"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"}
|
package/transpiled/operation.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Readable } from 'node:stream';
|
|
2
2
|
import { Connector } from './connector.js';
|
|
3
3
|
import { SystemException, RequestContractException } from './exceptions.js';
|
|
4
|
+
import { environment } from '@toa.io/generic';
|
|
4
5
|
export class Operation extends Connector {
|
|
5
6
|
scope;
|
|
6
7
|
/**
|
|
@@ -62,7 +63,7 @@ export class Operation extends Connector {
|
|
|
62
63
|
const { request, state } = store;
|
|
63
64
|
const reply = await this.#cascade.run(request.input, state);
|
|
64
65
|
// validate reply only on local environments
|
|
65
|
-
if (
|
|
66
|
+
if (environment.get('TOA_ENV') === 'local' && !(reply instanceof Readable))
|
|
66
67
|
this.#contracts.reply.fit(reply);
|
|
67
68
|
store.reply = reply;
|
|
68
69
|
}
|