@reshotdev/screenshot 0.0.1-beta.0

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.
Files changed (59) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +388 -0
  3. package/package.json +64 -0
  4. package/src/commands/auth.js +259 -0
  5. package/src/commands/chrome.js +140 -0
  6. package/src/commands/ci-run.js +123 -0
  7. package/src/commands/ci-setup.js +288 -0
  8. package/src/commands/drifts.js +423 -0
  9. package/src/commands/import-tests.js +309 -0
  10. package/src/commands/ingest.js +458 -0
  11. package/src/commands/init.js +633 -0
  12. package/src/commands/publish.js +1721 -0
  13. package/src/commands/pull.js +303 -0
  14. package/src/commands/record.js +94 -0
  15. package/src/commands/run.js +476 -0
  16. package/src/commands/setup-wizard.js +740 -0
  17. package/src/commands/setup.js +137 -0
  18. package/src/commands/status.js +275 -0
  19. package/src/commands/sync.js +621 -0
  20. package/src/commands/ui.js +248 -0
  21. package/src/commands/validate-docs.js +529 -0
  22. package/src/index.js +462 -0
  23. package/src/lib/api-client.js +815 -0
  24. package/src/lib/capture-engine.js +1623 -0
  25. package/src/lib/capture-script-runner.js +3120 -0
  26. package/src/lib/ci-detect.js +137 -0
  27. package/src/lib/config.js +1240 -0
  28. package/src/lib/diff-engine.js +642 -0
  29. package/src/lib/hash.js +74 -0
  30. package/src/lib/image-crop.js +396 -0
  31. package/src/lib/matrix.js +89 -0
  32. package/src/lib/output-path-template.js +318 -0
  33. package/src/lib/playwright-runner.js +252 -0
  34. package/src/lib/polished-clip.js +553 -0
  35. package/src/lib/privacy-engine.js +408 -0
  36. package/src/lib/progress-tracker.js +142 -0
  37. package/src/lib/record-browser-injection.js +654 -0
  38. package/src/lib/record-cdp.js +612 -0
  39. package/src/lib/record-clip.js +343 -0
  40. package/src/lib/record-config.js +623 -0
  41. package/src/lib/record-screenshot.js +360 -0
  42. package/src/lib/record-terminal.js +123 -0
  43. package/src/lib/recorder-service.js +781 -0
  44. package/src/lib/secrets.js +51 -0
  45. package/src/lib/selector-strategies.js +859 -0
  46. package/src/lib/standalone-mode.js +400 -0
  47. package/src/lib/storage-providers.js +569 -0
  48. package/src/lib/style-engine.js +684 -0
  49. package/src/lib/ui-api.js +4677 -0
  50. package/src/lib/ui-assets.js +373 -0
  51. package/src/lib/ui-executor.js +587 -0
  52. package/src/lib/variant-injector.js +591 -0
  53. package/src/lib/viewport-presets.js +454 -0
  54. package/src/lib/worker-pool.js +118 -0
  55. package/web/cropper/index.html +436 -0
  56. package/web/manager/dist/assets/index--ZgioErz.js +507 -0
  57. package/web/manager/dist/assets/index-n468W0Wr.css +1 -0
  58. package/web/manager/dist/index.html +27 -0
  59. package/web/subtitle-editor/index.html +295 -0
package/src/index.js ADDED
@@ -0,0 +1,462 @@
1
+ #!/usr/bin/env node
2
+
3
+ // index.js - Reshot CLI entry point
4
+ // Consolidated command structure for ease of use while maintaining power features
5
+
6
+ require("dotenv").config({
7
+ path: require("path").join(__dirname, "..", ".env"),
8
+ });
9
+
10
+ const { Command } = require("commander");
11
+ const chalk = require("chalk");
12
+ const pkg = require("../package.json");
13
+
14
+ const program = new Command();
15
+
16
+ program
17
+ .name("reshot")
18
+ .description("Visual documentation that stays in sync")
19
+ .version(pkg.version);
20
+
21
+ // ============================================================================
22
+ // CORE COMMANDS (Primary workflow)
23
+ // ============================================================================
24
+
25
+ // Setup: Interactive wizard for initial configuration
26
+ program
27
+ .command("setup")
28
+ .description("Interactive setup wizard (auth, config, features)")
29
+ .option("--offline", "Skip authentication (local-only mode)")
30
+ .option("--force", "Force re-initialization even if already set up")
31
+ .action(async (options) => {
32
+ try {
33
+ const setupWizard = require("./commands/setup-wizard");
34
+ await setupWizard(options);
35
+ } catch (error) {
36
+ console.error(chalk.red("Error:"), error.message);
37
+ process.exit(1);
38
+ }
39
+ });
40
+
41
+ // Sync: Upload traces and documentation to platform
42
+ program
43
+ .command("sync")
44
+ .description("Upload Playwright traces and documentation to Reshot")
45
+ .option("--trace-dir <path>", "Path to test-results directory")
46
+ .option("--traces", "Sync traces only")
47
+ .option("--docs", "Sync documentation only")
48
+ .option("--dry-run", "Preview what would be synced")
49
+ .option("-v, --verbose", "Show detailed output")
50
+ .action(async (options) => {
51
+ try {
52
+ const syncCommand = require("./commands/sync");
53
+ await syncCommand({
54
+ traceDir: options.traceDir,
55
+ traces: options.traces,
56
+ docs: options.docs,
57
+ dryRun: options.dryRun,
58
+ verbose: options.verbose,
59
+ });
60
+ } catch (error) {
61
+ console.error(chalk.red("Error:"), error.message);
62
+ process.exit(1);
63
+ }
64
+ });
65
+
66
+ // Status: View project status, sync jobs, and drift summary
67
+ program
68
+ .command("status")
69
+ .description("View project status, sync history, and drift summary")
70
+ .option("--jobs", "Show only sync job history")
71
+ .option("--drifts", "Show only drift queue")
72
+ .option("--config", "Show only configuration")
73
+ .option("--limit <n>", "Limit number of items shown", parseInt)
74
+ .option("--json", "Output as JSON")
75
+ .action(async (options) => {
76
+ try {
77
+ const statusCommand = require("./commands/status");
78
+ await statusCommand(options);
79
+ } catch (error) {
80
+ console.error(chalk.red("Error:"), error.message);
81
+ process.exit(1);
82
+ }
83
+ });
84
+
85
+ // Studio: Launch visual management UI
86
+ program
87
+ .command("studio")
88
+ .description("Launch Reshot Studio (visual management UI)")
89
+ .option("--port <port>", "Port for web UI", "4300")
90
+ .option("--host <host>", "Host for web UI", "127.0.0.1")
91
+ .option("--no-open", "Do not automatically open browser")
92
+ .action(async (options) => {
93
+ try {
94
+ const uiCommand = require("./commands/ui");
95
+ await uiCommand(options);
96
+ } catch (error) {
97
+ console.error(chalk.red("Error:"), error.message);
98
+ process.exit(1);
99
+ }
100
+ });
101
+
102
+ // Validate: Check configuration and documentation bindings
103
+ program
104
+ .command("validate")
105
+ .description("Validate configuration and documentation bindings")
106
+ .option("--strict", "Fail on warnings (zombie links, unbound files)")
107
+ .option("--fix", "Attempt to auto-fix issues where possible")
108
+ .option("-v, --verbose", "Show detailed validation output")
109
+ .action(async (options) => {
110
+ try {
111
+ const validateCommand = require("./commands/validate-docs");
112
+ if (typeof validateCommand.validateDocSync === "function") {
113
+ await validateCommand.validateDocSync(options);
114
+ } else {
115
+ await validateCommand.validateDocs(options);
116
+ }
117
+ } catch (error) {
118
+ console.error(chalk.red("Error:"), error.message);
119
+ process.exit(1);
120
+ }
121
+ });
122
+
123
+ // ============================================================================
124
+ // VISUAL CAPTURE COMMANDS
125
+ // ============================================================================
126
+
127
+ // Run: Execute scenarios from config (automated visual capture)
128
+ program
129
+ .command("run")
130
+ .description("Execute visual capture scenarios from config")
131
+ .option("-s, --scenarios <keys>", "Comma-separated list of scenario keys")
132
+ .option("--no-headless", "Run browser in visible mode")
133
+ .option("--variant <json>", "Override variant configuration as JSON")
134
+ .option("--all-variants", "Run all configured variant combinations")
135
+ .option("--no-variants", "Skip variant expansion")
136
+ .option(
137
+ "-f, --format <format>",
138
+ "Output format: step-by-step-images | summary-video",
139
+ )
140
+ .option(
141
+ "-c, --concurrency <n>",
142
+ "Number of parallel browser workers",
143
+ parseInt,
144
+ )
145
+ .option("--diff", "Enable baseline comparison")
146
+ .option("--no-diff", "Disable baseline comparison")
147
+ .option("--no-privacy", "Disable privacy masking")
148
+ .option("--no-style", "Disable style processing")
149
+ .option("--cloud", "Compare against cloud baselines")
150
+ .option("--debug", "Enable verbose debug logging")
151
+ .action(async (options) => {
152
+ if (options.debug) {
153
+ process.env.RESHOT_DEBUG = "1";
154
+ }
155
+ try {
156
+ const runCommand = require("./commands/run");
157
+ const scenarioKeys = options.scenarios
158
+ ? options.scenarios.split(",").map((s) => s.trim())
159
+ : null;
160
+ await runCommand({
161
+ scenarioKeys,
162
+ headless: options.headless,
163
+ variant: options.variant,
164
+ allVariants: options.allVariants,
165
+ noVariants: options.variants === false,
166
+ noPrivacy: options.privacy === false,
167
+ noStyle: options.style === false,
168
+ format: options.format,
169
+ diff: options.diff,
170
+ cloud: options.cloud,
171
+ concurrency: options.concurrency,
172
+ });
173
+ } catch (error) {
174
+ console.error(chalk.red("Error:"), error.message);
175
+ if (options.debug && error.stack) {
176
+ console.error(chalk.gray(error.stack));
177
+ }
178
+ process.exit(1);
179
+ }
180
+ });
181
+
182
+ // Record: Interactive visual recording from live browser
183
+ program
184
+ .command("record [title]")
185
+ .description("Interactively record visuals from a live browser session")
186
+ .option("--browser", "Launch Chrome with remote debugging before recording")
187
+ .option("-p, --port <port>", "Chrome debugging port (default: 9222)")
188
+ .option("--url <url>", "URL to open when launching browser")
189
+ .option("--debug", "Enable verbose debug logging")
190
+ .action(async (title, options) => {
191
+ if (options.debug) {
192
+ process.env.RESHOT_DEBUG = "1";
193
+ }
194
+ try {
195
+ // If --browser flag, launch Chrome first
196
+ if (options.browser) {
197
+ const chromeCommand = require("./commands/chrome");
198
+ await chromeCommand({
199
+ port: options.port || "9222",
200
+ url: options.url || "about:blank",
201
+ });
202
+ // Give Chrome time to start
203
+ await new Promise((resolve) => setTimeout(resolve, 2000));
204
+ }
205
+
206
+ const recordCommand = require("./commands/record");
207
+ await recordCommand(title);
208
+ } catch (error) {
209
+ console.error(chalk.red("Error:"), error.message);
210
+ if (options.debug && error.stack) {
211
+ console.error(chalk.gray(error.stack));
212
+ }
213
+ process.exit(1);
214
+ }
215
+ });
216
+
217
+ // Import tests: Import existing Playwright tests into Reshot
218
+ program
219
+ .command("import-tests")
220
+ .description("Import existing Playwright tests and create journey mappings")
221
+ .option("--dry-run", "Preview mappings without saving")
222
+ .option("--no-interactive", "Run without prompts")
223
+ .action(async (options) => {
224
+ try {
225
+ const importTestsCommand = require("./commands/import-tests");
226
+ await importTestsCommand({
227
+ dryRun: options.dryRun,
228
+ interactive: options.interactive,
229
+ });
230
+ } catch (error) {
231
+ console.error(chalk.red("Error:"), error.message);
232
+ process.exit(1);
233
+ }
234
+ });
235
+
236
+ // ============================================================================
237
+ // PUBLISHING & INTEGRATION COMMANDS
238
+ // ============================================================================
239
+
240
+ // Publish: Upload generated assets to platform with versioning
241
+ program
242
+ .command("publish")
243
+ .description("Publish visual assets to Reshot platform")
244
+ .option("--tag <tag>", "Version tag (e.g., v1.2, release-2024-01)")
245
+ .option("-m, --message <message>", "Commit message for this publish")
246
+ .option("--video <path>", "Explicit video file to upload with this publish")
247
+ .option("--dry-run", "Preview without uploading")
248
+ .option("-f, --force", "Skip confirmation prompts")
249
+ .option("--output-json", "Write structured result to .reshot/output/publish-result.json")
250
+ .action(async (options) => {
251
+ try {
252
+ const publishCommand = require("./commands/publish");
253
+ await publishCommand({
254
+ ...options,
255
+ outputJson: options.outputJson,
256
+ });
257
+ } catch (error) {
258
+ console.error(chalk.red("Error:"), error.message);
259
+ process.exit(1);
260
+ }
261
+ });
262
+
263
+ // Pull: Generate asset map for build pipelines
264
+ program
265
+ .command("pull")
266
+ .description("Pull asset map for your build pipeline")
267
+ .option("-f, --format <format>", "Output format: json, ts, csv", "json")
268
+ .option("-o, --output <path>", "Output file path")
269
+ .option("--full", "Include full metadata in TypeScript output")
270
+ .option("--status <status>", "Filter: approved, pending, all", "approved")
271
+ .action(async (options) => {
272
+ try {
273
+ const pullCommand = require("./commands/pull");
274
+ await pullCommand({
275
+ format: options.format,
276
+ output: options.output,
277
+ full: options.full,
278
+ status: options.status,
279
+ });
280
+ } catch (error) {
281
+ console.error(chalk.red("Error:"), error.message);
282
+ process.exit(1);
283
+ }
284
+ });
285
+
286
+ // CI: CI/CD integration commands
287
+ const ciCommand = program
288
+ .command("ci")
289
+ .description("CI/CD integration commands");
290
+
291
+ ciCommand
292
+ .command("setup")
293
+ .description("Interactive CI/CD setup wizard (GitHub Actions, etc.)")
294
+ .action(async () => {
295
+ try {
296
+ const ciSetup = require("./commands/ci-setup");
297
+ await ciSetup();
298
+ } catch (error) {
299
+ console.error(chalk.red("Error:"), error.message);
300
+ process.exit(1);
301
+ }
302
+ });
303
+
304
+ ciCommand
305
+ .command("run")
306
+ .description("Run capture + publish in one step (CI-optimized)")
307
+ .option("-c, --config <path>", "Path to docsync.config.json")
308
+ .option("--tag <tag>", "Version tag for publish")
309
+ .option("-m, --message <message>", "Commit message for publish")
310
+ .option("--dry-run", "Preview without uploading")
311
+ .option("--no-publish", "Run capture only, skip publish")
312
+ .action(async (options) => {
313
+ try {
314
+ const ciRun = require("./commands/ci-run");
315
+ await ciRun(options);
316
+ } catch (error) {
317
+ console.error(chalk.red("Error:"), error.message);
318
+ process.exit(1);
319
+ }
320
+ });
321
+
322
+ // ============================================================================
323
+ // DRIFT MANAGEMENT COMMANDS
324
+ // ============================================================================
325
+
326
+ // Drifts: View and manage documentation drifts
327
+ program
328
+ .command("drifts [action] [id]")
329
+ .description("View and manage documentation drifts")
330
+ .addHelpText(
331
+ "after",
332
+ `
333
+ Actions:
334
+ list List all drifts (default)
335
+ show <id> Show drift details
336
+ approve <id> Approve a drift
337
+ reject <id> Reject a drift
338
+ ignore <id> Mark drift as ignored
339
+ sync <id> Mark as manually synced (external_host)
340
+ approve-all Approve all pending drifts
341
+ reject-all Reject all pending drifts
342
+ validate Validate journey bindings
343
+ `,
344
+ )
345
+ .option("--status <status>", "Filter: PENDING, APPROVED, REJECTED, IGNORED")
346
+ .option("--journey <key>", "Filter by journey key")
347
+ .option("-v, --verbose", "Show detailed information")
348
+ .action(async (action, id, options) => {
349
+ try {
350
+ const driftsCommand = require("./commands/drifts");
351
+ // Map action/id to the expected subcommand/args format
352
+ const subcommand = action || "list";
353
+ const args = id ? [id] : [];
354
+ await driftsCommand(subcommand, args, options);
355
+ } catch (error) {
356
+ console.error(chalk.red("Error:"), error.message);
357
+ process.exit(1);
358
+ }
359
+ });
360
+
361
+ // ============================================================================
362
+ // UTILITY COMMANDS (Hidden from main help, but available)
363
+ // ============================================================================
364
+
365
+ // Auth: Standalone authentication (for re-auth scenarios)
366
+ program
367
+ .command("auth", { hidden: true })
368
+ .description("Authenticate with Reshot Cloud")
369
+ .action(async () => {
370
+ try {
371
+ const authCommand = require("./commands/auth");
372
+ await authCommand();
373
+ } catch (error) {
374
+ console.error(chalk.red("Error:"), error.message);
375
+ process.exit(1);
376
+ }
377
+ });
378
+
379
+ // Init: Standalone initialization (for manual config)
380
+ program
381
+ .command("init", { hidden: true })
382
+ .description("Initialize Reshot configuration")
383
+ .action(async () => {
384
+ try {
385
+ const initCommand = require("./commands/init");
386
+ await initCommand();
387
+ } catch (error) {
388
+ console.error(chalk.red("Error:"), error.message);
389
+ process.exit(1);
390
+ }
391
+ });
392
+
393
+ // Chrome: Launch Chrome with debugging (absorbed into record --browser)
394
+ program
395
+ .command("chrome", { hidden: true })
396
+ .description("Launch Chrome with remote debugging")
397
+ .option("-p, --port <port>", "Remote debugging port", "9222")
398
+ .option("--url <url>", "URL to open after launch", "about:blank")
399
+ .action(async (options) => {
400
+ try {
401
+ const chromeCommand = require("./commands/chrome");
402
+ await chromeCommand(options);
403
+ } catch (error) {
404
+ console.error(chalk.red("Error:"), error.message);
405
+ process.exit(1);
406
+ }
407
+ });
408
+
409
+ // Ingest: Alias for sync (backward compatibility)
410
+ program
411
+ .command("ingest", { hidden: true })
412
+ .description("Upload traces and docs (alias for sync)")
413
+ .option("--trace-dir <path>", "Path to test-results directory")
414
+ .option("--dry-run", "Preview what would be synced")
415
+ .action(async (options) => {
416
+ console.log(
417
+ chalk.yellow("Note: 'ingest' is now 'sync'. Running sync...\n"),
418
+ );
419
+ try {
420
+ const syncCommand = require("./commands/sync");
421
+ await syncCommand({
422
+ traceDir: options.traceDir,
423
+ dryRun: options.dryRun,
424
+ });
425
+ } catch (error) {
426
+ console.error(chalk.red("Error:"), error.message);
427
+ process.exit(1);
428
+ }
429
+ });
430
+
431
+ // UI: Alias for studio (backward compatibility)
432
+ program
433
+ .command("ui", { hidden: true })
434
+ .description("Launch Reshot Studio (alias for studio)")
435
+ .option("--port <port>", "Port for web UI", "4300")
436
+ .option("--host <host>", "Host for web UI", "127.0.0.1")
437
+ .option("--no-open", "Do not automatically open browser")
438
+ .action(async (options) => {
439
+ try {
440
+ const uiCommand = require("./commands/ui");
441
+ await uiCommand(options);
442
+ } catch (error) {
443
+ console.error(chalk.red("Error:"), error.message);
444
+ process.exit(1);
445
+ }
446
+ });
447
+
448
+ // Init-docs: Alias hidden (merged into setup wizard)
449
+ program
450
+ .command("init-docs", { hidden: true })
451
+ .description("Initialize documentation sync (use setup instead)")
452
+ .action(async () => {
453
+ try {
454
+ const initDocsCommand = require("./commands/init-docs");
455
+ await initDocsCommand();
456
+ } catch (error) {
457
+ console.error(chalk.red("Error:"), error.message);
458
+ process.exit(1);
459
+ }
460
+ });
461
+
462
+ program.parse(process.argv);