@toa.io/norm 1.0.0-alpha.33 → 1.0.0-alpha.330
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 +381 -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 +8 -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 +72 -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 -70
- package/src/.component/validate.js +67 -17
- package/src/.context/.dependencies/connectors.js +5 -9
- package/src/.context/.dependencies/describe.js +4 -5
- package/src/.context/.dependencies/extensions.js +98 -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 +44 -6
- package/src/.context/dereference.js +11 -6
- package/src/.context/evict.js +40 -0
- package/src/.context/expand.js +37 -5
- 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 +47 -15
- package/src/definition.js +63 -0
- package/src/entity.js +15 -0
- package/src/index.js +7 -9
- package/src/manifest.js +159 -0
- package/src/map.js +26 -0
- package/src/shortcuts.js +12 -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 +311 -108
- 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 +137 -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 +32 -5
- 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, DISCARD]
|
|
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 message of the error returned
|
|
190
|
+
type: array
|
|
191
|
+
items:
|
|
192
|
+
type: string
|
|
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,17 +290,23 @@ properties:
|
|
|
205
290
|
then:
|
|
206
291
|
properties:
|
|
207
292
|
scope:
|
|
208
|
-
|
|
209
|
-
|
|
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]
|
|
210
301
|
additionalProperties: false
|
|
211
302
|
additionalProperties: false
|
|
212
303
|
|
|
213
304
|
events:
|
|
214
305
|
type: object
|
|
215
306
|
propertyNames:
|
|
216
|
-
$ref:
|
|
307
|
+
$ref: "#/definitions/name"
|
|
217
308
|
patternProperties:
|
|
218
|
-
|
|
309
|
+
".*":
|
|
219
310
|
type: object
|
|
220
311
|
properties:
|
|
221
312
|
bridge:
|
|
@@ -223,49 +314,53 @@ properties:
|
|
|
223
314
|
path:
|
|
224
315
|
type: string
|
|
225
316
|
binding:
|
|
226
|
-
$ref:
|
|
317
|
+
$ref: "#/definitions/binding"
|
|
227
318
|
conditioned:
|
|
228
319
|
type: boolean
|
|
229
|
-
default: false
|
|
230
320
|
subjective:
|
|
231
321
|
type: boolean
|
|
232
|
-
default: false
|
|
233
322
|
required: [bridge, path]
|
|
234
323
|
additionalProperties: false
|
|
235
324
|
|
|
236
325
|
receivers:
|
|
237
326
|
type: object
|
|
238
327
|
patternProperties:
|
|
239
|
-
|
|
328
|
+
".*":
|
|
240
329
|
type: object
|
|
241
330
|
properties:
|
|
242
331
|
operation:
|
|
243
|
-
$ref:
|
|
332
|
+
$ref: "#/definitions/name"
|
|
244
333
|
bridge:
|
|
245
334
|
type: string
|
|
246
335
|
binding:
|
|
247
336
|
type: string
|
|
248
337
|
source:
|
|
249
|
-
$ref:
|
|
338
|
+
$ref: "#/definitions/name"
|
|
250
339
|
not:
|
|
251
340
|
const: context
|
|
252
341
|
path:
|
|
253
342
|
type: string
|
|
254
343
|
conditioned:
|
|
255
344
|
type: boolean
|
|
256
|
-
default: false
|
|
257
345
|
adaptive:
|
|
258
346
|
type: boolean
|
|
259
|
-
default: false
|
|
260
347
|
arguments:
|
|
261
348
|
type: array
|
|
262
349
|
required: [operation]
|
|
263
350
|
additionalProperties: false
|
|
264
351
|
|
|
265
|
-
|
|
352
|
+
guards:
|
|
266
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
|
|
267
362
|
|
|
268
|
-
|
|
363
|
+
extensions:
|
|
269
364
|
type: object
|
|
270
365
|
|
|
271
366
|
additionalProperties: false
|
|
@@ -1,25 +1,73 @@
|
|
|
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, and to have
|
|
29
|
+
// nothing of it committed; neither is ever stored
|
|
30
|
+
for (const name of ['TRAILERS', 'DISCARD'])
|
|
31
|
+
if (properties[name] !== undefined)
|
|
32
|
+
throw new Error(`System property '${name}' cannot be declared`)
|
|
33
|
+
|
|
34
|
+
for (const name of required ?? [])
|
|
35
|
+
if (properties[name] === undefined)
|
|
36
|
+
throw new Error(`Entity requires property '${name}', which is not defined`)
|
|
37
|
+
|
|
38
|
+
for (const name of Object.keys(blank ?? {}))
|
|
39
|
+
if (properties[name] === undefined)
|
|
40
|
+
throw new Error(`Entity blank names property '${name}', which is not defined`)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* An operation that takes a stream is reachable over a binding that carries one. A binding that
|
|
45
|
+
* declares none is served in this process alone, which is a component saying so.
|
|
46
|
+
*/
|
|
47
|
+
const streams = async (manifest) => {
|
|
48
|
+
for (const [endpoint, operation] of Object.entries(manifest.operations)) {
|
|
49
|
+
if (operation.stream === undefined || operation.bindings.length === 0) continue
|
|
50
|
+
if (await carried(operation.bindings)) continue
|
|
51
|
+
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Operation '${endpoint}' takes a stream, which none of its bindings carries`
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Whether any of these bindings carries a call whose input holds a stream. */
|
|
59
|
+
const carried = async (bindings) => {
|
|
60
|
+
for (const binding of bindings)
|
|
61
|
+
if ((await definition(binding)).module.properties.streams === true) return true
|
|
62
|
+
|
|
63
|
+
return false
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const events = async (manifest) => {
|
|
21
67
|
for (const [label, event] of Object.entries(manifest.events)) {
|
|
22
|
-
|
|
68
|
+
const { properties } = (await definition(event.binding)).module
|
|
69
|
+
|
|
70
|
+
if (properties.async !== true) {
|
|
23
71
|
throw new Error(`Event '${label}' binding '${event.binding}' is not async`)
|
|
24
72
|
}
|
|
25
73
|
}
|
|
@@ -28,15 +76,17 @@ const events = (manifest) => {
|
|
|
28
76
|
const receivers = (manifest) => {
|
|
29
77
|
for (const [locator, receiver] of Object.entries(manifest.receivers)) {
|
|
30
78
|
if (manifest.operations?.[receiver.operation] === undefined) {
|
|
31
|
-
throw new Error(
|
|
79
|
+
throw new Error(
|
|
80
|
+
`Receiver '${locator}' refers to undefined operation '${receiver.operation}'`
|
|
81
|
+
)
|
|
32
82
|
}
|
|
33
83
|
|
|
34
84
|
if (!TYPES.has(manifest.operations[receiver.operation].type)) {
|
|
35
|
-
throw new Error(
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Receiver '${locator}' must refer to an operation of the allowed types: ${Array.from(TYPES).join(', ')}`
|
|
87
|
+
)
|
|
36
88
|
}
|
|
37
89
|
}
|
|
38
90
|
}
|
|
39
91
|
|
|
40
|
-
const TYPES = new Set(['transition', 'effect'])
|
|
41
|
-
|
|
42
|
-
exports.validate = validate
|
|
92
|
+
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
|
+
})
|