@toa.io/bridges.node 0.2.0-dev.0 → 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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
const { Connector } = require('@toa.io/core')
|
|
5
|
+
|
|
6
|
+
const { Runner } = require('../src/algorithms/runner')
|
|
7
|
+
|
|
8
|
+
it('should be', () => {
|
|
9
|
+
expect(Runner).toBeDefined()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const context = /** @type {toa.node.Context} */ new Connector()
|
|
13
|
+
|
|
14
|
+
it('should return output', async () => {
|
|
15
|
+
const values = [{ [generate()]: generate() }, generate()]
|
|
16
|
+
|
|
17
|
+
for (const value of values) {
|
|
18
|
+
const run = () => value
|
|
19
|
+
const ctor = () => /** @type {toa.core.bridges.Algorithm} */ ({ run })
|
|
20
|
+
const runner = new Runner(ctor, context)
|
|
21
|
+
|
|
22
|
+
await runner.connect()
|
|
23
|
+
|
|
24
|
+
const reply = await runner.run()
|
|
25
|
+
|
|
26
|
+
expect(reply.output).toStrictEqual(value)
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should not return undefined output', async () => {
|
|
31
|
+
const run = () => undefined
|
|
32
|
+
const ctor = () => ({ run })
|
|
33
|
+
const runner = new Runner(ctor, context)
|
|
34
|
+
|
|
35
|
+
await runner.connect()
|
|
36
|
+
|
|
37
|
+
const reply = await runner.run()
|
|
38
|
+
|
|
39
|
+
expect(reply).toStrictEqual(undefined)
|
|
40
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const configuration = { foo: { bar: generate() } }
|
|
6
|
+
|
|
7
|
+
const context = /** @type {toa.core.Context} */ {
|
|
8
|
+
apply: jest.fn(),
|
|
9
|
+
call: jest.fn(),
|
|
10
|
+
aspects: [
|
|
11
|
+
{
|
|
12
|
+
name: 'configuration',
|
|
13
|
+
invoke: jest.fn(() => configuration)
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
link: jest.fn(),
|
|
17
|
+
connect: jest.fn()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.context = context
|
|
21
|
+
exports.configuration = configuration
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const fixtures = require('./context.configuration.fixtures')
|
|
4
|
+
const { Context } = require('../src/context')
|
|
5
|
+
|
|
6
|
+
let context
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
jest.clearAllMocks()
|
|
10
|
+
|
|
11
|
+
context = new Context(fixtures.context)
|
|
12
|
+
|
|
13
|
+
await context.connect()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should expose aspect', async () => {
|
|
17
|
+
expect(context.aspects.configuration).toBeDefined()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should expose values', () => {
|
|
21
|
+
expect(context.configuration).toStrictEqual(fixtures.configuration)
|
|
22
|
+
expect(context.configuration.foo).toStrictEqual(fixtures.configuration.foo)
|
|
23
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const context = /** @type {toa.core.Context} */ {
|
|
4
|
+
apply: jest.fn(),
|
|
5
|
+
call: jest.fn(),
|
|
6
|
+
aspects: [
|
|
7
|
+
{
|
|
8
|
+
name: 'origins',
|
|
9
|
+
invoke: jest.fn()
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
link: jest.fn(),
|
|
13
|
+
connect: jest.fn()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.context = context
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { generate } = require('randomstring')
|
|
4
|
+
|
|
5
|
+
const fixtures = require('./context.origins.fixtures')
|
|
6
|
+
const { Context } = require('../src/context')
|
|
7
|
+
|
|
8
|
+
const origins = fixtures.context.aspects[0]
|
|
9
|
+
|
|
10
|
+
let context
|
|
11
|
+
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
jest.clearAllMocks()
|
|
14
|
+
|
|
15
|
+
context = new Context(fixtures.context)
|
|
16
|
+
|
|
17
|
+
await context.connect()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should expose aspect', async () => {
|
|
21
|
+
expect(context.aspects.origins).toBeDefined()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should invoke', async () => {
|
|
25
|
+
const name = generate()
|
|
26
|
+
const arg = { [generate()]: generate() }
|
|
27
|
+
|
|
28
|
+
await context.origins[name].baz.quu.get(arg)
|
|
29
|
+
|
|
30
|
+
expect(origins.invoke).toHaveBeenCalled()
|
|
31
|
+
expect(origins.invoke).toHaveBeenCalledWith(name, 'baz/quu', expect.objectContaining(arg), undefined)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should define request method', async () => {
|
|
35
|
+
const arg = { [generate()]: generate() }
|
|
36
|
+
|
|
37
|
+
await context.origins.foo.post(arg)
|
|
38
|
+
await context.origins.bar.baz.put()
|
|
39
|
+
|
|
40
|
+
expect(origins.invoke).toHaveBeenNthCalledWith(1, 'foo', '', { method: 'POST', ...arg }, undefined)
|
|
41
|
+
expect(origins.invoke).toHaveBeenNthCalledWith(2, 'bar', 'baz', { method: 'PUT' }, undefined)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('should throw if no origin name specified', async () => {
|
|
45
|
+
await expect(context.origins.get()).rejects.toThrow(/at least 2 arguments/)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should pass options', async () => {
|
|
49
|
+
const options = { [generate()]: generate() }
|
|
50
|
+
await context.origins.foo.post({}, options)
|
|
51
|
+
|
|
52
|
+
expect(origins.invoke.mock.calls[0][3]).toStrictEqual(options)
|
|
53
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { resolve } = require('node:path')
|
|
4
|
+
const define = require('../src/define')
|
|
5
|
+
|
|
6
|
+
it('should be', () => {
|
|
7
|
+
expect(define.operations).toBeDefined()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const DUMMIES = resolve(__dirname, 'dummies')
|
|
11
|
+
const find = (component) => resolve(DUMMIES, component)
|
|
12
|
+
|
|
13
|
+
const root = find('one')
|
|
14
|
+
|
|
15
|
+
/** @type {toa.node.define.algorithms.List} */
|
|
16
|
+
let operations
|
|
17
|
+
|
|
18
|
+
beforeAll(async () => {
|
|
19
|
+
operations = await define.operations(root)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should be', () => {
|
|
23
|
+
expect(operations).toBeDefined()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('should find function operations', () => {
|
|
27
|
+
expect(operations.fn).toBeDefined()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should find class operations', () => {
|
|
31
|
+
expect(operations.cls).toBeDefined()
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should find factory operations', () => {
|
|
35
|
+
expect(operations.fct).toBeDefined()
|
|
36
|
+
})
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// noinspection JSUnusedLocalSymbols,JSUnusedGlobalSymbols
|
|
2
|
+
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
const { define } = require('../src/define/.operations')
|
|
6
|
+
|
|
7
|
+
it('should be', () => {
|
|
8
|
+
expect(define).toBeDefined()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
/** @type {toa.node.define.operations.Definition} */
|
|
12
|
+
let definition
|
|
13
|
+
|
|
14
|
+
it('should throw if function does not match conventions', () => {
|
|
15
|
+
const append = () => null
|
|
16
|
+
const module = { append }
|
|
17
|
+
|
|
18
|
+
expect(() => define(module)).toThrow('does not match conventions')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('should throw if class does not match conventions', () => {
|
|
22
|
+
class Foo {}
|
|
23
|
+
|
|
24
|
+
const module = { Foo }
|
|
25
|
+
|
|
26
|
+
expect(() => define(module)).toThrow('does not match conventions')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should throw if no function exported', () => {
|
|
30
|
+
const foo = 'bar'
|
|
31
|
+
const module = { foo }
|
|
32
|
+
|
|
33
|
+
expect(() => define(module)).toThrow('Module does not export function')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
describe('function', () => {
|
|
37
|
+
it('should parse declaration', () => {
|
|
38
|
+
function transition (input, object) {}
|
|
39
|
+
|
|
40
|
+
const module = { transition }
|
|
41
|
+
const definition = define(module)
|
|
42
|
+
|
|
43
|
+
expect(definition).toMatchObject({ type: 'transition', scope: 'object' })
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('should parse expression', () => {
|
|
47
|
+
const observation = (input, objects) => null
|
|
48
|
+
const module = { observation }
|
|
49
|
+
const definition = define(module)
|
|
50
|
+
|
|
51
|
+
expect(definition).toMatchObject({ type: 'observation', scope: 'objects' })
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should parse scope changeset', () => {
|
|
55
|
+
const assignment = (input, changeset) => null
|
|
56
|
+
const module = { assignment }
|
|
57
|
+
const definition = define(module)
|
|
58
|
+
|
|
59
|
+
expect(definition.scope).toStrictEqual('changeset')
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('should not define unknown scope', () => {
|
|
63
|
+
const assignment = (input, message) => null
|
|
64
|
+
const module = { assignment }
|
|
65
|
+
const definition = define(module)
|
|
66
|
+
|
|
67
|
+
expect(definition.scope).toStrictEqual(undefined)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('should define none scope', async () => {
|
|
71
|
+
const observation = (input) => null
|
|
72
|
+
const module = { observation }
|
|
73
|
+
const definition = define(module)
|
|
74
|
+
|
|
75
|
+
expect(definition.scope).toStrictEqual('none')
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('should define none scope for _', async () => {
|
|
79
|
+
const observation = (input, none, context) => null
|
|
80
|
+
const module = { observation }
|
|
81
|
+
const definition = define(module)
|
|
82
|
+
|
|
83
|
+
expect(definition.scope).toStrictEqual('none')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('should define null input', async () => {
|
|
87
|
+
const observation = () => null
|
|
88
|
+
const module = { observation }
|
|
89
|
+
const definition = define(module)
|
|
90
|
+
|
|
91
|
+
expect(definition.input).toStrictEqual(null)
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
describe('class', () => {
|
|
96
|
+
class Transition {
|
|
97
|
+
run (input, object) {}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const module = { Transition }
|
|
101
|
+
|
|
102
|
+
beforeAll(() => {
|
|
103
|
+
definition = define(module)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('should define type', () => {
|
|
107
|
+
expect(definition.type).toStrictEqual('transition')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('should define scope', () => {
|
|
111
|
+
expect(definition.scope).toStrictEqual('object')
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('should find run method', () => {
|
|
115
|
+
class Assignment {
|
|
116
|
+
execute (input, objects) {}
|
|
117
|
+
|
|
118
|
+
run (input, object) {}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const module = { Assignment }
|
|
122
|
+
const definition = define(module)
|
|
123
|
+
|
|
124
|
+
expect(definition).toMatchObject({ type: 'assignment', scope: 'object' })
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('should throw if no run method found', () => {
|
|
128
|
+
class Observation {}
|
|
129
|
+
|
|
130
|
+
const module = { Observation }
|
|
131
|
+
|
|
132
|
+
expect(() => define(module)).toThrow('Method \'run\' not found')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('should throw if function is not a class', () => {
|
|
136
|
+
function Transition () {}
|
|
137
|
+
|
|
138
|
+
const module = { Transition }
|
|
139
|
+
|
|
140
|
+
expect(() => define(module)).toThrow('does not match conventions')
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it('should define none scope', async () => {
|
|
144
|
+
class Observation {
|
|
145
|
+
run (input) {}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const module = { Observation }
|
|
149
|
+
const definition = define(module)
|
|
150
|
+
|
|
151
|
+
expect(definition.scope).toStrictEqual('none')
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('should define null input', async () => {
|
|
155
|
+
class Observation {
|
|
156
|
+
run () {}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const module = { Observation }
|
|
160
|
+
const definition = define(module)
|
|
161
|
+
|
|
162
|
+
expect(definition.input).toStrictEqual(null)
|
|
163
|
+
})
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
describe('factory', () => {
|
|
167
|
+
class ObjectTransitionFactory {
|
|
168
|
+
create () {}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const module = { ObjectTransitionFactory }
|
|
172
|
+
|
|
173
|
+
beforeAll(() => {
|
|
174
|
+
definition = define(module)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('should define type', () => {
|
|
178
|
+
expect(definition.type).toStrictEqual('transition')
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
it('should define scope', () => {
|
|
182
|
+
expect(definition.scope).toStrictEqual('object')
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('should define none scope', async () => {
|
|
186
|
+
class NoneObservationFactory {
|
|
187
|
+
create () {}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const module = { NoneObservationFactory }
|
|
191
|
+
const definition = define(module)
|
|
192
|
+
|
|
193
|
+
expect(definition.scope).toStrictEqual('none')
|
|
194
|
+
})
|
|
195
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @implements {toa.core.bridges.Algorithm}
|
|
5
|
+
*/
|
|
6
|
+
class Transition {
|
|
7
|
+
#context
|
|
8
|
+
|
|
9
|
+
constructor (context) {
|
|
10
|
+
this.#context = context
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async run (input, object) {
|
|
14
|
+
return { output: { input, state: object, context: this.#context !== undefined } }
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
exports.Transition = Transition
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { Transition } = require('./cls')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.node.algorithms.Factory}
|
|
7
|
+
*/
|
|
8
|
+
class ObjectTransitionFactory {
|
|
9
|
+
#context
|
|
10
|
+
|
|
11
|
+
constructor (context) {
|
|
12
|
+
this.#context = context
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
create () {
|
|
16
|
+
return new Transition(this.#context)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.ObjectTransitionFactory = ObjectTransitionFactory
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { resolve } = require('node:path')
|
|
4
|
+
const { generate } = require('randomstring')
|
|
5
|
+
const { Connector } = require('@toa.io/core')
|
|
6
|
+
|
|
7
|
+
const { Factory } = require('../src/factory')
|
|
8
|
+
|
|
9
|
+
const root = resolve(__dirname, 'dummies/one')
|
|
10
|
+
|
|
11
|
+
let factory
|
|
12
|
+
|
|
13
|
+
const context = new Connector()
|
|
14
|
+
const input = generate()
|
|
15
|
+
const state = generate()
|
|
16
|
+
|
|
17
|
+
context.aspects = []
|
|
18
|
+
|
|
19
|
+
beforeAll(() => {
|
|
20
|
+
factory = new Factory()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should be', () => {
|
|
24
|
+
expect(factory.algorithm).toBeDefined()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
for (const sample of ['fn', 'cls', 'fct']) {
|
|
28
|
+
it(`should create '${sample}' operation`, async () => {
|
|
29
|
+
const algorithm = factory.algorithm(root, sample, context)
|
|
30
|
+
|
|
31
|
+
expect(algorithm).toBeDefined()
|
|
32
|
+
|
|
33
|
+
await algorithm.connect()
|
|
34
|
+
|
|
35
|
+
const promise = algorithm.run(input, state)
|
|
36
|
+
|
|
37
|
+
await expect(promise).resolves.not.toThrow()
|
|
38
|
+
|
|
39
|
+
const response = await promise
|
|
40
|
+
|
|
41
|
+
expect(response.output).toStrictEqual({ input, state, context: true })
|
|
42
|
+
})
|
|
43
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Underlay } from '@toa.io/generic/types'
|
|
2
|
+
import { Connector } from "@toa.io/core/types";
|
|
3
|
+
|
|
4
|
+
declare namespace toa.node {
|
|
5
|
+
|
|
6
|
+
interface Aspectes {
|
|
7
|
+
[key: string]: Function
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Context extends Connector {
|
|
11
|
+
local: Underlay
|
|
12
|
+
remote: Underlay
|
|
13
|
+
aspects: Aspectes
|
|
14
|
+
|
|
15
|
+
// known extensions
|
|
16
|
+
origins?: Underlay
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type Context = toa.node.Context
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Operation } from '@toa.io/norm/types'
|
|
2
|
+
import { Node, Statement } from '@babel/types'
|
|
3
|
+
import { bridges } from '@toa.io/core/types'
|
|
4
|
+
import * as context from './context'
|
|
5
|
+
|
|
6
|
+
declare namespace toa.node.define {
|
|
7
|
+
|
|
8
|
+
namespace algorithms {
|
|
9
|
+
type Definition = Partial<Operation>
|
|
10
|
+
|
|
11
|
+
type List = Record<string, Definition>
|
|
12
|
+
|
|
13
|
+
type Syntax = 'function' | 'class' | 'factory'
|
|
14
|
+
|
|
15
|
+
type Descriptor = {
|
|
16
|
+
name: string
|
|
17
|
+
statement: Statement
|
|
18
|
+
syntax: Syntax
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type Define = (descriptor: Descriptor) => Definition
|
|
22
|
+
|
|
23
|
+
type Test = (node: Node, type: string) => boolean
|
|
24
|
+
|
|
25
|
+
type Constructor = (func: Function, context: context.Context) => bridges.Algorithm
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type Algorithms = (root: string) => Promise<algorithms.List>
|
|
29
|
+
|
|
30
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2020-present Artem Gurtovoi
|
|
2
|
-
|
|
3
|
-
MIT License
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
-
a copy of this software and associated documentation files (the
|
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
-
the following conditions:
|
|
12
|
-
|
|
13
|
-
The above copyright notice and this permission notice shall be
|
|
14
|
-
included in all copies or substantial portions of the Software.
|
|
15
|
-
|
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const parser = require('@babel/parser')
|
|
4
|
-
const { merge } = require('@toa.io/gears')
|
|
5
|
-
|
|
6
|
-
const definition = (module) => {
|
|
7
|
-
const definition = {}
|
|
8
|
-
|
|
9
|
-
if (typeof module.transition === 'function') definition.type = 'transition'
|
|
10
|
-
if (typeof module.observation === 'function') definition.type = 'observation'
|
|
11
|
-
if (typeof module.assignment === 'function') definition.type = 'assignment'
|
|
12
|
-
|
|
13
|
-
if (definition.type === undefined) {
|
|
14
|
-
throw new Error('Operation must export either transition, observation or assignment function')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const func = module[definition.type]
|
|
18
|
-
const meta = parse(func)
|
|
19
|
-
|
|
20
|
-
return merge(definition, meta)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const parse = (func) => {
|
|
24
|
-
const ast = parser.parse(func.toString())
|
|
25
|
-
|
|
26
|
-
return node(ast.program.body[0])
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function node (node) {
|
|
30
|
-
if (node.type === 'ExpressionStatement') node = node.expression
|
|
31
|
-
if (node.async !== true) { throw new Error('Operation must export async function') }
|
|
32
|
-
|
|
33
|
-
const result = {}
|
|
34
|
-
|
|
35
|
-
if (node.params.length > 1) result.subject = node.params[1]?.name
|
|
36
|
-
|
|
37
|
-
return result
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
exports.definition = definition
|
package/src/operation.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Connector } = require('@toa.io/core')
|
|
4
|
-
|
|
5
|
-
class Operation extends Connector {
|
|
6
|
-
#operation
|
|
7
|
-
#context
|
|
8
|
-
|
|
9
|
-
constructor (operation, context) {
|
|
10
|
-
super()
|
|
11
|
-
|
|
12
|
-
this.#operation = operation.transition || operation.observation || operation.assignment
|
|
13
|
-
this.#context = context
|
|
14
|
-
|
|
15
|
-
this.depends(context)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async run (input, state) {
|
|
19
|
-
return this.#operation(input, state, this.#context)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
exports.Operation = Operation
|
package/test/operation.test.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Connector } = require('@toa.io/core')
|
|
4
|
-
|
|
5
|
-
const { Operation } = require('../src/operation')
|
|
6
|
-
const fixtures = require('./operation.fixtures')
|
|
7
|
-
|
|
8
|
-
let operation
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
operation = new Operation(fixtures.operation, fixtures.context)
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
it('should extend Connector', () => {
|
|
15
|
-
expect(Operation.prototype).toBeInstanceOf(Connector)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('should run algorithm', async () => {
|
|
19
|
-
await operation.run({ input: 1 })
|
|
20
|
-
|
|
21
|
-
expect(fixtures.operation.observation).toHaveBeenCalled()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('should pass input, state, context', async () => {
|
|
25
|
-
const input = { a: 1 }
|
|
26
|
-
const state = { b: 2 }
|
|
27
|
-
|
|
28
|
-
await operation.run(input, state)
|
|
29
|
-
|
|
30
|
-
expect(fixtures.operation.observation).toHaveBeenCalledWith(input, state, fixtures.context)
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('should return output', async () => {
|
|
34
|
-
const reply = await operation.run()
|
|
35
|
-
const result = await fixtures.operation.observation.mock.results[0].value
|
|
36
|
-
|
|
37
|
-
expect(reply).toBeDefined()
|
|
38
|
-
expect(reply).toStrictEqual(result)
|
|
39
|
-
})
|