fidelity-kit 0.1.1 → 0.2.0
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/README.md +27 -2
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +2 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts +7 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +9 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/hash.d.ts +2 -0
- package/dist/commands/hash.d.ts.map +1 -1
- package/dist/commands/hash.js +7 -3
- package/dist/commands/hash.js.map +1 -1
- package/dist/commands/process.d.ts +6 -0
- package/dist/commands/process.d.ts.map +1 -1
- package/dist/commands/process.js +35 -7
- package/dist/commands/process.js.map +1 -1
- package/dist/commands/serve.d.ts +3 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +2 -1
- package/dist/commands/serve.js.map +1 -1
- package/dist/core/compare.d.ts +4 -2
- package/dist/core/compare.d.ts.map +1 -1
- package/dist/core/compare.js +7 -5
- package/dist/core/compare.js.map +1 -1
- package/dist/core/hash.d.ts +2 -0
- package/dist/core/hash.d.ts.map +1 -1
- package/dist/core/hash.js +37 -10
- package/dist/core/hash.js.map +1 -1
- package/dist/core/hash.test.js +8 -1
- package/dist/core/hash.test.js.map +1 -1
- package/dist/core/process.d.ts +52 -3
- package/dist/core/process.d.ts.map +1 -1
- package/dist/core/process.js +450 -57
- package/dist/core/process.js.map +1 -1
- package/dist/core/process.test.d.ts +2 -0
- package/dist/core/process.test.d.ts.map +1 -0
- package/dist/core/process.test.js +269 -0
- package/dist/core/process.test.js.map +1 -0
- package/dist/core/progress.d.ts +8 -0
- package/dist/core/progress.d.ts.map +1 -0
- package/dist/core/progress.js +2 -0
- package/dist/core/progress.js.map +1 -0
- package/dist/core/scan.d.ts +8 -1
- package/dist/core/scan.d.ts.map +1 -1
- package/dist/core/scan.js +70 -6
- package/dist/core/scan.js.map +1 -1
- package/dist/core/suite.test.js +24 -1
- package/dist/core/suite.test.js.map +1 -1
- package/dist/progress.d.ts +12 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +46 -0
- package/dist/progress.js.map +1 -0
- package/dist/progress.test.d.ts +2 -0
- package/dist/progress.test.d.ts.map +1 -0
- package/dist/progress.test.js +36 -0
- package/dist/progress.test.js.map +1 -0
- package/dist/run.d.ts +4 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +32 -6
- package/dist/run.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +20 -2
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +42 -1
- package/dist/server.test.js.map +1 -1
- package/dist/watch.d.ts +9 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +96 -0
- package/dist/watch.js.map +1 -0
- package/dist/watch.test.d.ts +2 -0
- package/dist/watch.test.d.ts.map +1 -0
- package/dist/watch.test.js +138 -0
- package/dist/watch.test.js.map +1 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# fidelity-kit
|
|
2
2
|
|
|
3
|
+
[![NPM Package][npm]][npm-url]
|
|
4
|
+
[![NPM Downloads][npm-downloads]][npmtrends-url]
|
|
5
|
+
[![Tests][tests-badge]][tests-url]
|
|
6
|
+
[![Coverage][coverage-badge]][coverage-url]
|
|
7
|
+
[![Discord][discord-badge]][discord-url]
|
|
8
|
+
|
|
3
9
|
**Compare renderer output without building a comparison site.** fidelity-kit turns a folder of AVIF renders into image quality metrics, visual difference images, and a browsable website. Use it for rendering fidelity suites, visual regression reviews, and side-by-side comparisons of a renderer against one or more references.
|
|
4
10
|
|
|
5
11
|
Your renderer writes images; fidelity-kit handles the comparisons and viewer. Run the viewer locally while developing, serve the results from a container, or export a static site.
|
|
@@ -12,7 +18,7 @@ If you already have a results folder in the format below:
|
|
|
12
18
|
npx fidelity-kit dev results
|
|
13
19
|
```
|
|
14
20
|
|
|
15
|
-
Open <http://localhost:3000
|
|
21
|
+
Open the URL printed by the command (usually <http://localhost:3000>). `dev` processes new or changed images before starting and serves files without browser caching, so a reload shows your latest render. See the [working example](https://github.com/bhouston/fidelity-kit/tree/main/examples/demo) for a complete suite.
|
|
16
22
|
|
|
17
23
|
## Adopt it in your suite
|
|
18
24
|
|
|
@@ -76,7 +82,9 @@ The CLI supports this workflow:
|
|
|
76
82
|
| `fidelity-kit serve results` | Process stale comparisons, then serve the viewer with browser and CDN caching. |
|
|
77
83
|
| `fidelity-kit build results --out site/` | Process stale comparisons and export a site for static hosting. |
|
|
78
84
|
|
|
79
|
-
`process` computes PSNR, RMSE, MAE, and maximum error for each available comparison. Reference and renderer images in a pair must have the same dimensions. Both `dev` and `serve`
|
|
85
|
+
`process` computes PSNR, RMSE, MAE, and maximum error for each available comparison. Reference and renderer images in a pair must have the same dimensions. Both `dev` and `serve` start at `localhost:3000` and try higher ports if one is occupied; use `--port` to require a specific port and `--host` to change the bind address. The actual viewer URL is printed at startup. To serve results already processed during a build, pass `--no-process`.
|
|
86
|
+
|
|
87
|
+
`process`, `dev`, and `hash` show scanning and processing progress on one updating terminal line, including the remaining count and an approximate ETA. Use `--quiet` to suppress progress and summary output; errors are still reported.
|
|
80
88
|
|
|
81
89
|
For example, add scripts to your suite's `package.json`:
|
|
82
90
|
|
|
@@ -116,3 +124,20 @@ Open <http://localhost:8080>. `hash` prepares versioned image URLs so repeat vis
|
|
|
116
124
|
## Author and sponsor
|
|
117
125
|
|
|
118
126
|
Created by [Ben Houston](https://github.com/bhouston) and sponsored by [Land of Assets](https://landofassets.com).
|
|
127
|
+
|
|
128
|
+
[npm]: https://img.shields.io/npm/v/fidelity-kit
|
|
129
|
+
[npm-url]: https://www.npmjs.com/package/fidelity-kit
|
|
130
|
+
[npm-downloads]: https://img.shields.io/npm/dw/fidelity-kit
|
|
131
|
+
[npmtrends-url]: https://www.npmtrends.com/fidelity-kit
|
|
132
|
+
[tests-badge]: https://github.com/bhouston/fidelity-kit/actions/workflows/ci.yml/badge.svg
|
|
133
|
+
[tests-url]: https://github.com/bhouston/fidelity-kit/actions/workflows/ci.yml
|
|
134
|
+
[coverage-badge]: https://codecov.io/gh/bhouston/fidelity-kit/branch/main/graph/badge.svg
|
|
135
|
+
[coverage-url]: https://codecov.io/gh/bhouston/fidelity-kit
|
|
136
|
+
[discord-badge]: https://img.shields.io/badge/Discord-Join-5865F2?logo=discord&logoColor=white
|
|
137
|
+
[discord-url]: https://discord.gg/5J5Ur3F6Z2
|
|
138
|
+
|
|
139
|
+
### Incremental processing
|
|
140
|
+
|
|
141
|
+
`process --watch` and `dev` retain per-scene dependencies, batch source changes, and share the configured `--concurrency` limit. Scenes and renderer/reference images can be added or removed while watching. Restart after changing renderer IDs, output/pass IDs, or other settings in `fidelity.json`.
|
|
142
|
+
|
|
143
|
+
Input freshness uses modification time and byte size recorded in metrics files. Older-dated replacements are detected; changes preserving both values require `--force`. Metrics without saved input signatures are regenerated once. Generated metrics, delta images, index files, and temporary writes are ignored by the watcher. Removed comparisons are dropped from the index; generated files may remain on disk.
|
package/dist/commands/build.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO;;;;;;;;EA+BlB,CAAC"}
|
package/dist/commands/build.js
CHANGED
|
@@ -14,13 +14,14 @@ export const command = defineCommand({
|
|
|
14
14
|
describe: 'Suite results directory (contains fidelity.json)',
|
|
15
15
|
})
|
|
16
16
|
.option('out', { type: 'string', demandOption: true, describe: 'Output directory' })
|
|
17
|
+
.option('concurrency', { type: 'number', describe: 'Image pairs compared in parallel (default: CPU count)' })
|
|
17
18
|
.option('process', { type: 'boolean', default: true, describe: 'Refresh stale metrics/deltas first' }),
|
|
18
19
|
handler: async (argv) => {
|
|
19
20
|
assertViewerBuilt();
|
|
20
21
|
const root = resolve(argv.root);
|
|
21
22
|
const out = resolve(argv.out);
|
|
22
23
|
if (argv.process) {
|
|
23
|
-
const result = await processSuite(root);
|
|
24
|
+
const result = await processSuite(root, { concurrency: argv.concurrency });
|
|
24
25
|
if (result.failed.length)
|
|
25
26
|
throw new Error(`Failed to compare ${result.failed.length} image pair(s): ${result.failed.map((f) => `${f.file}: ${f.error}`).join('; ')}`);
|
|
26
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAExE,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,kEAAkE;IAC5E,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC;SACnF,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,oCAAoC,EAAE,CAAC;IAC1G,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,iBAAiB,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAExE,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,kEAAkE;IAC5E,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC;SACnF,MAAM,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,uDAAuD,EAAE,CAAC;SAC5G,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,oCAAoC,EAAE,CAAC;IAC1G,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,iBAAiB,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAC3E,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM;gBACtB,MAAM,IAAI,KAAK,CACb,qBAAqB,MAAM,CAAC,MAAM,CAAC,MAAM,mBAAmB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3H,CAAC;QACN,CAAC;QACD,MAAM,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,EAAE;YAC5B,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;SAChG,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;IAC7C,CAAC;CACF,CAAC,CAAC"}
|
package/dist/commands/dev.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
export declare const command: import("yargs-file-commands").DefineCommandResult<{}, {
|
|
2
2
|
root: string;
|
|
3
3
|
} & {
|
|
4
|
-
port: number;
|
|
4
|
+
port: number | undefined;
|
|
5
5
|
} & {
|
|
6
6
|
host: string;
|
|
7
|
+
} & {
|
|
8
|
+
concurrency: number | undefined;
|
|
9
|
+
} & {
|
|
10
|
+
quiet: boolean;
|
|
7
11
|
} & {
|
|
8
12
|
process: boolean;
|
|
13
|
+
} & {
|
|
14
|
+
watch: boolean;
|
|
9
15
|
}>;
|
|
10
16
|
//# sourceMappingURL=dev.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,OAAO;;;;;;;;;;;;;;EAqBlB,CAAC"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -9,9 +9,16 @@ export const command = defineCommand({
|
|
|
9
9
|
demandOption: true,
|
|
10
10
|
describe: 'Suite results directory (contains fidelity.json)',
|
|
11
11
|
})
|
|
12
|
-
.option('port', { type: 'number',
|
|
12
|
+
.option('port', { type: 'number', describe: 'Port to listen on (default: first open port from 3000)' })
|
|
13
13
|
.option('host', { type: 'string', default: 'localhost', describe: 'Interface to bind (0.0.0.0 for all)' })
|
|
14
|
-
.option('
|
|
14
|
+
.option('concurrency', { type: 'number', describe: 'Image pairs compared in parallel (default: CPU count)' })
|
|
15
|
+
.option('quiet', { type: 'boolean', default: false, describe: 'Suppress progress and summary output' })
|
|
16
|
+
.option('process', { type: 'boolean', default: true, describe: 'Refresh stale metrics/deltas before serving' })
|
|
17
|
+
.option('watch', {
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
default: true,
|
|
20
|
+
describe: 'Keep metrics, deltas, and index updated as results change',
|
|
21
|
+
}),
|
|
15
22
|
handler: (argv) => run(argv, true),
|
|
16
23
|
});
|
|
17
24
|
//# sourceMappingURL=dev.js.map
|
package/dist/commands/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,kGAAkG;IAC5G,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,kGAAkG;IAC5G,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,wDAAwD,EAAE,CAAC;SACtG,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,qCAAqC,EAAE,CAAC;SACzG,MAAM,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,uDAAuD,EAAE,CAAC;SAC5G,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,sCAAsC,EAAE,CAAC;SACtG,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,6CAA6C,EAAE,CAAC;SAC9G,MAAM,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,2DAA2D;KACtE,CAAC;IACN,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC;CACnC,CAAC,CAAC"}
|
package/dist/commands/hash.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/commands/hash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/commands/hash.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,OAAO;;;;;;EAuBlB,CAAC"}
|
package/dist/commands/hash.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { availableParallelism } from 'node:os';
|
|
2
2
|
import { defineCommand } from 'yargs-file-commands';
|
|
3
3
|
import { hashSuite } from '../core/index.js';
|
|
4
|
+
import { createProgress } from '../progress.js';
|
|
4
5
|
export const command = defineCommand({
|
|
5
6
|
command: 'hash <root>',
|
|
6
7
|
describe: 'Write image-hashes.json so `serve` can use immutable, content-hashed image URLs from the first request',
|
|
@@ -14,10 +15,13 @@ export const command = defineCommand({
|
|
|
14
15
|
type: 'number',
|
|
15
16
|
default: availableParallelism(),
|
|
16
17
|
describe: 'Files hashed in parallel (default: os.availableParallelism())',
|
|
17
|
-
})
|
|
18
|
+
})
|
|
19
|
+
.option('quiet', { type: 'boolean', default: false, describe: 'Suppress progress and summary output' }),
|
|
18
20
|
handler: async (argv) => {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
+
const progress = createProgress('hash', argv.quiet);
|
|
22
|
+
const r = await hashSuite(argv.root, { concurrency: argv.concurrency, onProgress: progress.update }).finally(progress.finish);
|
|
23
|
+
if (!argv.quiet)
|
|
24
|
+
console.log(`${r.hashed} hashed, ${r.reused} reused, ${r.total} total`);
|
|
21
25
|
},
|
|
22
26
|
});
|
|
23
27
|
//# sourceMappingURL=hash.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/commands/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/commands/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,aAAa;IACtB,QAAQ,EAAE,wGAAwG;IAClH,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,aAAa,EAAE;QACrB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,oBAAoB,EAAE;QAC/B,QAAQ,EAAE,+DAA+D;KAC1E,CAAC;SACD,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,sCAAsC,EAAE,CAAC;IAC3G,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAC1G,QAAQ,CAAC,MAAM,CAChB,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,YAAY,CAAC,CAAC,MAAM,YAAY,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IAC3F,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export declare const command: import("yargs-file-commands").DefineCommandResult<{}, {
|
|
2
2
|
root: string;
|
|
3
|
+
} & {
|
|
4
|
+
concurrency: number | undefined;
|
|
5
|
+
} & {
|
|
6
|
+
quiet: boolean;
|
|
3
7
|
} & {
|
|
4
8
|
force: boolean;
|
|
9
|
+
} & {
|
|
10
|
+
watch: boolean;
|
|
5
11
|
}>;
|
|
6
12
|
//# sourceMappingURL=process.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/commands/process.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/commands/process.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,OAAO;;;;;;;;;;EAkClB,CAAC"}
|
package/dist/commands/process.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { processSuite } from '../core/index.js';
|
|
2
2
|
import { defineCommand } from 'yargs-file-commands';
|
|
3
|
+
import { watchResults } from '../watch.js';
|
|
4
|
+
import { createProgress } from '../progress.js';
|
|
5
|
+
function report(r, quiet) {
|
|
6
|
+
if (!quiet)
|
|
7
|
+
console.log(`${r.computed} computed, ${r.skipped} up to date, ${r.failed.length} failed`);
|
|
8
|
+
for (const f of r.failed)
|
|
9
|
+
console.error(`FAILED ${f.file}: ${f.error}`);
|
|
10
|
+
if (r.failed.length)
|
|
11
|
+
process.exitCode = 1;
|
|
12
|
+
}
|
|
3
13
|
export const command = defineCommand({
|
|
4
14
|
command: 'process <root>',
|
|
5
15
|
describe: 'Compute metrics + delta images for stale pairs and write index.json',
|
|
@@ -9,14 +19,32 @@ export const command = defineCommand({
|
|
|
9
19
|
demandOption: true,
|
|
10
20
|
describe: 'Suite results directory (contains fidelity.json)',
|
|
11
21
|
})
|
|
12
|
-
.option('
|
|
22
|
+
.option('concurrency', { type: 'number', describe: 'Image pairs compared in parallel (default: CPU count)' })
|
|
23
|
+
.option('quiet', { type: 'boolean', default: false, describe: 'Suppress progress and summary output' })
|
|
24
|
+
.option('force', { type: 'boolean', default: false, describe: 'Recompute even when up to date' })
|
|
25
|
+
.option('watch', {
|
|
26
|
+
type: 'boolean',
|
|
27
|
+
default: false,
|
|
28
|
+
describe: 'Keep metrics, deltas, and index updated as results change',
|
|
29
|
+
}),
|
|
13
30
|
handler: async (argv) => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
31
|
+
const progress = createProgress('process', argv.quiet);
|
|
32
|
+
const options = {
|
|
33
|
+
force: argv.force,
|
|
34
|
+
concurrency: argv.concurrency,
|
|
35
|
+
onProgress: progress.update,
|
|
36
|
+
};
|
|
37
|
+
const onResult = (result) => {
|
|
38
|
+
progress.finish();
|
|
39
|
+
report(result, argv.quiet);
|
|
40
|
+
};
|
|
41
|
+
if (argv.watch) {
|
|
42
|
+
await watchResults(argv.root, onResult, options);
|
|
43
|
+
if (!argv.quiet)
|
|
44
|
+
console.log(`Watching ${argv.root}`);
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
onResult(await processSuite(argv.root, options).finally(progress.finish));
|
|
20
48
|
},
|
|
21
49
|
});
|
|
22
50
|
//# sourceMappingURL=process.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/commands/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/commands/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,SAAS,MAAM,CAAC,CAAgB,EAAE,KAAc;IAC9C,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,cAAc,CAAC,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;IACtG,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACxE,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,qEAAqE;IAC/E,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,uDAAuD,EAAE,CAAC;SAC5G,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,sCAAsC,EAAE,CAAC;SACtG,MAAM,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,gCAAgC,EAAE,CAAC;SAChG,MAAM,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,2DAA2D;KACtE,CAAC;IACN,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG;YACd,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,QAAQ,CAAC,MAAM;SAC5B,CAAC;QACF,MAAM,QAAQ,GAAG,CAAC,MAAqB,EAAE,EAAE;YACzC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YACjD,IAAI,CAAC,IAAI,CAAC,KAAK;gBAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;;YAAM,QAAQ,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACnF,CAAC;CACF,CAAC,CAAC"}
|
package/dist/commands/serve.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
export declare const command: import("yargs-file-commands").DefineCommandResult<{}, {
|
|
2
2
|
root: string;
|
|
3
3
|
} & {
|
|
4
|
-
port: number;
|
|
4
|
+
port: number | undefined;
|
|
5
5
|
} & {
|
|
6
6
|
host: string;
|
|
7
7
|
} & {
|
|
8
8
|
"max-age": number;
|
|
9
9
|
} & {
|
|
10
10
|
"stale-while-revalidate": number;
|
|
11
|
+
} & {
|
|
12
|
+
concurrency: number | undefined;
|
|
11
13
|
} & {
|
|
12
14
|
process: boolean;
|
|
13
15
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO;;;;;;;;;;;;;;EAyBlB,CAAC"}
|
package/dist/commands/serve.js
CHANGED
|
@@ -10,7 +10,7 @@ export const command = defineCommand({
|
|
|
10
10
|
demandOption: true,
|
|
11
11
|
describe: 'Suite results directory (contains fidelity.json)',
|
|
12
12
|
})
|
|
13
|
-
.option('port', { type: 'number',
|
|
13
|
+
.option('port', { type: 'number', describe: 'Port to listen on (default: first open port from 3000)' })
|
|
14
14
|
.option('host', { type: 'string', default: 'localhost', describe: 'Interface to bind (0.0.0.0 for all)' })
|
|
15
15
|
.option('max-age', {
|
|
16
16
|
type: 'number',
|
|
@@ -22,6 +22,7 @@ export const command = defineCommand({
|
|
|
22
22
|
default: defaultCachePolicy.staleWhileRevalidate,
|
|
23
23
|
describe: 'Seconds a stale image may be served while it refreshes in the background',
|
|
24
24
|
})
|
|
25
|
+
.option('concurrency', { type: 'number', describe: 'Image pairs compared in parallel (default: CPU count)' })
|
|
25
26
|
.option('process', { type: 'boolean', default: true, describe: 'Refresh stale metrics/deltas before serving' }),
|
|
26
27
|
handler: (argv) => run(argv, false),
|
|
27
28
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,gFAAgF;IAC1F,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;IACnC,OAAO,EAAE,cAAc;IACvB,QAAQ,EAAE,gFAAgF;IAC1F,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;SACD,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,wDAAwD,EAAE,CAAC;SACtG,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,qCAAqC,EAAE,CAAC;SACzG,MAAM,CAAC,SAAS,EAAE;QACjB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,kBAAkB,CAAC,MAAM;QAClC,QAAQ,EAAE,oEAAoE;KAC/E,CAAC;SACD,MAAM,CAAC,wBAAwB,EAAE;QAChC,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,kBAAkB,CAAC,oBAAoB;QAChD,QAAQ,EAAE,0EAA0E;KACrF,CAAC;SACD,MAAM,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,uDAAuD,EAAE,CAAC;SAC5G,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,6CAA6C,EAAE,CAAC;IACnH,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC;CACpC,CAAC,CAAC"}
|
package/dist/core/compare.d.ts
CHANGED
|
@@ -22,8 +22,10 @@ export declare function compareRgb(reference: RawImage, test: RawImage): {
|
|
|
22
22
|
metrics: ImageMetrics;
|
|
23
23
|
delta: RawImage;
|
|
24
24
|
};
|
|
25
|
-
/** Compares two encoded images (paths or buffers); returns metrics and the delta encoded like the renders. */
|
|
26
|
-
export declare function compareImages(reference: string | Buffer, test: string | Buffer
|
|
25
|
+
/** Compares two encoded images (paths or buffers); returns metrics and the delta encoded like the renders (an empty buffer when disabled). */
|
|
26
|
+
export declare function compareImages(reference: string | Buffer, test: string | Buffer, options?: {
|
|
27
|
+
delta?: boolean;
|
|
28
|
+
}): Promise<{
|
|
27
29
|
metrics: ImageMetrics;
|
|
28
30
|
width: number;
|
|
29
31
|
height: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/core/compare.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kIAAkI;AAClI,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gJAAgJ;AAChJ,eAAO,MAAM,WAAW;aAAK,OAAO,EAAE,EAAE;aAAE,iBAAiB,EAAE,OAAO;CAAW,CAAC;AAEhF,8EAA8E;AAC9E,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOvE;AA0BD,2GAA2G;AAC3G,wBAAgB,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAmC1G;AAED,
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/core/compare.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kIAAkI;AAClI,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gJAAgJ;AAChJ,eAAO,MAAM,WAAW;aAAK,OAAO,EAAE,EAAE;aAAE,iBAAiB,EAAE,OAAO;CAAW,CAAC;AAEhF,8EAA8E;AAC9E,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOvE;AA0BD,2GAA2G;AAC3G,wBAAgB,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAmC1G;AAED,8IAA8I;AAC9I,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAChC,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAUvF"}
|
package/dist/core/compare.js
CHANGED
|
@@ -69,13 +69,15 @@ export function compareRgb(reference, test) {
|
|
|
69
69
|
delta: { data: delta, width: reference.width, height: reference.height },
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
-
/** Compares two encoded images (paths or buffers); returns metrics and the delta encoded like the renders. */
|
|
73
|
-
export async function compareImages(reference, test) {
|
|
72
|
+
/** Compares two encoded images (paths or buffers); returns metrics and the delta encoded like the renders (an empty buffer when disabled). */
|
|
73
|
+
export async function compareImages(reference, test, options = {}) {
|
|
74
74
|
const [ref, tst] = await Promise.all([readRgb(reference), readRgb(test)]);
|
|
75
75
|
const { metrics, delta } = compareRgb(ref, tst);
|
|
76
|
-
const deltaImage =
|
|
77
|
-
.
|
|
78
|
-
.
|
|
76
|
+
const deltaImage = options.delta === false
|
|
77
|
+
? Buffer.alloc(0)
|
|
78
|
+
: await sharp(delta.data, { raw: { width: delta.width, height: delta.height, channels: 3 } })
|
|
79
|
+
.avif(RESULT_AVIF)
|
|
80
|
+
.toBuffer();
|
|
79
81
|
return { metrics, width: ref.width, height: ref.height, deltaImage };
|
|
80
82
|
}
|
|
81
83
|
//# sourceMappingURL=compare.js.map
|
package/dist/core/compare.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/core/compare.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/core/compare.ts"],"names":[],"mappings":"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"}
|
package/dist/core/hash.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProgressCallback } from './progress.js';
|
|
1
2
|
export declare const HASHES_FILE = "image-hashes.json";
|
|
2
3
|
export interface HashEntry {
|
|
3
4
|
hash: string;
|
|
@@ -16,6 +17,7 @@ export interface HashSuiteOptions {
|
|
|
16
17
|
concurrency?: number;
|
|
17
18
|
/** Injectable for tests. */
|
|
18
19
|
hash?: (path: string) => Promise<string>;
|
|
20
|
+
onProgress?: ProgressCallback;
|
|
19
21
|
}
|
|
20
22
|
export interface HashSuiteResult {
|
|
21
23
|
hashed: number;
|
package/dist/core/hash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAE/C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5D;AAED,gHAAgH;AAChH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAMnF;AAED,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AACD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoDnG"}
|
package/dist/core/hash.js
CHANGED
|
@@ -42,24 +42,51 @@ export async function hashSuite(root, opts = {}) {
|
|
|
42
42
|
const { concurrency = availableParallelism(), hash = hashFile } = opts;
|
|
43
43
|
const limit = pLimit(Math.max(1, Math.floor(concurrency)));
|
|
44
44
|
const previous = await readHashFile(root);
|
|
45
|
-
const rels =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
const rels = [];
|
|
46
|
+
const pending = [''];
|
|
47
|
+
let scanned = 0;
|
|
48
|
+
const scanProgress = () => opts.onProgress?.({ phase: 'Scanning', completed: scanned, total: scanned + pending.length, unit: 'directories' });
|
|
49
|
+
scanProgress();
|
|
50
|
+
while (pending.length) {
|
|
51
|
+
const dir = pending.pop();
|
|
52
|
+
for (const entry of await readdir(join(root, dir), { withFileTypes: true })) {
|
|
53
|
+
const rel = dir ? `${dir}/${entry.name}` : entry.name;
|
|
54
|
+
if (entry.name.startsWith('.'))
|
|
55
|
+
continue;
|
|
56
|
+
if (entry.isDirectory())
|
|
57
|
+
pending.push(rel);
|
|
58
|
+
else if (entry.isFile() && rel.endsWith('.avif') && isDataFile(rel))
|
|
59
|
+
rels.push(rel);
|
|
60
|
+
}
|
|
61
|
+
scanned++;
|
|
62
|
+
scanProgress();
|
|
63
|
+
}
|
|
64
|
+
rels.sort();
|
|
49
65
|
let reused = 0;
|
|
66
|
+
let completed = 0;
|
|
67
|
+
const hashProgress = () => opts.onProgress?.({ phase: 'Hashing', completed, total: rels.length, unit: 'images' });
|
|
68
|
+
hashProgress();
|
|
50
69
|
const entries = await Promise.all(rels.map((rel) => limit(async () => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
try {
|
|
71
|
+
const s = await stat(join(root, rel));
|
|
72
|
+
const old = previous[rel];
|
|
73
|
+
if (old && old.size === s.size && old.mtimeMs === s.mtimeMs) {
|
|
74
|
+
reused++;
|
|
75
|
+
return [rel, old];
|
|
76
|
+
}
|
|
77
|
+
return [rel, { hash: await hash(join(root, rel)), size: s.size, mtimeMs: s.mtimeMs }];
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
completed++;
|
|
81
|
+
hashProgress();
|
|
56
82
|
}
|
|
57
|
-
return [rel, { hash: await hash(join(root, rel)), size: s.size, mtimeMs: s.mtimeMs }];
|
|
58
83
|
})));
|
|
59
84
|
const out = join(root, HASHES_FILE);
|
|
85
|
+
opts.onProgress?.({ phase: 'Writing hashes', completed: 0, total: 1, unit: 'files' });
|
|
60
86
|
const tmp = `${out}.${process.pid}.tmp`;
|
|
61
87
|
await writeFile(tmp, `${JSON.stringify({ version: 1, files: Object.fromEntries(entries) }, null, 2)}\n`);
|
|
62
88
|
await rename(tmp, out);
|
|
89
|
+
opts.onProgress?.({ phase: 'Writing hashes', completed: 1, total: 1, unit: 'files' });
|
|
63
90
|
return { hashed: entries.length - reused, reused, total: entries.length };
|
|
64
91
|
}
|
|
65
92
|
//# sourceMappingURL=hash.js.map
|
package/dist/core/hash.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"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"}
|
package/dist/core/hash.test.js
CHANGED
|
@@ -22,7 +22,14 @@ async function suite() {
|
|
|
22
22
|
const read = async (root) => JSON.parse(await readFile(join(root, HASHES_FILE), 'utf8'));
|
|
23
23
|
test('hash is deterministic, sorted, covers only served images, and is incremental', async () => {
|
|
24
24
|
const root = await suite();
|
|
25
|
-
|
|
25
|
+
const progress = [];
|
|
26
|
+
expect(await hashSuite(root, { onProgress: (update) => progress.push(update) })).toEqual({
|
|
27
|
+
hashed: 3,
|
|
28
|
+
reused: 0,
|
|
29
|
+
total: 3,
|
|
30
|
+
});
|
|
31
|
+
expect(progress.at(-1)).toEqual({ phase: 'Writing hashes', completed: 1, total: 1, unit: 'files' });
|
|
32
|
+
expect(progress.find((update) => update.phase === 'Hashing' && update.completed === 3)).toBeDefined();
|
|
26
33
|
const first = await readFile(join(root, HASHES_FILE), 'utf8');
|
|
27
34
|
const json = JSON.parse(first);
|
|
28
35
|
expect(json.version).toBe(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.test.js","sourceRoot":"","sources":["../../src/core/hash.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"hash.test.js","sourceRoot":"","sources":["../../src/core/hash.test.ts"],"names":[],"mappings":"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"}
|