@toa.io/userland 0.2.1-dev.3
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/example/components/echo/beacon/manifest.toa.yaml +9 -0
- package/example/components/echo/beacon/operations/signal.js +7 -0
- package/example/components/echo/beacon/samples/signal.yaml +7 -0
- package/example/components/math/calculations/manifest.toa.yaml +16 -0
- package/example/components/math/calculations/operations/add.js +7 -0
- package/example/components/math/calculations/operations/increment.js +15 -0
- package/example/components/math/calculations/samples/add.yaml +11 -0
- package/example/components/math/calculations/samples/increment.yaml +30 -0
- package/example/components/math/proxy/manifest.toa.yaml +11 -0
- package/example/components/math/proxy/operations/add.js +10 -0
- package/example/components/math/proxy/samples/add.yaml +11 -0
- package/example/components/tea/pots/manifest.toa.yaml +28 -0
- package/example/components/tea/pots/operations/same.js +13 -0
- package/example/components/tea/pots/receivers/store.orders.created.js +8 -0
- package/example/components/tea/pots/samples/messages/store.orders.created.yaml +37 -0
- package/example/components/tea/pots/samples/same.yaml +8 -0
- package/example/components/tea/pots/samples/transit.yaml +43 -0
- package/example/context.toa.yaml +3 -0
- package/example/samples/math.proxy.add.yaml +5 -0
- package/example/samples/messages/store.orders.created.yaml +8 -0
- package/example/stage/call.test.js +39 -0
- package/example/stage/events.test.js +48 -0
- package/example/stage/invoke.test.js +29 -0
- package/package.json +36 -0
- package/readme.md +9 -0
- package/samples/docs/sampling-dark.jpg +0 -0
- package/samples/docs/sampling-light.jpg +0 -0
- package/samples/notes.md +12 -0
- package/samples/package.json +5 -0
- package/samples/readme.md +66 -0
- package/samples/src/.replay/.suite/component.js +25 -0
- package/samples/src/.replay/.suite/index.js +7 -0
- package/samples/src/.replay/.suite/messages.js +39 -0
- package/samples/src/.replay/.suite/operation.js +28 -0
- package/samples/src/.replay/.suite/operations.js +18 -0
- package/samples/src/.replay/.suite/translate/.message/index.js +5 -0
- package/samples/src/.replay/.suite/translate/.message/request.js +31 -0
- package/samples/src/.replay/.suite/translate/.operation/calls.js +49 -0
- package/samples/src/.replay/.suite/translate/.operation/cleanup.js +16 -0
- package/samples/src/.replay/.suite/translate/.operation/events.js +16 -0
- package/samples/src/.replay/.suite/translate/.operation/index.js +11 -0
- package/samples/src/.replay/.suite/translate/.operation/prepare.js +14 -0
- package/samples/src/.replay/.suite/translate/.operation/specials/configuration.js +26 -0
- package/samples/src/.replay/.suite/translate/.operation/specials/index.js +5 -0
- package/samples/src/.replay/.suite/translate/index.js +7 -0
- package/samples/src/.replay/.suite/translate/message.js +26 -0
- package/samples/src/.replay/.suite/translate/operation.js +47 -0
- package/samples/src/.replay/.suite/translate/schemas/index.js +7 -0
- package/samples/src/.replay/.suite/translate/schemas/message.cos.yaml +10 -0
- package/samples/src/.replay/.suite/translate/schemas/operation.cos.yaml +23 -0
- package/samples/src/.replay/index.js +5 -0
- package/samples/src/.replay/suite.js +22 -0
- package/samples/src/.replay/test.js +17 -0
- package/samples/src/components.js +13 -0
- package/samples/src/context.js +18 -0
- package/samples/src/index.js +9 -0
- package/samples/src/replay.js +17 -0
- package/samples/src/suite/.read/index.js +7 -0
- package/samples/src/suite/.read/messages.js +35 -0
- package/samples/src/suite/.read/operations.js +45 -0
- package/samples/src/suite/.read/parse.js +24 -0
- package/samples/src/suite/components.js +28 -0
- package/samples/src/suite/context.js +19 -0
- package/samples/src/suite/index.js +7 -0
- package/samples/test/components.test.js +39 -0
- package/samples/test/context/components/ok/manifest.toa.yaml +2 -0
- package/samples/test/context/components/ok/samples/do.yaml +11 -0
- package/samples/test/context/components/ok/samples/dummies.dummy.do.yaml +11 -0
- package/samples/test/context/components/ok/samples/dummies.dummy.undo.yaml +7 -0
- package/samples/test/context/components/ok/samples/messages/somewhere.something.happened.yaml +6 -0
- package/samples/test/context/context.toa.yaml +3 -0
- package/samples/test/context/samples/dummies.dummy.observe.yaml +6 -0
- package/samples/test/context/samples/dummies.dummy.transit.yaml +10 -0
- package/samples/test/context/samples/messages/somewhere.something.happened.yaml +6 -0
- package/samples/test/context.fixtures.js +8 -0
- package/samples/test/context.test.js +78 -0
- package/samples/test/replay.fixtures.js +72 -0
- package/samples/test/replay.mock.js +7 -0
- package/samples/test/replay.test.js +116 -0
- package/samples/test/replay.translate.message.fixtures.js +24 -0
- package/samples/test/replay.translate.message.test.js +123 -0
- package/samples/test/replay.translate.mock.js +17 -0
- package/samples/test/replay.translate.operation.fixtures.js +107 -0
- package/samples/test/replay.translate.operation.test.js +68 -0
- package/samples/test/stage.mock.js +34 -0
- package/samples/test/suite.components.test.js +85 -0
- package/samples/test/suite.context.test.js +79 -0
- package/samples/test/suite.mock.js +10 -0
- package/samples/types/index.d.ts +8 -0
- package/samples/types/message.d.ts +24 -0
- package/samples/types/operation.d.ts +36 -0
- package/samples/types/replay.d.ts +13 -0
- package/samples/types/suite.d.ts +19 -0
- package/stage/package.json +5 -0
- package/stage/readme.md +41 -0
- package/stage/src/binding/binding.js +49 -0
- package/stage/src/binding/consumer.js +30 -0
- package/stage/src/binding/emitter.js +26 -0
- package/stage/src/binding/factory.js +49 -0
- package/stage/src/binding/index.js +10 -0
- package/stage/src/binding/label.js +12 -0
- package/stage/src/binding/producer.js +43 -0
- package/stage/src/binding/receiver.js +35 -0
- package/stage/src/component.js +18 -0
- package/stage/src/composition.js +19 -0
- package/stage/src/index.js +18 -0
- package/stage/src/manifest.js +12 -0
- package/stage/src/remote.js +22 -0
- package/stage/src/shutdown.js +19 -0
- package/stage/src/state.js +17 -0
- package/stage/test/binding/binding.test.js +15 -0
- package/stage/test/binding/consumer.test.js +52 -0
- package/stage/test/binding/emitter.test.js +54 -0
- package/stage/test/binding/producer.fixtures.js +10 -0
- package/stage/test/binding/producer.test.js +49 -0
- package/stage/test/binding/receiver.fixtures.js +7 -0
- package/stage/test/binding/receiver.test.js +54 -0
- package/stage/test/binding.mock.js +8 -0
- package/stage/test/boot.mock.js +16 -0
- package/stage/test/component.test.js +25 -0
- package/stage/test/composition.test.js +38 -0
- package/stage/test/manifest.test.js +24 -0
- package/stage/test/remote.test.js +32 -0
- package/stage/test/shutdown.test.js +66 -0
- package/stage/test/state.mock.js +8 -0
- package/stage/test/state.test.js +27 -0
- package/stage/types/binding.d.ts +20 -0
- package/stage/types/index.d.ts +28 -0
- package/stage/types/state.d.ts +14 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { component } = require('./component')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {toa.samples.suite.Operations} operations
|
|
7
|
+
* @param {boolean} autonomous
|
|
8
|
+
* @return {Function}
|
|
9
|
+
*/
|
|
10
|
+
const operations = (operations, autonomous) =>
|
|
11
|
+
async (test) => {
|
|
12
|
+
for (const [id, set] of Object.entries(operations)) {
|
|
13
|
+
await test.test(id, component(id, set, autonomous))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
exports.operations = operations
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { add, defined } = require('@toa.io/generic')
|
|
4
|
+
const translate = require('../operation')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {toa.samples.Message} declaration
|
|
8
|
+
* @param {boolean} autonomous
|
|
9
|
+
* @returns {toa.sampling.request.Sample}
|
|
10
|
+
*/
|
|
11
|
+
const request = (declaration, autonomous) => {
|
|
12
|
+
const { title, input, query } = declaration
|
|
13
|
+
|
|
14
|
+
/** @type {toa.sampling.request.Sample} */
|
|
15
|
+
const sample = declaration.request === undefined
|
|
16
|
+
? {}
|
|
17
|
+
: translate.operation(declaration.request, autonomous).sample
|
|
18
|
+
|
|
19
|
+
const request = defined({ input, query })
|
|
20
|
+
|
|
21
|
+
/** @type {Partial<toa.sampling.request.Sample>} */
|
|
22
|
+
const patch = { title, autonomous, request }
|
|
23
|
+
|
|
24
|
+
if (declaration.request === undefined) patch.terminate = true
|
|
25
|
+
|
|
26
|
+
add(sample, patch)
|
|
27
|
+
|
|
28
|
+
return sample
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
exports.request = request
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { defined } = require('@toa.io/generic')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {toa.samples.operation.Calls} calls
|
|
7
|
+
* @returns {toa.sampling.request.context.Calls}
|
|
8
|
+
*/
|
|
9
|
+
const calls = (calls) => {
|
|
10
|
+
/** @type {toa.sampling.request.context.Calls} */
|
|
11
|
+
const output = {}
|
|
12
|
+
|
|
13
|
+
for (let [endpoint, samples] of Object.entries(calls)) {
|
|
14
|
+
if (!Array.isArray(samples)) samples = [samples]
|
|
15
|
+
|
|
16
|
+
const target = []
|
|
17
|
+
|
|
18
|
+
for (const sample of samples) {
|
|
19
|
+
const translation = call(sample)
|
|
20
|
+
|
|
21
|
+
target.push(translation)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
output[endpoint] = target
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return output
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {toa.samples.operation.Call} call
|
|
32
|
+
* @returns {toa.sampling.request.context.Call}
|
|
33
|
+
*/
|
|
34
|
+
const call = (call) => {
|
|
35
|
+
let request
|
|
36
|
+
let reply
|
|
37
|
+
|
|
38
|
+
const sample = {}
|
|
39
|
+
const { input, query, output } = call
|
|
40
|
+
|
|
41
|
+
if (input !== undefined || query !== undefined) request = defined({ input, query })
|
|
42
|
+
if (output !== undefined) reply = { output }
|
|
43
|
+
if (request !== undefined) sample.request = request
|
|
44
|
+
if (reply !== undefined) sample.reply = reply
|
|
45
|
+
|
|
46
|
+
return sample
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
exports.calls = calls
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { defined, empty } = require('@toa.io/generic')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {toa.sampling.request.Sample} sample
|
|
7
|
+
*/
|
|
8
|
+
const cleanup = (sample) => {
|
|
9
|
+
for (const [key, value] of Object.entries(sample)) {
|
|
10
|
+
if (value === undefined || (typeof value === 'object' && empty(defined(value)))) {
|
|
11
|
+
delete sample[key]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.cleanup = cleanup
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {toa.samples.operations.Events} events
|
|
5
|
+
* @returns {toa.sampling.request.Events}
|
|
6
|
+
*/
|
|
7
|
+
const events = (events) => {
|
|
8
|
+
/** @type {toa.sampling.request.Events} */
|
|
9
|
+
const set = {}
|
|
10
|
+
|
|
11
|
+
for (const [label, sample] of Object.entries(events)) set[label] = { payload: sample }
|
|
12
|
+
|
|
13
|
+
return set
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.events = events
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { calls } = require('./calls')
|
|
4
|
+
const { events } = require('./events')
|
|
5
|
+
const { cleanup } = require('./cleanup')
|
|
6
|
+
const { prepare } = require('./prepare')
|
|
7
|
+
|
|
8
|
+
exports.calls = calls
|
|
9
|
+
exports.events = events
|
|
10
|
+
exports.cleanup = cleanup
|
|
11
|
+
exports.prepare = prepare
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const specials = require('./specials')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {toa.samples.Operation & Object} declaration
|
|
7
|
+
*/
|
|
8
|
+
const prepare = (declaration) => {
|
|
9
|
+
for (const [keyword, prepare] of Object.entries(specials)) {
|
|
10
|
+
if (keyword in declaration) prepare(declaration)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
exports.prepare = prepare
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { schemas } = require('./schemas')
|
|
4
|
+
const translate = require('./.message')
|
|
5
|
+
|
|
6
|
+
const schema = schemas.schema('message')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {toa.samples.Message} declaration
|
|
10
|
+
* @param {boolean} autonomous
|
|
11
|
+
* @param {string} component
|
|
12
|
+
* @returns {toa.sampling.Message}
|
|
13
|
+
*/
|
|
14
|
+
const message = (declaration, autonomous, component) => {
|
|
15
|
+
schema.validate(declaration)
|
|
16
|
+
|
|
17
|
+
const payload = declaration.payload
|
|
18
|
+
const request = translate.request(declaration, autonomous)
|
|
19
|
+
|
|
20
|
+
/** @type {toa.sampling.messages.Sample} */
|
|
21
|
+
const sample = { authentic: true, component, request }
|
|
22
|
+
|
|
23
|
+
return { payload, sample }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
exports.message = message
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const transform = require('./.operation')
|
|
4
|
+
const { schemas } = require('./schemas')
|
|
5
|
+
|
|
6
|
+
const schema = schemas.schema('operation')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {toa.samples.Operation} declaration
|
|
10
|
+
* @param {boolean} autonomous
|
|
11
|
+
* @returns {toa.sampling.Request}
|
|
12
|
+
*/
|
|
13
|
+
const operation = (declaration, autonomous) => {
|
|
14
|
+
transform.prepare(declaration)
|
|
15
|
+
schema.validate(declaration)
|
|
16
|
+
|
|
17
|
+
const { title, input, output, local, remote, current, next, extensions } = declaration
|
|
18
|
+
const reply = { output }
|
|
19
|
+
const storage = { current, next }
|
|
20
|
+
|
|
21
|
+
/** @type {toa.sampling.request.Context} */
|
|
22
|
+
let context = {}
|
|
23
|
+
|
|
24
|
+
/** @type {toa.sampling.request.Events} */
|
|
25
|
+
let events
|
|
26
|
+
|
|
27
|
+
if (local !== undefined) context.local = transform.calls(local)
|
|
28
|
+
if (remote !== undefined) context.remote = transform.calls(remote)
|
|
29
|
+
if (declaration.events !== undefined) events = transform.events(declaration.events)
|
|
30
|
+
|
|
31
|
+
const sample = /** @type {toa.sampling.request.Sample} */ {
|
|
32
|
+
authentic: true,
|
|
33
|
+
autonomous,
|
|
34
|
+
title,
|
|
35
|
+
reply,
|
|
36
|
+
context,
|
|
37
|
+
storage,
|
|
38
|
+
events,
|
|
39
|
+
extensions
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
transform.cleanup(sample)
|
|
43
|
+
|
|
44
|
+
return { input, sample }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
exports.operation = operation
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
autonomous: boolean
|
|
2
|
+
title: string
|
|
3
|
+
input: ~
|
|
4
|
+
output: ~
|
|
5
|
+
local: &calls
|
|
6
|
+
~+:
|
|
7
|
+
input: ~
|
|
8
|
+
query:
|
|
9
|
+
id: string
|
|
10
|
+
criteria: string
|
|
11
|
+
omit: number
|
|
12
|
+
limit: number
|
|
13
|
+
output: ~
|
|
14
|
+
remote: *calls
|
|
15
|
+
current+: object
|
|
16
|
+
next: object
|
|
17
|
+
events:
|
|
18
|
+
~: object
|
|
19
|
+
extensions:
|
|
20
|
+
~:
|
|
21
|
+
- arguments: [~]
|
|
22
|
+
result: ~
|
|
23
|
+
permanent: boolean
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const replay = require('./.suite')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {toa.samples.Suite} suite
|
|
7
|
+
* @returns {Function}
|
|
8
|
+
*/
|
|
9
|
+
const suite = (suite) =>
|
|
10
|
+
async (test) => {
|
|
11
|
+
if ('operations' in suite) {
|
|
12
|
+
await test.test('Operations', replay.operations(suite.operations, suite.autonomous))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if ('messages' in suite) {
|
|
16
|
+
await test.test('Messages', replay.messages(suite.messages, suite.autonomous))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
test.end()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
exports.suite = suite
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const tap = require('tap')
|
|
4
|
+
|
|
5
|
+
const replay = require('./suite')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {toa.samples.Suite} suite
|
|
9
|
+
* @return {Promise<boolean>}
|
|
10
|
+
*/
|
|
11
|
+
const test = async (suite) => {
|
|
12
|
+
const { ok } = await tap.test(suite.title, replay.suite(suite))
|
|
13
|
+
|
|
14
|
+
return ok
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.test = test
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { components: load } = require('./suite')
|
|
4
|
+
const { replay } = require('./replay')
|
|
5
|
+
|
|
6
|
+
/** @type {toa.samples.replay.components} */
|
|
7
|
+
const components = async (paths) => {
|
|
8
|
+
const suite = await load(paths)
|
|
9
|
+
|
|
10
|
+
return await replay(suite, paths)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
exports.components = components
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const norm = require('@toa.io/norm')
|
|
4
|
+
|
|
5
|
+
const test = require('./components')
|
|
6
|
+
const { context: load } = require('./suite')
|
|
7
|
+
const { replay } = require('./replay')
|
|
8
|
+
|
|
9
|
+
/** @type {toa.samples.replay.context} */
|
|
10
|
+
const context = async (path) => {
|
|
11
|
+
const context = await norm.context(path)
|
|
12
|
+
const paths = context.components.map((component) => component.path)
|
|
13
|
+
const suite = await load(path)
|
|
14
|
+
|
|
15
|
+
return await test.components(paths) && await replay(suite, paths)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
exports.context = context
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const stage = require('@toa.io/userland/stage')
|
|
4
|
+
const { test } = require('./.replay')
|
|
5
|
+
|
|
6
|
+
/** @type {toa.samples.replay.replay} */
|
|
7
|
+
const replay = async (suite, paths) => {
|
|
8
|
+
await stage.composition(paths)
|
|
9
|
+
|
|
10
|
+
const ok = await test(suite)
|
|
11
|
+
|
|
12
|
+
await stage.shutdown()
|
|
13
|
+
|
|
14
|
+
return ok
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.replay = replay
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { join, basename } = require('node:path')
|
|
4
|
+
const { file: { glob } } = require('@toa.io/filesystem')
|
|
5
|
+
const yaml = require('@toa.io/yaml')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} path
|
|
9
|
+
* @param {string} [id]
|
|
10
|
+
* @returns {Promise<toa.samples.messages.Set>}
|
|
11
|
+
*/
|
|
12
|
+
const messages = async (path, id) => {
|
|
13
|
+
/** @type {toa.samples.messages.Set} */
|
|
14
|
+
const messages = {}
|
|
15
|
+
|
|
16
|
+
const pattern = join(path, DIRECTORY, PATTERN)
|
|
17
|
+
const files = await glob(pattern)
|
|
18
|
+
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
const label = basename(file, EXTENSION)
|
|
21
|
+
const samples = /** @type {toa.samples.Message[]} */ await yaml.load.all(file)
|
|
22
|
+
|
|
23
|
+
if (id !== undefined) samples.forEach((sample) => (sample.component = id))
|
|
24
|
+
|
|
25
|
+
messages[label] = samples
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return messages
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const DIRECTORY = 'samples/messages'
|
|
32
|
+
const EXTENSION = '.yaml'
|
|
33
|
+
const PATTERN = '*' + EXTENSION
|
|
34
|
+
|
|
35
|
+
exports.messages = messages
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { basename, join } = require('node:path')
|
|
4
|
+
const { file: { glob } } = require('@toa.io/filesystem')
|
|
5
|
+
const { merge } = require('@toa.io/generic')
|
|
6
|
+
const yaml = require('@toa.io/yaml')
|
|
7
|
+
|
|
8
|
+
const { parse } = require('./parse')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} path
|
|
12
|
+
* @param {string} [id]
|
|
13
|
+
* @returns {Promise<toa.samples.suite.Operations>}
|
|
14
|
+
*/
|
|
15
|
+
const operations = async (path, id) => {
|
|
16
|
+
/** @type {toa.samples.suite.Operations} */
|
|
17
|
+
const operations = {}
|
|
18
|
+
|
|
19
|
+
const pattern = join(path, DIRECTORY, PATTERN)
|
|
20
|
+
const files = await glob(pattern)
|
|
21
|
+
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
const name = basename(file, EXTENSION)
|
|
24
|
+
const [component, operation] = parse(name, id)
|
|
25
|
+
|
|
26
|
+
/** @type {toa.samples.Operation[]} */
|
|
27
|
+
const samples = await yaml.load.all(file)
|
|
28
|
+
|
|
29
|
+
if (operations[component] === undefined) operations[component] = {}
|
|
30
|
+
|
|
31
|
+
/** @type {toa.samples.operations.Set} */
|
|
32
|
+
const set = operations[component]
|
|
33
|
+
|
|
34
|
+
if (set[operation] === undefined) set[operation] = samples
|
|
35
|
+
else set[operation] = merge(set[operation], samples)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return operations
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const DIRECTORY = 'samples'
|
|
42
|
+
const EXTENSION = '.yaml'
|
|
43
|
+
const PATTERN = '*' + EXTENSION
|
|
44
|
+
|
|
45
|
+
exports.operations = operations
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} name
|
|
5
|
+
* @param {string} [def]
|
|
6
|
+
* @returns {[string, string]}
|
|
7
|
+
*/
|
|
8
|
+
const parse = (name, def) => {
|
|
9
|
+
const parts = name.split('.')
|
|
10
|
+
const [endpoint, component, namespace] = parts.reverse()
|
|
11
|
+
const id = namespace === undefined ? def : namespace + '.' + component
|
|
12
|
+
|
|
13
|
+
if (id !== undefined && def !== undefined && id !== def) {
|
|
14
|
+
throw new Error(`Component id mismatch: '${id}' expected, '${component}' given`)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// if (id === undefined) {
|
|
18
|
+
// throw new Error('Sample file name must be an operation endpoint')
|
|
19
|
+
// }
|
|
20
|
+
|
|
21
|
+
return [id, endpoint]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
exports.parse = parse
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const norm = require('@toa.io/norm')
|
|
4
|
+
const { merge } = require('@toa.io/generic')
|
|
5
|
+
|
|
6
|
+
const read = require('./.read')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string[]} paths
|
|
10
|
+
* @returns {Promise<toa.samples.Suite>}
|
|
11
|
+
*/
|
|
12
|
+
const components = async (paths) => {
|
|
13
|
+
/** @type {toa.samples.Suite} */
|
|
14
|
+
const suite = { title: 'Component samples', autonomous: true, operations: {}, messages: {} }
|
|
15
|
+
|
|
16
|
+
for (const path of paths) {
|
|
17
|
+
const manifest = await norm.component(path)
|
|
18
|
+
const id = manifest.locator.id
|
|
19
|
+
const operations = await read.operations(path, id)
|
|
20
|
+
const messages = await read.messages(path, id)
|
|
21
|
+
|
|
22
|
+
merge(suite, { operations, messages })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return suite
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
exports.components = components
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const read = require('./.read')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {string} path
|
|
7
|
+
* @returns {Promise<toa.samples.Suite>}
|
|
8
|
+
*/
|
|
9
|
+
const context = async (path) => {
|
|
10
|
+
/** @type {toa.samples.Suite} */
|
|
11
|
+
const suite = { title: 'Integration samples', autonomous: false }
|
|
12
|
+
|
|
13
|
+
suite.operations = await read.operations(path)
|
|
14
|
+
suite.messages = await read.messages(path)
|
|
15
|
+
|
|
16
|
+
return suite
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
exports.context = context
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const { suite } = require('./suite.mock')
|
|
6
|
+
const { replay } = require('./replay.mock')
|
|
7
|
+
const mock = { suite, replay }
|
|
8
|
+
|
|
9
|
+
jest.mock('../src/suite', () => mock.suite)
|
|
10
|
+
jest.mock('../src/replay', () => mock.replay)
|
|
11
|
+
|
|
12
|
+
const { components } = require('../')
|
|
13
|
+
|
|
14
|
+
it('should be', () => {
|
|
15
|
+
expect(components).toBeDefined()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const paths = [generate()]
|
|
19
|
+
|
|
20
|
+
/** @type {boolean} */
|
|
21
|
+
let result
|
|
22
|
+
|
|
23
|
+
beforeAll(async () => {
|
|
24
|
+
result = await components(paths)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should load suite', async () => {
|
|
28
|
+
expect(mock.suite.components).toHaveBeenCalledWith(paths)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('should replay suite', async () => {
|
|
32
|
+
const suite = await mock.suite.components.mock.results[0].value
|
|
33
|
+
|
|
34
|
+
expect(mock.replay.replay).toHaveBeenCalledWith(suite, paths)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('should return result', async () => {
|
|
38
|
+
expect(result).toStrictEqual(await mock.replay.replay.mock.results[0].value)
|
|
39
|
+
})
|