@toa.io/norm 1.0.0-alpha.32 → 1.0.0-alpha.321
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/CHANGELOG.md +305 -0
- package/package.json +9 -7
- package/src/.component/.expand/bridge.js +2 -6
- package/src/.component/.expand/entity.js +2 -9
- package/src/.component/.expand/events.js +2 -6
- package/src/.component/.expand/extensions.js +7 -9
- package/src/.component/.expand/index.js +7 -19
- package/src/.component/.expand/operations.js +2 -9
- package/src/.component/.expand/receivers.js +4 -7
- package/src/.component/.expand/version.js +69 -28
- package/src/.component/.normalize/entity.js +7 -0
- package/src/.component/.normalize/events.js +16 -4
- package/src/.component/.normalize/index.js +4 -9
- package/src/.component/.normalize/operations.js +13 -6
- package/src/.component/.normalize/receivers.js +4 -5
- package/src/.component/collapse.js +60 -9
- package/src/.component/defaults.js +5 -11
- package/src/.component/dependencies.js +14 -10
- package/src/.component/dereference.js +5 -49
- package/src/.component/expand.js +3 -9
- package/src/.component/extensions.js +9 -10
- package/src/.component/index.js +10 -21
- package/src/.component/merge.js +25 -15
- package/src/.component/migrations.js +57 -0
- package/src/.component/normalize.js +10 -6
- package/src/.component/schema.yaml +165 -73
- package/src/.component/validate.js +63 -17
- package/src/.context/.dependencies/connectors.js +5 -9
- package/src/.context/.dependencies/describe.js +4 -5
- package/src/.context/.dependencies/extensions.js +93 -20
- package/src/.context/.dependencies/index.js +3 -9
- package/src/.context/.dependencies/resolve.js +44 -7
- package/src/.context/complete.js +1 -5
- package/src/.context/converge.js +31 -0
- package/src/.context/dependencies.js +43 -6
- package/src/.context/dereference.js +11 -6
- package/src/.context/evict.js +38 -0
- package/src/.context/expand.js +11 -6
- package/src/.context/index.js +8 -15
- package/src/.context/normalize.js +9 -7
- package/src/.context/schema.yaml +183 -11
- package/src/.context/validate.js +11 -14
- package/src/component.js +33 -14
- package/src/context.js +44 -15
- package/src/definition.js +63 -0
- package/src/entity.js +15 -0
- package/src/index.js +7 -9
- package/src/manifest.js +154 -0
- package/src/map.js +24 -0
- package/src/shortcuts.js +11 -15
- package/test/component/collapse.fixtures.js +30 -39
- package/test/component/collapse.test.js +90 -10
- package/test/component/dependencies.test.js +16 -14
- package/test/component/dereference.fixtures.js +10 -98
- package/test/component/dereference.test.js +10 -14
- package/test/component/dummies/extension/index.js +1 -5
- package/test/component/dummies/migrations/conflicting/migrations/0001-one.yaml +2 -0
- package/test/component/dummies/migrations/conflicting/migrations/0001-one.yml +2 -0
- package/test/component/dummies/migrations/malformed/migrations/0001-one.yaml +1 -0
- package/test/component/dummies/migrations/ordered/migrations/0001-first.yml +4 -0
- package/test/component/dummies/migrations/ordered/migrations/0002-second.yaml +4 -0
- package/test/component/dummies/migrations/ordered/migrations/0010-third.json +1 -0
- package/test/component/dummies/migrations/stateless/migrations/0001-one.yaml +2 -0
- package/test/component/expand.fixtures.js +13 -13
- package/test/component/expand.test.js +17 -13
- package/test/component/migrations.test.js +62 -0
- package/test/component/normalize.fixtures.js +3 -7
- package/test/component/normalize.test.js +94 -28
- package/test/component/validate.fixtures.js +17 -15
- package/test/component/validate.test.js +289 -109
- package/test/context/complete.fixtures.js +2 -8
- package/test/context/complete.test.js +14 -8
- package/test/context/converge.test.js +57 -0
- package/test/context/dereference.fixtures.js +3 -9
- package/test/context/dereference.test.js +18 -7
- package/test/context/evict.fixtures.js +39 -0
- package/test/context/evict.test.js +73 -0
- package/test/context/expand.fixtures.js +1 -5
- package/test/context/expand.test.js +36 -8
- package/test/context/normalize.fixtures.js +2 -7
- package/test/context/normalize.test.js +33 -9
- package/test/context/validate.fixtures.js +1 -6
- package/test/context/validate.test.js +173 -35
- package/test/definition.test.js +35 -0
- package/test/dummies/bare/index.js +1 -0
- package/test/dummies/defined/definition.js +1 -0
- package/test/dummies/defined/index.js +1 -0
- package/test/dummies/defined/package.json +1 -0
- package/test/manifest.test.js +126 -0
- package/test/shortcuts.fixtures.js +4 -9
- package/test/shortcuts.test.js +17 -15
- package/test/system.test.js +31 -0
- package/types/component.d.ts +31 -4
- package/types/context/declaration.d.ts +34 -3
- package/types/context.d.ts +27 -13
- package/types/entity.d.ts +7 -0
- package/types/index.d.ts +18 -3
- package/src/.component/.expand/properties.js +0 -14
- package/src/.context/.dependencies/load.js +0 -36
- package/test/context/dependencies.load.test.js +0 -24
|
@@ -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,40 +17,55 @@ 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
|
|
36
36
|
|
|
37
|
+
files:
|
|
38
|
+
# what this component's version is made of, where a build of it copies only some of it
|
|
39
|
+
type: array
|
|
40
|
+
items:
|
|
41
|
+
type: string
|
|
42
|
+
|
|
43
|
+
ignore:
|
|
44
|
+
# what its version is not made of, added to what the bridge states; `!` puts one of those back
|
|
45
|
+
type: array
|
|
46
|
+
items:
|
|
47
|
+
type: string
|
|
48
|
+
|
|
37
49
|
locator:
|
|
38
50
|
type: object
|
|
39
51
|
properties:
|
|
40
52
|
id:
|
|
41
|
-
|
|
53
|
+
type: string
|
|
54
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(\.([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))$
|
|
42
55
|
label:
|
|
43
|
-
|
|
56
|
+
type: string
|
|
57
|
+
pattern: ^([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?)(-([a-zA-Z]+([_a-zA-Z0-9]*[a-zA-Z0-9]+)?))*$
|
|
44
58
|
|
|
45
59
|
name:
|
|
46
|
-
|
|
60
|
+
type: string
|
|
61
|
+
pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
|
|
47
62
|
|
|
48
63
|
namespace:
|
|
49
|
-
|
|
50
|
-
|
|
64
|
+
type: string
|
|
65
|
+
pattern: ^[a-zA-Z]([a-zA-Z0-9]{1,31})?$
|
|
51
66
|
not:
|
|
52
67
|
oneOf:
|
|
53
|
-
- const:
|
|
68
|
+
- const: "system"
|
|
54
69
|
|
|
55
70
|
version:
|
|
56
71
|
type: string
|
|
@@ -60,56 +75,60 @@ properties:
|
|
|
60
75
|
properties:
|
|
61
76
|
image:
|
|
62
77
|
type: string
|
|
78
|
+
run:
|
|
79
|
+
type: string
|
|
63
80
|
|
|
64
81
|
entity:
|
|
65
82
|
type: object
|
|
66
83
|
properties:
|
|
67
84
|
storage:
|
|
68
85
|
type: string
|
|
69
|
-
|
|
70
|
-
schema:
|
|
71
|
-
$ref: 'definitions#/definitions/schema'
|
|
86
|
+
properties:
|
|
72
87
|
type: object
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
# a system property is named like any other, so nothing is enumerated beside them
|
|
89
|
+
propertyNames:
|
|
90
|
+
$ref: "#/definitions/name"
|
|
91
|
+
additionalProperties:
|
|
92
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
93
|
+
required:
|
|
94
|
+
type: array
|
|
95
|
+
uniqueItems: true
|
|
96
|
+
items:
|
|
97
|
+
$ref: "#/definitions/name"
|
|
98
|
+
blank:
|
|
99
|
+
# what a record holds before anything is written to it; a system property is the
|
|
100
|
+
# runtime's to write, so none may be named here
|
|
84
101
|
type: object
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
propertyNames:
|
|
103
|
+
not:
|
|
104
|
+
enum: [id, VERSION, CREATED, UPDATED, DELETED, REGION, TRAILERS]
|
|
105
|
+
migrations:
|
|
106
|
+
type: array
|
|
107
|
+
items:
|
|
108
|
+
type: object
|
|
109
|
+
properties:
|
|
110
|
+
id:
|
|
89
111
|
type: string
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
enum: [asc, desc, hash]
|
|
112
|
+
# what a step means belongs to the storage, which is the only thing that reads it
|
|
113
|
+
steps:
|
|
114
|
+
type: array
|
|
115
|
+
# the prototype it is inherited from; absent on the component's own
|
|
116
|
+
prototype:
|
|
117
|
+
type: string
|
|
118
|
+
required: [id, steps]
|
|
119
|
+
additionalProperties: false
|
|
99
120
|
associated:
|
|
100
121
|
type: boolean
|
|
101
|
-
default: false
|
|
102
122
|
custom:
|
|
103
123
|
type: boolean
|
|
104
|
-
|
|
105
|
-
required: [schema]
|
|
124
|
+
required: [properties]
|
|
106
125
|
additionalProperties: false
|
|
107
126
|
|
|
108
127
|
bindings:
|
|
109
128
|
type: array
|
|
110
129
|
uniqueItems: true
|
|
111
130
|
items:
|
|
112
|
-
$ref:
|
|
131
|
+
$ref: "#/definitions/binding"
|
|
113
132
|
|
|
114
133
|
bridge:
|
|
115
134
|
type: string
|
|
@@ -117,27 +136,60 @@ properties:
|
|
|
117
136
|
operations:
|
|
118
137
|
type: object
|
|
119
138
|
propertyNames:
|
|
120
|
-
$ref:
|
|
139
|
+
$ref: "#/definitions/name"
|
|
121
140
|
patternProperties:
|
|
122
|
-
|
|
141
|
+
".*":
|
|
123
142
|
type: object
|
|
124
143
|
properties:
|
|
125
144
|
type:
|
|
126
|
-
enum:
|
|
145
|
+
enum:
|
|
146
|
+
[
|
|
147
|
+
transition,
|
|
148
|
+
observation,
|
|
149
|
+
assignment,
|
|
150
|
+
computation,
|
|
151
|
+
effect,
|
|
152
|
+
unmanaged,
|
|
153
|
+
]
|
|
127
154
|
scope:
|
|
128
|
-
enum: [
|
|
155
|
+
enum: [entry, entries, changeset, stream, none]
|
|
129
156
|
concurrency:
|
|
130
157
|
enum: [none, retry]
|
|
158
|
+
once:
|
|
159
|
+
# the same call arriving twice changes state once; see documentation/inbox.md
|
|
160
|
+
# a number is how many seconds a call is remembered, which a deployment's
|
|
161
|
+
# `inbox.retention` is the default for; ten minutes at least, because the broker
|
|
162
|
+
# alone repeats a call for about that long. One type list rather than `oneOf`: the
|
|
163
|
+
# manifest is validated with coercion, and a branch would coerce `true` into `1`
|
|
164
|
+
type: [boolean, integer]
|
|
165
|
+
minimum: 600
|
|
166
|
+
stateful:
|
|
167
|
+
# served by every process under an address of its own, which a call names; see documentation/stateful.md
|
|
168
|
+
type: boolean
|
|
169
|
+
unchained:
|
|
170
|
+
# every call begins a chain of its own, so a circle through it is refused by neither rule; see documentation/cycles.md
|
|
171
|
+
type: boolean
|
|
172
|
+
stream:
|
|
173
|
+
# the input property that carries a stream, read as its caller writes it; see documentation/streams.md
|
|
174
|
+
$ref: "#/definitions/name"
|
|
131
175
|
forward:
|
|
132
|
-
$ref:
|
|
176
|
+
$ref: "#/definitions/name"
|
|
133
177
|
bridge:
|
|
134
178
|
type: string
|
|
135
179
|
bindings:
|
|
136
|
-
$ref:
|
|
180
|
+
$ref: "#/properties/bindings"
|
|
181
|
+
description:
|
|
182
|
+
# what the operation is, for whoever reads it: a generated type, an OPTIONS, a model
|
|
183
|
+
type: string
|
|
137
184
|
input:
|
|
138
|
-
$ref:
|
|
185
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
139
186
|
output:
|
|
140
|
-
$ref:
|
|
187
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
188
|
+
errors:
|
|
189
|
+
# what a reply may carry as a code: the error schema allows either
|
|
190
|
+
type: array
|
|
191
|
+
items:
|
|
192
|
+
type: [string, integer]
|
|
141
193
|
query:
|
|
142
194
|
type: boolean
|
|
143
195
|
required: [type, scope, bindings]
|
|
@@ -149,8 +201,8 @@ properties:
|
|
|
149
201
|
then:
|
|
150
202
|
properties:
|
|
151
203
|
scope:
|
|
152
|
-
enum: [
|
|
153
|
-
if: #
|
|
204
|
+
enum: [entry, entries]
|
|
205
|
+
if: # not query: false
|
|
154
206
|
not:
|
|
155
207
|
properties:
|
|
156
208
|
query:
|
|
@@ -158,6 +210,17 @@ properties:
|
|
|
158
210
|
required: [query]
|
|
159
211
|
then:
|
|
160
212
|
required: [concurrency]
|
|
213
|
+
- if: # transition and scope=entries
|
|
214
|
+
properties:
|
|
215
|
+
type:
|
|
216
|
+
const: transition
|
|
217
|
+
scope:
|
|
218
|
+
const: entries
|
|
219
|
+
then:
|
|
220
|
+
properties:
|
|
221
|
+
query:
|
|
222
|
+
not:
|
|
223
|
+
const: false
|
|
161
224
|
- if: # not transition
|
|
162
225
|
not:
|
|
163
226
|
properties:
|
|
@@ -167,6 +230,30 @@ properties:
|
|
|
167
230
|
properties:
|
|
168
231
|
concurrency:
|
|
169
232
|
const: ~ # never pass
|
|
233
|
+
- if: # neither a transition nor an assignment
|
|
234
|
+
not:
|
|
235
|
+
properties:
|
|
236
|
+
type:
|
|
237
|
+
enum: [transition, assignment]
|
|
238
|
+
then:
|
|
239
|
+
properties:
|
|
240
|
+
# An operation that writes nothing has nothing to record. An effect writes, but
|
|
241
|
+
# its write is get-or-create, so a second arrival of one writes nothing already —
|
|
242
|
+
# and it writes in `acquire`, before its algorithm has run, so its reply is not
|
|
243
|
+
# known where the record is made.
|
|
244
|
+
once:
|
|
245
|
+
const: ~ # never pass
|
|
246
|
+
- if: # commits more than one entity
|
|
247
|
+
properties:
|
|
248
|
+
type:
|
|
249
|
+
const: transition
|
|
250
|
+
scope:
|
|
251
|
+
const: entries
|
|
252
|
+
then:
|
|
253
|
+
properties:
|
|
254
|
+
# the reply is recorded, and over a set it is unbounded
|
|
255
|
+
once:
|
|
256
|
+
const: ~ # never pass
|
|
170
257
|
- if: # observation
|
|
171
258
|
properties:
|
|
172
259
|
type:
|
|
@@ -174,7 +261,7 @@ properties:
|
|
|
174
261
|
then:
|
|
175
262
|
properties:
|
|
176
263
|
scope:
|
|
177
|
-
enum: [
|
|
264
|
+
enum: [entry, entries, stream, none]
|
|
178
265
|
query:
|
|
179
266
|
not:
|
|
180
267
|
const: false
|
|
@@ -189,15 +276,13 @@ properties:
|
|
|
189
276
|
- if: # computation
|
|
190
277
|
properties:
|
|
191
278
|
type:
|
|
192
|
-
|
|
279
|
+
enum: [computation, unmanaged]
|
|
193
280
|
then:
|
|
194
281
|
properties:
|
|
195
282
|
scope:
|
|
196
283
|
const: none
|
|
197
|
-
default: none
|
|
198
284
|
query:
|
|
199
285
|
const: false
|
|
200
|
-
default: false
|
|
201
286
|
- if: # effect
|
|
202
287
|
properties:
|
|
203
288
|
type:
|
|
@@ -205,20 +290,23 @@ properties:
|
|
|
205
290
|
then:
|
|
206
291
|
properties:
|
|
207
292
|
scope:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
293
|
+
enum: [entry, entries, stream, none]
|
|
294
|
+
- if: # takes a stream
|
|
295
|
+
required: [stream]
|
|
296
|
+
then:
|
|
297
|
+
properties:
|
|
298
|
+
type:
|
|
299
|
+
# a transition may run its algorithm twice over one call, and a stream is read once
|
|
300
|
+
enum: [effect, computation, unmanaged]
|
|
213
301
|
additionalProperties: false
|
|
214
302
|
additionalProperties: false
|
|
215
303
|
|
|
216
304
|
events:
|
|
217
305
|
type: object
|
|
218
306
|
propertyNames:
|
|
219
|
-
$ref:
|
|
307
|
+
$ref: "#/definitions/name"
|
|
220
308
|
patternProperties:
|
|
221
|
-
|
|
309
|
+
".*":
|
|
222
310
|
type: object
|
|
223
311
|
properties:
|
|
224
312
|
bridge:
|
|
@@ -226,49 +314,53 @@ properties:
|
|
|
226
314
|
path:
|
|
227
315
|
type: string
|
|
228
316
|
binding:
|
|
229
|
-
$ref:
|
|
317
|
+
$ref: "#/definitions/binding"
|
|
230
318
|
conditioned:
|
|
231
319
|
type: boolean
|
|
232
|
-
default: false
|
|
233
320
|
subjective:
|
|
234
321
|
type: boolean
|
|
235
|
-
default: false
|
|
236
322
|
required: [bridge, path]
|
|
237
323
|
additionalProperties: false
|
|
238
324
|
|
|
239
325
|
receivers:
|
|
240
326
|
type: object
|
|
241
327
|
patternProperties:
|
|
242
|
-
|
|
328
|
+
".*":
|
|
243
329
|
type: object
|
|
244
330
|
properties:
|
|
245
331
|
operation:
|
|
246
|
-
$ref:
|
|
332
|
+
$ref: "#/definitions/name"
|
|
247
333
|
bridge:
|
|
248
334
|
type: string
|
|
249
335
|
binding:
|
|
250
336
|
type: string
|
|
251
337
|
source:
|
|
252
|
-
$ref:
|
|
338
|
+
$ref: "#/definitions/name"
|
|
253
339
|
not:
|
|
254
340
|
const: context
|
|
255
341
|
path:
|
|
256
342
|
type: string
|
|
257
343
|
conditioned:
|
|
258
344
|
type: boolean
|
|
259
|
-
default: false
|
|
260
345
|
adaptive:
|
|
261
346
|
type: boolean
|
|
262
|
-
default: false
|
|
263
347
|
arguments:
|
|
264
348
|
type: array
|
|
265
349
|
required: [operation]
|
|
266
350
|
additionalProperties: false
|
|
267
351
|
|
|
268
|
-
|
|
352
|
+
guards:
|
|
269
353
|
type: object
|
|
354
|
+
patternProperties:
|
|
355
|
+
".*":
|
|
356
|
+
type: object
|
|
357
|
+
properties:
|
|
358
|
+
bridge: { type: string }
|
|
359
|
+
path: { type: string }
|
|
360
|
+
required: [bridge, path]
|
|
361
|
+
additionalProperties: false
|
|
270
362
|
|
|
271
|
-
|
|
363
|
+
extensions:
|
|
272
364
|
type: object
|
|
273
365
|
|
|
274
366
|
additionalProperties: false
|
|
@@ -1,25 +1,69 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'node:path'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { readFileSync } from 'node:fs'
|
|
4
|
+
import { yaml } from '@toa.io/generic'
|
|
5
|
+
import * as schemas from '@toa.io/schemas'
|
|
6
|
+
import { definition } from '../definition.js'
|
|
4
7
|
|
|
5
|
-
const
|
|
6
|
-
|
|
8
|
+
const object = yaml.load(
|
|
9
|
+
readFileSync(path.resolve(import.meta.dirname, 'schema.yaml'), 'utf8')
|
|
10
|
+
)
|
|
11
|
+
const schema = schemas.schema(object)
|
|
7
12
|
|
|
8
|
-
const
|
|
9
|
-
const schema = new Schema(object)
|
|
10
|
-
|
|
11
|
-
const validate = (manifest) => {
|
|
13
|
+
export const validate = async (manifest) => {
|
|
12
14
|
const error = schema.fit(manifest)
|
|
13
15
|
|
|
14
|
-
if (error) throw
|
|
16
|
+
if (error) throw error
|
|
15
17
|
|
|
16
|
-
if (manifest.
|
|
18
|
+
if (manifest.entity !== undefined) entity(manifest)
|
|
19
|
+
if (manifest.operations !== undefined) await streams(manifest)
|
|
20
|
+
if (manifest.events !== undefined) await events(manifest)
|
|
17
21
|
if (manifest.receivers !== undefined) receivers(manifest)
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
/** What only the entity's own declaration can answer: whether a name it uses is one it declares. */
|
|
25
|
+
const entity = (manifest) => {
|
|
26
|
+
const { properties, required, blank } = manifest.entity
|
|
27
|
+
|
|
28
|
+
// what an algorithm writes beside the record for the event of its commit; never stored
|
|
29
|
+
if (properties.TRAILERS !== undefined)
|
|
30
|
+
throw new Error("System property 'TRAILERS' cannot be declared")
|
|
31
|
+
|
|
32
|
+
for (const name of required ?? [])
|
|
33
|
+
if (properties[name] === undefined)
|
|
34
|
+
throw new Error(`Entity requires property '${name}', which is not defined`)
|
|
35
|
+
|
|
36
|
+
for (const name of Object.keys(blank ?? {}))
|
|
37
|
+
if (properties[name] === undefined)
|
|
38
|
+
throw new Error(`Entity blank names property '${name}', which is not defined`)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* An operation that takes a stream is reachable over a binding that carries one. A binding that
|
|
43
|
+
* declares none is served in this process alone, which is a component saying so.
|
|
44
|
+
*/
|
|
45
|
+
const streams = async (manifest) => {
|
|
46
|
+
for (const [endpoint, operation] of Object.entries(manifest.operations)) {
|
|
47
|
+
if (operation.stream === undefined || operation.bindings.length === 0) continue
|
|
48
|
+
if (await carried(operation.bindings)) continue
|
|
49
|
+
|
|
50
|
+
throw new Error(`Operation '${endpoint}' takes a stream, which none of its bindings carries`)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Whether any of these bindings carries a call whose input holds a stream. */
|
|
55
|
+
const carried = async (bindings) => {
|
|
56
|
+
for (const binding of bindings)
|
|
57
|
+
if ((await definition(binding)).module.properties.streams === true) return true
|
|
58
|
+
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const events = async (manifest) => {
|
|
21
63
|
for (const [label, event] of Object.entries(manifest.events)) {
|
|
22
|
-
|
|
64
|
+
const { properties } = (await definition(event.binding)).module
|
|
65
|
+
|
|
66
|
+
if (properties.async !== true) {
|
|
23
67
|
throw new Error(`Event '${label}' binding '${event.binding}' is not async`)
|
|
24
68
|
}
|
|
25
69
|
}
|
|
@@ -28,15 +72,17 @@ const events = (manifest) => {
|
|
|
28
72
|
const receivers = (manifest) => {
|
|
29
73
|
for (const [locator, receiver] of Object.entries(manifest.receivers)) {
|
|
30
74
|
if (manifest.operations?.[receiver.operation] === undefined) {
|
|
31
|
-
throw new Error(
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Receiver '${locator}' refers to undefined operation '${receiver.operation}'`
|
|
77
|
+
)
|
|
32
78
|
}
|
|
33
79
|
|
|
34
80
|
if (!TYPES.has(manifest.operations[receiver.operation].type)) {
|
|
35
|
-
throw new Error(
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Receiver '${locator}' must refer to an operation of the allowed types: ${Array.from(TYPES).join(', ')}`
|
|
83
|
+
)
|
|
36
84
|
}
|
|
37
85
|
}
|
|
38
86
|
}
|
|
39
87
|
|
|
40
|
-
const TYPES = new Set(['transition', 'effect'])
|
|
41
|
-
|
|
42
|
-
exports.validate = validate
|
|
88
|
+
const TYPES = new Set(['transition', 'assignment', 'effect', 'unmanaged'])
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { resolve } from 'node:path'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const connectors = (context, extracted) => {
|
|
3
|
+
export const connectors = (context, extracted) => {
|
|
6
4
|
const connectors = {}
|
|
7
5
|
|
|
8
|
-
const components =
|
|
6
|
+
const components =
|
|
7
|
+
(context.components === undefined
|
|
9
8
|
? extracted
|
|
10
|
-
: context.components.concat(extracted)
|
|
11
|
-
) ?? []
|
|
9
|
+
: context.components.concat(extracted)) ?? []
|
|
12
10
|
|
|
13
11
|
for (const component of components) {
|
|
14
12
|
if (component.entity !== undefined) {
|
|
@@ -47,5 +45,3 @@ const connectors = (context, extracted) => {
|
|
|
47
45
|
|
|
48
46
|
return connectors
|
|
49
47
|
}
|
|
50
|
-
|
|
51
|
-
exports.connectors = connectors
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* @param {toa.norm.Component} component
|
|
5
3
|
* @param {Object} manifest
|
|
6
4
|
* @returns {toa.norm.context.dependencies.Instance}
|
|
7
5
|
*/
|
|
8
|
-
const describe = (component, manifest = undefined) => ({
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
export const describe = (component, manifest = undefined) => ({
|
|
7
|
+
locator: component.locator,
|
|
8
|
+
manifest
|
|
9
|
+
})
|