@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.
Files changed (155) hide show
  1. package/README.md +168 -79
  2. package/dist/commands/add.d.ts +6 -0
  3. package/dist/commands/add.d.ts.map +1 -0
  4. package/dist/commands/add.js +26 -0
  5. package/dist/commands/add.js.map +1 -0
  6. package/dist/commands/capture.d.ts +3 -2
  7. package/dist/commands/capture.d.ts.map +1 -1
  8. package/dist/commands/capture.js +256 -20
  9. package/dist/commands/capture.js.map +1 -1
  10. package/dist/commands/discover.d.ts +2 -0
  11. package/dist/commands/discover.d.ts.map +1 -0
  12. package/dist/commands/discover.js +62 -0
  13. package/dist/commands/discover.js.map +1 -0
  14. package/dist/commands/edit.d.ts +1 -1
  15. package/dist/commands/edit.d.ts.map +1 -1
  16. package/dist/commands/edit.js +82 -26
  17. package/dist/commands/edit.js.map +1 -1
  18. package/dist/commands/init.d.ts +1 -1
  19. package/dist/commands/init.d.ts.map +1 -1
  20. package/dist/commands/init.js +240 -105
  21. package/dist/commands/init.js.map +1 -1
  22. package/dist/commands/list.d.ts +2 -0
  23. package/dist/commands/list.d.ts.map +1 -0
  24. package/dist/commands/list.js +33 -0
  25. package/dist/commands/list.js.map +1 -0
  26. package/dist/commands/login.d.ts +6 -0
  27. package/dist/commands/login.d.ts.map +1 -0
  28. package/dist/commands/login.js +131 -0
  29. package/dist/commands/login.js.map +1 -0
  30. package/dist/commands/validate.js +1 -1
  31. package/dist/commands/validate.js.map +1 -1
  32. package/dist/editor/inject-script/annotations.d.ts +11 -0
  33. package/dist/editor/inject-script/annotations.d.ts.map +1 -0
  34. package/dist/editor/inject-script/annotations.js +409 -0
  35. package/dist/editor/inject-script/annotations.js.map +1 -0
  36. package/dist/editor/inject-script/bridge.d.ts +13 -0
  37. package/dist/editor/inject-script/bridge.d.ts.map +1 -0
  38. package/dist/editor/inject-script/bridge.js +33 -0
  39. package/dist/editor/inject-script/bridge.js.map +1 -0
  40. package/dist/editor/inject-script/crop.d.ts +9 -0
  41. package/dist/editor/inject-script/crop.d.ts.map +1 -0
  42. package/dist/editor/inject-script/crop.js +236 -0
  43. package/dist/editor/inject-script/crop.js.map +1 -0
  44. package/dist/editor/inject-script/dom.d.ts +7 -0
  45. package/dist/editor/inject-script/dom.d.ts.map +1 -0
  46. package/dist/editor/inject-script/dom.js +32 -0
  47. package/dist/editor/inject-script/dom.js.map +1 -0
  48. package/dist/editor/inject-script/index.d.ts +2 -0
  49. package/dist/editor/inject-script/index.d.ts.map +1 -0
  50. package/dist/editor/inject-script/index.js +56 -0
  51. package/dist/editor/inject-script/index.js.map +1 -0
  52. package/dist/editor/inject-script/record.d.ts +5 -0
  53. package/dist/editor/inject-script/record.d.ts.map +1 -0
  54. package/dist/editor/inject-script/record.js +398 -0
  55. package/dist/editor/inject-script/record.js.map +1 -0
  56. package/dist/editor/inject-script/selector.d.ts +6 -0
  57. package/dist/editor/inject-script/selector.d.ts.map +1 -0
  58. package/dist/editor/inject-script/selector.js +112 -0
  59. package/dist/editor/inject-script/selector.js.map +1 -0
  60. package/dist/editor/inject-script/state.d.ts +27 -0
  61. package/dist/editor/inject-script/state.d.ts.map +1 -0
  62. package/dist/editor/inject-script/state.js +26 -0
  63. package/dist/editor/inject-script/state.js.map +1 -0
  64. package/dist/editor/inject-script/svg.d.ts +7 -0
  65. package/dist/editor/inject-script/svg.d.ts.map +1 -0
  66. package/dist/editor/inject-script/svg.js +39 -0
  67. package/dist/editor/inject-script/svg.js.map +1 -0
  68. package/dist/editor/inject-script/toolbar.d.ts +14 -0
  69. package/dist/editor/inject-script/toolbar.d.ts.map +1 -0
  70. package/dist/editor/inject-script/toolbar.js +240 -0
  71. package/dist/editor/inject-script/toolbar.js.map +1 -0
  72. package/dist/editor/inject-script/types.d.ts +102 -0
  73. package/dist/editor/inject-script/types.d.ts.map +1 -0
  74. package/dist/editor/inject-script/types.js +5 -0
  75. package/dist/editor/inject-script/types.js.map +1 -0
  76. package/dist/editor/inject-script.js +1276 -353
  77. package/dist/index.js +34 -16
  78. package/dist/index.js.map +1 -1
  79. package/dist/lib/annotate.d.ts +2 -2
  80. package/dist/lib/annotate.d.ts.map +1 -1
  81. package/dist/lib/annotate.js +35 -43
  82. package/dist/lib/annotate.js.map +1 -1
  83. package/dist/lib/auth.d.ts +18 -0
  84. package/dist/lib/auth.d.ts.map +1 -0
  85. package/dist/lib/auth.js +45 -0
  86. package/dist/lib/auth.js.map +1 -0
  87. package/dist/lib/aws-error.d.ts +7 -0
  88. package/dist/lib/aws-error.d.ts.map +1 -0
  89. package/dist/lib/aws-error.js +74 -0
  90. package/dist/lib/aws-error.js.map +1 -0
  91. package/dist/lib/canonical.d.ts +54 -0
  92. package/dist/lib/canonical.d.ts.map +1 -0
  93. package/dist/lib/canonical.js +152 -0
  94. package/dist/lib/canonical.js.map +1 -0
  95. package/dist/lib/config.d.ts +2 -0
  96. package/dist/lib/config.d.ts.map +1 -1
  97. package/dist/lib/config.js +23 -13
  98. package/dist/lib/config.js.map +1 -1
  99. package/dist/lib/crawl.d.ts +1 -1
  100. package/dist/lib/crawl.d.ts.map +1 -1
  101. package/dist/lib/crawl.js +213 -20
  102. package/dist/lib/crawl.js.map +1 -1
  103. package/dist/lib/definition.d.ts +2 -0
  104. package/dist/lib/definition.d.ts.map +1 -0
  105. package/dist/lib/definition.js +6 -0
  106. package/dist/lib/definition.js.map +1 -0
  107. package/dist/lib/diff.d.ts +71 -0
  108. package/dist/lib/diff.d.ts.map +1 -0
  109. package/dist/lib/diff.js +40 -0
  110. package/dist/lib/diff.js.map +1 -0
  111. package/dist/lib/login-error.d.ts +10 -0
  112. package/dist/lib/login-error.d.ts.map +1 -0
  113. package/dist/lib/login-error.js +13 -0
  114. package/dist/lib/login-error.js.map +1 -0
  115. package/dist/lib/page-ready.d.ts +18 -0
  116. package/dist/lib/page-ready.d.ts.map +1 -0
  117. package/dist/lib/page-ready.js +19 -0
  118. package/dist/lib/page-ready.js.map +1 -0
  119. package/dist/lib/screenshot.d.ts +11 -2
  120. package/dist/lib/screenshot.d.ts.map +1 -1
  121. package/dist/lib/screenshot.js +73 -64
  122. package/dist/lib/screenshot.js.map +1 -1
  123. package/dist/lib/staging.d.ts +7 -0
  124. package/dist/lib/staging.d.ts.map +1 -0
  125. package/dist/lib/staging.js +21 -0
  126. package/dist/lib/staging.js.map +1 -0
  127. package/dist/types.d.ts +10 -23
  128. package/dist/types.d.ts.map +1 -1
  129. package/package.json +20 -3
  130. package/dist/commands/preview.d.ts +0 -6
  131. package/dist/commands/preview.d.ts.map +0 -1
  132. package/dist/commands/preview.js +0 -33
  133. package/dist/commands/preview.js.map +0 -1
  134. package/dist/commands/run.d.ts +0 -6
  135. package/dist/commands/run.d.ts.map +0 -1
  136. package/dist/commands/run.js +0 -39
  137. package/dist/commands/run.js.map +0 -1
  138. package/dist/editor/editor/editor.html +0 -313
  139. package/dist/editor/editor/inject.ts +0 -385
  140. package/dist/editor/editor.html +0 -338
  141. package/dist/editor/inject-script.cjs +0 -398
  142. package/dist/editor/inject-script.cjs.map +0 -1
  143. package/dist/editor/inject-script.d.cts +0 -2
  144. package/dist/editor/inject-script.d.cts.map +0 -1
  145. package/dist/editor/inject-script.d.ts +0 -2
  146. package/dist/editor/inject-script.d.ts.map +0 -1
  147. package/dist/editor/inject-script.js.map +0 -1
  148. package/dist/editor/inject.d.ts +0 -2
  149. package/dist/editor/inject.d.ts.map +0 -1
  150. package/dist/editor/inject.js +0 -385
  151. package/dist/editor/inject.js.map +0 -1
  152. package/dist/lib/upload.d.ts +0 -9
  153. package/dist/lib/upload.d.ts.map +0 -1
  154. package/dist/lib/upload.js +0 -43
  155. package/dist/lib/upload.js.map +0 -1
@@ -3,8 +3,11 @@ import path from "node:path";
3
3
  import chalk from "chalk";
4
4
  import inquirer from "inquirer";
5
5
  import { stringify as toYaml } from "yaml";
6
+ import { hasAuthState } from "../lib/auth.js";
7
+ import { loadDefinitions, saveDefinitions } from "../lib/config.js";
6
8
  import { discoverPages } from "../lib/crawl.js";
7
- export async function initCommand() {
9
+ import { deriveIdFromPath } from "../lib/definition.js";
10
+ export const initCommand = async () => {
8
11
  console.log(chalk.bold("\n🄷 Kagemusha — Setup\n"));
9
12
  const cwd = process.cwd();
10
13
  if (fs.existsSync(path.join(cwd, "kagemusha.config.yaml"))) {
@@ -26,48 +29,6 @@ export async function initCommand() {
26
29
  message: "Target URL (the app to take screenshots of):",
27
30
  default: "http://localhost:3000",
28
31
  });
29
- const { needsAuth } = await inquirer.prompt({
30
- type: "confirm",
31
- name: "needsAuth",
32
- message: "Does the app require login?",
33
- default: true,
34
- });
35
- let loginUrl = "/login";
36
- let emailSelector = "#email";
37
- let passwordSelector = "#password";
38
- let submitSelector = "button[type='submit']";
39
- if (needsAuth) {
40
- const authAnswers = await inquirer.prompt([
41
- {
42
- type: "input",
43
- name: "loginUrl",
44
- message: "Login page path:",
45
- default: "/login",
46
- },
47
- {
48
- type: "input",
49
- name: "emailSelector",
50
- message: "Email input selector:",
51
- default: "#email",
52
- },
53
- {
54
- type: "input",
55
- name: "passwordSelector",
56
- message: "Password input selector:",
57
- default: "#password",
58
- },
59
- {
60
- type: "input",
61
- name: "submitSelector",
62
- message: "Login button selector:",
63
- default: "button[type='submit']",
64
- },
65
- ]);
66
- loginUrl = authAnswers.loginUrl;
67
- emailSelector = authAnswers.emailSelector;
68
- passwordSelector = authAnswers.passwordSelector;
69
- submitSelector = authAnswers.submitSelector;
70
- }
71
32
  const { destination } = await inquirer.prompt({
72
33
  type: "list",
73
34
  name: "destination",
@@ -110,50 +71,54 @@ export async function initCommand() {
110
71
  app: { baseUrl },
111
72
  screenshot: {
112
73
  defaultViewport: { width: 1280, height: 720, deviceScaleFactor: 2 },
113
- defaultDiffThreshold: 0.5,
74
+ defaultDiffThreshold: 0.005,
114
75
  },
76
+ publish: destination === "local"
77
+ ? { destination: "local", outputDir }
78
+ : { destination: "s3", cdnBucket, cdnBaseUrl },
115
79
  };
116
- if (destination === "local") {
117
- config.publish = {
118
- destination: "local",
119
- outputDir,
120
- };
121
- }
122
- else {
123
- config.publish = {
124
- destination: "s3",
125
- cdnBucket,
126
- cdnBaseUrl,
127
- };
128
- }
129
- if (needsAuth) {
130
- config.auth = {
131
- loginUrl,
132
- steps: [
133
- {
134
- action: "type",
135
- selector: emailSelector,
136
- text: "${KAGEMUSHA_DEMO_EMAIL}",
137
- },
138
- {
139
- action: "type",
140
- selector: passwordSelector,
141
- text: "${KAGEMUSHA_DEMO_PASSWORD}",
142
- },
143
- { action: "click", selector: submitSelector },
144
- { action: "waitForNavigation" },
145
- ],
146
- };
147
- }
148
80
  // Write config
149
81
  fs.writeFileSync(path.join(cwd, "kagemusha.config.yaml"), toYaml(config, { lineWidth: 120 }));
150
82
  console.log(chalk.green("\nāœ“ Created kagemusha.config.yaml"));
83
+ // Update .gitignore so canonical/staging artifacts don't pollute the repo.
84
+ // Canonical lives in S3 (or a local outputDir for testing) — never in git.
85
+ updateGitignore(cwd, outputDir);
151
86
  // Step 2: Discover pages and create screenshot definitions
152
- fs.mkdirSync(path.join(cwd, ".kagemusha/definitions"), { recursive: true });
153
- console.log(chalk.blue(`\nšŸ” Scanning ${baseUrl} for pages...\n`));
87
+ // Check if login is needed
88
+ if (!hasAuthState(cwd)) {
89
+ const { needsLogin } = await inquirer.prompt({
90
+ type: "confirm",
91
+ name: "needsLogin",
92
+ message: "Does this app require login?",
93
+ default: true,
94
+ });
95
+ if (needsLogin) {
96
+ const { ciAuto } = await inquirer.prompt({
97
+ type: "confirm",
98
+ name: "ciAuto",
99
+ message: "Generate a login.js skeleton for headless / CI auto-login? (recommended)",
100
+ default: true,
101
+ });
102
+ if (ciAuto) {
103
+ const skeletonPath = path.join(cwd, ".kagemusha", "login.mjs");
104
+ if (!fs.existsSync(skeletonPath)) {
105
+ fs.mkdirSync(path.dirname(skeletonPath), { recursive: true });
106
+ fs.writeFileSync(skeletonPath, generateLoginSkeleton());
107
+ console.log(chalk.green("āœ“ Created .kagemusha/login.mjs (edit before use)"));
108
+ }
109
+ }
110
+ console.log(chalk.blue("\nšŸ” Opening browser for login...\n"));
111
+ const { loginCommand } = await import("./login.js");
112
+ await loginCommand();
113
+ }
114
+ }
115
+ else {
116
+ console.log(chalk.green(" āœ“ Using saved login session\n"));
117
+ }
118
+ console.log(chalk.blue(`šŸ” Scanning ${baseUrl} for pages...\n`));
154
119
  let pages = [];
155
120
  try {
156
- pages = await discoverPages(baseUrl);
121
+ pages = await discoverPages(baseUrl, cwd);
157
122
  }
158
123
  catch {
159
124
  console.log(chalk.yellow(" Could not auto-discover pages.\n"));
@@ -192,9 +157,32 @@ export async function initCommand() {
192
157
  addMore = more;
193
158
  }
194
159
  }
160
+ // Preserve existing definitions; merge new ones (skip ID duplicates)
161
+ const existing = loadDefinitions(cwd);
162
+ let merged = existing;
163
+ let resetExisting = false;
164
+ if (existing.length > 0) {
165
+ const { keepExisting } = await inquirer.prompt({
166
+ type: "confirm",
167
+ name: "keepExisting",
168
+ message: `${existing.length} existing definition(s) found. Keep them and merge new selections?`,
169
+ default: true,
170
+ });
171
+ if (!keepExisting) {
172
+ console.log(chalk.yellow(` ⚠ ${existing.length} existing definition(s) will be replaced.`));
173
+ merged = [];
174
+ resetExisting = true;
175
+ }
176
+ }
177
+ const existingIds = new Set(merged.map((d) => d.id));
178
+ let added = 0;
195
179
  for (const pagePath of selectedPaths) {
196
180
  const id = deriveIdFromPath(pagePath);
197
- const definition = {
181
+ if (existingIds.has(id)) {
182
+ console.log(chalk.gray(` ↷ ${id} (already exists, skipped)`));
183
+ continue;
184
+ }
185
+ const def = {
198
186
  id,
199
187
  name: id,
200
188
  url: pagePath,
@@ -202,9 +190,13 @@ export async function initCommand() {
202
190
  hideElements: [],
203
191
  decorations: [],
204
192
  };
205
- const defPath = path.join(cwd, ".kagemusha/definitions", `${id}.json`);
206
- fs.writeFileSync(defPath, `${JSON.stringify(definition, null, 2)}\n`);
207
- console.log(chalk.green(` āœ“ ${id} → ${defPath}`));
193
+ merged.push(def);
194
+ existingIds.add(id);
195
+ added++;
196
+ console.log(chalk.green(` āœ“ ${id}`));
197
+ }
198
+ if (added > 0 || resetExisting) {
199
+ saveDefinitions(merged, cwd);
208
200
  }
209
201
  console.log("");
210
202
  // Step 3: GitHub Actions workflow
@@ -219,49 +211,192 @@ export async function initCommand() {
219
211
  fs.mkdirSync(workflowDir, { recursive: true });
220
212
  fs.writeFileSync(path.join(workflowDir, "kagemusha.yml"), generateWorkflowTemplate());
221
213
  console.log(chalk.green("āœ“ Created .github/workflows/kagemusha.yml"));
214
+ // Notification formatter is user-editable (= belongs to the project,
215
+ // not to kagemusha). Place a Slack-shaped skeleton next to login.mjs.
216
+ const notifyJqPath = path.join(cwd, ".kagemusha", "notify-slack.jq");
217
+ if (!fs.existsSync(notifyJqPath)) {
218
+ fs.mkdirSync(path.dirname(notifyJqPath), { recursive: true });
219
+ fs.writeFileSync(notifyJqPath, generateNotifySlackJq());
220
+ console.log(chalk.green("āœ“ Created .kagemusha/notify-slack.jq (edit to customize format)"));
221
+ }
222
222
  }
223
223
  console.log(chalk.bold.green("\nāœ… Setup complete!\n"));
224
224
  console.log(chalk.gray("Next steps:"));
225
- console.log(chalk.gray(" npx kagemusha preview — Preview screenshots locally"));
226
- console.log(chalk.gray(" npx kagemusha validate — Validate config files"));
227
- console.log(chalk.gray(" npx kagemusha run — Run full pipeline\n"));
228
- }
229
- function generateWorkflowTemplate() {
230
- return `name: Kagemusha - Screenshot Update
225
+ console.log(chalk.gray(" npx kagemusha capture — Capture & publish changed"));
226
+ console.log(chalk.gray(" npx kagemusha capture --dry-run — Preview diffs only"));
227
+ console.log(chalk.gray(" npx kagemusha edit — Edit annotations\n"));
228
+ };
229
+ // login.mjs は team ć§å…±ęœ‰ć•ć‚Œć‚‹ć¹ć (selector / ćƒ•ćƒ­ćƒ¼å®šē¾©ćÆ team property)
230
+ // ćŖć®ć§ę„å›³ēš„ć« gitignore しない。
231
+ const GITIGNORE_ENTRIES = [
232
+ ".kagemusha/.staging/",
233
+ ".kagemusha/.cache/",
234
+ ".kagemusha/auth-state.json",
235
+ ".kagemusha/auth-meta.json",
236
+ "reports/",
237
+ ];
238
+ // Strip trailing slash so `screenshots` and `screenshots/` are treated as the
239
+ // same gitignore entry (and we don't append duplicates).
240
+ const stripTrailingSlash = (s) => s.replace(/\/+$/, "");
241
+ const updateGitignore = (cwd, outputDir) => {
242
+ const gitignorePath = path.join(cwd, ".gitignore");
243
+ const existing = fs.existsSync(gitignorePath)
244
+ ? fs.readFileSync(gitignorePath, "utf8")
245
+ : "";
246
+ const present = new Set(existing
247
+ .split("\n")
248
+ .map((l) => l.trim())
249
+ .filter((l) => l.length > 0)
250
+ .map(stripTrailingSlash));
251
+ const normalizedOutputDir = outputDir
252
+ .replace(/^\.\//, "")
253
+ .replace(/\/+$/, "");
254
+ const entries = [...GITIGNORE_ENTRIES, `${normalizedOutputDir}/`];
255
+ const additions = entries.filter((e) => !present.has(stripTrailingSlash(e)));
256
+ if (additions.length === 0)
257
+ return;
258
+ const block = ["", "# kagemusha", ...additions, ""];
259
+ const next = existing.endsWith("\n") || existing === ""
260
+ ? existing + block.join("\n")
261
+ : `${existing}\n${block.join("\n")}`;
262
+ fs.writeFileSync(gitignorePath, next);
263
+ console.log(chalk.green(`āœ“ Updated .gitignore (added ${additions.length} kagemusha entries)`));
264
+ };
265
+ const generateLoginSkeleton = () => `// Custom login flow — runs headless, called by \`kagemusha login\`.
266
+ // Saved storage state is reused by \`kagemusha capture\` for all definitions.
267
+ //
268
+ // Examples:
269
+ // - Form login: fill email/password, submit, wait for redirect
270
+ // - HTTP basic: set extraHTTPHeaders or httpCredentials in kagemusha.config.yaml
271
+ // - Token-based: inject Authorization header via extraHTTPHeaders
272
+ // - SSO / OAuth: fall back to interactive \`kagemusha login\` (delete this file)
273
+ //
274
+ // The page already has \`baseURL\` set from kagemusha.config.yaml, so relative
275
+ // paths work in \`page.goto('/login')\`.
276
+ //
277
+ // āš ļø Env var naming:
278
+ // The example below uses MY_APP_EMAIL / MY_APP_PASSWORD as placeholders.
279
+ // Rename them to whatever fits your project (e.g. STAGING_EMAIL, WEVOX_TEST_EMAIL).
280
+ // Avoid:
281
+ // - Generic names like EMAIL / PASSWORD (collide with shell rc / other tools)
282
+ // - KAGEMUSHA_* prefix (reserved for kagemusha's own future config / GUI auth)
283
+
284
+ /** @param {import('playwright-chromium').Page} page */
285
+ export const login = async (page) => {
286
+ await page.goto("/login");
287
+
288
+ await page.fill('input[name="email"]', process.env.MY_APP_EMAIL ?? "");
289
+ await page.fill('input[name="password"]', process.env.MY_APP_PASSWORD ?? "");
290
+ await page.click('button[type="submit"]');
291
+
292
+ // Wait until we leave the login URL (= login succeeded).
293
+ await page.waitForURL((url) => !url.pathname.startsWith("/login"));
294
+ };
295
+ `;
296
+ const generateWorkflowTemplate = () => `name: Kagemusha - Screenshot Update
231
297
 
298
+ # Triggered when main is updated (= push or PR merge land on main).
232
299
  on:
233
- pull_request:
234
- types: [closed]
300
+ push:
235
301
  branches: [main]
236
302
  workflow_dispatch:
237
303
 
304
+ # Cancel in-progress runs when a newer merge arrives — kagemusha always
305
+ # captures the full set, so the latest run subsumes any earlier one.
306
+ concurrency:
307
+ group: kagemusha
308
+ cancel-in-progress: true
309
+
310
+ # OIDC is recommended over long-lived access keys.
311
+ # To use OIDC instead: replace the AWS env vars below with
312
+ # \`uses: aws-actions/configure-aws-credentials@v4\` + \`role-to-assume\` and
313
+ # add \`permissions: { id-token: write, contents: read }\`.
314
+
238
315
  jobs:
239
316
  update-screenshots:
240
- if: github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
241
317
  runs-on: ubuntu-latest
242
318
  steps:
243
319
  - uses: actions/checkout@v4
244
- with:
245
- fetch-depth: 0
246
320
  - uses: actions/setup-node@v4
247
321
  with:
248
322
  node-version: 20
249
323
  - run: npm ci
250
324
  - run: npx playwright install chromium
251
325
 
252
- - run: npx kagemusha run
326
+ # If your app needs login, kagemusha auto-runs .kagemusha/login.mjs
327
+ # (generated by \`kagemusha init\`) to create a fresh session.
328
+ # Set login credentials as secrets and pass them as env below.
329
+ #
330
+ # For SSO / MFA apps where scripted login isn't possible, use:
331
+ # - name: Restore login session
332
+ # if: env.KAGEMUSHA_STORAGE_STATE != ''
333
+ # run: mkdir -p .kagemusha && echo "$KAGEMUSHA_STORAGE_STATE" | base64 --decode > .kagemusha/auth-state.json
334
+ # env:
335
+ # KAGEMUSHA_STORAGE_STATE: \${{ secrets.KAGEMUSHA_STORAGE_STATE }}
336
+
337
+ # Pulls canonical from S3, diffs against fresh capture,
338
+ # pushes only what changed back to S3. No screenshots/ commit needed.
339
+ # Region is auto-detected from publish.cdnBaseUrl in kagemusha.config.yaml.
340
+ - run: npx kagemusha capture
253
341
  env:
254
- KAGEMUSHA_DEMO_EMAIL: \${{ secrets.KAGEMUSHA_DEMO_EMAIL }}
255
- KAGEMUSHA_DEMO_PASSWORD: \${{ secrets.KAGEMUSHA_DEMO_PASSWORD }}
256
342
  AWS_ACCESS_KEY_ID: \${{ secrets.AWS_ACCESS_KEY_ID }}
257
343
  AWS_SECRET_ACCESS_KEY: \${{ secrets.AWS_SECRET_ACCESS_KEY }}
344
+ # Rename these to match what your .kagemusha/login.mjs reads.
345
+ # Avoid generic names (EMAIL) or KAGEMUSHA_* (reserved).
346
+ MY_APP_EMAIL: \${{ secrets.MY_APP_EMAIL }}
347
+ MY_APP_PASSWORD: \${{ secrets.MY_APP_PASSWORD }}
348
+
349
+ # Keep summary.json as artifact for later review
350
+ - uses: actions/upload-artifact@v4
351
+ with:
352
+ name: kagemusha-reports
353
+ path: reports/
354
+ if-no-files-found: ignore
355
+
356
+ # Slack notification: one message per changed/new screenshot.
357
+ # Slack unfurls image URLs per-message, so the preview comes out
358
+ # clean even with many updates. Format defined in
359
+ # .kagemusha/notify-slack.jq — each line of jq output becomes one
360
+ # POST body. Test locally:
361
+ # jq -c -f .kagemusha/notify-slack.jq reports/summary.json
362
+ - name: Slack notify
363
+ env:
364
+ SLACK_WEBHOOK_URL: \${{ secrets.SLACK_WEBHOOK_URL }}
365
+ run: |
366
+ [ -n "$SLACK_WEBHOOK_URL" ] || exit 0
367
+ jq -c -f .kagemusha/notify-slack.jq reports/summary.json | while IFS= read -r payload; do
368
+ [ -z "$payload" ] && continue
369
+ curl -sS -X POST "$SLACK_WEBHOOK_URL" \\
370
+ -H 'Content-Type: application/json' \\
371
+ --data "$payload"
372
+ done
373
+ `;
374
+ const generateNotifySlackJq = () => `# Slack notification formatter for kagemusha.
375
+ # Called by .github/workflows/kagemusha.yml on reports/summary.json.
376
+ # Emits ONE Slack payload object per changed/new screenshot — the
377
+ # workflow loops over the lines and POSTs each as a separate message.
378
+ # Slack unfurls image URLs per-message, so before/after previews render
379
+ # cleanly even when many pages changed.
380
+ #
381
+ # Each emitted object is a full Slack chat.postMessage body, so you can
382
+ # customize freely (add blocks, attachments, channel override, etc).
383
+ #
384
+ # Test locally:
385
+ # jq -c -f .kagemusha/notify-slack.jq reports/summary.json
386
+
387
+ .results[]
388
+ | select(.status == "changed" or .status == "new")
389
+ | {
390
+ text: (
391
+ if .status == "changed" then
392
+ "šŸ“ø *\\(.id)* changed (\\((.diffPercentage * 100 | floor) / 100)%)" +
393
+ (if .urls.before then "\\nBefore: \\(.urls.before)" else "" end) +
394
+ (if .urls.after then "\\nAfter: \\(.urls.after)" else "" end)
395
+ else
396
+ "šŸ“ø *\\(.id)* added" +
397
+ (if .urls.after then "\\n\\(.urls.after)" else "" end)
398
+ end
399
+ )
400
+ }
258
401
  `;
259
- }
260
- function deriveIdFromPath(urlPath) {
261
- return (urlPath
262
- .replace(/^\//, "")
263
- .replace(/\.\w+$/, "")
264
- .replace(/[/\\]/g, "-")
265
- .replace(/[^a-zA-Z0-9-]/g, "") || "page");
266
- }
267
402
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const listCommand: () => Promise<void>;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,QAAa,OAAO,CAAC,IAAI,CAsChD,CAAC"}
@@ -0,0 +1,33 @@
1
+ import chalk from "chalk";
2
+ import { findProjectRoot, loadDefinitions } from "../lib/config.js";
3
+ export const listCommand = async () => {
4
+ const projectRoot = findProjectRoot();
5
+ const definitions = loadDefinitions(projectRoot);
6
+ if (definitions.length === 0) {
7
+ console.log(chalk.yellow("\nNo definitions found.\n"));
8
+ return;
9
+ }
10
+ // Group by URL
11
+ const byUrl = new Map();
12
+ for (const def of definitions) {
13
+ const list = byUrl.get(def.url) ?? [];
14
+ list.push(def);
15
+ byUrl.set(def.url, list);
16
+ }
17
+ console.log(chalk.bold(`\nšŸ“‹ ${definitions.length} definition(s) across ${byUrl.size} URL(s)\n`));
18
+ for (const [url, defs] of byUrl) {
19
+ console.log(chalk.blue(` ${url}`));
20
+ for (const def of defs) {
21
+ const decorations = def.decorations?.length ?? 0;
22
+ const meta = [
23
+ def.capture.mode,
24
+ decorations > 0 ? `${decorations} annotations` : null,
25
+ ]
26
+ .filter(Boolean)
27
+ .join(", ");
28
+ console.log(` ${chalk.white(def.id)} ${chalk.dim(meta)}`);
29
+ }
30
+ }
31
+ console.log("");
32
+ };
33
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGpE,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,IAAmB,EAAE;IACpD,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,WAAW,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAEjD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACvD,OAAO;IACR,CAAC;IAED,eAAe;IACf,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkC,CAAC;IACxD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,CAAC,GAAG,CACV,KAAK,CAAC,IAAI,CACT,QAAQ,WAAW,CAAC,MAAM,yBAAyB,KAAK,CAAC,IAAI,WAAW,CACxE,CACD,CAAC;IAEF,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;QACpC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG;gBACZ,GAAG,CAAC,OAAO,CAAC,IAAI;gBAChB,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,cAAc,CAAC,CAAC,CAAC,IAAI;aACrD;iBACC,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,IAAI,CAAC,CAAC;YAEb,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC;IACF,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACjB,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface LoginOptions {
2
+ headed?: boolean;
3
+ }
4
+ export declare const loginCommand: (options?: LoginOptions) => Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAoBA,UAAU,YAAY;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,YAAY,GACxB,UAAS,YAAiB,KACxB,OAAO,CAAC,IAAI,CAoBd,CAAC"}
@@ -0,0 +1,131 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import chalk from "chalk";
5
+ import { defaultContextOptions, getAuthMetaPath, getAuthStatePath, resolveLoginScriptPath, } from "../lib/auth.js";
6
+ import { findProjectRoot, loadConfig } from "../lib/config.js";
7
+ import { LoginError } from "../lib/login-error.js";
8
+ export const loginCommand = async (options = {}) => {
9
+ const projectRoot = findProjectRoot();
10
+ const config = loadConfig(projectRoot);
11
+ const scriptPath = resolveLoginScriptPath(config, projectRoot);
12
+ try {
13
+ if (scriptPath) {
14
+ await runScriptedLogin(scriptPath, config, projectRoot, options);
15
+ }
16
+ else {
17
+ await runInteractiveLogin(config, projectRoot);
18
+ }
19
+ }
20
+ catch (e) {
21
+ if (e instanceof LoginError) {
22
+ // Friendly message + screenshot already printed inside runScriptedLogin.
23
+ // Just signal failure via exit code without dumping a stack.
24
+ process.exitCode = 1;
25
+ return;
26
+ }
27
+ throw e;
28
+ }
29
+ };
30
+ const runScriptedLogin = async (scriptPath, config, projectRoot, options = {}) => {
31
+ console.log(chalk.bold("\n🄷 Kagemusha — Login (scripted)\n"));
32
+ console.log(chalk.gray(` using: ${path.relative(projectRoot, scriptPath)}`));
33
+ if (options.headed) {
34
+ console.log(chalk.gray(` mode: headed (debug)\n`));
35
+ }
36
+ else {
37
+ console.log("");
38
+ }
39
+ const mod = (await import(pathToFileURL(scriptPath).href));
40
+ const loginFn = mod.login ?? mod.default;
41
+ if (typeof loginFn !== "function") {
42
+ throw new Error(`${scriptPath} must export a 'login(page)' function (named or default export).`);
43
+ }
44
+ const { chromium } = await import("playwright-chromium");
45
+ const browser = await chromium.launch({ headless: !options.headed });
46
+ // projectRoot=undefined → no storageState applied (we are creating one).
47
+ const context = await browser.newContext(defaultContextOptions(config, undefined));
48
+ const page = await context.newPage();
49
+ try {
50
+ try {
51
+ await loginFn(page);
52
+ }
53
+ catch (e) {
54
+ console.error(chalk.red(`\nāœ— Login script threw: ${formatError(e)}`));
55
+ console.error(chalk.gray(` Last URL: ${page.url()}`));
56
+ console.error(chalk.yellow(`\nHint:\n` +
57
+ ` - Re-run with --headed to watch the flow live: \`kagemusha login --headed\`\n` +
58
+ ` - Verify form selectors in .kagemusha/login.mjs match the live page\n` +
59
+ ` - Check that the credentials env vars are correct`));
60
+ throw new LoginError(`login script threw: ${formatError(e)}`);
61
+ }
62
+ const landingUrl = page.url();
63
+ const landingPath = new URL(landingUrl).pathname;
64
+ // Verify login actually succeeded — landing on /login* means we failed silently.
65
+ if (landingPath.startsWith("/login") || landingPath === "/") {
66
+ console.error(chalk.red(`\nāœ— Login script completed but the page is still on ${landingPath}.`));
67
+ console.error(chalk.yellow(`\nHint:\n` +
68
+ ` - Re-run with \`kagemusha login --headed\` to see the live flow\n` +
69
+ ` - Verify selectors / credentials in .kagemusha/login.mjs`));
70
+ throw new LoginError(`stuck on ${landingPath} after login script`);
71
+ }
72
+ // Verify the storageState actually has cookies (= a session was established).
73
+ const state = await context.storageState();
74
+ const cookieCount = state.cookies?.length ?? 0;
75
+ if (cookieCount === 0) {
76
+ console.warn(chalk.yellow(`⚠ Login script finished but no cookies were set — the saved session may be empty.`));
77
+ }
78
+ const authStatePath = getAuthStatePath(projectRoot);
79
+ fs.mkdirSync(path.dirname(authStatePath), { recursive: true });
80
+ await context.storageState({ path: authStatePath });
81
+ const metaPath = getAuthMetaPath(projectRoot);
82
+ fs.writeFileSync(metaPath, JSON.stringify({ loginPath: "/login", landingPath }, null, 2));
83
+ console.log(chalk.bold.green("\nāœ… Session saved"));
84
+ console.log(chalk.gray(` Landing: ${landingPath} (${cookieCount} cookies)\n`));
85
+ }
86
+ finally {
87
+ await browser.close();
88
+ }
89
+ };
90
+ const formatError = (e) => e instanceof Error ? e.message : String(e);
91
+ const runInteractiveLogin = async (config, projectRoot) => {
92
+ console.log(chalk.bold("\n🄷 Kagemusha — Login\n"));
93
+ const inquirer = await import("inquirer");
94
+ const { loginPath } = await inquirer.default.prompt({
95
+ type: "input",
96
+ name: "loginPath",
97
+ message: "Login page path (e.g. /login):",
98
+ default: "/login",
99
+ });
100
+ const loginUrl = new URL(loginPath, config.app.baseUrl).toString();
101
+ const { chromium } = await import("playwright-chromium");
102
+ const browser = await chromium.launch({ headless: false });
103
+ const context = await browser.newContext(defaultContextOptions(config, undefined));
104
+ const page = await context.newPage();
105
+ console.log(chalk.blue(`🌐 Opening ${loginUrl}...`));
106
+ console.log(chalk.gray(" Log in manually in the browser.\n"));
107
+ await page.goto(loginUrl, { waitUntil: "networkidle" });
108
+ await inquirer.default.prompt({
109
+ type: "confirm",
110
+ name: "done",
111
+ message: "Done logging in?",
112
+ default: true,
113
+ });
114
+ const landingUrl = page.url();
115
+ const landingPath = new URL(landingUrl).pathname;
116
+ if (landingPath === loginPath) {
117
+ console.log(chalk.yellow(`\n⚠ Still on ${loginPath} — looks like login wasn't completed.`));
118
+ console.log(chalk.yellow(" Session not saved. Re-run 'kagemusha login' after signing in.\n"));
119
+ await browser.close();
120
+ return;
121
+ }
122
+ const authStatePath = getAuthStatePath(projectRoot);
123
+ fs.mkdirSync(path.dirname(authStatePath), { recursive: true });
124
+ await context.storageState({ path: authStatePath });
125
+ const metaPath = getAuthMetaPath(projectRoot);
126
+ fs.writeFileSync(metaPath, JSON.stringify({ loginPath, landingPath }, null, 2));
127
+ await browser.close();
128
+ console.log(chalk.bold.green("\nāœ… Session saved"));
129
+ console.log(chalk.gray(` Landing page: ${landingPath}\n`));
130
+ };
131
+ //# sourceMappingURL=login.js.map