@toa.io/norm 1.0.0-alpha.28 → 1.0.0-alpha.283

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 (72) hide show
  1. package/CHANGELOG.md +195 -0
  2. package/package.json +8 -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 +4 -8
  7. package/src/.component/.expand/index.js +8 -19
  8. package/src/.component/.expand/operations.js +2 -9
  9. package/src/.component/.expand/properties.js +2 -6
  10. package/src/.component/.expand/receivers.js +2 -6
  11. package/src/.component/.expand/version.js +39 -27
  12. package/src/.component/.normalize/events.js +12 -5
  13. package/src/.component/.normalize/index.js +3 -9
  14. package/src/.component/.normalize/operations.js +2 -6
  15. package/src/.component/.normalize/receivers.js +1 -5
  16. package/src/.component/collapse.js +7 -6
  17. package/src/.component/defaults.js +14 -7
  18. package/src/.component/dependencies.js +7 -6
  19. package/src/.component/dereference.js +8 -7
  20. package/src/.component/expand.js +2 -15
  21. package/src/.component/extensions.js +13 -7
  22. package/src/.component/index.js +9 -21
  23. package/src/.component/merge.js +22 -9
  24. package/src/.component/normalize.js +3 -7
  25. package/src/.component/schema.yaml +82 -41
  26. package/src/.component/validate.js +15 -16
  27. package/src/.context/.dependencies/connectors.js +2 -6
  28. package/src/.context/.dependencies/describe.js +1 -5
  29. package/src/.context/.dependencies/extensions.js +55 -18
  30. package/src/.context/.dependencies/index.js +3 -9
  31. package/src/.context/.dependencies/load.js +14 -13
  32. package/src/.context/.dependencies/resolve.js +23 -6
  33. package/src/.context/complete.js +1 -5
  34. package/src/.context/dependencies.js +2 -6
  35. package/src/.context/dereference.js +9 -6
  36. package/src/.context/expand.js +8 -6
  37. package/src/.context/index.js +6 -15
  38. package/src/.context/normalize.js +2 -6
  39. package/src/.context/schema.yaml +126 -7
  40. package/src/.context/validate.js +8 -14
  41. package/src/component.js +31 -28
  42. package/src/context.js +28 -20
  43. package/src/index.js +3 -9
  44. package/src/shortcuts.js +7 -12
  45. package/test/component/collapse.fixtures.js +2 -5
  46. package/test/component/collapse.test.js +17 -10
  47. package/test/component/dependencies.test.js +12 -10
  48. package/test/component/dereference.fixtures.js +2 -7
  49. package/test/component/dereference.test.js +9 -8
  50. package/test/component/dummies/extension/index.js +1 -5
  51. package/test/component/expand.fixtures.js +13 -13
  52. package/test/component/expand.test.js +25 -10
  53. package/test/component/normalize.fixtures.js +3 -7
  54. package/test/component/normalize.test.js +27 -17
  55. package/test/component/validate.fixtures.js +1 -5
  56. package/test/component/validate.test.js +89 -90
  57. package/test/context/complete.fixtures.js +2 -8
  58. package/test/context/complete.test.js +10 -8
  59. package/test/context/dependencies.load.test.js +13 -12
  60. package/test/context/dereference.fixtures.js +3 -9
  61. package/test/context/dereference.test.js +17 -7
  62. package/test/context/expand.fixtures.js +1 -5
  63. package/test/context/expand.test.js +34 -8
  64. package/test/context/normalize.fixtures.js +2 -7
  65. package/test/context/normalize.test.js +10 -8
  66. package/test/context/validate.fixtures.js +1 -6
  67. package/test/context/validate.test.js +54 -30
  68. package/test/shortcuts.fixtures.js +4 -9
  69. package/test/shortcuts.test.js +16 -15
  70. package/types/context/declaration.d.ts +25 -2
  71. package/types/context.d.ts +5 -4
  72. package/types/index.d.ts +3 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,195 @@
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.283](https://github.com/toa-io/toa/compare/v1.0.0-alpha.282...v1.0.0-alpha.283) (2026-09-04)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **exposition:** declare the errors the built-in components return ([27200c3](https://github.com/toa-io/toa/commit/27200c348ab09068d58c52c3e83208cb29cd7290))
11
+
12
+ ### Features
13
+
14
+ * **operations:** run extension services inside a composition ([154aced](https://github.com/toa-io/toa/commit/154aced047228a250ac3bab353e09432fcc5a34d))
15
+
16
+
17
+ # [1.0.0-alpha.282](https://github.com/toa-io/toa/compare/v1.0.0-alpha.281...v1.0.0-alpha.282) (2026-09-03)
18
+
19
+ **Note:** Version bump only for package @toa.io/norm
20
+
21
+
22
+
23
+
24
+
25
+ # [1.0.0-alpha.278](https://github.com/toa-io/toa/compare/v1.0.0-alpha.277...v1.0.0-alpha.278) (2026-09-03)
26
+
27
+ **Note:** Version bump only for package @toa.io/norm
28
+
29
+
30
+
31
+
32
+
33
+ # [1.0.0-alpha.277](https://github.com/toa-io/toa/compare/v1.0.0-alpha.276...v1.0.0-alpha.277) (2026-09-03)
34
+
35
+ ### Bug Fixes
36
+
37
+ * read a manifest the way js-yaml read one before ([fcea1b2](https://github.com/toa-io/toa/commit/fcea1b21996d6efa6c3198acbfc9f70f1ce0c35c))
38
+ * settle what the module loader made asynchronous ([d4ab9df](https://github.com/toa-io/toa/commit/d4ab9dfb09e382da311dba08f52214e7645f4a6c))
39
+ * what the loader resolves, and what it will not ([1b8a02f](https://github.com/toa-io/toa/commit/1b8a02ff0a5e0f18ee62e3f71bc81116f86f9af1))
40
+
41
+
42
+ # [1.0.0-alpha.274](https://github.com/toa-io/toa/compare/v1.0.0-alpha.273...v1.0.0-alpha.274) (2026-09-02)
43
+
44
+ **Note:** Version bump only for package @toa.io/norm
45
+
46
+
47
+
48
+
49
+
50
+ # [1.0.0-alpha.273](https://github.com/toa-io/toa/compare/v1.0.0-alpha.272...v1.0.0-alpha.273) (2026-09-02)
51
+
52
+ **Note:** Version bump only for package @toa.io/norm
53
+
54
+
55
+
56
+
57
+
58
+ # [1.0.0-alpha.272](https://github.com/toa-io/toa/compare/v1.0.0-alpha.271...v1.0.0-alpha.272) (2026-09-01)
59
+
60
+
61
+ ### Bug Fixes
62
+
63
+ * **atomicity:** honour a cluster, and let it be unreachable ([c475d66](https://github.com/toa-io/toa/commit/c475d663ddf7329d86da517ccceee4cb03280e95))
64
+
65
+
66
+ * feat(atomicity)!: take a quorum of independent servers ([862562f](https://github.com/toa-io/toa/commit/862562f24d77ec00127dbbd88d43802b208c643b))
67
+ * refactor(atomicity)!: take one Redis, not a cluster ([b0a4770](https://github.com/toa-io/toa/commit/b0a4770dff5dfe8fee4b9ae637a4dd297454fcd4))
68
+ * refactor(atomicity)!: take the lock manager from the stash ([4fd91eb](https://github.com/toa-io/toa/commit/4fd91eb2fdb68f7b87aaf16d182794bbc567ba57))
69
+ * refactor(core)!: pump the outbox in one cycle ([bf590fe](https://github.com/toa-io/toa/commit/bf590fe8ed59c701b5fd1a91ba4874685b79242f))
70
+ * refactor(atomicity)!: rename the connector and free it of the outbox ([21f1a41](https://github.com/toa-io/toa/commit/21f1a41aceafcfd35c7620014062fe46b54afa95))
71
+ * feat(core)!: commit events with the state that produced them ([1eb68cc](https://github.com/toa-io/toa/commit/1eb68cc435dbfa03faa16009fceb866693d22e1a)), closes [#20](https://github.com/toa-io/toa/issues/20)
72
+
73
+
74
+ ### Features
75
+
76
+ * **atomicity:** make the interval a setting, and stop repeating n-and-i ([5c3a6d1](https://github.com/toa-io/toa/commit/5c3a6d1533751a21b7eb7d9c737f1a270bf5a5ae))
77
+
78
+
79
+ ### BREAKING CHANGES
80
+
81
+ * `atomicity.redis` accepts a list again, of independent servers rather
82
+ than cluster nodes, and refuses an even number of them.
83
+
84
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
85
+ * `atomicity.redis` is a string. A list is refused at export.
86
+
87
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
88
+ * `context.stash.lock` is gone; lock through `context.atom` instead.
89
+ A stash pointer resolving to several addresses now uses the first.
90
+
91
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
92
+ * `Storage.outbox.pending` takes a fourth argument, the id to
93
+ continue from.
94
+
95
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
96
+ * `@toa.io/partitions.redis` is now `@toa.io/atomicity`, and its
97
+ `lanes(total)` is `slots(total)`. Redis is declared as `atomicity` in the context
98
+ rather than `outbox.redis`, and read from `TOA_ATOMICITY_REDIS`.
99
+ `TOA_OUTBOX_PARTITION_INTERVAL` is `TOA_ATOMICITY_INTERVAL`.
100
+
101
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
102
+ * `event.changeset` is removed; use `origin` and `state`. `State`
103
+ takes an `Outbox` in place of an `Emission`. `difference` is dropped from
104
+ `@toa.io/generic` along with its last caller.
105
+
106
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
107
+
108
+
109
+
110
+
111
+
112
+ # [1.0.0-alpha.270](https://github.com/toa-io/toa/compare/v1.0.0-alpha.269...v1.0.0-alpha.270) (2026-08-31)
113
+
114
+
115
+ ### Bug Fixes
116
+
117
+ * **norm:** resolve annotations keyed by a dependency id ([e2860cd](https://github.com/toa-io/toa/commit/e2860cd2cc93dd3a135c092db1d943f80648ee56))
118
+ * **norm:** return the hash after hashing a file ([35058bd](https://github.com/toa-io/toa/commit/35058bdaae19f367197ea5b800742349e507ab11))
119
+
120
+
121
+ ### Performance Improvements
122
+
123
+ * **boot:** stop paying for what a composition does not need to start ([1619c27](https://github.com/toa-io/toa/commit/1619c2743072f4706939ce72f3074e615d26a91e))
124
+
125
+
126
+
127
+
128
+
129
+ # [1.0.0-alpha.266](https://github.com/toa-io/toa/compare/v1.0.0-alpha.265...v1.0.0-alpha.266) (2026-08-29)
130
+
131
+ **Note:** Version bump only for package @toa.io/norm
132
+
133
+
134
+
135
+
136
+
137
+ # [1.0.0-alpha.265](https://github.com/toa-io/toa/compare/v1.0.0-alpha.264...v1.0.0-alpha.265) (2026-08-29)
138
+
139
+ **Note:** Version bump only for package @toa.io/norm
140
+
141
+
142
+
143
+
144
+
145
+ # [1.0.0-alpha.264](https://github.com/toa-io/toa/compare/v1.0.0-alpha.263...v1.0.0-alpha.264) (2026-08-29)
146
+
147
+ **Note:** Version bump only for package @toa.io/norm
148
+
149
+
150
+
151
+
152
+
153
+ # [1.0.0-alpha.263](https://github.com/toa-io/toa/compare/v1.0.0-alpha.262...v1.0.0-alpha.263) (2026-08-29)
154
+
155
+ **Note:** Version bump only for package @toa.io/norm
156
+
157
+
158
+
159
+
160
+
161
+ # [1.0.0-alpha.262](https://github.com/toa-io/toa/compare/v1.0.0-alpha.261...v1.0.0-alpha.262) (2026-08-28)
162
+
163
+
164
+ ### Features
165
+
166
+ * **introspection:** add the introspection extension ([a07ed86](https://github.com/toa-io/toa/commit/a07ed8651404258d544f3b6d8236e58cf4da09ac))
167
+ * **operations:** let a service claim a path prefix on the host ([02677d1](https://github.com/toa-io/toa/commit/02677d17fcd4222b07c3be458d93bcc496a016a8))
168
+
169
+
170
+
171
+
172
+
173
+ # [1.0.0-alpha.259](https://github.com/toa-io/toa/compare/v1.0.0-alpha.258...v1.0.0-alpha.259) (2026-08-24)
174
+
175
+ **Note:** Version bump only for package @toa.io/norm
176
+
177
+
178
+
179
+
180
+
181
+ # [1.0.0-alpha.257](https://github.com/toa-io/toa/compare/v1.0.0-alpha.256...v1.0.0-alpha.257) (2026-08-24)
182
+
183
+ **Note:** Version bump only for package @toa.io/norm
184
+
185
+
186
+
187
+
188
+
189
+ # [1.0.0-alpha.256](https://github.com/toa-io/toa/compare/v1.0.0-alpha.255...v1.0.0-alpha.256) (2026-08-23)
190
+
191
+
192
+ ### Features
193
+
194
+ * add toa mono and discover components at components/* ([787a111](https://github.com/toa-io/toa/commit/787a111c8f83e56ebc734801c97106c585d034ea))
195
+ * deploy a single mono image with toa deploy --mono ([a7f14f9](https://github.com/toa-io/toa/commit/a7f14f9877a280e9c74d16c195028b35d74fb15a))
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@toa.io/norm",
3
- "version": "1.0.0-alpha.28",
3
+ "version": "1.0.0-alpha.283",
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,11 @@
20
21
  "test": "echo \"Error: run tests from root\" && exit 1"
21
22
  },
22
23
  "dependencies": {
23
- "@toa.io/core": "1.0.0-alpha.28",
24
- "@toa.io/generic": "1.0.0-alpha.28",
25
- "@toa.io/schema": "1.0.0-alpha.28",
26
- "@toa.io/schemas": "1.0.0-alpha.28",
27
- "@toa.io/yaml": "1.0.0-alpha.28"
24
+ "@toa.io/core": "1.0.0-alpha.283",
25
+ "@toa.io/generic": "1.0.0-alpha.283",
26
+ "@toa.io/schemas": "1.0.0-alpha.283",
27
+ "fast-glob": "3.3.3",
28
+ "js-yaml": "5.4.1"
28
29
  },
29
- "gitHead": "89c3b7d1314e357c9e33df8d95f8d46954cd3bcf"
30
+ "gitHead": "2f52b023bed0ccb2ecdb2b82fe59fbe38bf282e1"
30
31
  }
@@ -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,8 +1,6 @@
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
  }
@@ -10,11 +8,9 @@ function extensions (manifest) {
10
8
  const SHORTCUTS = {
11
9
  exposition: '@toa.io/extensions.exposition',
12
10
  realtime: '@toa.io/extensions.realtime',
13
- origins: '@toa.io/extensions.origins',
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
+ introspection: '@toa.io/extensions.introspection'
18
16
  }
19
-
20
- exports.extensions = extensions
@@ -1,19 +1,8 @@
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 { properties } from './properties.js'
7
+ export { receivers } from './receivers.js'
8
+ 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,8 +1,6 @@
1
- 'use strict'
1
+ import { recognize } from '../../shortcuts.js'
2
2
 
3
- const { recognize } = require('../../shortcuts')
4
-
5
- function properties (manifest) {
3
+ export function properties (manifest) {
6
4
  recognize(SHORTCUTS, manifest, 'properties')
7
5
  recognize(SHORTCUTS, manifest.properties)
8
6
  }
@@ -10,5 +8,3 @@ function properties (manifest) {
10
8
  const SHORTCUTS = {
11
9
  queues: '@toa.io/storages.queues'
12
10
  }
13
-
14
- exports.properties = properties
@@ -1,8 +1,6 @@
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)) {
@@ -12,5 +10,3 @@ function receivers (manifest) {
12
10
  if (receiver.bridge !== undefined) receiver.bridge = resolve(receiver.bridge)
13
11
  }
14
12
  }
15
-
16
- exports.receivers = receivers
@@ -1,45 +1,57 @@
1
- 'use strict'
1
+ import { join } from 'node:path'
2
+ import { createHash } from 'node:crypto'
3
+ import fs from 'node:fs/promises'
2
4
 
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')
8
-
9
- async function version (manifest) {
5
+ export async function version (manifest) {
10
6
  manifest.version ??= await hash(manifest.path)
11
7
  }
12
8
 
9
+ /**
10
+ * Identifies a build of a component: it becomes the tag of its image, so it must be the
11
+ * same for the same sources and different for different ones — on any machine.
12
+ *
13
+ * What the image excludes cannot change it: `node_modules` is in the `.dockerignore` the
14
+ * build writes (see `operations/src/deployment/images/image.js`), so hashing it would only
15
+ * retag an identical image after a local install.
16
+ */
13
17
  async function hash (path) {
14
- const hash = await hashd(path)
18
+ const files = (await list(path)).sort()
19
+ const digests = await Promise.all(files.map((file) => digest(join(path, file))))
20
+ const total = createHash('sha256')
21
+
22
+ // the path is part of it: moving a file changes the build even if no content did
23
+ for (let i = 0; i < files.length; i++)
24
+ total.update(files[i]).update(digests[i])
15
25
 
16
- return hash.digest('hex').slice(0, 8)
26
+ return total.digest('hex').slice(0, 8)
17
27
  }
18
28
 
19
29
  /**
20
- * @param {string} path
21
- * @param {import('node:crypto').Hash} hash
30
+ * @param {string} root
31
+ * @param {string} [path] relative
32
+ * @param {string[]} [acc]
33
+ * @returns {Promise<string[]>} paths relative to `root`
22
34
  */
23
- async function hashd (path, hash = createHash('sha256')) {
24
- const stat = await fs.stat(path)
35
+ async function list (root, path = '', acc = []) {
36
+ const entries = await fs.readdir(join(root, path), { withFileTypes: true })
25
37
 
26
- if (stat.isFile()) {
27
- const stream = createReadStream(path)
38
+ for (const entry of entries) {
39
+ if (EXCLUDED.has(entry.name))
40
+ continue
28
41
 
29
- stream.pipe(hash, { end: false })
42
+ const relative = path === '' ? entry.name : `${path}/${entry.name}`
30
43
 
31
- return await once(stream, 'end')
44
+ if (entry.isDirectory())
45
+ await list(root, relative, acc)
46
+ else if (entry.isFile())
47
+ acc.push(relative)
32
48
  }
33
49
 
34
- if (stat.isDirectory()) {
35
- const entries = await fs.opendir(path)
36
-
37
- for await (const entry of entries) {
38
- await hashd(join(path, entry.name), hash)
39
- }
50
+ return acc
51
+ }
40
52
 
41
- return hash
42
- }
53
+ async function digest (path) {
54
+ return createHash('sha256').update(await fs.readFile(path)).digest()
43
55
  }
44
56
 
45
- exports.version = version
57
+ const EXCLUDED = new Set(['node_modules', '.git'])
@@ -1,13 +1,20 @@
1
- 'use strict'
2
-
3
- const events = (component) => {
1
+ export const events = async (component) => {
4
2
  if (component.events === undefined) return
5
3
 
6
- const binding = component.bindings.find((binding) => require(binding).properties.async === true)
4
+ const binding = await asynchronous(component.bindings)
7
5
 
8
6
  for (const event of Object.values(component.events)) {
9
7
  if (event.binding === undefined) event.binding = binding
10
8
  }
11
9
  }
12
10
 
13
- exports.events = events
11
+ /** The first binding that carries events, which only its module can say. */
12
+ async function asynchronous (bindings) {
13
+ for (const binding of bindings) {
14
+ const { properties } = await import(binding)
15
+
16
+ if (properties.async === true) return binding
17
+ }
18
+
19
+ return undefined
20
+ }
@@ -1,9 +1,3 @@
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 { events } from './events.js'
2
+ export { operations } from './operations.js'
3
+ export { receivers } from './receivers.js'
@@ -1,10 +1,8 @@
1
- 'use strict'
2
-
3
- const operations = (component) => {
1
+ export const operations = (component) => {
4
2
  if (component.operations === undefined) return
5
3
 
6
4
  for (const [endpoint, operation] of Object.entries(component.operations)) {
7
- if (operation.type === 'computation' || operation.type === 'effect')
5
+ if (operation.scope === 'none')
8
6
  operation.query = false
9
7
 
10
8
  if (operation.bindings === undefined) operation.bindings = component.bindings
@@ -12,5 +10,3 @@ const operations = (component) => {
12
10
  if (operation.virtual === true) delete component.operations[endpoint]
13
11
  }
14
12
  }
15
-
16
- exports.operations = operations
@@ -1,6 +1,4 @@
1
- 'use strict'
2
-
3
- function receivers (component) {
1
+ export function receivers (component) {
4
2
  if (component.receivers === undefined) return
5
3
 
6
4
  const receivers = component.receivers
@@ -18,5 +16,3 @@ function receivers (component) {
18
16
  receivers[newKey] = value
19
17
  }
20
18
  }
21
-
22
- exports.receivers = receivers
@@ -1,8 +1,6 @@
1
- 'use strict'
1
+ import { merge } from '@toa.io/generic'
2
2
 
3
- const { merge } = require('@toa.io/generic')
4
-
5
- const collapse = (manifest, prototype) => {
3
+ export const collapse = (manifest, prototype) => {
6
4
  delete manifest.prototype
7
5
 
8
6
  if (prototype.operations) {
@@ -42,7 +40,10 @@ const collapse = (manifest, prototype) => {
42
40
  delete prototype.entity.schema.properties.id
43
41
  }
44
42
 
43
+ if (prototype.events !== undefined && manifest.events !== undefined)
44
+ for (const event of Object.keys(prototype.events))
45
+ if (event in manifest.events)
46
+ delete prototype.events[event]
47
+
45
48
  merge(manifest, { entity, events, extensions })
46
49
  }
47
-
48
- exports.collapse = collapse
@@ -1,11 +1,11 @@
1
- 'use strict'
2
-
3
- const { hash } = require('@toa.io/generic')
4
- const assert = require('node:assert')
1
+ import { hash } from '@toa.io/generic'
5
2
 
6
3
  // these defaults are required before validation
7
- const defaults = (manifest) => {
8
- if (manifest.name === undefined) manifest.name = protoName(manifest)
4
+ export const defaults = (manifest, proto) => {
5
+ if (manifest.name === undefined)
6
+ if (proto) manifest.name = protoName(manifest)
7
+ else nameAfterDir(manifest)
8
+
9
9
  if (manifest.bindings === undefined) manifest.bindings = ['@toa.io/bindings.amqp']
10
10
  if (manifest.bridge === undefined) manifest.bridge = '@toa.io/bridges.node'
11
11
 
@@ -24,4 +24,11 @@ function protoName (manifest) {
24
24
  return 'proto' + hash(manifest.path)
25
25
  }
26
26
 
27
- exports.defaults = defaults
27
+ function nameAfterDir (manifest) {
28
+ const parts = manifest.path.split('/')
29
+ const dirname = parts[parts.length - 1]
30
+ const [name, namespace] = dirname.split('.').reverse()
31
+
32
+ manifest.name = name
33
+ manifest.namespace = namespace
34
+ }
@@ -1,16 +1,19 @@
1
- 'use strict'
1
+ import { createRequire } from 'node:module'
2
+ import { join, dirname } from 'node:path'
2
3
 
3
- const { join, dirname } = require('node:path')
4
+ // import.meta.resolve takes no paths, and a storage is resolved against the
5
+ // component that names it
6
+ const require = createRequire(import.meta.url)
4
7
 
5
8
  /**
6
9
  * @param {toa.norm.Component} component
7
10
  */
8
- const dependencies = (component) => {
11
+ export const dependencies = (component) => {
9
12
  if ('entity' in component) component.entity.storage = resolve(component.path, component.entity.storage)
10
13
  }
11
14
 
12
15
  function resolve (root, reference) {
13
- const paths = [root, __dirname]
16
+ const paths = [root, import.meta.dirname]
14
17
  const options = { paths }
15
18
 
16
19
  let path
@@ -25,5 +28,3 @@ function resolve (root, reference) {
25
28
 
26
29
  return dirname(path)
27
30
  }
28
-
29
- exports.dependencies = dependencies
@@ -1,8 +1,6 @@
1
- 'use strict'
1
+ import { merge } from '@toa.io/generic'
2
2
 
3
- const { merge } = require('@toa.io/generic')
4
-
5
- const dereference = (manifest) => {
3
+ export const dereference = (manifest) => {
6
4
  // schemas
7
5
  const resolver = createResolver(manifest.entity?.schema?.properties)
8
6
 
@@ -25,7 +23,12 @@ const createResolver = (properties) => (property) => {
25
23
  function operations (manifest, resolver) {
26
24
  for (const operation of Object.values(manifest.operations)) {
27
25
  if (operation.input !== undefined) operation.input = schema(operation.input, resolver)
28
- if (operation.output !== undefined) operation.output = schema(operation.output, resolver)
26
+
27
+ if (operation.output !== undefined)
28
+ if (Array.isArray(operation.output) && operation.output.length === 1)
29
+ operation.output = [schema(operation.output[0], resolver)]
30
+ else
31
+ operation.output = schema(operation.output, resolver)
29
32
  }
30
33
 
31
34
  // forwarding
@@ -72,5 +75,3 @@ const forward = (operation, operations) => {
72
75
 
73
76
  merge(operation, real)
74
77
  }
75
-
76
- exports.dereference = dereference