@toa.io/norm 1.0.0-alpha.32 → 1.0.0-alpha.320
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 +298 -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 +162 -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 +271 -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 +29 -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,57 @@ 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
|
+
stream:
|
|
170
|
+
# the input property that carries a stream, read as its caller writes it; see documentation/streams.md
|
|
171
|
+
$ref: "#/definitions/name"
|
|
131
172
|
forward:
|
|
132
|
-
$ref:
|
|
173
|
+
$ref: "#/definitions/name"
|
|
133
174
|
bridge:
|
|
134
175
|
type: string
|
|
135
176
|
bindings:
|
|
136
|
-
$ref:
|
|
177
|
+
$ref: "#/properties/bindings"
|
|
178
|
+
description:
|
|
179
|
+
# what the operation is, for whoever reads it: a generated type, an OPTIONS, a model
|
|
180
|
+
type: string
|
|
137
181
|
input:
|
|
138
|
-
$ref:
|
|
182
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
139
183
|
output:
|
|
140
|
-
$ref:
|
|
184
|
+
$ref: https://json-schema.org/draft/2019-09/schema
|
|
185
|
+
errors:
|
|
186
|
+
# what a reply may carry as a code: the error schema allows either
|
|
187
|
+
type: array
|
|
188
|
+
items:
|
|
189
|
+
type: [string, integer]
|
|
141
190
|
query:
|
|
142
191
|
type: boolean
|
|
143
192
|
required: [type, scope, bindings]
|
|
@@ -149,8 +198,8 @@ properties:
|
|
|
149
198
|
then:
|
|
150
199
|
properties:
|
|
151
200
|
scope:
|
|
152
|
-
enum: [
|
|
153
|
-
if: #
|
|
201
|
+
enum: [entry, entries]
|
|
202
|
+
if: # not query: false
|
|
154
203
|
not:
|
|
155
204
|
properties:
|
|
156
205
|
query:
|
|
@@ -158,6 +207,17 @@ properties:
|
|
|
158
207
|
required: [query]
|
|
159
208
|
then:
|
|
160
209
|
required: [concurrency]
|
|
210
|
+
- if: # transition and scope=entries
|
|
211
|
+
properties:
|
|
212
|
+
type:
|
|
213
|
+
const: transition
|
|
214
|
+
scope:
|
|
215
|
+
const: entries
|
|
216
|
+
then:
|
|
217
|
+
properties:
|
|
218
|
+
query:
|
|
219
|
+
not:
|
|
220
|
+
const: false
|
|
161
221
|
- if: # not transition
|
|
162
222
|
not:
|
|
163
223
|
properties:
|
|
@@ -167,6 +227,30 @@ properties:
|
|
|
167
227
|
properties:
|
|
168
228
|
concurrency:
|
|
169
229
|
const: ~ # never pass
|
|
230
|
+
- if: # neither a transition nor an assignment
|
|
231
|
+
not:
|
|
232
|
+
properties:
|
|
233
|
+
type:
|
|
234
|
+
enum: [transition, assignment]
|
|
235
|
+
then:
|
|
236
|
+
properties:
|
|
237
|
+
# An operation that writes nothing has nothing to record. An effect writes, but
|
|
238
|
+
# its write is get-or-create, so a second arrival of one writes nothing already —
|
|
239
|
+
# and it writes in `acquire`, before its algorithm has run, so its reply is not
|
|
240
|
+
# known where the record is made.
|
|
241
|
+
once:
|
|
242
|
+
const: ~ # never pass
|
|
243
|
+
- if: # commits more than one entity
|
|
244
|
+
properties:
|
|
245
|
+
type:
|
|
246
|
+
const: transition
|
|
247
|
+
scope:
|
|
248
|
+
const: entries
|
|
249
|
+
then:
|
|
250
|
+
properties:
|
|
251
|
+
# the reply is recorded, and over a set it is unbounded
|
|
252
|
+
once:
|
|
253
|
+
const: ~ # never pass
|
|
170
254
|
- if: # observation
|
|
171
255
|
properties:
|
|
172
256
|
type:
|
|
@@ -174,7 +258,7 @@ properties:
|
|
|
174
258
|
then:
|
|
175
259
|
properties:
|
|
176
260
|
scope:
|
|
177
|
-
enum: [
|
|
261
|
+
enum: [entry, entries, stream, none]
|
|
178
262
|
query:
|
|
179
263
|
not:
|
|
180
264
|
const: false
|
|
@@ -189,15 +273,13 @@ properties:
|
|
|
189
273
|
- if: # computation
|
|
190
274
|
properties:
|
|
191
275
|
type:
|
|
192
|
-
|
|
276
|
+
enum: [computation, unmanaged]
|
|
193
277
|
then:
|
|
194
278
|
properties:
|
|
195
279
|
scope:
|
|
196
280
|
const: none
|
|
197
|
-
default: none
|
|
198
281
|
query:
|
|
199
282
|
const: false
|
|
200
|
-
default: false
|
|
201
283
|
- if: # effect
|
|
202
284
|
properties:
|
|
203
285
|
type:
|
|
@@ -205,20 +287,23 @@ properties:
|
|
|
205
287
|
then:
|
|
206
288
|
properties:
|
|
207
289
|
scope:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
290
|
+
enum: [entry, entries, stream, none]
|
|
291
|
+
- if: # takes a stream
|
|
292
|
+
required: [stream]
|
|
293
|
+
then:
|
|
294
|
+
properties:
|
|
295
|
+
type:
|
|
296
|
+
# a transition may run its algorithm twice over one call, and a stream is read once
|
|
297
|
+
enum: [effect, computation, unmanaged]
|
|
213
298
|
additionalProperties: false
|
|
214
299
|
additionalProperties: false
|
|
215
300
|
|
|
216
301
|
events:
|
|
217
302
|
type: object
|
|
218
303
|
propertyNames:
|
|
219
|
-
$ref:
|
|
304
|
+
$ref: "#/definitions/name"
|
|
220
305
|
patternProperties:
|
|
221
|
-
|
|
306
|
+
".*":
|
|
222
307
|
type: object
|
|
223
308
|
properties:
|
|
224
309
|
bridge:
|
|
@@ -226,49 +311,53 @@ properties:
|
|
|
226
311
|
path:
|
|
227
312
|
type: string
|
|
228
313
|
binding:
|
|
229
|
-
$ref:
|
|
314
|
+
$ref: "#/definitions/binding"
|
|
230
315
|
conditioned:
|
|
231
316
|
type: boolean
|
|
232
|
-
default: false
|
|
233
317
|
subjective:
|
|
234
318
|
type: boolean
|
|
235
|
-
default: false
|
|
236
319
|
required: [bridge, path]
|
|
237
320
|
additionalProperties: false
|
|
238
321
|
|
|
239
322
|
receivers:
|
|
240
323
|
type: object
|
|
241
324
|
patternProperties:
|
|
242
|
-
|
|
325
|
+
".*":
|
|
243
326
|
type: object
|
|
244
327
|
properties:
|
|
245
328
|
operation:
|
|
246
|
-
$ref:
|
|
329
|
+
$ref: "#/definitions/name"
|
|
247
330
|
bridge:
|
|
248
331
|
type: string
|
|
249
332
|
binding:
|
|
250
333
|
type: string
|
|
251
334
|
source:
|
|
252
|
-
$ref:
|
|
335
|
+
$ref: "#/definitions/name"
|
|
253
336
|
not:
|
|
254
337
|
const: context
|
|
255
338
|
path:
|
|
256
339
|
type: string
|
|
257
340
|
conditioned:
|
|
258
341
|
type: boolean
|
|
259
|
-
default: false
|
|
260
342
|
adaptive:
|
|
261
343
|
type: boolean
|
|
262
|
-
default: false
|
|
263
344
|
arguments:
|
|
264
345
|
type: array
|
|
265
346
|
required: [operation]
|
|
266
347
|
additionalProperties: false
|
|
267
348
|
|
|
268
|
-
|
|
349
|
+
guards:
|
|
269
350
|
type: object
|
|
351
|
+
patternProperties:
|
|
352
|
+
".*":
|
|
353
|
+
type: object
|
|
354
|
+
properties:
|
|
355
|
+
bridge: { type: string }
|
|
356
|
+
path: { type: string }
|
|
357
|
+
required: [bridge, path]
|
|
358
|
+
additionalProperties: false
|
|
270
359
|
|
|
271
|
-
|
|
360
|
+
extensions:
|
|
272
361
|
type: object
|
|
273
362
|
|
|
274
363
|
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
|
+
})
|