@wasao/kagemusha 0.1.1 → 0.3.4
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 +168 -79
- package/dist/commands/add.d.ts +6 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +26 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/capture.d.ts +3 -2
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +256 -20
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/discover.d.ts +2 -0
- package/dist/commands/discover.d.ts.map +1 -0
- package/dist/commands/discover.js +62 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/edit.d.ts +1 -1
- package/dist/commands/edit.d.ts.map +1 -1
- package/dist/commands/edit.js +82 -26
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +240 -105
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +33 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +131 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/validate.js +1 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/editor/inject-script/annotations.d.ts +11 -0
- package/dist/editor/inject-script/annotations.d.ts.map +1 -0
- package/dist/editor/inject-script/annotations.js +409 -0
- package/dist/editor/inject-script/annotations.js.map +1 -0
- package/dist/editor/inject-script/bridge.d.ts +13 -0
- package/dist/editor/inject-script/bridge.d.ts.map +1 -0
- package/dist/editor/inject-script/bridge.js +33 -0
- package/dist/editor/inject-script/bridge.js.map +1 -0
- package/dist/editor/inject-script/crop.d.ts +9 -0
- package/dist/editor/inject-script/crop.d.ts.map +1 -0
- package/dist/editor/inject-script/crop.js +236 -0
- package/dist/editor/inject-script/crop.js.map +1 -0
- package/dist/editor/inject-script/dom.d.ts +7 -0
- package/dist/editor/inject-script/dom.d.ts.map +1 -0
- package/dist/editor/inject-script/dom.js +32 -0
- package/dist/editor/inject-script/dom.js.map +1 -0
- package/dist/editor/inject-script/index.d.ts +2 -0
- package/dist/editor/inject-script/index.d.ts.map +1 -0
- package/dist/editor/inject-script/index.js +56 -0
- package/dist/editor/inject-script/index.js.map +1 -0
- package/dist/editor/inject-script/record.d.ts +5 -0
- package/dist/editor/inject-script/record.d.ts.map +1 -0
- package/dist/editor/inject-script/record.js +398 -0
- package/dist/editor/inject-script/record.js.map +1 -0
- package/dist/editor/inject-script/selector.d.ts +6 -0
- package/dist/editor/inject-script/selector.d.ts.map +1 -0
- package/dist/editor/inject-script/selector.js +112 -0
- package/dist/editor/inject-script/selector.js.map +1 -0
- package/dist/editor/inject-script/state.d.ts +27 -0
- package/dist/editor/inject-script/state.d.ts.map +1 -0
- package/dist/editor/inject-script/state.js +26 -0
- package/dist/editor/inject-script/state.js.map +1 -0
- package/dist/editor/inject-script/svg.d.ts +7 -0
- package/dist/editor/inject-script/svg.d.ts.map +1 -0
- package/dist/editor/inject-script/svg.js +39 -0
- package/dist/editor/inject-script/svg.js.map +1 -0
- package/dist/editor/inject-script/toolbar.d.ts +14 -0
- package/dist/editor/inject-script/toolbar.d.ts.map +1 -0
- package/dist/editor/inject-script/toolbar.js +240 -0
- package/dist/editor/inject-script/toolbar.js.map +1 -0
- package/dist/editor/inject-script/types.d.ts +102 -0
- package/dist/editor/inject-script/types.d.ts.map +1 -0
- package/dist/editor/inject-script/types.js +5 -0
- package/dist/editor/inject-script/types.js.map +1 -0
- package/dist/editor/inject-script.js +1276 -353
- package/dist/index.js +34 -16
- package/dist/index.js.map +1 -1
- package/dist/lib/annotate.d.ts +2 -2
- package/dist/lib/annotate.d.ts.map +1 -1
- package/dist/lib/annotate.js +35 -43
- package/dist/lib/annotate.js.map +1 -1
- package/dist/lib/auth.d.ts +18 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +45 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/aws-error.d.ts +7 -0
- package/dist/lib/aws-error.d.ts.map +1 -0
- package/dist/lib/aws-error.js +74 -0
- package/dist/lib/aws-error.js.map +1 -0
- package/dist/lib/canonical.d.ts +54 -0
- package/dist/lib/canonical.d.ts.map +1 -0
- package/dist/lib/canonical.js +152 -0
- package/dist/lib/canonical.js.map +1 -0
- package/dist/lib/config.d.ts +2 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +23 -13
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/crawl.d.ts +1 -1
- package/dist/lib/crawl.d.ts.map +1 -1
- package/dist/lib/crawl.js +213 -20
- package/dist/lib/crawl.js.map +1 -1
- package/dist/lib/definition.d.ts +2 -0
- package/dist/lib/definition.d.ts.map +1 -0
- package/dist/lib/definition.js +6 -0
- package/dist/lib/definition.js.map +1 -0
- package/dist/lib/diff.d.ts +71 -0
- package/dist/lib/diff.d.ts.map +1 -0
- package/dist/lib/diff.js +40 -0
- package/dist/lib/diff.js.map +1 -0
- package/dist/lib/login-error.d.ts +10 -0
- package/dist/lib/login-error.d.ts.map +1 -0
- package/dist/lib/login-error.js +13 -0
- package/dist/lib/login-error.js.map +1 -0
- package/dist/lib/page-ready.d.ts +18 -0
- package/dist/lib/page-ready.d.ts.map +1 -0
- package/dist/lib/page-ready.js +19 -0
- package/dist/lib/page-ready.js.map +1 -0
- package/dist/lib/screenshot.d.ts +11 -2
- package/dist/lib/screenshot.d.ts.map +1 -1
- package/dist/lib/screenshot.js +73 -64
- package/dist/lib/screenshot.js.map +1 -1
- package/dist/lib/staging.d.ts +7 -0
- package/dist/lib/staging.d.ts.map +1 -0
- package/dist/lib/staging.js +21 -0
- package/dist/lib/staging.js.map +1 -0
- package/dist/types.d.ts +10 -23
- package/dist/types.d.ts.map +1 -1
- package/package.json +20 -3
- package/dist/commands/preview.d.ts +0 -6
- package/dist/commands/preview.d.ts.map +0 -1
- package/dist/commands/preview.js +0 -33
- package/dist/commands/preview.js.map +0 -1
- package/dist/commands/run.d.ts +0 -6
- package/dist/commands/run.d.ts.map +0 -1
- package/dist/commands/run.js +0 -39
- package/dist/commands/run.js.map +0 -1
- package/dist/editor/editor/editor.html +0 -313
- package/dist/editor/editor/inject.ts +0 -385
- package/dist/editor/editor.html +0 -338
- package/dist/editor/inject-script.cjs +0 -398
- package/dist/editor/inject-script.cjs.map +0 -1
- package/dist/editor/inject-script.d.cts +0 -2
- package/dist/editor/inject-script.d.cts.map +0 -1
- package/dist/editor/inject-script.d.ts +0 -2
- package/dist/editor/inject-script.d.ts.map +0 -1
- package/dist/editor/inject-script.js.map +0 -1
- package/dist/editor/inject.d.ts +0 -2
- package/dist/editor/inject.d.ts.map +0 -1
- package/dist/editor/inject.js +0 -385
- package/dist/editor/inject.js.map +0 -1
- package/dist/lib/upload.d.ts +0 -9
- package/dist/lib/upload.d.ts.map +0 -1
- package/dist/lib/upload.js +0 -43
- package/dist/lib/upload.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
2
4
|
import chalk from "chalk";
|
|
3
5
|
import { Command } from "commander";
|
|
6
|
+
import { addCommand } from "./commands/add.js";
|
|
4
7
|
import { captureCommand } from "./commands/capture.js";
|
|
8
|
+
import { discoverCommand } from "./commands/discover.js";
|
|
5
9
|
import { editCommand } from "./commands/edit.js";
|
|
6
10
|
import { initCommand } from "./commands/init.js";
|
|
7
|
-
import {
|
|
11
|
+
import { listCommand } from "./commands/list.js";
|
|
12
|
+
import { loginCommand } from "./commands/login.js";
|
|
8
13
|
import { validateCommand } from "./commands/validate.js";
|
|
14
|
+
// Read version from package.json at runtime so release-please only needs to
|
|
15
|
+
// update one file (= package.json) on every bump. dist/index.js sits next
|
|
16
|
+
// to dist/, so package.json is two levels up (= ../package.json).
|
|
17
|
+
const pkgPath = fileURLToPath(new URL("../package.json", import.meta.url));
|
|
18
|
+
const VERSION = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
|
|
9
19
|
const BANNER = `
|
|
10
|
-
${chalk.bold("kagemusha")} ${chalk.gray(
|
|
20
|
+
${chalk.bold("kagemusha")} ${chalk.gray(`v${VERSION}`)}
|
|
11
21
|
${chalk.dim("The shadow warrior for your documentation.")}
|
|
12
22
|
|
|
13
23
|
${chalk.white("Auto-update help center screenshots")}
|
|
@@ -16,7 +26,7 @@ const BANNER = `
|
|
|
16
26
|
const program = new Command();
|
|
17
27
|
program
|
|
18
28
|
.name("kagemusha")
|
|
19
|
-
.version(
|
|
29
|
+
.version(VERSION)
|
|
20
30
|
.addHelpText("beforeAll", BANNER)
|
|
21
31
|
.configureHelp({
|
|
22
32
|
sortSubcommands: false,
|
|
@@ -26,16 +36,30 @@ program
|
|
|
26
36
|
.description("Set up config, screenshot definitions, and GitHub Actions workflow")
|
|
27
37
|
.action(initCommand);
|
|
28
38
|
program
|
|
29
|
-
.command("
|
|
30
|
-
.description("
|
|
31
|
-
.option("--
|
|
32
|
-
.action(
|
|
39
|
+
.command("login")
|
|
40
|
+
.description("Log in to your app (opens browser, saves session)")
|
|
41
|
+
.option("--headed", "Run scripted login in a visible browser (debug; ignored in interactive mode)")
|
|
42
|
+
.action(loginCommand);
|
|
43
|
+
program
|
|
44
|
+
.command("add <path>")
|
|
45
|
+
.description("Add a screenshot definition (defaults to fullPage; use 'edit' to change capture range)")
|
|
46
|
+
.option("--id <id>", "Custom definition ID (auto-suffixed if exists)")
|
|
47
|
+
.action(addCommand);
|
|
48
|
+
program
|
|
49
|
+
.command("discover")
|
|
50
|
+
.description("Auto-discover pages by crawling your app")
|
|
51
|
+
.action(discoverCommand);
|
|
52
|
+
program
|
|
53
|
+
.command("list")
|
|
54
|
+
.description("List current screenshot definitions")
|
|
55
|
+
.action(listCommand);
|
|
33
56
|
program
|
|
34
57
|
.command("capture")
|
|
35
|
-
.description("Capture screenshots only")
|
|
58
|
+
.description("Capture screenshots, diff against canonical, and publish only what changed (use --dry-run to preview)")
|
|
36
59
|
.option("--ids <ids>", "Comma-separated screenshot definition IDs")
|
|
37
|
-
.option("--
|
|
38
|
-
.option("--
|
|
60
|
+
.option("--dry-run", "Preview only — capture and diff but do not update canonical (S3 push skipped)")
|
|
61
|
+
.option("--threshold <ratio>", "Diff ratio (0-1) above which to flag as changed; overrides config")
|
|
62
|
+
.option("--open", "Open changed/new results in the system default viewer (Preview / xdg-open / start)")
|
|
39
63
|
.action(captureCommand);
|
|
40
64
|
program
|
|
41
65
|
.command("edit")
|
|
@@ -47,12 +71,6 @@ program
|
|
|
47
71
|
.description("Validate config and definition files")
|
|
48
72
|
.action(validateCommand);
|
|
49
73
|
// Phase 2 commands
|
|
50
|
-
program
|
|
51
|
-
.command("compare")
|
|
52
|
-
.description(`Compare screenshots with baselines (VRT) ${chalk.yellow("[coming soon]")}`)
|
|
53
|
-
.action(() => {
|
|
54
|
-
console.log(chalk.yellow("\n🚧 compare is coming in Phase 2.\n"));
|
|
55
|
-
});
|
|
56
74
|
program
|
|
57
75
|
.command("publish")
|
|
58
76
|
.description("Publish screenshots to Intercom / external services " +
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/annotate.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare
|
|
1
|
+
import type { CaptureSpec, Decoration } from "../types.js";
|
|
2
|
+
export declare const drawAnnotations: (input: Buffer | string, outputPath: string, decorations: Decoration[], capture: CaptureSpec, dpr: number) => Promise<void>;
|
|
3
3
|
//# sourceMappingURL=annotate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotate.d.ts","sourceRoot":"","sources":["../../src/lib/annotate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"annotate.d.ts","sourceRoot":"","sources":["../../src/lib/annotate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAe3D,eAAO,MAAM,eAAe,GAC3B,OAAO,MAAM,GAAG,MAAM,EACtB,YAAY,MAAM,EAClB,aAAa,UAAU,EAAE,EACzB,SAAS,WAAW,EACpB,KAAK,MAAM,KACT,OAAO,CAAC,IAAI,CAsCd,CAAC"}
|
package/dist/lib/annotate.js
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
1
|
import sharp from "sharp";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const annotatedPath = result.rawPath.replace(".raw.png", ".png");
|
|
10
|
-
fs.copyFileSync(result.rawPath, annotatedPath);
|
|
11
|
-
annotatedResults.push({ ...result, annotatedPath });
|
|
12
|
-
continue;
|
|
13
|
-
}
|
|
14
|
-
const annotatedPath = result.rawPath.replace(".raw.png", ".png");
|
|
15
|
-
await drawAnnotations(result.rawPath, annotatedPath, def.decorations);
|
|
16
|
-
annotatedResults.push({ ...result, annotatedPath });
|
|
2
|
+
// Decorations are saved in page-relative device-pixel coords. When the
|
|
3
|
+
// captured image is a crop, we subtract the crop's top-left so the SVG overlay
|
|
4
|
+
// lines up with what's actually in the PNG.
|
|
5
|
+
const captureOffset = (capture, dpr) => {
|
|
6
|
+
if (capture.mode === "crop") {
|
|
7
|
+
return { x: capture.crop.start.x * dpr, y: capture.crop.start.y * dpr };
|
|
17
8
|
}
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const
|
|
9
|
+
return { x: 0, y: 0 };
|
|
10
|
+
};
|
|
11
|
+
export const drawAnnotations = async (input, outputPath, decorations, capture, dpr) => {
|
|
12
|
+
const offset = captureOffset(capture, dpr);
|
|
13
|
+
const image = sharp(input);
|
|
22
14
|
const metadata = await image.metadata();
|
|
23
15
|
const width = metadata.width ?? 1280;
|
|
24
16
|
const height = metadata.height ?? 720;
|
|
@@ -26,13 +18,13 @@ async function drawAnnotations(inputPath, outputPath, decorations) {
|
|
|
26
18
|
for (const dec of decorations) {
|
|
27
19
|
switch (dec.type) {
|
|
28
20
|
case "rect":
|
|
29
|
-
svgParts.push(renderRect(dec));
|
|
21
|
+
svgParts.push(renderRect(dec, offset));
|
|
30
22
|
break;
|
|
31
23
|
case "arrow":
|
|
32
|
-
svgParts.push(renderArrow(dec));
|
|
24
|
+
svgParts.push(renderArrow(dec, offset));
|
|
33
25
|
break;
|
|
34
26
|
case "label":
|
|
35
|
-
svgParts.push(renderLabel(dec));
|
|
27
|
+
svgParts.push(renderLabel(dec, offset));
|
|
36
28
|
break;
|
|
37
29
|
}
|
|
38
30
|
}
|
|
@@ -50,53 +42,53 @@ async function drawAnnotations(inputPath, outputPath, decorations) {
|
|
|
50
42
|
await image
|
|
51
43
|
.composite([{ input: Buffer.from(svgOverlay), top: 0, left: 0 }])
|
|
52
44
|
.toFile(outputPath);
|
|
53
|
-
}
|
|
54
|
-
|
|
45
|
+
};
|
|
46
|
+
const renderRect = (dec, offset) => {
|
|
55
47
|
const color = dec.style?.color ?? "#FF0000";
|
|
56
48
|
const strokeWidth = dec.style?.strokeWidth ?? 2;
|
|
57
49
|
const borderRadius = dec.style?.borderRadius ?? 0;
|
|
58
50
|
if ("selector" in dec.target) {
|
|
59
|
-
// Selector-based rects need runtime resolution — use placeholder
|
|
60
|
-
// In real usage, the bounding box is resolved during capture
|
|
51
|
+
// Selector-based rects need runtime resolution — use placeholder.
|
|
52
|
+
// In real usage, the bounding box is resolved during capture.
|
|
61
53
|
return `<!-- rect: selector "${dec.target.selector}" needs runtime resolution -->`;
|
|
62
54
|
}
|
|
63
55
|
const { x, y, width, height } = dec.target;
|
|
64
|
-
return `<rect x="${x}" y="${y}" width="${width}" height="${height}"
|
|
56
|
+
return `<rect x="${x - offset.x}" y="${y - offset.y}" width="${width}" height="${height}"
|
|
65
57
|
rx="${borderRadius}" ry="${borderRadius}"
|
|
66
58
|
fill="none" stroke="${color}" stroke-width="${strokeWidth}" />`;
|
|
67
|
-
}
|
|
68
|
-
|
|
59
|
+
};
|
|
60
|
+
const renderArrow = (dec, offset) => {
|
|
69
61
|
const color = dec.style?.color ?? "#FF0000";
|
|
70
62
|
const strokeWidth = dec.style?.strokeWidth ?? 2;
|
|
71
63
|
const from = "x" in dec.from ? dec.from : { x: 0, y: 0 };
|
|
72
64
|
const to = "x" in dec.to ? dec.to : { x: 100, y: 100 };
|
|
73
|
-
return `<line x1="${from.x}" y1="${from.y}" x2="${to.x}" y2="${to.y}"
|
|
65
|
+
return `<line x1="${from.x - offset.x}" y1="${from.y - offset.y}" x2="${to.x - offset.x}" y2="${to.y - offset.y}"
|
|
74
66
|
stroke="${color}" stroke-width="${strokeWidth}"
|
|
75
67
|
marker-end="url(#arrowhead)" />`;
|
|
76
|
-
}
|
|
77
|
-
|
|
68
|
+
};
|
|
69
|
+
const renderLabel = (dec, offset) => {
|
|
78
70
|
const fontSize = dec.style?.fontSize ?? 14;
|
|
79
71
|
const color = dec.style?.color ?? "#FF0000";
|
|
80
72
|
const bg = dec.style?.background ?? "#FFFFFF";
|
|
81
73
|
const pos = "x" in dec.position ? dec.position : { x: 0, y: 0 };
|
|
74
|
+
const px = pos.x - offset.x;
|
|
75
|
+
const py = pos.y - offset.y;
|
|
82
76
|
const paddingX = 6;
|
|
83
77
|
const paddingY = 4;
|
|
84
78
|
const textWidth = dec.text.length * fontSize * 0.6;
|
|
85
79
|
const textHeight = fontSize;
|
|
86
80
|
return `
|
|
87
|
-
<rect x="${
|
|
81
|
+
<rect x="${px - paddingX}" y="${py - textHeight - paddingY}"
|
|
88
82
|
width="${textWidth + paddingX * 2}" height="${textHeight + paddingY * 2}"
|
|
89
83
|
rx="4" ry="4" fill="${bg}" />
|
|
90
|
-
<text x="${
|
|
84
|
+
<text x="${px}" y="${py}" font-size="${fontSize}"
|
|
91
85
|
fill="${color}" font-family="sans-serif">${escapeXml(dec.text)}</text>
|
|
92
86
|
`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.replace(/'/g, "'");
|
|
101
|
-
}
|
|
87
|
+
};
|
|
88
|
+
const escapeXml = (str) => str
|
|
89
|
+
.replace(/&/g, "&")
|
|
90
|
+
.replace(/</g, "<")
|
|
91
|
+
.replace(/>/g, ">")
|
|
92
|
+
.replace(/"/g, """)
|
|
93
|
+
.replace(/'/g, "'");
|
|
102
94
|
//# sourceMappingURL=annotate.js.map
|
package/dist/lib/annotate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotate.js","sourceRoot":"","sources":["../../src/lib/annotate.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"annotate.js","sourceRoot":"","sources":["../../src/lib/annotate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { KagemushaConfig } from "../types.js";
|
|
2
|
+
export declare const resolveLoginScriptPath: (config: KagemushaConfig, projectRoot: string) => string | null;
|
|
3
|
+
export declare const getAuthStatePath: (projectRoot: string) => string;
|
|
4
|
+
export declare const hasAuthState: (projectRoot: string) => boolean;
|
|
5
|
+
export declare const getAuthMetaPath: (projectRoot: string) => string;
|
|
6
|
+
export declare const authContextOptions: (projectRoot: string | undefined) => {
|
|
7
|
+
storageState?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const defaultContextOptions: (config: KagemushaConfig, projectRoot: string | undefined) => {
|
|
10
|
+
storageState?: string;
|
|
11
|
+
baseURL: string;
|
|
12
|
+
viewport: {
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
};
|
|
16
|
+
deviceScaleFactor: number;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAYnD,eAAO,MAAM,sBAAsB,GAClC,QAAQ,eAAe,EACvB,aAAa,MAAM,KACjB,MAAM,GAAG,IAWX,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,KAAG,MACA,CAAC;AAExD,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,KAAG,OACN,CAAC;AAE9C,eAAO,MAAM,eAAe,GAAI,aAAa,MAAM,KAAG,MACA,CAAC;AAIvD,eAAO,MAAM,kBAAkB,GAC9B,aAAa,MAAM,GAAG,SAAS,KAC7B;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAGpB,CAAC;AAKP,eAAO,MAAM,qBAAqB,GACjC,QAAQ,eAAe,EACvB,aAAa,MAAM,GAAG,SAAS;mBAVZ,MAAM;;;;;;;CAmBzB,CAAC"}
|
package/dist/lib/auth.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const AUTH_STATE_FILE = "auth-state.json";
|
|
4
|
+
const AUTH_META_FILE = "auth-meta.json";
|
|
5
|
+
const KAGEMUSHA_DIR = ".kagemusha";
|
|
6
|
+
// .mjs is preferred (no ambiguity with package.json's "type" field). .js is
|
|
7
|
+
// accepted for projects that already declare "type": "module".
|
|
8
|
+
const DEFAULT_LOGIN_SCRIPTS = ["login.mjs", "login.js"];
|
|
9
|
+
// Resolves the path to the user-provided login script. Returns null if
|
|
10
|
+
// neither `auth.scriptPath` nor any default candidate exists.
|
|
11
|
+
// Both `login` and `capture` go through this so behavior stays in sync.
|
|
12
|
+
export const resolveLoginScriptPath = (config, projectRoot) => {
|
|
13
|
+
const configured = config.auth?.scriptPath;
|
|
14
|
+
if (configured) {
|
|
15
|
+
const p = path.resolve(projectRoot, configured);
|
|
16
|
+
return fs.existsSync(p) ? p : null;
|
|
17
|
+
}
|
|
18
|
+
for (const name of DEFAULT_LOGIN_SCRIPTS) {
|
|
19
|
+
const p = path.join(projectRoot, KAGEMUSHA_DIR, name);
|
|
20
|
+
if (fs.existsSync(p))
|
|
21
|
+
return p;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
export const getAuthStatePath = (projectRoot) => path.join(projectRoot, KAGEMUSHA_DIR, AUTH_STATE_FILE);
|
|
26
|
+
export const hasAuthState = (projectRoot) => fs.existsSync(getAuthStatePath(projectRoot));
|
|
27
|
+
export const getAuthMetaPath = (projectRoot) => path.join(projectRoot, KAGEMUSHA_DIR, AUTH_META_FILE);
|
|
28
|
+
// Spread into Playwright's browser.newContext() options to enable auth reuse
|
|
29
|
+
// when a saved storageState exists. No-op when missing.
|
|
30
|
+
export const authContextOptions = (projectRoot) => projectRoot && hasAuthState(projectRoot)
|
|
31
|
+
? { storageState: getAuthStatePath(projectRoot) }
|
|
32
|
+
: {};
|
|
33
|
+
// Standard browser.newContext() options used by login / edit / capture so all
|
|
34
|
+
// sessions render at identical viewport + DPR (avoids annotation drift between
|
|
35
|
+
// editor view and captured image).
|
|
36
|
+
export const defaultContextOptions = (config, projectRoot) => {
|
|
37
|
+
const vp = config.screenshot.defaultViewport;
|
|
38
|
+
return {
|
|
39
|
+
baseURL: config.app.baseUrl,
|
|
40
|
+
viewport: { width: vp.width, height: vp.height },
|
|
41
|
+
deviceScaleFactor: vp.deviceScaleFactor ?? 2,
|
|
42
|
+
...authContextOptions(projectRoot),
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAC1C,MAAM,cAAc,GAAG,gBAAgB,CAAC;AACxC,MAAM,aAAa,GAAG,YAAY,CAAC;AACnC,4EAA4E;AAC5E,+DAA+D;AAC/D,MAAM,qBAAqB,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAExD,uEAAuE;AACvE,8DAA8D;AAC9D,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACrC,MAAuB,EACvB,WAAmB,EACH,EAAE;IAClB,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC;IAC3C,IAAI,UAAU,EAAE,CAAC;QAChB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAChD,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,qBAAqB,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAmB,EAAU,EAAE,CAC/D,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC;AAExD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,WAAmB,EAAW,EAAE,CAC5D,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;AAE9C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,WAAmB,EAAU,EAAE,CAC9D,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;AAEvD,6EAA6E;AAC7E,wDAAwD;AACxD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,WAA+B,EACH,EAAE,CAC9B,WAAW,IAAI,YAAY,CAAC,WAAW,CAAC;IACvC,CAAC,CAAC,EAAE,YAAY,EAAE,gBAAgB,CAAC,WAAW,CAAC,EAAE;IACjD,CAAC,CAAC,EAAE,CAAC;AAEP,8EAA8E;AAC9E,+EAA+E;AAC/E,mCAAmC;AACnC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACpC,MAAuB,EACvB,WAA+B,EAC9B,EAAE;IACH,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC;IAC7C,OAAO;QACN,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO;QAC3B,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE;QAChD,iBAAiB,EAAE,EAAE,CAAC,iBAAiB,IAAI,CAAC;QAC5C,GAAG,kBAAkB,CAAC,WAAW,CAAC;KAClC,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If `e` is a recognizable AWS error, print a friendly hint and return true.
|
|
3
|
+
* The caller is responsible for setting `process.exitCode` and returning.
|
|
4
|
+
* If the error isn't recognized, returns false — the caller should rethrow.
|
|
5
|
+
*/
|
|
6
|
+
export declare const handleAwsError: (e: unknown) => boolean;
|
|
7
|
+
//# sourceMappingURL=aws-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-error.d.ts","sourceRoot":"","sources":["../../src/lib/aws-error.ts"],"names":[],"mappings":"AA0CA;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,GAAG,OAAO,KAAG,OA2C3C,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
const errorName = (e) => typeof e === "object" && e !== null
|
|
3
|
+
? (e.name ?? "")
|
|
4
|
+
: "";
|
|
5
|
+
const errorCode = (e) => typeof e === "object" && e !== null
|
|
6
|
+
? (e.Code ?? "")
|
|
7
|
+
: "";
|
|
8
|
+
const errorMessage = (e) => typeof e === "object" && e !== null
|
|
9
|
+
? (e.message ?? "")
|
|
10
|
+
: "";
|
|
11
|
+
const matchesAuthError = (e) => {
|
|
12
|
+
const name = errorName(e);
|
|
13
|
+
const code = errorCode(e);
|
|
14
|
+
const message = errorMessage(e);
|
|
15
|
+
if (name === "CredentialsProviderError")
|
|
16
|
+
return true;
|
|
17
|
+
if (name === "ExpiredToken" || name === "ExpiredTokenException")
|
|
18
|
+
return true;
|
|
19
|
+
if (code === "ExpiredToken" || code === "ExpiredTokenException")
|
|
20
|
+
return true;
|
|
21
|
+
if (/token (is )?expired/i.test(message))
|
|
22
|
+
return true;
|
|
23
|
+
if (/credentials.*expired/i.test(message))
|
|
24
|
+
return true;
|
|
25
|
+
return false;
|
|
26
|
+
};
|
|
27
|
+
const matchesAccessDeniedError = (e) => {
|
|
28
|
+
const name = errorName(e);
|
|
29
|
+
const code = errorCode(e);
|
|
30
|
+
return name === "AccessDenied" || code === "AccessDenied";
|
|
31
|
+
};
|
|
32
|
+
const matchesNoSuchBucket = (e) => {
|
|
33
|
+
const name = errorName(e);
|
|
34
|
+
const code = errorCode(e);
|
|
35
|
+
return name === "NoSuchBucket" || code === "NoSuchBucket";
|
|
36
|
+
};
|
|
37
|
+
const profileLabel = () => process.env.AWS_PROFILE ?? "(default)";
|
|
38
|
+
/**
|
|
39
|
+
* If `e` is a recognizable AWS error, print a friendly hint and return true.
|
|
40
|
+
* The caller is responsible for setting `process.exitCode` and returning.
|
|
41
|
+
* If the error isn't recognized, returns false — the caller should rethrow.
|
|
42
|
+
*/
|
|
43
|
+
export const handleAwsError = (e) => {
|
|
44
|
+
if (matchesAuthError(e)) {
|
|
45
|
+
const profile = profileLabel();
|
|
46
|
+
console.error("");
|
|
47
|
+
console.error(chalk.red(`✗ AWS authentication failed: ${errorMessage(e)}`));
|
|
48
|
+
console.error(chalk.yellow("\nHint:"));
|
|
49
|
+
console.error(chalk.gray(` - Run: aws sso login --profile ${profile}`));
|
|
50
|
+
console.error(chalk.gray(` - Or refresh credentials for the active profile (AWS_PROFILE=${profile})`));
|
|
51
|
+
console.error("");
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (matchesAccessDeniedError(e)) {
|
|
55
|
+
const profile = profileLabel();
|
|
56
|
+
console.error("");
|
|
57
|
+
console.error(chalk.red(`✗ AWS access denied: ${errorMessage(e)}`));
|
|
58
|
+
console.error(chalk.yellow("\nHint:"));
|
|
59
|
+
console.error(chalk.gray(` - Active profile: AWS_PROFILE=${profile}`));
|
|
60
|
+
console.error(chalk.gray(` - Verify the IAM principal has s3:GetObject / s3:PutObject on the target bucket`));
|
|
61
|
+
console.error("");
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (matchesNoSuchBucket(e)) {
|
|
65
|
+
console.error("");
|
|
66
|
+
console.error(chalk.red(`✗ S3 bucket not found: ${errorMessage(e)}`));
|
|
67
|
+
console.error(chalk.yellow("\nHint:"));
|
|
68
|
+
console.error(chalk.gray(" - Check publish.cdnBucket in kagemusha.config.yaml"));
|
|
69
|
+
console.error("");
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=aws-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws-error.js","sourceRoot":"","sources":["../../src/lib/aws-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,SAAS,GAAG,CAAC,CAAU,EAAU,EAAE,CACxC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;IAClC,CAAC,CAAC,CAAE,CAAuB,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,CAAC,CAAC,EAAE,CAAC;AACP,MAAM,SAAS,GAAG,CAAC,CAAU,EAAU,EAAE,CACxC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;IAClC,CAAC,CAAC,CAAE,CAAuB,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,CAAC,CAAC,EAAE,CAAC;AACP,MAAM,YAAY,GAAG,CAAC,CAAU,EAAU,EAAE,CAC3C,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;IAClC,CAAC,CAAC,CAAE,CAA0B,CAAC,OAAO,IAAI,EAAE,CAAC;IAC7C,CAAC,CAAC,EAAE,CAAC;AAEP,MAAM,gBAAgB,GAAG,CAAC,CAAU,EAAW,EAAE;IAChD,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAEhC,IAAI,IAAI,KAAK,0BAA0B;QAAE,OAAO,IAAI,CAAC;IACrD,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,uBAAuB;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,uBAAuB;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACvD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,wBAAwB,GAAG,CAAC,CAAU,EAAW,EAAE;IACxD,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,cAAc,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,CAAU,EAAW,EAAE;IACnD,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,cAAc,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,GAAW,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,WAAW,CAAC;AAE1E;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAU,EAAW,EAAE;IACrD,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,gCAAgC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5E,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,oCAAoC,OAAO,EAAE,CAAC,CAAC,CAAC;QACzE,OAAO,CAAC,KAAK,CACZ,KAAK,CAAC,IAAI,CACT,kEAAkE,OAAO,GAAG,CAC5E,CACD,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,wBAAwB,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC,CAAC;QACxE,OAAO,CAAC,KAAK,CACZ,KAAK,CAAC,IAAI,CACT,mFAAmF,CACnF,CACD,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,KAAK,CACZ,KAAK,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAClE,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { KagemushaConfig } from "../types.js";
|
|
2
|
+
export declare const getOutputDir: (config: KagemushaConfig, projectRoot: string) => string;
|
|
3
|
+
export declare const getCanonicalPath: (config: KagemushaConfig, projectRoot: string, id: string) => string;
|
|
4
|
+
export type FetchResult = "ok" | "not-found";
|
|
5
|
+
/**
|
|
6
|
+
* URLs returned by `push()` so callers can include them in summary.json
|
|
7
|
+
* for downstream notification consumers (Slack, PR comments, etc.).
|
|
8
|
+
*
|
|
9
|
+
* - `after`: the new `latest.png` we just uploaded
|
|
10
|
+
* - `before`: the previous `latest.png`, copied to `previous.png` before
|
|
11
|
+
* being overwritten. Undefined when no prior version existed (= first push)
|
|
12
|
+
*/
|
|
13
|
+
export interface PushUrls {
|
|
14
|
+
after: string;
|
|
15
|
+
before?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* S3-backed canonical store.
|
|
19
|
+
* Local mode has no remote — outputDir itself is the source of truth.
|
|
20
|
+
*/
|
|
21
|
+
export declare class S3Canonical {
|
|
22
|
+
private readonly bucket;
|
|
23
|
+
private readonly cdnBaseUrl?;
|
|
24
|
+
private readonly client;
|
|
25
|
+
constructor(bucket: string, cdnBaseUrl?: string | undefined);
|
|
26
|
+
private latestKey;
|
|
27
|
+
private previousKey;
|
|
28
|
+
private historyKey;
|
|
29
|
+
private urlFor;
|
|
30
|
+
/** Download canonical for `id` to `localPath`. Returns "not-found" if absent. */
|
|
31
|
+
fetch(id: string, localPath: string): Promise<FetchResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Upload `localPath` as the canonical for `id`.
|
|
34
|
+
*
|
|
35
|
+
* Side effects on S3 for a single push:
|
|
36
|
+
* 1. Copy existing latest.png → previous.png (no-op if missing)
|
|
37
|
+
* 2. Upload localPath → latest.png
|
|
38
|
+
* 3. Upload localPath → history/<timestamp>.png
|
|
39
|
+
*
|
|
40
|
+
* Step 1 must complete first (otherwise the soon-to-be-overwritten latest
|
|
41
|
+
* would be replaced before the snapshot is taken). Steps 2-3 target
|
|
42
|
+
* different keys and run in parallel.
|
|
43
|
+
*
|
|
44
|
+
* Returns URLs (`before` / `after`) so callers can surface them in
|
|
45
|
+
* `reports/summary.json` (= public API). Consumers compare before vs after
|
|
46
|
+
* visually; kagemusha intentionally does not publish a pre-generated diff
|
|
47
|
+
* image (= pixelmatch's red overlay is alarming and adds little vs the
|
|
48
|
+
* raw pair).
|
|
49
|
+
*/
|
|
50
|
+
push(id: string, localPath: string): Promise<PushUrls>;
|
|
51
|
+
label(): string;
|
|
52
|
+
}
|
|
53
|
+
export declare const createS3Canonical: (config: KagemushaConfig) => S3Canonical | null;
|
|
54
|
+
//# sourceMappingURL=canonical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../src/lib/canonical.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,eAAO,MAAM,YAAY,GACxB,QAAQ,eAAe,EACvB,aAAa,MAAM,KACjB,MAKF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC5B,QAAQ,eAAe,EACvB,aAAa,MAAM,EACnB,IAAI,MAAM,KACR,MAAmE,CAAC;AAEvE,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,WAAW,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD;;;GAGG;AAEH,qBAAa,WAAW;IAItB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAJ7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;gBAGhB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,YAAA;IAMrC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,MAAM;IAKd,iFAAiF;IAC3E,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBhE;;;;;;;;;;;;;;;;;OAiBG;IACG,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAuD5D,KAAK,IAAI,MAAM;CAGf;AASD,eAAO,MAAM,iBAAiB,GAC7B,QAAQ,eAAe,KACrB,WAAW,GAAG,IAOhB,CAAC"}
|