laxy-verify 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/comment.d.ts CHANGED
@@ -1,21 +1,21 @@
1
- import type { TrendDelta } from "./trend.js";
2
- interface LaxyResult {
3
- grade: string;
4
- lighthouse: {
5
- performance: number;
6
- accessibility: number;
7
- seo: number;
8
- bestPractices: number;
9
- runs: number;
10
- } | null;
11
- thresholds: {
12
- performance: number;
13
- accessibility: number;
14
- seo: number;
15
- bestPractices: number;
16
- };
17
- exitCode: number;
18
- config_fail_on: string;
19
- }
20
- export declare function postPRComment(result: LaxyResult, trend?: TrendDelta | null): Promise<void>;
21
- export {};
1
+ import type { TrendDelta } from "./trend.js";
2
+ interface LaxyResult {
3
+ grade: string;
4
+ lighthouse: {
5
+ performance: number;
6
+ accessibility: number;
7
+ seo: number;
8
+ bestPractices: number;
9
+ runs: number;
10
+ } | null;
11
+ thresholds: {
12
+ performance: number;
13
+ accessibility: number;
14
+ seo: number;
15
+ bestPractices: number;
16
+ };
17
+ exitCode: number;
18
+ config_fail_on: string;
19
+ }
20
+ export declare function postPRComment(result: LaxyResult, trend?: TrendDelta | null): Promise<void>;
21
+ export {};
package/dist/comment.js CHANGED
@@ -1,106 +1,106 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.postPRComment = postPRComment;
37
- const fs = __importStar(require("node:fs"));
38
- const github_js_1 = require("./github.js");
39
- const trend_js_1 = require("./trend.js");
40
- function renderTrendTable(delta) {
41
- const lines = [
42
- "| Check | This PR | vs Base |",
43
- "|---|---|---|",
44
- ];
45
- const gradeUp = (0, trend_js_1.gradeIndex)(delta.grade.current) > (0, trend_js_1.gradeIndex)(delta.grade.base);
46
- const gradeDown = (0, trend_js_1.gradeIndex)(delta.grade.current) < (0, trend_js_1.gradeIndex)(delta.grade.base);
47
- const gradeTrendStr = gradeUp ? ` ↑ (was ${delta.grade.base})` :
48
- gradeDown ? ` ↓ (was ${delta.grade.base})` :
49
- "";
50
- lines.push(`| Grade | **${delta.grade.current}**${gradeTrendStr} | ${delta.grade.base} |`);
51
- function fmtDelta(d) {
52
- if (d === null)
53
- return "—";
54
- if (d > 0)
55
- return `+${d}`;
56
- if (d < 0)
57
- return `${d}`;
58
- return "—";
59
- }
60
- if (delta.performance.current !== null) {
61
- lines.push(`| Performance | ${delta.performance.current} | ${fmtDelta(delta.performance.delta)} |`);
62
- }
63
- if (delta.accessibility.current !== null) {
64
- lines.push(`| Accessibility | ${delta.accessibility.current} | ${fmtDelta(delta.accessibility.delta)} |`);
65
- }
66
- if (delta.seo.current !== null) {
67
- lines.push(`| SEO | ${delta.seo.current} | ${fmtDelta(delta.seo.delta)} |`);
68
- }
69
- if (delta.bestPractices.current !== null) {
70
- lines.push(`| Best Practices | ${delta.bestPractices.current} | ${fmtDelta(delta.bestPractices.delta)} |`);
71
- }
72
- if (delta.e2e.current !== null) {
73
- lines.push(`| E2E | ${delta.e2e.current} | ${delta.e2e.base ?? "—"} (base) |`);
74
- }
75
- return `${lines.join("\n")}\n`;
76
- }
77
- async function postPRComment(result, trend) {
78
- const ctx = (0, github_js_1.getGitHubContext)();
79
- if (!ctx || ctx.eventName !== "pull_request")
80
- return;
81
- let prNumber = 0;
82
- if (ctx.eventPath && fs.existsSync(ctx.eventPath)) {
83
- const event = JSON.parse(fs.readFileSync(ctx.eventPath, "utf-8"));
84
- prNumber = event.pull_request?.number ?? 0;
85
- }
86
- if (!prNumber)
87
- return;
88
- const grade = result.grade ?? "Unverified";
89
- const lh = result.lighthouse;
90
- const t = result.thresholds;
91
- let lhTable = "";
92
- if (lh) {
93
- lhTable = `| Performance | Accessibility | SEO | Best Practices |\n|---|---|---|---|\n| ${lh.performance} / ${t.performance} | ${lh.accessibility} / ${t.accessibility} | ${lh.seo} / ${t.seo} | ${lh.bestPractices} / ${t.bestPractices} |\n\n`;
94
- }
95
- const trendTable = trend ? `${renderTrendTable(trend)}\n` : "";
96
- const passed = result.exitCode === 0;
97
- const statusLabel = passed ? "[PASS]" : "[HOLD]";
98
- const headline = passed ? "No deployment blockers found" : "Deployment blockers found";
99
- const summary = passed
100
- ? `This PR passed the current verification gate. Grade summary: **${grade}**.`
101
- : grade === "Unverified"
102
- ? "The production build failed or verification could not complete, so this PR should be held."
103
- : `This PR did not clear the current verification gate. Grade summary: **${grade}**.`;
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.postPRComment = postPRComment;
37
+ const fs = __importStar(require("node:fs"));
38
+ const github_js_1 = require("./github.js");
39
+ const trend_js_1 = require("./trend.js");
40
+ function renderTrendTable(delta) {
41
+ const lines = [
42
+ "| Check | This PR | vs Base |",
43
+ "|---|---|---|",
44
+ ];
45
+ const gradeUp = (0, trend_js_1.gradeIndex)(delta.grade.current) > (0, trend_js_1.gradeIndex)(delta.grade.base);
46
+ const gradeDown = (0, trend_js_1.gradeIndex)(delta.grade.current) < (0, trend_js_1.gradeIndex)(delta.grade.base);
47
+ const gradeTrendStr = gradeUp ? ` ↑ (was ${delta.grade.base})` :
48
+ gradeDown ? ` ↓ (was ${delta.grade.base})` :
49
+ "";
50
+ lines.push(`| Grade | **${delta.grade.current}**${gradeTrendStr} | ${delta.grade.base} |`);
51
+ function fmtDelta(d) {
52
+ if (d === null)
53
+ return "—";
54
+ if (d > 0)
55
+ return `+${d}`;
56
+ if (d < 0)
57
+ return `${d}`;
58
+ return "—";
59
+ }
60
+ if (delta.performance.current !== null) {
61
+ lines.push(`| Performance | ${delta.performance.current} | ${fmtDelta(delta.performance.delta)} |`);
62
+ }
63
+ if (delta.accessibility.current !== null) {
64
+ lines.push(`| Accessibility | ${delta.accessibility.current} | ${fmtDelta(delta.accessibility.delta)} |`);
65
+ }
66
+ if (delta.seo.current !== null) {
67
+ lines.push(`| SEO | ${delta.seo.current} | ${fmtDelta(delta.seo.delta)} |`);
68
+ }
69
+ if (delta.bestPractices.current !== null) {
70
+ lines.push(`| Best Practices | ${delta.bestPractices.current} | ${fmtDelta(delta.bestPractices.delta)} |`);
71
+ }
72
+ if (delta.e2e.current !== null) {
73
+ lines.push(`| E2E | ${delta.e2e.current} | ${delta.e2e.base ?? "—"} (base) |`);
74
+ }
75
+ return `${lines.join("\n")}\n`;
76
+ }
77
+ async function postPRComment(result, trend) {
78
+ const ctx = (0, github_js_1.getGitHubContext)();
79
+ if (!ctx || ctx.eventName !== "pull_request")
80
+ return;
81
+ let prNumber = 0;
82
+ if (ctx.eventPath && fs.existsSync(ctx.eventPath)) {
83
+ const event = JSON.parse(fs.readFileSync(ctx.eventPath, "utf-8"));
84
+ prNumber = event.pull_request?.number ?? 0;
85
+ }
86
+ if (!prNumber)
87
+ return;
88
+ const grade = result.grade ?? "Unverified";
89
+ const lh = result.lighthouse;
90
+ const t = result.thresholds;
91
+ let lhTable = "";
92
+ if (lh) {
93
+ lhTable = `| Performance | Accessibility | SEO | Best Practices |\n|---|---|---|---|\n| ${lh.performance} / ${t.performance} | ${lh.accessibility} / ${t.accessibility} | ${lh.seo} / ${t.seo} | ${lh.bestPractices} / ${t.bestPractices} |\n\n`;
94
+ }
95
+ const trendTable = trend ? `${renderTrendTable(trend)}\n` : "";
96
+ const passed = result.exitCode === 0;
97
+ const statusLabel = passed ? "[PASS]" : "[HOLD]";
98
+ const headline = passed ? "No deployment blockers found" : "Deployment blockers found";
99
+ const summary = passed
100
+ ? `This PR passed the current verification gate. Grade summary: **${grade}**.`
101
+ : grade === "Unverified"
102
+ ? "The production build failed or verification could not complete, so this PR should be held."
103
+ : `This PR did not clear the current verification gate. Grade summary: **${grade}**.`;
104
104
  const body = `## ${statusLabel} Laxy Verify: ${headline}
105
105
 
106
106
  ${summary}
@@ -110,25 +110,25 @@ ${trendTable}${lhTable}**Fail-on threshold**: ${result.config_fail_on ?? "bronze
110
110
  Grade remains available for automation, but this check should be read first as a merge and release blocker gate.
111
111
 
112
112
  ---
113
- [Open laxy-verify docs](https://github.com/SUNgm24/Laxy/tree/main/laxy-verify)`;
114
- const [owner, repo] = ctx.repository.split("/");
115
- const url = `https://api.github.com/repos/${owner}/${repo}/issues/${prNumber}/comments`;
116
- try {
117
- const res = await fetch(url, {
118
- method: "POST",
119
- headers: {
120
- Authorization: `Bearer ${ctx.token}`,
121
- Accept: "application/vnd.github.v3+json",
122
- "Content-Type": "application/json",
123
- },
124
- body: JSON.stringify({ body }),
125
- });
126
- if (!res.ok) {
127
- console.warn(`GitHub PR comment API returned ${res.status}; skipping comment.`);
128
- return;
129
- }
130
- }
131
- catch (err) {
132
- console.warn(`GitHub PR comment request failed: ${err instanceof Error ? err.message : String(err)}`);
133
- }
134
- }
113
+ [Open laxy-verify docs](https://github.com/SUNgm24/Laxy/tree/main/laxy-verify)`;
114
+ const [owner, repo] = ctx.repository.split("/");
115
+ const url = `https://api.github.com/repos/${owner}/${repo}/issues/${prNumber}/comments`;
116
+ try {
117
+ const res = await fetch(url, {
118
+ method: "POST",
119
+ headers: {
120
+ Authorization: `Bearer ${ctx.token}`,
121
+ Accept: "application/vnd.github.v3+json",
122
+ "Content-Type": "application/json",
123
+ },
124
+ body: JSON.stringify({ body }),
125
+ });
126
+ if (!res.ok) {
127
+ console.warn(`GitHub PR comment API returned ${res.status}; skipping comment.`);
128
+ return;
129
+ }
130
+ }
131
+ catch (err) {
132
+ console.warn(`GitHub PR comment request failed: ${err instanceof Error ? err.message : String(err)}`);
133
+ }
134
+ }
package/dist/crawler.d.ts CHANGED
@@ -1,36 +1,36 @@
1
- import type { E2EScenario } from "./e2e.js";
2
- import type { VerificationTier } from "./verification-core/types.js";
3
- export interface CrawlPage {
4
- url: string;
5
- path: string;
6
- title: string;
7
- forms: CrawlForm[];
8
- buttons: string[];
9
- internalLinks: string[];
10
- hasConsoleErrors: boolean;
11
- consoleErrors: string[];
12
- }
13
- export interface CrawlForm {
14
- selector: string;
15
- inputs: {
16
- selector: string;
17
- type: string;
18
- placeholder?: string;
19
- }[];
20
- submitSelector?: string;
21
- }
22
- export interface CrawlResult {
23
- pages: CrawlPage[];
24
- totalLinks: number;
25
- crawledCount: number;
26
- }
27
- export interface CrawlOptions {
28
- maxDepth?: number;
29
- maxPages?: number;
30
- timeout?: number;
31
- }
32
- export declare function crawlApp(baseUrl: string, options?: CrawlOptions): Promise<CrawlResult>;
33
- /**
34
- * Generate E2E scenarios from crawl results.
35
- */
36
- export declare function buildScenariosFromCrawl(crawlResult: CrawlResult, tier: VerificationTier): E2EScenario[];
1
+ import type { E2EScenario } from "./e2e.js";
2
+ import type { VerificationTier } from "./verification-core/types.js";
3
+ export interface CrawlPage {
4
+ url: string;
5
+ path: string;
6
+ title: string;
7
+ forms: CrawlForm[];
8
+ buttons: string[];
9
+ internalLinks: string[];
10
+ hasConsoleErrors: boolean;
11
+ consoleErrors: string[];
12
+ }
13
+ export interface CrawlForm {
14
+ selector: string;
15
+ inputs: {
16
+ selector: string;
17
+ type: string;
18
+ placeholder?: string;
19
+ }[];
20
+ submitSelector?: string;
21
+ }
22
+ export interface CrawlResult {
23
+ pages: CrawlPage[];
24
+ totalLinks: number;
25
+ crawledCount: number;
26
+ }
27
+ export interface CrawlOptions {
28
+ maxDepth?: number;
29
+ maxPages?: number;
30
+ timeout?: number;
31
+ }
32
+ export declare function crawlApp(baseUrl: string, options?: CrawlOptions): Promise<CrawlResult>;
33
+ /**
34
+ * Generate E2E scenarios from crawl results.
35
+ */
36
+ export declare function buildScenariosFromCrawl(crawlResult: CrawlResult, tier: VerificationTier): E2EScenario[];