@toa.io/core 0.24.0-alpha.2 → 0.24.0-alpha.20
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 +8 -6
- package/src/contract/request.js +13 -5
- package/src/contract/schemas/index.js +2 -3
- package/src/contract/schemas/query.yaml +1 -2
- package/src/entities/entity.js +2 -3
- package/src/exposition.js +2 -2
- package/src/observation.js +0 -4
- package/src/query/options.js +3 -0
- package/src/state.js +5 -9
- package/test/contract/request.test.js +23 -20
- package/test/entities/entity.test.js +2 -2
- package/types/bindings.d.ts +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/core",
|
|
3
|
-
"version": "0.24.0-alpha.
|
|
3
|
+
"version": "0.24.0-alpha.20",
|
|
4
4
|
"description": "Toa Core",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -21,11 +21,13 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@rsql/parser": "1.2.4",
|
|
24
|
-
"@toa.io/console": "0.24.0-alpha.
|
|
25
|
-
"@toa.io/generic": "0.24.0-alpha.
|
|
26
|
-
"@toa.io/yaml": "0.24.0-alpha.
|
|
27
|
-
"clone-deep": "4.0.1",
|
|
24
|
+
"@toa.io/console": "0.24.0-alpha.20",
|
|
25
|
+
"@toa.io/generic": "0.24.0-alpha.20",
|
|
26
|
+
"@toa.io/yaml": "0.24.0-alpha.20",
|
|
28
27
|
"error-value": "0.3.0"
|
|
29
28
|
},
|
|
30
|
-
"
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"clone-deep": "4.0.1"
|
|
31
|
+
},
|
|
32
|
+
"gitHead": "53b95a1f5a29ca53c929e12023753853425350a1"
|
|
31
33
|
}
|
package/src/contract/request.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const clone = require('clone-deep')
|
|
4
|
-
|
|
5
3
|
const schemas = require('./schemas')
|
|
6
4
|
const { RequestContractException } = require('../exceptions')
|
|
7
5
|
const { Conditions } = require('./conditions')
|
|
@@ -12,8 +10,13 @@ class Request extends Conditions {
|
|
|
12
10
|
/**
|
|
13
11
|
* @returns {toa.schema.JSON}
|
|
14
12
|
*/
|
|
15
|
-
static schema (definition) {
|
|
16
|
-
const schema = {
|
|
13
|
+
static schema (definition, entity) {
|
|
14
|
+
const schema = {
|
|
15
|
+
type: 'object',
|
|
16
|
+
properties: { authentic: { type: 'boolean' } },
|
|
17
|
+
additionalProperties: true
|
|
18
|
+
}
|
|
19
|
+
|
|
17
20
|
const required = []
|
|
18
21
|
|
|
19
22
|
if (definition.input !== undefined) {
|
|
@@ -23,6 +26,9 @@ class Request extends Conditions {
|
|
|
23
26
|
schema.properties.input = { type: 'null' }
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
if (entity === undefined)
|
|
30
|
+
definition.query = false
|
|
31
|
+
|
|
26
32
|
if (definition.query === true) required.push('query')
|
|
27
33
|
|
|
28
34
|
if (definition.query === false) {
|
|
@@ -30,7 +36,9 @@ class Request extends Conditions {
|
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
if (definition.query !== false) {
|
|
33
|
-
const query =
|
|
39
|
+
const query = structuredClone(schemas.query)
|
|
40
|
+
|
|
41
|
+
query.properties.id = entity.schema.properties.id
|
|
34
42
|
|
|
35
43
|
if (definition.type === 'observation') {
|
|
36
44
|
delete query.properties.version
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const { resolve } = require('path')
|
|
4
4
|
const { load } = require('@toa.io/yaml')
|
|
5
|
-
const { freeze } = require('@toa.io/generic')
|
|
6
5
|
|
|
7
|
-
exports.query =
|
|
8
|
-
exports.error =
|
|
6
|
+
exports.query = load.sync(resolve(__dirname, './query.yaml'))
|
|
7
|
+
exports.error = load.sync(resolve(__dirname, './error.yaml'))
|
package/src/entities/entity.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const clone = require('clone-deep')
|
|
4
3
|
const { difference, newid } = require('@toa.io/generic')
|
|
5
4
|
|
|
6
5
|
const { EntityContractException } = require('../exceptions')
|
|
@@ -14,11 +13,11 @@ class Entity {
|
|
|
14
13
|
this.#schema = schema
|
|
15
14
|
|
|
16
15
|
if (typeof argument === 'object') {
|
|
17
|
-
const object =
|
|
16
|
+
const object = structuredClone(argument)
|
|
18
17
|
this.set(object)
|
|
19
18
|
this.#origin = argument
|
|
20
19
|
} else {
|
|
21
|
-
const id =
|
|
20
|
+
const id = argument === undefined ? newid() : argument
|
|
22
21
|
this.#init(id)
|
|
23
22
|
}
|
|
24
23
|
}
|
package/src/exposition.js
CHANGED
|
@@ -20,8 +20,8 @@ class Exposition extends Connector {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const expose = (manifest) => {
|
|
23
|
-
const { namespace, name, operations, events } = manifest
|
|
24
|
-
return { namespace, name, operations, events }
|
|
23
|
+
const { namespace, name, operations, events, entity } = manifest
|
|
24
|
+
return { namespace, name, operations, events, entity }
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
exports.Exposition = Exposition
|
package/src/observation.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { freeze } = require('@toa.io/generic')
|
|
4
|
-
|
|
5
3
|
const { Operation } = require('./operation')
|
|
6
4
|
|
|
7
5
|
class Observation extends Operation {
|
|
@@ -9,8 +7,6 @@ class Observation extends Operation {
|
|
|
9
7
|
const scope = await this.query(store.request.query)
|
|
10
8
|
const state = scope === null ? null : scope.get()
|
|
11
9
|
|
|
12
|
-
freeze(state)
|
|
13
|
-
|
|
14
10
|
store.scope = scope
|
|
15
11
|
store.state = state
|
|
16
12
|
}
|
package/src/query/options.js
CHANGED
|
@@ -32,6 +32,9 @@ const projection = (projection, properties) => {
|
|
|
32
32
|
throw new QuerySyntaxException(`Projection property '${property}' is not defined`)
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
|
|
36
|
+
if (projection.includes('_version') === false)
|
|
37
|
+
projection.push('_version')
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
exports.options = options
|
package/src/state.js
CHANGED
|
@@ -18,20 +18,16 @@ class State {
|
|
|
18
18
|
/** @type {toa.core.entity.Factory} */
|
|
19
19
|
#entity
|
|
20
20
|
#emission
|
|
21
|
-
#
|
|
21
|
+
#dependent
|
|
22
22
|
|
|
23
|
-
constructor (storage, entity, emission,
|
|
23
|
+
constructor (storage, entity, emission, dependent) {
|
|
24
24
|
this.#storage = storage
|
|
25
25
|
this.#entity = entity
|
|
26
26
|
this.#emission = emission
|
|
27
|
-
this.#
|
|
27
|
+
this.#dependent = dependent === true
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
init (id) {
|
|
31
|
-
// if (this.#initialized === true && id === undefined) {
|
|
32
|
-
// throw new StateInitializationException('Cannot initialize entity which is initialized. Use request.query.id to access.')
|
|
33
|
-
// }
|
|
34
|
-
|
|
35
31
|
return this.#entity.init(id)
|
|
36
32
|
}
|
|
37
33
|
|
|
@@ -39,7 +35,7 @@ class State {
|
|
|
39
35
|
const record = await this.#storage.get(query)
|
|
40
36
|
|
|
41
37
|
if (record === null) {
|
|
42
|
-
if (this.#
|
|
38
|
+
if (this.#dependent && query.id !== undefined && query.version === undefined) return this.init(query.id)
|
|
43
39
|
else if (query.version !== undefined) throw new StatePreconditionException()
|
|
44
40
|
}
|
|
45
41
|
|
|
@@ -83,7 +79,7 @@ class State {
|
|
|
83
79
|
|
|
84
80
|
let upsert
|
|
85
81
|
|
|
86
|
-
if (this.#
|
|
82
|
+
if (this.#dependent && state.query.id !== undefined && state.query.version === undefined) {
|
|
87
83
|
upsert = insert
|
|
88
84
|
}
|
|
89
85
|
|
|
@@ -17,6 +17,8 @@ beforeEach(() => {
|
|
|
17
17
|
contract = new Request(fixtures.schema)
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
+
const dummy = { schema: { properties: {} } }
|
|
21
|
+
|
|
20
22
|
it('should extend Conditions', () => {
|
|
21
23
|
expect(contract).toBeInstanceOf(Conditions)
|
|
22
24
|
expect(Conditions).toHaveBeenCalledWith(fixtures.schema)
|
|
@@ -38,73 +40,74 @@ describe('schema', () => {
|
|
|
38
40
|
})
|
|
39
41
|
|
|
40
42
|
it('should provide schema', () => {
|
|
41
|
-
expect(Request.schema({})).toBeDefined()
|
|
43
|
+
expect(Request.schema({}, dummy)).toBeDefined()
|
|
42
44
|
})
|
|
43
45
|
|
|
44
46
|
it('should add required input if defined', () => {
|
|
45
47
|
const input = { type: 'number' }
|
|
46
48
|
|
|
47
|
-
expect(Request.schema({ input }).properties.input).toStrictEqual(input)
|
|
49
|
+
expect(Request.schema({ input }, dummy).properties.input).toStrictEqual(input)
|
|
48
50
|
})
|
|
49
51
|
|
|
50
52
|
it('should set input as null if undefined', async () => {
|
|
51
|
-
expect(Request.schema({}).properties.input).toStrictEqual({ type: 'null' })
|
|
53
|
+
expect(Request.schema({}, dummy).properties.input).toStrictEqual({ type: 'null' })
|
|
52
54
|
})
|
|
53
55
|
|
|
54
56
|
it('should contain query if declaration.query is not defined', () => {
|
|
55
|
-
expect(Request.schema({}).properties.query).toBeDefined()
|
|
57
|
+
expect(Request.schema({}, dummy).properties.query).toBeDefined()
|
|
56
58
|
})
|
|
57
59
|
|
|
58
60
|
it('should not contain query if declaration.query is false', () => {
|
|
59
61
|
delete schema.properties.query
|
|
60
62
|
schema.not = { required: ['query'] }
|
|
61
|
-
expect(Request.schema({ query: false })).toStrictEqual(schema)
|
|
63
|
+
expect(Request.schema({ query: false }, dummy)).toStrictEqual(schema)
|
|
62
64
|
})
|
|
63
65
|
|
|
64
66
|
it('should require query if declaration.query is true', () => {
|
|
65
67
|
schema.required = ['query']
|
|
66
|
-
expect(Request.schema({ query: true }).required).toStrictEqual(expect.arrayContaining(['query']))
|
|
68
|
+
expect(Request.schema({ query: true }, dummy).required).toStrictEqual(expect.arrayContaining(['query']))
|
|
67
69
|
})
|
|
68
70
|
|
|
69
71
|
it('should forbid projection for non observations', () => {
|
|
70
|
-
expect(Request.schema({ type: 'transition' }).properties.query.properties.projection)
|
|
72
|
+
expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.projection)
|
|
71
73
|
.toBe(undefined)
|
|
72
74
|
|
|
73
|
-
expect(Request.schema({ type: 'assignment' }).properties.query.properties.projection)
|
|
75
|
+
expect(Request.schema({ type: 'assignment' }, dummy).properties.query.properties.projection)
|
|
74
76
|
.toBe(undefined)
|
|
75
77
|
|
|
76
|
-
expect(Request.schema({ type: 'observation' }).properties.query.properties.projection)
|
|
78
|
+
expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.projection)
|
|
77
79
|
.toBeDefined()
|
|
78
80
|
})
|
|
79
81
|
|
|
80
82
|
it('should forbid version for observations', () => {
|
|
81
|
-
expect(Request.schema({ type: 'transition' }).properties.query.properties.version)
|
|
83
|
+
expect(Request.schema({ type: 'transition' }, dummy).properties.query.properties.version)
|
|
82
84
|
.toBeDefined()
|
|
83
85
|
|
|
84
|
-
expect(Request.schema({ type: 'observation' }).properties.query.properties.version)
|
|
86
|
+
expect(Request.schema({ type: 'observation' }, dummy).properties.query.properties.version)
|
|
85
87
|
.toBe(undefined)
|
|
86
88
|
})
|
|
87
89
|
|
|
88
90
|
it('should allow omit, limit only for set observations', () => {
|
|
89
|
-
const
|
|
91
|
+
const schema = Request.schema({ type: 'transition' }, dummy)
|
|
92
|
+
const transition = schema.properties.query.properties
|
|
90
93
|
|
|
91
94
|
expect(transition.omit).toBeUndefined()
|
|
92
95
|
expect(transition.limit).toBeUndefined()
|
|
93
96
|
|
|
94
|
-
const
|
|
97
|
+
const object = Request.schema({
|
|
95
98
|
type: 'observation',
|
|
96
99
|
scope: 'object'
|
|
97
|
-
}).properties.query.properties
|
|
100
|
+
}, dummy).properties.query.properties
|
|
98
101
|
|
|
99
|
-
expect(
|
|
100
|
-
expect(
|
|
102
|
+
expect(object.omit).toBeUndefined()
|
|
103
|
+
expect(object.limit).toBeUndefined()
|
|
101
104
|
|
|
102
|
-
const
|
|
105
|
+
const objects = Request.schema({
|
|
103
106
|
type: 'observation',
|
|
104
107
|
scope: 'objects'
|
|
105
|
-
}).properties.query.properties
|
|
108
|
+
}, dummy).properties.query.properties
|
|
106
109
|
|
|
107
|
-
expect(
|
|
108
|
-
expect(
|
|
110
|
+
expect(objects.omit).toBeDefined()
|
|
111
|
+
expect(objects.limit).toBeDefined()
|
|
109
112
|
})
|
|
110
113
|
})
|
|
@@ -37,7 +37,7 @@ describe('argument', () => {
|
|
|
37
37
|
const state = fixtures.state()
|
|
38
38
|
const entity = new Entity(fixtures.schema, state)
|
|
39
39
|
|
|
40
|
-
expect(entity.get()).
|
|
40
|
+
expect(entity.get()).toEqual(state)
|
|
41
41
|
})
|
|
42
42
|
})
|
|
43
43
|
|
|
@@ -51,7 +51,7 @@ it('should provide event', () => {
|
|
|
51
51
|
|
|
52
52
|
const event = entity.event()
|
|
53
53
|
|
|
54
|
-
expect(event).
|
|
54
|
+
expect(event).toEqual({
|
|
55
55
|
state,
|
|
56
56
|
origin,
|
|
57
57
|
changeset: { foo: 'new value' }
|
package/types/bindings.d.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import * as _core from './index'
|
|
2
2
|
|
|
3
|
-
declare namespace toa.core.bindings
|
|
3
|
+
declare namespace toa.core.bindings{
|
|
4
4
|
|
|
5
5
|
type Properties = {
|
|
6
6
|
async?: boolean
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
interface Consumer extends _core.Connector
|
|
9
|
+
interface Consumer extends _core.Connector{
|
|
10
10
|
request (request: Request): Promise<_core.Reply>
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
interface Emitter extends _core.Connector
|
|
13
|
+
interface Emitter extends _core.Connector{
|
|
14
14
|
emit (message: _core.Message): Promise<void>
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
interface Broadcast<L> extends _core.Connector
|
|
17
|
+
interface Broadcast<L> extends _core.Connector{
|
|
18
18
|
transmit<T> (label: L, payload: T): Promise<void>
|
|
19
19
|
|
|
20
20
|
receive<T> (label: L, callback: (payload: T) => void | Promise<void>): Promise<void>
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
interface Factory
|
|
23
|
+
interface Factory{
|
|
24
24
|
producer? (locator: _core.Locator, endpoints: Array<string>, producer: _core.Component): _core.Connector
|
|
25
25
|
|
|
26
26
|
consumer? (locator: _core.Locator, endpoint: string): Consumer
|
|
@@ -37,4 +37,4 @@ declare namespace toa.core.bindings {
|
|
|
37
37
|
export type Emitter = toa.core.bindings.Emitter
|
|
38
38
|
export type Factory = toa.core.bindings.Factory
|
|
39
39
|
export type Properties = toa.core.bindings.Properties
|
|
40
|
-
export type Broadcast<L> = toa.core.bindings.Broadcast<L>
|
|
40
|
+
export type Broadcast<L = any> = toa.core.bindings.Broadcast<L>
|