@deeeed/metamask-harness 0.17.1 → 0.17.2
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 +8 -2
- package/adapters/shared/update-check-worker.mjs +37 -0
- package/dist/commands/update.js +15 -28
- package/dist/mm-harness-cli.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.17.2 - 2026-07-15
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Passive update discovery now runs in a detached, once-daily registry probe, so fast commands populate the cache without adding latency or contaminating machine output.
|
|
10
|
+
|
|
11
|
+
## 0.17.1 - 2026-07-15
|
|
12
|
+
|
|
5
13
|
### Fixed
|
|
6
14
|
|
|
7
15
|
- Extension `debug` now uses Chrome's native DevTools command for the active slot target and opens directly on Console; `debug --worker` targets the service worker without creating a frontend browser tab.
|
|
@@ -20,8 +28,6 @@
|
|
|
20
28
|
- Removed compatibility-only runtime-start fields, hidden `live` execution, removed-command handlers, undomained recipe aliases, flat/non-ESM action lookup, old port-resolver filenames, duplicate Extension launcher naming, obsolete fixture search locations, and the alternate Mobile product-source bridge. Mobile install now requires the current product-owned bridge and writes metadata only.
|
|
21
29
|
- Removed the historical CLI migration/spec documents; current behavior is documented in the README, cheatsheet, architecture, and human QA checklist.
|
|
22
30
|
|
|
23
|
-
## 0.17.1 - 2026-07-14
|
|
24
|
-
|
|
25
31
|
### Fixed
|
|
26
32
|
|
|
27
33
|
- Human recipe results now print an absolute-path artifact inventory and expand run-scoped application diagnostics inline; single-action calls show the same `CLEAN`/`REVIEW` diagnostics instead of requiring another query.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
const [cacheFile, timeoutText, endpointOverride] = process.argv.slice(2);
|
|
6
|
+
const timeoutMs = Number.parseInt(timeoutText ?? '', 10);
|
|
7
|
+
const endpoint = endpointOverride
|
|
8
|
+
?? 'https://registry.npmjs.org/-/package/%40deeeed%2Fmetamask-harness/dist-tags';
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
if (!cacheFile || !Number.isInteger(timeoutMs) || timeoutMs < 1) return;
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
14
|
+
try {
|
|
15
|
+
const response = await fetch(endpoint, { signal: controller.signal });
|
|
16
|
+
if (!response.ok) return;
|
|
17
|
+
const data = await response.json();
|
|
18
|
+
if (!data || typeof data.latest !== 'string' || data.latest.length === 0) return;
|
|
19
|
+
let lastCheck = Date.now();
|
|
20
|
+
try {
|
|
21
|
+
const cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
22
|
+
if (typeof cached.lastCheck === 'number') lastCheck = cached.lastCheck;
|
|
23
|
+
} catch {
|
|
24
|
+
// The parent may have exited before creating the cache; recreate it below.
|
|
25
|
+
}
|
|
26
|
+
fs.mkdirSync(path.dirname(cacheFile), { recursive: true });
|
|
27
|
+
const temporary = `${cacheFile}.${process.pid}.tmp`;
|
|
28
|
+
fs.writeFileSync(temporary, JSON.stringify({ lastCheck, latest: data.latest }));
|
|
29
|
+
fs.renameSync(temporary, cacheFile);
|
|
30
|
+
} catch {
|
|
31
|
+
// Passive checks are intentionally silent; the explicit update command teaches failures.
|
|
32
|
+
} finally {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
await main();
|
package/dist/commands/update.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
1
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
@@ -6,7 +6,7 @@ import { runnerDir } from "../paths.js";
|
|
|
6
6
|
import { EXIT, flag, parseFlags } from "./shared.js";
|
|
7
7
|
const PACKAGE_NAME = "@deeeed/metamask-harness";
|
|
8
8
|
const NUDGE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
9
|
-
const NUDGE_FETCH_TIMEOUT_MS =
|
|
9
|
+
const NUDGE_FETCH_TIMEOUT_MS = 2e3;
|
|
10
10
|
function currentVersion() {
|
|
11
11
|
try {
|
|
12
12
|
const pkg = JSON.parse(fs.readFileSync(path.join(runnerDir, "package.json"), "utf8"));
|
|
@@ -56,24 +56,6 @@ function fetchLatest(timeoutMs) {
|
|
|
56
56
|
if (!latest) return { error: { kind: "unreachable", message: "npm returned no dist-tag for latest" } };
|
|
57
57
|
return { latest };
|
|
58
58
|
}
|
|
59
|
-
async function fetchLatestAsync(timeoutMs) {
|
|
60
|
-
const controller = new AbortController();
|
|
61
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
62
|
-
try {
|
|
63
|
-
const url = `https://registry.npmjs.org/-/package/${encodeURIComponent(PACKAGE_NAME)}/dist-tags`;
|
|
64
|
-
const res = await fetch(url, { signal: controller.signal });
|
|
65
|
-
if (!res.ok) return { error: { kind: "unreachable", message: `registry returned HTTP ${res.status}` } };
|
|
66
|
-
const data = await res.json();
|
|
67
|
-
const latest = data["latest"];
|
|
68
|
-
if (!latest) return { error: { kind: "unreachable", message: "npm registry returned no latest dist-tag" } };
|
|
69
|
-
return { latest };
|
|
70
|
-
} catch (err) {
|
|
71
|
-
const msg = err.name === "AbortError" ? `registry fetch timed out after ${timeoutMs}ms` : err.message;
|
|
72
|
-
return { error: { kind: "unreachable", message: msg } };
|
|
73
|
-
} finally {
|
|
74
|
-
clearTimeout(timer);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
59
|
function teachFailure(json, current, code, message, userAction) {
|
|
78
60
|
if (json) {
|
|
79
61
|
console.log(
|
|
@@ -211,23 +193,28 @@ function nudgeDisabled() {
|
|
|
211
193
|
function nudgeLine(current, latest) {
|
|
212
194
|
return isNewer(latest, current) ? `mm-harness ${current} \u2192 ${latest} available \xB7 run: mm-harness update` : null;
|
|
213
195
|
}
|
|
214
|
-
|
|
196
|
+
function maybeNudge(now = Date.now()) {
|
|
215
197
|
if (nudgeDisabled()) return;
|
|
216
198
|
const file = cacheFile();
|
|
217
199
|
const cache = readCache(file);
|
|
218
200
|
const current = currentVersion();
|
|
219
|
-
let latest = cache?.latest ?? "";
|
|
220
201
|
process.once("exit", () => {
|
|
221
|
-
const line = nudgeLine(current, latest);
|
|
202
|
+
const line = nudgeLine(current, cache?.latest ?? "");
|
|
222
203
|
if (line) process.stderr.write(`${line}
|
|
223
204
|
`);
|
|
224
205
|
});
|
|
225
206
|
if (!cache || now - cache.lastCheck >= NUDGE_INTERVAL_MS) {
|
|
226
|
-
writeCache(file, { lastCheck: now, latest });
|
|
227
|
-
const
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
207
|
+
writeCache(file, { lastCheck: now, latest: cache?.latest ?? "" });
|
|
208
|
+
const worker = path.join(runnerDir, "adapters", "shared", "update-check-worker.mjs");
|
|
209
|
+
if (!fs.existsSync(worker)) return;
|
|
210
|
+
try {
|
|
211
|
+
const child = spawn(
|
|
212
|
+
process.execPath,
|
|
213
|
+
[worker, file, String(NUDGE_FETCH_TIMEOUT_MS)],
|
|
214
|
+
{ detached: true, stdio: "ignore" }
|
|
215
|
+
);
|
|
216
|
+
child.unref();
|
|
217
|
+
} catch {
|
|
231
218
|
}
|
|
232
219
|
}
|
|
233
220
|
}
|
package/dist/mm-harness-cli.js
CHANGED
|
@@ -696,7 +696,7 @@ program.command("completions").description("Install/print bundled shell tab-comp
|
|
|
696
696
|
});
|
|
697
697
|
const NUDGE_SKIP = ["update", "completions", "completion-candidates"];
|
|
698
698
|
if (rawArgv.length > 0 && !NUDGE_SKIP.includes(rawArgv[0])) {
|
|
699
|
-
|
|
699
|
+
maybeNudge();
|
|
700
700
|
}
|
|
701
701
|
function hasPassthroughHelp(argv) {
|
|
702
702
|
const divider = argv.indexOf("--");
|