@toa.io/userland 0.10.0 → 0.20.0-alpha.0

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 (68) hide show
  1. package/example/.env +9 -0
  2. package/example/components/echo/manifest.toa.yaml +7 -0
  3. package/example/components/echo/operations/get.js +7 -0
  4. package/example/components/echo/operations/resolve.js +7 -0
  5. package/example/components/echo/operations/signal.js +11 -3
  6. package/example/components/echo/samples/get.yaml +12 -0
  7. package/example/components/echo/samples/signal.yaml +0 -3
  8. package/example/components/math.calculations/operations/increment.js +1 -3
  9. package/example/components/math.calculations/samples/add.yaml +1 -2
  10. package/example/components/math.calculations/samples/assets/ab.yaml +2 -0
  11. package/example/components/math.calculations/samples/increment.yaml +3 -6
  12. package/example/components/tea.pots/manifest.toa.yaml +2 -2
  13. package/example/components/web/manifest.toa.yaml +8 -0
  14. package/example/components/web/operations/get.js +14 -0
  15. package/example/components/web/samples/get.yaml +8 -0
  16. package/example/context.toa.yaml +7 -0
  17. package/example/stage/call.test.js +5 -4
  18. package/example/stage/events.test.js +6 -3
  19. package/example/stage/invoke.test.js +4 -0
  20. package/package.json +10 -9
  21. package/samples/notes.md +2 -2
  22. package/samples/readme.md +74 -8
  23. package/samples/src/.replay/.suite/component.js +3 -8
  24. package/samples/src/.replay/.suite/operation.js +1 -1
  25. package/samples/src/.replay/.suite/operations.js +5 -3
  26. package/samples/src/.replay/.suite/translate/.operation/.prepare/cast.js +20 -0
  27. package/samples/src/.replay/.suite/translate/.operation/.prepare/cast.test.js +94 -0
  28. package/samples/src/.replay/.suite/translate/.operation/.prepare/expand.js +14 -0
  29. package/samples/src/.replay/.suite/translate/.operation/.prepare/index.js +7 -0
  30. package/samples/src/.replay/.suite/translate/.operation/.prepare/shortcuts/.aspect.js +26 -0
  31. package/samples/src/.replay/.suite/translate/.operation/.prepare/shortcuts/configuration.js +5 -0
  32. package/samples/src/.replay/.suite/translate/.operation/.prepare/shortcuts/http.js +5 -0
  33. package/samples/src/.replay/.suite/translate/.operation/.prepare/shortcuts/index.js +9 -0
  34. package/samples/src/.replay/.suite/translate/.operation/.prepare/shortcuts/state.js +5 -0
  35. package/samples/src/.replay/.suite/translate/.operation/.prepare/types/async.js +3 -0
  36. package/samples/src/.replay/.suite/translate/.operation/.prepare/types/cast.js +26 -0
  37. package/samples/src/.replay/.suite/translate/.operation/.prepare/types/index.js +5 -0
  38. package/samples/src/.replay/.suite/translate/.operation/.prepare/types/map.js +3 -0
  39. package/samples/src/.replay/.suite/translate/.operation/.prepare/types/set.js +3 -0
  40. package/samples/src/.replay/.suite/translate/.operation/.prepare/types/sync.js +3 -0
  41. package/samples/src/.replay/.suite/translate/.operation/prepare.js +4 -4
  42. package/samples/src/.replay/index.js +2 -0
  43. package/samples/src/.replay/stage.js +60 -0
  44. package/samples/src/.replay/suite.js +3 -2
  45. package/samples/src/.replay/test.js +5 -3
  46. package/samples/src/components.js +1 -1
  47. package/samples/src/context.js +2 -2
  48. package/samples/src/replay.js +4 -5
  49. package/samples/src/suite/components.js +3 -3
  50. package/samples/test/components.test.js +2 -2
  51. package/samples/test/context.test.js +2 -2
  52. package/samples/test/replay.test.js +108 -72
  53. package/samples/test/replay.translate.message.test.js +2 -6
  54. package/samples/test/replay.translate.operation.test.js +1 -1
  55. package/samples/test/stage.mock.js +10 -14
  56. package/samples/test/suite.components.test.js +5 -31
  57. package/samples/types/operation.d.ts +2 -2
  58. package/samples/types/replay.d.ts +3 -3
  59. package/samples/types/suite.d.ts +5 -2
  60. package/stage/src/binding/binding.js +14 -13
  61. package/stage/src/component.js +7 -2
  62. package/stage/src/index.js +0 -3
  63. package/stage/test/component.test.js +1 -1
  64. package/stage/types/index.d.ts +2 -1
  65. package/example/components/tea.pots/samples/messages/store.orders.created.yaml +0 -37
  66. package/samples/src/.replay/.suite/translate/.operation/specials/configuration.js +0 -26
  67. package/samples/src/.replay/.suite/translate/.operation/specials/index.js +0 -5
  68. package/samples/test/replay.fixtures.js +0 -72
@@ -34,7 +34,7 @@ it('should define suite as autonomous', async () => {
34
34
  expect(suite.autonomous).toStrictEqual(true)
35
35
  })
36
36
 
37
- it('should load component samples', async () => {
37
+ it('should load operation samples', async () => {
38
38
  const expected = await operations()
39
39
 
40
40
  expect(Object.keys(suite.operations)).toStrictEqual([component])
@@ -47,12 +47,6 @@ it('should load component samples', async () => {
47
47
  expect(set.undo).toStrictEqual(expected.undo)
48
48
  })
49
49
 
50
- it('should load message samples', async () => {
51
- const expected = await messages()
52
-
53
- expect(suite.messages).toStrictEqual(expected)
54
- })
55
-
56
50
  describe('options', () => {
57
51
  const paths = [dummy, pot]
58
52
 
@@ -63,11 +57,6 @@ describe('options', () => {
63
57
  suite = await components(paths, options)
64
58
 
65
59
  expect(suite.operations['dummies.pot']).toBeUndefined()
66
-
67
- const messages = suite.messages['somewhere.something.happened']
68
-
69
- expect(messages.length).toStrictEqual(1)
70
- expect(messages[0].component).toStrictEqual('dummies.dummy')
71
60
  })
72
61
 
73
62
  it('should filter samples by operation name', async () => {
@@ -101,16 +90,14 @@ describe('options', () => {
101
90
  expect(suite.operations['dummies.dummy'].undo[0].title).toStrictEqual('Should not undo')
102
91
  })
103
92
 
104
- it('should filter message samples by title', async () => {
93
+ it('should filter operation samples by title', async () => {
105
94
  /** @type {toa.samples.suite.Options} */
106
- const options = { title: 'Something happened with a dummy' }
95
+ const options = { title: 'Should not undo' }
107
96
 
108
97
  suite = await components(paths, options)
109
98
 
110
- const messages = suite.messages['somewhere.something.happened']
111
-
112
- expect(messages.length).toStrictEqual(1)
113
- expect(messages[0].title).toStrictEqual(options.title)
99
+ expect(Object.keys(suite.operations['dummies.dummy']).length).toStrictEqual(1)
100
+ expect(suite.operations['dummies.dummy'].undo[0].title).toStrictEqual(options.title)
114
101
  })
115
102
  })
116
103
 
@@ -133,16 +120,3 @@ const operations = async () => {
133
120
  do: [...do1, ...do2], undo
134
121
  }
135
122
  }
136
-
137
- /**
138
- *
139
- * @returns {Promise<toa.samples.messages.Set>}
140
- */
141
- const messages = async () => {
142
- const label = 'somewhere.something.happened'
143
- const file = resolve(dummy, 'samples/messages', label + '.yaml')
144
- const declarations = await yaml.load.all(file)
145
- const messages = declarations.map((sample) => ({ component, ...sample }))
146
-
147
- return { [label]: messages }
148
- }
@@ -1,5 +1,5 @@
1
1
  import * as _core from '@toa.io/core/types'
2
- import * as _sampling from '@toa.io/extensions.sampling'
2
+ import * as _sampling from '@toa.io/extensions.sampling/types/request'
3
3
 
4
4
  declare namespace toa.samples {
5
5
 
@@ -27,7 +27,7 @@ declare namespace toa.samples {
27
27
  remote?: operations.Calls
28
28
  local?: operations.Calls
29
29
  events?: operations.Events
30
- extensions?: _sampling.request.Extensions
30
+ extensions?: _sampling.Extensions
31
31
  }
32
32
 
33
33
  }
@@ -2,9 +2,9 @@ import * as _suite from './suite'
2
2
 
3
3
  declare namespace toa.samples.replay {
4
4
 
5
- type components = (paths: string[], options?: _suite.Options) => Promise<boolean>
6
- type context = (path: string, options?: _suite.Options) => Promise<boolean>
7
- type replay = (suite: _suite.Suite, paths: string[]) => Promise<boolean>
5
+ type components = (paths: string[], options?: _suite.Options) => Promise<boolean>
6
+ type context = (path: string, options?: _suite.Options) => Promise<boolean>
7
+ type replay = (suite: _suite.Suite, paths: string[], options?: object) => Promise<boolean>
8
8
 
9
9
  }
10
10
 
@@ -1,3 +1,4 @@
1
+ import * as _core from '@toa.io/core/types'
1
2
  import * as _operations from './operation'
2
3
  import * as _messages from './message'
3
4
 
@@ -8,15 +9,17 @@ declare namespace toa.samples {
8
9
 
9
10
  type Options = {
10
11
  id?: string
11
- integration?: boolean
12
12
  component?: string
13
+ autonomous?: boolean
14
+ integration?: boolean
13
15
  operation?: string
14
16
  title?: string
17
+ runner?: object
15
18
  }
16
19
  }
17
20
 
18
21
  type Suite = {
19
- title: string
22
+ title?: string
20
23
  autonomous: boolean
21
24
  operations?: suite.Operations
22
25
  messages?: _messages.Set
@@ -5,42 +5,43 @@
5
5
  */
6
6
  class Binding {
7
7
  /** @type {Record<string, function[]>} */
8
- #subs = {}
8
+ #callbacks = {}
9
9
 
10
10
  /** @type {Record<string, function>} */
11
- #calls = {}
11
+ #producers = {}
12
12
 
13
13
  async subscribe (label, callback) {
14
- if (this.#subs[label] === undefined) this.#subs[label] = []
14
+ if (this.#callbacks[label] === undefined) this.#callbacks[label] = []
15
15
 
16
- this.#subs[label].push(callback)
16
+ this.#callbacks[label].push(callback)
17
17
  }
18
18
 
19
19
  async emit (label, message) {
20
- const callbacks = this.#subs[label]
21
-
22
- if (callbacks === undefined) return undefined
20
+ if (!(label in this.#callbacks)) return
23
21
 
22
+ const callbacks = this.#callbacks[label]
24
23
  const promises = callbacks.map((callback) => callback(message))
25
24
 
26
25
  await Promise.all(promises)
27
26
  }
28
27
 
29
28
  async reply (label, produce) {
30
- if (this.#calls[label] !== undefined) throw new Error(`Label '${label}' is already bound`)
29
+ if (label in this.#producers) throw new Error(`Label '${label}' is already bound`)
31
30
 
32
- this.#calls[label] = produce
31
+ this.#producers[label] = produce
33
32
  }
34
33
 
35
34
  async request (label, request) {
36
- if (this.#calls[label] === undefined) throw new Error(`Label '${label}' is not bound`)
35
+ if (!(label in this.#producers)) throw new Error(`Label '${label}' is not bound`)
36
+
37
+ const produce = this.#producers[label]
37
38
 
38
- return this.#calls[label](request)
39
+ return produce(request)
39
40
  }
40
41
 
41
42
  reset () {
42
- this.#subs = {}
43
- this.#calls = {}
43
+ this.#callbacks = {}
44
+ this.#producers = {}
44
45
  }
45
46
  }
46
47
 
@@ -4,8 +4,10 @@ const boot = require('@toa.io/boot')
4
4
  const { state } = require('./state')
5
5
 
6
6
  /** @type {toa.stage.Component} */
7
- const component = async (path) => {
8
- const manifest = await boot.manifest(path)
7
+ const component = async (path, options) => {
8
+ options = Object.assign({}, DEFAULTS, options)
9
+
10
+ const manifest = await boot.manifest(path, options)
9
11
  const component = await boot.component(manifest)
10
12
 
11
13
  await component.connect()
@@ -15,4 +17,7 @@ const component = async (path) => {
15
17
  return component
16
18
  }
17
19
 
20
+ const binding = require.resolve('./binding')
21
+ const DEFAULTS = { bindings: [binding] }
22
+
18
23
  exports.component = component
@@ -7,9 +7,6 @@ const { remote } = require('./remote')
7
7
  const { shutdown } = require('./shutdown')
8
8
  const binding = require('./binding')
9
9
 
10
- // staging always runs on local deployment environment
11
- process.env.TOA_DEV = '1'
12
-
13
10
  exports.manifest = manifest
14
11
  exports.component = component
15
12
  exports.composition = composition
@@ -18,7 +18,7 @@ it('should boot component', async () => {
18
18
  const path = generate()
19
19
  const component = await stage.component(path)
20
20
 
21
- expect(mock.boot.manifest).toHaveBeenCalledWith(path)
21
+ expect(mock.boot.manifest.mock.calls[0][0]).toStrictEqual(path)
22
22
  expect(mock.boot.component).toHaveBeenCalledWith(await mock.boot.manifest.mock.results[0].value)
23
23
  expect(component).toStrictEqual(await mock.boot.component.mock.results[0].value)
24
24
  expect(component.connect).toHaveBeenCalled()
@@ -1,9 +1,10 @@
1
1
  import * as _core from '@toa.io/core/types'
2
2
  import * as _norm from '@toa.io/norm/types'
3
+ import * as _composition from '@toa.io/boot/types/composition'
3
4
 
4
5
  declare namespace toa.stage {
5
6
  type Manifest = (path: string) => Promise<_norm.Component>
6
- type Component = (path: string) => Promise<_core.Component>
7
+ type Component = (path: string, options?: _composition.Options) => Promise<_core.Component>
7
8
  type Composition = (paths: string[]) => Promise<void>
8
9
  type Remote = (id: string) => Promise<_core.Component>
9
10
  type Shutdown = () => Promise<void>
@@ -1,37 +0,0 @@
1
- title: Should book a pot
2
- payload:
3
- pot: 1b9d7983bc204c8f8928d843a666a642
4
- input:
5
- booked: true
6
- query:
7
- id: 1b9d7983bc204c8f8928d843a666a642
8
- ---
9
- title: Should book a pot (with request sample)
10
- payload:
11
- pot: 1b9d7983bc204c8f8928d843a666a642
12
- input:
13
- booked: true
14
- query:
15
- id: 1b9d7983bc204c8f8928d843a666a642
16
- request:
17
- current:
18
- id: 1b9d7983bc204c8f8928d843a666a642
19
- material: glass
20
- booked: false
21
- next:
22
- id: 1b9d7983bc204c8f8928d843a666a642
23
- material: glass
24
- booked: true
25
- ---
26
- title: Should book a pot (without receiver output verification)
27
- payload:
28
- pot: 1b9d7983bc204c8f8928d843a666a642
29
- request:
30
- current:
31
- id: 1b9d7983bc204c8f8928d843a666a642
32
- material: glass
33
- booked: false
34
- next:
35
- id: 1b9d7983bc204c8f8928d843a666a642
36
- material: glass
37
- booked: true
@@ -1,26 +0,0 @@
1
- 'use strict'
2
-
3
- /**
4
- * @param {toa.samples.Operation & Object} declaration
5
- */
6
- const configuration = (declaration) => {
7
- const configuration = declaration.configuration
8
-
9
- delete declaration.configuration
10
-
11
- if (declaration.extensions === undefined) declaration.extensions = {}
12
-
13
- if ('configuration' in declaration.extensions) {
14
- throw new Error('Configuration extension sample is ambiguous')
15
- }
16
-
17
- /** @type {toa.sampling.request.extensions.Call} */
18
- const call = {
19
- result: configuration,
20
- permanent: true
21
- }
22
-
23
- declaration.extensions.configuration = [call]
24
- }
25
-
26
- exports.configuration = configuration
@@ -1,5 +0,0 @@
1
- 'use strict'
2
-
3
- const { configuration } = require('./configuration')
4
-
5
- exports.configuration = configuration
@@ -1,72 +0,0 @@
1
- 'use strict'
2
-
3
- const { generate } = require('randomstring')
4
- const { random } = require('@toa.io/generic')
5
-
6
- /** @type {toa.samples.Suite} */
7
- const suite = { autonomous: true, operations: {} }
8
-
9
- /**
10
- * @returns {toa.samples.Operation[]}
11
- */
12
- const ops = () => {
13
- const samples = []
14
-
15
- for (let i = 0; i < random(3) + 1; i++) {
16
- const sample = {
17
- input: generate(),
18
- output: generate(),
19
- local: generate(),
20
- current: generate(),
21
- next: generate()
22
- }
23
-
24
- samples.push(sample)
25
- }
26
-
27
- return samples
28
- }
29
-
30
- /**
31
- * @returns {toa.samples.Message[]}
32
- */
33
- const msgs = () => {
34
- /** @type {toa.samples.Message[]} */
35
- const samples = []
36
-
37
- for (let i = 0; i < random(3) + 1; i++) {
38
- const sample = /** @type {toa.samples.Message} */ {
39
- component: generate(),
40
- payload: generate(),
41
- input: generate()
42
- }
43
-
44
- samples.push(sample)
45
- }
46
-
47
- return samples
48
- }
49
-
50
- // components
51
- for (let i = 0; i < random(3) + 1; i++) {
52
- const id = generate() + '.' + generate()
53
- const operations = {}
54
- const messages = {}
55
-
56
- for (let j = 0; j < random(3) + 1; j++) {
57
- const endpoint = generate()
58
- const label = generate()
59
-
60
- operations[endpoint] = ops()
61
- messages[label] = msgs()
62
- }
63
-
64
- suite.operations[id] = operations
65
- }
66
-
67
- /** @type {string} */
68
- const label = generate()
69
-
70
- suite.messages = { [label]: msgs() }
71
-
72
- exports.suite = suite