@reshotdev/screenshot 0.0.1-beta.16 → 0.0.1-beta.17
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 +1 -1
- package/src/commands/auth.js +3 -1
- package/src/commands/publish.js +59 -17
- package/src/index.js +24 -3
package/package.json
CHANGED
package/src/commands/auth.js
CHANGED
|
@@ -179,7 +179,9 @@ async function authCommand(options = {}) {
|
|
|
179
179
|
try {
|
|
180
180
|
const apiBaseUrl = options.apiBaseUrl || getApiBaseUrl();
|
|
181
181
|
const verified = await verifyApiKeyFn(apiBaseUrl, envApiKey, httpClient);
|
|
182
|
-
|
|
182
|
+
// /auth/cli/verify wraps its payload in an { data: … } envelope.
|
|
183
|
+
const payload = verified?.data || verified;
|
|
184
|
+
projectName = payload?.project?.name || null;
|
|
183
185
|
} catch {
|
|
184
186
|
// Verification is best-effort here; keep going without the name.
|
|
185
187
|
}
|
package/src/commands/publish.js
CHANGED
|
@@ -666,6 +666,7 @@ async function publishWithTransactionalFlow(
|
|
|
666
666
|
let successCount = 0;
|
|
667
667
|
let failCount = 0;
|
|
668
668
|
let skippedCount = 0;
|
|
669
|
+
let reviewPendingCount = 0;
|
|
669
670
|
let viewUrl = null;
|
|
670
671
|
|
|
671
672
|
// Flatten all assets with metadata
|
|
@@ -878,7 +879,16 @@ async function publishWithTransactionalFlow(
|
|
|
878
879
|
contentType: file.contentType,
|
|
879
880
|
});
|
|
880
881
|
|
|
881
|
-
|
|
882
|
+
// Label the artifact type so PNG + MHTML-sidecar lines for the same
|
|
883
|
+
// visual don't read as a duplicate-upload bug (audit run-10 F3).
|
|
884
|
+
const artifactLabel = file._isThumbnail
|
|
885
|
+
? "thumbnail"
|
|
886
|
+
: file._isDomScene
|
|
887
|
+
? "dom scene .mhtml"
|
|
888
|
+
: (path.extname(file.path || "").replace(/^\./, "") || "asset");
|
|
889
|
+
console.log(
|
|
890
|
+
chalk.green(` ✔ Uploaded ${file.visualKey} (${artifactLabel})`),
|
|
891
|
+
);
|
|
882
892
|
return { success: true, file, s3Path: urlInfo.path };
|
|
883
893
|
} catch (err) {
|
|
884
894
|
console.log(
|
|
@@ -1008,6 +1018,10 @@ async function publishWithTransactionalFlow(
|
|
|
1008
1018
|
// Unwrap API envelope: response may be { data: { results, ... } } or { results, ... }
|
|
1009
1019
|
const batchResult = rawBatchResult.data || rawBatchResult;
|
|
1010
1020
|
|
|
1021
|
+
// Count only NEWLY-pending (new/changed) captures, so the final summary
|
|
1022
|
+
// doesn't imply a re-publish reset already-live captures (audit F1).
|
|
1023
|
+
reviewPendingCount += batchResult.reviewQueueItems || 0;
|
|
1024
|
+
|
|
1011
1025
|
for (const r of batchResult.results || []) {
|
|
1012
1026
|
if (r.status === "ok") {
|
|
1013
1027
|
const count = r.assetsProcessed || 0;
|
|
@@ -1051,7 +1065,14 @@ async function publishWithTransactionalFlow(
|
|
|
1051
1065
|
}
|
|
1052
1066
|
}
|
|
1053
1067
|
|
|
1054
|
-
return {
|
|
1068
|
+
return {
|
|
1069
|
+
successCount,
|
|
1070
|
+
failCount,
|
|
1071
|
+
skippedCount,
|
|
1072
|
+
reviewPendingCount,
|
|
1073
|
+
viewUrl,
|
|
1074
|
+
failedUploadKeys,
|
|
1075
|
+
};
|
|
1055
1076
|
}
|
|
1056
1077
|
|
|
1057
1078
|
/**
|
|
@@ -1697,6 +1718,7 @@ async function publishCommand(options = {}) {
|
|
|
1697
1718
|
let successCount = 0;
|
|
1698
1719
|
let failCount = 0;
|
|
1699
1720
|
let skippedCount = 0;
|
|
1721
|
+
let reviewPendingCount = 0;
|
|
1700
1722
|
let viewUrl = null;
|
|
1701
1723
|
|
|
1702
1724
|
// Load diff manifests for attaching diff data to screenshot assets
|
|
@@ -1743,6 +1765,7 @@ async function publishCommand(options = {}) {
|
|
|
1743
1765
|
successCount = result.successCount;
|
|
1744
1766
|
failCount = result.failCount;
|
|
1745
1767
|
skippedCount = result.skippedCount || 0;
|
|
1768
|
+
reviewPendingCount = result.reviewPendingCount || 0;
|
|
1746
1769
|
viewUrl = result.viewUrl || null;
|
|
1747
1770
|
} catch (txError) {
|
|
1748
1771
|
// Fall back to legacy flow if transactional fails
|
|
@@ -1809,21 +1832,40 @@ async function publishCommand(options = {}) {
|
|
|
1809
1832
|
}
|
|
1810
1833
|
|
|
1811
1834
|
if (!autoApprove && successCount > 0) {
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1835
|
+
// Only NEW/CHANGED captures await review; unchanged captures dedup to
|
|
1836
|
+
// their existing (often already-approved) version and stay live. Report
|
|
1837
|
+
// the accurate pending count so a re-publish doesn't look like it reset
|
|
1838
|
+
// already-approved work (audit run-10 F1).
|
|
1839
|
+
const pending = reviewPendingCount;
|
|
1840
|
+
const keptLive = Math.max(0, successCount - pending);
|
|
1841
|
+
if (pending > 0) {
|
|
1842
|
+
console.log(
|
|
1843
|
+
chalk.cyan(
|
|
1844
|
+
`\n ℹ ${pending} new/changed visual${pending === 1 ? "" : "s"} awaiting review (PENDING)`,
|
|
1845
|
+
),
|
|
1846
|
+
);
|
|
1847
|
+
if (keptLive > 0) {
|
|
1848
|
+
console.log(
|
|
1849
|
+
chalk.gray(
|
|
1850
|
+
` ${keptLive} unchanged visual${keptLive === 1 ? "" : "s"} stayed live (no re-approval needed).`,
|
|
1851
|
+
),
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
console.log(
|
|
1855
|
+
chalk.gray(
|
|
1856
|
+
" To skip review for first-time captures, re-run with `reshot publish --auto-approve`",
|
|
1857
|
+
),
|
|
1858
|
+
);
|
|
1859
|
+
console.log(
|
|
1860
|
+
chalk.gray(" or approve them in the studio link above."),
|
|
1861
|
+
);
|
|
1862
|
+
} else {
|
|
1863
|
+
console.log(
|
|
1864
|
+
chalk.cyan(
|
|
1865
|
+
`\n ℹ No new captures to review — all ${successCount} published visual${successCount === 1 ? "" : "s"} were unchanged and stayed live.`,
|
|
1866
|
+
),
|
|
1867
|
+
);
|
|
1868
|
+
}
|
|
1827
1869
|
}
|
|
1828
1870
|
|
|
1829
1871
|
// Helpful guidance about diff percentages
|
package/src/index.js
CHANGED
|
@@ -159,6 +159,7 @@ program
|
|
|
159
159
|
.command("run [target]")
|
|
160
160
|
.description("Execute visual capture scenarios from config")
|
|
161
161
|
.option("-s, --scenarios <keys>", "Comma-separated list of scenario keys")
|
|
162
|
+
.option("--scenario <keys>", "Alias for --scenarios")
|
|
162
163
|
.option("--no-headless", "Run browser in visible mode")
|
|
163
164
|
.option("--variant <json>", "Override variant configuration as JSON")
|
|
164
165
|
.option("--all-variants", "Run all configured variant combinations")
|
|
@@ -431,7 +432,24 @@ program
|
|
|
431
432
|
});
|
|
432
433
|
|
|
433
434
|
// Doctor: Validate target contract and readiness
|
|
434
|
-
const doctor = program
|
|
435
|
+
const doctor = program
|
|
436
|
+
.command("doctor")
|
|
437
|
+
.description("Validate target configuration and readiness")
|
|
438
|
+
.option("-s, --scenarios <keys>", "Comma-separated list of scenario keys")
|
|
439
|
+
.option("--timeout <ms>", "Per-step timeout in milliseconds (default 15000)")
|
|
440
|
+
.option("--json", "Output JSON report")
|
|
441
|
+
.action(async (options) => {
|
|
442
|
+
// Bare `reshot doctor` runs the target readiness audit by default instead
|
|
443
|
+
// of just printing help (audit run-10 F5). Use `doctor release` for the
|
|
444
|
+
// full release gate.
|
|
445
|
+
try {
|
|
446
|
+
const doctorTargetCommand = require("./commands/doctor-target");
|
|
447
|
+
await doctorTargetCommand(options || {});
|
|
448
|
+
} catch (error) {
|
|
449
|
+
console.error(chalk.red("Error:"), error.message);
|
|
450
|
+
process.exit(1);
|
|
451
|
+
}
|
|
452
|
+
});
|
|
435
453
|
|
|
436
454
|
doctor
|
|
437
455
|
.command("target")
|
|
@@ -640,8 +658,11 @@ function resolveRecordClipScenarioKeys(target, options = {}) {
|
|
|
640
658
|
}
|
|
641
659
|
|
|
642
660
|
function resolveScenarioKeysFromTarget(target, options = {}) {
|
|
643
|
-
|
|
644
|
-
|
|
661
|
+
// Accept the singular `--scenario` as an alias for `--scenarios` — an easy
|
|
662
|
+
// trap that otherwise hard-fails the run (audit run-10 F2).
|
|
663
|
+
const scenarioList = options.scenarios || options.scenario;
|
|
664
|
+
if (scenarioList) {
|
|
665
|
+
return scenarioList.split(",").map((value) => value.trim()).filter(Boolean);
|
|
645
666
|
}
|
|
646
667
|
|
|
647
668
|
if (!target) {
|