@toa.io/norm 1.0.0-alpha.266 → 1.0.0-alpha.270
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
CHANGED
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [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)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **norm:** resolve annotations keyed by a dependency id ([e2860cd](https://github.com/toa-io/toa/commit/e2860cd2cc93dd3a135c092db1d943f80648ee56))
|
|
12
|
+
* **norm:** return the hash after hashing a file ([35058bd](https://github.com/toa-io/toa/commit/35058bdaae19f367197ea5b800742349e507ab11))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Performance Improvements
|
|
16
|
+
|
|
17
|
+
* **boot:** stop paying for what a composition does not need to start ([1619c27](https://github.com/toa-io/toa/commit/1619c2743072f4706939ce72f3074e615d26a91e))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
6
23
|
# [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)
|
|
7
24
|
|
|
8
25
|
**Note:** Version bump only for package @toa.io/norm
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/norm",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.270",
|
|
4
4
|
"description": "Toa declarations normalization and validation",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
23
|
+
"@toa.io/core": "1.0.0-alpha.270",
|
|
24
24
|
"@toa.io/generic": "1.0.0-alpha.254",
|
|
25
|
-
"@toa.io/schemas": "1.0.0-alpha.
|
|
25
|
+
"@toa.io/schemas": "1.0.0-alpha.270",
|
|
26
26
|
"@toa.io/yaml": "1.0.0-alpha.254"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "94400bdd411b4c25074ffcf58184580ddd060268"
|
|
29
29
|
}
|
|
@@ -3,43 +3,59 @@
|
|
|
3
3
|
const { join } = require('node:path')
|
|
4
4
|
const { createHash } = require('node:crypto')
|
|
5
5
|
const fs = require('node:fs/promises')
|
|
6
|
-
const { createReadStream } = require('node:fs')
|
|
7
|
-
const { once } = require('node:events')
|
|
8
6
|
|
|
9
7
|
async function version (manifest) {
|
|
10
8
|
manifest.version ??= await hash(manifest.path)
|
|
11
9
|
}
|
|
12
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Identifies a build of a component: it becomes the tag of its image, so it must be the
|
|
13
|
+
* same for the same sources and different for different ones — on any machine.
|
|
14
|
+
*
|
|
15
|
+
* What the image excludes cannot change it: `node_modules` is in the `.dockerignore` the
|
|
16
|
+
* build writes (see `operations/src/deployment/images/image.js`), so hashing it would only
|
|
17
|
+
* retag an identical image after a local install.
|
|
18
|
+
*/
|
|
13
19
|
async function hash (path) {
|
|
14
|
-
const
|
|
20
|
+
const files = (await list(path)).sort()
|
|
21
|
+
const digests = await Promise.all(files.map((file) => digest(join(path, file))))
|
|
22
|
+
const total = createHash('sha256')
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
// the path is part of it: moving a file changes the build even if no content did
|
|
25
|
+
for (let i = 0; i < files.length; i++)
|
|
26
|
+
total.update(files[i]).update(digests[i])
|
|
27
|
+
|
|
28
|
+
return total.digest('hex').slice(0, 8)
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
/**
|
|
20
|
-
* @param {string}
|
|
21
|
-
* @param {
|
|
32
|
+
* @param {string} root
|
|
33
|
+
* @param {string} [path] relative
|
|
34
|
+
* @param {string[]} [acc]
|
|
35
|
+
* @returns {Promise<string[]>} paths relative to `root`
|
|
22
36
|
*/
|
|
23
|
-
async function
|
|
24
|
-
const
|
|
37
|
+
async function list (root, path = '', acc = []) {
|
|
38
|
+
const entries = await fs.readdir(join(root, path), { withFileTypes: true })
|
|
25
39
|
|
|
26
|
-
|
|
27
|
-
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
if (EXCLUDED.has(entry.name))
|
|
42
|
+
continue
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
const relative = path === '' ? entry.name : `${path}/${entry.name}`
|
|
30
45
|
|
|
31
|
-
|
|
46
|
+
if (entry.isDirectory())
|
|
47
|
+
await list(root, relative, acc)
|
|
48
|
+
else if (entry.isFile())
|
|
49
|
+
acc.push(relative)
|
|
32
50
|
}
|
|
33
51
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
for await (const entry of entries) {
|
|
38
|
-
await hashd(join(path, entry.name), hash)
|
|
39
|
-
}
|
|
52
|
+
return acc
|
|
53
|
+
}
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
async function digest (path) {
|
|
56
|
+
return createHash('sha256').update(await fs.readFile(path)).digest()
|
|
43
57
|
}
|
|
44
58
|
|
|
59
|
+
const EXCLUDED = new Set(['node_modules', '.git'])
|
|
60
|
+
|
|
45
61
|
exports.version = version
|
|
@@ -25,15 +25,27 @@ const resolve = (references, annotations) => {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
for (const dependency of Object.keys(annotations)) {
|
|
28
|
-
|
|
28
|
+
if (dependency in dependencies) continue
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
// an annotation may be keyed by a dependency id rather than by a module reference
|
|
31
|
+
const module = optional(dependency)
|
|
32
32
|
|
|
33
|
-
dependencies[dependency] = []
|
|
33
|
+
if (module?.standalone === true) dependencies[dependency] = []
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return dependencies
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* @param {string} reference
|
|
41
|
+
* @returns {object | null}
|
|
42
|
+
*/
|
|
43
|
+
function optional (reference) {
|
|
44
|
+
try {
|
|
45
|
+
return load(reference).module
|
|
46
|
+
} catch {
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
exports.resolve = resolve
|
|
@@ -11,17 +11,31 @@ beforeEach(() => {
|
|
|
11
11
|
source = clone(fixtures.source)
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
it('should expand', () => {
|
|
15
|
-
expand(source)
|
|
14
|
+
it('should expand', async () => {
|
|
15
|
+
await expand(source)
|
|
16
16
|
expect(source).toMatchObject(fixtures.target)
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
+
it('should derive version from the component contents', async () => {
|
|
20
|
+
await expand(source)
|
|
21
|
+
|
|
22
|
+
expect(source.version).toMatch(/^[0-9a-f]{8}$/)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should keep declared version', async () => {
|
|
26
|
+
source.version = '1.0.0'
|
|
27
|
+
|
|
28
|
+
await expand(source)
|
|
29
|
+
|
|
30
|
+
expect(source.version).toStrictEqual('1.0.0')
|
|
31
|
+
})
|
|
32
|
+
|
|
19
33
|
it('should recognize storages.queues', async () => {
|
|
20
34
|
const queues = { foo: 'bar' }
|
|
21
35
|
|
|
22
36
|
source.queues = clone(queues)
|
|
23
37
|
|
|
24
|
-
expand(source)
|
|
38
|
+
await expand(source)
|
|
25
39
|
|
|
26
40
|
expect(source.queues).toBeUndefined()
|
|
27
41
|
expect(source.properties['@toa.io/storages.queues']).toMatchObject(queues)
|