@reshotdev/screenshot 0.0.1-beta.4 ā 0.0.1-beta.7
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/README.md +2 -2
- package/package.json +9 -2
- package/src/commands/auth.js +2 -4
- package/src/commands/ci-setup.js +2 -2
- package/src/commands/drifts.js +5 -70
- package/src/commands/import-tests.js +13 -13
- package/src/commands/ingest.js +10 -10
- package/src/commands/init.js +16 -277
- package/src/commands/publish.js +55 -227
- package/src/commands/pull.js +2 -2
- package/src/commands/setup-wizard.js +123 -523
- package/src/commands/setup.js +7 -7
- package/src/commands/status.js +26 -43
- package/src/commands/sync.js +28 -236
- package/src/commands/ui.js +1 -1
- package/src/index.js +11 -90
- package/src/lib/api-client.js +57 -12
- package/src/lib/capture-engine.js +3 -3
- package/src/lib/capture-script-runner.js +24 -2
- package/src/lib/config.js +8 -72
- package/src/lib/record-config.js +1 -1
- package/src/lib/standalone-mode.js +1 -1
- package/src/lib/storage-providers.js +4 -4
- package/src/lib/ui-api.js +6 -7
- package/web/manager/dist/assets/{index--ZgioErz.js ā index-8H7P9ANi.js} +1 -1
- package/web/manager/dist/index.html +1 -1
- package/src/commands/validate-docs.js +0 -529
package/src/commands/publish.js
CHANGED
|
@@ -390,13 +390,13 @@ function resolveProjectContext({ settings, docSyncConfig, storageMode }) {
|
|
|
390
390
|
if (!apiKey) {
|
|
391
391
|
throw new Error(
|
|
392
392
|
"No API key found. Set RESHOT_API_KEY in your environment or run `reshot auth` locally to create .reshot/settings.json.\n" +
|
|
393
|
-
"Alternatively, configure BYOS (Bring Your Own Storage) in
|
|
393
|
+
"Alternatively, configure BYOS (Bring Your Own Storage) in reshot.config.json to publish without authentication.",
|
|
394
394
|
);
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
if (!projectId) {
|
|
398
398
|
throw new Error(
|
|
399
|
-
"No project ID found. Set RESHOT_PROJECT_ID in your environment or ensure
|
|
399
|
+
"No project ID found. Set RESHOT_PROJECT_ID in your environment or ensure reshot.config.json contains _metadata.projectId.",
|
|
400
400
|
);
|
|
401
401
|
}
|
|
402
402
|
|
|
@@ -578,6 +578,7 @@ async function publishWithTransactionalFlow(
|
|
|
578
578
|
docSyncConfig,
|
|
579
579
|
gitInfo,
|
|
580
580
|
diffManifests = null,
|
|
581
|
+
{ autoApprove = false } = {},
|
|
581
582
|
) {
|
|
582
583
|
console.log(
|
|
583
584
|
chalk.cyan(" š Using transactional upload (direct to R2)...\n"),
|
|
@@ -807,7 +808,10 @@ async function publishWithTransactionalFlow(
|
|
|
807
808
|
});
|
|
808
809
|
}
|
|
809
810
|
|
|
810
|
-
//
|
|
811
|
+
// Build all commits for batch request
|
|
812
|
+
const MAX_BATCH_SIZE = 200;
|
|
813
|
+
const commits = [];
|
|
814
|
+
|
|
811
815
|
for (const { group, scenarioConfig, assets } of groupMap.values()) {
|
|
812
816
|
const contextObj = buildContextForVariation(
|
|
813
817
|
scenarioConfig,
|
|
@@ -824,38 +828,58 @@ async function publishWithTransactionalFlow(
|
|
|
824
828
|
});
|
|
825
829
|
|
|
826
830
|
if (metadata.cli) {
|
|
827
|
-
metadata.cli.features = ["steps", "transactional"];
|
|
831
|
+
metadata.cli.features = ["steps", "transactional", "batch"];
|
|
828
832
|
}
|
|
829
833
|
|
|
834
|
+
commits.push({ metadata, assets });
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// Send in batches
|
|
838
|
+
console.log(
|
|
839
|
+
chalk.gray(` Committing ${commits.length} scenario(s) to platform...`),
|
|
840
|
+
);
|
|
841
|
+
|
|
842
|
+
for (let i = 0; i < commits.length; i += MAX_BATCH_SIZE) {
|
|
843
|
+
const chunk = commits.slice(i, i + MAX_BATCH_SIZE);
|
|
844
|
+
|
|
830
845
|
try {
|
|
831
|
-
const
|
|
832
|
-
|
|
833
|
-
|
|
846
|
+
const batchResult = await apiClient.publishBatch(apiKey, {
|
|
847
|
+
commits: chunk,
|
|
848
|
+
autoApprove: autoApprove || false,
|
|
834
849
|
});
|
|
835
850
|
|
|
836
|
-
const
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
851
|
+
for (const r of batchResult.results || []) {
|
|
852
|
+
if (r.status === "ok") {
|
|
853
|
+
const count = r.assetsProcessed || 0;
|
|
854
|
+
console.log(
|
|
855
|
+
chalk.green(
|
|
856
|
+
` ā Committed "${r.scenario}" (${r.context}): ${count} asset(s)`,
|
|
857
|
+
),
|
|
858
|
+
);
|
|
859
|
+
successCount += count;
|
|
843
860
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
861
|
+
if (r.skippedAssets?.length > 0) {
|
|
862
|
+
for (const key of r.skippedAssets) {
|
|
863
|
+
console.log(chalk.yellow(` ā Skipped "${key}" (plan limit reached)`));
|
|
864
|
+
}
|
|
865
|
+
skippedCount += r.skippedAssets.length;
|
|
866
|
+
}
|
|
867
|
+
} else {
|
|
868
|
+
console.log(
|
|
869
|
+
chalk.red(
|
|
870
|
+
` ā "${r.scenario}" (${r.context}): ${r.error || "Unknown error"}`,
|
|
871
|
+
),
|
|
872
|
+
);
|
|
873
|
+
failCount++;
|
|
848
874
|
}
|
|
849
|
-
skippedCount += result.skippedAssets.length;
|
|
850
875
|
}
|
|
851
876
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
viewUrl = result.viewUrl;
|
|
877
|
+
if (!viewUrl && batchResult.viewUrl) {
|
|
878
|
+
viewUrl = batchResult.viewUrl;
|
|
855
879
|
}
|
|
856
880
|
} catch (error) {
|
|
857
|
-
console.log(chalk.red(` ā
|
|
858
|
-
failCount +=
|
|
881
|
+
console.log(chalk.red(` ā Batch request failed: ${error.message}`));
|
|
882
|
+
failCount += chunk.length;
|
|
859
883
|
}
|
|
860
884
|
}
|
|
861
885
|
|
|
@@ -1167,70 +1191,6 @@ function getRecentCommits(lastCommitHash) {
|
|
|
1167
1191
|
}
|
|
1168
1192
|
}
|
|
1169
1193
|
|
|
1170
|
-
/**
|
|
1171
|
-
* Recursively find all markdown files matching include/exclude patterns
|
|
1172
|
-
*/
|
|
1173
|
-
function findDocFiles(
|
|
1174
|
-
docsRoot,
|
|
1175
|
-
includePatterns = ["**/*.md", "**/*.mdx"],
|
|
1176
|
-
excludePatterns = [],
|
|
1177
|
-
) {
|
|
1178
|
-
const files = [];
|
|
1179
|
-
const rootPath = path.resolve(process.cwd(), docsRoot);
|
|
1180
|
-
|
|
1181
|
-
if (!fs.existsSync(rootPath)) {
|
|
1182
|
-
return files;
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
function walkDir(dir, relativePath = "") {
|
|
1186
|
-
const items = fs.readdirSync(dir);
|
|
1187
|
-
|
|
1188
|
-
for (const item of items) {
|
|
1189
|
-
const fullPath = path.join(dir, item);
|
|
1190
|
-
const relativeItemPath = path
|
|
1191
|
-
.join(relativePath, item)
|
|
1192
|
-
.replace(/\\/g, "/");
|
|
1193
|
-
const stat = fs.statSync(fullPath);
|
|
1194
|
-
|
|
1195
|
-
// Check exclude patterns
|
|
1196
|
-
const shouldExclude = excludePatterns.some((pattern) => {
|
|
1197
|
-
const regex = new RegExp(
|
|
1198
|
-
pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*"),
|
|
1199
|
-
);
|
|
1200
|
-
return regex.test(relativeItemPath) || regex.test(fullPath);
|
|
1201
|
-
});
|
|
1202
|
-
|
|
1203
|
-
if (shouldExclude) {
|
|
1204
|
-
continue;
|
|
1205
|
-
}
|
|
1206
|
-
|
|
1207
|
-
if (stat.isDirectory()) {
|
|
1208
|
-
walkDir(fullPath, relativeItemPath);
|
|
1209
|
-
} else if (stat.isFile()) {
|
|
1210
|
-
const ext = path.extname(item).toLowerCase();
|
|
1211
|
-
const matchesInclude = includePatterns.some((pattern) => {
|
|
1212
|
-
const regex = new RegExp(
|
|
1213
|
-
pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*"),
|
|
1214
|
-
);
|
|
1215
|
-
return (
|
|
1216
|
-
regex.test(relativeItemPath) || ext === ".md" || ext === ".mdx"
|
|
1217
|
-
);
|
|
1218
|
-
});
|
|
1219
|
-
|
|
1220
|
-
if (matchesInclude && (ext === ".md" || ext === ".mdx")) {
|
|
1221
|
-
files.push({
|
|
1222
|
-
fullPath,
|
|
1223
|
-
relativePath: relativeItemPath,
|
|
1224
|
-
});
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
walkDir(rootPath);
|
|
1231
|
-
return files;
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
1194
|
/**
|
|
1235
1195
|
* Parse frontmatter from markdown content
|
|
1236
1196
|
*/
|
|
@@ -1268,7 +1228,7 @@ function parseFrontmatter(content) {
|
|
|
1268
1228
|
}
|
|
1269
1229
|
|
|
1270
1230
|
async function publishCommand(options = {}) {
|
|
1271
|
-
const { tag, message, dryRun, force, video, outputJson } = options;
|
|
1231
|
+
const { tag, message, dryRun, force, video, outputJson, autoApprove } = options;
|
|
1272
1232
|
|
|
1273
1233
|
// Result tracking for --output-json and programmatic callers
|
|
1274
1234
|
const publishResult = {
|
|
@@ -1294,6 +1254,10 @@ async function publishCommand(options = {}) {
|
|
|
1294
1254
|
console.log(chalk.yellow("š DRY RUN MODE - No assets will be uploaded\n"));
|
|
1295
1255
|
}
|
|
1296
1256
|
|
|
1257
|
+
if (autoApprove) {
|
|
1258
|
+
console.log(chalk.cyan(" ā
Auto-approve enabled: visuals will be approved immediately\n"));
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1297
1261
|
// Read config + settings (if available)
|
|
1298
1262
|
const settings = readSettingsSafe();
|
|
1299
1263
|
let docSyncConfig = null;
|
|
@@ -1368,8 +1332,6 @@ async function publishCommand(options = {}) {
|
|
|
1368
1332
|
// Get feature toggles
|
|
1369
1333
|
const features = docSyncConfig?._metadata?.features || {
|
|
1370
1334
|
visuals: true,
|
|
1371
|
-
docs: false,
|
|
1372
|
-
changelog: true,
|
|
1373
1335
|
};
|
|
1374
1336
|
|
|
1375
1337
|
// Get git information
|
|
@@ -1479,6 +1441,7 @@ async function publishCommand(options = {}) {
|
|
|
1479
1441
|
docSyncConfig,
|
|
1480
1442
|
{ commitHash, commitMessage, publishSessionId },
|
|
1481
1443
|
diffManifests,
|
|
1444
|
+
{ autoApprove },
|
|
1482
1445
|
);
|
|
1483
1446
|
successCount = result.successCount;
|
|
1484
1447
|
failCount = result.failCount;
|
|
@@ -1558,141 +1521,6 @@ async function publishCommand(options = {}) {
|
|
|
1558
1521
|
);
|
|
1559
1522
|
}
|
|
1560
1523
|
|
|
1561
|
-
// Stream B: Documentation
|
|
1562
|
-
if (features.docs === true) {
|
|
1563
|
-
console.log(chalk.cyan("\nš Publishing documentation...\n"));
|
|
1564
|
-
|
|
1565
|
-
if (!docSyncConfig || !docSyncConfig.docs) {
|
|
1566
|
-
console.log(
|
|
1567
|
-
chalk.yellow(
|
|
1568
|
-
" ā No docs configuration found in docsync.config.json. Skipping docs stream.",
|
|
1569
|
-
),
|
|
1570
|
-
);
|
|
1571
|
-
} else {
|
|
1572
|
-
const docsConfig = docSyncConfig.docs;
|
|
1573
|
-
const docsRoot = docsConfig.root || "./docs";
|
|
1574
|
-
const includePatterns = docsConfig.include || ["**/*.md", "**/*.mdx"];
|
|
1575
|
-
const excludePatterns = docsConfig.exclude || [
|
|
1576
|
-
"**/node_modules/**",
|
|
1577
|
-
"**/.git/**",
|
|
1578
|
-
];
|
|
1579
|
-
|
|
1580
|
-
const docFiles = findDocFiles(docsRoot, includePatterns, excludePatterns);
|
|
1581
|
-
|
|
1582
|
-
if (docFiles.length === 0) {
|
|
1583
|
-
console.log(
|
|
1584
|
-
chalk.yellow(" ā No documentation files found to publish."),
|
|
1585
|
-
);
|
|
1586
|
-
} else {
|
|
1587
|
-
console.log(
|
|
1588
|
-
chalk.cyan(` Found ${docFiles.length} documentation file(s)\n`),
|
|
1589
|
-
);
|
|
1590
|
-
|
|
1591
|
-
const docsPayload = [];
|
|
1592
|
-
for (const docFile of docFiles) {
|
|
1593
|
-
const content = fs.readFileSync(docFile.fullPath, "utf-8");
|
|
1594
|
-
const { frontmatter, content: docContent } =
|
|
1595
|
-
parseFrontmatter(content);
|
|
1596
|
-
|
|
1597
|
-
docsPayload.push({
|
|
1598
|
-
path: docFile.relativePath,
|
|
1599
|
-
content: docContent,
|
|
1600
|
-
frontmatter:
|
|
1601
|
-
Object.keys(frontmatter).length > 0 ? frontmatter : undefined,
|
|
1602
|
-
status: frontmatter.status || "draft",
|
|
1603
|
-
});
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
// Docs publishing requires platform (no BYOS support yet)
|
|
1607
|
-
if (resolvedMode === "byos") {
|
|
1608
|
-
console.log(
|
|
1609
|
-
chalk.yellow(
|
|
1610
|
-
" ā Documentation publishing requires Reshot platform.",
|
|
1611
|
-
),
|
|
1612
|
-
);
|
|
1613
|
-
console.log(
|
|
1614
|
-
chalk.gray(
|
|
1615
|
-
" Run 'reshot auth' to enable doc hosting with review workflow.",
|
|
1616
|
-
),
|
|
1617
|
-
);
|
|
1618
|
-
} else {
|
|
1619
|
-
try {
|
|
1620
|
-
const result = await apiClient.publishDocs(apiKey, {
|
|
1621
|
-
projectId,
|
|
1622
|
-
docs: docsPayload,
|
|
1623
|
-
});
|
|
1624
|
-
console.log(
|
|
1625
|
-
chalk.green(
|
|
1626
|
-
` ā Published ${result.created || 0} new doc(s), updated ${
|
|
1627
|
-
result.updated || 0
|
|
1628
|
-
} doc(s)`,
|
|
1629
|
-
),
|
|
1630
|
-
);
|
|
1631
|
-
} catch (error) {
|
|
1632
|
-
console.log(
|
|
1633
|
-
chalk.red(` ā Failed to publish docs: ${error.message}`),
|
|
1634
|
-
);
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
} else {
|
|
1640
|
-
console.log(
|
|
1641
|
-
chalk.yellow(
|
|
1642
|
-
" ā Documentation publishing is disabled for this project.",
|
|
1643
|
-
),
|
|
1644
|
-
);
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
// Stream C: Changelog
|
|
1648
|
-
if (features.changelog === true) {
|
|
1649
|
-
// Changelog requires platform (no BYOS support)
|
|
1650
|
-
if (resolvedMode === "byos") {
|
|
1651
|
-
console.log(chalk.cyan("\nš Changelog drafts...\n"));
|
|
1652
|
-
console.log(
|
|
1653
|
-
chalk.yellow(
|
|
1654
|
-
" ā Changelog requires Reshot platform for tracking and publishing.",
|
|
1655
|
-
),
|
|
1656
|
-
);
|
|
1657
|
-
console.log(
|
|
1658
|
-
chalk.gray(" Run 'reshot auth' to enable changelog generation."),
|
|
1659
|
-
);
|
|
1660
|
-
} else {
|
|
1661
|
-
console.log(chalk.cyan("\nš Posting changelog drafts...\n"));
|
|
1662
|
-
const lastPublishedHash = settings?.lastPublishedCommitHash;
|
|
1663
|
-
const recentCommits = getRecentCommits(lastPublishedHash);
|
|
1664
|
-
|
|
1665
|
-
if (recentCommits.length > 0) {
|
|
1666
|
-
try {
|
|
1667
|
-
await apiClient.postChangelogDrafts(projectId, recentCommits, apiKey);
|
|
1668
|
-
console.log(
|
|
1669
|
-
chalk.green(
|
|
1670
|
-
` ā Posted ${recentCommits.length} changelog draft(s)`,
|
|
1671
|
-
),
|
|
1672
|
-
);
|
|
1673
|
-
|
|
1674
|
-
// Update last published commit hash
|
|
1675
|
-
if (settings) {
|
|
1676
|
-
settings.lastPublishedCommitHash = commitHash;
|
|
1677
|
-
config.writeSettings(settings);
|
|
1678
|
-
}
|
|
1679
|
-
} catch (error) {
|
|
1680
|
-
console.log(
|
|
1681
|
-
chalk.yellow(
|
|
1682
|
-
` ā Failed to post changelog drafts: ${error.message}`,
|
|
1683
|
-
),
|
|
1684
|
-
);
|
|
1685
|
-
}
|
|
1686
|
-
} else {
|
|
1687
|
-
console.log(chalk.gray(" No new commits to publish"));
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
|
-
} else {
|
|
1691
|
-
console.log(
|
|
1692
|
-
chalk.yellow(" ā Changelog publishing is disabled for this project."),
|
|
1693
|
-
);
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
1524
|
// Print upgrade path for BYOS users
|
|
1697
1525
|
if (resolvedMode === "byos") {
|
|
1698
1526
|
console.log(chalk.cyan("\nš” Upgrade to Reshot Platform for:"));
|
|
@@ -1700,7 +1528,7 @@ async function publishCommand(options = {}) {
|
|
|
1700
1528
|
console.log(chalk.gray(" ⢠Unbreakable URLs that never change"));
|
|
1701
1529
|
console.log(chalk.gray(" ⢠Version history and rollback"));
|
|
1702
1530
|
console.log(chalk.gray(" ⢠Team collaboration and RBAC"));
|
|
1703
|
-
console.log(chalk.gray(" ā¢
|
|
1531
|
+
console.log(chalk.gray(" ⢠Drift detection and notifications"));
|
|
1704
1532
|
console.log(chalk.gray("\n Run 'reshot auth' to connect your project."));
|
|
1705
1533
|
}
|
|
1706
1534
|
|
package/src/commands/pull.js
CHANGED
|
@@ -112,7 +112,7 @@ async function pullCommand(options = {}) {
|
|
|
112
112
|
projectConfig = config.readConfig();
|
|
113
113
|
} catch (e) {
|
|
114
114
|
console.error(
|
|
115
|
-
chalk.red("Error: No
|
|
115
|
+
chalk.red("Error: No reshot.config.json found. Run 'reshot init' first.")
|
|
116
116
|
);
|
|
117
117
|
process.exit(1);
|
|
118
118
|
}
|
|
@@ -120,7 +120,7 @@ async function pullCommand(options = {}) {
|
|
|
120
120
|
const projectId = projectConfig._metadata?.projectId || projectConfig.projectId;
|
|
121
121
|
if (!projectId) {
|
|
122
122
|
console.error(
|
|
123
|
-
chalk.red("Error: No projectId found in
|
|
123
|
+
chalk.red("Error: No projectId found in reshot.config.json")
|
|
124
124
|
);
|
|
125
125
|
process.exit(1);
|
|
126
126
|
}
|