@code-pushup/lighthouse-plugin 0.45.0 → 0.46.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/index.js +90 -100
- package/package.json +4 -4
- package/src/lib/normalize-flags.d.ts +1 -2
- package/src/lib/runner/constants.d.ts +1 -2
- package/src/lib/runner/types.d.ts +0 -2
- package/src/lib/runner/utils.d.ts +4 -4
package/index.js
CHANGED
|
@@ -110,6 +110,7 @@ var fileNameSchema = z.string().trim().regex(filenameRegex, {
|
|
|
110
110
|
}).min(1, { message: "file name is invalid" });
|
|
111
111
|
var positiveIntSchema = z.number().int().positive();
|
|
112
112
|
var nonnegativeIntSchema = z.number().int().nonnegative();
|
|
113
|
+
var nonnegativeNumberSchema = z.number().nonnegative();
|
|
113
114
|
function packageVersionSchema(options) {
|
|
114
115
|
const { versionDescription = "NPM version of the package", required } = options ?? {};
|
|
115
116
|
const packageSchema = z.string({ description: "NPM package name" });
|
|
@@ -122,7 +123,7 @@ function packageVersionSchema(options) {
|
|
|
122
123
|
{ description: "NPM package name and version of a published package" }
|
|
123
124
|
);
|
|
124
125
|
}
|
|
125
|
-
var weightSchema =
|
|
126
|
+
var weightSchema = nonnegativeNumberSchema.describe(
|
|
126
127
|
"Coefficient for the given score (use weight 0 if only for display)"
|
|
127
128
|
);
|
|
128
129
|
function weightedRefSchema(description, slugDescription) {
|
|
@@ -264,7 +265,7 @@ var tableObjectSchema = tableSharedSchema.merge(
|
|
|
264
265
|
var tableSchema = (description = "Table information") => z4.union([tablePrimitiveSchema, tableObjectSchema], { description });
|
|
265
266
|
|
|
266
267
|
// packages/models/src/lib/audit-output.ts
|
|
267
|
-
var auditValueSchema =
|
|
268
|
+
var auditValueSchema = nonnegativeNumberSchema.describe("Raw numeric value");
|
|
268
269
|
var auditDisplayValueSchema = z5.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" }).optional();
|
|
269
270
|
var auditDetailsSchema = z5.object(
|
|
270
271
|
{
|
|
@@ -708,6 +709,79 @@ var LIGHTHOUSE_OUTPUT_PATH = join(
|
|
|
708
709
|
// packages/plugin-lighthouse/src/lib/normalize-flags.ts
|
|
709
710
|
import chalk6 from "chalk";
|
|
710
711
|
|
|
712
|
+
// packages/utils/src/lib/file-system.ts
|
|
713
|
+
import { bundleRequire } from "bundle-require";
|
|
714
|
+
import chalk2 from "chalk";
|
|
715
|
+
import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
|
|
716
|
+
|
|
717
|
+
// packages/utils/src/lib/logging.ts
|
|
718
|
+
import isaacs_cliui from "@isaacs/cliui";
|
|
719
|
+
import { cliui } from "@poppinss/cliui";
|
|
720
|
+
import chalk from "chalk";
|
|
721
|
+
|
|
722
|
+
// packages/utils/src/lib/reports/constants.ts
|
|
723
|
+
var TERMINAL_WIDTH = 80;
|
|
724
|
+
|
|
725
|
+
// packages/utils/src/lib/logging.ts
|
|
726
|
+
var singletonUiInstance;
|
|
727
|
+
function ui() {
|
|
728
|
+
if (singletonUiInstance === void 0) {
|
|
729
|
+
singletonUiInstance = cliui();
|
|
730
|
+
}
|
|
731
|
+
return {
|
|
732
|
+
...singletonUiInstance,
|
|
733
|
+
row: (args) => {
|
|
734
|
+
logListItem(args);
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
var singletonisaacUi;
|
|
739
|
+
function logListItem(args) {
|
|
740
|
+
if (singletonisaacUi === void 0) {
|
|
741
|
+
singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
|
|
742
|
+
}
|
|
743
|
+
singletonisaacUi.div(...args);
|
|
744
|
+
const content = singletonisaacUi.toString();
|
|
745
|
+
singletonisaacUi.rows = [];
|
|
746
|
+
singletonUiInstance?.logger.log(content);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// packages/utils/src/lib/file-system.ts
|
|
750
|
+
async function readTextFile(path) {
|
|
751
|
+
const buffer = await readFile(path);
|
|
752
|
+
return buffer.toString();
|
|
753
|
+
}
|
|
754
|
+
async function readJsonFile(path) {
|
|
755
|
+
const text = await readTextFile(path);
|
|
756
|
+
return JSON.parse(text);
|
|
757
|
+
}
|
|
758
|
+
async function ensureDirectoryExists(baseDir) {
|
|
759
|
+
try {
|
|
760
|
+
await mkdir(baseDir, { recursive: true });
|
|
761
|
+
return;
|
|
762
|
+
} catch (error) {
|
|
763
|
+
ui().logger.info(error.message);
|
|
764
|
+
if (error.code !== "EEXIST") {
|
|
765
|
+
throw error;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
var NoExportError = class extends Error {
|
|
770
|
+
constructor(filepath) {
|
|
771
|
+
super(`No default export found in ${filepath}`);
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
async function importEsmModule(options) {
|
|
775
|
+
const { mod } = await bundleRequire({
|
|
776
|
+
format: "esm",
|
|
777
|
+
...options
|
|
778
|
+
});
|
|
779
|
+
if (!("default" in mod)) {
|
|
780
|
+
throw new NoExportError(options.filepath);
|
|
781
|
+
}
|
|
782
|
+
return mod.default;
|
|
783
|
+
}
|
|
784
|
+
|
|
711
785
|
// packages/utils/src/lib/text-formats/constants.ts
|
|
712
786
|
var NEW_LINE = "\n";
|
|
713
787
|
var TAB = " ";
|
|
@@ -983,79 +1057,6 @@ var html = {
|
|
|
983
1057
|
table
|
|
984
1058
|
};
|
|
985
1059
|
|
|
986
|
-
// packages/utils/src/lib/file-system.ts
|
|
987
|
-
import { bundleRequire } from "bundle-require";
|
|
988
|
-
import chalk2 from "chalk";
|
|
989
|
-
import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
|
|
990
|
-
|
|
991
|
-
// packages/utils/src/lib/logging.ts
|
|
992
|
-
import isaacs_cliui from "@isaacs/cliui";
|
|
993
|
-
import { cliui } from "@poppinss/cliui";
|
|
994
|
-
import chalk from "chalk";
|
|
995
|
-
|
|
996
|
-
// packages/utils/src/lib/reports/constants.ts
|
|
997
|
-
var TERMINAL_WIDTH = 80;
|
|
998
|
-
|
|
999
|
-
// packages/utils/src/lib/logging.ts
|
|
1000
|
-
var singletonUiInstance;
|
|
1001
|
-
function ui() {
|
|
1002
|
-
if (singletonUiInstance === void 0) {
|
|
1003
|
-
singletonUiInstance = cliui();
|
|
1004
|
-
}
|
|
1005
|
-
return {
|
|
1006
|
-
...singletonUiInstance,
|
|
1007
|
-
row: (args) => {
|
|
1008
|
-
logListItem(args);
|
|
1009
|
-
}
|
|
1010
|
-
};
|
|
1011
|
-
}
|
|
1012
|
-
var singletonisaacUi;
|
|
1013
|
-
function logListItem(args) {
|
|
1014
|
-
if (singletonisaacUi === void 0) {
|
|
1015
|
-
singletonisaacUi = isaacs_cliui({ width: TERMINAL_WIDTH });
|
|
1016
|
-
}
|
|
1017
|
-
singletonisaacUi.div(...args);
|
|
1018
|
-
const content = singletonisaacUi.toString();
|
|
1019
|
-
singletonisaacUi.rows = [];
|
|
1020
|
-
singletonUiInstance?.logger.log(content);
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
// packages/utils/src/lib/file-system.ts
|
|
1024
|
-
async function readTextFile(path2) {
|
|
1025
|
-
const buffer = await readFile(path2);
|
|
1026
|
-
return buffer.toString();
|
|
1027
|
-
}
|
|
1028
|
-
async function readJsonFile(path2) {
|
|
1029
|
-
const text = await readTextFile(path2);
|
|
1030
|
-
return JSON.parse(text);
|
|
1031
|
-
}
|
|
1032
|
-
async function ensureDirectoryExists(baseDir) {
|
|
1033
|
-
try {
|
|
1034
|
-
await mkdir(baseDir, { recursive: true });
|
|
1035
|
-
return;
|
|
1036
|
-
} catch (error) {
|
|
1037
|
-
ui().logger.info(error.message);
|
|
1038
|
-
if (error.code !== "EEXIST") {
|
|
1039
|
-
throw error;
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
var NoExportError = class extends Error {
|
|
1044
|
-
constructor(filepath) {
|
|
1045
|
-
super(`No default export found in ${filepath}`);
|
|
1046
|
-
}
|
|
1047
|
-
};
|
|
1048
|
-
async function importEsmModule(options) {
|
|
1049
|
-
const { mod } = await bundleRequire({
|
|
1050
|
-
format: "esm",
|
|
1051
|
-
...options
|
|
1052
|
-
});
|
|
1053
|
-
if (!("default" in mod)) {
|
|
1054
|
-
throw new NoExportError(options.filepath);
|
|
1055
|
-
}
|
|
1056
|
-
return mod.default;
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
1060
|
// packages/utils/src/lib/reports/utils.ts
|
|
1060
1061
|
var { image: image2, bold: boldMd } = md;
|
|
1061
1062
|
|
|
@@ -1156,8 +1157,8 @@ async function loadLighthouseAudit(value) {
|
|
|
1156
1157
|
if (typeof value === "function") {
|
|
1157
1158
|
return value;
|
|
1158
1159
|
}
|
|
1159
|
-
const
|
|
1160
|
-
const module = await import(`lighthouse/core/audits/${
|
|
1160
|
+
const path = typeof value === "string" ? value : value.path;
|
|
1161
|
+
const module = await import(`lighthouse/core/audits/${path}.js`);
|
|
1161
1162
|
return module.default;
|
|
1162
1163
|
}
|
|
1163
1164
|
var LIGHTHOUSE_REPORT_NAME = "lighthouse-report.json";
|
|
@@ -1165,7 +1166,6 @@ var DEFAULT_CLI_FLAGS = {
|
|
|
1165
1166
|
// default values extracted from
|
|
1166
1167
|
// https://github.com/GoogleChrome/lighthouse/blob/7d80178c37a1b600ea8f092fc0b098029799a659/cli/cli-flags.js#L80
|
|
1167
1168
|
verbose: false,
|
|
1168
|
-
quiet: false,
|
|
1169
1169
|
saveAssets: false,
|
|
1170
1170
|
// needed to pass CI on linux and windows (locally it works without headless too)
|
|
1171
1171
|
chromeFlags: ["--headless=shell"],
|
|
@@ -1174,10 +1174,11 @@ var DEFAULT_CLI_FLAGS = {
|
|
|
1174
1174
|
view: false,
|
|
1175
1175
|
channel: "cli",
|
|
1176
1176
|
// custom overwrites in favour of the plugin
|
|
1177
|
+
// hide logs by default
|
|
1178
|
+
quiet: true,
|
|
1177
1179
|
onlyAudits: [],
|
|
1178
1180
|
skipAudits: [],
|
|
1179
1181
|
onlyCategories: [],
|
|
1180
|
-
budgets: [],
|
|
1181
1182
|
output: ["json"],
|
|
1182
1183
|
outputPath: join2(LIGHTHOUSE_OUTPUT_PATH, LIGHTHOUSE_REPORT_NAME)
|
|
1183
1184
|
};
|
|
@@ -1188,7 +1189,6 @@ import log from "lighthouse-logger";
|
|
|
1188
1189
|
import desktopConfig from "lighthouse/core/config/desktop-config.js";
|
|
1189
1190
|
import experimentalConfig from "lighthouse/core/config/experimental-config.js";
|
|
1190
1191
|
import perfConfig from "lighthouse/core/config/perf-config.js";
|
|
1191
|
-
import path from "node:path";
|
|
1192
1192
|
function normalizeAuditOutputs(auditOutputs, flags = { skipAudits: [] }) {
|
|
1193
1193
|
const toSkip = new Set(flags.skipAudits ?? []);
|
|
1194
1194
|
return auditOutputs.filter(({ slug }) => {
|
|
@@ -1260,17 +1260,18 @@ function logUnsupportedDetails(lhrAudits, { displayCount = 3 } = {}) {
|
|
|
1260
1260
|
);
|
|
1261
1261
|
}
|
|
1262
1262
|
}
|
|
1263
|
-
function
|
|
1263
|
+
function determineAndSetLogLevel({
|
|
1264
1264
|
verbose,
|
|
1265
1265
|
quiet
|
|
1266
1266
|
} = {}) {
|
|
1267
|
+
let logLevel = "info";
|
|
1267
1268
|
if (verbose) {
|
|
1268
|
-
|
|
1269
|
+
logLevel = "verbose";
|
|
1269
1270
|
} else if (quiet) {
|
|
1270
|
-
|
|
1271
|
-
} else {
|
|
1272
|
-
log.setLevel("info");
|
|
1271
|
+
logLevel = "silent";
|
|
1273
1272
|
}
|
|
1273
|
+
log.setLevel(logLevel);
|
|
1274
|
+
return logLevel;
|
|
1274
1275
|
}
|
|
1275
1276
|
async function getConfig(options = {}) {
|
|
1276
1277
|
const { configPath: filepath, preset } = options;
|
|
@@ -1296,14 +1297,6 @@ async function getConfig(options = {}) {
|
|
|
1296
1297
|
}
|
|
1297
1298
|
return void 0;
|
|
1298
1299
|
}
|
|
1299
|
-
async function getBudgets(budgetPath) {
|
|
1300
|
-
if (budgetPath) {
|
|
1301
|
-
return await readJsonFile(
|
|
1302
|
-
path.resolve(process.cwd(), budgetPath)
|
|
1303
|
-
);
|
|
1304
|
-
}
|
|
1305
|
-
return [];
|
|
1306
|
-
}
|
|
1307
1300
|
|
|
1308
1301
|
// packages/plugin-lighthouse/src/lib/runner/runner.ts
|
|
1309
1302
|
function createRunnerFunction(urlUnderTest, flags = DEFAULT_CLI_FLAGS) {
|
|
@@ -1311,21 +1304,18 @@ function createRunnerFunction(urlUnderTest, flags = DEFAULT_CLI_FLAGS) {
|
|
|
1311
1304
|
const {
|
|
1312
1305
|
configPath,
|
|
1313
1306
|
preset,
|
|
1314
|
-
budgetPath,
|
|
1315
|
-
budgets,
|
|
1316
1307
|
outputPath,
|
|
1317
1308
|
...parsedFlags
|
|
1318
1309
|
} = flags;
|
|
1319
|
-
|
|
1310
|
+
const logLevel = determineAndSetLogLevel(parsedFlags);
|
|
1320
1311
|
const config = await getConfig({ configPath, preset });
|
|
1321
|
-
|
|
1322
|
-
if (typeof outputPath === "string") {
|
|
1312
|
+
if (outputPath) {
|
|
1323
1313
|
await ensureDirectoryExists(dirname(outputPath));
|
|
1324
1314
|
}
|
|
1325
1315
|
const enrichedFlags = {
|
|
1326
1316
|
...parsedFlags,
|
|
1327
|
-
|
|
1328
|
-
|
|
1317
|
+
logLevel,
|
|
1318
|
+
outputPath
|
|
1329
1319
|
};
|
|
1330
1320
|
const runnerResult = await runLighthouse(
|
|
1331
1321
|
urlUnderTest,
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-pushup/lighthouse-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@code-pushup/models": "0.
|
|
7
|
-
"lighthouse": "^
|
|
8
|
-
"@code-pushup/utils": "0.
|
|
6
|
+
"@code-pushup/models": "0.46.0",
|
|
7
|
+
"lighthouse": "^12.0.0",
|
|
8
|
+
"@code-pushup/utils": "0.46.0",
|
|
9
9
|
"lighthouse-logger": "2.0.1",
|
|
10
10
|
"chalk": "^5.3.0"
|
|
11
11
|
},
|
|
@@ -3,16 +3,15 @@ import type { LighthouseOptions } from './types';
|
|
|
3
3
|
export declare const DEFAULT_LIGHTHOUSE_OPTIONS: {
|
|
4
4
|
onlyGroups: never[];
|
|
5
5
|
verbose: false;
|
|
6
|
-
quiet: false;
|
|
7
6
|
saveAssets: false;
|
|
8
7
|
chromeFlags: string[];
|
|
9
8
|
port: number;
|
|
10
9
|
hostname: string;
|
|
11
10
|
view: false;
|
|
12
11
|
channel: string;
|
|
12
|
+
quiet: true;
|
|
13
13
|
onlyAudits: never[];
|
|
14
14
|
skipAudits: never[];
|
|
15
|
-
budgets: never[];
|
|
16
15
|
output: "json"[];
|
|
17
16
|
outputPath: string;
|
|
18
17
|
};
|
|
@@ -5,17 +5,16 @@ export declare const LIGHTHOUSE_GROUPS: Group[];
|
|
|
5
5
|
export declare const LIGHTHOUSE_REPORT_NAME = "lighthouse-report.json";
|
|
6
6
|
export declare const DEFAULT_CLI_FLAGS: {
|
|
7
7
|
verbose: false;
|
|
8
|
-
quiet: false;
|
|
9
8
|
saveAssets: false;
|
|
10
9
|
chromeFlags: string[];
|
|
11
10
|
port: number;
|
|
12
11
|
hostname: string;
|
|
13
12
|
view: false;
|
|
14
13
|
channel: string;
|
|
14
|
+
quiet: true;
|
|
15
15
|
onlyAudits: never[];
|
|
16
16
|
skipAudits: never[];
|
|
17
17
|
onlyCategories: never[];
|
|
18
|
-
budgets: never[];
|
|
19
18
|
output: "json"[];
|
|
20
19
|
outputPath: string;
|
|
21
20
|
};
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import type { Budget } from 'lighthouse';
|
|
2
1
|
import type { LighthouseOptions } from '../types';
|
|
3
2
|
export type NormalizedFlags = {
|
|
4
3
|
chromeFlags: string[];
|
|
5
4
|
onlyAudits: string[];
|
|
6
5
|
onlyCategories: string[];
|
|
7
6
|
skipAudits: string[];
|
|
8
|
-
budgets: Budget[];
|
|
9
7
|
};
|
|
10
8
|
export type LighthouseCliFlags = Omit<LighthouseOptions, keyof NormalizedFlags> & NormalizedFlags;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Config } from 'lighthouse';
|
|
2
2
|
import { Result } from 'lighthouse/types/lhr/audit-result';
|
|
3
3
|
import { AuditOutputs } from '@code-pushup/models';
|
|
4
4
|
import type { LighthouseOptions } from '../types';
|
|
@@ -11,10 +11,10 @@ export declare const unsupportedDetailTypes: Set<string>;
|
|
|
11
11
|
export declare function logUnsupportedDetails(lhrAudits: Result[], { displayCount }?: {
|
|
12
12
|
displayCount?: number;
|
|
13
13
|
}): void;
|
|
14
|
-
export
|
|
14
|
+
export type LighthouseLogLevel = 'verbose' | 'error' | 'info' | 'silent' | 'warn' | undefined;
|
|
15
|
+
export declare function determineAndSetLogLevel({ verbose, quiet, }?: {
|
|
15
16
|
verbose?: boolean;
|
|
16
17
|
quiet?: boolean;
|
|
17
|
-
}):
|
|
18
|
+
}): LighthouseLogLevel;
|
|
18
19
|
export type ConfigOptions = Partial<Pick<LighthouseCliFlags, 'configPath' | 'preset'>>;
|
|
19
20
|
export declare function getConfig(options?: ConfigOptions): Promise<Config | undefined>;
|
|
20
|
-
export declare function getBudgets(budgetPath?: string): Promise<Budget[]>;
|