git-shots-cli 0.5.6 → 0.6.1

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 (2) hide show
  1. package/dist/index.js +89 -4
  2. package/package.json +27 -27
package/dist/index.js CHANGED
@@ -503,7 +503,7 @@ async function syncFlows(config) {
503
503
  const listUrl = `${config.server}/api/projects/${config.project}/flows`;
504
504
  let existingFlows = [];
505
505
  try {
506
- const res = await fetch(listUrl, { headers: { Origin: config.server } });
506
+ const res = await fetch(listUrl, { headers: { Origin: config.server, ...authHeaders(config) } });
507
507
  if (res.ok) {
508
508
  const data = await res.json();
509
509
  existingFlows = data.flows ?? [];
@@ -517,7 +517,7 @@ async function syncFlows(config) {
517
517
  const patchUrl = `${config.server}/api/projects/${config.project}/flows/${flow.slug}`;
518
518
  const patchRes = await fetch(patchUrl, {
519
519
  method: "PATCH",
520
- headers: { "Content-Type": "application/json", Origin: config.server },
520
+ headers: { "Content-Type": "application/json", Origin: config.server, ...authHeaders(config) },
521
521
  body: JSON.stringify({
522
522
  name: flow.name,
523
523
  description: flow.description ?? null,
@@ -532,7 +532,7 @@ async function syncFlows(config) {
532
532
  const stepsUrl = `${config.server}/api/projects/${config.project}/flows/${flow.slug}/steps`;
533
533
  const stepsRes = await fetch(stepsUrl, {
534
534
  method: "PUT",
535
- headers: { "Content-Type": "application/json", Origin: config.server },
535
+ headers: { "Content-Type": "application/json", Origin: config.server, ...authHeaders(config) },
536
536
  body: JSON.stringify({ steps: flow.steps })
537
537
  });
538
538
  if (stepsRes.ok) {
@@ -545,7 +545,7 @@ async function syncFlows(config) {
545
545
  const createUrl = `${config.server}/api/projects/${config.project}/flows`;
546
546
  const res = await fetch(createUrl, {
547
547
  method: "POST",
548
- headers: { "Content-Type": "application/json", Origin: config.server },
548
+ headers: { "Content-Type": "application/json", Origin: config.server, ...authHeaders(config) },
549
549
  body: JSON.stringify({
550
550
  slug: flow.slug,
551
551
  name: flow.name,
@@ -565,6 +565,77 @@ async function syncFlows(config) {
565
565
  console.log(chalk8.green("Flows synced."));
566
566
  }
567
567
 
568
+ // src/rename.ts
569
+ import chalk9 from "chalk";
570
+ async function rename(config, oldSlug, newSlug, options) {
571
+ console.log(chalk9.dim(`Project: ${config.project}`));
572
+ console.log(chalk9.dim(`Rename: ${oldSlug} \u2192 ${newSlug}`));
573
+ if (options.category !== void 0) {
574
+ console.log(chalk9.dim(`Category: ${options.category ?? "(none)"}`));
575
+ }
576
+ console.log();
577
+ const projectUrl = `${config.server}/api/projects/${encodeURIComponent(config.project)}`;
578
+ const projectRes = await fetch(projectUrl, {
579
+ headers: { Origin: config.server, ...authHeaders(config) }
580
+ });
581
+ checkAuthError(projectRes);
582
+ if (!projectRes.ok) {
583
+ console.error(chalk9.red(`Failed to fetch project: ${projectRes.status}`));
584
+ process.exit(1);
585
+ }
586
+ const projectData = await projectRes.json();
587
+ const screensArr = projectData.screens;
588
+ if (!screensArr || screensArr.length === 0) {
589
+ console.error(chalk9.red("No screens found for this project."));
590
+ process.exit(1);
591
+ }
592
+ const matches = screensArr.filter((s) => {
593
+ if (s.slug !== oldSlug) return false;
594
+ if (options.platform && s.platform !== options.platform) return false;
595
+ return true;
596
+ });
597
+ if (matches.length === 0) {
598
+ console.error(chalk9.red(`Screen "${oldSlug}" not found.`));
599
+ const slugs = [...new Set(screensArr.map((s) => s.slug))].sort();
600
+ console.error(chalk9.dim(`Available screens: ${slugs.join(", ")}`));
601
+ process.exit(1);
602
+ }
603
+ if (matches.length > 1) {
604
+ console.error(
605
+ chalk9.red(
606
+ `Multiple screens match "${oldSlug}" (platforms: ${matches.map((m) => m.platform).join(", ")}). Use --platform to disambiguate.`
607
+ )
608
+ );
609
+ process.exit(1);
610
+ }
611
+ const screen = matches[0];
612
+ const body = { slug: newSlug };
613
+ if (options.category !== void 0) {
614
+ body.category = options.category;
615
+ }
616
+ const patchUrl = `${config.server}/api/screens/${screen.id}`;
617
+ console.log(chalk9.dim(`Renaming screen ${screen.id}...`));
618
+ const res = await fetch(patchUrl, {
619
+ method: "PATCH",
620
+ headers: {
621
+ "Content-Type": "application/json",
622
+ Origin: config.server,
623
+ ...authHeaders(config)
624
+ },
625
+ body: JSON.stringify(body)
626
+ });
627
+ checkAuthError(res);
628
+ const data = await res.json();
629
+ if (!res.ok) {
630
+ console.error(chalk9.red(`Rename failed: ${JSON.stringify(data)}`));
631
+ process.exit(1);
632
+ }
633
+ console.log(chalk9.green(`Renamed "${oldSlug}" \u2192 "${newSlug}"`));
634
+ if (options.category !== void 0) {
635
+ console.log(chalk9.green(`Category set to: ${options.category ?? "(none)"}`));
636
+ }
637
+ }
638
+
568
639
  // src/index.ts
569
640
  var require2 = createRequire(import.meta.url);
570
641
  var { version } = require2("../package.json");
@@ -637,6 +708,20 @@ program.command("review").description("Upload screenshots, create review session
637
708
  screens
638
709
  });
639
710
  });
711
+ program.command("rename <old-slug> <new-slug>").description("Rename a screen slug (moves R2 objects server-side)").option("-p, --project <slug>", "Project slug").option("-s, --server <url>", "Server URL").option("--platform <name>", "Platform to disambiguate (e.g., android, web)").option("--category <value>", "Set new category (use empty string to clear)").action(async (oldSlug, newSlug, options) => {
712
+ const config = loadConfig();
713
+ if (options.project) config.project = options.project;
714
+ if (options.server) config.server = options.server;
715
+ if (!config.project) {
716
+ console.error("Error: project slug required. Use --project or .git-shots.json");
717
+ process.exit(1);
718
+ }
719
+ const category = options.category === "" ? null : options.category;
720
+ await rename(config, oldSlug, newSlug, {
721
+ platform: options.platform,
722
+ category
723
+ });
724
+ });
640
725
  var hook = program.command("hook").description("Manage git hooks for automatic visual review");
641
726
  hook.command("install").description("Install a pre-push hook that runs git-shots review before each push").action(async () => {
642
727
  await hookInstall();
package/package.json CHANGED
@@ -1,27 +1,27 @@
1
- {
2
- "name": "git-shots-cli",
3
- "version": "0.5.6",
4
- "description": "CLI for git-shots visual regression platform",
5
- "type": "module",
6
- "bin": {
7
- "git-shots": "./dist/index.js"
8
- },
9
- "files": [
10
- "dist"
11
- ],
12
- "scripts": {
13
- "build": "tsup src/index.ts --format esm --dts",
14
- "dev": "tsup src/index.ts --format esm --watch"
15
- },
16
- "dependencies": {
17
- "commander": "^12.0.0",
18
- "chalk": "^5.3.0",
19
- "dotenv": "^16.4.0",
20
- "glob": "^11.0.0"
21
- },
22
- "devDependencies": {
23
- "tsup": "^8.0.0",
24
- "typescript": "^5.0.0",
25
- "@types/node": "^22.0.0"
26
- }
27
- }
1
+ {
2
+ "name": "git-shots-cli",
3
+ "version": "0.6.1",
4
+ "description": "CLI for git-shots visual regression platform",
5
+ "type": "module",
6
+ "bin": {
7
+ "git-shots": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsup src/index.ts --format esm --dts",
14
+ "dev": "tsup src/index.ts --format esm --watch"
15
+ },
16
+ "dependencies": {
17
+ "commander": "^12.0.0",
18
+ "chalk": "^5.3.0",
19
+ "dotenv": "^16.4.0",
20
+ "glob": "^11.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "tsup": "^8.0.0",
24
+ "typescript": "^5.0.0",
25
+ "@types/node": "^22.0.0"
26
+ }
27
+ }