afterbefore 0.2.9 → 0.2.11

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.
@@ -1,13 +1,80 @@
1
- // src/server/save.ts
2
- import { NextResponse } from "next/server";
3
- import { writeFile } from "fs/promises";
1
+ // src/server/config.ts
2
+ import { readFile, writeFile, mkdir } from "fs/promises";
4
3
  import { join } from "path";
5
4
  import { homedir } from "os";
5
+ import { NextResponse } from "next/server";
6
6
  import { execFile } from "child_process";
7
7
  import { promisify } from "util";
8
8
  var execFileAsync = promisify(execFile);
9
+ var CONFIG_DIR = join(process.cwd(), ".afterbefore");
10
+ var CONFIG_PATH = join(CONFIG_DIR, "config.json");
11
+ var DEFAULT_SAVE_DIR = join(homedir(), "Desktop");
12
+ async function readConfig() {
13
+ try {
14
+ const raw = await readFile(CONFIG_PATH, "utf-8");
15
+ const parsed = JSON.parse(raw);
16
+ return { saveDir: parsed.saveDir || DEFAULT_SAVE_DIR };
17
+ } catch {
18
+ return { saveDir: DEFAULT_SAVE_DIR };
19
+ }
20
+ }
21
+ async function writeConfig(config) {
22
+ await mkdir(CONFIG_DIR, { recursive: true });
23
+ await writeFile(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
24
+ }
25
+ async function getSaveDir() {
26
+ const config = await readConfig();
27
+ return config.saveDir;
28
+ }
29
+ async function handleGetConfig() {
30
+ const config = await readConfig();
31
+ return NextResponse.json(config);
32
+ }
33
+ async function handleSetConfig(req) {
34
+ let body;
35
+ try {
36
+ body = await req.json();
37
+ } catch {
38
+ return NextResponse.json({ error: "Invalid JSON" }, { status: 400 });
39
+ }
40
+ if (typeof body.saveDir !== "string" || body.saveDir.trim() === "") {
41
+ return NextResponse.json({ error: "Invalid saveDir" }, { status: 400 });
42
+ }
43
+ const config = { saveDir: body.saveDir.trim() };
44
+ await writeConfig(config);
45
+ return NextResponse.json(config);
46
+ }
47
+ async function handlePickFolder() {
48
+ if (process.platform !== "darwin") {
49
+ return NextResponse.json(
50
+ { error: "Folder picker is only supported on macOS" },
51
+ { status: 501 }
52
+ );
53
+ }
54
+ try {
55
+ const { stdout } = await execFileAsync("osascript", [
56
+ "-e",
57
+ 'POSIX path of (choose folder with prompt "Select screenshot save location")'
58
+ ]);
59
+ const folder = stdout.trim().replace(/\/$/, "");
60
+ if (!folder) {
61
+ return NextResponse.json({ cancelled: true });
62
+ }
63
+ return NextResponse.json({ folder });
64
+ } catch {
65
+ return NextResponse.json({ cancelled: true });
66
+ }
67
+ }
68
+
69
+ // src/server/save.ts
70
+ import { NextResponse as NextResponse2 } from "next/server";
71
+ import { writeFile as writeFile2 } from "fs/promises";
72
+ import { join as join2 } from "path";
73
+ import { execFile as execFile2 } from "child_process";
74
+ import { promisify as promisify2 } from "util";
75
+ var execFileAsync2 = promisify2(execFile2);
9
76
  async function getBranch() {
10
- const { stdout } = await execFileAsync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
77
+ const { stdout } = await execFileAsync2("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
11
78
  cwd: process.cwd()
12
79
  });
13
80
  return stdout.trim();
@@ -20,26 +87,26 @@ async function handleSave(req) {
20
87
  try {
21
88
  body = await req.json();
22
89
  } catch {
23
- return NextResponse.json(
90
+ return NextResponse2.json(
24
91
  { error: "Invalid JSON body" },
25
92
  { status: 400 }
26
93
  );
27
94
  }
28
95
  const { type, mode, image } = body;
29
96
  if (!VALID_TYPES.includes(type)) {
30
- return NextResponse.json(
97
+ return NextResponse2.json(
31
98
  { error: `Invalid type: must be "before" or "after"` },
32
99
  { status: 400 }
33
100
  );
34
101
  }
35
102
  if (!VALID_MODES.includes(mode)) {
36
- return NextResponse.json(
103
+ return NextResponse2.json(
37
104
  { error: `Invalid mode: must be "fullpage", "viewport", or "area"` },
38
105
  { status: 400 }
39
106
  );
40
107
  }
41
108
  if (typeof image !== "string" || !image.startsWith(DATA_URL_PREFIX)) {
42
- return NextResponse.json(
109
+ return NextResponse2.json(
43
110
  { error: "Invalid image: must be a data:image/png;base64 data URL" },
44
111
  { status: 400 }
45
112
  );
@@ -47,29 +114,29 @@ async function handleSave(req) {
47
114
  const base64 = image.slice(DATA_URL_PREFIX.length);
48
115
  const buffer = Buffer.from(base64, "base64");
49
116
  const branch = await getBranch();
117
+ const saveDir = await getSaveDir();
50
118
  const filename = `${branch}-${type}.png`;
51
- const filepath = join(homedir(), "Desktop", filename);
119
+ const filepath = join2(saveDir, filename);
52
120
  try {
53
- await writeFile(filepath, buffer);
121
+ await writeFile2(filepath, buffer);
54
122
  } catch (err) {
55
- return NextResponse.json(
123
+ return NextResponse2.json(
56
124
  { error: "Failed to write screenshot", detail: String(err) },
57
125
  { status: 500 }
58
126
  );
59
127
  }
60
- return NextResponse.json({ success: true, path: `~/Desktop/${filename}` });
128
+ return NextResponse2.json({ success: true, path: filepath });
61
129
  }
62
130
 
63
131
  // src/server/push.ts
64
- import { NextResponse as NextResponse2 } from "next/server";
65
- import { execFile as execFile2 } from "child_process";
66
- import { access, mkdir, copyFile } from "fs/promises";
67
- import { join as join2 } from "path";
68
- import { homedir as homedir2 } from "os";
69
- import { promisify as promisify2 } from "util";
70
- var execFileAsync2 = promisify2(execFile2);
132
+ import { NextResponse as NextResponse3 } from "next/server";
133
+ import { execFile as execFile3 } from "child_process";
134
+ import { access, mkdir as mkdir2, copyFile } from "fs/promises";
135
+ import { join as join3 } from "path";
136
+ import { promisify as promisify3 } from "util";
137
+ var execFileAsync3 = promisify3(execFile3);
71
138
  async function run(cmd, args) {
72
- return execFileAsync2(cmd, args, { cwd: process.cwd() });
139
+ return execFileAsync3(cmd, args, { cwd: process.cwd() });
73
140
  }
74
141
  async function ghAvailable() {
75
142
  try {
@@ -102,22 +169,22 @@ async function fileExists(path) {
102
169
  }
103
170
  async function handlePush(req) {
104
171
  if (!await ghAvailable()) {
105
- return NextResponse2.json(
172
+ return NextResponse3.json(
106
173
  { success: false, error: "GitHub CLI (gh) is not installed or not in PATH" },
107
174
  { status: 500 }
108
175
  );
109
176
  }
110
177
  const pr = await getPrInfo();
111
178
  if (!pr) {
112
- return NextResponse2.json(
179
+ return NextResponse3.json(
113
180
  { success: false, error: "No PR found for current branch" },
114
181
  { status: 404 }
115
182
  );
116
183
  }
117
- const desktop = join2(homedir2(), "Desktop");
184
+ const desktop = await getSaveDir();
118
185
  const branch = pr.headRefName;
119
- const beforePath = join2(desktop, `${branch}-before.png`);
120
- const afterPath = join2(desktop, `${branch}-after.png`);
186
+ const beforePath = join3(desktop, `${branch}-before.png`);
187
+ const afterPath = join3(desktop, `${branch}-after.png`);
121
188
  const [hasBefore, hasAfter] = await Promise.all([
122
189
  fileExists(beforePath),
123
190
  fileExists(afterPath)
@@ -127,20 +194,20 @@ async function handlePush(req) {
127
194
  !hasBefore && `${branch}-before.png`,
128
195
  !hasAfter && `${branch}-after.png`
129
196
  ].filter(Boolean);
130
- return NextResponse2.json(
197
+ return NextResponse3.json(
131
198
  { success: false, error: `Missing screenshots: ${missing.join(", ")}` },
132
199
  { status: 400 }
133
200
  );
134
201
  }
135
- const repoDir = join2(process.cwd(), ".afterbefore");
136
- const repoBefore = join2(repoDir, `${branch}-before.png`);
137
- const repoAfter = join2(repoDir, `${branch}-after.png`);
202
+ const repoDir = join3(process.cwd(), ".afterbefore");
203
+ const repoBefore = join3(repoDir, `${branch}-before.png`);
204
+ const repoAfter = join3(repoDir, `${branch}-after.png`);
138
205
  try {
139
- await mkdir(repoDir, { recursive: true });
206
+ await mkdir2(repoDir, { recursive: true });
140
207
  await copyFile(beforePath, repoBefore);
141
208
  await copyFile(afterPath, repoAfter);
142
209
  } catch (err) {
143
- return NextResponse2.json(
210
+ return NextResponse3.json(
144
211
  { success: false, error: "Failed to copy screenshots into repo", detail: String(err) },
145
212
  { status: 500 }
146
213
  );
@@ -155,7 +222,7 @@ async function handlePush(req) {
155
222
  } catch (err) {
156
223
  const msg = String(err);
157
224
  if (!msg.includes("nothing to commit")) {
158
- return NextResponse2.json(
225
+ return NextResponse3.json(
159
226
  { success: false, error: "Failed to commit screenshots", detail: msg },
160
227
  { status: 500 }
161
228
  );
@@ -164,7 +231,7 @@ async function handlePush(req) {
164
231
  try {
165
232
  await run("git", ["push"]);
166
233
  } catch (err) {
167
- return NextResponse2.json(
234
+ return NextResponse3.json(
168
235
  { success: false, error: "Failed to push to remote", detail: String(err) },
169
236
  { status: 500 }
170
237
  );
@@ -193,12 +260,12 @@ async function handlePush(req) {
193
260
  ]);
194
261
  commentUrl = stdout.trim() || void 0;
195
262
  } catch (err) {
196
- return NextResponse2.json(
263
+ return NextResponse3.json(
197
264
  { success: false, error: "Failed to post PR comment", detail: String(err) },
198
265
  { status: 500 }
199
266
  );
200
267
  }
201
- return NextResponse2.json({
268
+ return NextResponse3.json({
202
269
  success: true,
203
270
  prNumber: pr.number,
204
271
  prUrl: pr.url,
@@ -207,20 +274,21 @@ async function handlePush(req) {
207
274
  }
208
275
 
209
276
  // src/server/open.ts
210
- import { NextResponse as NextResponse3 } from "next/server";
211
- import { execFile as execFile3 } from "child_process";
212
- import { join as join3 } from "path";
213
- import { homedir as homedir3 } from "os";
277
+ import { NextResponse as NextResponse4 } from "next/server";
278
+ import { execFile as execFile4 } from "child_process";
214
279
  async function handleOpen(_req) {
215
- const desktop = join3(homedir3(), "Desktop");
280
+ const desktop = await getSaveDir();
216
281
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer" : "xdg-open";
217
- execFile3(cmd, [desktop]);
218
- return NextResponse3.json({ success: true });
282
+ execFile4(cmd, [desktop]);
283
+ return NextResponse4.json({ success: true });
219
284
  }
220
285
 
221
286
  export {
287
+ handleGetConfig,
288
+ handleSetConfig,
289
+ handlePickFolder,
222
290
  handleSave,
223
291
  handlePush,
224
292
  handleOpen
225
293
  };
226
- //# sourceMappingURL=chunk-A73KCX5G.js.map
294
+ //# sourceMappingURL=chunk-BFC2HVPX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server/config.ts","../src/server/save.ts","../src/server/push.ts","../src/server/open.ts"],"sourcesContent":["import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { NextRequest, NextResponse } from \"next/server\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execFileAsync = promisify(execFile);\n\ninterface Config {\n saveDir: string;\n}\n\nconst CONFIG_DIR = join(process.cwd(), \".afterbefore\");\nconst CONFIG_PATH = join(CONFIG_DIR, \"config.json\");\nconst DEFAULT_SAVE_DIR = join(homedir(), \"Desktop\");\n\nasync function readConfig(): Promise<Config> {\n try {\n const raw = await readFile(CONFIG_PATH, \"utf-8\");\n const parsed = JSON.parse(raw);\n return { saveDir: parsed.saveDir || DEFAULT_SAVE_DIR };\n } catch {\n return { saveDir: DEFAULT_SAVE_DIR };\n }\n}\n\nasync function writeConfig(config: Config): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n await writeFile(CONFIG_PATH, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nexport async function getSaveDir(): Promise<string> {\n const config = await readConfig();\n return config.saveDir;\n}\n\nexport async function handleGetConfig(): Promise<NextResponse> {\n const config = await readConfig();\n return NextResponse.json(config);\n}\n\nexport async function handleSetConfig(req: NextRequest): Promise<NextResponse> {\n let body: Partial<Config>;\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n if (typeof body.saveDir !== \"string\" || body.saveDir.trim() === \"\") {\n return NextResponse.json({ error: \"Invalid saveDir\" }, { status: 400 });\n }\n\n const config: Config = { saveDir: body.saveDir.trim() };\n await writeConfig(config);\n return NextResponse.json(config);\n}\n\nexport async function handlePickFolder(): Promise<NextResponse> {\n if (process.platform !== \"darwin\") {\n return NextResponse.json(\n { error: \"Folder picker is only supported on macOS\" },\n { status: 501 },\n );\n }\n\n try {\n const { stdout } = await execFileAsync(\"osascript\", [\n \"-e\",\n 'POSIX path of (choose folder with prompt \"Select screenshot save location\")',\n ]);\n const folder = stdout.trim().replace(/\\/$/, \"\");\n if (!folder) {\n return NextResponse.json({ cancelled: true });\n }\n return NextResponse.json({ folder });\n } catch {\n // User cancelled the dialog\n return NextResponse.json({ cancelled: true });\n }\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { getSaveDir } from \"./config\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function getBranch(): Promise<string> {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"], {\n cwd: process.cwd(),\n });\n return stdout.trim();\n}\n\nconst VALID_TYPES = [\"before\", \"after\"] as const;\ntype ScreenshotType = (typeof VALID_TYPES)[number];\n\nconst VALID_MODES = [\"fullpage\", \"viewport\", \"area\", \"component\"] as const;\n\nconst DATA_URL_PREFIX = \"data:image/png;base64,\";\n\ninterface SaveRequestBody {\n type: ScreenshotType;\n mode: string;\n image: string;\n}\n\nexport async function handleSave(req: NextRequest): Promise<NextResponse> {\n let body: SaveRequestBody;\n try {\n body = await req.json();\n } catch {\n return NextResponse.json(\n { error: \"Invalid JSON body\" },\n { status: 400 },\n );\n }\n\n const { type, mode, image } = body;\n\n if (!VALID_TYPES.includes(type as ScreenshotType)) {\n return NextResponse.json(\n { error: `Invalid type: must be \"before\" or \"after\"` },\n { status: 400 },\n );\n }\n\n if (!VALID_MODES.includes(mode as (typeof VALID_MODES)[number])) {\n return NextResponse.json(\n { error: `Invalid mode: must be \"fullpage\", \"viewport\", or \"area\"` },\n { status: 400 },\n );\n }\n\n if (typeof image !== \"string\" || !image.startsWith(DATA_URL_PREFIX)) {\n return NextResponse.json(\n { error: \"Invalid image: must be a data:image/png;base64 data URL\" },\n { status: 400 },\n );\n }\n\n const base64 = image.slice(DATA_URL_PREFIX.length);\n const buffer = Buffer.from(base64, \"base64\");\n\n const branch = await getBranch();\n const saveDir = await getSaveDir();\n const filename = `${branch}-${type}.png`;\n const filepath = join(saveDir, filename);\n\n try {\n await writeFile(filepath, buffer);\n } catch (err) {\n return NextResponse.json(\n { error: \"Failed to write screenshot\", detail: String(err) },\n { status: 500 },\n );\n }\n\n return NextResponse.json({ success: true, path: filepath });\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { execFile } from \"node:child_process\";\nimport { access, mkdir, copyFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { getSaveDir } from \"./config\";\n\nconst execFileAsync = promisify(execFile);\n\ninterface PrInfo {\n number: number;\n url: string;\n headRepository: { owner: { login: string }; name: string };\n headRefName: string;\n}\n\nasync function run(\n cmd: string,\n args: string[],\n): Promise<{ stdout: string; stderr: string }> {\n return execFileAsync(cmd, args, { cwd: process.cwd() });\n}\n\nasync function ghAvailable(): Promise<boolean> {\n try {\n await run(\"gh\", [\"--version\"]);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function getPrInfo(): Promise<PrInfo | null> {\n try {\n const { stdout } = await run(\"gh\", [\n \"pr\",\n \"view\",\n \"--json\",\n \"number,url,headRepository,headRefName\",\n ]);\n return JSON.parse(stdout) as PrInfo;\n } catch {\n return null;\n }\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function handlePush(req: NextRequest): Promise<NextResponse> {\n // 1. Check gh CLI availability\n if (!(await ghAvailable())) {\n return NextResponse.json(\n { success: false, error: \"GitHub CLI (gh) is not installed or not in PATH\" },\n { status: 500 },\n );\n }\n\n // 2. Check for active PR\n const pr = await getPrInfo();\n if (!pr) {\n return NextResponse.json(\n { success: false, error: \"No PR found for current branch\" },\n { status: 404 },\n );\n }\n\n // 3. Check that screenshot files exist in save directory\n const desktop = await getSaveDir();\n const branch = pr.headRefName;\n const beforePath = join(desktop, `${branch}-before.png`);\n const afterPath = join(desktop, `${branch}-after.png`);\n\n const [hasBefore, hasAfter] = await Promise.all([\n fileExists(beforePath),\n fileExists(afterPath),\n ]);\n\n if (!hasBefore || !hasAfter) {\n const missing = [\n !hasBefore && `${branch}-before.png`,\n !hasAfter && `${branch}-after.png`,\n ].filter(Boolean);\n return NextResponse.json(\n { success: false, error: `Missing screenshots: ${missing.join(\", \")}` },\n { status: 400 },\n );\n }\n\n // 4. Copy from Desktop into repo, stage, commit, and push\n const repoDir = join(process.cwd(), \".afterbefore\");\n const repoBefore = join(repoDir, `${branch}-before.png`);\n const repoAfter = join(repoDir, `${branch}-after.png`);\n\n try {\n await mkdir(repoDir, { recursive: true });\n await copyFile(beforePath, repoBefore);\n await copyFile(afterPath, repoAfter);\n } catch (err) {\n return NextResponse.json(\n { success: false, error: \"Failed to copy screenshots into repo\", detail: String(err) },\n { status: 500 },\n );\n }\n\n try {\n await run(\"git\", [\"add\", repoBefore, repoAfter]);\n await run(\"git\", [\n \"commit\",\n \"-m\",\n \"chore: add before/after screenshots\",\n ]);\n } catch (err) {\n // Commit may fail if files are already committed with no changes.\n // That's fine -- we still want to push and comment.\n const msg = String(err);\n if (!msg.includes(\"nothing to commit\")) {\n return NextResponse.json(\n { success: false, error: \"Failed to commit screenshots\", detail: msg },\n { status: 500 },\n );\n }\n }\n\n try {\n await run(\"git\", [\"push\"]);\n } catch (err) {\n return NextResponse.json(\n { success: false, error: \"Failed to push to remote\", detail: String(err) },\n { status: 500 },\n );\n }\n\n // 5. Build raw GitHub URLs for the images\n const owner = pr.headRepository.owner.login;\n const repo = pr.headRepository.name;\n const rawBase = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}`;\n\n const beforeUrl = `${rawBase}/.afterbefore/${branch}-before.png`;\n const afterUrl = `${rawBase}/.afterbefore/${branch}-after.png`;\n\n // Cache-bust with timestamp so GitHub doesn't serve stale images\n const ts = Date.now();\n const commentBody = [\n \"## Before / After\",\n \"\",\n \"| Before | After |\",\n \"|--------|-------|\",\n `| ![before](${beforeUrl}?t=${ts}) | ![after](${afterUrl}?t=${ts}) |`,\n ].join(\"\\n\");\n\n // 6. Post PR comment\n let commentUrl: string | undefined;\n try {\n const { stdout } = await run(\"gh\", [\n \"pr\",\n \"comment\",\n String(pr.number),\n \"--body\",\n commentBody,\n ]);\n // gh pr comment prints the comment URL to stdout\n commentUrl = stdout.trim() || undefined;\n } catch (err) {\n return NextResponse.json(\n { success: false, error: \"Failed to post PR comment\", detail: String(err) },\n { status: 500 },\n );\n }\n\n return NextResponse.json({\n success: true,\n prNumber: pr.number,\n prUrl: pr.url,\n commentUrl,\n });\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { execFile } from \"node:child_process\";\nimport { getSaveDir } from \"./config\";\n\nexport async function handleOpen(_req: NextRequest): Promise<NextResponse> {\n const desktop = await getSaveDir();\n\n const cmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"explorer\"\n : \"xdg-open\";\n\n execFile(cmd, [desktop]);\n\n return NextResponse.json({ success: true });\n}\n"],"mappings":"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","names":["NextResponse","writeFile","join","execFile","promisify","execFileAsync","promisify","execFile","NextResponse","join","writeFile","NextResponse","execFile","mkdir","join","promisify","execFileAsync","promisify","execFile","NextResponse","join","mkdir","NextResponse","execFile","execFile","NextResponse"]}