@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reshotdev/screenshot",
3
- "version": "0.0.1-beta.17",
3
+ "version": "0.0.1-beta.19",
4
4
  "description": "Screenshot and video capture CLI",
5
5
  "author": "Reshot <hello@reshot.dev>",
6
6
  "license": "MIT",
@@ -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.
@@ -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"} stayed live (no re-approval needed).`,
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 and stayed live.`,
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
  }
@@ -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
- return { group, visualKey, context };
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(