@reshotdev/screenshot 0.0.1-beta.17 → 0.0.1-beta.19
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/package.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const chalk = require("chalk");
|
|
4
4
|
const { runDoctorTarget } = require("../lib/certification");
|
|
5
|
+
const config = require("../lib/config");
|
|
5
6
|
|
|
6
7
|
async function doctorTargetCommand(options = {}) {
|
|
7
8
|
const scenarioKeys = options.scenarios
|
|
@@ -11,6 +12,32 @@ async function doctorTargetCommand(options = {}) {
|
|
|
11
12
|
.filter(Boolean)
|
|
12
13
|
: null;
|
|
13
14
|
|
|
15
|
+
// Check for a config BEFORE the banner so we don't print "scenarios: all
|
|
16
|
+
// certified" immediately above a "Config file not found" error (audit run-11
|
|
17
|
+
// F5). Without a config there is nothing to certify.
|
|
18
|
+
let hasConfig = false;
|
|
19
|
+
try {
|
|
20
|
+
hasConfig = config.configExists();
|
|
21
|
+
} catch {
|
|
22
|
+
hasConfig = false;
|
|
23
|
+
}
|
|
24
|
+
if (!hasConfig) {
|
|
25
|
+
if (options.json) {
|
|
26
|
+
console.log(
|
|
27
|
+
JSON.stringify({ ok: false, error: "Config file not found" }, null, 2),
|
|
28
|
+
);
|
|
29
|
+
} else {
|
|
30
|
+
console.error(
|
|
31
|
+
chalk.red("\n ✖ Target doctor aborted: Config file not found."),
|
|
32
|
+
);
|
|
33
|
+
console.error(
|
|
34
|
+
chalk.gray(" Run `reshot init` (or `reshot setup`) to create one."),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
process.exitCode = 1;
|
|
38
|
+
return { ok: false, error: "Config file not found" };
|
|
39
|
+
}
|
|
40
|
+
|
|
14
41
|
// Emit an immediate banner BEFORE any async work so the command is never
|
|
15
42
|
// silent — previously it produced zero output while preparing fixtures and
|
|
16
43
|
// launching a browser, which read as a hang.
|
package/src/commands/publish.js
CHANGED
|
@@ -1847,7 +1847,7 @@ async function publishCommand(options = {}) {
|
|
|
1847
1847
|
if (keptLive > 0) {
|
|
1848
1848
|
console.log(
|
|
1849
1849
|
chalk.gray(
|
|
1850
|
-
` ${keptLive} unchanged visual${keptLive === 1 ? "" : "s"}
|
|
1850
|
+
` ${keptLive} unchanged visual${keptLive === 1 ? "" : "s"} kept current state (live pointers preserved; no re-approval needed).`,
|
|
1851
1851
|
),
|
|
1852
1852
|
);
|
|
1853
1853
|
}
|
|
@@ -1862,7 +1862,7 @@ async function publishCommand(options = {}) {
|
|
|
1862
1862
|
} else {
|
|
1863
1863
|
console.log(
|
|
1864
1864
|
chalk.cyan(
|
|
1865
|
-
`\n ℹ No new captures to review — all ${successCount} published visual${successCount === 1 ? "" : "s"} were unchanged
|
|
1865
|
+
`\n ℹ No new captures to review — all ${successCount} published visual${successCount === 1 ? "" : "s"} were unchanged; existing live pointers are preserved (already-approved stay live, pending stay pending).`,
|
|
1866
1866
|
),
|
|
1867
1867
|
);
|
|
1868
1868
|
}
|
package/src/commands/pull.js
CHANGED
|
@@ -120,7 +120,13 @@ function deriveUsageSample(assets) {
|
|
|
120
120
|
const contexts = Object.keys(assets[group][visualKey] || {});
|
|
121
121
|
if (contexts.length === 0) continue;
|
|
122
122
|
const context = contexts.includes("default") ? "default" : contexts[0];
|
|
123
|
-
|
|
123
|
+
// A capture entry is either flat ({src,width,height}) or step-based
|
|
124
|
+
// ({steps:[{src,...}]}). Tell the caller which, so the printed example
|
|
125
|
+
// references the right path (`.steps[0].src` vs `.src`) and doesn't
|
|
126
|
+
// produce an undefined src (audit run-12 MED-1).
|
|
127
|
+
const entry = assets[group][visualKey][context];
|
|
128
|
+
const stepped = !!(entry && Array.isArray(entry.steps));
|
|
129
|
+
return { group, visualKey, context, stepped };
|
|
124
130
|
}
|
|
125
131
|
}
|
|
126
132
|
return null;
|
|
@@ -479,6 +485,9 @@ async function pullCommand(options = {}) {
|
|
|
479
485
|
const sGroup = sample?.group ?? "dashboard";
|
|
480
486
|
const sVisual = sample?.visualKey ?? "mainView";
|
|
481
487
|
const sCtx = sample?.context ?? "default";
|
|
488
|
+
// Step-based capture entries nest the fields under `steps[0]`; reference it
|
|
489
|
+
// so the printed example's src/width/height aren't undefined (run-12 MED-1).
|
|
490
|
+
const sStep = sample?.stepped ? ".steps[0]" : "";
|
|
482
491
|
|
|
483
492
|
// Show format-specific usage instructions
|
|
484
493
|
if (format === "ts") {
|
|
@@ -499,10 +508,10 @@ async function pullCommand(options = {}) {
|
|
|
499
508
|
console.log(chalk.cyan(' import assets from "./reshot-assets.json";\n'));
|
|
500
509
|
console.log(chalk.white("Access assets with dot notation:\n"));
|
|
501
510
|
console.log(chalk.cyan(" <img"));
|
|
502
|
-
console.log(chalk.cyan(` src={assets.assets.${sGroup}.${sVisual}.${sCtx}.src}`));
|
|
503
|
-
console.log(chalk.cyan(` width={assets.assets.${sGroup}.${sVisual}.${sCtx}.width}`));
|
|
504
|
-
console.log(chalk.cyan(` height={assets.assets.${sGroup}.${sVisual}.${sCtx}.height}`));
|
|
505
|
-
console.log(chalk.cyan(` alt={assets.assets.${sGroup}.${sVisual}.${sCtx}.alt}`));
|
|
511
|
+
console.log(chalk.cyan(` src={assets.assets.${sGroup}.${sVisual}.${sCtx}${sStep}.src}`));
|
|
512
|
+
console.log(chalk.cyan(` width={assets.assets.${sGroup}.${sVisual}.${sCtx}${sStep}.width}`));
|
|
513
|
+
console.log(chalk.cyan(` height={assets.assets.${sGroup}.${sVisual}.${sCtx}${sStep}.height}`));
|
|
514
|
+
console.log(chalk.cyan(` alt={assets.assets.${sGroup}.${sVisual}.${sCtx}${sStep}.alt}`));
|
|
506
515
|
console.log(chalk.cyan(" />\n"));
|
|
507
516
|
} else if (format === "csv") {
|
|
508
517
|
console.log(chalk.blue("━━━ CSV Usage ━━━\n"));
|
|
@@ -225,6 +225,26 @@ async function setupWizard(options = {}) {
|
|
|
225
225
|
);
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
// The interactive wizard below needs a TTY. In CI / piped-stdin contexts
|
|
229
|
+
// (and when no `--project/--token` were supplied to drive it non-
|
|
230
|
+
// interactively), bail out with clear guidance instead of letting inquirer
|
|
231
|
+
// throw an unhandled `ERR_USE_AFTER_CLOSE: readline` (audit run-11 F4).
|
|
232
|
+
if (!isInteractive() && !didLinkFromOptions) {
|
|
233
|
+
console.log(
|
|
234
|
+
chalk.yellow("\n⚠ Non-interactive environment detected (no TTY)."),
|
|
235
|
+
);
|
|
236
|
+
console.log(
|
|
237
|
+
chalk.gray(" Run setup with your project credentials instead:"),
|
|
238
|
+
);
|
|
239
|
+
console.log(
|
|
240
|
+
chalk.cyan(" npx reshot setup --project <projectId> --token <token>"),
|
|
241
|
+
);
|
|
242
|
+
console.log(
|
|
243
|
+
chalk.gray(" or set RESHOT_PROJECT_ID and RESHOT_API_KEY, then re-run.\n"),
|
|
244
|
+
);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
228
248
|
// If already set up and not forcing, show status and offer options
|
|
229
249
|
if ((isAlreadyAuthed || existingConfig) && !force && !didLinkFromOptions) {
|
|
230
250
|
console.log(
|