@toa.io/userland 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.
Files changed (55) hide show
  1. package/CHANGELOG.md +322 -0
  2. package/example/components/echo/manifest.toa.yaml +14 -5
  3. package/example/components/echo/operations/get.js +1 -5
  4. package/example/components/echo/operations/resolve.js +1 -5
  5. package/example/components/echo/operations/signal.js +1 -5
  6. package/example/components/math.calculations/manifest.toa.yaml +17 -6
  7. package/example/components/math.calculations/operations/add.js +1 -5
  8. package/example/components/math.calculations/operations/increment.js +1 -5
  9. package/example/components/math.proxy/manifest.toa.yaml +8 -3
  10. package/example/components/math.proxy/operations/add.js +1 -5
  11. package/example/components/tea.pots/manifest.toa.yaml +37 -9
  12. package/example/components/tea.pots/operations/same.js +1 -5
  13. package/example/components/tea.pots/receivers/store.orders.created.js +1 -5
  14. package/example/components/web/manifest.toa.yaml +2 -4
  15. package/example/components/web/operations/get.js +2 -6
  16. package/example/context.toa.yaml +0 -5
  17. package/example/stage/call.test.js +14 -10
  18. package/example/stage/events.test.js +63 -16
  19. package/example/stage/invoke.test.js +11 -8
  20. package/package.json +18 -11
  21. package/stage/package.json +1 -0
  22. package/stage/src/component.js +3 -12
  23. package/stage/src/composition.js +3 -11
  24. package/stage/src/index.js +7 -17
  25. package/stage/src/manifest.js +2 -6
  26. package/stage/src/remote.js +11 -8
  27. package/stage/src/service.js +10 -9
  28. package/stage/src/shutdown.js +2 -8
  29. package/stage/src/state.js +1 -4
  30. package/stage/test/boot.mock.js +9 -11
  31. package/stage/test/component.test.js +16 -10
  32. package/stage/test/composition.test.js +11 -20
  33. package/stage/test/manifest.test.js +11 -8
  34. package/stage/test/remote.test.js +14 -12
  35. package/stage/test/shutdown.test.js +26 -22
  36. package/stage/test/state.mock.js +5 -6
  37. package/stage/test/state.test.js +10 -9
  38. package/stage/types/index.d.ts +0 -2
  39. package/stage/src/binding/binding.js +0 -50
  40. package/stage/src/binding/consumer.js +0 -32
  41. package/stage/src/binding/emitter.js +0 -27
  42. package/stage/src/binding/factory.js +0 -49
  43. package/stage/src/binding/index.js +0 -10
  44. package/stage/src/binding/label.js +0 -12
  45. package/stage/src/binding/producer.js +0 -43
  46. package/stage/src/binding/receiver.js +0 -34
  47. package/stage/test/binding/binding.test.js +0 -15
  48. package/stage/test/binding/consumer.test.js +0 -52
  49. package/stage/test/binding/emitter.test.js +0 -78
  50. package/stage/test/binding/producer.fixtures.js +0 -10
  51. package/stage/test/binding/producer.test.js +0 -49
  52. package/stage/test/binding/receiver.fixtures.js +0 -7
  53. package/stage/test/binding/receiver.test.js +0 -54
  54. package/stage/test/binding.mock.js +0 -8
  55. package/stage/types/binding.d.ts +0 -20
package/CHANGELOG.md ADDED
@@ -0,0 +1,322 @@
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
+ **Note:** Version bump only for package @toa.io/userland
9
+
10
+
11
+
12
+
13
+
14
+ # [1.0.0-alpha.279](https://github.com/toa-io/toa/compare/v1.0.0-alpha.278...v1.0.0-alpha.279) (2026-09-03)
15
+
16
+ ### Bug Fixes
17
+
18
+ * **userland:** let a TypeScript consumer find the declarations of `stage` ([c108cb5](https://github.com/toa-io/toa/commit/c108cb545d62204339b924f47f3863b8c40831d3))
19
+
20
+
21
+ # [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)
22
+
23
+ **Note:** Version bump only for package @toa.io/userland
24
+
25
+
26
+
27
+
28
+
29
+ # [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)
30
+
31
+ ### Bug Fixes
32
+
33
+ * settle what the module loader made asynchronous ([d4ab9df](https://github.com/toa-io/toa/commit/d4ab9dfb09e382da311dba08f52214e7645f4a6c))
34
+ * what the loader resolves, and what it will not ([1b8a02f](https://github.com/toa-io/toa/commit/1b8a02ff0a5e0f18ee62e3f71bc81116f86f9af1))
35
+
36
+
37
+ # [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)
38
+
39
+
40
+ * Configuration is served by a component, followed live, and kept per epoch (#1017) ([b05997d](https://github.com/toa-io/toa/commit/b05997d3adb784f238a222cb46878b23859339a2)), closes [#1017](https://github.com/toa-io/toa/issues/1017)
41
+
42
+
43
+ ### BREAKING CHANGES
44
+
45
+ * a secret configuration value is an object, not a string;
46
+ read it with `unwrap()`.
47
+
48
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
49
+
50
+ * test(configuration): wait for the second round rather than assume it
51
+
52
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
53
+
54
+ * refactor(configuration)!: read a secret with its own unwrap
55
+
56
+ Component code depends on no Toa package, so a secret is read as
57
+ `context.configuration.apiKey.unwrap()` and the helper in `@toa.io/generic`
58
+ goes. A value a component reads as a secret is therefore given as a reference:
59
+ `identity.basic` no longer defaults `pepper` to `''`, the development context
60
+ and the feature harness give the token keys, the federation client secret and
61
+ the signing key as references, and the harness has a step for the secrets a
62
+ scenario refers to. CONTRIBUTING states the rule.
63
+ * `identity.basic` `pepper` has no default; a value read as a
64
+ secret must be given as a `$NAME` reference.
65
+
66
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
67
+
68
+ * feat(configuration): list the configurations
69
+
70
+ `configuration.values.list` returns every component's configuration for its
71
+ deployed epoch, by component name, and `GET /configuration/values/` serves it
72
+ behind `system:configuration:get`.
73
+
74
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
75
+
76
+ * fix(exposition): write a value in YAML the way its toJSON says
77
+
78
+ A redacted secret in a reply was dumped as an empty object; it is written as
79
+ `<REDACTED>`, as JSON and msgpack already write it.
80
+
81
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
82
+
83
+ * test(configuration): a secret is an object, and stays redacted in a reply
84
+
85
+ A component with `{ a: 1, b: $SECRET_B }` returns its configuration as
86
+ `{ a: 1, b: '<REDACTED>' }` and the secret itself through `unwrap()`. The reply
87
+ step also accepts a reply as a caller across a process boundary receives it,
88
+ since a call within the process hands the object over as it is.
89
+
90
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
91
+
92
+ * chore(schemas): bump the dependencies
93
+
94
+ ajv 8.18.0 to 8.20.0, ajv-formats 2.1.1 to 3.0.1, better-ajv-errors 1.2.0
95
+ to 2.0.3, fast-glob 3.2.12 to 3.3.3 and js-yaml 4.3.1 to 5.4.1 — the version
96
+ exposition already uses. The three majors keep the CommonJS entry points this
97
+ library calls: ajv-formats as a function, better-ajv-errors as .default, and
98
+ js-yaml's load.
99
+
100
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
101
+
102
+ * feat(configuration)!: serve the schema with the value
103
+
104
+ GET /configuration/values/:component/ answers { configuration, schema, epoch }
105
+ where it answered with the configuration alone, and list carries the schema of
106
+ every component. Nothing reads a configuration without needing to know what it
107
+ is checked against, and the schema was only ever on the values service.
108
+
109
+ An epoch the deployment does not know has no schema; the value stored for it
110
+ is still returned.
111
+
112
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
113
+
114
+ * feat(configuration): publish a configuration UI
115
+
116
+ The values service serves a page at /.configuration on port 8003, out of the
117
+ directory ui builds: the configured components, a screen per component showing
118
+ what it holds now, and a dialog creating the next one. Reading needs
119
+ system:configuration:get and creating needs system:configuration:create.
120
+
121
+ A configuration is immutable, so the dialog opens on the current value and what
122
+ is left out of it is left out of the component. The editor takes YAML, the
123
+ schema is applied before anything is sent, and a secret is a reference the page
124
+ never shows.
125
+
126
+ The page is always published: the annotation is the per-component values map
127
+ and has nowhere to carry a switch.
128
+
129
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
130
+
131
+ * feat(introspection): link a component to its configuration
132
+
133
+ A card carrying @toa.io/extensions.configuration reads that extension as a link
134
+ to the configuration UI rather than as a name, and configuration joins the
135
+ namespaces the runtime provides, so its components band under System.
136
+
137
+ Deployed, both pages sit behind the same ingress and the path alone is right;
138
+ locally each console has its own port.
139
+
140
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
141
+
142
+ * feat(introspection): scroll the map, zoom with a modifier
143
+
144
+ The map was grabbed to move and zoomed with a bare wheel, which is neither what
145
+ a page does nor what the wheel does anywhere else. A plain scroll now pans on
146
+ both axes and the wheel scales only with the modifier held — a trackpad pinch
147
+ arrives as one of those on every platform.
148
+
149
+ A card's own scrollable box keeps its wheel, in both paths.
150
+
151
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
152
+
153
+ * refactor(introspection): centre the filter in the header
154
+
155
+ The sides take equal space, which is what leaves the filter between them.
156
+ Neither side may shrink under what it holds, or the tabs run out from under
157
+ their side and across the filter, and the filter across the sign-out button;
158
+ the title gives way instead.
159
+
160
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
161
+
162
+ * fix(configuration): connect the UI to the values service
163
+
164
+ The page was declared as a dependency from inside `open`, and a connector connects
165
+ what it depends on before `open` runs — so the server was constructed and never
166
+ listened. Nothing caught it: the UI feature builds the server itself.
167
+
168
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
169
+
170
+ * feat(configuration)!: reserve resources in the annotation
171
+
172
+ The values service deploys like any other and must state what it may take, but the
173
+ annotation is a map of component ids and had nowhere to put it — so `toa env` failed
174
+ for every context using configuration unless it declared a context-wide `resources`.
175
+
176
+ `resources` is now the service's own, read the way `introspection` and `realtime` read
177
+ theirs. A component actually named `resources` is written `default.resources`, which is
178
+ what its id is anyway.
179
+
180
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
181
+
182
+ * feat(configuration): follow the system colour scheme
183
+
184
+ The dark tokens were behind a `.dark` class nothing sets, and the `dark:` variant was
185
+ pointed at that class too — so a component's own dark styling never applied either.
186
+ Both now key off `prefers-color-scheme`, and `color-scheme` hands the native chrome
187
+ the same answer.
188
+
189
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
190
+
191
+ * feat(introspection): follow the system colour scheme
192
+
193
+ The dark tokens were behind a `.dark` class nothing sets, and the `dark:` variant was
194
+ pointed at that class too — so a component's own dark styling never applied either.
195
+ Both now key off `prefers-color-scheme`, and `color-scheme` hands the native chrome
196
+ the same answer.
197
+
198
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
199
+
200
+ * feat(configuration): present a change as an edit of what is there
201
+
202
+ A configuration is immutable and creating one replaces the whole of it, but the dialog
203
+ opens on the current value and the page never shows an older one — so what the reader
204
+ does is edit. The words follow: Edit rather than New, Update rather than Create, and
205
+ the paragraph explaining the model goes, along with the field's label, which the title
206
+ above it already said.
207
+
208
+ The editor also stayed as wide as its longest line — `field-sizing: content` sizes to
209
+ content, and no `max-width` clamps that — so a long value painted outside the dialog.
210
+ It is fixed now, the dialog takes the width the screen has rather than a fixed step,
211
+ and the band held for errors no longer leaves a gap when there are none.
212
+
213
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
214
+
215
+ * feat(configuration): mark a component that keeps a secret
216
+
217
+ A key after the name on the row, wherever the configuration holds a reference, however
218
+ deep. The predicate reads the same lines the value screen renders, so the two cannot
219
+ disagree about what counts as a secret.
220
+
221
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
222
+
223
+ * feat(configuration): lead back to the list from the title
224
+
225
+ Every address ends in a slash, so the way up is the address itself on the list and one
226
+ level above it on a component's screen — which holds wherever the page is mounted.
227
+
228
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
229
+
230
+
231
+
232
+
233
+
234
+ # [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)
235
+
236
+ **Note:** Version bump only for package @toa.io/userland
237
+
238
+
239
+
240
+
241
+
242
+ # [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)
243
+
244
+ **Note:** Version bump only for package @toa.io/userland
245
+
246
+
247
+
248
+
249
+
250
+ # [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)
251
+
252
+ **Note:** Version bump only for package @toa.io/userland
253
+
254
+
255
+
256
+
257
+
258
+ # [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)
259
+
260
+ **Note:** Version bump only for package @toa.io/userland
261
+
262
+
263
+
264
+
265
+
266
+ # [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)
267
+
268
+ **Note:** Version bump only for package @toa.io/userland
269
+
270
+
271
+
272
+
273
+
274
+ # [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)
275
+
276
+ **Note:** Version bump only for package @toa.io/userland
277
+
278
+
279
+
280
+
281
+
282
+ # [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)
283
+
284
+ **Note:** Version bump only for package @toa.io/userland
285
+
286
+
287
+
288
+
289
+
290
+ # [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)
291
+
292
+
293
+ ### Bug Fixes
294
+
295
+ * **stage:** name the feature suite as the caller ([e4e593b](https://github.com/toa-io/toa/commit/e4e593b795cc7dc113f06e8a1554ae2ef36442c0))
296
+
297
+
298
+
299
+
300
+
301
+ # [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)
302
+
303
+ **Note:** Version bump only for package @toa.io/userland
304
+
305
+
306
+
307
+
308
+
309
+ # [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)
310
+
311
+ **Note:** Version bump only for package @toa.io/userland
312
+
313
+
314
+
315
+
316
+
317
+ # [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)
318
+
319
+
320
+ ### Features
321
+
322
+ * add toa mono and discover components at components/* ([787a111](https://github.com/toa-io/toa/commit/787a111c8f83e56ebc734801c97106c585d034ea))
@@ -2,14 +2,23 @@ name: echo
2
2
 
3
3
  operations:
4
4
  signal:
5
- output: string
5
+ output:
6
+ type: string
6
7
  get:
7
- output: string
8
+ output:
9
+ type: string
8
10
  resolve:
9
- input: string
10
- output: string
11
+ input:
12
+ type: string
13
+ output:
14
+ type: string
11
15
 
12
16
  configuration:
13
- signal: quack
17
+ schema:
18
+ type: object
19
+ properties:
20
+ signal:
21
+ type: string
22
+ default: quack
14
23
 
15
24
  state: ~
@@ -1,7 +1,3 @@
1
- 'use strict'
2
-
3
- async function computation (_, context) {
1
+ export async function computation (_, context) {
4
2
  return context.state.value
5
3
  }
6
-
7
- exports.computation = computation
@@ -1,7 +1,3 @@
1
- 'use strict'
2
-
3
- async function computation (key, context) {
1
+ export async function computation (key, context) {
4
2
  return context.state.values.get(key)
5
3
  }
6
-
7
- exports.computation = computation
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- class Computation {
1
+ export class Computation {
4
2
  #context
5
3
 
6
4
  async mount (context) {
@@ -11,5 +9,3 @@ class Computation {
11
9
  return this.#context.configuration.signal
12
10
  }
13
11
  }
14
-
15
- exports.Computation = Computation
@@ -4,11 +4,22 @@ namespace: math
4
4
  operations:
5
5
  add:
6
6
  input:
7
- a: number
8
- b: number
9
- output: number
7
+ properties:
8
+ a:
9
+ type: number
10
+ b:
11
+ type: number
12
+ type: object
13
+ output:
14
+ type: number
10
15
  increment:
11
16
  input:
12
- value: number
13
- times: 1
14
- output: number
17
+ properties:
18
+ value:
19
+ type: number
20
+ times:
21
+ type: number
22
+ default: 1
23
+ type: object
24
+ output:
25
+ type: number
@@ -1,7 +1,3 @@
1
- 'use strict'
2
-
3
- async function computation (input) {
1
+ export async function computation (input) {
4
2
  return input.a + input.b
5
3
  }
6
-
7
- exports.computation = computation
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- async function computation (input, context) {
1
+ export async function computation (input, context) {
4
2
  let value = input.value
5
3
 
6
4
  for (let i = 0; i < input.times; i++) {
@@ -9,5 +7,3 @@ async function computation (input, context) {
9
7
 
10
8
  return value
11
9
  }
12
-
13
- exports.computation = computation
@@ -4,6 +4,11 @@ namespace: math
4
4
  operations:
5
5
  add:
6
6
  input:
7
- a: number
8
- b: number
9
- output: number
7
+ properties:
8
+ a:
9
+ type: number
10
+ b:
11
+ type: number
12
+ type: object
13
+ output:
14
+ type: number
@@ -1,10 +1,6 @@
1
- 'use strict'
2
-
3
- async function computation (input, context) {
1
+ export async function computation (input, context) {
4
2
  const request = { input }
5
3
 
6
4
  // noinspection JSUnresolvedVariable
7
5
  return context.remote.math.calculations.add(request)
8
6
  }
9
-
10
- exports.computation = computation
@@ -4,20 +4,43 @@ namespace: tea
4
4
  entity:
5
5
  storage: mongodb
6
6
  schema:
7
- material*: [ glass, ceramic, steel ]
8
- volume: number
9
- booked: false
7
+ properties:
8
+ volume:
9
+ type: number
10
+ booked:
11
+ type: boolean
12
+ default: false
13
+ material:
14
+ type: string
15
+ enum:
16
+ - glass
17
+ - ceramic
18
+ - steel
19
+ type: object
20
+ required:
21
+ - material
10
22
 
11
23
  operations:
12
24
  transit:
13
25
  concurrency: none
14
26
  input:
15
- material: .
16
- volume: .
17
- booked: .
27
+ properties:
28
+ material:
29
+ type: string
30
+ default: .
31
+ volume:
32
+ type: string
33
+ default: .
34
+ booked:
35
+ type: string
36
+ default: .
37
+ type: object
18
38
  same:
19
- input: .material
20
- output: array
39
+ input:
40
+ type: string
41
+ default: .material
42
+ output:
43
+ type: array
21
44
 
22
45
  receivers:
23
46
  store.orders.created:
@@ -25,4 +48,9 @@ receivers:
25
48
  binding: amqp # avoid discovery
26
49
 
27
50
  configuration:
28
- step: 0.5
51
+ schema:
52
+ type: object
53
+ properties:
54
+ step:
55
+ type: number
56
+ default: 0.5
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- async function computation (input, context) {
1
+ export async function computation (input, context) {
4
2
  const criteria = `material==${input}`
5
3
  const query = { criteria, limit }
6
4
 
@@ -9,5 +7,3 @@ async function computation (input, context) {
9
7
  }
10
8
 
11
9
  const limit = 10
12
-
13
- exports.computation = computation
@@ -1,8 +1,4 @@
1
- 'use strict'
2
-
3
- const request = async (payload) => ({
1
+ export const request = async (payload) => ({
4
2
  input: { booked: true },
5
3
  query: { id: payload.pot }
6
4
  })
7
-
8
- exports.request = request
@@ -2,7 +2,5 @@ name: web
2
2
 
3
3
  operations:
4
4
  get:
5
- output: object
6
-
7
- origins:
8
- dev: http://api.example.com
5
+ output:
6
+ type: object
@@ -1,7 +1,5 @@
1
- 'use strict'
2
-
3
- async function computation (_, context) {
4
- const response = await context.http.dev.path.to.resource.get()
1
+ export async function computation (_, context) {
2
+ const response = await context.fetch('http://api.example.com/path/to/resource')
5
3
  const type = response.headers.get('content-type')
6
4
 
7
5
  if (type !== 'application/json')
@@ -11,5 +9,3 @@ async function computation (_, context) {
11
9
  }
12
10
 
13
11
  const ERR_UNSUPPORTED_MEDIA_TYPE = new Error('UNSUPPORTED_MEDIA_TYPE')
14
-
15
- exports.computation = computation
@@ -1,10 +1,5 @@
1
1
  name: examples
2
- packages: components/*
3
2
  registry: example
4
3
 
5
4
  amqp: amqp://localhost
6
5
  mongodb: mongodb://localhost
7
-
8
- origins:
9
- default.web:
10
- dev: http://localhost
@@ -1,16 +1,21 @@
1
- 'use strict'
1
+ import { it, before, after } from 'node:test'
2
+ import assert from 'node:assert/strict'
2
3
 
3
- const { resolve } = require('node:path')
4
- const { exceptions: { RequestContractException } } = require('@toa.io/core')
5
- const stage = require('@toa.io/userland/stage')
4
+ import { resolve } from 'node:path'
5
+ import { exceptions } from '@toa.io/core'
6
+ import * as stage from '@toa.io/userland/stage'
6
7
 
7
- const root = resolve(__dirname, '../components')
8
+ const { RequestContractException } = exceptions
9
+
10
+ const root = resolve(import.meta.dirname, '../components')
8
11
 
9
12
  let echo
10
13
  let math
11
14
 
12
- beforeAll(async () => {
15
+ before(async () => {
13
16
  process.env.TOA_DEV = '1'
17
+ process.env.TOA_CONFIGURATION_DEFAULT_ECHO = '{}'
18
+ process.env.TOA_CONFIGURATION_TEA_POTS = '{}'
14
19
 
15
20
  const paths = ['echo', 'math.calculations'].map((rel) => resolve(root, rel))
16
21
 
@@ -20,7 +25,7 @@ beforeAll(async () => {
20
25
  math = await stage.remote('math.calculations')
21
26
  })
22
27
 
23
- afterAll(async () => {
28
+ after(async () => {
24
29
  await stage.shutdown()
25
30
 
26
31
  delete process.env.TOA_DEV
@@ -29,13 +34,12 @@ afterAll(async () => {
29
34
  it('should call endpoint', async () => {
30
35
  const reply = await echo.invoke('signal', {})
31
36
 
32
- expect(reply).toStrictEqual('quack')
37
+ assert.deepStrictEqual(reply, 'quack')
33
38
  })
34
39
 
35
40
  it('should throw on invalid input', async () => {
36
41
  const a = 'not a number'
37
42
  const b = 'neither'
38
43
 
39
- await expect(math.invoke('add', { input: { a, b } }))
40
- .rejects.toBeInstanceOf(RequestContractException)
44
+ await assert.rejects(math.invoke('add', { input: { a, b } }), (error) => { assert.ok(error instanceof RequestContractException); return true })
41
45
  })