@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.
Files changed (100) hide show
  1. package/CHANGELOG.md +305 -0
  2. package/package.json +9 -7
  3. package/src/.component/.expand/bridge.js +2 -6
  4. package/src/.component/.expand/entity.js +2 -9
  5. package/src/.component/.expand/events.js +2 -6
  6. package/src/.component/.expand/extensions.js +7 -9
  7. package/src/.component/.expand/index.js +7 -19
  8. package/src/.component/.expand/operations.js +2 -9
  9. package/src/.component/.expand/receivers.js +4 -7
  10. package/src/.component/.expand/version.js +69 -28
  11. package/src/.component/.normalize/entity.js +7 -0
  12. package/src/.component/.normalize/events.js +16 -4
  13. package/src/.component/.normalize/index.js +4 -9
  14. package/src/.component/.normalize/operations.js +13 -6
  15. package/src/.component/.normalize/receivers.js +4 -5
  16. package/src/.component/collapse.js +60 -9
  17. package/src/.component/defaults.js +5 -11
  18. package/src/.component/dependencies.js +14 -10
  19. package/src/.component/dereference.js +5 -49
  20. package/src/.component/expand.js +3 -9
  21. package/src/.component/extensions.js +9 -10
  22. package/src/.component/index.js +10 -21
  23. package/src/.component/merge.js +25 -15
  24. package/src/.component/migrations.js +57 -0
  25. package/src/.component/normalize.js +10 -6
  26. package/src/.component/schema.yaml +165 -73
  27. package/src/.component/validate.js +63 -17
  28. package/src/.context/.dependencies/connectors.js +5 -9
  29. package/src/.context/.dependencies/describe.js +4 -5
  30. package/src/.context/.dependencies/extensions.js +93 -20
  31. package/src/.context/.dependencies/index.js +3 -9
  32. package/src/.context/.dependencies/resolve.js +44 -7
  33. package/src/.context/complete.js +1 -5
  34. package/src/.context/converge.js +31 -0
  35. package/src/.context/dependencies.js +43 -6
  36. package/src/.context/dereference.js +11 -6
  37. package/src/.context/evict.js +38 -0
  38. package/src/.context/expand.js +11 -6
  39. package/src/.context/index.js +8 -15
  40. package/src/.context/normalize.js +9 -7
  41. package/src/.context/schema.yaml +183 -11
  42. package/src/.context/validate.js +11 -14
  43. package/src/component.js +33 -14
  44. package/src/context.js +44 -15
  45. package/src/definition.js +63 -0
  46. package/src/entity.js +15 -0
  47. package/src/index.js +7 -9
  48. package/src/manifest.js +154 -0
  49. package/src/map.js +24 -0
  50. package/src/shortcuts.js +11 -15
  51. package/test/component/collapse.fixtures.js +30 -39
  52. package/test/component/collapse.test.js +90 -10
  53. package/test/component/dependencies.test.js +16 -14
  54. package/test/component/dereference.fixtures.js +10 -98
  55. package/test/component/dereference.test.js +10 -14
  56. package/test/component/dummies/extension/index.js +1 -5
  57. package/test/component/dummies/migrations/conflicting/migrations/0001-one.yaml +2 -0
  58. package/test/component/dummies/migrations/conflicting/migrations/0001-one.yml +2 -0
  59. package/test/component/dummies/migrations/malformed/migrations/0001-one.yaml +1 -0
  60. package/test/component/dummies/migrations/ordered/migrations/0001-first.yml +4 -0
  61. package/test/component/dummies/migrations/ordered/migrations/0002-second.yaml +4 -0
  62. package/test/component/dummies/migrations/ordered/migrations/0010-third.json +1 -0
  63. package/test/component/dummies/migrations/stateless/migrations/0001-one.yaml +2 -0
  64. package/test/component/expand.fixtures.js +13 -13
  65. package/test/component/expand.test.js +17 -13
  66. package/test/component/migrations.test.js +62 -0
  67. package/test/component/normalize.fixtures.js +3 -7
  68. package/test/component/normalize.test.js +94 -28
  69. package/test/component/validate.fixtures.js +17 -15
  70. package/test/component/validate.test.js +289 -109
  71. package/test/context/complete.fixtures.js +2 -8
  72. package/test/context/complete.test.js +14 -8
  73. package/test/context/converge.test.js +57 -0
  74. package/test/context/dereference.fixtures.js +3 -9
  75. package/test/context/dereference.test.js +18 -7
  76. package/test/context/evict.fixtures.js +39 -0
  77. package/test/context/evict.test.js +73 -0
  78. package/test/context/expand.fixtures.js +1 -5
  79. package/test/context/expand.test.js +36 -8
  80. package/test/context/normalize.fixtures.js +2 -7
  81. package/test/context/normalize.test.js +33 -9
  82. package/test/context/validate.fixtures.js +1 -6
  83. package/test/context/validate.test.js +173 -35
  84. package/test/definition.test.js +35 -0
  85. package/test/dummies/bare/index.js +1 -0
  86. package/test/dummies/defined/definition.js +1 -0
  87. package/test/dummies/defined/index.js +1 -0
  88. package/test/dummies/defined/package.json +1 -0
  89. package/test/manifest.test.js +126 -0
  90. package/test/shortcuts.fixtures.js +4 -9
  91. package/test/shortcuts.test.js +17 -15
  92. package/test/system.test.js +31 -0
  93. package/types/component.d.ts +31 -4
  94. package/types/context/declaration.d.ts +34 -3
  95. package/types/context.d.ts +27 -13
  96. package/types/entity.d.ts +7 -0
  97. package/types/index.d.ts +18 -3
  98. package/src/.component/.expand/properties.js +0 -14
  99. package/src/.context/.dependencies/load.js +0 -36
  100. package/test/context/dependencies.load.test.js +0 -24
package/CHANGELOG.md ADDED
@@ -0,0 +1,305 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [1.0.0-alpha.321](https://github.com/toa-io/toa/compare/v1.0.0-alpha.320...v1.0.0-alpha.321) (2026-09-28)
7
+
8
+ ### Features
9
+
10
+ * **core:** let an operation declared unchained begin a chain of its own ([6d94324](https://github.com/toa-io/toa/commit/6d94324cb43ff4b12e1bc267d81498445b40a02e))
11
+
12
+
13
+ # [1.0.0-alpha.320](https://github.com/toa-io/toa/compare/v1.0.0-alpha.319...v1.0.0-alpha.320) (2026-09-28)
14
+
15
+ **Note:** Version bump only for package @toa.io/norm
16
+
17
+
18
+
19
+
20
+
21
+ # [1.0.0-alpha.319](https://github.com/toa-io/toa/compare/v1.0.0-alpha.318...v1.0.0-alpha.319) (2026-09-27)
22
+
23
+ **Note:** Version bump only for package @toa.io/norm
24
+
25
+
26
+
27
+
28
+
29
+ # [1.0.0-alpha.318](https://github.com/toa-io/toa/compare/v1.0.0-alpha.317...v1.0.0-alpha.318) (2026-09-23)
30
+
31
+ ### Features
32
+
33
+ * **norm:** hash what a component links into its version ([c01db29](https://github.com/toa-io/toa/commit/c01db29954efbda1a1787abaf20b727f2cbbe7e2))
34
+
35
+
36
+ # [1.0.0-alpha.317](https://github.com/toa-io/toa/compare/v1.0.0-alpha.316...v1.0.0-alpha.317) (2026-09-23)
37
+
38
+ **Note:** Version bump only for package @toa.io/norm
39
+
40
+
41
+
42
+
43
+
44
+ # [1.0.0-alpha.316](https://github.com/toa-io/toa/compare/v1.0.0-alpha.315...v1.0.0-alpha.316) (2026-09-23)
45
+
46
+ **Note:** Version bump only for package @toa.io/norm
47
+
48
+
49
+
50
+
51
+
52
+ # [1.0.0-alpha.315](https://github.com/toa-io/toa/compare/v1.0.0-alpha.314...v1.0.0-alpha.315) (2026-09-23)
53
+
54
+ * feat(map)!: leave out of a contract what the runtime gives every component ([b81837a](https://github.com/toa-io/toa/commit/b81837a3bc4771d7ee1c10fe613c9a1d7501bf1a))
55
+
56
+ ### BREAKING CHANGES
57
+
58
+ * the deployed component map is `/etc/toa/.map.json.gz`.
59
+
60
+
61
+ # [1.0.0-alpha.314](https://github.com/toa-io/toa/compare/v1.0.0-alpha.313...v1.0.0-alpha.314) (2026-09-19)
62
+
63
+ * feat(core)!: let an operation state how long its calls are remembered ([af177c2](https://github.com/toa-io/toa/commit/af177c2ab3d00d475840b5ef9e612f04e82b72bd))
64
+ * feat(core)!: rename trailers to the TRAILERS system property ([8d59ef9](https://github.com/toa-io/toa/commit/8d59ef90d04b7329578203fe10bd21fe41dfe2f5))
65
+
66
+ ### Features
67
+
68
+ * **core:** a reference may name a declaration its package claims ([8040f60](https://github.com/toa-io/toa/commit/8040f60976549ab90497675bb54e664261f5b6bb))
69
+
70
+ ### BREAKING CHANGES
71
+
72
+ * `inbox.retention` under 600 is refused. See
73
+ migrations/313.md.
74
+ * `state._trailers` is `state.TRAILERS`; see migrations/313.md.
75
+
76
+
77
+ # [1.0.0-alpha.313](https://github.com/toa-io/toa/compare/v1.0.0-alpha.312...v1.0.0-alpha.313) (2026-09-18)
78
+
79
+ **Note:** Version bump only for package @toa.io/norm
80
+
81
+
82
+
83
+
84
+
85
+ # [1.0.0-alpha.312](https://github.com/toa-io/toa/compare/v1.0.0-alpha.311...v1.0.0-alpha.312) (2026-09-18)
86
+
87
+ ### Features
88
+
89
+ * **bindings.http:** carry a call that holds a stream ([c571793](https://github.com/toa-io/toa/commit/c571793b617e3d5ae1dce5b98b64d67d7d8224f6))
90
+ * **cli:** write the property that carries a stream into a component's types ([8eae8ce](https://github.com/toa-io/toa/commit/8eae8cea011c0be78b27ed1380a1a6f17c9479f8))
91
+ * **norm:** let an operation declare the input property that carries a stream ([85a8f1f](https://github.com/toa-io/toa/commit/85a8f1ff5b62f658e0527dcce7230d8388d28fe0))
92
+ * **operations:** refuse to render a chart for a context with no version ([d6cd083](https://github.com/toa-io/toa/commit/d6cd083bfe8d7da9f3d451c2c25d821eb41ce958))
93
+
94
+
95
+ # [1.0.0-alpha.311](https://github.com/toa-io/toa/compare/v1.0.0-alpha.310...v1.0.0-alpha.311) (2026-09-17)
96
+
97
+ **Note:** Version bump only for package @toa.io/norm
98
+
99
+
100
+
101
+
102
+
103
+ # [1.0.0-alpha.310](https://github.com/toa-io/toa/compare/v1.0.0-alpha.309...v1.0.0-alpha.310) (2026-09-16)
104
+
105
+ **Note:** Version bump only for package @toa.io/norm
106
+
107
+
108
+
109
+
110
+
111
+ # [1.0.0-alpha.309](https://github.com/toa-io/toa/compare/v1.0.0-alpha.308...v1.0.0-alpha.309) (2026-09-16)
112
+
113
+ **Note:** Version bump only for package @toa.io/norm
114
+
115
+
116
+
117
+
118
+
119
+ # [1.0.0-alpha.308](https://github.com/toa-io/toa/compare/v1.0.0-alpha.307...v1.0.0-alpha.308) (2026-09-15)
120
+
121
+ **Note:** Version bump only for package @toa.io/norm
122
+
123
+
124
+
125
+
126
+
127
+ # [1.0.0-alpha.307](https://github.com/toa-io/toa/compare/v1.0.0-alpha.306...v1.0.0-alpha.307) (2026-09-15)
128
+
129
+ **Note:** Version bump only for package @toa.io/norm
130
+
131
+
132
+
133
+
134
+
135
+ # [1.0.0-alpha.306](https://github.com/toa-io/toa/compare/v1.0.0-alpha.305...v1.0.0-alpha.306) (2026-09-14)
136
+
137
+ **Note:** Version bump only for package @toa.io/norm
138
+
139
+
140
+
141
+
142
+
143
+ # [1.0.0-alpha.305](https://github.com/toa-io/toa/compare/v1.0.0-alpha.304...v1.0.0-alpha.305) (2026-09-13)
144
+
145
+ **Note:** Version bump only for package @toa.io/norm
146
+
147
+
148
+
149
+
150
+
151
+ # [1.0.0-alpha.304](https://github.com/toa-io/toa/compare/v1.0.0-alpha.303...v1.0.0-alpha.304) (2026-09-13)
152
+
153
+ **Note:** Version bump only for package @toa.io/norm
154
+
155
+
156
+
157
+
158
+
159
+ # [1.0.0-alpha.303](https://github.com/toa-io/toa/compare/v1.0.0-alpha.302...v1.0.0-alpha.303) (2026-09-12)
160
+
161
+ ### Features
162
+
163
+ * **operations:** a composition states how many replicas it runs ([4466f5a](https://github.com/toa-io/toa/commit/4466f5abcc22c6dceb2994a0143b6bf9d5201d9d))
164
+ * **telemetry:** let a component declare its own metrics ([05aa3c7](https://github.com/toa-io/toa/commit/05aa3c72cd6a160e1cef99df6176a7f627075bc0))
165
+
166
+
167
+ # [1.0.0-alpha.302](https://github.com/toa-io/toa/compare/v1.0.0-alpha.301...v1.0.0-alpha.302) (2026-09-11)
168
+
169
+ **Note:** Version bump only for package @toa.io/norm
170
+
171
+
172
+
173
+
174
+
175
+ # [1.0.0-alpha.301](https://github.com/toa-io/toa/compare/v1.0.0-alpha.300...v1.0.0-alpha.301) (2026-09-11)
176
+
177
+ ### Bug Fixes
178
+
179
+ * **norm:** an operation that takes no input states none ([3b69b4c](https://github.com/toa-io/toa/commit/3b69b4c92b3f06361a3552f036a927f4ff32e58b))
180
+
181
+ ### Features
182
+
183
+ * **norm:** an environment name may fall back along a colon-separated chain ([a267c1c](https://github.com/toa-io/toa/commit/a267c1caae816a75ada8352d5361b99817c72eb1))
184
+ * **operations:** an evicted component is given its environment and configuration ([6cf7890](https://github.com/toa-io/toa/commit/6cf7890a632a2185d2b7d9790890a04187e5a897))
185
+
186
+
187
+ # [1.0.0-alpha.300](https://github.com/toa-io/toa/compare/v1.0.0-alpha.299...v1.0.0-alpha.300) (2026-09-11)
188
+
189
+ * feat(boot)!: a process is a thing, and an extension may keep something in one ([528d6cd](https://github.com/toa-io/toa/commit/528d6cdd307b45a6c30b6a184d7e06b3328cecf8))
190
+ * feat(core)!: an operation may ask to run once ([dca616c](https://github.com/toa-io/toa/commit/dca616cb380a7a389e277875d3bd5ca55a6e4d45))
191
+
192
+ ### Features
193
+
194
+ * **core:** a call may name the process it goes to, and wait for a set time ([7d8adb2](https://github.com/toa-io/toa/commit/7d8adb2772a95ff45ae5374efdedfb5a857fbbe9))
195
+ * **core:** an assignment may ask to run once as well ([10fbcbd](https://github.com/toa-io/toa/commit/10fbcbd86a5e82960e65f62c09d0a465ae8d0353))
196
+ * **norm:** a context says what it does not deploy ([135e6fd](https://github.com/toa-io/toa/commit/135e6fdfbc4270762028e9e5a0516766960ce59c))
197
+
198
+ ### BREAKING CHANGES
199
+
200
+ * `Storage.store`, `.upsert` and `.ensure` take one more
201
+ argument, and `Storage` has two more members. A connector that ignores them
202
+ works exactly as it did; a component that asks it for `once` is refused at
203
+ boot. See migrations/299.md.
204
+ * a composition booted directly has no readiness probe. Readiness is
205
+ the process's, and a composition is not a process. `stage.workload` boots one where a
206
+ suite needs it.
207
+
208
+
209
+ # [1.0.0-alpha.299](https://github.com/toa-io/toa/compare/v1.0.0-alpha.298...v1.0.0-alpha.299) (2026-09-10)
210
+
211
+ ### Features
212
+
213
+ * **convergence:** deployments of one context converge ([8a70343](https://github.com/toa-io/toa/commit/8a70343cf6953aab58d4a25bac215508ff8d9a37))
214
+ * **convergence:** what an extension ships converges too ([b3be33d](https://github.com/toa-io/toa/commit/b3be33d2a1db45cfd844288467441aea2f4a722d))
215
+ * **core:** a record carries the region that wrote it ([13ed187](https://github.com/toa-io/toa/commit/13ed187604f06dec66feec2e26ccf9dae30bb048))
216
+
217
+
218
+ # [1.0.0-alpha.298](https://github.com/toa-io/toa/compare/v1.0.0-alpha.297...v1.0.0-alpha.298) (2026-09-08)
219
+
220
+ **Note:** Version bump only for package @toa.io/norm
221
+
222
+
223
+
224
+
225
+
226
+ # [1.0.0-alpha.297](https://github.com/toa-io/toa/compare/v1.0.0-alpha.296...v1.0.0-alpha.297) (2026-09-08)
227
+
228
+ **Note:** Version bump only for package @toa.io/norm
229
+
230
+
231
+
232
+
233
+
234
+ # [1.0.0-alpha.296](https://github.com/toa-io/toa/compare/v1.0.0-alpha.295...v1.0.0-alpha.296) (2026-09-08)
235
+
236
+ **Note:** Version bump only for package @toa.io/norm
237
+
238
+
239
+
240
+
241
+
242
+ # [1.0.0-alpha.295](https://github.com/toa-io/toa/compare/v1.0.0-alpha.294...v1.0.0-alpha.295) (2026-09-07)
243
+
244
+ **Note:** Version bump only for package @toa.io/norm
245
+
246
+
247
+
248
+
249
+
250
+ # [1.0.0-alpha.294](https://github.com/toa-io/toa/compare/v1.0.0-alpha.293...v1.0.0-alpha.294) (2026-09-07)
251
+
252
+ **Note:** Version bump only for package @toa.io/norm
253
+
254
+
255
+
256
+
257
+
258
+ # [1.0.0-alpha.293](https://github.com/toa-io/toa/compare/v1.0.0-alpha.292...v1.0.0-alpha.293) (2026-09-07)
259
+
260
+ **Note:** Version bump only for package @toa.io/norm
261
+
262
+
263
+
264
+
265
+
266
+ # [1.0.0-alpha.292](https://github.com/toa-io/toa/compare/v1.0.0-alpha.291...v1.0.0-alpha.292) (2026-09-07)
267
+
268
+ ### Features
269
+
270
+ * **cli:** the deployment library is a peer, and the binary is the CLI's ([a923f81](https://github.com/toa-io/toa/commit/a923f8173a55ed1c091213a7c7db1863ca1d0ba6))
271
+ * **definitions:** the version of Toa is the definitions package's ([3d0272e](https://github.com/toa-io/toa/commit/3d0272ea0ab862f4b6c2e58a2f003f92d0f8a87f))
272
+ * **definitions:** what a package declares is read from one package ([7052341](https://github.com/toa-io/toa/commit/70523411b5d9e2b204c999aa02365173f3bb518d))
273
+ * **norm:** a package's definition is read by one resolver ([bffd41c](https://github.com/toa-io/toa/commit/bffd41c8d18c42786b0bf321623088b9dabc4724))
274
+
275
+
276
+ # [1.0.0-alpha.291](https://github.com/toa-io/toa/compare/v1.0.0-alpha.290...v1.0.0-alpha.291) (2026-09-07)
277
+
278
+ **Note:** Version bump only for package @toa.io/norm
279
+
280
+
281
+
282
+
283
+
284
+ # [1.0.0-alpha.289](https://github.com/toa-io/toa/compare/v1.0.0-alpha.288...v1.0.0-alpha.289) (2026-09-07)
285
+
286
+ * A deploy moves only what changed, and a component sees none of the runtime's environment (#1073) ([f38e3db](https://github.com/toa-io/toa/commit/f38e3db533f24db866c57bfa1ef294eff1eaf499)), closes [#1073](https://github.com/toa-io/toa/issues/1073) [#1064](https://github.com/toa-io/toa/issues/1064) [#1066](https://github.com/toa-io/toa/issues/1066) [#1067](https://github.com/toa-io/toa/issues/1067) [#1068](https://github.com/toa-io/toa/issues/1068) [#1069](https://github.com/toa-io/toa/issues/1069) [#1071](https://github.com/toa-io/toa/issues/1071) [#1070](https://github.com/toa-io/toa/issues/1070) [#1072](https://github.com/toa-io/toa/issues/1072)
287
+
288
+ ### BREAKING CHANGES
289
+
290
+ * a component that read `process.env.TOA_*` reads `context` instead;
291
+ `echo(input)` no longer substitutes from the environment; a bash operation sees no
292
+ `TOA_*`; images no longer set `USER node` — see migrations/289.md.
293
+
294
+
295
+ # [1.0.0-alpha.288](https://github.com/toa-io/toa/compare/v1.0.0-alpha.287...v1.0.0-alpha.288) (2026-09-06)
296
+
297
+ **Note:** Version bump only for package @toa.io/norm
298
+
299
+
300
+
301
+
302
+
303
+ # [1.0.0-alpha.287](https://github.com/toa-io/toa/compare/v1.0.0-alpha.286...v1.0.0-alpha.287) (2026-09-06)
304
+
305
+ **Note:** Version bump only for package @toa.io/norm
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@toa.io/norm",
3
- "version": "1.0.0-alpha.32",
3
+ "version": "1.0.0-alpha.321",
4
+ "type": "module",
4
5
  "description": "Toa declarations normalization and validation",
5
6
  "author": "temich <tema.gurtovoy@gmail.com>",
6
7
  "homepage": "https://github.com/toa-io/toa#readme",
@@ -20,11 +21,12 @@
20
21
  "test": "echo \"Error: run tests from root\" && exit 1"
21
22
  },
22
23
  "dependencies": {
23
- "@toa.io/core": "1.0.0-alpha.32",
24
- "@toa.io/generic": "1.0.0-alpha.32",
25
- "@toa.io/schema": "1.0.0-alpha.32",
26
- "@toa.io/schemas": "1.0.0-alpha.32",
27
- "@toa.io/yaml": "1.0.0-alpha.32"
24
+ "@toa.io/core": "1.0.0-alpha.321",
25
+ "@toa.io/definitions": "1.0.0-alpha.321",
26
+ "@toa.io/generic": "1.0.0-alpha.311",
27
+ "@toa.io/prototype": "1.0.0-alpha.319",
28
+ "@toa.io/schemas": "1.0.0-alpha.311",
29
+ "fast-glob": "3.3.3"
28
30
  },
29
- "gitHead": "93ceb53797363abb77eb9c550db77e906691d42a"
31
+ "gitHead": "fa850e861a0c748d7364ccf7c8a09ce26973fc04"
30
32
  }
@@ -1,9 +1,5 @@
1
- 'use strict'
1
+ import { resolve } from '../../shortcuts.js'
2
2
 
3
- const { resolve } = require('../../shortcuts')
4
-
5
- function bridge (manifest) {
3
+ export function bridge(manifest) {
6
4
  manifest.bridge = resolve(manifest.bridge)
7
5
  }
8
-
9
- exports.bridge = bridge
@@ -1,14 +1,7 @@
1
- 'use strict'
1
+ import { resolve } from '../../shortcuts.js'
2
2
 
3
- const { expand } = require('@toa.io/schemas')
4
-
5
- const { resolve } = require('../../shortcuts')
6
-
7
- function entity (manifest) {
3
+ export function entity(manifest) {
8
4
  if (!('entity' in manifest)) return
9
- if ('schema' in manifest.entity) manifest.entity.schema = expand(manifest.entity.schema)
10
5
 
11
6
  manifest.entity.storage = resolve(manifest.entity.storage)
12
7
  }
13
-
14
- exports.entity = entity
@@ -1,8 +1,6 @@
1
- 'use strict'
1
+ import { resolve } from '../../shortcuts.js'
2
2
 
3
- const { resolve } = require('../../shortcuts')
4
-
5
- function events (manifest) {
3
+ export function events(manifest) {
6
4
  if (manifest.events === undefined) return
7
5
 
8
6
  for (const event of Object.values(manifest.events)) {
@@ -10,5 +8,3 @@ function events (manifest) {
10
8
  if (event.bridge !== undefined) event.bridge = resolve(event.bridge)
11
9
  }
12
10
  }
13
-
14
- exports.events = events
@@ -1,20 +1,18 @@
1
- 'use strict'
1
+ import { recognize } from '../../shortcuts.js'
2
2
 
3
- const { recognize } = require('../../shortcuts')
4
-
5
- function extensions (manifest) {
3
+ export function extensions(manifest) {
6
4
  recognize(SHORTCUTS, manifest, 'extensions')
7
5
  recognize(SHORTCUTS, manifest.extensions)
8
6
  }
9
7
 
10
8
  const SHORTCUTS = {
11
9
  exposition: '@toa.io/extensions.exposition',
12
- realtime: '@toa.io/extensions.realtime',
13
- origins: '@toa.io/extensions.origins',
10
+ realtime: '@toa.io/extensions.exposition#realtime',
14
11
  configuration: '@toa.io/extensions.configuration',
15
12
  state: '@toa.io/extensions.state',
16
13
  stash: '@toa.io/extensions.stash',
17
- storages: '@toa.io/extensions.storages'
14
+ storages: '@toa.io/extensions.storages',
15
+ cadence: '@toa.io/extensions.cadence',
16
+ introspection: '@toa.io/extensions.introspection',
17
+ telemetry: '@toa.io/extensions.telemetry'
18
18
  }
19
-
20
- exports.extensions = extensions
@@ -1,19 +1,7 @@
1
- 'use strict'
2
-
3
- const { bridge } = require('./bridge')
4
- const { entity } = require('./entity')
5
- const { events } = require('./events')
6
- const { extensions } = require('./extensions')
7
- const { operations } = require('./operations')
8
- const { properties } = require('./properties')
9
- const { receivers } = require('./receivers')
10
- const { version } = require('./version')
11
-
12
- exports.bridge = bridge
13
- exports.entity = entity
14
- exports.events = events
15
- exports.extensions = extensions
16
- exports.operations = operations
17
- exports.properties = properties
18
- exports.receivers = receivers
19
- exports.version = version
1
+ export { bridge } from './bridge.js'
2
+ export { entity } from './entity.js'
3
+ export { events } from './events.js'
4
+ export { extensions } from './extensions.js'
5
+ export { operations } from './operations.js'
6
+ export { receivers } from './receivers.js'
7
+ export { version } from './version.js'
@@ -1,14 +1,9 @@
1
- 'use strict'
1
+ import { resolve } from '../../shortcuts.js'
2
2
 
3
- const { expand } = require('@toa.io/schemas')
4
- const { resolve } = require('../../shortcuts')
5
-
6
- function operations (manifest) {
3
+ export function operations(manifest) {
7
4
  if (manifest.operations === undefined) return
8
5
 
9
6
  for (const operation of Object.values(manifest.operations)) {
10
- if (operation.input !== undefined) operation.input = expand(operation.input)
11
- if (operation.output !== undefined) operation.output = expand(operation.output)
12
7
  if (operation.bridge !== undefined) operation.bridge = resolve(operation.bridge)
13
8
 
14
9
  if (operation.bindings !== undefined && operation.bindings !== null) {
@@ -16,5 +11,3 @@ function operations (manifest) {
16
11
  }
17
12
  }
18
13
  }
19
-
20
- exports.operations = operations
@@ -1,16 +1,13 @@
1
- 'use strict'
1
+ import { resolve } from '../../shortcuts.js'
2
2
 
3
- const { resolve } = require('../../shortcuts')
4
-
5
- function receivers (manifest) {
3
+ export function receivers(manifest) {
6
4
  if (manifest.receivers === undefined) return
7
5
 
8
6
  for (const [locator, receiver] of Object.entries(manifest.receivers)) {
9
- if (typeof receiver === 'string') manifest.receivers[locator] = { operation: receiver }
7
+ if (typeof receiver === 'string')
8
+ manifest.receivers[locator] = { operation: receiver }
10
9
 
11
10
  if (receiver.binding !== undefined) receiver.binding = resolve(receiver.binding)
12
11
  if (receiver.bridge !== undefined) receiver.bridge = resolve(receiver.bridge)
13
12
  }
14
13
  }
15
-
16
- exports.receivers = receivers
@@ -1,45 +1,86 @@
1
- 'use strict'
1
+ import { join } from 'node:path'
2
+ import { createHash } from 'node:crypto'
3
+ import fs from 'node:fs/promises'
4
+ import glob from 'fast-glob'
2
5
 
3
- const { join } = require('node:path')
4
- const { createHash } = require('node:crypto')
5
- const fs = require('node:fs/promises')
6
- const { createReadStream } = require('node:fs')
7
- const { once } = require('node:events')
6
+ import { definition } from '../../definition.js'
8
7
 
9
- async function version (manifest) {
10
- manifest.version ??= await hash(manifest.path)
8
+ export async function version(manifest) {
9
+ manifest.version ??= await hash(manifest)
11
10
  }
12
11
 
13
- async function hash (path) {
14
- const hash = await hashd(path)
12
+ /**
13
+ * Identifies a build of a component: it becomes the tag of its image, so it must be the
14
+ * same for the same sources and different for different ones — on any machine, and whichever
15
+ * build produced them.
16
+ *
17
+ * What a build leaves out cannot change it: the bridge states what no build ships, a component
18
+ * adds to that with `ignore` and puts one back with `!`, and `files` names what its version is
19
+ * made of where a build copies only some of it. Its manifest is always one of them, because
20
+ * what it declares is what a caller is held to.
21
+ */
22
+ async function hash(manifest) {
23
+ const files = (await list(manifest)).sort()
24
+ const digests = await Promise.all(files.map((file) => digest(join(manifest.path, file))))
25
+ const total = createHash('sha256')
15
26
 
16
- return hash.digest('hex').slice(0, 8)
27
+ // the path is part of it: moving a file changes the build even if no content did
28
+ for (let i = 0; i < files.length; i++) total.update(files[i]).update(digests[i])
29
+
30
+ return total.digest('hex').slice(0, 8)
17
31
  }
18
32
 
19
33
  /**
20
- * @param {string} path
21
- * @param {import('node:crypto').Hash} hash
34
+ * @param {toa.norm.Component} manifest
35
+ * @returns {Promise<string[]>} paths relative to the component
22
36
  */
23
- async function hashd (path, hash = createHash('sha256')) {
24
- const stat = await fs.stat(path)
37
+ async function list(manifest) {
38
+ const files = await glob(patterns(manifest.files), {
39
+ cwd: manifest.path,
40
+ dot: true,
41
+ onlyFiles: true,
42
+ // sources a component keeps outside its own directory are its own: what a link points to is
43
+ // hashed as the file it stands for, so changing it changes the version
44
+ followSymbolicLinks: true,
45
+ ignore: await ignore(manifest)
46
+ })
47
+
48
+ // what a component declares is what a caller is held to, so its manifest is always one of them
49
+ if (!files.includes(MANIFEST) && (await exists(join(manifest.path, MANIFEST))))
50
+ files.push(MANIFEST)
25
51
 
26
- if (stat.isFile()) {
27
- const stream = createReadStream(path)
52
+ return files
53
+ }
28
54
 
29
- stream.pipe(hash, { end: false })
55
+ /** A path names what is under it, and a pattern is taken as it is. */
56
+ function patterns(files = ['**']) {
57
+ return files.flatMap((file) => (file.includes('*') ? [file] : [file, file + '/**']))
58
+ }
30
59
 
31
- return await once(stream, 'end')
32
- }
60
+ async function ignore(manifest) {
61
+ const { module } = await definition(manifest.bridge)
62
+ const stated = manifest.ignore ?? []
63
+ const back = new Set(
64
+ stated.filter((pattern) => pattern[0] === '!').map((pattern) => pattern.slice(1))
65
+ )
33
66
 
34
- if (stat.isDirectory()) {
35
- const entries = await fs.opendir(path)
67
+ return [
68
+ ...(module.ignore ?? []).filter((pattern) => !back.has(pattern)),
69
+ ...stated.filter((pattern) => pattern[0] !== '!')
70
+ ]
71
+ }
36
72
 
37
- for await (const entry of entries) {
38
- await hashd(join(path, entry.name), hash)
39
- }
73
+ async function exists(path) {
74
+ return await fs
75
+ .access(path)
76
+ .then(() => true)
77
+ .catch(() => false)
78
+ }
40
79
 
41
- return hash
42
- }
80
+ async function digest(path) {
81
+ return createHash('sha256')
82
+ .update(await fs.readFile(path))
83
+ .digest()
43
84
  }
44
85
 
45
- exports.version = version
86
+ const MANIFEST = 'manifest.toa.yaml'
@@ -0,0 +1,7 @@
1
+ export function entity(component) {
2
+ if (component.entity === undefined) return
3
+
4
+ component.entity.storage ??= '@toa.io/storages.mongodb'
5
+ component.entity.associated ??= false
6
+ component.entity.custom ??= false
7
+ }
@@ -1,13 +1,25 @@
1
- 'use strict'
1
+ import { definition } from '../../definition.js'
2
2
 
3
- const events = (component) => {
3
+ export const events = async (component) => {
4
4
  if (component.events === undefined) return
5
5
 
6
- const binding = component.bindings.find((binding) => require(binding).properties.async === true)
6
+ const binding = await asynchronous(component.bindings)
7
7
 
8
8
  for (const event of Object.values(component.events)) {
9
9
  if (event.binding === undefined) event.binding = binding
10
+
11
+ event.conditioned ??= false
12
+ event.subjective ??= false
10
13
  }
11
14
  }
12
15
 
13
- exports.events = events
16
+ /** The first binding that carries events, which only its module can say. */
17
+ async function asynchronous(bindings) {
18
+ for (const binding of bindings) {
19
+ const { properties } = (await definition(binding)).module
20
+
21
+ if (properties.async === true) return binding
22
+ }
23
+
24
+ return undefined
25
+ }
@@ -1,9 +1,4 @@
1
- 'use strict'
2
-
3
- const { events } = require('./events')
4
- const { operations } = require('./operations')
5
- const { receivers } = require('./receivers')
6
-
7
- exports.events = events
8
- exports.operations = operations
9
- exports.receivers = receivers
1
+ export { entity } from './entity.js'
2
+ export { events } from './events.js'
3
+ export { operations } from './operations.js'
4
+ export { receivers } from './receivers.js'