@toa.io/bridges.node 0.1.1-dev.3 → 0.2.1-dev.2
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/package.json +5 -3
- package/readme.md +103 -0
- package/src/algorithms/class.js +6 -0
- package/src/algorithms/factory.js +10 -0
- package/src/algorithms/function.js +10 -0
- package/src/algorithms/runner.js +50 -0
- package/src/context.js +68 -3
- package/src/define/.operations/define.js +16 -0
- package/src/define/.operations/extract.js +48 -0
- package/src/define/.operations/index.js +7 -0
- package/src/define/.operations/syntaxes/class.js +42 -0
- package/src/define/.operations/syntaxes/constants.js +4 -0
- package/src/define/.operations/syntaxes/factory.js +27 -0
- package/src/define/.operations/syntaxes/function.js +41 -0
- package/src/define/.operations/syntaxes/index.js +5 -0
- package/src/define/index.js +3 -6
- package/src/define/operations.js +11 -2
- package/src/event.js +8 -1
- package/src/factory.js +24 -4
- package/src/index.js +0 -1
- package/src/load.js +1 -1
- package/src/receiver.js +8 -1
- package/test/algorithms.runner.test.js +40 -0
- package/test/context.configuration.fixtures.js +21 -0
- package/test/context.configuration.test.js +23 -0
- package/test/context.origins.fixtures.js +16 -0
- package/test/context.origins.test.js +53 -0
- package/test/define.algorithms.test.js +36 -0
- package/test/define.operations.define.test.js +195 -0
- package/test/dummies/one/operations/cls.js +18 -0
- package/test/dummies/one/operations/fct.js +20 -0
- package/test/dummies/one/operations/fn.js +7 -0
- package/test/factory.algorithm.test.js +43 -0
- package/types/algorithms.d.ts +15 -0
- package/types/context.d.ts +21 -0
- package/types/define.d.ts +30 -0
- package/LICENSE +0 -22
- package/src/define/operations/definition.js +0 -40
- package/src/operation.js +0 -23
- package/test/operation.fixtures.js +0 -9
- package/test/operation.test.js +0 -39
- package/test/operations.definition.test.js +0 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/bridges.node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1-dev.2",
|
|
4
4
|
"description": "Toa Node Bridge (inproc)",
|
|
5
5
|
"homepage": "https://toa.io",
|
|
6
6
|
"author": {
|
|
@@ -26,11 +26,13 @@
|
|
|
26
26
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@
|
|
29
|
+
"@toa.io/core": "*",
|
|
30
|
+
"@toa.io/filesystem": "*",
|
|
31
|
+
"@toa.io/generic": "*",
|
|
30
32
|
"fast-glob": "3.2.7"
|
|
31
33
|
},
|
|
32
34
|
"devDependencies": {
|
|
33
35
|
"clone-deep": "4.0.1"
|
|
34
36
|
},
|
|
35
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "2be07592325b2e4dc823e81d882a4e50bf50de24"
|
|
36
38
|
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Node.js Bridge
|
|
2
|
+
|
|
3
|
+
> Currently, Node.js bridge only
|
|
4
|
+
> supports [CommonJS modules](https://nodejs.org/api/modules.html#modules-commonjs-modules).
|
|
5
|
+
|
|
6
|
+
## Algorithm Definition
|
|
7
|
+
|
|
8
|
+
Operation's algorithms are defined as CommonJS modules in under `operations` directory in the
|
|
9
|
+
component root. Algorithm module must export a function which is Algorithm Function, Class or
|
|
10
|
+
Factory. Module file name without extension is an operation name (endpoint).
|
|
11
|
+
|
|
12
|
+
### Function
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
// operations/create.js
|
|
16
|
+
|
|
17
|
+
function transition (input, object, context) {
|
|
18
|
+
// ...
|
|
19
|
+
|
|
20
|
+
return { output: { foo: 'bar' } }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.transition = transition
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Exported function's name defines operation `type` property, thus must be one of:
|
|
27
|
+
`transition`, `observation`, or `assignment`. Second (state) argument name must be `object`,
|
|
28
|
+
`objects`, or `changeset` as it defines operation's `scope`.
|
|
29
|
+
|
|
30
|
+
Following function signature defines operation of `observation` type with `objects` scope.
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
// operations/set.js
|
|
34
|
+
|
|
35
|
+
function observation (input, objects) {
|
|
36
|
+
// ...
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
See [Operation properties](#).
|
|
41
|
+
|
|
42
|
+
### Class
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// operations/transit.js
|
|
46
|
+
|
|
47
|
+
class Transition {
|
|
48
|
+
constructor (context) {}
|
|
49
|
+
|
|
50
|
+
execute (input, object) {
|
|
51
|
+
// ...
|
|
52
|
+
|
|
53
|
+
return { output: { foo: 'bar' } }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.Transition = Transition
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Exported class name must be one of: `Transition`, `Observation`, or `Assignment`, as it defines
|
|
61
|
+
operation's `type`. Class must implement [Algorithm interface](./types/operations.d.ts).
|
|
62
|
+
Second (state) argument name of the `execute` method must be `object`, `objects`, or `changeset` as
|
|
63
|
+
it defines operation's `scope`.
|
|
64
|
+
|
|
65
|
+
### Factory
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
class ObjectTransitionFactory {
|
|
69
|
+
constructor (context) {}
|
|
70
|
+
|
|
71
|
+
create () {
|
|
72
|
+
// ...
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
exports.ObjectTransitionFactory = ObjectTransitionFactory
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Exported class name must follow the pattern: `{Subject}{Type}Factory`, where `Subject` and `Type`
|
|
80
|
+
defines operation's `scope` and `type` respectively. Class must
|
|
81
|
+
implement [Algorithm Factory interface](#).
|
|
82
|
+
|
|
83
|
+
> Factory class name examples: `ObjectTransitionFactory`, `ObjectsObservationFactory`,
|
|
84
|
+
> `ChangesetAssignmentFactory`.
|
|
85
|
+
|
|
86
|
+
### Return value
|
|
87
|
+
|
|
88
|
+
Algorithm's return value must match [UCP Response](#), that is, to be an object with either `output`
|
|
89
|
+
or `error` properties. If return value is a primitive or an object without neither `output`
|
|
90
|
+
nor `error` properties, then it is considered as the value of `output`.
|
|
91
|
+
|
|
92
|
+
Next two return values are equivalent.
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
return { ok: 1 }
|
|
96
|
+
|
|
97
|
+
return { output: { ok: 1 } }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Storing Context
|
|
101
|
+
|
|
102
|
+
> Algorithm definition should store reference to the `context` object without copying its value
|
|
103
|
+
> type variables as they may change over time.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.core.bridges.Algorithm}
|
|
7
|
+
*/
|
|
8
|
+
class Runner extends Connector {
|
|
9
|
+
/** @type {toa.node.algorithms.Constructor} */
|
|
10
|
+
#ctor
|
|
11
|
+
|
|
12
|
+
/** @type {toa.core.bridges.Algorithm} */
|
|
13
|
+
#instance
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {toa.node.algorithms.Constructor} ctor
|
|
17
|
+
* @param {toa.node.Context} context
|
|
18
|
+
*/
|
|
19
|
+
constructor (ctor, context) {
|
|
20
|
+
super()
|
|
21
|
+
|
|
22
|
+
this.#ctor = ctor
|
|
23
|
+
|
|
24
|
+
this.depends(context)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async connection () {
|
|
28
|
+
this.#instance = /** @type {toa.core.bridges.Algorithm} */ this.#ctor()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async run (input, state) {
|
|
32
|
+
let reply = await this.#instance.run(input, state)
|
|
33
|
+
|
|
34
|
+
if (reply !== undefined) reply = normalize(reply)
|
|
35
|
+
|
|
36
|
+
return reply
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function normalize (reply) {
|
|
41
|
+
const object = typeof reply === 'object'
|
|
42
|
+
const output = object && reply.output !== undefined
|
|
43
|
+
const error = object && reply.error !== undefined
|
|
44
|
+
|
|
45
|
+
if (!output && !error) reply = { output: reply }
|
|
46
|
+
|
|
47
|
+
return reply
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
exports.Runner = Runner
|
package/src/context.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { Connector } = require('@toa.io/core')
|
|
4
|
-
const { underlay } = require('@toa.io/
|
|
4
|
+
const { underlay } = require('@toa.io/generic')
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @implements {toa.node.Context}
|
|
8
|
+
*/
|
|
6
9
|
class Context extends Connector {
|
|
10
|
+
aspects
|
|
11
|
+
configuration
|
|
12
|
+
origins
|
|
13
|
+
|
|
7
14
|
#context
|
|
8
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @param {toa.core.Context} context
|
|
18
|
+
*/
|
|
9
19
|
constructor (context) {
|
|
10
20
|
super()
|
|
11
21
|
|
|
@@ -14,8 +24,63 @@ class Context extends Connector {
|
|
|
14
24
|
this.depends(context)
|
|
15
25
|
}
|
|
16
26
|
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
async connection () {
|
|
28
|
+
this.aspects = this.#aspects(/** @type {toa.core.extensions.Aspect[]} */ this.#context.aspects)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
local = underlay(async ([endpoint], [request]) => {
|
|
32
|
+
return this.#context.apply(endpoint, request)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
remote = underlay(async ([namespace, name, endpoint], [request]) => {
|
|
36
|
+
return this.#context.call(namespace, name, endpoint, request)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {toa.core.extensions.Aspect[]} aspects
|
|
41
|
+
* @returns {{ [key: string]: Function}}
|
|
42
|
+
*/
|
|
43
|
+
#aspects (aspects) {
|
|
44
|
+
const map = {}
|
|
45
|
+
|
|
46
|
+
for (const aspect of aspects) {
|
|
47
|
+
if (map[aspect.name] !== undefined) throw new Error(`Aspect conflict on '${aspect.name}'`)
|
|
48
|
+
|
|
49
|
+
map[aspect.name] = aspect.invoke.bind(aspect)
|
|
50
|
+
|
|
51
|
+
// well-known aspects
|
|
52
|
+
if (aspect.name === 'configuration') this.#configuration(aspect)
|
|
53
|
+
if (aspect.name === 'origins') this.origins = this.#origins(aspect)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return map
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {toa.core.extensions.Aspect} aspect
|
|
61
|
+
*/
|
|
62
|
+
#origins (aspect) {
|
|
63
|
+
return underlay(async (segs, args) => {
|
|
64
|
+
if (segs.length < 2) throw new Error(`Origins call requires at least 2 arguments, ${segs.length} given`)
|
|
65
|
+
|
|
66
|
+
const name = segs.shift()
|
|
67
|
+
const method = segs.pop().toUpperCase()
|
|
68
|
+
const path = segs.join('/')
|
|
69
|
+
const request = { method, ...args[0] }
|
|
70
|
+
const options = args[1]
|
|
71
|
+
|
|
72
|
+
return await aspect.invoke(name, path, request, options)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {toa.core.extensions.Aspect} aspect
|
|
78
|
+
*/
|
|
79
|
+
#configuration (aspect) {
|
|
80
|
+
Object.defineProperty(this, 'configuration', {
|
|
81
|
+
get: () => aspect.invoke()
|
|
82
|
+
})
|
|
83
|
+
}
|
|
19
84
|
}
|
|
20
85
|
|
|
21
86
|
exports.Context = Context
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { extract } = require('./extract')
|
|
4
|
+
const syntaxes = require('./syntaxes')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {Object} module
|
|
8
|
+
* @returns {toa.node.define.operations.Definition}
|
|
9
|
+
*/
|
|
10
|
+
const define = (module) => {
|
|
11
|
+
const descriptor = extract(module)
|
|
12
|
+
|
|
13
|
+
return syntaxes[descriptor.syntax].define(descriptor)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.define = define
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const parser = require('@babel/parser')
|
|
4
|
+
const syntaxes = require('./syntaxes')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {Object} module
|
|
8
|
+
* @returns {toa.node.define.algorithms.Descriptor}
|
|
9
|
+
*/
|
|
10
|
+
const extract = (module) => {
|
|
11
|
+
const [name, func] = find(module)
|
|
12
|
+
const statement = parse(func)
|
|
13
|
+
|
|
14
|
+
/** @type {toa.node.define.algorithms.Descriptor} */
|
|
15
|
+
const descriptor = { name, statement, syntax: undefined }
|
|
16
|
+
|
|
17
|
+
for (const [syntax, { test }] of Object.entries(syntaxes)) {
|
|
18
|
+
if (test(statement, name)) descriptor.syntax = /** @type {toa.node.define.algorithms.Syntax} */ syntax
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (descriptor.syntax === undefined) throw new Error('Exported function does not match conventions')
|
|
22
|
+
|
|
23
|
+
return descriptor
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {Object} module
|
|
28
|
+
* @returns [string, Function]
|
|
29
|
+
*/
|
|
30
|
+
const find = (module) => {
|
|
31
|
+
for (const [key, value] of Object.entries(module)) {
|
|
32
|
+
if (typeof value === 'function') return [key, value]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
throw new Error('Module does not export function')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {Function} func
|
|
40
|
+
* @returns {import('@babel/types').Statement}
|
|
41
|
+
*/
|
|
42
|
+
const parse = (func) => {
|
|
43
|
+
const file = parser.parse(func.toString())
|
|
44
|
+
|
|
45
|
+
return file.program.body[0]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
exports.extract = extract
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { letters: { capitalize } } = require('@toa.io/generic')
|
|
4
|
+
const { types } = require('./constants')
|
|
5
|
+
const func = require('./function')
|
|
6
|
+
|
|
7
|
+
/** @type {toa.node.define.operations.Define} */
|
|
8
|
+
const define = (descriptor) => {
|
|
9
|
+
const declaration = /** @type {import('@babel/types').ClassDeclaration} */ descriptor.statement
|
|
10
|
+
|
|
11
|
+
descriptor.name = descriptor.name.toLowerCase()
|
|
12
|
+
descriptor.statement = method(declaration, 'run')
|
|
13
|
+
|
|
14
|
+
return func.define(descriptor)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** @type {toa.node.define.operations.Test} */
|
|
18
|
+
const test = (statement, name) => {
|
|
19
|
+
const declaration = statement.type === 'ClassDeclaration'
|
|
20
|
+
const known = names.includes(name)
|
|
21
|
+
|
|
22
|
+
return declaration && known
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {import('@babel/types').ClassDeclaration} statement
|
|
27
|
+
* @param {string} name
|
|
28
|
+
* @returns {import('@babel/types').Statement}
|
|
29
|
+
*/
|
|
30
|
+
const method = (statement, name) => {
|
|
31
|
+
const methods = statement.body.body
|
|
32
|
+
const method = methods.find((method) => method.type === 'ClassMethod' && method.key.name === name)
|
|
33
|
+
|
|
34
|
+
if (method === undefined) throw new Error(`Method '${name}' not found`)
|
|
35
|
+
|
|
36
|
+
return /** @type {import('@babel/types').Statement} */ method
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const names = types.map((type) => capitalize(type))
|
|
40
|
+
|
|
41
|
+
exports.define = define
|
|
42
|
+
exports.test = test
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/** @type {toa.node.define.operations.Define} */
|
|
4
|
+
const define = (descriptor) => {
|
|
5
|
+
const match = descriptor.name.match(pattern)
|
|
6
|
+
|
|
7
|
+
/** @type {toa.node.define.operations.Definition} */
|
|
8
|
+
const definition = {}
|
|
9
|
+
|
|
10
|
+
definition.type = /** @type {typeof toa.norm.component.Operation.scope} */ match[2].toLowerCase()
|
|
11
|
+
definition.scope = /** @type {typeof toa.norm.component.Operation.type} */ match[1].toLowerCase()
|
|
12
|
+
|
|
13
|
+
return definition
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** @type {toa.node.define.operations.Test} */
|
|
17
|
+
const test = (statement, name) => {
|
|
18
|
+
const declaration = statement.type === 'ClassDeclaration'
|
|
19
|
+
const match = name.match(pattern) !== null
|
|
20
|
+
|
|
21
|
+
return declaration && match
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const pattern = new RegExp('^(Objects?|Changeset|None)(Transition|Observation|Assignment)Factory$')
|
|
25
|
+
|
|
26
|
+
exports.define = define
|
|
27
|
+
exports.test = test
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { types, scopes } = require('./constants')
|
|
4
|
+
|
|
5
|
+
/** @type {toa.node.define.operations.Define} */
|
|
6
|
+
const define = (descriptor) => {
|
|
7
|
+
const { statement, name } = descriptor
|
|
8
|
+
const node = statement.type === 'ExpressionStatement' ? statement.expression : statement
|
|
9
|
+
|
|
10
|
+
/** @type {toa.node.define.operations.Definition} */
|
|
11
|
+
const definition = {}
|
|
12
|
+
|
|
13
|
+
definition.type = /** @type {typeof toa.norm.component.Operation.type} */ name
|
|
14
|
+
|
|
15
|
+
if (node.params.length > 1) definition.scope = scope(node.params[1].name)
|
|
16
|
+
else definition.scope = 'none'
|
|
17
|
+
|
|
18
|
+
if (node.params.length === 0) definition.input = null
|
|
19
|
+
|
|
20
|
+
return definition
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** @type {toa.node.define.operations.Test} */
|
|
24
|
+
const test = (statement, type) => {
|
|
25
|
+
const node = statement.type === 'ExpressionStatement' ? statement.expression : statement
|
|
26
|
+
const func = nodes.includes(node.type)
|
|
27
|
+
const known = types.includes(type)
|
|
28
|
+
|
|
29
|
+
return func && known
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} name
|
|
34
|
+
* @returns {typeof toa.norm.component.Operation.scope}
|
|
35
|
+
*/
|
|
36
|
+
const scope = (name) => scopes.includes(name) ? name : undefined
|
|
37
|
+
|
|
38
|
+
const nodes = ['FunctionDeclaration', 'ArrowFunctionExpression', 'ClassMethod']
|
|
39
|
+
|
|
40
|
+
exports.define = define
|
|
41
|
+
exports.test = test
|
package/src/define/index.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { events
|
|
4
|
-
const { receivers
|
|
5
|
-
const {
|
|
3
|
+
const { events } = require('./events')
|
|
4
|
+
const { receivers } = require('./receivers')
|
|
5
|
+
const { operations } = require('./operations')
|
|
6
6
|
|
|
7
|
-
exports.event = event
|
|
8
7
|
exports.events = events
|
|
9
|
-
exports.receiver = receiver
|
|
10
8
|
exports.receivers = receivers
|
|
11
|
-
exports.operation = operation
|
|
12
9
|
exports.operations = operations
|
package/src/define/operations.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { definition } = require('./operations/definition')
|
|
4
3
|
const load = require('../load')
|
|
4
|
+
const algorithm = require('./.operations')
|
|
5
5
|
|
|
6
|
+
/** @type {toa.node.define.Algorithms} */
|
|
6
7
|
const operations = async (root) => {
|
|
7
8
|
const modules = await load.operations(root)
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
/** @type {toa.node.define.algorithms.List} */
|
|
11
|
+
const algorithms = {}
|
|
12
|
+
|
|
13
|
+
for (const [name, module] of modules) algorithms[name] = algorithm.define(module)
|
|
14
|
+
|
|
15
|
+
return algorithms
|
|
10
16
|
}
|
|
11
17
|
|
|
18
|
+
const extract = (module) => algorithm.extract(module)
|
|
19
|
+
|
|
12
20
|
exports.operations = operations
|
|
21
|
+
exports.extract = extract
|
package/src/event.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.core.bridges.Event}
|
|
7
|
+
*/
|
|
8
|
+
class Event extends Connector {
|
|
4
9
|
#event
|
|
5
10
|
|
|
6
11
|
constructor (event) {
|
|
12
|
+
super()
|
|
13
|
+
|
|
7
14
|
this.#event = event
|
|
8
15
|
}
|
|
9
16
|
|
package/src/factory.js
CHANGED
|
@@ -1,28 +1,48 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const load = require('./load')
|
|
4
|
-
const {
|
|
4
|
+
const { Runner } = require('./algorithms/runner')
|
|
5
5
|
const { Event } = require('./event')
|
|
6
6
|
const { Receiver } = require('./receiver')
|
|
7
7
|
const { Context } = require('./context')
|
|
8
|
+
const { extract } = require('./define/operations')
|
|
8
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @implements {toa.core.bridges.Factory}
|
|
12
|
+
*/
|
|
9
13
|
class Factory {
|
|
10
|
-
|
|
11
|
-
const
|
|
14
|
+
algorithm (root, name, context) {
|
|
15
|
+
const module = load.operation(root, name)
|
|
12
16
|
const ctx = new Context(context)
|
|
13
17
|
|
|
14
|
-
return
|
|
18
|
+
return runner(module, ctx)
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
event (root, label) {
|
|
18
22
|
const event = load.event(root, label)
|
|
23
|
+
|
|
19
24
|
return new Event(event)
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
receiver (root, label) {
|
|
23
28
|
const receiver = load.receiver(root, label)
|
|
29
|
+
|
|
24
30
|
return new Receiver(receiver)
|
|
25
31
|
}
|
|
26
32
|
}
|
|
27
33
|
|
|
34
|
+
/**
|
|
35
|
+
* @param {Object} module
|
|
36
|
+
* @param {toa.node.Context} context
|
|
37
|
+
* @returns {Runner}
|
|
38
|
+
*/
|
|
39
|
+
function runner (module, context) {
|
|
40
|
+
const descriptor = extract(module)
|
|
41
|
+
const func = module[descriptor.name]
|
|
42
|
+
const factory = require('./algorithms/' + descriptor.syntax)
|
|
43
|
+
const ctor = () => factory.create(func, context)
|
|
44
|
+
|
|
45
|
+
return new Runner(ctor, context)
|
|
46
|
+
}
|
|
47
|
+
|
|
28
48
|
exports.Factory = Factory
|
package/src/index.js
CHANGED
package/src/load.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { basename, resolve } = require('path')
|
|
4
|
-
const glob = require('
|
|
4
|
+
const { file: { glob } } = require('@toa.io/filesystem')
|
|
5
5
|
|
|
6
6
|
const operation = (root, name) => load(root, OPERATIONS_DIRECTORY, name)
|
|
7
7
|
const event = (root, name) => load(root, EVENTS_DIRECTORY, name)
|
package/src/receiver.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const { Connector } = require('@toa.io/core')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.core.bridges.Receiver}
|
|
7
|
+
*/
|
|
8
|
+
class Receiver extends Connector {
|
|
4
9
|
#receiver
|
|
5
10
|
|
|
6
11
|
constructor (receiver) {
|
|
12
|
+
super()
|
|
13
|
+
|
|
7
14
|
this.#receiver = receiver
|
|
8
15
|
}
|
|
9
16
|
|