supercov 0.0.2 → 0.0.4

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 (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +159 -30
  3. package/bin/supercov.js +10 -0
  4. package/dist/atomic.d.ts +6 -0
  5. package/dist/atomic.d.ts.map +1 -0
  6. package/dist/atomic.js +47 -0
  7. package/dist/atomic.js.map +1 -0
  8. package/dist/buildCache.d.ts +14 -0
  9. package/dist/buildCache.d.ts.map +1 -0
  10. package/dist/buildCache.js +84 -0
  11. package/dist/buildCache.js.map +1 -0
  12. package/dist/cli.js +536 -215
  13. package/dist/cli.js.map +1 -1
  14. package/dist/directInstrumenter.d.ts +8 -0
  15. package/dist/directInstrumenter.d.ts.map +1 -0
  16. package/dist/directInstrumenter.js +70 -0
  17. package/dist/directInstrumenter.js.map +1 -0
  18. package/dist/evidenceArchive.d.ts +35 -0
  19. package/dist/evidenceArchive.d.ts.map +1 -0
  20. package/dist/evidenceArchive.js +101 -0
  21. package/dist/evidenceArchive.js.map +1 -0
  22. package/dist/instrumenter.d.ts.map +1 -1
  23. package/dist/instrumenter.js +251 -41
  24. package/dist/instrumenter.js.map +1 -1
  25. package/dist/integrity.d.ts.map +1 -1
  26. package/dist/integrity.js +27 -0
  27. package/dist/integrity.js.map +1 -1
  28. package/dist/launchSupervisor.d.ts +24 -0
  29. package/dist/launchSupervisor.d.ts.map +1 -0
  30. package/dist/launchSupervisor.js +397 -0
  31. package/dist/launchSupervisor.js.map +1 -0
  32. package/dist/playwright.d.ts +0 -4
  33. package/dist/playwright.d.ts.map +1 -1
  34. package/dist/playwright.js +33 -17
  35. package/dist/playwright.js.map +1 -1
  36. package/dist/playwrightReporter.d.ts.map +1 -1
  37. package/dist/playwrightReporter.js +3 -2
  38. package/dist/playwrightReporter.js.map +1 -1
  39. package/dist/project.d.ts +5 -2
  40. package/dist/project.d.ts.map +1 -1
  41. package/dist/project.js +192 -27
  42. package/dist/project.js.map +1 -1
  43. package/dist/query.d.ts.map +1 -1
  44. package/dist/query.js +29 -21
  45. package/dist/query.js.map +1 -1
  46. package/dist/register.mjs +18 -13
  47. package/dist/register.mjs.map +1 -1
  48. package/dist/reporter.d.ts +6 -10
  49. package/dist/reporter.d.ts.map +1 -1
  50. package/dist/reporter.js +23 -82
  51. package/dist/reporter.js.map +1 -1
  52. package/dist/resolve-loader.d.mts.map +1 -1
  53. package/dist/resolve-loader.mjs +11 -3
  54. package/dist/resolve-loader.mjs.map +1 -1
  55. package/dist/runAnalysis.d.ts +19 -0
  56. package/dist/runAnalysis.d.ts.map +1 -0
  57. package/dist/runAnalysis.js +112 -0
  58. package/dist/runAnalysis.js.map +1 -0
  59. package/dist/runtime.d.ts +2 -2
  60. package/dist/runtime.d.ts.map +1 -1
  61. package/dist/runtime.js +35 -7
  62. package/dist/runtime.js.map +1 -1
  63. package/dist/transport.d.ts +2 -0
  64. package/dist/transport.d.ts.map +1 -1
  65. package/dist/transport.js +13 -5
  66. package/dist/transport.js.map +1 -1
  67. package/dist/types.d.ts +2 -1
  68. package/dist/types.d.ts.map +1 -1
  69. package/dist/vitePlugin.d.ts +1 -0
  70. package/dist/vitePlugin.d.ts.map +1 -1
  71. package/dist/vitePlugin.js +35 -3
  72. package/dist/vitePlugin.js.map +1 -1
  73. package/dist/vitest.js +3 -2
  74. package/dist/vitest.js.map +1 -1
  75. package/dist/vitestReporter.d.ts +17 -2
  76. package/dist/vitestReporter.d.ts.map +1 -1
  77. package/dist/vitestReporter.js +51 -2
  78. package/dist/vitestReporter.js.map +1 -1
  79. package/dist/workspace.d.ts +81 -0
  80. package/dist/workspace.d.ts.map +1 -0
  81. package/dist/workspace.js +501 -0
  82. package/dist/workspace.js.map +1 -0
  83. package/docs/performance.md +107 -0
  84. package/docs/workspace-isolation.md +118 -0
  85. package/package.json +21 -5
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Supercov contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -18,32 +18,64 @@ npm link
18
18
 
19
19
  ## Verifying the instrumenter
20
20
 
21
- The coverage engine has three independent test layers:
21
+ The coverage engine has seven independent release gates:
22
22
 
23
23
  - semantic differential fixtures execute original and instrumented programs
24
24
  in isolated scopes and compare return values, thrown errors, and observable
25
25
  side-effect order;
26
26
  - a deterministic generated corpus exercises 160 nested combinations of
27
27
  short-circuiting, ternaries, coercion, and thrown expressions on every run;
28
+ - seeded `fast-check` properties exercise another 500 generated nested
29
+ expressions and 300 generated control-flow executions, with shrinking and a
30
+ reproducible seed on failure;
28
31
  - coverage oracles assert exact decision vectors, MC/DC witnesses, and branch
29
- alternatives independently of program behavior.
32
+ alternatives independently of program behavior;
33
+ - the same three-condition masking-MC/DC golden cases must report 100% for a
34
+ complete witness set and 33.33% for an incomplete one under both Supercov
35
+ and Clang/LLVM source-based MC/DC;
36
+ - release CI shards the pinned TC39 Test262 corpus across 16 workers, runs the
37
+ official Test262 harness on original and instrumented sources, and rejects
38
+ any scenario that passes originally but fails after transformation; and
39
+ - checked performance budgets cover transform latency, transactional workspace
40
+ preparation, output expansion, and runtime probe overhead.
30
41
 
31
42
  ```sh
32
43
  npm test
44
+ npm run test:clang-mcdc
45
+ npm run benchmark:check
46
+ TEST262_DIR=/path/to/test262 npm run test:test262
33
47
  ```
34
48
 
35
49
  The differential suite includes getters, proxies, optional calls and `this`,
36
50
  computed logical assignments, defaults, `try`/`catch`/`finally`, iterator
37
51
  closing, switch fallthrough, labeled loops, async functions, and generators.
38
- Every generated failure prints its reproducible seed and expression.
52
+ The compatibility workflow additionally runs Node 22/24/25, Playwright
53
+ 1.55/current, Vite 5/current, Vitest 2/current, Chromium, Firefox, WebKit, and
54
+ modern JavaScript/JSX/TypeScript/TSX syntax fixtures. Filesystem publication,
55
+ symlink, copy fallback, ENOSPC, failed rename, and forced-termination recovery
56
+ also run on Ubuntu, macOS, and Windows. Test262's module, async,
57
+ raw, parse/resolution-negative, Annex B sloppy-script extension, and explicit
58
+ `Function.prototype.toString`/function-source-coercion tests are intentionally
59
+ excluded from the source-rewrite comparison, with reason counts printed for
60
+ every shard. Annex B does not apply to the Vite application modules Supercov
61
+ instruments; exact source reflection necessarily observes a source transform.
62
+ When application code directly coerces or observes a function's source,
63
+ Supercov leaves that function body uninstrumented and records a visible
64
+ `semantic-safety` completeness blocker. The release corpus covers every other eligible synchronous
65
+ script and runtime-negative scenario, while dedicated differential fixtures
66
+ cover async functions and generators. Every semantic-equivalence failure
67
+ blocks the trusted-publishing workflow.
39
68
 
40
69
  ## Agent query workflow
41
70
 
42
- Each run is stored locally as a compressed, immutable report under
43
- `.supercov/runs/<run-id>/`. Its `report.json.gz`, `run.json`, and
44
- `report.html` keep the machine report, run metadata, and human report together.
45
- Agents should use bounded CLI queries instead of loading the complete report
46
- into context.
71
+ Each run is stored locally as two immutable files under
72
+ `.supercov/runs/<run-id>/`: `evidence.raw.gz` and `run.json`. The archive
73
+ contains the exact coverage denominator manifest plus raw per-worker and
74
+ background evidence. Every query reconstructs its requested coverage view
75
+ directly from that archive; no derived report or query cache is retained.
76
+ Loose evidence is removed only after the whole run directory is atomically
77
+ visible. HTML is not generated during a test run; agents should use bounded
78
+ CLI queries instead of loading the complete derived model into context.
47
79
 
48
80
  ```sh
49
81
  # Orient using only a few lines.
@@ -75,8 +107,8 @@ Use `--filter passed` for verified coverage from successful attempts of
75
107
  ultimately passing tests, or `--filter failed` to inspect only execution from
76
108
  failed attempts (including failed retries of flaky tests). Reports record
77
109
  attempt status and classify each test as passed, failed, flaky, skipped, timed
78
- out, interrupted, or unknown. The HTML equivalents are `report.html`,
79
- `report-passed.html`, and `report-failed.html`.
110
+ out, interrupted, or unknown. The passed and failed subsets are stored inside
111
+ the same compressed report rather than duplicated into presentation files.
80
112
 
81
113
  The run ID is positional because all coverage queries operate on one immutable
82
114
  run. `latest` is a convenience selector for interactive use. Every query
@@ -87,31 +119,128 @@ Text output is concise for an interactive agent; JSON is the stable machine
87
119
  interface that can later back hosted coverage tools without changing the
88
120
  stored schema.
89
121
 
90
- For a conventional Vite project, the CLI:
91
-
92
- 1. creates ignored Vite, Vitest, and Playwright overlays under
93
- `.supercov/`;
122
+ For a conventional Vite project, or a Node project with no build step, the
123
+ CLI:
124
+
125
+ 1. refreshes a stable isolated source namespace under
126
+ `.supercov/cache/instrumented-workspace/<project>/`, links the existing
127
+ dependency tree, and creates all Vite, Vitest, Playwright, and build output
128
+ only there; file data uses copy-on-write reflinks where the filesystem
129
+ supports them, and falls back to copying where it does not; the stable path
130
+ lets VM/container snapshot systems reuse a coverage build without touching
131
+ the application's ordinary build; when the complete source/config/toolchain
132
+ fingerprint is unchanged, the prior instrumented output and manifest are
133
+ carried into the refreshed source snapshot and the build is skipped;
94
134
  2. inventories every `app/**/*.ts(x)` and `src/**/*.ts(x)` file for the
95
- denominator, then
96
- instruments modules loaded by Vite without changing the project's config;
97
- 3. redirects existing `@playwright/test` imports at module-load time and injects
98
- a Vitest setup through the child runner's generated config, without changing
99
- specs, imports, package scripts, or checked-in configs;
100
- 4. runs the exact command following `--`;
135
+ denominator, then instruments modules loaded by Vite without changing the
136
+ project's config; when no build script exists, it instruments only the
137
+ disposable source copy and supplies a module-format-neutral runtime through
138
+ the inherited Node preload;
139
+ 3. discovers the Playwright-compatible fixture provider, test export, and
140
+ additional named exports from the suite's existing imports, then redirects
141
+ that provider at module-load time; Vitest setup is injected through the
142
+ child runner's generated config;
143
+ 4. runs the exact command following `--`, propagating coverage through every
144
+ Node child process it launches;
101
145
  5. attributes every source hit and decision vector to its individual test,
102
146
  automatically wraps Playwright actions and assertions, and records the
103
147
  action/assertion phase responsible for each correlated hit; then merges
104
- server and browser evidence into HTML and JSON reports; and
105
- 6. restores an ordinary application build even after a failed test command.
148
+ server and browser evidence into one compressed JSON report; and
149
+ 6. atomically publishes the compressed evidence/report into `.supercov/`, then
150
+ removes loose evidence and terminal per-run work state, retaining only the
151
+ immutable run and disposable isolated build namespace. The
152
+ ordinary application build is never read as an input, overwritten, or
153
+ rebuilt afterward.
154
+
155
+ Only `.supercov/` is modified in the user's checkout. A per-project lock
156
+ rejects overlapping runs before either can build. Run state is durably written
157
+ through preparing/building/testing/reporting phases; SIGINT, SIGTERM,
158
+ and SIGHUP are forwarded to the entire child process group. If the process is
159
+ killed without a cleanup opportunity, the next invocation marks the dead PID's
160
+ run abandoned and refreshes the isolated namespace before using it. Cache
161
+ refresh is transactional: a new sibling generation is prepared completely,
162
+ the stable name is switched only at publication, and the prior complete
163
+ generation is retained until that switch succeeds. The next invocation
164
+ discards orphan staging trees or restores the prior generation if a host crash
165
+ landed between the two same-filesystem renames. Report, evidence archive, and
166
+ state writes use sibling-temp files, fsync, and atomic rename; lock acquisition
167
+ uses exclusive creation and fsync. Published `run.json` is the durable terminal
168
+ record, so terminal work state is not retained.
169
+
170
+ Retention is deterministic because UTC run IDs sort chronologically:
171
+
172
+ ```sh
173
+ npx supercov prune --keep 20
174
+ npx supercov prune --keep 20 --dry-run
175
+ npx supercov clean --keep 20 # also removes the shared build cache
176
+ ```
177
+
178
+ Neither operation runs automatically. `prune` removes explicit history beyond
179
+ the requested retention and orphan/terminal transient data while preserving
180
+ the shared cache. `clean` also removes that cache. Both acquire the same lock
181
+ as a coverage run, refuse to race an active run, and never touch files outside
182
+ `.supercov/`.
183
+
184
+ The complete ownership, crash-recovery, symlink, and future copy-free design is
185
+ documented in [Workspace isolation](docs/workspace-isolation.md).
186
+
187
+ Every run prints and stores monotonic phase timings for initialization,
188
+ workspace preparation, adapter setup, the instrumented build, the unchanged
189
+ test command, and report preparation. They are available in
190
+ `.supercov/runs/<run-id>/run.json` and in the JSON form of `supercov runs`.
191
+ These phase timings do not pretend to be end-to-end overhead: that percentage
192
+ requires an explicit comparison with the same command run without Supercov,
193
+ which Supercov never executes automatically because an arbitrary test command
194
+ may have side effects or external cost. See
195
+ [Performance and storage](docs/performance.md) for the comparison methodology,
196
+ strategy trade-offs, and a measured real-suite reference.
106
197
 
107
198
  The automatic adapters currently support standard Playwright suites (ESM and
108
- CommonJS specs in arbitrary project directories), Vitest, and the Essential
109
- Apps isolated Playwright VM runner. A single command such as
110
- `supercov -- npm test` can collect Vitest and Playwright evidence into
111
- the same run. The application build must currently be Vite-based. Jest,
112
- `node:test`, non-Vite build systems, browser component runners, and distributed
113
- multi-host merging still require adapters; they are not silently reported as
114
- covered.
199
+ CommonJS specs in arbitrary project directories), project-owned Playwright
200
+ fixture packages, Vitest, no-build Node commands, and Node coordinators that
201
+ launch tests inside a mounted VM/container workspace. A single command such as
202
+ `supercov -- npm test` can collect Vitest and Playwright evidence into the same
203
+ run. No-build Node execution is retained as background/unattributed evidence
204
+ until a recognized test-runner adapter supplies exact test boundaries. Jest,
205
+ exact `node:test` attribution, non-Vite application builds, browser component
206
+ runners, and distributed multi-host merging still require adapters; they are
207
+ not silently reported as per-test coverage.
208
+
209
+ Remote execution discovery is structural rather than provider-specific. The
210
+ preload observes CommonJS exports for a static `build(options)` capability,
211
+ activates only when those options contain a host-to-guest mount that includes
212
+ the isolated project, scopes an existing cache/snapshot identity to the run's
213
+ source fingerprint, and follows the opaque returned object graph. A method
214
+ whose options contain `argv`, `cmd`, or `command` receives guest-translated
215
+ Supercov paths and a guest-valid Node preload. The execution log records this
216
+ process/capability graph but hashes long or multiline arguments so embedded
217
+ shell bodies and credentials are never persisted.
218
+
219
+ This first zero-edit mechanism has explicit boundaries. It follows Node child
220
+ processes, not arbitrary non-Node supervisors or a remote control plane that
221
+ never exposes launches to the local process. The remote SDK must currently be
222
+ visible through CommonJS loading, its build options must expose the workspace
223
+ mount, and its execution call must accept an environment. Pure-ESM executor
224
+ SDKs, positional-only remote exec APIs, and providers that hide all launch
225
+ state behind an RPC need additional interception layers. Supercov reports
226
+ missing evidence rather than claiming those paths are covered.
227
+
228
+ The public regression suite includes a provider-neutral opaque executor. Its
229
+ CommonJS SDK exposes only a static build capability, a host-to-guest mount,
230
+ an existing snapshot key, an opaque image/pool/machine chain, and an
231
+ argv-shaped execution method. CI requires Supercov to discover that structure,
232
+ scope the cache identity, translate paths and the Node preload into the guest,
233
+ run nested Vitest and Playwright commands, parse every concurrent trace shard,
234
+ and produce 100% fixture coverage. A separate clean-room gate packs the npm
235
+ tarball and invokes it through `npx` in a project with no build step, asserting
236
+ that no source or configuration file changes.
237
+
238
+ Before the isolated build, Supercov also compares the invoked npm/pnpm/yarn/bun
239
+ script with explicit string-valued `process.env` mode checks in the project's
240
+ build config. A semantic match such as `test:preview` and
241
+ `process.env.TEST_PREVIEW === "true"` activates that build-only flag and is
242
+ printed before the build. It never guesses values for unrelated environment
243
+ variables.
115
244
 
116
245
  Each test carries two independent provenance fields:
117
246
 
@@ -147,7 +276,7 @@ phase travels on browser requests into automatically wrapped Remix loaders,
147
276
  actions, and the server document renderer. Node async context preserves that
148
277
  ID through awaited helpers. An assertion also retains the preceding action ID,
149
278
  making chains such as “click -> application lines/decisions -> visible
150
- assertion” queryable in JSON and visible in HTML.
279
+ assertion” queryable in JSON.
151
280
 
152
281
  Server evidence is safe when Playwright uses multiple workers against one
153
282
  application server. Every routed request carries a run/worker/test/retry scope;
package/bin/supercov.js CHANGED
@@ -13,6 +13,16 @@ const child = spawn(
13
13
  },
14
14
  );
15
15
 
16
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
17
+ process.once(signal, () => {
18
+ try {
19
+ child.kill(signal);
20
+ } catch {
21
+ // The child may already have completed.
22
+ }
23
+ });
24
+ }
25
+
16
26
  child.on("error", (error) => {
17
27
  console.error("[supercov] failed to start", error);
18
28
  process.exitCode = 1;
@@ -0,0 +1,6 @@
1
+ import { type WriteFileOptions } from "node:fs";
2
+ /** Write a complete sibling file and atomically replace the destination. */
3
+ export declare function atomicWriteFileSync(path: string, data: string | NodeJS.ArrayBufferView, options?: WriteFileOptions): void;
4
+ /** Atomically publish a fully prepared file or directory and persist its entry. */
5
+ export declare function atomicRenameSync(source: string, destination: string): void;
6
+ //# sourceMappingURL=atomic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,gBAAgB,EACtB,MAAM,SAAS,CAAC;AAiBjB,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,eAAe,EACrC,OAAO,CAAC,EAAE,gBAAgB,GACzB,IAAI,CAmBN;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAI1E"}
package/dist/atomic.js ADDED
@@ -0,0 +1,47 @@
1
+ import { mkdirSync, openSync, closeSync, fsyncSync, renameSync, rmSync, writeFileSync, } from "node:fs";
2
+ import { randomUUID } from "node:crypto";
3
+ import { dirname } from "node:path";
4
+ function fsyncDirectory(path) {
5
+ try {
6
+ const directory = openSync(path, "r");
7
+ try {
8
+ fsyncSync(directory);
9
+ }
10
+ finally {
11
+ closeSync(directory);
12
+ }
13
+ }
14
+ catch {
15
+ // Some platforms (notably Windows) do not permit opening directories.
16
+ }
17
+ }
18
+ /** Write a complete sibling file and atomically replace the destination. */
19
+ export function atomicWriteFileSync(path, data, options) {
20
+ mkdirSync(dirname(path), { recursive: true });
21
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
22
+ let descriptor;
23
+ try {
24
+ descriptor = openSync(temporary, "wx", 0o600);
25
+ writeFileSync(descriptor, data, options);
26
+ fsyncSync(descriptor);
27
+ closeSync(descriptor);
28
+ descriptor = undefined;
29
+ renameSync(temporary, path);
30
+ // Persist the directory entry as well as the file contents on POSIX. Some
31
+ // platforms (notably Windows) do not permit opening directories, so file
32
+ // fsync + atomic rename remains the portable fallback there.
33
+ fsyncDirectory(dirname(path));
34
+ }
35
+ finally {
36
+ if (descriptor !== undefined)
37
+ closeSync(descriptor);
38
+ rmSync(temporary, { force: true });
39
+ }
40
+ }
41
+ /** Atomically publish a fully prepared file or directory and persist its entry. */
42
+ export function atomicRenameSync(source, destination) {
43
+ mkdirSync(dirname(destination), { recursive: true });
44
+ renameSync(source, destination);
45
+ fsyncDirectory(dirname(destination));
46
+ }
47
+ //# sourceMappingURL=atomic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic.js","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,UAAU,EACV,MAAM,EACN,aAAa,GAEd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,SAAS,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,SAAS,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,IAAqC,EACrC,OAA0B;IAE1B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;IAC/D,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,GAAG,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9C,aAAa,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,SAAS,CAAC,UAAU,CAAC,CAAC;QACtB,UAAU,GAAG,SAAS,CAAC;QACvB,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC5B,0EAA0E;QAC1E,yEAAyE;QACzE,6DAA6D;QAC7D,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,CAAC;YAAS,CAAC;QACT,IAAI,UAAU,KAAK,SAAS;YAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,WAAmB;IAClE,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,UAAU,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAChC,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { CoverageRunIntegrity } from "./types.ts";
2
+ import type { CoverageProject } from "./project.ts";
3
+ export declare const INSTRUMENTED_BUILD_CACHE_SCHEMA_VERSION = 1;
4
+ export interface InstrumentedBuildCache {
5
+ schemaVersion: typeof INSTRUMENTED_BUILD_CACHE_SCHEMA_VERSION;
6
+ key: string;
7
+ createdAt: string;
8
+ artifactPaths: string[];
9
+ }
10
+ export declare function instrumentedBuildCacheKey(integrity: CoverageRunIntegrity, project: CoverageProject): string;
11
+ export declare function readInstrumentedBuildCache(workspace: string, key: string): InstrumentedBuildCache | undefined;
12
+ export declare function writeInstrumentedBuildCache(workspace: string, key: string): InstrumentedBuildCache | undefined;
13
+ export declare function buildCacheReusePaths(metadata: InstrumentedBuildCache): string[];
14
+ //# sourceMappingURL=buildCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildCache.d.ts","sourceRoot":"","sources":["../src/buildCache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,eAAO,MAAM,uCAAuC,IAAI,CAAC;AAUzD,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,OAAO,uCAAuC,CAAC;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAgBD,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,oBAAoB,EAC/B,OAAO,EAAE,eAAe,GACvB,MAAM,CAeR;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,sBAAsB,GAAG,SAAS,CAqBpC;AAED,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,sBAAsB,GAAG,SAAS,CAqCpC;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,sBAAsB,GAC/B,MAAM,EAAE,CAEV"}
@@ -0,0 +1,84 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { isAbsolute, resolve, sep } from "node:path";
4
+ import { atomicWriteFileSync } from "./atomic.js";
5
+ export const INSTRUMENTED_BUILD_CACHE_SCHEMA_VERSION = 1;
6
+ const BUILD_OUTPUT_CANDIDATES = [
7
+ "build",
8
+ "dist",
9
+ ".next",
10
+ ".nuxt",
11
+ ".output",
12
+ ];
13
+ function metadataPath(workspace) {
14
+ return resolve(workspace, ".supercov/build-cache.json");
15
+ }
16
+ function safeRelativePath(path) {
17
+ return Boolean(path &&
18
+ !isAbsolute(path) &&
19
+ path !== ".." &&
20
+ !path.startsWith(`..${sep}`) &&
21
+ !path.split(/[\\/]/).includes(".."));
22
+ }
23
+ export function instrumentedBuildCacheKey(integrity, project) {
24
+ return createHash("sha256")
25
+ .update(JSON.stringify({
26
+ schemaVersion: INSTRUMENTED_BUILD_CACHE_SCHEMA_VERSION,
27
+ executionFingerprint: integrity.fingerprint.execution,
28
+ adapter: project.buildAdapter,
29
+ command: project.buildCommand,
30
+ environment: project.buildEnvironment,
31
+ node: process.versions.node,
32
+ platform: process.platform,
33
+ architecture: process.arch,
34
+ }))
35
+ .digest("hex");
36
+ }
37
+ export function readInstrumentedBuildCache(workspace, key) {
38
+ let metadata;
39
+ try {
40
+ metadata = JSON.parse(readFileSync(metadataPath(workspace), "utf8"));
41
+ }
42
+ catch {
43
+ return undefined;
44
+ }
45
+ if (metadata.schemaVersion !== INSTRUMENTED_BUILD_CACHE_SCHEMA_VERSION ||
46
+ metadata.key !== key ||
47
+ !Array.isArray(metadata.artifactPaths) ||
48
+ metadata.artifactPaths.length === 0 ||
49
+ metadata.artifactPaths.some((path) => !safeRelativePath(path) || !existsSync(resolve(workspace, path)))) {
50
+ return undefined;
51
+ }
52
+ return metadata;
53
+ }
54
+ export function writeInstrumentedBuildCache(workspace, key) {
55
+ let declared = {};
56
+ try {
57
+ declared = JSON.parse(readFileSync(resolve(workspace, ".supercov/build-outputs.json"), "utf8"));
58
+ }
59
+ catch {
60
+ // Older/native Vite integrations use the conservative known outputs.
61
+ }
62
+ const existingOutputs = [
63
+ ...new Set([
64
+ ...BUILD_OUTPUT_CANDIDATES,
65
+ ...(declared.paths ?? []).filter(safeRelativePath),
66
+ ]),
67
+ ].filter((path) => existsSync(resolve(workspace, path)));
68
+ const outputs = existingOutputs.filter((path) => !existingOutputs.some((parent) => parent !== path && path.startsWith(`${parent}/`)));
69
+ const manifest = ".supercov/manifest.json";
70
+ if (outputs.length === 0 || !existsSync(resolve(workspace, manifest)))
71
+ return undefined;
72
+ const metadata = {
73
+ schemaVersion: INSTRUMENTED_BUILD_CACHE_SCHEMA_VERSION,
74
+ key,
75
+ createdAt: new Date().toISOString(),
76
+ artifactPaths: [...outputs, manifest],
77
+ };
78
+ atomicWriteFileSync(metadataPath(workspace), `${JSON.stringify(metadata, null, 2)}\n`);
79
+ return metadata;
80
+ }
81
+ export function buildCacheReusePaths(metadata) {
82
+ return [...metadata.artifactPaths, ".supercov/build-cache.json"];
83
+ }
84
+ //# sourceMappingURL=buildCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildCache.js","sourceRoot":"","sources":["../src/buildCache.ts"],"names":[],"mappings":"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"}