@toa.io/core 0.2.0-dev.3 → 0.2.1-dev.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.
- package/package.json +5 -4
- package/src/assignment.js +7 -7
- package/src/cascade.js +1 -1
- package/src/{runtime.js → component.js} +7 -4
- package/src/composition.js +6 -7
- package/src/connector.js +89 -24
- package/src/context.js +23 -11
- package/src/contract/reply.js +4 -1
- package/src/contract/request.js +13 -3
- package/src/contract/schemas/index.js +4 -3
- package/src/discovery.js +11 -0
- package/src/entities/changeset.js +4 -3
- package/src/entities/entity.js +17 -6
- package/src/entities/factory.js +3 -3
- package/src/event.js +12 -5
- package/src/exceptions.js +9 -1
- package/src/exposition.js +12 -9
- package/src/index.js +4 -2
- package/src/locator.js +21 -35
- package/src/observation.js +6 -6
- package/src/operation.js +20 -13
- package/src/query/options.js +4 -7
- package/src/query.js +6 -1
- package/src/receiver.js +36 -7
- package/src/reflection.js +28 -0
- package/src/remote.js +3 -3
- package/src/state.js +33 -25
- package/src/transition.js +24 -16
- package/test/call.fixtures.js +1 -0
- package/test/{runtime.fixtures.js → component.fixtures.js} +4 -2
- package/test/{runtime.test.js → component.test.js} +7 -7
- package/test/connector.fixtures.js +1 -1
- package/test/connector.test.js +6 -29
- package/test/context.fixtures.js +18 -0
- package/test/context.test.js +29 -0
- package/test/contract/contract.fixtures.js +8 -3
- package/test/contract/request.test.js +14 -3
- package/test/emission.fixtures.js +1 -0
- package/test/entities/entity.fixtures.js +4 -4
- package/test/entities/entity.test.js +22 -10
- package/test/entities/factory.test.js +6 -6
- package/test/event.fixtures.js +1 -0
- package/test/event.test.js +16 -4
- package/test/locator.test.js +76 -19
- package/test/receiver.fixtures.js +6 -5
- package/test/receiver.test.js +36 -7
- package/test/reflection.test.js +30 -0
- package/test/state.fixtures.js +6 -5
- package/test/state.test.js +8 -16
- package/types/bindings.d.ts +39 -0
- package/types/bridges.d.ts +35 -0
- package/types/component.ts +16 -0
- package/types/connector.d.ts +22 -0
- package/types/context.d.ts +24 -0
- package/types/entity.d.ts +46 -0
- package/types/event.d.ts +11 -0
- package/types/exception.d.ts +10 -0
- package/types/extensions.d.ts +36 -0
- package/types/index.d.ts +14 -0
- package/types/locator.d.ts +16 -0
- package/types/message.d.ts +9 -0
- package/types/query.d.ts +15 -0
- package/types/receiver.d.ts +12 -0
- package/types/reflection.d.ts +16 -0
- package/types/reply.d.ts +15 -0
- package/types/request.d.ts +25 -0
- package/types/state.d.ts +35 -0
- package/types/storages.d.ts +71 -0
- package/LICENSE +0 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1-dev.0",
|
|
4
4
|
"description": "Toa Core",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -20,9 +20,10 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@rsql/parser": "1.2.4",
|
|
23
|
-
"@toa.io/
|
|
24
|
-
"@toa.io/
|
|
23
|
+
"@toa.io/console": "*",
|
|
24
|
+
"@toa.io/generic": "*",
|
|
25
|
+
"@toa.io/yaml": "*",
|
|
25
26
|
"clone-deep": "4.0.1"
|
|
26
27
|
},
|
|
27
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "2be07592325b2e4dc823e81d882a4e50bf50de24"
|
|
28
29
|
}
|
package/src/assignment.js
CHANGED
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
const { Operation } = require('./operation')
|
|
4
4
|
|
|
5
5
|
class Assignment extends Operation {
|
|
6
|
-
async acquire (
|
|
7
|
-
scope
|
|
8
|
-
|
|
6
|
+
async acquire (store) {
|
|
7
|
+
store.scope = this.scope.changeset(store.request.query)
|
|
8
|
+
store.state = store.scope.get()
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
async commit (
|
|
12
|
-
const {
|
|
11
|
+
async commit (store) {
|
|
12
|
+
const { scope, state, reply } = store
|
|
13
13
|
|
|
14
14
|
if (reply.error !== undefined) return
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
scope.set(state)
|
|
17
17
|
|
|
18
|
-
await this.
|
|
18
|
+
await this.scope.apply(scope)
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
package/src/cascade.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { console } = require('@toa.io/
|
|
3
|
+
const { console } = require('@toa.io/console')
|
|
4
4
|
const { Connector } = require('./connector')
|
|
5
5
|
const { NotImplementedException } = require('./exceptions')
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* @implements {toa.core.Component}
|
|
9
|
+
*/
|
|
10
|
+
class Component extends Connector {
|
|
8
11
|
locator
|
|
9
12
|
|
|
10
13
|
#operations
|
|
@@ -18,7 +21,7 @@ class Runtime extends Connector {
|
|
|
18
21
|
Object.values(operations).forEach((operation) => this.depends(operation))
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
connection () {
|
|
24
|
+
async connection () {
|
|
22
25
|
console.info(`Runtime '${this.locator.id}' connected`)
|
|
23
26
|
}
|
|
24
27
|
|
|
@@ -35,4 +38,4 @@ class Runtime extends Connector {
|
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
exports.
|
|
41
|
+
exports.Component = Component
|
package/src/composition.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { console } = require('@toa.io/
|
|
4
|
-
|
|
3
|
+
const { console } = require('@toa.io/console')
|
|
5
4
|
const { Connector } = require('./connector')
|
|
6
5
|
|
|
7
6
|
class Composition extends Connector {
|
|
8
|
-
constructor (expositions, producers, receivers,
|
|
7
|
+
constructor (expositions, producers, receivers, tenants) {
|
|
9
8
|
super()
|
|
10
9
|
|
|
11
|
-
this.depends(expositions)
|
|
12
|
-
this.depends(producers)
|
|
13
|
-
this.depends(receivers)
|
|
14
|
-
this.depends(
|
|
10
|
+
if (expositions.length > 0) this.depends(expositions)
|
|
11
|
+
if (producers.length > 0) this.depends(producers)
|
|
12
|
+
if (receivers.length > 0) this.depends(receivers)
|
|
13
|
+
if (tenants.length > 0) this.depends(tenants)
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
async connection () {
|
package/src/connector.js
CHANGED
|
@@ -1,60 +1,93 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { console } = require('@toa.io/
|
|
4
|
-
const { newid } = require('@toa.io/
|
|
5
|
-
|
|
3
|
+
const { console } = require('@toa.io/console')
|
|
4
|
+
const { newid } = require('@toa.io/generic')
|
|
5
|
+
|
|
6
|
+
// noinspection JSClosureCompilerSyntax
|
|
7
|
+
/**
|
|
8
|
+
* Abstract connections hierarchy
|
|
9
|
+
* @implements {toa.core.Connector}
|
|
10
|
+
*/
|
|
6
11
|
class Connector {
|
|
7
|
-
|
|
8
|
-
#
|
|
12
|
+
/** @type {Array<Connector>} */
|
|
13
|
+
#dependencies = []
|
|
14
|
+
/** @type {Array<Connector>} */
|
|
15
|
+
#links = []
|
|
16
|
+
/** @type {Promise} */
|
|
9
17
|
#connecting
|
|
18
|
+
/** @type {Promise} */
|
|
10
19
|
#disconnecting
|
|
11
20
|
|
|
21
|
+
/** @type {string} */
|
|
12
22
|
id
|
|
23
|
+
/** @type {boolean} */
|
|
13
24
|
connected = false
|
|
14
25
|
|
|
15
26
|
constructor () {
|
|
16
27
|
this.id = this.constructor.name + '#' + newid().substring(0, 8)
|
|
17
28
|
}
|
|
18
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Creates a dependency and backlink with another Connector or a set of Connectors
|
|
32
|
+
*
|
|
33
|
+
* See .connect() and .disconnect()
|
|
34
|
+
*
|
|
35
|
+
* @param connector {Connector | any | Array<Connector | any>}
|
|
36
|
+
* @returns {Connector}
|
|
37
|
+
*/
|
|
19
38
|
depends (connector) {
|
|
39
|
+
/** @type {Connector} */
|
|
20
40
|
let next
|
|
21
41
|
|
|
22
42
|
if (connector instanceof Array) {
|
|
23
|
-
connector
|
|
43
|
+
if (connector.length === 0) throw new Error('Connectors array must not be empty')
|
|
24
44
|
|
|
25
|
-
if (connector.length >
|
|
45
|
+
if (connector.length > 1) {
|
|
26
46
|
next = new Connector()
|
|
27
47
|
|
|
28
48
|
for (const item of connector) {
|
|
29
|
-
this.#
|
|
49
|
+
this.#dependencies.push(item)
|
|
30
50
|
item.depends(next)
|
|
31
51
|
}
|
|
32
|
-
}
|
|
33
|
-
} else
|
|
34
|
-
if (connector instanceof Connector) {
|
|
35
|
-
next = connector
|
|
36
|
-
}
|
|
37
|
-
}
|
|
52
|
+
} else next = connector[0]
|
|
53
|
+
} else next = connector
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
next.link(this)
|
|
55
|
+
this.#dependencies.push(next)
|
|
56
|
+
next.link(this)
|
|
42
57
|
|
|
43
|
-
|
|
44
|
-
} else return this
|
|
58
|
+
return next
|
|
45
59
|
}
|
|
46
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Creates a backlink to another Connector
|
|
63
|
+
*
|
|
64
|
+
* See .connect() and .disconnect()
|
|
65
|
+
*
|
|
66
|
+
* @param connector {Connector}
|
|
67
|
+
* @returns {void}
|
|
68
|
+
*/
|
|
47
69
|
link (connector) {
|
|
48
|
-
this.#
|
|
70
|
+
this.#links.push(connector)
|
|
49
71
|
}
|
|
50
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Connects dependants then self
|
|
75
|
+
*
|
|
76
|
+
* In case of exception disconnects with current connection interruption
|
|
77
|
+
*
|
|
78
|
+
* Method is idempotent
|
|
79
|
+
*
|
|
80
|
+
* @returns {Promise<void>}
|
|
81
|
+
*/
|
|
51
82
|
async connect () {
|
|
52
83
|
if (this.#connecting) return this.#connecting
|
|
53
84
|
|
|
54
85
|
this.#disconnecting = undefined
|
|
55
86
|
|
|
87
|
+
console.debug(`Connecting '${this.id}' with ${this.#dependencies.length} dependencies...`)
|
|
88
|
+
|
|
56
89
|
this.#connecting = (async () => {
|
|
57
|
-
await Promise.all(this.#
|
|
90
|
+
await Promise.all(this.#dependencies.map((connector) => connector.connect()))
|
|
58
91
|
await this.connection()
|
|
59
92
|
})()
|
|
60
93
|
|
|
@@ -69,12 +102,22 @@ class Connector {
|
|
|
69
102
|
console.debug(`Connector '${this.id}' connected`)
|
|
70
103
|
}
|
|
71
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Disconnects self then dependants
|
|
107
|
+
*
|
|
108
|
+
* Does nothing if there are connected linked Connectors
|
|
109
|
+
*
|
|
110
|
+
* Method is idempotent
|
|
111
|
+
*
|
|
112
|
+
* @param [interrupt] {boolean}
|
|
113
|
+
* @returns {Promise<void>}
|
|
114
|
+
*/
|
|
72
115
|
async disconnect (interrupt) {
|
|
73
116
|
if (interrupt !== true) await this.#connecting
|
|
74
117
|
|
|
75
118
|
if (this.#disconnecting) return this.#disconnecting
|
|
76
119
|
|
|
77
|
-
const linked = this.#
|
|
120
|
+
const linked = this.#links.reduce((acc, parent) => acc || parent.connected, false)
|
|
78
121
|
|
|
79
122
|
if (linked && interrupt !== true) return
|
|
80
123
|
|
|
@@ -83,6 +126,7 @@ class Connector {
|
|
|
83
126
|
|
|
84
127
|
this.#disconnecting = (async () => {
|
|
85
128
|
const start = +new Date()
|
|
129
|
+
|
|
86
130
|
const interval = setInterval(() => {
|
|
87
131
|
const delay = +new Date() - start
|
|
88
132
|
|
|
@@ -93,7 +137,8 @@ class Connector {
|
|
|
93
137
|
|
|
94
138
|
clearInterval(interval)
|
|
95
139
|
|
|
96
|
-
await Promise.all(this.#
|
|
140
|
+
await Promise.all(this.#dependencies.map(connector => connector.disconnect()))
|
|
141
|
+
|
|
97
142
|
this.disconnected()
|
|
98
143
|
})()
|
|
99
144
|
|
|
@@ -102,18 +147,38 @@ class Connector {
|
|
|
102
147
|
console.debug(`Connector '${this.id}' disconnected`)
|
|
103
148
|
}
|
|
104
149
|
|
|
150
|
+
async reconnect () {
|
|
151
|
+
await this.disconnect()
|
|
152
|
+
await this.connect()
|
|
153
|
+
}
|
|
154
|
+
|
|
105
155
|
debug (node = {}) {
|
|
106
156
|
node[this.id] = { connected: this.connected }
|
|
107
157
|
|
|
108
|
-
if (this.#
|
|
158
|
+
if (this.#dependencies.length > 0) for (const connector of this.#dependencies) connector.debug?.(node[this.id])
|
|
109
159
|
|
|
110
160
|
return node
|
|
111
161
|
}
|
|
112
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Called on connection
|
|
165
|
+
*
|
|
166
|
+
* @returns {Promise<void>}
|
|
167
|
+
*/
|
|
113
168
|
async connection () {}
|
|
114
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Called on disconnection
|
|
172
|
+
*
|
|
173
|
+
* @returns {Promise<void>}
|
|
174
|
+
*/
|
|
115
175
|
async disconnection () {}
|
|
116
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Called after self and dependants disconnection is complete
|
|
179
|
+
*
|
|
180
|
+
* @returns {void}
|
|
181
|
+
*/
|
|
117
182
|
disconnected () {}
|
|
118
183
|
}
|
|
119
184
|
|
package/src/context.js
CHANGED
|
@@ -2,41 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
const { Connector } = require('./connector')
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.core.Context}
|
|
7
|
+
*/
|
|
5
8
|
class Context extends Connector {
|
|
9
|
+
aspects
|
|
10
|
+
|
|
6
11
|
#local
|
|
7
12
|
#discover
|
|
8
13
|
#remotes = {}
|
|
9
14
|
|
|
10
|
-
constructor (local, discover) {
|
|
15
|
+
constructor (local, discover, aspects = []) {
|
|
11
16
|
super()
|
|
12
17
|
|
|
18
|
+
this.aspects = aspects
|
|
19
|
+
|
|
13
20
|
this.#local = local
|
|
14
21
|
this.#discover = discover
|
|
15
22
|
|
|
16
23
|
this.depends(local)
|
|
24
|
+
|
|
25
|
+
if (aspects.length > 0) this.depends(aspects)
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
async apply (endpoint, request) {
|
|
20
29
|
return this.#local.invoke(endpoint, request)
|
|
21
30
|
}
|
|
22
31
|
|
|
23
|
-
async call (
|
|
24
|
-
const remote = await this.#remote(
|
|
32
|
+
async call (namespace, name, endpoint, request) {
|
|
33
|
+
const remote = await this.#remote(namespace, name)
|
|
25
34
|
|
|
26
35
|
return remote.invoke(endpoint, request)
|
|
27
36
|
}
|
|
28
37
|
|
|
29
|
-
async #remote (
|
|
30
|
-
|
|
38
|
+
async #remote (namespace, name) {
|
|
39
|
+
const key = namespace + '.' + name
|
|
40
|
+
|
|
41
|
+
if (this.#remotes[key] === undefined) this.#remotes[key] = this.#connect(namespace, name)
|
|
42
|
+
|
|
43
|
+
return this.#remotes[key]
|
|
44
|
+
}
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
async #connect (namespace, name) {
|
|
47
|
+
const remote = await this.#discover(namespace, name)
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
this.#remotes[domain][name] = remote
|
|
37
|
-
}
|
|
49
|
+
this.depends(remote)
|
|
38
50
|
|
|
39
|
-
return
|
|
51
|
+
return remote
|
|
40
52
|
}
|
|
41
53
|
}
|
|
42
54
|
|
package/src/contract/reply.js
CHANGED
|
@@ -7,8 +7,11 @@ const { ResponseContractException } = require('../exceptions')
|
|
|
7
7
|
class Reply extends Conditions {
|
|
8
8
|
static Exception = ResponseContractException
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* @returns {toa.schema.JSON}
|
|
12
|
+
*/
|
|
10
13
|
static schema (output, error) {
|
|
11
|
-
const schema = { properties: {}, additionalProperties: false }
|
|
14
|
+
const schema = { type: 'object', properties: {}, additionalProperties: false }
|
|
12
15
|
|
|
13
16
|
if (output !== undefined) schema.properties.output = output
|
|
14
17
|
|
package/src/contract/request.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const clone = require('clone-deep')
|
|
4
|
+
|
|
4
5
|
const schemas = require('./schemas')
|
|
5
6
|
const { RequestContractException } = require('../exceptions')
|
|
6
7
|
const { Conditions } = require('./conditions')
|
|
@@ -8,18 +9,27 @@ const { Conditions } = require('./conditions')
|
|
|
8
9
|
class Request extends Conditions {
|
|
9
10
|
static Exception = RequestContractException
|
|
10
11
|
|
|
12
|
+
/**
|
|
13
|
+
* @returns {toa.schema.JSON}
|
|
14
|
+
*/
|
|
11
15
|
static schema (definition) {
|
|
12
|
-
const schema = { properties: {}, additionalProperties:
|
|
16
|
+
const schema = { type: 'object', properties: {}, additionalProperties: true }
|
|
13
17
|
const required = []
|
|
14
18
|
|
|
15
|
-
if (definition.input) {
|
|
19
|
+
if (definition.input !== undefined) {
|
|
16
20
|
definition.input.additionalProperties = false
|
|
17
21
|
schema.properties.input = definition.input
|
|
18
22
|
required.push('input')
|
|
23
|
+
} else {
|
|
24
|
+
schema.properties.input = { type: 'null' }
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
if (definition.query === true) required.push('query')
|
|
22
28
|
|
|
29
|
+
if (definition.query === false) {
|
|
30
|
+
schema.not = { required: ['query'] }
|
|
31
|
+
}
|
|
32
|
+
|
|
23
33
|
if (definition.query !== false) {
|
|
24
34
|
const query = clone(schemas.query)
|
|
25
35
|
|
|
@@ -29,7 +39,7 @@ class Request extends Conditions {
|
|
|
29
39
|
delete query.properties.projection
|
|
30
40
|
}
|
|
31
41
|
|
|
32
|
-
if (definition.type !== 'observation' || definition.
|
|
42
|
+
if (definition.type !== 'observation' || definition.scope !== 'objects') {
|
|
33
43
|
delete query.properties.omit
|
|
34
44
|
delete query.properties.limit
|
|
35
45
|
} else {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { resolve } = require('path')
|
|
4
|
-
const {
|
|
4
|
+
const { load } = require('@toa.io/yaml')
|
|
5
|
+
const { freeze } = require('@toa.io/generic')
|
|
5
6
|
|
|
6
|
-
exports.query = freeze(
|
|
7
|
-
exports.error = freeze(
|
|
7
|
+
exports.query = freeze(load.sync(resolve(__dirname, './query.yaml')))
|
|
8
|
+
exports.error = freeze(load.sync(resolve(__dirname, './error.yaml')))
|
package/src/discovery.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { console } = require('@toa.io/console')
|
|
3
4
|
const { Connector } = require('./connector')
|
|
4
5
|
|
|
5
6
|
class Discovery extends Connector {
|
|
@@ -24,10 +25,20 @@ class Discovery extends Connector {
|
|
|
24
25
|
this.depends(this.#lookups[id])
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
console.debug(`Sending lookup request to '${id}'`)
|
|
29
|
+
|
|
30
|
+
const warning = () => console.warn(`Waiting for lookup response from '${id}'...`)
|
|
31
|
+
const timeout = setTimeout(warning, TIMEOUT)
|
|
32
|
+
|
|
27
33
|
const { output } = await this.#lookups[id].invoke()
|
|
28
34
|
|
|
35
|
+
console.debug(`Lookup response from '${id}' received`)
|
|
36
|
+
clearTimeout(timeout)
|
|
37
|
+
|
|
29
38
|
return output
|
|
30
39
|
}
|
|
31
40
|
}
|
|
32
41
|
|
|
42
|
+
const TIMEOUT = 5000
|
|
43
|
+
|
|
33
44
|
exports.Discovery = Discovery
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { merge, newid } = require('@toa.io/
|
|
3
|
+
const { merge, overwrite, newid } = require('@toa.io/generic')
|
|
4
4
|
const { EntityContractException } = require('../exceptions')
|
|
5
5
|
|
|
6
6
|
class Changeset {
|
|
7
|
+
/** @type {toa.core.Query} */
|
|
7
8
|
query
|
|
8
9
|
|
|
9
10
|
#schema
|
|
@@ -21,7 +22,7 @@ class Changeset {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
set (value) {
|
|
24
|
-
const error = this.#schema.
|
|
25
|
+
const error = this.#schema.adapt(value)
|
|
25
26
|
|
|
26
27
|
if (error !== null) throw new EntityContractException(error)
|
|
27
28
|
|
|
@@ -36,7 +37,7 @@ class Changeset {
|
|
|
36
37
|
|
|
37
38
|
if (error === null) {
|
|
38
39
|
delete insert.id
|
|
39
|
-
result.insert =
|
|
40
|
+
result.insert = overwrite(insert, changeset)
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
return result
|
package/src/entities/entity.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const clone = require('clone-deep')
|
|
4
|
-
const { difference, newid } = require('@toa.io/
|
|
4
|
+
const { difference, newid } = require('@toa.io/generic')
|
|
5
5
|
|
|
6
6
|
const { EntityContractException } = require('../exceptions')
|
|
7
7
|
|
|
@@ -14,11 +14,12 @@ class Entity {
|
|
|
14
14
|
this.#schema = schema
|
|
15
15
|
|
|
16
16
|
if (typeof argument === 'object') {
|
|
17
|
-
|
|
17
|
+
const object = clone(argument)
|
|
18
|
+
this.set(object)
|
|
18
19
|
this.#origin = argument
|
|
19
20
|
} else {
|
|
20
21
|
const id = typeof argument === 'string' ? argument : newid()
|
|
21
|
-
this.#
|
|
22
|
+
this.#init(id)
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -29,9 +30,9 @@ class Entity {
|
|
|
29
30
|
set (value) {
|
|
30
31
|
const error = this.#schema.fit(value)
|
|
31
32
|
|
|
32
|
-
if (error) throw new EntityContractException(error)
|
|
33
|
+
if (error !== null) throw new EntityContractException(error)
|
|
33
34
|
|
|
34
|
-
this.#
|
|
35
|
+
this.#set(value)
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
event () {
|
|
@@ -42,7 +43,17 @@ class Entity {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
#
|
|
46
|
+
#init (id) {
|
|
47
|
+
const value = { ...this.#schema.defaults({ id }), _version: 0 }
|
|
48
|
+
|
|
49
|
+
this.#set(value)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#set (value) {
|
|
53
|
+
Object.defineProperty(value, 'id', { writable: false, configurable: false })
|
|
54
|
+
|
|
55
|
+
this.#state = value
|
|
56
|
+
}
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
exports.Entity = Entity
|
package/src/entities/factory.js
CHANGED
|
@@ -15,12 +15,12 @@ class Factory {
|
|
|
15
15
|
return new Entity(this.#schema, id)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
object (record) {
|
|
19
19
|
return new Entity(this.#schema, record)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
const set = recordset.map((record) => this.
|
|
22
|
+
objects (recordset) {
|
|
23
|
+
const set = recordset.map((record) => this.object(record))
|
|
24
24
|
|
|
25
25
|
return new EntitySet(set)
|
|
26
26
|
}
|
package/src/event.js
CHANGED
|
@@ -2,21 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
const { Connector } = require('./connector')
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @implements {toa.core.Event}
|
|
7
|
+
*/
|
|
5
8
|
class Event extends Connector {
|
|
6
|
-
|
|
9
|
+
/** @type {toa.core.bindings.Emitter} */
|
|
10
|
+
#emitter
|
|
7
11
|
#bridge
|
|
8
12
|
#conditioned
|
|
9
13
|
#subjective
|
|
10
14
|
|
|
11
|
-
constructor (definition,
|
|
15
|
+
constructor (definition, emitter, bridge = undefined) {
|
|
12
16
|
super()
|
|
13
17
|
|
|
14
18
|
this.#conditioned = definition.conditioned
|
|
15
19
|
this.#subjective = definition.subjective
|
|
16
|
-
this.#
|
|
20
|
+
this.#emitter = emitter
|
|
17
21
|
this.#bridge = bridge
|
|
18
22
|
|
|
19
|
-
this.depends(
|
|
23
|
+
this.depends(emitter)
|
|
20
24
|
|
|
21
25
|
if (bridge !== undefined) this.depends(bridge)
|
|
22
26
|
}
|
|
@@ -25,7 +29,10 @@ class Event extends Connector {
|
|
|
25
29
|
if (this.#conditioned === false || await this.#bridge.condition(event) === true) {
|
|
26
30
|
const payload = this.#subjective ? await this.#bridge.payload(event) : event.state
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
/** @type {toa.core.Message} */
|
|
33
|
+
const message = { payload }
|
|
34
|
+
|
|
35
|
+
await this.#emitter.emit(message)
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
}
|
package/src/exceptions.js
CHANGED
|
@@ -22,6 +22,9 @@ const codes = {
|
|
|
22
22
|
Transmission: 401
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* @implements {toa.core.Exception}
|
|
27
|
+
*/
|
|
25
28
|
class Exception {
|
|
26
29
|
code
|
|
27
30
|
message
|
|
@@ -71,6 +74,7 @@ class EntityContractException extends ContractException {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
// #region exports
|
|
77
|
+
exports.Exception = Exception
|
|
74
78
|
exports.SystemException = SystemException
|
|
75
79
|
exports.RequestContractException = RequestContractException
|
|
76
80
|
exports.ResponseContractException = ResponseContractException
|
|
@@ -80,7 +84,11 @@ for (const [name, code] of Object.entries(codes)) {
|
|
|
80
84
|
const classname = name + 'Exception'
|
|
81
85
|
|
|
82
86
|
if (exports[classname] === undefined) {
|
|
83
|
-
exports[classname] = class extends Exception {
|
|
87
|
+
exports[classname] = class extends Exception {
|
|
88
|
+
constructor (message) {
|
|
89
|
+
super(code, message || classname)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
94
|
|