@@ -60835,7 +60835,7 @@ var require_dist_node14 = __commonJS({
6083560835// src/index.ts
6083660836var core = __toESM(require_core());
6083760837var github = __toESM(require_github());
60838- var import_node_child_process2 = require("node:child_process");
60838+ var import_node_child_process3 = require("node:child_process");
6083960839
6084060840// ../../node_modules/.pnpm/@anthropic-ai+sdk@0.24.3/node_modules/@anthropic-ai/sdk/error.mjs
6084160841var error_exports = {};
@@ -65516,15 +65516,67 @@ async function generateDemoScript(client, analysis, rawDiff, baseUrl, config, ge
6551665516}
6551765517
6551865518// ../core/dist/recorder/playwright-runner.js
65519+ var import_node_fs3 = require("node:fs");
65520+ var import_node_path2 = require("node:path");
65521+
65522+ // ../core/dist/recorder/ensure-playwright.js
6551965523var import_node_fs2 = require("node:fs");
6552065524var import_node_path = require("node:path");
65525+ var import_node_os = require("node:os");
65526+ var import_node_child_process = require("node:child_process");
6552165527var import_node_module = require("node:module");
65528+ async function ensurePlaywright() {
65529+ try {
65530+ const req2 = (0, import_node_module.createRequire)((0, import_node_path.join)(process.cwd(), "package.json"));
65531+ return req2("@playwright/test");
65532+ } catch {
65533+ }
65534+ const installDir = resolveInstallDir();
65535+ const playwrightPkgPath = (0, import_node_path.join)(installDir, "node_modules", "@playwright", "test", "package.json");
65536+ if (!(0, import_node_fs2.existsSync)(playwrightPkgPath)) {
65537+ console.info("[git-glimpse] @playwright/test not found in consumer project. Installing...");
65538+ console.info(`[git-glimpse] Install directory: ${installDir}`);
65539+ (0, import_node_child_process.execFileSync)("npm", ["install", "--prefix", installDir, "--no-save", "@playwright/test"], {
65540+ stdio: "inherit"
65541+ });
65542+ console.info("[git-glimpse] @playwright/test installed successfully.");
65543+ }
65544+ const req = (0, import_node_module.createRequire)((0, import_node_path.join)(installDir, "package.json"));
65545+ const pw = req("@playwright/test");
65546+ await ensureChromium(installDir);
65547+ return pw;
65548+ }
65549+ function resolveInstallDir() {
65550+ try {
65551+ const dir = (0, import_node_path.join)((0, import_node_os.homedir)(), ".cache", "git-glimpse", "playwright");
65552+ return dir;
65553+ } catch {
65554+ return (0, import_node_path.join)((0, import_node_os.tmpdir)(), "git-glimpse-playwright");
65555+ }
65556+ }
65557+ async function ensureChromium(installDir) {
65558+ const msPlaywrightCache = (0, import_node_path.join)((0, import_node_os.homedir)(), ".cache", "ms-playwright");
65559+ if ((0, import_node_fs2.existsSync)(msPlaywrightCache)) {
65560+ const entries = await import("node:fs").then((fs2) => fs2.readdirSync(msPlaywrightCache).filter((e2) => e2.startsWith("chromium")));
65561+ if (entries.length > 0) {
65562+ return;
65563+ }
65564+ }
65565+ console.info("[git-glimpse] Installing Playwright Chromium browser...");
65566+ const playwrightCli = (0, import_node_path.join)(installDir, "node_modules", ".bin", "playwright");
65567+ (0, import_node_child_process.execFileSync)(playwrightCli, ["install", "chromium", "--with-deps"], {
65568+ stdio: "inherit"
65569+ });
65570+ console.info("[git-glimpse] Chromium installed.");
65571+ }
65572+
65573+ // ../core/dist/recorder/playwright-runner.js
6552265574async function runScriptAndRecord(options) {
6552365575 const { script, baseUrl, recording, outputDir } = options;
65524- if (!(0, import_node_fs2 .existsSync)(outputDir)) {
65525- (0, import_node_fs2 .mkdirSync)(outputDir, { recursive: true });
65576+ if (!(0, import_node_fs3 .existsSync)(outputDir)) {
65577+ (0, import_node_fs3 .mkdirSync)(outputDir, { recursive: true });
6552665578 }
65527- const { chromium } = (0, import_node_module.createRequire)((0, import_node_path.join)(process.cwd(), "package.json"))("@playwright/test" );
65579+ const { chromium } = await ensurePlaywright( );
6552865580 const browser = await chromium.launch({ headless: true });
6552965581 const startTime = Date.now();
6553065582 try {
@@ -65617,11 +65669,11 @@ function buildMouseClickOverlayEvalScript() {
6561765669}
6561865670async function executeScript(script, page, _baseUrl) {
6561965671 const { writeFileSync: writeFileSync2, unlinkSync: unlinkSync2 } = await import("node:fs");
65620- const { tmpdir } = await import("node:os");
65672+ const { tmpdir: tmpdir2 } = await import("node:os");
6562165673 const { pathToFileURL: pathToFileURL2 } = await import("node:url");
6562265674 const { transform } = await Promise.resolve().then(() => __toESM(require_dist2(), 1));
6562365675 const { code } = transform(script, { transforms: ["typescript"] });
65624- const tmpPath = (0, import_node_path .join)(tmpdir (), `git-glimpse-script-${Date.now()}.mjs`);
65676+ const tmpPath = (0, import_node_path2 .join)(tmpdir2 (), `git-glimpse-script-${Date.now()}.mjs`);
6562565677 writeFileSync2(tmpPath, code, "utf-8");
6562665678 try {
6562765679 const mod = await import(pathToFileURL2(tmpPath).href);
@@ -65635,23 +65687,23 @@ async function executeScript(script, page, _baseUrl) {
6563565687}
6563665688async function resolveVideoPath(outputDir) {
6563765689 const { readdirSync: readdirSync2, statSync: statSync3 } = await import("node:fs");
65638- const files = readdirSync2(outputDir).filter((f2) => f2.endsWith(".webm")).map((f2) => ({ name: f2, mtime: statSync3((0, import_node_path .join)(outputDir, f2)).mtimeMs })).sort((a2, b2) => b2.mtime - a2.mtime);
65690+ const files = readdirSync2(outputDir).filter((f2) => f2.endsWith(".webm")).map((f2) => ({ name: f2, mtime: statSync3((0, import_node_path2 .join)(outputDir, f2)).mtimeMs })).sort((a2, b2) => b2.mtime - a2.mtime);
6563965691 const latest = files[0];
6564065692 if (!latest)
6564165693 throw new Error(`No video file found in ${outputDir}`);
65642- return (0, import_node_path .join)(outputDir, latest.name);
65694+ return (0, import_node_path2 .join)(outputDir, latest.name);
6564365695}
6564465696
6564565697// ../core/dist/recorder/post-processor.js
65646- var import_node_child_process = require("node:child_process");
65647- var import_node_fs3 = require("node:fs");
65648- var import_node_path2 = require("node:path");
65649- var import_node_os = __toESM(require("node:os"), 1);
65698+ var import_node_child_process2 = require("node:child_process");
65699+ var import_node_fs4 = require("node:fs");
65700+ var import_node_path3 = require("node:path");
65701+ var import_node_os2 = __toESM(require("node:os"), 1);
6565065702async function postProcess(options) {
6565165703 const { inputPath, outputDir, format } = options;
6565265704 const ffmpegPath = resolveFfmpegPath();
65653- const outputName = (0, import_node_path2 .basename)(inputPath, ".webm") + "." + format;
65654- const outputPath = (0, import_node_path2 .join)(outputDir, outputName);
65705+ const outputName = (0, import_node_path3 .basename)(inputPath, ".webm") + "." + format;
65706+ const outputPath = (0, import_node_path3 .join)(outputDir, outputName);
6565565707 if (format === "gif") {
6565665708 await convertToGif(ffmpegPath, inputPath, outputPath, options.viewport);
6565765709 } else if (format === "mp4") {
@@ -65665,7 +65717,7 @@ async function postProcess(options) {
6566565717async function convertToGif(ffmpegPath, input, output, viewport) {
6566665718 const targetWidth = Math.min(viewport.width / 2, 960);
6566765719 const palettePath = output.replace(".gif", "-palette.png");
65668- (0, import_node_child_process .execFileSync)(ffmpegPath, [
65720+ (0, import_node_child_process2 .execFileSync)(ffmpegPath, [
6566965721 "-i",
6567065722 input,
6567165723 "-vf",
@@ -65675,7 +65727,7 @@ async function convertToGif(ffmpegPath, input, output, viewport) {
6567565727 "-y",
6567665728 palettePath
6567765729 ]);
65678- (0, import_node_child_process .execFileSync)(ffmpegPath, [
65730+ (0, import_node_child_process2 .execFileSync)(ffmpegPath, [
6567965731 "-i",
6568065732 input,
6568165733 "-i",
@@ -65688,11 +65740,11 @@ async function convertToGif(ffmpegPath, input, output, viewport) {
6568865740 output
6568965741 ]);
6569065742 const { unlinkSync: unlinkSync2 } = await import("node:fs");
65691- if ((0, import_node_fs3 .existsSync)(palettePath))
65743+ if ((0, import_node_fs4 .existsSync)(palettePath))
6569265744 unlinkSync2(palettePath);
6569365745}
6569465746async function convertToMp4(ffmpegPath, input, output) {
65695- (0, import_node_child_process .execFileSync)(ffmpegPath, [
65747+ (0, import_node_child_process2 .execFileSync)(ffmpegPath, [
6569665748 "-i",
6569765749 input,
6569865750 "-c:v",
@@ -65710,7 +65762,7 @@ async function convertToMp4(ffmpegPath, input, output) {
6571065762 ]);
6571165763}
6571265764async function trimWebm(ffmpegPath, input, output) {
65713- (0, import_node_child_process .execFileSync)(ffmpegPath, [
65765+ (0, import_node_child_process2 .execFileSync)(ffmpegPath, [
6571465766 "-i",
6571565767 input,
6571665768 "-c",
@@ -65726,7 +65778,7 @@ async function getFileSizeMB(filePath) {
6572665778}
6572765779function resolveFfmpegPath() {
6572865780 try {
65729- (0, import_node_child_process .execFileSync)("ffmpeg", ["-version"], { stdio: "ignore" });
65781+ (0, import_node_child_process2 .execFileSync)("ffmpeg", ["-version"], { stdio: "ignore" });
6573065782 return "ffmpeg";
6573165783 } catch {
6573265784 }
@@ -65742,45 +65794,44 @@ function findPlaywrightCacheDir() {
6574265794 const envPath = process.env["PLAYWRIGHT_BROWSERS_PATH"];
6574365795 if (envPath && envPath !== "0")
6574465796 return envPath;
65745- const home = import_node_os .default.homedir();
65797+ const home = import_node_os2 .default.homedir();
6574665798 if (process.platform === "linux") {
6574765799 const xdgCache = process.env["XDG_CACHE_HOME"];
65748- return xdgCache ? (0, import_node_path2 .join)(xdgCache, "ms-playwright") : (0, import_node_path2 .join)(home, ".cache", "ms-playwright");
65800+ return xdgCache ? (0, import_node_path3 .join)(xdgCache, "ms-playwright") : (0, import_node_path3 .join)(home, ".cache", "ms-playwright");
6574965801 }
6575065802 if (process.platform === "darwin") {
65751- return (0, import_node_path2 .join)(home, "Library", "Caches", "ms-playwright");
65803+ return (0, import_node_path3 .join)(home, "Library", "Caches", "ms-playwright");
6575265804 }
6575365805 if (process.platform === "win32") {
65754- const localAppData = process.env["LOCALAPPDATA"] ?? (0, import_node_path2 .join)(home, "AppData", "Local");
65755- return (0, import_node_path2 .join)(localAppData, "ms-playwright");
65806+ const localAppData = process.env["LOCALAPPDATA"] ?? (0, import_node_path3 .join)(home, "AppData", "Local");
65807+ return (0, import_node_path3 .join)(localAppData, "ms-playwright");
6575665808 }
6575765809 return null;
6575865810}
6575965811function scanForFfmpeg(cacheDir) {
65760- if (!(0, import_node_fs3 .existsSync)(cacheDir))
65812+ if (!(0, import_node_fs4 .existsSync)(cacheDir))
6576165813 return null;
65762- const entries = (0, import_node_fs3 .readdirSync)(cacheDir);
65814+ const entries = (0, import_node_fs4 .readdirSync)(cacheDir);
6576365815 const ffmpegDir = entries.find((e2) => e2.startsWith("ffmpeg"));
6576465816 if (!ffmpegDir)
6576565817 return null;
65766- const dir = (0, import_node_path2 .join)(cacheDir, ffmpegDir);
65818+ const dir = (0, import_node_path3 .join)(cacheDir, ffmpegDir);
6576765819 for (const name of ["ffmpeg-linux", "ffmpeg-mac", "ffmpeg-win64.exe", "ffmpeg"]) {
65768- const candidate = (0, import_node_path2 .join)(dir, name);
65769- if ((0, import_node_fs3 .existsSync)(candidate))
65820+ const candidate = (0, import_node_path3 .join)(dir, name);
65821+ if ((0, import_node_fs4 .existsSync)(candidate))
6577065822 return candidate;
6577165823 }
6577265824 return null;
6577365825}
6577465826
6577565827// ../core/dist/recorder/fallback.js
65776- var import_node_fs4 = require("node:fs");
65777- var import_node_path3 = require("node:path");
65778- var import_node_module2 = require("node:module");
65828+ var import_node_fs5 = require("node:fs");
65829+ var import_node_path4 = require("node:path");
6577965830async function takeScreenshots(baseUrl, routes, recording, outputDir) {
65780- if (!(0, import_node_fs4 .existsSync)(outputDir)) {
65781- (0, import_node_fs4 .mkdirSync)(outputDir, { recursive: true });
65831+ if (!(0, import_node_fs5 .existsSync)(outputDir)) {
65832+ (0, import_node_fs5 .mkdirSync)(outputDir, { recursive: true });
6578265833 }
65783- const { chromium } = (0, import_node_module2.createRequire)((0, import_node_path3.join)(process.cwd(), "package.json"))("@playwright/test" );
65834+ const { chromium } = await ensurePlaywright( );
6578465835 const browser = await chromium.launch({ headless: true });
6578565836 const screenshots = [];
6578665837 try {
@@ -65795,7 +65846,7 @@ async function takeScreenshots(baseUrl, routes, recording, outputDir) {
6579565846 await page.goto(url);
6579665847 await page.waitForLoadState("networkidle");
6579765848 await page.waitForTimeout(1e3);
65798- const screenshotPath = (0, import_node_path3 .join)(outputDir, `screenshot-${sanitizeRoute(route.route)}.png`);
65849+ const screenshotPath = (0, import_node_path4 .join)(outputDir, `screenshot-${sanitizeRoute(route.route)}.png`);
6579965850 await page.screenshot({ path: screenshotPath, fullPage: false });
6580065851 screenshots.push(screenshotPath);
6580165852 }
@@ -65894,8 +65945,8 @@ async function runPipeline(options) {
6589465945
6589565946// ../core/dist/config/loader.js
6589665947var import_node_url = require("node:url");
65897- var import_node_fs5 = require("node:fs");
65898- var import_node_path4 = require("node:path");
65948+ var import_node_fs6 = require("node:fs");
65949+ var import_node_path5 = require("node:path");
6589965950
6590065951// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
6590165952var external_exports = {};
@@ -70003,30 +70054,30 @@ var DEFAULT_TRIGGER = {
7000370054
7000470055// ../core/dist/config/loader.js
7000570056async function importConfigFile(filePath) {
70006- if ((0, import_node_path4 .extname)(filePath) !== ".ts") {
70057+ if ((0, import_node_path5 .extname)(filePath) !== ".ts") {
7000770058 const mod = await import((0, import_node_url.pathToFileURL)(filePath).href);
7000870059 return mod.default ?? mod;
7000970060 }
7001070061 const { transform } = await Promise.resolve().then(() => __toESM(require_dist2(), 1));
70011- const source = (0, import_node_fs5 .readFileSync)(filePath, "utf-8");
70062+ const source = (0, import_node_fs6 .readFileSync)(filePath, "utf-8");
7001270063 const { code } = transform(source, { transforms: ["typescript"] });
70013- const tmpFile = (0, import_node_path4 .resolve)((0, import_node_path4 .dirname)(filePath), `.git-glimpse-config-${Date.now()}.mjs`);
70064+ const tmpFile = (0, import_node_path5 .resolve)((0, import_node_path5 .dirname)(filePath), `.git-glimpse-config-${Date.now()}.mjs`);
7001470065 try {
70015- (0, import_node_fs5 .writeFileSync)(tmpFile, code);
70066+ (0, import_node_fs6 .writeFileSync)(tmpFile, code);
7001670067 const mod = await import((0, import_node_url.pathToFileURL)(tmpFile).href);
7001770068 return mod.default ?? mod;
7001870069 } finally {
7001970070 try {
70020- (0, import_node_fs5 .unlinkSync)(tmpFile);
70071+ (0, import_node_fs6 .unlinkSync)(tmpFile);
7002170072 } catch {
7002270073 }
7002370074 }
7002470075}
7002570076async function loadConfig(configPath) {
7002670077 const candidates = configPath ? [configPath] : ["git-glimpse.config.ts", "git-glimpse.config.js", "git-glimpse.config.mjs"];
7002770078 for (const candidate of candidates) {
70028- const fullPath = (0, import_node_path4 .resolve)(process.cwd(), candidate);
70029- if ((0, import_node_fs5 .existsSync)(fullPath)) {
70079+ const fullPath = (0, import_node_path5 .resolve)(process.cwd(), candidate);
70080+ if ((0, import_node_fs6 .existsSync)(fullPath)) {
7003070081 const raw = await importConfigFile(fullPath);
7003170082 return parseConfig(raw);
7003270083 }
@@ -70147,14 +70198,14 @@ ${script}
7014770198}
7014870199
7014970200// ../core/dist/publisher/storage.js
70150- var import_node_fs6 = require("node:fs");
70151- var import_node_path5 = require("node:path");
70201+ var import_node_fs7 = require("node:fs");
70202+ var import_node_path6 = require("node:path");
7015270203async function uploadToGitHubAssets(token, owner, repo, filePath) {
7015370204 const { Octokit: Octokit2 } = await Promise.resolve().then(() => __toESM(require_dist_node14(), 1));
7015470205 const octokit = new Octokit2({ auth: token });
70155- const fileBuffer = (0, import_node_fs6 .readFileSync)(filePath);
70156- const fileName = (0, import_node_path5 .basename)(filePath);
70157- const size = (0, import_node_fs6 .statSync)(filePath).size;
70206+ const fileBuffer = (0, import_node_fs7 .readFileSync)(filePath);
70207+ const fileName = (0, import_node_path6 .basename)(filePath);
70208+ const size = (0, import_node_fs7 .statSync)(filePath).size;
7015870209 const release = await octokit.rest.repos.createRelease({
7015970210 owner,
7016070211 repo,
@@ -70269,11 +70320,36 @@ function evaluateTrigger(opts) {
7026970320 };
7027070321}
7027170322
70323+ // src/resolve-base-url.ts
70324+ function resolveBaseUrl(config, previewUrlOverride) {
70325+ const previewUrl = previewUrlOverride ?? config.app.previewUrl;
70326+ if (previewUrl) {
70327+ const resolved = process.env[previewUrl];
70328+ if (resolved === void 0) {
70329+ if (previewUrl.startsWith("http")) return { url: previewUrl };
70330+ return {
70331+ error: `app.previewUrl is set to "${previewUrl}" but it doesn't look like a URL and no env var with that name was found. Set it to a full URL (e.g. "https://my-preview.vercel.app") or an env var name that is available in this workflow job.`
70332+ };
70333+ }
70334+ if (!resolved.startsWith("http")) {
70335+ return {
70336+ error: `Env var "${previewUrl}" was found but its value "${resolved}" is not a valid URL. Expected a value starting with "http".`
70337+ };
70338+ }
70339+ return { url: resolved };
70340+ }
70341+ if (config.app.readyWhen?.url) {
70342+ const u2 = new URL(config.app.readyWhen.url);
70343+ return { url: u2.origin };
70344+ }
70345+ return { url: "http://localhost:3000" };
70346+ }
70347+
7027270348// src/index.ts
7027370349function streamCommand(cmd, args) {
7027470350 return new Promise((resolve2, reject) => {
7027570351 const chunks = [];
70276- const proc = (0, import_node_child_process2 .spawn)(cmd, args, { shell: false });
70352+ const proc = (0, import_node_child_process3 .spawn)(cmd, args, { shell: false });
7027770353 proc.stdout.on("data", (chunk) => chunks.push(chunk));
7027870354 proc.stderr.on("data", (chunk) => chunks.push(chunk));
7027970355 proc.on("error", reject);
@@ -70385,17 +70461,16 @@ async function run() {
7038570461 core.setOutput("success", "false");
7038670462 return;
7038770463 }
70388- const baseUrl = resolveBaseUrl(config, previewUrlInput);
70389- if (!baseUrl) {
70390- core.setFailed(
70391- "No base URL available. Set app.previewUrl or app.startCommand + app.readyWhen in config."
70392- );
70464+ const baseUrlResult = resolveBaseUrl(config, previewUrlInput);
70465+ if (!baseUrlResult.url) {
70466+ core.setFailed(baseUrlResult.error);
7039370467 return;
7039470468 }
70469+ const baseUrl = baseUrlResult.url;
7039570470 if (config.setup) {
7039670471 core.info(`Running setup: ${config.setup}`);
7039770472 const parts = config.setup.split(" ");
70398- (0, import_node_child_process2 .execFileSync)(parts[0], parts.slice(1), { stdio: "inherit" });
70473+ (0, import_node_child_process3 .execFileSync)(parts[0], parts.slice(1), { stdio: "inherit" });
7039970474 }
7040070475 let appProcess = null;
7040170476 if (config.app.startCommand && !config.app.previewUrl) {
@@ -70447,22 +70522,10 @@ ${result.errors.join("\n")}`);
7044770522 appProcess?.kill();
7044870523 }
7044970524}
70450- function resolveBaseUrl(config, previewUrlOverride) {
70451- const previewUrl = previewUrlOverride ?? config.app.previewUrl;
70452- if (previewUrl) {
70453- const resolved = process.env[previewUrl] ?? previewUrl;
70454- return resolved.startsWith("http") ? resolved : null;
70455- }
70456- if (config.app.readyWhen?.url) {
70457- const u2 = new URL(config.app.readyWhen.url);
70458- return u2.origin;
70459- }
70460- return "http://localhost:3000";
70461- }
7046270525async function startApp(startCommand, readyUrl) {
7046370526 const parts = startCommand.split(" ");
7046470527 core.info(`Starting app: ${startCommand}`);
70465- const proc = (0, import_node_child_process2 .spawn)(parts[0], parts.slice(1), { stdio: "inherit", shell: false });
70528+ const proc = (0, import_node_child_process3 .spawn)(parts[0], parts.slice(1), { stdio: "inherit", shell: false });
7046670529 await waitForUrl(readyUrl, 3e4);
7046770530 core.info("App is ready");
7046870531 return proc;
0 commit comments