@toa.io/norm 1.0.0-alpha.19 → 1.0.0-alpha.192
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 +6 -7
- package/src/.component/.expand/extensions.js +2 -1
- package/src/.component/.normalize/operations.js +1 -1
- package/src/.component/collapse.js +5 -0
- package/src/.component/defaults.js +14 -3
- package/src/.component/dereference.js +6 -1
- package/src/.component/extensions.js +12 -2
- package/src/.component/merge.js +19 -5
- package/src/.component/schema.yaml +68 -39
- package/src/.component/validate.js +5 -5
- package/src/.context/.dependencies/resolve.js +9 -0
- package/src/.context/schema.yaml +7 -4
- package/src/.context/validate.js +2 -5
- package/src/component.js +5 -5
- package/src/shortcuts.js +3 -1
- package/test/component/validate.test.js +8 -11
- package/test/context/validate.test.js +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/norm",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.192",
|
|
4
4
|
"description": "Toa declarations normalization and validation",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -20,11 +20,10 @@
|
|
|
20
20
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
24
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
25
|
-
"@toa.io/
|
|
26
|
-
"@toa.io/
|
|
27
|
-
"@toa.io/yaml": "1.0.0-alpha.19"
|
|
23
|
+
"@toa.io/core": "1.0.0-alpha.190",
|
|
24
|
+
"@toa.io/generic": "1.0.0-alpha.173",
|
|
25
|
+
"@toa.io/schemas": "1.0.0-alpha.182",
|
|
26
|
+
"@toa.io/yaml": "1.0.0-alpha.182"
|
|
28
27
|
},
|
|
29
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "21f5b09a8c401620a4cca4f1e8f9c1b31b7fb918"
|
|
30
29
|
}
|
|
@@ -14,7 +14,8 @@ const SHORTCUTS = {
|
|
|
14
14
|
configuration: '@toa.io/extensions.configuration',
|
|
15
15
|
state: '@toa.io/extensions.state',
|
|
16
16
|
stash: '@toa.io/extensions.stash',
|
|
17
|
-
storages: '@toa.io/extensions.storages'
|
|
17
|
+
storages: '@toa.io/extensions.storages',
|
|
18
|
+
mail: '@toa.io/extensions.mail'
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
exports.extensions = extensions
|
|
@@ -4,7 +4,7 @@ const operations = (component) => {
|
|
|
4
4
|
if (component.operations === undefined) return
|
|
5
5
|
|
|
6
6
|
for (const [endpoint, operation] of Object.entries(component.operations)) {
|
|
7
|
-
if (operation.
|
|
7
|
+
if (operation.scope === 'none')
|
|
8
8
|
operation.query = false
|
|
9
9
|
|
|
10
10
|
if (operation.bindings === undefined) operation.bindings = component.bindings
|
|
@@ -42,6 +42,11 @@ const collapse = (manifest, prototype) => {
|
|
|
42
42
|
delete prototype.entity.schema.properties.id
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
if (prototype.events !== undefined && manifest.events !== undefined)
|
|
46
|
+
for (const event of Object.keys(prototype.events))
|
|
47
|
+
if (event in manifest.events)
|
|
48
|
+
delete prototype.events[event]
|
|
49
|
+
|
|
45
50
|
merge(manifest, { entity, events, extensions })
|
|
46
51
|
}
|
|
47
52
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { hash } = require('@toa.io/generic')
|
|
4
|
-
const assert = require('node:assert')
|
|
5
4
|
|
|
6
5
|
// these defaults are required before validation
|
|
7
|
-
const defaults = (manifest) => {
|
|
8
|
-
if (manifest.name === undefined)
|
|
6
|
+
const defaults = (manifest, proto) => {
|
|
7
|
+
if (manifest.name === undefined)
|
|
8
|
+
if (proto) manifest.name = protoName(manifest)
|
|
9
|
+
else nameAfterDir(manifest)
|
|
10
|
+
|
|
9
11
|
if (manifest.bindings === undefined) manifest.bindings = ['@toa.io/bindings.amqp']
|
|
10
12
|
if (manifest.bridge === undefined) manifest.bridge = '@toa.io/bridges.node'
|
|
11
13
|
|
|
@@ -24,4 +26,13 @@ function protoName (manifest) {
|
|
|
24
26
|
return 'proto' + hash(manifest.path)
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
function nameAfterDir (manifest) {
|
|
30
|
+
const parts = manifest.path.split('/')
|
|
31
|
+
const dirname = parts[parts.length - 1]
|
|
32
|
+
const [name, namespace] = dirname.split('.').reverse()
|
|
33
|
+
|
|
34
|
+
manifest.name = name
|
|
35
|
+
manifest.namespace = namespace
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
exports.defaults = defaults
|
|
@@ -25,7 +25,12 @@ const createResolver = (properties) => (property) => {
|
|
|
25
25
|
function operations (manifest, resolver) {
|
|
26
26
|
for (const operation of Object.values(manifest.operations)) {
|
|
27
27
|
if (operation.input !== undefined) operation.input = schema(operation.input, resolver)
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
if (operation.output !== undefined)
|
|
30
|
+
if (Array.isArray(operation.output) && operation.output.length === 1)
|
|
31
|
+
operation.output = [schema(operation.output[0], resolver)]
|
|
32
|
+
else
|
|
33
|
+
operation.output = schema(operation.output, resolver)
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
// forwarding
|
|
@@ -3,8 +3,13 @@
|
|
|
3
3
|
const { directory: { find } } = require('@toa.io/filesystem')
|
|
4
4
|
const { resolve } = require('../shortcuts')
|
|
5
5
|
|
|
6
|
+
const cache = {}
|
|
7
|
+
|
|
6
8
|
const extensions = (manifest) => {
|
|
7
|
-
if (manifest.extensions === undefined)
|
|
9
|
+
if (manifest.extensions === undefined)
|
|
10
|
+
manifest.extensions = PREDEFINED
|
|
11
|
+
else
|
|
12
|
+
manifest.extensions = Object.assign({}, PREDEFINED, manifest.extensions)
|
|
8
13
|
|
|
9
14
|
const extensions = manifest.extensions
|
|
10
15
|
|
|
@@ -14,7 +19,8 @@ const extensions = (manifest) => {
|
|
|
14
19
|
// relative path
|
|
15
20
|
if (key[0] === '.') key = find(key, manifest.path)
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
cache[key] ??= require(key)
|
|
23
|
+
const extension = cache[key]
|
|
18
24
|
|
|
19
25
|
if (extension.manifest !== undefined) {
|
|
20
26
|
declaration = extension.manifest(declaration, manifest)
|
|
@@ -29,4 +35,8 @@ const extensions = (manifest) => {
|
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
const PREDEFINED = {
|
|
39
|
+
'@toa.io/extensions.telemetry': null
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
exports.extensions = extensions
|
package/src/.component/merge.js
CHANGED
|
@@ -6,7 +6,8 @@ const bridge = async (root, manifest) => {
|
|
|
6
6
|
await Promise.all([
|
|
7
7
|
define(root, manifest, 'operations'),
|
|
8
8
|
define(root, manifest, 'events'),
|
|
9
|
-
define(root, manifest, 'receivers')
|
|
9
|
+
define(root, manifest, 'receivers'),
|
|
10
|
+
define(root, manifest, 'guards')
|
|
10
11
|
])
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -19,7 +20,7 @@ const define = async (root, manifest, property) => {
|
|
|
19
20
|
if (item.bridge === undefined || item.bridge === manifest.bridge) continue // default bridge later
|
|
20
21
|
|
|
21
22
|
const bridge = item.bridge || manifest.bridge
|
|
22
|
-
const
|
|
23
|
+
const define = req(bridge).define
|
|
23
24
|
const definition = await define[singular](root, endpoint)
|
|
24
25
|
|
|
25
26
|
merge(item, definition)
|
|
@@ -44,14 +45,27 @@ const define = async (root, manifest, property) => {
|
|
|
44
45
|
|
|
45
46
|
const declared = manifest[property][endpoint]
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
try {
|
|
49
|
+
if (declared === undefined) manifest[property][endpoint] = item
|
|
50
|
+
else merge(declared, item)
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(`Error merging ${singular} '${endpoint}' in ${root}`)
|
|
53
|
+
throw error
|
|
54
|
+
}
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
|
|
59
|
+
const cache = {}
|
|
60
|
+
|
|
61
|
+
function req(mod) {
|
|
62
|
+
cache[mod] ??= require(mod)
|
|
63
|
+
|
|
64
|
+
return cache[mod]
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
const scan = async (bridge, root, property) => {
|
|
54
|
-
const
|
|
68
|
+
const define = req(bridge).define
|
|
55
69
|
|
|
56
70
|
if (property in define)
|
|
57
71
|
return define[property](root)
|
|
@@ -8,7 +8,7 @@ definitions:
|
|
|
8
8
|
binding:
|
|
9
9
|
type: string
|
|
10
10
|
not:
|
|
11
|
-
const:
|
|
11
|
+
const: "@toa.io/bindings.loop" # loop is for system use only
|
|
12
12
|
|
|
13
13
|
type: object
|
|
14
14
|
properties:
|
|
@@ -17,19 +17,19 @@ properties:
|
|
|
17
17
|
nullable: true
|
|
18
18
|
properties:
|
|
19
19
|
prototype:
|
|
20
|
-
$ref:
|
|
20
|
+
$ref: "#/properties/prototype"
|
|
21
21
|
path:
|
|
22
22
|
type: string
|
|
23
23
|
operations:
|
|
24
24
|
type: object
|
|
25
25
|
propertyNames:
|
|
26
|
-
$ref:
|
|
26
|
+
$ref: "#/definitions/name"
|
|
27
27
|
patternProperties:
|
|
28
|
-
|
|
28
|
+
".*":
|
|
29
29
|
type: object
|
|
30
30
|
properties:
|
|
31
31
|
bridge:
|
|
32
|
-
$ref:
|
|
32
|
+
$ref: "#/properties/bridge"
|
|
33
33
|
|
|
34
34
|
path:
|
|
35
35
|
type: string
|
|
@@ -38,19 +38,23 @@ properties:
|
|
|
38
38
|
type: object
|
|
39
39
|
properties:
|
|
40
40
|
id:
|
|
41
|
-
|
|
41
|
+
type: string
|
|
42
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(\.([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))$
|
|
42
43
|
label:
|
|
43
|
-
|
|
44
|
+
type: string
|
|
45
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(-([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))*$
|
|
44
46
|
|
|
45
47
|
name:
|
|
46
|
-
|
|
48
|
+
type: string
|
|
49
|
+
pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
|
|
47
50
|
|
|
48
51
|
namespace:
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
type: string
|
|
53
|
+
pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
|
|
54
|
+
default: "default"
|
|
51
55
|
not:
|
|
52
56
|
oneOf:
|
|
53
|
-
- const:
|
|
57
|
+
- const: "system"
|
|
54
58
|
|
|
55
59
|
version:
|
|
56
60
|
type: string
|
|
@@ -60,15 +64,17 @@ properties:
|
|
|
60
64
|
properties:
|
|
61
65
|
image:
|
|
62
66
|
type: string
|
|
67
|
+
run:
|
|
68
|
+
type: string
|
|
63
69
|
|
|
64
70
|
entity:
|
|
65
71
|
type: object
|
|
66
72
|
properties:
|
|
67
73
|
storage:
|
|
68
74
|
type: string
|
|
69
|
-
default:
|
|
75
|
+
default: "@toa.io/storages.mongodb"
|
|
70
76
|
schema:
|
|
71
|
-
$ref:
|
|
77
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
72
78
|
type: object
|
|
73
79
|
properties:
|
|
74
80
|
type:
|
|
@@ -78,24 +84,24 @@ properties:
|
|
|
78
84
|
type: object
|
|
79
85
|
propertyNames:
|
|
80
86
|
oneOf:
|
|
81
|
-
- $ref:
|
|
87
|
+
- $ref: "#/definitions/name"
|
|
82
88
|
- enum: [_version, _created, _updated, _deleted]
|
|
83
89
|
unique:
|
|
84
90
|
type: object
|
|
85
91
|
patternProperties:
|
|
86
|
-
|
|
92
|
+
".*":
|
|
87
93
|
type: array
|
|
88
94
|
items:
|
|
89
95
|
type: string
|
|
90
96
|
index:
|
|
91
97
|
type: object
|
|
92
98
|
patternProperties:
|
|
93
|
-
|
|
99
|
+
".*":
|
|
94
100
|
type: object
|
|
95
101
|
patternProperties:
|
|
96
|
-
|
|
102
|
+
".*":
|
|
97
103
|
type: string
|
|
98
|
-
enum: [asc, desc, hash]
|
|
104
|
+
enum: [asc, desc, hash, text]
|
|
99
105
|
associated:
|
|
100
106
|
type: boolean
|
|
101
107
|
default: false
|
|
@@ -109,7 +115,7 @@ properties:
|
|
|
109
115
|
type: array
|
|
110
116
|
uniqueItems: true
|
|
111
117
|
items:
|
|
112
|
-
$ref:
|
|
118
|
+
$ref: "#/definitions/binding"
|
|
113
119
|
|
|
114
120
|
bridge:
|
|
115
121
|
type: string
|
|
@@ -117,27 +123,40 @@ properties:
|
|
|
117
123
|
operations:
|
|
118
124
|
type: object
|
|
119
125
|
propertyNames:
|
|
120
|
-
$ref:
|
|
126
|
+
$ref: "#/definitions/name"
|
|
121
127
|
patternProperties:
|
|
122
|
-
|
|
128
|
+
".*":
|
|
123
129
|
type: object
|
|
124
130
|
properties:
|
|
125
131
|
type:
|
|
126
|
-
enum:
|
|
132
|
+
enum:
|
|
133
|
+
[
|
|
134
|
+
transition,
|
|
135
|
+
observation,
|
|
136
|
+
assignment,
|
|
137
|
+
computation,
|
|
138
|
+
effect,
|
|
139
|
+
unmanaged,
|
|
140
|
+
]
|
|
127
141
|
scope:
|
|
128
|
-
enum: [object, objects, changeset, none]
|
|
142
|
+
enum: [object, objects, changeset, stream, none]
|
|
129
143
|
concurrency:
|
|
130
144
|
enum: [none, retry]
|
|
131
145
|
forward:
|
|
132
|
-
$ref:
|
|
146
|
+
$ref: "#/definitions/name"
|
|
133
147
|
bridge:
|
|
134
148
|
type: string
|
|
135
149
|
bindings:
|
|
136
|
-
$ref:
|
|
150
|
+
$ref: "#/properties/bindings"
|
|
137
151
|
input:
|
|
138
|
-
$ref:
|
|
152
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
139
153
|
output:
|
|
140
|
-
$ref:
|
|
154
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
155
|
+
default: {}
|
|
156
|
+
errors:
|
|
157
|
+
type: array
|
|
158
|
+
items:
|
|
159
|
+
type: string
|
|
141
160
|
query:
|
|
142
161
|
type: boolean
|
|
143
162
|
required: [type, scope, bindings]
|
|
@@ -174,7 +193,7 @@ properties:
|
|
|
174
193
|
then:
|
|
175
194
|
properties:
|
|
176
195
|
scope:
|
|
177
|
-
enum: [object, objects, none]
|
|
196
|
+
enum: [object, objects, stream, none]
|
|
178
197
|
query:
|
|
179
198
|
not:
|
|
180
199
|
const: false
|
|
@@ -189,7 +208,7 @@ properties:
|
|
|
189
208
|
- if: # computation
|
|
190
209
|
properties:
|
|
191
210
|
type:
|
|
192
|
-
|
|
211
|
+
enum: [computation, unmanaged]
|
|
193
212
|
then:
|
|
194
213
|
properties:
|
|
195
214
|
scope:
|
|
@@ -205,20 +224,17 @@ properties:
|
|
|
205
224
|
then:
|
|
206
225
|
properties:
|
|
207
226
|
scope:
|
|
208
|
-
const: none
|
|
209
227
|
default: none
|
|
210
|
-
|
|
211
|
-
const: false
|
|
212
|
-
default: false
|
|
228
|
+
enum: [object, objects, stream, none]
|
|
213
229
|
additionalProperties: false
|
|
214
230
|
additionalProperties: false
|
|
215
231
|
|
|
216
232
|
events:
|
|
217
233
|
type: object
|
|
218
234
|
propertyNames:
|
|
219
|
-
$ref:
|
|
235
|
+
$ref: "#/definitions/name"
|
|
220
236
|
patternProperties:
|
|
221
|
-
|
|
237
|
+
".*":
|
|
222
238
|
type: object
|
|
223
239
|
properties:
|
|
224
240
|
bridge:
|
|
@@ -226,7 +242,7 @@ properties:
|
|
|
226
242
|
path:
|
|
227
243
|
type: string
|
|
228
244
|
binding:
|
|
229
|
-
$ref:
|
|
245
|
+
$ref: "#/definitions/binding"
|
|
230
246
|
conditioned:
|
|
231
247
|
type: boolean
|
|
232
248
|
default: false
|
|
@@ -239,17 +255,17 @@ properties:
|
|
|
239
255
|
receivers:
|
|
240
256
|
type: object
|
|
241
257
|
patternProperties:
|
|
242
|
-
|
|
258
|
+
".*":
|
|
243
259
|
type: object
|
|
244
260
|
properties:
|
|
245
261
|
operation:
|
|
246
|
-
$ref:
|
|
262
|
+
$ref: "#/definitions/name"
|
|
247
263
|
bridge:
|
|
248
264
|
type: string
|
|
249
265
|
binding:
|
|
250
266
|
type: string
|
|
251
267
|
source:
|
|
252
|
-
$ref:
|
|
268
|
+
$ref: "#/definitions/name"
|
|
253
269
|
not:
|
|
254
270
|
const: context
|
|
255
271
|
path:
|
|
@@ -260,9 +276,22 @@ properties:
|
|
|
260
276
|
adaptive:
|
|
261
277
|
type: boolean
|
|
262
278
|
default: false
|
|
279
|
+
arguments:
|
|
280
|
+
type: array
|
|
263
281
|
required: [operation]
|
|
264
282
|
additionalProperties: false
|
|
265
283
|
|
|
284
|
+
guards:
|
|
285
|
+
type: object
|
|
286
|
+
patternProperties:
|
|
287
|
+
".*":
|
|
288
|
+
type: object
|
|
289
|
+
properties:
|
|
290
|
+
bridge: { type: string }
|
|
291
|
+
path: { type: string }
|
|
292
|
+
required: [bridge, path]
|
|
293
|
+
additionalProperties: false
|
|
294
|
+
|
|
266
295
|
extensions:
|
|
267
296
|
type: object
|
|
268
297
|
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
const path = require('node:path')
|
|
4
4
|
|
|
5
5
|
const { load } = require('@toa.io/yaml')
|
|
6
|
-
const
|
|
6
|
+
const schemas = require('@toa.io/schemas')
|
|
7
7
|
|
|
8
8
|
const object = load.sync(path.resolve(__dirname, 'schema.yaml'))
|
|
9
|
-
const schema =
|
|
9
|
+
const schema = schemas.schema(object)
|
|
10
10
|
|
|
11
11
|
const validate = (manifest) => {
|
|
12
12
|
const error = schema.fit(manifest)
|
|
13
13
|
|
|
14
|
-
if (error) throw
|
|
14
|
+
if (error) throw error
|
|
15
15
|
|
|
16
16
|
if (manifest.events !== undefined) events(manifest)
|
|
17
17
|
if (manifest.receivers !== undefined) receivers(manifest)
|
|
@@ -32,11 +32,11 @@ const receivers = (manifest) => {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
if (!TYPES.has(manifest.operations[receiver.operation].type)) {
|
|
35
|
-
throw new Error(`Receiver '${locator}' must refer to an operation of
|
|
35
|
+
throw new Error(`Receiver '${locator}' must refer to an operation of the allowed types: ${Array.from(TYPES).join(', ')}`)
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const TYPES = new Set(['transition', 'effect'])
|
|
40
|
+
const TYPES = new Set(['transition', 'assignment', 'effect', 'unmanaged'])
|
|
41
41
|
|
|
42
42
|
exports.validate = validate
|
|
@@ -24,6 +24,15 @@ const resolve = (references, annotations) => {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
for (const dependency of Object.keys(annotations)) {
|
|
28
|
+
const { module } = load(dependency)
|
|
29
|
+
|
|
30
|
+
if (!module.standalone || (dependency in dependencies))
|
|
31
|
+
continue
|
|
32
|
+
|
|
33
|
+
dependencies[dependency] = []
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
return dependencies
|
|
28
37
|
}
|
|
29
38
|
|
package/src/.context/schema.yaml
CHANGED
|
@@ -6,7 +6,8 @@ properties:
|
|
|
6
6
|
version:
|
|
7
7
|
type: string
|
|
8
8
|
name:
|
|
9
|
-
|
|
9
|
+
type: string
|
|
10
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(-([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))*$
|
|
10
11
|
description:
|
|
11
12
|
type: string
|
|
12
13
|
packages:
|
|
@@ -46,7 +47,7 @@ properties:
|
|
|
46
47
|
- linux/amd64
|
|
47
48
|
- linux/arm/v7
|
|
48
49
|
- linux/arm64
|
|
49
|
-
required: [base
|
|
50
|
+
# required: [base]
|
|
50
51
|
compositions:
|
|
51
52
|
type: array
|
|
52
53
|
minItems: 1
|
|
@@ -54,14 +55,16 @@ properties:
|
|
|
54
55
|
type: object
|
|
55
56
|
properties:
|
|
56
57
|
name:
|
|
57
|
-
|
|
58
|
+
type: string
|
|
59
|
+
pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
|
|
58
60
|
image:
|
|
59
61
|
type: string
|
|
60
62
|
components:
|
|
61
63
|
type: array
|
|
62
64
|
minItems: 1
|
|
63
65
|
items:
|
|
64
|
-
|
|
66
|
+
type: string
|
|
67
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(\.([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))$
|
|
65
68
|
required: [name, components]
|
|
66
69
|
annotations:
|
|
67
70
|
type: object
|
package/src/.context/validate.js
CHANGED
|
@@ -3,15 +3,12 @@
|
|
|
3
3
|
const { resolve } = require('node:path')
|
|
4
4
|
|
|
5
5
|
const { load } = require('@toa.io/yaml')
|
|
6
|
-
const
|
|
6
|
+
const schemas = require('@toa.io/schemas')
|
|
7
7
|
|
|
8
8
|
const path = resolve(__dirname, 'schema.yaml')
|
|
9
9
|
const object = load.sync(path)
|
|
10
|
-
const schema =
|
|
10
|
+
const schema = schemas.schema(object)
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* @param {toa.norm.context.Declaration} context
|
|
14
|
-
*/
|
|
15
12
|
const validate = (context) => {
|
|
16
13
|
schema.validate(context)
|
|
17
14
|
}
|
package/src/component.js
CHANGED
|
@@ -20,7 +20,7 @@ const {
|
|
|
20
20
|
const component = async (path) => {
|
|
21
21
|
const manifest = await load(path)
|
|
22
22
|
|
|
23
|
-
normalize(manifest)
|
|
23
|
+
normalize(manifest, path)
|
|
24
24
|
validate(manifest)
|
|
25
25
|
extensions(manifest)
|
|
26
26
|
|
|
@@ -29,21 +29,21 @@ const component = async (path) => {
|
|
|
29
29
|
return manifest
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const load = async (path, base) => {
|
|
32
|
+
const load = async (path, base, proto = false) => {
|
|
33
33
|
if (base !== undefined) path = find(path, base, MANIFEST)
|
|
34
34
|
|
|
35
35
|
const file = join(path, MANIFEST)
|
|
36
|
-
const manifest =
|
|
36
|
+
const manifest = await yaml(file) ?? {}
|
|
37
37
|
|
|
38
38
|
manifest.path = path
|
|
39
39
|
|
|
40
|
-
defaults(manifest)
|
|
40
|
+
defaults(manifest, proto)
|
|
41
41
|
await expand(manifest)
|
|
42
42
|
|
|
43
43
|
await merge(path, manifest)
|
|
44
44
|
|
|
45
45
|
if (manifest.prototype !== null) {
|
|
46
|
-
const prototype = await load(manifest.prototype, path)
|
|
46
|
+
const prototype = await load(manifest.prototype, path, true)
|
|
47
47
|
|
|
48
48
|
collapse(manifest, prototype)
|
|
49
49
|
}
|
package/src/shortcuts.js
CHANGED
|
@@ -50,7 +50,9 @@ const SHORTCUTS = {
|
|
|
50
50
|
configuration: '@toa.io/extensions.configuration',
|
|
51
51
|
origins: '@toa.io/extensions.origins',
|
|
52
52
|
stash: '@toa.io/extensions.stash',
|
|
53
|
-
storages: '@toa.io/extensions.storages'
|
|
53
|
+
storages: '@toa.io/extensions.storages',
|
|
54
|
+
telemetry: '@toa.io/extensions.telemetry',
|
|
55
|
+
mail: '@toa.io/extensions.mail'
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
exports.recognize = recognize
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// noinspection JSUnresolvedVariable
|
|
2
|
-
|
|
3
1
|
'use strict'
|
|
4
2
|
|
|
5
3
|
const clone = require('clone-deep')
|
|
@@ -20,13 +18,13 @@ it('should be ok', () => {
|
|
|
20
18
|
it('should provide error', () => {
|
|
21
19
|
manifest.foo = 'bar'
|
|
22
20
|
|
|
23
|
-
expect(() => validate(manifest)).toThrow(
|
|
21
|
+
expect(() => validate(manifest)).toThrow()
|
|
24
22
|
})
|
|
25
23
|
|
|
26
24
|
it('should not have additional properties', () => {
|
|
27
25
|
manifest.foo = 'bar'
|
|
28
26
|
|
|
29
|
-
expect(() => validate(manifest)).toThrow(
|
|
27
|
+
expect(() => validate(manifest)).toThrow()
|
|
30
28
|
})
|
|
31
29
|
|
|
32
30
|
describe('namespace', () => {
|
|
@@ -83,13 +81,13 @@ describe('entity', () => {
|
|
|
83
81
|
|
|
84
82
|
it('should not have additional properties', () => {
|
|
85
83
|
manifest.entity.foo = 'bar'
|
|
86
|
-
expect(() => validate(manifest)).toThrow(
|
|
84
|
+
expect(() => validate(manifest)).toThrow()
|
|
87
85
|
})
|
|
88
86
|
|
|
89
87
|
describe('schema', () => {
|
|
90
88
|
it('should be required', () => {
|
|
91
89
|
delete manifest.entity.schema
|
|
92
|
-
expect(() => validate(manifest)).toThrow(
|
|
90
|
+
expect(() => validate(manifest)).toThrow()
|
|
93
91
|
})
|
|
94
92
|
|
|
95
93
|
it('should be JSON schema object', () => {
|
|
@@ -99,7 +97,7 @@ describe('entity', () => {
|
|
|
99
97
|
|
|
100
98
|
it('should be JSON schema object of type object', () => {
|
|
101
99
|
manifest.entity.schema = { type: 'integer' }
|
|
102
|
-
expect(() => validate(manifest)).toThrow(/must be equal to constant
|
|
100
|
+
expect(() => validate(manifest)).toThrow(/must be equal to constant/)
|
|
103
101
|
|
|
104
102
|
manifest.entity.schema = {}
|
|
105
103
|
validate(manifest)
|
|
@@ -154,7 +152,7 @@ describe('operations', () => {
|
|
|
154
152
|
|
|
155
153
|
it('should not have additional properties', () => {
|
|
156
154
|
manifest.operations.get.foo = 'bar'
|
|
157
|
-
expect(() => validate(manifest)).toThrow(
|
|
155
|
+
expect(() => validate(manifest)).toThrow()
|
|
158
156
|
})
|
|
159
157
|
|
|
160
158
|
it('should have type (transition or observation)', () => {
|
|
@@ -176,8 +174,7 @@ describe('operations', () => {
|
|
|
176
174
|
})
|
|
177
175
|
|
|
178
176
|
it.each([
|
|
179
|
-
['computation', 'compute']
|
|
180
|
-
['effect', 'affect']
|
|
177
|
+
['computation', 'compute']
|
|
181
178
|
])('should set query: false for %s', async (_, operation) => {
|
|
182
179
|
validate(manifest)
|
|
183
180
|
|
|
@@ -250,7 +247,7 @@ describe('receivers', () => {
|
|
|
250
247
|
it('should throw if transition points to observation', () => {
|
|
251
248
|
manifest.receivers['foo.bar.happened'].operation = 'get'
|
|
252
249
|
|
|
253
|
-
expect(() => validate(manifest)).toThrow(/
|
|
250
|
+
expect(() => validate(manifest)).toThrow(/of the allowed types/)
|
|
254
251
|
})
|
|
255
252
|
|
|
256
253
|
it('should throw if source has a name `context`', async () => {
|
|
@@ -45,12 +45,6 @@ describe('registry', () => {
|
|
|
45
45
|
expect(() => validate(context)).toThrow(/required property 'registry'/)
|
|
46
46
|
})
|
|
47
47
|
|
|
48
|
-
it('should require base', () => {
|
|
49
|
-
delete context.registry.base
|
|
50
|
-
|
|
51
|
-
expect(() => validate(context)).toThrow(/required property 'base'/)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
48
|
it('should set default platforms', () => {
|
|
55
49
|
delete context.registry.platforms
|
|
56
50
|
|