laxy-verify 0.1.2 → 1.0.0
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 +150 -163
- package/dist/badge.d.ts +1 -0
- package/dist/badge.js +11 -0
- package/dist/build.d.ts +11 -0
- package/dist/build.js +59 -0
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +257 -102
- package/dist/comment.d.ts +20 -0
- package/dist/comment.js +53 -0
- package/dist/config.d.ts +34 -16
- package/dist/config.js +118 -55
- package/dist/detect.d.ts +10 -0
- package/dist/detect.js +97 -0
- package/dist/github.d.ts +8 -0
- package/dist/github.js +11 -0
- package/dist/grade.d.ts +37 -0
- package/dist/grade.js +57 -0
- package/dist/init.d.ts +1 -0
- package/dist/init.js +85 -0
- package/dist/lighthouse.d.ts +7 -0
- package/dist/lighthouse.js +94 -0
- package/dist/serve.d.ts +12 -0
- package/dist/serve.js +83 -0
- package/dist/status.d.ts +6 -0
- package/dist/status.js +33 -0
- package/package.json +29 -44
- package/action.yml +0 -97
- package/dist/build-runner.d.ts +0 -22
- package/dist/build-runner.js +0 -156
- package/dist/build-runner.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/dev-server.d.ts +0 -8
- package/dist/dev-server.js +0 -81
- package/dist/dev-server.js.map +0 -1
- package/dist/lighthouse-runner.d.ts +0 -10
- package/dist/lighthouse-runner.js +0 -119
- package/dist/lighthouse-runner.js.map +0 -1
- package/dist/project-runtime.d.ts +0 -32
- package/dist/project-runtime.js +0 -99
- package/dist/project-runtime.js.map +0 -1
- package/dist/reporter.d.ts +0 -21
- package/dist/reporter.js +0 -100
- package/dist/reporter.js.map +0 -1
- package/dist/verification.d.ts +0 -42
- package/dist/verification.js +0 -105
- package/dist/verification.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,102 +1,257 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { runBuild } from "./build
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { loadConfig } from "./config.js";
|
|
5
|
+
import { detect } from "./detect.js";
|
|
6
|
+
import { runBuild } from "./build.js";
|
|
7
|
+
import { startDevServer, stopDevServer } from "./serve.js";
|
|
8
|
+
import { runLighthouse } from "./lighthouse.js";
|
|
9
|
+
import { calculateGrade } from "./grade.js";
|
|
10
|
+
import { runInit } from "./init.js";
|
|
11
|
+
import { generateBadge } from "./badge.js";
|
|
12
|
+
import { postPRComment } from "./comment.js";
|
|
13
|
+
import { createStatusCheck } from "./status.js";
|
|
14
|
+
function parseArgs() {
|
|
15
|
+
const raw = process.argv.slice(2);
|
|
16
|
+
// Single-pass: collect flags and first positional
|
|
17
|
+
let projectDir = ".";
|
|
18
|
+
const flags = {};
|
|
19
|
+
for (let i = 0; i < raw.length; i++) {
|
|
20
|
+
const arg = raw[i];
|
|
21
|
+
if (arg.startsWith("--")) {
|
|
22
|
+
const eqIndex = arg.indexOf("=");
|
|
23
|
+
if (eqIndex >= 0) {
|
|
24
|
+
const key = arg.slice(2, eqIndex);
|
|
25
|
+
flags[key] = arg.slice(eqIndex + 1);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const key = arg.slice(2);
|
|
29
|
+
// Check if next arg is a value
|
|
30
|
+
if (i + 1 < raw.length && !raw[i + 1].startsWith("-")) {
|
|
31
|
+
flags[key] = raw[++i];
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
flags[key] = "true";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Only first non-flag arg is positional (projectDir)
|
|
40
|
+
if (projectDir === ".") {
|
|
41
|
+
projectDir = arg;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
projectDir: path.resolve(projectDir),
|
|
47
|
+
format: flags["format"] ?? "console",
|
|
48
|
+
ciMode: flags["ci"] !== undefined || process.env.CI === "true",
|
|
49
|
+
configPath: flags["config"],
|
|
50
|
+
failOn: flags["fail-on"] ?? undefined,
|
|
51
|
+
skipLighthouse: flags["skip-lighthouse"] !== undefined,
|
|
52
|
+
badge: flags["badge"] !== undefined,
|
|
53
|
+
init: flags["init"] !== undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function writeResultFile(projectDir, result) {
|
|
57
|
+
const filePath = path.join(projectDir, ".laxy-result.json");
|
|
58
|
+
fs.writeFileSync(filePath, JSON.stringify(result, null, 2) + "\n", "utf-8");
|
|
59
|
+
}
|
|
60
|
+
function consoleOutput(result) {
|
|
61
|
+
const gradeLabel = result.grade;
|
|
62
|
+
const checkEmoji = result.grade !== "Unverified" ? " ✅" : "";
|
|
63
|
+
console.log(`\n Laxy Verify — ${gradeLabel}${checkEmoji}`);
|
|
64
|
+
console.log(` Build: ${result.build.success ? `OK (${result.build.durationMs}ms)` : "FAILED"}`);
|
|
65
|
+
if (result.build.errors.length > 0) {
|
|
66
|
+
const last5 = result.build.errors.slice(-5);
|
|
67
|
+
console.log(` Errors:`);
|
|
68
|
+
for (const e of last5)
|
|
69
|
+
console.error(` ${e}`);
|
|
70
|
+
}
|
|
71
|
+
if (result.lighthouse !== null) {
|
|
72
|
+
const lh = result.lighthouse;
|
|
73
|
+
const t = result.thresholds;
|
|
74
|
+
const check = (passed) => passed ? " ✅" : " ❌";
|
|
75
|
+
console.log(` Lighthouse:`);
|
|
76
|
+
console.log(` Performance: ${lh.performance} / ${t.performance}${check(lh.performance >= t.performance)}`);
|
|
77
|
+
console.log(` Accessibility: ${lh.accessibility} / ${t.accessibility}${check(lh.accessibility >= t.accessibility)}`);
|
|
78
|
+
console.log(` SEO: ${lh.seo} / ${t.seo}${check(lh.seo >= t.seo)}`);
|
|
79
|
+
console.log(` Best Practices: ${lh.bestPractices} / ${t.bestPractices}${check(lh.bestPractices >= t.bestPractices)}`);
|
|
80
|
+
console.log(` Runs: ${lh.runs}`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.log(` Lighthouse: skipped`);
|
|
84
|
+
}
|
|
85
|
+
if (result.github) {
|
|
86
|
+
if (result.github.status === "comment_posted")
|
|
87
|
+
console.log(` PR comment: posted`);
|
|
88
|
+
if (result.github.status === "status_set")
|
|
89
|
+
console.log(` Status check: ${result.github.grade}`);
|
|
90
|
+
}
|
|
91
|
+
console.log(` Result: .laxy-result.json`);
|
|
92
|
+
console.log(` Exit code: ${result.exitCode}`);
|
|
93
|
+
}
|
|
94
|
+
async function run() {
|
|
95
|
+
const args = parseArgs();
|
|
96
|
+
// --init
|
|
97
|
+
if (args.init) {
|
|
98
|
+
runInit(args.projectDir);
|
|
99
|
+
process.exit(0);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// --badge
|
|
103
|
+
if (args.badge) {
|
|
104
|
+
const resultPath = path.join(args.projectDir, ".laxy-result.json");
|
|
105
|
+
if (!fs.existsSync(resultPath)) {
|
|
106
|
+
console.error("Error: .laxy-result.json not found. Run `npx laxy-verify .` first to generate it.");
|
|
107
|
+
process.exit(2);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const content = JSON.parse(fs.readFileSync(resultPath, "utf-8"));
|
|
111
|
+
const badge = generateBadge(content.grade);
|
|
112
|
+
console.log(badge);
|
|
113
|
+
process.exit(0);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Load config
|
|
117
|
+
let config;
|
|
118
|
+
try {
|
|
119
|
+
config = loadConfig({
|
|
120
|
+
dir: args.projectDir,
|
|
121
|
+
configPath: args.configPath,
|
|
122
|
+
ciMode: args.ciMode,
|
|
123
|
+
cliFlags: {
|
|
124
|
+
failOn: args.failOn,
|
|
125
|
+
skipLighthouse: args.skipLighthouse,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
console.error(`Config error: ${err instanceof Error ? err.message : String(err)}`);
|
|
131
|
+
process.exit(2);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Auto-detect framework + package manager
|
|
135
|
+
let detected;
|
|
136
|
+
try {
|
|
137
|
+
detected = detect(args.projectDir);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
console.error(`Detection error: ${err instanceof Error ? err.message : String(err)}`);
|
|
141
|
+
process.exit(2);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
// Merge config overrides
|
|
145
|
+
const buildCmd = config.build_command || detected.buildCmd;
|
|
146
|
+
const devCmd = config.dev_command || detected.devCmd;
|
|
147
|
+
const port = config.port;
|
|
148
|
+
// Phase 1: Build
|
|
149
|
+
let buildResult;
|
|
150
|
+
try {
|
|
151
|
+
buildResult = await runBuild(buildCmd, config.build_timeout);
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
buildResult = {
|
|
155
|
+
success: false,
|
|
156
|
+
durationMs: 0,
|
|
157
|
+
errors: err instanceof Error ? [err.message] : [String(err)],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
let scores = undefined;
|
|
161
|
+
let lighthouseResult = null;
|
|
162
|
+
const adjustedThresholds = {
|
|
163
|
+
performance: config.ciMode
|
|
164
|
+
? config.thresholds.performance - 10
|
|
165
|
+
: config.thresholds.performance,
|
|
166
|
+
accessibility: config.thresholds.accessibility,
|
|
167
|
+
seo: config.thresholds.seo,
|
|
168
|
+
bestPractices: config.thresholds.bestPractices,
|
|
169
|
+
};
|
|
170
|
+
// Phase 2: Dev server + Lighthouse (only if build succeeded and not skipped)
|
|
171
|
+
if (buildResult.success && !args.skipLighthouse) {
|
|
172
|
+
let servePid;
|
|
173
|
+
try {
|
|
174
|
+
const serve = await startDevServer(devCmd, port, config.dev_timeout);
|
|
175
|
+
servePid = serve.pid;
|
|
176
|
+
try {
|
|
177
|
+
const lhResult = await runLighthouse(port, config.lighthouse_runs);
|
|
178
|
+
scores = lhResult.scores ?? undefined;
|
|
179
|
+
if (scores) {
|
|
180
|
+
lighthouseResult = {
|
|
181
|
+
performance: scores.performance,
|
|
182
|
+
accessibility: scores.accessibility,
|
|
183
|
+
seo: scores.seo,
|
|
184
|
+
bestPractices: scores.bestPractices,
|
|
185
|
+
runs: config.lighthouse_runs,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (lhErr) {
|
|
190
|
+
console.error(`Lighthouse error: ${lhErr instanceof Error ? lhErr.message : String(lhErr)}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch (serveErr) {
|
|
194
|
+
console.error(`Dev server error: ${serveErr instanceof Error ? serveErr.message : String(serveErr)}`);
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
if (servePid) {
|
|
198
|
+
stopDevServer(servePid);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Calculate grade
|
|
203
|
+
const gradeResult = calculateGrade({
|
|
204
|
+
buildSuccess: buildResult.success,
|
|
205
|
+
scores,
|
|
206
|
+
thresholds: adjustedThresholds,
|
|
207
|
+
failOn: config.fail_on,
|
|
208
|
+
});
|
|
209
|
+
// Build result object
|
|
210
|
+
const resultObj = {
|
|
211
|
+
grade: gradeResult.grade.charAt(0).toUpperCase() + gradeResult.grade.slice(1), // Capitalize
|
|
212
|
+
timestamp: new Date().toISOString(),
|
|
213
|
+
build: {
|
|
214
|
+
success: buildResult.success,
|
|
215
|
+
durationMs: buildResult.durationMs,
|
|
216
|
+
errors: buildResult.errors,
|
|
217
|
+
},
|
|
218
|
+
lighthouse: lighthouseResult,
|
|
219
|
+
thresholds: adjustedThresholds,
|
|
220
|
+
ciMode: config.ciMode,
|
|
221
|
+
framework: detected.framework,
|
|
222
|
+
exitCode: gradeResult.exitCode,
|
|
223
|
+
config_fail_on: config.fail_on,
|
|
224
|
+
};
|
|
225
|
+
// GitHub integration (only in Actions)
|
|
226
|
+
const inGitHubActions = !!process.env.GITHUB_ACTIONS;
|
|
227
|
+
if (inGitHubActions) {
|
|
228
|
+
try {
|
|
229
|
+
if (process.env.GITHUB_EVENT_NAME === "pull_request") {
|
|
230
|
+
await postPRComment(resultObj);
|
|
231
|
+
resultObj.github = { status: "comment_posted", grade: resultObj.grade };
|
|
232
|
+
}
|
|
233
|
+
await createStatusCheck({ grade: resultObj.grade, exitCode: resultObj.exitCode });
|
|
234
|
+
resultObj.github ??= { status: "status_set", grade: resultObj.grade };
|
|
235
|
+
}
|
|
236
|
+
catch (ghErr) {
|
|
237
|
+
console.error(`GitHub API warning: ${ghErr instanceof Error ? ghErr.message : String(ghErr)}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
writeResultFile(args.projectDir, resultObj);
|
|
241
|
+
// Output
|
|
242
|
+
if (args.format === "json") {
|
|
243
|
+
console.log(JSON.stringify(resultObj, null, 2));
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
consoleOutput(resultObj);
|
|
247
|
+
}
|
|
248
|
+
// Set $GITHUB_OUTPUT if in Actions
|
|
249
|
+
if (inGitHubActions && process.env.GITHUB_OUTPUT) {
|
|
250
|
+
fs.appendFileSync(process.env.GITHUB_OUTPUT, `grade=${resultObj.grade}\n`);
|
|
251
|
+
}
|
|
252
|
+
process.exit(gradeResult.exitCode);
|
|
253
|
+
}
|
|
254
|
+
run().catch((err) => {
|
|
255
|
+
console.error(`Fatal error: ${err instanceof Error ? err.message : String(err)}`);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface LaxyResult {
|
|
2
|
+
grade: string;
|
|
3
|
+
lighthouse: {
|
|
4
|
+
performance: number;
|
|
5
|
+
accessibility: number;
|
|
6
|
+
seo: number;
|
|
7
|
+
bestPractices: number;
|
|
8
|
+
runs: number;
|
|
9
|
+
} | null;
|
|
10
|
+
thresholds: {
|
|
11
|
+
performance: number;
|
|
12
|
+
accessibility: number;
|
|
13
|
+
seo: number;
|
|
14
|
+
bestPractices: number;
|
|
15
|
+
};
|
|
16
|
+
exitCode: number;
|
|
17
|
+
config_fail_on: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function postPRComment(result: LaxyResult): Promise<void>;
|
|
20
|
+
export {};
|
package/dist/comment.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import { getGitHubContext } from "./github.js";
|
|
3
|
+
export async function postPRComment(result) {
|
|
4
|
+
const ctx = getGitHubContext();
|
|
5
|
+
if (!ctx || ctx.eventName !== "pull_request")
|
|
6
|
+
return;
|
|
7
|
+
// Parse PR number from event
|
|
8
|
+
let prNumber = 0;
|
|
9
|
+
if (ctx.eventPath && fs.existsSync(ctx.eventPath)) {
|
|
10
|
+
const event = JSON.parse(fs.readFileSync(ctx.eventPath, "utf-8"));
|
|
11
|
+
prNumber = event.pull_request?.number ?? 0;
|
|
12
|
+
}
|
|
13
|
+
if (!prNumber)
|
|
14
|
+
return;
|
|
15
|
+
const grade = result.grade ?? "Unverified";
|
|
16
|
+
const lh = result.lighthouse;
|
|
17
|
+
const t = result.thresholds;
|
|
18
|
+
let lhTable = "";
|
|
19
|
+
if (lh) {
|
|
20
|
+
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`;
|
|
21
|
+
}
|
|
22
|
+
const emoji = grade === "Gold" ? "🥇" :
|
|
23
|
+
grade === "Silver" ? "🥈" :
|
|
24
|
+
grade === "Bronze" ? "🥉" : "⚪";
|
|
25
|
+
const body = `## ${emoji} Laxy Verify — **${grade}**
|
|
26
|
+
|
|
27
|
+
${grade === "Unverified" ? "The build failed or verification could not be completed." : `Build passed verification with a **${grade}** grade.`}
|
|
28
|
+
|
|
29
|
+
${lhTable}**Fail-on threshold**: ${result.config_fail_on ?? "bronze"}
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
[🔍 Laxy Verify](https://github.com/psungmin24/laxy-verify) — Frontend quality gate`;
|
|
33
|
+
const [owner, repo] = ctx.repository.split("/");
|
|
34
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/issues/${prNumber}/comments`;
|
|
35
|
+
try {
|
|
36
|
+
const res = await fetch(url, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: {
|
|
39
|
+
"Authorization": `Bearer ${ctx.token}`,
|
|
40
|
+
"Accept": "application/vnd.github.v3+json",
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify({ body }),
|
|
44
|
+
});
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
console.warn(`GitHub PR comment API returned ${res.status} — skipping comment`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
console.warn(`GitHub PR comment request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
export type FailOn = "unverified" | "bronze" | "silver" | "gold";
|
|
2
|
+
export interface Thresholds {
|
|
3
|
+
performance: number;
|
|
4
|
+
accessibility: number;
|
|
5
|
+
seo: number;
|
|
6
|
+
bestPractices: number;
|
|
7
|
+
}
|
|
8
|
+
export interface LaxyConfig {
|
|
9
|
+
framework: string;
|
|
10
|
+
build_command: string;
|
|
11
|
+
dev_command: string;
|
|
12
|
+
package_manager: string;
|
|
13
|
+
port: number;
|
|
14
|
+
build_timeout: number;
|
|
15
|
+
dev_timeout: number;
|
|
16
|
+
lighthouse_runs: number;
|
|
17
|
+
thresholds: Thresholds;
|
|
18
|
+
fail_on: FailOn;
|
|
19
|
+
}
|
|
20
|
+
export declare class ConfigParseError extends Error {
|
|
21
|
+
constructor(msg: string);
|
|
22
|
+
}
|
|
23
|
+
export interface LoadConfigOptions {
|
|
24
|
+
dir: string;
|
|
25
|
+
configPath?: string;
|
|
26
|
+
cliFlags?: {
|
|
27
|
+
failOn?: FailOn;
|
|
28
|
+
skipLighthouse?: boolean;
|
|
29
|
+
};
|
|
30
|
+
ciMode: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function loadConfig(options: LoadConfigOptions): LaxyConfig & {
|
|
33
|
+
ciMode: boolean;
|
|
34
|
+
};
|