@reddoorla/maintenance 0.85.2 → 0.86.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 +8 -0
- package/dist/airtable-G7WBQQMI.js +9 -0
- package/dist/{announce-GIAYN67S.js → announce-MXTUQ6C7.js} +26 -19
- package/dist/announce-MXTUQ6C7.js.map +1 -0
- package/dist/{bump-deps-SWJB6H5V.js → bump-deps-EC74CPLS.js} +9 -9
- package/dist/chunk-2EVEFOZY.js +129 -0
- package/dist/chunk-2EVEFOZY.js.map +1 -0
- package/dist/{chunk-COZPL62X.js → chunk-2NDRHXMR.js} +25 -17
- package/dist/chunk-2NDRHXMR.js.map +1 -0
- package/dist/{chunk-SDUJIANJ.js → chunk-2NJQLSEU.js} +3 -3
- package/dist/chunk-2NQUCS7O.js +243 -0
- package/dist/chunk-2NQUCS7O.js.map +1 -0
- package/dist/{chunk-DTTIFYAM.js → chunk-2ZPT7GLV.js} +42 -403
- package/dist/chunk-2ZPT7GLV.js.map +1 -0
- package/dist/{chunk-ZTPPCHDB.js → chunk-3G25KIWW.js} +4 -4
- package/dist/chunk-3SF7D4DY.js +359 -0
- package/dist/chunk-3SF7D4DY.js.map +1 -0
- package/dist/{chunk-Q276MZ7E.js → chunk-3VQWSE3F.js} +4 -4
- package/dist/{chunk-37S6L6G4.js → chunk-5UINJNAJ.js} +72 -2
- package/dist/chunk-5UINJNAJ.js.map +1 -0
- package/dist/{chunk-THEFTZ7F.js → chunk-62CMMGEO.js} +5 -5
- package/dist/{chunk-FDIFTIXC.js → chunk-6TWWY7ZU.js} +2 -2
- package/dist/{chunk-UYCAF77E.js → chunk-7RJ2HMMJ.js} +3 -3
- package/dist/chunk-ACBRLLFT.js +198 -0
- package/dist/chunk-ACBRLLFT.js.map +1 -0
- package/dist/chunk-BNM5POSJ.js +284 -0
- package/dist/chunk-BNM5POSJ.js.map +1 -0
- package/dist/{chunk-R6FPFMOS.js → chunk-BQRFQSGY.js} +3 -3
- package/dist/{chunk-MGR2H7F4.js → chunk-BYK66EWO.js} +19 -12
- package/dist/chunk-BYK66EWO.js.map +1 -0
- package/dist/{chunk-6QRLRT3P.js → chunk-CQR4LIM7.js} +12 -265
- package/dist/chunk-CQR4LIM7.js.map +1 -0
- package/dist/{chunk-SEEA6RXF.js → chunk-DJZWYIPP.js} +2 -2
- package/dist/chunk-DJZWYIPP.js.map +1 -0
- package/dist/chunk-EVBCK2KC.js +68 -0
- package/dist/chunk-EVBCK2KC.js.map +1 -0
- package/dist/{chunk-TP5M2NQB.js → chunk-F5KM4LEQ.js} +3 -3
- package/dist/{chunk-62VF32IC.js → chunk-ILUNZHYV.js} +2 -2
- package/dist/chunk-ITIOFN7A.js +396 -0
- package/dist/chunk-ITIOFN7A.js.map +1 -0
- package/dist/{chunk-LS6QPANO.js → chunk-IYSEC543.js} +2 -2
- package/dist/{chunk-DC5H7KEQ.js → chunk-JHGHLKFS.js} +2 -2
- package/dist/{chunk-PBWDDDQH.js → chunk-KTH5ZODA.js} +2 -2
- package/dist/{chunk-4DHQCN5H.js → chunk-LBYOLBW7.js} +17 -2
- package/dist/chunk-LBYOLBW7.js.map +1 -0
- package/dist/{chunk-577HCGZO.js → chunk-LDWZSLSU.js} +38 -23
- package/dist/chunk-LDWZSLSU.js.map +1 -0
- package/dist/{chunk-LTB6KVJW.js → chunk-N45M3FDK.js} +13 -11
- package/dist/{chunk-LTB6KVJW.js.map → chunk-N45M3FDK.js.map} +1 -1
- package/dist/chunk-NYUYNYQL.js +48 -0
- package/dist/chunk-NYUYNYQL.js.map +1 -0
- package/dist/{chunk-7J53SUT6.js → chunk-P2FE5AI6.js} +4 -4
- package/dist/{chunk-3YXDSCM6.js → chunk-PPE5KZJK.js} +29 -11
- package/dist/chunk-PPE5KZJK.js.map +1 -0
- package/dist/chunk-PTDMVGKL.js +31 -0
- package/dist/chunk-PTDMVGKL.js.map +1 -0
- package/dist/{chunk-D4FVAIEJ.js → chunk-PZR4EBPY.js} +5 -2
- package/dist/chunk-PZR4EBPY.js.map +1 -0
- package/dist/{chunk-NWB4O5EY.js → chunk-SLUQ7R6I.js} +3 -3
- package/dist/chunk-SLUQ7R6I.js.map +1 -0
- package/dist/{chunk-GZNBCHAZ.js → chunk-TERE5SDF.js} +4 -4
- package/dist/{chunk-ZMIPG6TR.js → chunk-TVL5MVUF.js} +4 -4
- package/dist/chunk-UDRHAQT7.js +172 -0
- package/dist/chunk-UDRHAQT7.js.map +1 -0
- package/dist/chunk-VAD43MOR.js +72 -0
- package/dist/chunk-VAD43MOR.js.map +1 -0
- package/dist/chunk-VSBFM7DS.js +229 -0
- package/dist/chunk-VSBFM7DS.js.map +1 -0
- package/dist/chunk-W7Z3BGCI.js +274 -0
- package/dist/chunk-W7Z3BGCI.js.map +1 -0
- package/dist/chunk-X3B723J4.js +1209 -0
- package/dist/chunk-X3B723J4.js.map +1 -0
- package/dist/{chunk-VRWUL4TR.js → chunk-XHHMM5HX.js} +2 -2
- package/dist/{chunk-RJB3QUSP.js → chunk-XIDUYLSR.js} +3 -3
- package/dist/{chunk-QG6OSL4M.js → chunk-XUGSZP7Z.js} +2 -2
- package/dist/{chunk-S56JQJ4F.js → chunk-Y53WOQIJ.js} +3 -3
- package/dist/{chunk-ICXV25N7.js → chunk-Z3KYFUN6.js} +3 -3
- package/dist/{chunk-MPBXOJ3N.js → chunk-Z7AXYKQB.js} +33 -2
- package/dist/chunk-Z7AXYKQB.js.map +1 -0
- package/dist/{chunk-WYYQK4D3.js → chunk-ZKXSX4LO.js} +11 -11
- package/dist/cli/bin.js +46 -28
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.d.ts +30 -1
- package/dist/cli/commands/audit.js +62 -30
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/client-AUE3XUPO.js +11 -0
- package/dist/{convert-to-pnpm-AT52NWZB.js → convert-to-pnpm-6L6P74WR.js} +9 -9
- package/dist/db-B35OGV3G.js +217 -0
- package/dist/db-B35OGV3G.js.map +1 -0
- package/dist/{digest-UVHYZUYE.js → digest-BL6UJYKH.js} +23 -20
- package/dist/{digest-UVHYZUYE.js.map → digest-BL6UJYKH.js.map} +1 -1
- package/dist/dump-P6EBSIOH.js +68 -0
- package/dist/dump-P6EBSIOH.js.map +1 -0
- package/dist/email-VTTTKKL5.js +195 -0
- package/dist/email-VTTTKKL5.js.map +1 -0
- package/dist/{ensure-site-S25MDDHW.js → ensure-site-DFTB7MN3.js} +8 -7
- package/dist/ensure-site-DFTB7MN3.js.map +1 -0
- package/dist/fleet-events-cF2Om88w.d.ts +24 -0
- package/dist/{forms-notify-target-TWN4EH6K.js → forms-notify-target-75U6OU7L.js} +38 -132
- package/dist/forms-notify-target-75U6OU7L.js.map +1 -0
- package/dist/{github-signals-G4ILZAJ6.js → github-signals-IJUPGCUX.js} +40 -19
- package/dist/github-signals-IJUPGCUX.js.map +1 -0
- package/dist/{header-image-T7XD37JL.js → header-image-AWLLQA4L.js} +34 -11
- package/dist/header-image-AWLLQA4L.js.map +1 -0
- package/dist/header-images-335L2AKB.js +68 -0
- package/dist/header-images-335L2AKB.js.map +1 -0
- package/dist/{health-endpoint-242WG2OJ.js → health-endpoint-WJC2UMYS.js} +9 -9
- package/dist/health-mirror-4B2L7T2Y.js +75 -0
- package/dist/health-mirror-4B2L7T2Y.js.map +1 -0
- package/dist/import-airtable-HE43FB4H.js +35 -0
- package/dist/index.d.ts +175 -21
- package/dist/index.js +115 -73
- package/dist/index.js.map +1 -1
- package/dist/{init-JN26NTWF.js → init-NJEOEO7I.js} +20 -17
- package/dist/{init-JN26NTWF.js.map → init-NJEOEO7I.js.map} +1 -1
- package/dist/{launch-JA7Z4CIM.js → launch-XNAX427U.js} +31 -25
- package/dist/{launch-JA7Z4CIM.js.map → launch-XNAX427U.js.map} +1 -1
- package/dist/lighthouse-VHI77PFB.js +11 -0
- package/dist/{lighthouse-airtable-BIPM26SZ.js → lighthouse-airtable-LBVIYYP5.js} +3 -3
- package/dist/mailchimp-XYCTEEJY.js +72 -0
- package/dist/mailchimp-XYCTEEJY.js.map +1 -0
- package/dist/migrate-GQH237A6.js +7 -0
- package/dist/notify-C645PGD5.js +22 -0
- package/dist/{onboard-53CITIM7.js → onboard-GK4PHPNI.js} +9 -9
- package/dist/orchestrate-77UO4BYJ.js +30 -0
- package/dist/orchestrate-77UO4BYJ.js.map +1 -0
- package/dist/parity-MWS24A3H.js +12 -0
- package/dist/parity-MWS24A3H.js.map +1 -0
- package/dist/pipeline-S6CVHDGB.js +12 -0
- package/dist/pipeline-S6CVHDGB.js.map +1 -0
- package/dist/{preflight-3XPDUHFJ.js → preflight-6WBNU2GZ.js} +16 -13
- package/dist/{preflight-3XPDUHFJ.js.map → preflight-6WBNU2GZ.js.map} +1 -1
- package/dist/{prismic-ci-UTQ6LRR3.js → prismic-ci-3RHOZUUT.js} +15 -15
- package/dist/{prismic-models-PVES6R5V.js → prismic-models-QBGUT2Q3.js} +10 -10
- package/dist/prospect-audit-IUNCJ2LV.js +174 -0
- package/dist/prospect-audit-IUNCJ2LV.js.map +1 -0
- package/dist/prospect-audits-3PMIO73D.js +19 -0
- package/dist/prospect-audits-3PMIO73D.js.map +1 -0
- package/dist/{protection-audit-64PLLBLI.js → protection-audit-SJO53MEQ.js} +3 -3
- package/dist/recipes/sync-configs.js +3 -3
- package/dist/render-AQAVQDPZ.js +10 -0
- package/dist/render-AQAVQDPZ.js.map +1 -0
- package/dist/{renovate-dispatch-ICJGSFCE.js → renovate-dispatch-QJY75ODR.js} +8 -8
- package/dist/replay-C2LXMJZP.js +66 -0
- package/dist/replay-C2LXMJZP.js.map +1 -0
- package/dist/{report-6CKSWJNG.js → report-4EVNDHOZ.js} +55 -29
- package/dist/report-4EVNDHOZ.js.map +1 -0
- package/dist/reports/header-image/assets/headline-announcement.png +0 -0
- package/dist/reports/header-image/assets/headline-launch.png +0 -0
- package/dist/reports/header-image/assets/headline-maintenance.png +0 -0
- package/dist/reports/header-image/assets/headline-testing.png +0 -0
- package/dist/reports/header-image/assets/plate-clean.png +0 -0
- package/dist/{self-updating-PPQVV6UA.js → self-updating-6DWI2Z56.js} +9 -9
- package/dist/{selftest-CQ6NOX52.js → selftest-RC36MTKP.js} +25 -20
- package/dist/selftest-RC36MTKP.js.map +1 -0
- package/dist/smoke-B2GQOSIZ.js +20 -0
- package/dist/smoke-B2GQOSIZ.js.map +1 -0
- package/dist/{smoke-suite-TMCSOYRK.js → smoke-suite-VYY2LXM2.js} +9 -9
- package/dist/{submissions-GJ6ITBRH.js → submissions-Q7DRFOCD.js} +3 -3
- package/dist/{svelte-codemods-ZOBDHIES.js → svelte-codemods-25J2FO22.js} +9 -9
- package/dist/sync-34HNZZ56.js +44 -0
- package/dist/sync-34HNZZ56.js.map +1 -0
- package/dist/{sync-configs-CJXUX6MD.js → sync-configs-3SE6PSCO.js} +9 -9
- package/dist/{upgrade-WLX27UPC.js → upgrade-WBRQ62FX.js} +9 -9
- package/dist/{webflow-624FEBFD.js → webflow-IRKOIT7S.js} +4 -4
- package/dist/webhook-VOGOW3W6.js +38 -0
- package/dist/webhook-VOGOW3W6.js.map +1 -0
- package/dist/{websites-SADZR4XQ.js → websites-SXWTP72S.js} +6 -2
- package/dist/websites-SXWTP72S.js.map +1 -0
- package/dist/{write-audits-to-airtable-7PH75YWY.js → write-audits-to-airtable-MBEILLPU.js} +4 -4
- package/dist/write-audits-to-airtable-MBEILLPU.js.map +1 -0
- package/package.json +5 -2
- package/dist/airtable-HRKSA7V4.js +0 -9
- package/dist/announce-GIAYN67S.js.map +0 -1
- package/dist/chunk-37S6L6G4.js.map +0 -1
- package/dist/chunk-3YXDSCM6.js.map +0 -1
- package/dist/chunk-4DHQCN5H.js.map +0 -1
- package/dist/chunk-4SOCPK7A.js +0 -108
- package/dist/chunk-4SOCPK7A.js.map +0 -1
- package/dist/chunk-577HCGZO.js.map +0 -1
- package/dist/chunk-6QRLRT3P.js.map +0 -1
- package/dist/chunk-COZPL62X.js.map +0 -1
- package/dist/chunk-D4FVAIEJ.js.map +0 -1
- package/dist/chunk-DTTIFYAM.js.map +0 -1
- package/dist/chunk-MGR2H7F4.js.map +0 -1
- package/dist/chunk-MPBXOJ3N.js.map +0 -1
- package/dist/chunk-NWB4O5EY.js.map +0 -1
- package/dist/chunk-SEEA6RXF.js.map +0 -1
- package/dist/chunk-U5SZ4FOP.js +0 -26
- package/dist/chunk-U5SZ4FOP.js.map +0 -1
- package/dist/client-X5WUJWDE.js +0 -11
- package/dist/db-JSIZYT23.js +0 -23
- package/dist/db-JSIZYT23.js.map +0 -1
- package/dist/ensure-site-S25MDDHW.js.map +0 -1
- package/dist/forms-notify-target-TWN4EH6K.js.map +0 -1
- package/dist/github-signals-G4ILZAJ6.js.map +0 -1
- package/dist/header-image-T7XD37JL.js.map +0 -1
- package/dist/migrate-LJUFGXQZ.js +0 -7
- package/dist/orchestrate-KDNXZQX7.js +0 -27
- package/dist/report-6CKSWJNG.js.map +0 -1
- package/dist/reports/header-image/assets/plate.png +0 -0
- package/dist/selftest-CQ6NOX52.js.map +0 -1
- /package/dist/{airtable-HRKSA7V4.js.map → airtable-G7WBQQMI.js.map} +0 -0
- /package/dist/{bump-deps-SWJB6H5V.js.map → bump-deps-EC74CPLS.js.map} +0 -0
- /package/dist/{chunk-SDUJIANJ.js.map → chunk-2NJQLSEU.js.map} +0 -0
- /package/dist/{chunk-ZTPPCHDB.js.map → chunk-3G25KIWW.js.map} +0 -0
- /package/dist/{chunk-Q276MZ7E.js.map → chunk-3VQWSE3F.js.map} +0 -0
- /package/dist/{chunk-THEFTZ7F.js.map → chunk-62CMMGEO.js.map} +0 -0
- /package/dist/{chunk-FDIFTIXC.js.map → chunk-6TWWY7ZU.js.map} +0 -0
- /package/dist/{chunk-UYCAF77E.js.map → chunk-7RJ2HMMJ.js.map} +0 -0
- /package/dist/{chunk-R6FPFMOS.js.map → chunk-BQRFQSGY.js.map} +0 -0
- /package/dist/{chunk-TP5M2NQB.js.map → chunk-F5KM4LEQ.js.map} +0 -0
- /package/dist/{chunk-62VF32IC.js.map → chunk-ILUNZHYV.js.map} +0 -0
- /package/dist/{chunk-LS6QPANO.js.map → chunk-IYSEC543.js.map} +0 -0
- /package/dist/{chunk-DC5H7KEQ.js.map → chunk-JHGHLKFS.js.map} +0 -0
- /package/dist/{chunk-PBWDDDQH.js.map → chunk-KTH5ZODA.js.map} +0 -0
- /package/dist/{chunk-7J53SUT6.js.map → chunk-P2FE5AI6.js.map} +0 -0
- /package/dist/{chunk-GZNBCHAZ.js.map → chunk-TERE5SDF.js.map} +0 -0
- /package/dist/{chunk-ZMIPG6TR.js.map → chunk-TVL5MVUF.js.map} +0 -0
- /package/dist/{chunk-VRWUL4TR.js.map → chunk-XHHMM5HX.js.map} +0 -0
- /package/dist/{chunk-RJB3QUSP.js.map → chunk-XIDUYLSR.js.map} +0 -0
- /package/dist/{chunk-QG6OSL4M.js.map → chunk-XUGSZP7Z.js.map} +0 -0
- /package/dist/{chunk-S56JQJ4F.js.map → chunk-Y53WOQIJ.js.map} +0 -0
- /package/dist/{chunk-ICXV25N7.js.map → chunk-Z3KYFUN6.js.map} +0 -0
- /package/dist/{chunk-WYYQK4D3.js.map → chunk-ZKXSX4LO.js.map} +0 -0
- /package/dist/{client-X5WUJWDE.js.map → client-AUE3XUPO.js.map} +0 -0
- /package/dist/{convert-to-pnpm-AT52NWZB.js.map → convert-to-pnpm-6L6P74WR.js.map} +0 -0
- /package/dist/{health-endpoint-242WG2OJ.js.map → health-endpoint-WJC2UMYS.js.map} +0 -0
- /package/dist/{lighthouse-airtable-BIPM26SZ.js.map → import-airtable-HE43FB4H.js.map} +0 -0
- /package/dist/{migrate-LJUFGXQZ.js.map → lighthouse-VHI77PFB.js.map} +0 -0
- /package/dist/{orchestrate-KDNXZQX7.js.map → lighthouse-airtable-LBVIYYP5.js.map} +0 -0
- /package/dist/{websites-SADZR4XQ.js.map → migrate-GQH237A6.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-7PH75YWY.js.map → notify-C645PGD5.js.map} +0 -0
- /package/dist/{onboard-53CITIM7.js.map → onboard-GK4PHPNI.js.map} +0 -0
- /package/dist/{prismic-ci-UTQ6LRR3.js.map → prismic-ci-3RHOZUUT.js.map} +0 -0
- /package/dist/{prismic-models-PVES6R5V.js.map → prismic-models-QBGUT2Q3.js.map} +0 -0
- /package/dist/{protection-audit-64PLLBLI.js.map → protection-audit-SJO53MEQ.js.map} +0 -0
- /package/dist/{renovate-dispatch-ICJGSFCE.js.map → renovate-dispatch-QJY75ODR.js.map} +0 -0
- /package/dist/{self-updating-PPQVV6UA.js.map → self-updating-6DWI2Z56.js.map} +0 -0
- /package/dist/{smoke-suite-TMCSOYRK.js.map → smoke-suite-VYY2LXM2.js.map} +0 -0
- /package/dist/{submissions-GJ6ITBRH.js.map → submissions-Q7DRFOCD.js.map} +0 -0
- /package/dist/{svelte-codemods-ZOBDHIES.js.map → svelte-codemods-25J2FO22.js.map} +0 -0
- /package/dist/{sync-configs-CJXUX6MD.js.map → sync-configs-3SE6PSCO.js.map} +0 -0
- /package/dist/{upgrade-WLX27UPC.js.map → upgrade-WBRQ62FX.js.map} +0 -0
- /package/dist/{webflow-624FEBFD.js.map → webflow-IRKOIT7S.js.map} +0 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findFreePort,
|
|
3
|
+
withFreePort
|
|
4
|
+
} from "./chunk-PTDMVGKL.js";
|
|
5
|
+
import {
|
|
6
|
+
defaultSpawn
|
|
7
|
+
} from "./chunk-LBYOLBW7.js";
|
|
8
|
+
import {
|
|
9
|
+
siteLabel
|
|
10
|
+
} from "./chunk-XXTZBPUY.js";
|
|
11
|
+
import {
|
|
12
|
+
lighthouseConfig
|
|
13
|
+
} from "./chunk-NMAWXBJA.js";
|
|
14
|
+
|
|
15
|
+
// src/audits/lighthouse.ts
|
|
16
|
+
import { readFile as readFile2, writeFile, mkdtemp, rm, readdir } from "fs/promises";
|
|
17
|
+
import { tmpdir } from "os";
|
|
18
|
+
import { join as join2 } from "path";
|
|
19
|
+
|
|
20
|
+
// src/audits/util/site-config.ts
|
|
21
|
+
import { readFile } from "fs/promises";
|
|
22
|
+
import { join } from "path";
|
|
23
|
+
async function readSiteConfig(sitePath) {
|
|
24
|
+
let raw;
|
|
25
|
+
try {
|
|
26
|
+
raw = await readFile(join(sitePath, "package.json"), "utf-8");
|
|
27
|
+
} catch {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
let pkg;
|
|
31
|
+
try {
|
|
32
|
+
pkg = JSON.parse(raw);
|
|
33
|
+
} catch {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
if (!pkg || typeof pkg !== "object") return {};
|
|
37
|
+
const cfg = pkg.reddoor;
|
|
38
|
+
if (!cfg || typeof cfg !== "object") return {};
|
|
39
|
+
const out = {};
|
|
40
|
+
const url = cfg.lighthouseUrl;
|
|
41
|
+
if (typeof url === "string" && url.length > 0) {
|
|
42
|
+
out.lighthouseUrl = url;
|
|
43
|
+
}
|
|
44
|
+
const routes = cfg.a11yRoutes;
|
|
45
|
+
if (Array.isArray(routes)) {
|
|
46
|
+
const clean = routes.filter((r) => typeof r === "string").map((r) => r.trim()).filter((r) => r.length > 0);
|
|
47
|
+
if (clean.length > 0) out.a11yRoutes = clean;
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/audits/lighthouse.ts
|
|
53
|
+
async function readJsonMaybe(path) {
|
|
54
|
+
try {
|
|
55
|
+
const raw = await readFile2(path, "utf-8");
|
|
56
|
+
return JSON.parse(raw);
|
|
57
|
+
} catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function readLhrEntries(resultsDir) {
|
|
62
|
+
const files = await readdir(resultsDir).catch(() => []);
|
|
63
|
+
const entries = [];
|
|
64
|
+
for (const f of files) {
|
|
65
|
+
if (!f.startsWith("lhr-") || !f.endsWith(".json")) continue;
|
|
66
|
+
const lhr = await readJsonMaybe(join2(resultsDir, f));
|
|
67
|
+
if (!lhr || !lhr.categories) continue;
|
|
68
|
+
const summary = {};
|
|
69
|
+
for (const [k, v] of Object.entries(lhr.categories)) {
|
|
70
|
+
if (typeof v?.score === "number") summary[k] = v.score;
|
|
71
|
+
}
|
|
72
|
+
entries.push({ url: lhr.requestedUrl, summary });
|
|
73
|
+
}
|
|
74
|
+
return entries;
|
|
75
|
+
}
|
|
76
|
+
function averageSummaries(entries) {
|
|
77
|
+
if (entries.length === 0) return {};
|
|
78
|
+
const sums = {};
|
|
79
|
+
const counts = {};
|
|
80
|
+
for (const e of entries) {
|
|
81
|
+
for (const [k, v] of Object.entries(e.summary ?? {})) {
|
|
82
|
+
if (typeof v !== "number") continue;
|
|
83
|
+
sums[k] = (sums[k] ?? 0) + v;
|
|
84
|
+
counts[k] = (counts[k] ?? 0) + 1;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const out = {};
|
|
88
|
+
for (const k of Object.keys(sums)) {
|
|
89
|
+
const total = sums[k] ?? 0;
|
|
90
|
+
const count = counts[k] ?? 1;
|
|
91
|
+
out[k] = total / count;
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
function categoryFromAssertion(a) {
|
|
96
|
+
const colonIdx = a.name.indexOf(":");
|
|
97
|
+
return colonIdx >= 0 ? a.name.slice(colonIdx + 1) : a.name;
|
|
98
|
+
}
|
|
99
|
+
function messageForAssertion(a) {
|
|
100
|
+
const actual = typeof a.actual === "number" ? a.actual.toFixed(2) : "n/a";
|
|
101
|
+
return `${a.name} ${a.operator} ${a.expected} (actual: ${actual})`;
|
|
102
|
+
}
|
|
103
|
+
async function parseLhciResults(resultsDir, label, raw) {
|
|
104
|
+
const manifest = await readLhrEntries(resultsDir);
|
|
105
|
+
if (manifest.length === 0) {
|
|
106
|
+
return {
|
|
107
|
+
audit: "lighthouse",
|
|
108
|
+
site: label,
|
|
109
|
+
status: "fail",
|
|
110
|
+
summary: `lighthouse: no lhr-*.json written (exit ${raw.code})${raw.stderr ? ` \u2014 ${raw.stderr.slice(0, 200)}` : ""}`
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const assertionResults = await readJsonMaybe(join2(resultsDir, "assertion-results.json")) ?? [];
|
|
114
|
+
const failed = assertionResults.filter((a) => !a.passed);
|
|
115
|
+
const assertions = failed.map((a) => ({
|
|
116
|
+
category: categoryFromAssertion(a),
|
|
117
|
+
level: a.level,
|
|
118
|
+
message: messageForAssertion(a)
|
|
119
|
+
}));
|
|
120
|
+
const anyError = assertions.some((a) => a.level === "error");
|
|
121
|
+
const anyWarn = assertions.some((a) => a.level === "warn");
|
|
122
|
+
const status = anyError ? "fail" : anyWarn ? "warn" : "pass";
|
|
123
|
+
const normalized = {
|
|
124
|
+
summary: averageSummaries(manifest),
|
|
125
|
+
assertionsFailed: failed.length,
|
|
126
|
+
assertions
|
|
127
|
+
};
|
|
128
|
+
const summary = status === "pass" ? "lighthouse: all categories passing" : `lighthouse: ${failed.length} assertion(s) failed`;
|
|
129
|
+
return { audit: "lighthouse", site: label, status, summary, details: normalized };
|
|
130
|
+
}
|
|
131
|
+
async function checkoutLighthouse(spawn, site, label) {
|
|
132
|
+
const siteCfg = await readSiteConfig(site.path);
|
|
133
|
+
const port = await findFreePort();
|
|
134
|
+
const baseUrl = siteCfg.lighthouseUrl ?? lighthouseConfig.ci.collect.url[0];
|
|
135
|
+
const resolvedConfig = {
|
|
136
|
+
...lighthouseConfig,
|
|
137
|
+
ci: {
|
|
138
|
+
...lighthouseConfig.ci,
|
|
139
|
+
collect: {
|
|
140
|
+
...lighthouseConfig.ci.collect,
|
|
141
|
+
url: [withFreePort(baseUrl, port)],
|
|
142
|
+
startServerCommand: `npm run vite:dev -- --port ${port} --strictPort`
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const configDir = await mkdtemp(join2(tmpdir(), "reddoor-lhci-"));
|
|
147
|
+
const configPath = join2(configDir, "lighthouserc.json");
|
|
148
|
+
await writeFile(configPath, JSON.stringify(resolvedConfig), "utf-8");
|
|
149
|
+
const resultsDir = join2(site.path, ".lighthouseci");
|
|
150
|
+
await rm(resultsDir, { recursive: true, force: true });
|
|
151
|
+
let raw;
|
|
152
|
+
try {
|
|
153
|
+
raw = await spawn("npx", ["--yes", "@lhci/cli", "autorun", `--config=${configPath}`], {
|
|
154
|
+
cwd: site.path,
|
|
155
|
+
timeoutMs: 5 * 6e4
|
|
156
|
+
});
|
|
157
|
+
} catch (err) {
|
|
158
|
+
await rm(configDir, { recursive: true, force: true });
|
|
159
|
+
const e = err;
|
|
160
|
+
if (e.code === "ENOENT" || /ENOENT/.test(String(err))) {
|
|
161
|
+
return {
|
|
162
|
+
audit: "lighthouse",
|
|
163
|
+
site: label,
|
|
164
|
+
status: "skip",
|
|
165
|
+
summary: "npx/@lhci/cli not available"
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
await rm(configDir, { recursive: true, force: true });
|
|
171
|
+
return parseLhciResults(resultsDir, label, raw);
|
|
172
|
+
}
|
|
173
|
+
async function deployedLighthouse(spawn, deployedUrl, label) {
|
|
174
|
+
const workDir = await mkdtemp(join2(tmpdir(), "reddoor-lh-deployed-"));
|
|
175
|
+
const resolvedConfig = {
|
|
176
|
+
ci: {
|
|
177
|
+
// Deliberately NOT spread from lighthouseConfig.ci.collect: deployed mode
|
|
178
|
+
// must omit startServerCommand and the dev-server settings entirely.
|
|
179
|
+
collect: {
|
|
180
|
+
url: [deployedUrl],
|
|
181
|
+
// 3 runs to damp Lighthouse's run-to-run variance; parseLhciResults
|
|
182
|
+
// averages the lhr files. (Median is a tracked future refinement.)
|
|
183
|
+
numberOfRuns: 3,
|
|
184
|
+
// Use devtools (applied) throttling instead of the desktop preset's
|
|
185
|
+
// default `simulate` (Lantern). Lantern estimates LCP from the
|
|
186
|
+
// dependency graph and can't model an LCP element revealed by a
|
|
187
|
+
// JS-load opacity fade (e.g. gallerysonder's GridImage): on a fast
|
|
188
|
+
// observed load it finds no LCP node and throws NO_LCP, nulling the
|
|
189
|
+
// perf score, which the cockpit then coerces to a misleading 0.
|
|
190
|
+
// devtools reads the real LCP paint event from the throttled trace
|
|
191
|
+
// instead. Trade-off: slightly noisier run-to-run, damped by the
|
|
192
|
+
// numberOfRuns:3 average above.
|
|
193
|
+
settings: { preset: "desktop", throttlingMethod: "devtools", skipAudits: ["uses-http2"] }
|
|
194
|
+
},
|
|
195
|
+
assert: lighthouseConfig.ci.assert,
|
|
196
|
+
upload: { target: "filesystem", outputDir: join2(workDir, "lhci-report") }
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const configPath = join2(workDir, "lighthouserc.json");
|
|
200
|
+
await writeFile(configPath, JSON.stringify(resolvedConfig), "utf-8");
|
|
201
|
+
const resultsDir = join2(workDir, ".lighthouseci");
|
|
202
|
+
let raw;
|
|
203
|
+
try {
|
|
204
|
+
raw = await spawn("npx", ["--yes", "@lhci/cli", "autorun", `--config=${configPath}`], {
|
|
205
|
+
cwd: workDir,
|
|
206
|
+
// 3 serial cold runs of a slow deployed site (lhci's own maxWaitForLoad
|
|
207
|
+
// ~45-60s each) + first-use Chrome download can plausibly exceed 3 min →
|
|
208
|
+
// SIGTERM → no lhr-*.json → spurious "no scores". Match the 5-min budget
|
|
209
|
+
// the checkout path already gives (erp-industrials nightly flake,
|
|
210
|
+
// morning-brief 2026-06-10 MEDIUM-F).
|
|
211
|
+
timeoutMs: 5 * 6e4
|
|
212
|
+
});
|
|
213
|
+
} catch (err) {
|
|
214
|
+
await rm(workDir, { recursive: true, force: true });
|
|
215
|
+
const e = err;
|
|
216
|
+
if (e.code === "ENOENT" || /ENOENT/.test(String(err))) {
|
|
217
|
+
return {
|
|
218
|
+
audit: "lighthouse",
|
|
219
|
+
site: label,
|
|
220
|
+
status: "skip",
|
|
221
|
+
summary: "npx/@lhci/cli not available"
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
throw err;
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
return await parseLhciResults(resultsDir, label, raw);
|
|
228
|
+
} finally {
|
|
229
|
+
await rm(workDir, { recursive: true, force: true });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
async function lighthouseAudit(ctx) {
|
|
233
|
+
const spawn = ctx.spawn ?? defaultSpawn;
|
|
234
|
+
const site = ctx.site;
|
|
235
|
+
const label = siteLabel(site);
|
|
236
|
+
return site.deployedUrl ? deployedLighthouse(spawn, site.deployedUrl, label) : checkoutLighthouse(spawn, site, label);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export {
|
|
240
|
+
readSiteConfig,
|
|
241
|
+
lighthouseAudit
|
|
242
|
+
};
|
|
243
|
+
//# sourceMappingURL=chunk-2NQUCS7O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/audits/lighthouse.ts","../src/audits/util/site-config.ts"],"sourcesContent":["import { readFile, writeFile, mkdtemp, rm, readdir } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AuditResult, Site } from \"../types.js\";\nimport { siteLabel } from \"../util/site.js\";\nimport { lighthouseConfig } from \"../configs/lighthouse.js\";\nimport { defaultSpawn } from \"./util/spawn.js\";\nimport type { SpawnFn, SpawnResult } from \"./util/spawn.js\";\nimport type { AuditContext } from \"./util/inject.js\";\nimport { readSiteConfig } from \"./util/site-config.js\";\nimport { findFreePort, withFreePort } from \"../util/free-port.js\";\n\ntype ManifestEntry = {\n url: string;\n summary: Record<string, number>;\n htmlPath?: string;\n jsonPath?: string;\n};\n\ntype AssertionResult = {\n name: string;\n actual: number;\n expected: number;\n operator: string;\n passed: boolean;\n level: \"warn\" | \"error\";\n auditProperty?: string;\n auditId?: string;\n};\n\ntype NormalizedLhciResult = {\n summary: Record<string, number>;\n assertionsFailed: number;\n assertions: Array<{ category: string; level: \"warn\" | \"error\"; message: string }>;\n};\n\nasync function readJsonMaybe<T>(path: string): Promise<T | null> {\n try {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\ntype LhrFile = {\n requestedUrl: string;\n finalUrl?: string;\n categories: Record<string, { score: number | null }>;\n};\n\n/**\n * Build manifest-equivalent entries by scanning the `.lighthouseci/` dir\n * for `lhr-*.json` files written by `lhci collect`. We used to read\n * `manifest.json` directly, but lhci 0.15+ no longer writes it — the\n * audit would silently return \"no manifest written\" against a perfectly\n * healthy run. Reproduced on caltex 2026-05-28 (0.10.5 dogfood).\n */\nasync function readLhrEntries(resultsDir: string): Promise<ManifestEntry[]> {\n const files = await readdir(resultsDir).catch(() => [] as string[]);\n const entries: ManifestEntry[] = [];\n for (const f of files) {\n if (!f.startsWith(\"lhr-\") || !f.endsWith(\".json\")) continue;\n const lhr = await readJsonMaybe<LhrFile>(join(resultsDir, f));\n if (!lhr || !lhr.categories) continue;\n const summary: Record<string, number> = {};\n for (const [k, v] of Object.entries(lhr.categories)) {\n if (typeof v?.score === \"number\") summary[k] = v.score;\n }\n entries.push({ url: lhr.requestedUrl, summary });\n }\n return entries;\n}\n\nfunction averageSummaries(entries: ManifestEntry[]): Record<string, number> {\n if (entries.length === 0) return {};\n const sums: Record<string, number> = {};\n const counts: Record<string, number> = {};\n for (const e of entries) {\n for (const [k, v] of Object.entries(e.summary ?? {})) {\n if (typeof v !== \"number\") continue;\n sums[k] = (sums[k] ?? 0) + v;\n counts[k] = (counts[k] ?? 0) + 1;\n }\n }\n const out: Record<string, number> = {};\n for (const k of Object.keys(sums)) {\n const total = sums[k] ?? 0;\n const count = counts[k] ?? 1;\n out[k] = total / count;\n }\n return out;\n}\n\nfunction categoryFromAssertion(a: AssertionResult): string {\n // `name` looks like \"categories:accessibility\" or \"audits:uses-http2\".\n const colonIdx = a.name.indexOf(\":\");\n return colonIdx >= 0 ? a.name.slice(colonIdx + 1) : a.name;\n}\n\nfunction messageForAssertion(a: AssertionResult): string {\n // `a.actual` is parsed from external lhci/Lighthouse JSON; a malformed or\n // missing value (not a number) would make `.toFixed` throw and crash the whole\n // audit. Guard it and fall back to a readable string instead.\n const actual = typeof a.actual === \"number\" ? a.actual.toFixed(2) : \"n/a\";\n return `${a.name} ${a.operator} ${a.expected} (actual: ${actual})`;\n}\n\n/** Shared tail: scan `.lighthouseci/` for lhr-*.json + assertion-results.json and\n * build the AuditResult. Identical for the checkout and deployed paths. */\nasync function parseLhciResults(\n resultsDir: string,\n label: string,\n raw: SpawnResult,\n): Promise<AuditResult> {\n const manifest = await readLhrEntries(resultsDir);\n\n if (manifest.length === 0) {\n return {\n audit: \"lighthouse\",\n site: label,\n status: \"fail\",\n summary: `lighthouse: no lhr-*.json written (exit ${raw.code})${\n raw.stderr ? ` — ${raw.stderr.slice(0, 200)}` : \"\"\n }`,\n };\n }\n\n const assertionResults =\n (await readJsonMaybe<AssertionResult[]>(join(resultsDir, \"assertion-results.json\"))) ?? [];\n\n const failed = assertionResults.filter((a) => !a.passed);\n const assertions = failed.map((a) => ({\n category: categoryFromAssertion(a),\n level: a.level,\n message: messageForAssertion(a),\n }));\n\n const anyError = assertions.some((a) => a.level === \"error\");\n const anyWarn = assertions.some((a) => a.level === \"warn\");\n const status: AuditResult[\"status\"] = anyError ? \"fail\" : anyWarn ? \"warn\" : \"pass\";\n\n const normalized: NormalizedLhciResult = {\n summary: averageSummaries(manifest),\n assertionsFailed: failed.length,\n assertions,\n };\n\n const summary =\n status === \"pass\"\n ? \"lighthouse: all categories passing\"\n : `lighthouse: ${failed.length} assertion(s) failed`;\n\n return { audit: \"lighthouse\", site: label, status, summary, details: normalized };\n}\n\n/** Checkout mode (unchanged behavior): boot the site's vite dev server on a\n * pinned free port and audit the local fixtures/override URL. */\nasync function checkoutLighthouse(spawn: SpawnFn, site: Site, label: string): Promise<AuditResult> {\n const siteCfg = await readSiteConfig(site.path);\n // Allocate a free port + force vite to `--strictPort` so the spawned dev\n // server either binds the port we picked or fails loudly (caltex 2026-05-28\n // zombie-vite incident).\n const port = await findFreePort();\n const baseUrl = siteCfg.lighthouseUrl ?? lighthouseConfig.ci.collect.url[0];\n const resolvedConfig = {\n ...lighthouseConfig,\n ci: {\n ...lighthouseConfig.ci,\n collect: {\n ...lighthouseConfig.ci.collect,\n url: [withFreePort(baseUrl, port)],\n startServerCommand: `npm run vite:dev -- --port ${port} --strictPort`,\n },\n },\n };\n\n const configDir = await mkdtemp(join(tmpdir(), \"reddoor-lhci-\"));\n const configPath = join(configDir, \"lighthouserc.json\");\n await writeFile(configPath, JSON.stringify(resolvedConfig), \"utf-8\");\n\n const resultsDir = join(site.path, \".lighthouseci\");\n await rm(resultsDir, { recursive: true, force: true });\n\n let raw: SpawnResult;\n try {\n raw = await spawn(\"npx\", [\"--yes\", \"@lhci/cli\", \"autorun\", `--config=${configPath}`], {\n cwd: site.path,\n timeoutMs: 5 * 60_000,\n });\n } catch (err) {\n await rm(configDir, { recursive: true, force: true });\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\" || /ENOENT/.test(String(err))) {\n return {\n audit: \"lighthouse\",\n site: label,\n status: \"skip\",\n summary: \"npx/@lhci/cli not available\",\n };\n }\n throw err;\n }\n await rm(configDir, { recursive: true, force: true });\n\n return parseLhciResults(resultsDir, label, raw);\n}\n\n/** Deployed mode: audit a production URL directly — no checkout, no dev server.\n * Runs in a throwaway tmp cwd; uploads to the filesystem so fleet runs never\n * push 200 public reports to temporary-public-storage. */\nasync function deployedLighthouse(\n spawn: SpawnFn,\n deployedUrl: string,\n label: string,\n): Promise<AuditResult> {\n const workDir = await mkdtemp(join(tmpdir(), \"reddoor-lh-deployed-\"));\n const resolvedConfig = {\n ci: {\n // Deliberately NOT spread from lighthouseConfig.ci.collect: deployed mode\n // must omit startServerCommand and the dev-server settings entirely.\n collect: {\n url: [deployedUrl],\n // 3 runs to damp Lighthouse's run-to-run variance; parseLhciResults\n // averages the lhr files. (Median is a tracked future refinement.)\n numberOfRuns: 3,\n // Use devtools (applied) throttling instead of the desktop preset's\n // default `simulate` (Lantern). Lantern estimates LCP from the\n // dependency graph and can't model an LCP element revealed by a\n // JS-load opacity fade (e.g. gallerysonder's GridImage): on a fast\n // observed load it finds no LCP node and throws NO_LCP, nulling the\n // perf score, which the cockpit then coerces to a misleading 0.\n // devtools reads the real LCP paint event from the throttled trace\n // instead. Trade-off: slightly noisier run-to-run, damped by the\n // numberOfRuns:3 average above.\n settings: { preset: \"desktop\", throttlingMethod: \"devtools\", skipAudits: [\"uses-http2\"] },\n },\n assert: lighthouseConfig.ci.assert,\n upload: { target: \"filesystem\", outputDir: join(workDir, \"lhci-report\") },\n },\n };\n\n const configPath = join(workDir, \"lighthouserc.json\");\n await writeFile(configPath, JSON.stringify(resolvedConfig), \"utf-8\");\n\n const resultsDir = join(workDir, \".lighthouseci\");\n\n let raw: SpawnResult;\n try {\n raw = await spawn(\"npx\", [\"--yes\", \"@lhci/cli\", \"autorun\", `--config=${configPath}`], {\n cwd: workDir,\n // 3 serial cold runs of a slow deployed site (lhci's own maxWaitForLoad\n // ~45-60s each) + first-use Chrome download can plausibly exceed 3 min →\n // SIGTERM → no lhr-*.json → spurious \"no scores\". Match the 5-min budget\n // the checkout path already gives (erp-industrials nightly flake,\n // morning-brief 2026-06-10 MEDIUM-F).\n timeoutMs: 5 * 60_000,\n });\n } catch (err) {\n await rm(workDir, { recursive: true, force: true });\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\" || /ENOENT/.test(String(err))) {\n return {\n audit: \"lighthouse\",\n site: label,\n status: \"skip\",\n summary: \"npx/@lhci/cli not available\",\n };\n }\n throw err;\n }\n\n try {\n return await parseLhciResults(resultsDir, label, raw);\n } finally {\n await rm(workDir, { recursive: true, force: true });\n }\n}\n\nexport async function lighthouseAudit(ctx: AuditContext): Promise<AuditResult> {\n const spawn = ctx.spawn ?? defaultSpawn;\n const site = ctx.site;\n const label = siteLabel(site);\n\n return site.deployedUrl\n ? deployedLighthouse(spawn, site.deployedUrl, label)\n : checkoutLighthouse(spawn, site, label);\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport type SiteConfig = {\n /** Override URL the lighthouse audit hits. Sites without the default\n * `/dev/a11y-fixtures` dev route set this to their homepage. */\n lighthouseUrl?: string;\n /**\n * Real site routes the a11y audit should axe-scan, IN ADDITION to the two\n * synthetic fixture pages it always covers. Opt-in per site and absent by\n * default: the audit runs with `--fail-on-violations` in the shared CI\n * workflow, and most of the fleet carries pre-existing a11y debt, so scanning\n * real routes everywhere at once would red every repo. A site adopts this once\n * its routes are clean. Omitted (never `[]`) when unset or unusable.\n */\n a11yRoutes?: string[];\n};\n\n/**\n * Read per-site overrides from `package.json#reddoor`. Returns `{}` on any\n * failure (missing file, malformed JSON, missing key, wrong type) so every\n * caller can safely fall back to its built-in default. Never throws.\n */\nexport async function readSiteConfig(sitePath: string): Promise<SiteConfig> {\n let raw: string;\n try {\n raw = await readFile(join(sitePath, \"package.json\"), \"utf-8\");\n } catch {\n return {};\n }\n let pkg: unknown;\n try {\n pkg = JSON.parse(raw);\n } catch {\n return {};\n }\n if (!pkg || typeof pkg !== \"object\") return {};\n const cfg = (pkg as { reddoor?: unknown }).reddoor;\n if (!cfg || typeof cfg !== \"object\") return {};\n\n const out: SiteConfig = {};\n const url = (cfg as { lighthouseUrl?: unknown }).lighthouseUrl;\n if (typeof url === \"string\" && url.length > 0) {\n out.lighthouseUrl = url;\n }\n const routes = (cfg as { a11yRoutes?: unknown }).a11yRoutes;\n if (Array.isArray(routes)) {\n // Junk entries are dropped rather than passed through — a `null` in the list\n // would become `page.goto(null)` inside the generated spec and fail the whole\n // audit for a typo. An all-junk list leaves the key omitted, so the caller's\n // \"no routes configured\" branch is the same shape as \"key absent\".\n const clean = routes\n .filter((r): r is string => typeof r === \"string\")\n .map((r) => r.trim())\n .filter((r) => r.length > 0);\n if (clean.length > 0) out.a11yRoutes = clean;\n }\n return out;\n}\n"],"mappings":"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","names":["readFile","join","readFile","join"]}
|