@reddoorla/maintenance 0.84.0 → 0.85.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/airtable-HRKSA7V4.js +9 -0
- package/dist/{announce-4H64L2Z6.js → announce-GIAYN67S.js} +4 -4
- package/dist/{bump-deps-2OL6PGTM.js → bump-deps-SWJB6H5V.js} +2 -2
- package/dist/{chunk-XDCRVYFL.js → chunk-3YXDSCM6.js} +3 -3
- package/dist/{chunk-CLWNAMUX.js → chunk-577HCGZO.js} +3 -2
- package/dist/chunk-577HCGZO.js.map +1 -0
- package/dist/chunk-5ML7FMBD.js +10 -0
- package/dist/chunk-5ML7FMBD.js.map +1 -0
- package/dist/{chunk-MQUOUVQP.js → chunk-7J53SUT6.js} +2 -2
- package/dist/{chunk-PBCGXXG6.js → chunk-COZPL62X.js} +2 -2
- package/dist/{chunk-KV7DIRRO.js → chunk-GZNBCHAZ.js} +3 -3
- package/dist/{chunk-5P2HVNLZ.js → chunk-LTB6KVJW.js} +3 -3
- package/dist/{chunk-JVWJJ36K.js → chunk-MGR2H7F4.js} +2 -2
- package/dist/{chunk-2WN4SNBQ.js → chunk-NWB4O5EY.js} +2 -2
- package/dist/{chunk-OQFOMKBP.js → chunk-PBWDDDQH.js} +2 -2
- package/dist/{chunk-FSRJAF2Q.js → chunk-TP5M2NQB.js} +10 -3
- package/dist/{chunk-FSRJAF2Q.js.map → chunk-TP5M2NQB.js.map} +1 -1
- package/dist/cli/bin.js +23 -23
- package/dist/cli/commands/audit.js +5 -5
- package/dist/{convert-to-pnpm-KCXOYOHW.js → convert-to-pnpm-AT52NWZB.js} +2 -2
- package/dist/{digest-WGEPAWMP.js → digest-UVHYZUYE.js} +9 -7
- package/dist/digest-UVHYZUYE.js.map +1 -0
- package/dist/{ensure-site-HYAIVZY2.js → ensure-site-S25MDDHW.js} +2 -2
- package/dist/{forms-notify-target-HSL4ZMT5.js → forms-notify-target-TWN4EH6K.js} +5 -6
- package/dist/forms-notify-target-TWN4EH6K.js.map +1 -0
- package/dist/{github-signals-I7XACMCE.js → github-signals-G4ILZAJ6.js} +4 -4
- package/dist/{header-image-ADYPTGVY.js → header-image-T7XD37JL.js} +2 -2
- package/dist/{health-endpoint-JNCUILHO.js → health-endpoint-242WG2OJ.js} +2 -2
- package/dist/index.d.ts +20 -0
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/{init-FLGLJCMJ.js → init-TFVAN5OY.js} +2 -2
- package/dist/{launch-AVKH2JVF.js → launch-DWY2MF54.js} +5 -5
- package/dist/{lighthouse-airtable-CHANWVO6.js → lighthouse-airtable-BIPM26SZ.js} +3 -3
- package/dist/{onboard-HF4FTJDE.js → onboard-53CITIM7.js} +2 -2
- package/dist/{orchestrate-5FMNYJEA.js → orchestrate-KDNXZQX7.js} +3 -3
- package/dist/{preflight-HTWIX3MN.js → preflight-3XPDUHFJ.js} +4 -4
- package/dist/{prismic-ci-4PDATHU6.js → prismic-ci-UTQ6LRR3.js} +2 -2
- package/dist/{prismic-models-HXCAM4ZL.js → prismic-models-PVES6R5V.js} +5 -5
- package/dist/{renovate-dispatch-HBZG2UEU.js → renovate-dispatch-ICJGSFCE.js} +2 -2
- package/dist/{report-LV7NY5W3.js → report-6CKSWJNG.js} +9 -6
- package/dist/report-6CKSWJNG.js.map +1 -0
- package/dist/{self-updating-4Q65OVXY.js → self-updating-PPQVV6UA.js} +2 -2
- package/dist/{selftest-K5XZKVTE.js → selftest-CQ6NOX52.js} +9 -6
- package/dist/selftest-CQ6NOX52.js.map +1 -0
- package/dist/{smoke-suite-J3LL3JZJ.js → smoke-suite-OBWNPALQ.js} +2 -2
- package/dist/{submissions-GMBUP4LV.js → submissions-GJ6ITBRH.js} +2 -2
- package/dist/{svelte-codemods-JTMX4BSX.js → svelte-codemods-ZOBDHIES.js} +2 -2
- package/dist/{sync-configs-5DXSL64Q.js → sync-configs-CJXUX6MD.js} +2 -2
- package/dist/{upgrade-HCR25P25.js → upgrade-WLX27UPC.js} +2 -2
- package/dist/{websites-VITQ3WXN.js → websites-SADZR4XQ.js} +2 -2
- package/dist/{write-audits-to-airtable-3SOXLKJK.js → write-audits-to-airtable-7PH75YWY.js} +4 -4
- package/package.json +1 -1
- package/dist/airtable-5ZPU3MT4.js +0 -9
- package/dist/chunk-CLWNAMUX.js.map +0 -1
- package/dist/digest-WGEPAWMP.js.map +0 -1
- package/dist/forms-notify-target-HSL4ZMT5.js.map +0 -1
- package/dist/report-LV7NY5W3.js.map +0 -1
- package/dist/selftest-K5XZKVTE.js.map +0 -1
- /package/dist/{airtable-5ZPU3MT4.js.map → airtable-HRKSA7V4.js.map} +0 -0
- /package/dist/{announce-4H64L2Z6.js.map → announce-GIAYN67S.js.map} +0 -0
- /package/dist/{bump-deps-2OL6PGTM.js.map → bump-deps-SWJB6H5V.js.map} +0 -0
- /package/dist/{chunk-XDCRVYFL.js.map → chunk-3YXDSCM6.js.map} +0 -0
- /package/dist/{chunk-MQUOUVQP.js.map → chunk-7J53SUT6.js.map} +0 -0
- /package/dist/{chunk-PBCGXXG6.js.map → chunk-COZPL62X.js.map} +0 -0
- /package/dist/{chunk-KV7DIRRO.js.map → chunk-GZNBCHAZ.js.map} +0 -0
- /package/dist/{chunk-5P2HVNLZ.js.map → chunk-LTB6KVJW.js.map} +0 -0
- /package/dist/{chunk-JVWJJ36K.js.map → chunk-MGR2H7F4.js.map} +0 -0
- /package/dist/{chunk-2WN4SNBQ.js.map → chunk-NWB4O5EY.js.map} +0 -0
- /package/dist/{chunk-OQFOMKBP.js.map → chunk-PBWDDDQH.js.map} +0 -0
- /package/dist/{convert-to-pnpm-KCXOYOHW.js.map → convert-to-pnpm-AT52NWZB.js.map} +0 -0
- /package/dist/{ensure-site-HYAIVZY2.js.map → ensure-site-S25MDDHW.js.map} +0 -0
- /package/dist/{github-signals-I7XACMCE.js.map → github-signals-G4ILZAJ6.js.map} +0 -0
- /package/dist/{header-image-ADYPTGVY.js.map → header-image-T7XD37JL.js.map} +0 -0
- /package/dist/{health-endpoint-JNCUILHO.js.map → health-endpoint-242WG2OJ.js.map} +0 -0
- /package/dist/{init-FLGLJCMJ.js.map → init-TFVAN5OY.js.map} +0 -0
- /package/dist/{launch-AVKH2JVF.js.map → launch-DWY2MF54.js.map} +0 -0
- /package/dist/{lighthouse-airtable-CHANWVO6.js.map → lighthouse-airtable-BIPM26SZ.js.map} +0 -0
- /package/dist/{onboard-HF4FTJDE.js.map → onboard-53CITIM7.js.map} +0 -0
- /package/dist/{orchestrate-5FMNYJEA.js.map → orchestrate-KDNXZQX7.js.map} +0 -0
- /package/dist/{preflight-HTWIX3MN.js.map → preflight-3XPDUHFJ.js.map} +0 -0
- /package/dist/{prismic-ci-4PDATHU6.js.map → prismic-ci-UTQ6LRR3.js.map} +0 -0
- /package/dist/{prismic-models-HXCAM4ZL.js.map → prismic-models-PVES6R5V.js.map} +0 -0
- /package/dist/{renovate-dispatch-HBZG2UEU.js.map → renovate-dispatch-ICJGSFCE.js.map} +0 -0
- /package/dist/{self-updating-4Q65OVXY.js.map → self-updating-PPQVV6UA.js.map} +0 -0
- /package/dist/{smoke-suite-J3LL3JZJ.js.map → smoke-suite-OBWNPALQ.js.map} +0 -0
- /package/dist/{submissions-GMBUP4LV.js.map → submissions-GJ6ITBRH.js.map} +0 -0
- /package/dist/{svelte-codemods-JTMX4BSX.js.map → svelte-codemods-ZOBDHIES.js.map} +0 -0
- /package/dist/{sync-configs-5DXSL64Q.js.map → sync-configs-CJXUX6MD.js.map} +0 -0
- /package/dist/{upgrade-HCR25P25.js.map → upgrade-WLX27UPC.js.map} +0 -0
- /package/dist/{websites-VITQ3WXN.js.map → websites-SADZR4XQ.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-3SOXLKJK.js.map → write-audits-to-airtable-7PH75YWY.js.map} +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-ZMIPG6TR.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveSites
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7J53SUT6.js";
|
|
9
9
|
import {
|
|
10
10
|
init
|
|
11
11
|
} from "./chunk-6V7565O2.js";
|
|
@@ -107,4 +107,4 @@ async function runInitCommand(site, opts) {
|
|
|
107
107
|
export {
|
|
108
108
|
runInitCommand
|
|
109
109
|
};
|
|
110
|
-
//# sourceMappingURL=init-
|
|
110
|
+
//# sourceMappingURL=init-TFVAN5OY.js.map
|
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
import "./chunk-MNDIED4M.js";
|
|
5
5
|
import {
|
|
6
6
|
writeAuditsToAirtable
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3YXDSCM6.js";
|
|
8
8
|
import {
|
|
9
9
|
hasRealScores,
|
|
10
10
|
lighthouseScoresFromResult
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PBWDDDQH.js";
|
|
12
12
|
import "./chunk-5L3FPQIJ.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveSites
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-7J53SUT6.js";
|
|
16
16
|
import {
|
|
17
17
|
queueDraft
|
|
18
18
|
} from "./chunk-62VF32IC.js";
|
|
@@ -46,7 +46,7 @@ import "./chunk-U5SZ4FOP.js";
|
|
|
46
46
|
import {
|
|
47
47
|
listWebsites,
|
|
48
48
|
siteSlug
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-577HCGZO.js";
|
|
50
50
|
import {
|
|
51
51
|
openBase,
|
|
52
52
|
readAirtableConfig
|
|
@@ -216,4 +216,4 @@ async function runLaunchCommand(site, opts) {
|
|
|
216
216
|
export {
|
|
217
217
|
runLaunchCommand
|
|
218
218
|
};
|
|
219
|
-
//# sourceMappingURL=launch-
|
|
219
|
+
//# sourceMappingURL=launch-DWY2MF54.js.map
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
hasRealScores,
|
|
3
3
|
lighthouseScoresFromResult,
|
|
4
4
|
resolveSlugFromCwd
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-PBWDDDQH.js";
|
|
6
|
+
import "./chunk-577HCGZO.js";
|
|
7
7
|
export {
|
|
8
8
|
hasRealScores,
|
|
9
9
|
lighthouseScoresFromResult,
|
|
10
10
|
resolveSlugFromCwd
|
|
11
11
|
};
|
|
12
|
-
//# sourceMappingURL=lighthouse-airtable-
|
|
12
|
+
//# sourceMappingURL=lighthouse-airtable-BIPM26SZ.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-ZMIPG6TR.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveSites
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7J53SUT6.js";
|
|
12
12
|
import {
|
|
13
13
|
onboard
|
|
14
14
|
} from "./chunk-UYCAF77E.js";
|
|
@@ -70,4 +70,4 @@ async function runOnboardCommand(site, opts) {
|
|
|
70
70
|
export {
|
|
71
71
|
runOnboardCommand
|
|
72
72
|
};
|
|
73
|
-
//# sourceMappingURL=onboard-
|
|
73
|
+
//# sourceMappingURL=onboard-53CITIM7.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
parseAddresses,
|
|
5
5
|
sendApprovedReports,
|
|
6
6
|
withGlobalCc
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-COZPL62X.js";
|
|
8
8
|
import "./chunk-GECESMVS.js";
|
|
9
9
|
import "./chunk-6QRLRT3P.js";
|
|
10
10
|
import "./chunk-MPBXOJ3N.js";
|
|
@@ -14,7 +14,7 @@ import "./chunk-QG6OSL4M.js";
|
|
|
14
14
|
import "./chunk-DC5H7KEQ.js";
|
|
15
15
|
import "./chunk-4SOCPK7A.js";
|
|
16
16
|
import "./chunk-U5SZ4FOP.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-577HCGZO.js";
|
|
18
18
|
import "./chunk-HN6I2XWI.js";
|
|
19
19
|
import "./chunk-6VAL7XJT.js";
|
|
20
20
|
export {
|
|
@@ -24,4 +24,4 @@ export {
|
|
|
24
24
|
sendApprovedReports,
|
|
25
25
|
withGlobalCc
|
|
26
26
|
};
|
|
27
|
-
//# sourceMappingURL=orchestrate-
|
|
27
|
+
//# sourceMappingURL=orchestrate-KDNXZQX7.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
preflight
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LTB6KVJW.js";
|
|
4
4
|
import "./chunk-D4FVAIEJ.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-COZPL62X.js";
|
|
6
6
|
import "./chunk-GECESMVS.js";
|
|
7
7
|
import "./chunk-6QRLRT3P.js";
|
|
8
8
|
import "./chunk-MPBXOJ3N.js";
|
|
@@ -12,7 +12,7 @@ import "./chunk-QG6OSL4M.js";
|
|
|
12
12
|
import "./chunk-DC5H7KEQ.js";
|
|
13
13
|
import "./chunk-4SOCPK7A.js";
|
|
14
14
|
import "./chunk-U5SZ4FOP.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-577HCGZO.js";
|
|
16
16
|
import "./chunk-HN6I2XWI.js";
|
|
17
17
|
import "./chunk-6VAL7XJT.js";
|
|
18
18
|
|
|
@@ -63,4 +63,4 @@ async function runPreflightCommand(site, opts) {
|
|
|
63
63
|
export {
|
|
64
64
|
runPreflightCommand
|
|
65
65
|
};
|
|
66
|
-
//# sourceMappingURL=preflight-
|
|
66
|
+
//# sourceMappingURL=preflight-3XPDUHFJ.js.map
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-ZMIPG6TR.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveSites
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-7J53SUT6.js";
|
|
16
16
|
import {
|
|
17
17
|
PRETTIER_FLAG_NOTE,
|
|
18
18
|
formatWithPrettier,
|
|
@@ -444,4 +444,4 @@ export {
|
|
|
444
444
|
formatPrismicCiResults,
|
|
445
445
|
runPrismicCiCommand
|
|
446
446
|
};
|
|
447
|
-
//# sourceMappingURL=prismic-ci-
|
|
447
|
+
//# sourceMappingURL=prismic-ci-UTQ6LRR3.js.map
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from "./chunk-ZMIPG6TR.js";
|
|
19
19
|
import {
|
|
20
20
|
resolveSites
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-7J53SUT6.js";
|
|
22
22
|
import {
|
|
23
23
|
PRETTIER_FLAG_NOTE,
|
|
24
24
|
formatWithPrettier
|
|
@@ -34,7 +34,7 @@ import "./chunk-XTK5VIQB.js";
|
|
|
34
34
|
import "./chunk-U5SZ4FOP.js";
|
|
35
35
|
import {
|
|
36
36
|
siteSlug
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-577HCGZO.js";
|
|
38
38
|
|
|
39
39
|
// src/cli/commands/prismic-models.ts
|
|
40
40
|
import { readdir, readFile, rename, rm, stat, writeFile } from "fs/promises";
|
|
@@ -166,7 +166,7 @@ var defaultDeps = () => ({
|
|
|
166
166
|
// every one of those runs fail on module load.
|
|
167
167
|
openVerdictSink: async () => {
|
|
168
168
|
const { openBase, readAirtableConfig } = await import("./client-EPVO3FEH.js");
|
|
169
|
-
const { listWebsites, updatePrismicModels } = await import("./websites-
|
|
169
|
+
const { listWebsites, updatePrismicModels } = await import("./websites-SADZR4XQ.js");
|
|
170
170
|
const base = openBase(readAirtableConfig());
|
|
171
171
|
const websites = await listWebsites(base);
|
|
172
172
|
return {
|
|
@@ -764,7 +764,7 @@ async function persistSweep(rows, deps) {
|
|
|
764
764
|
let sink;
|
|
765
765
|
let formatSummary;
|
|
766
766
|
try {
|
|
767
|
-
formatSummary = (await import("./write-audits-to-airtable-
|
|
767
|
+
formatSummary = (await import("./write-audits-to-airtable-7PH75YWY.js")).formatFleetWriteSummary;
|
|
768
768
|
sink = await deps.openVerdictSink();
|
|
769
769
|
} catch (e) {
|
|
770
770
|
return {
|
|
@@ -1017,4 +1017,4 @@ export {
|
|
|
1017
1017
|
sweepRowWriteback,
|
|
1018
1018
|
writeSweepToAirtable
|
|
1019
1019
|
};
|
|
1020
|
-
//# sourceMappingURL=prismic-models-
|
|
1020
|
+
//# sourceMappingURL=prismic-models-PVES6R5V.js.map
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
isDashboardVisible,
|
|
11
11
|
listWebsites,
|
|
12
12
|
updateAutoFixAttempts
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-577HCGZO.js";
|
|
14
14
|
import {
|
|
15
15
|
openBase,
|
|
16
16
|
readAirtableConfig
|
|
@@ -141,4 +141,4 @@ async function runRenovateDispatchCommand(opts) {
|
|
|
141
141
|
export {
|
|
142
142
|
runRenovateDispatchCommand
|
|
143
143
|
};
|
|
144
|
-
//# sourceMappingURL=renovate-dispatch-
|
|
144
|
+
//# sourceMappingURL=renovate-dispatch-ICJGSFCE.js.map
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
operatorEmail
|
|
3
|
+
} from "./chunk-5ML7FMBD.js";
|
|
1
4
|
import {
|
|
2
5
|
findDueReports,
|
|
3
6
|
nextDueDate,
|
|
@@ -6,7 +9,7 @@ import {
|
|
|
6
9
|
import {
|
|
7
10
|
draftReportForSite,
|
|
8
11
|
readGaConfig
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MGR2H7F4.js";
|
|
10
13
|
import {
|
|
11
14
|
reportTier
|
|
12
15
|
} from "./chunk-62VF32IC.js";
|
|
@@ -23,7 +26,7 @@ import {
|
|
|
23
26
|
listWebsites,
|
|
24
27
|
siteSlug,
|
|
25
28
|
updateNextDueDates
|
|
26
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-577HCGZO.js";
|
|
27
30
|
import {
|
|
28
31
|
openBase,
|
|
29
32
|
readAirtableConfig
|
|
@@ -73,11 +76,11 @@ function dashboardBaseUrl() {
|
|
|
73
76
|
}
|
|
74
77
|
async function runReportCommand(slug, opts) {
|
|
75
78
|
if (opts.digest) {
|
|
76
|
-
const { runDigest } = await import("./digest-
|
|
79
|
+
const { runDigest } = await import("./digest-UVHYZUYE.js");
|
|
77
80
|
return runDigest({ baseUrl: dashboardBaseUrl() });
|
|
78
81
|
}
|
|
79
82
|
if (opts.sendReady) {
|
|
80
|
-
const { sendApprovedReports } = await import("./orchestrate-
|
|
83
|
+
const { sendApprovedReports } = await import("./orchestrate-KDNXZQX7.js");
|
|
81
84
|
return sendApprovedReports();
|
|
82
85
|
}
|
|
83
86
|
if (opts.due) {
|
|
@@ -109,7 +112,7 @@ async function runDueDraft() {
|
|
|
109
112
|
async function alertOnFleetAnalyticsFailure(health) {
|
|
110
113
|
if (!assessAnalyticsAlert(health).fire) return;
|
|
111
114
|
try {
|
|
112
|
-
const to =
|
|
115
|
+
const to = operatorEmail();
|
|
113
116
|
const { subject, html } = composeAnalyticsAlertEmail(health, dashboardBaseUrl());
|
|
114
117
|
const { defaultResendClient } = await import("./resend-G2BJMAQV.js");
|
|
115
118
|
await defaultResendClient().send({
|
|
@@ -279,4 +282,4 @@ export {
|
|
|
279
282
|
parseSingleSiteReportType,
|
|
280
283
|
runReportCommand
|
|
281
284
|
};
|
|
282
|
-
//# sourceMappingURL=report-
|
|
285
|
+
//# sourceMappingURL=report-6CKSWJNG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/alerts/analytics-health.ts","../src/cli/commands/report.ts"],"sourcesContent":["import { escapeHtml } from \"../util/html.js\";\n\n/**\n * The GA/Search enrichment outcome of one `report --due` draft run, aggregated\n * across the sites it drafted. `softFailedSites` is how many drafted sites had GA\n * OR Search enrichment ERROR (not \"not configured\" — that's a legitimate skip);\n * `configuredSites` is how many drafted sites had analytics configured at all\n * (the subject is set AND the site has a GA4 property or a search query). The ratio\n * is what distinguishes a fleet-wide subject outage from a single transient blip.\n */\nexport type AnalyticsRunHealth = {\n softFailedSites: number;\n configuredSites: number;\n};\n\nexport type AnalyticsAlert = { fire: boolean; reason: string };\n\n/** A lone failure never alerts — that's a per-site config issue, not the shared-\n * subject SPOF. Two-plus AND a majority of configured sites is the fleet signature. */\nconst MIN_FAILED_SITES = 2;\n\n/**\n * Decide whether a draft run's GA/Search soft-failures look FLEET-WIDE — i.e. the\n * one impersonated subject (`GA_SUBJECT`) lost access — rather than one site's\n * transient blip. PURE. Fires when at least {@link MIN_FAILED_SITES} configured\n * sites failed AND they are a majority (≥ half) of the analytics-configured sites\n * this run. With <2 configured sites it can't distinguish a SPOF from a one-off, so\n * it never fires (at fleet scale there are always many configured sites).\n */\nexport function assessAnalyticsAlert(h: AnalyticsRunHealth): AnalyticsAlert {\n const { softFailedSites, configuredSites } = h;\n const fire =\n configuredSites >= 2 &&\n softFailedSites >= MIN_FAILED_SITES &&\n softFailedSites * 2 >= configuredSites;\n const reason = fire\n ? `${softFailedSites} of ${configuredSites} analytics-configured sites had GA/Search enrichment fail this run — the shared GA_SUBJECT likely lost access (an offboarded user, revoked property access, or a botched role-account cutover). Reports were drafted with BLANK analytics.`\n : \"\";\n return { fire, reason };\n}\n\n/**\n * Compose the operator alert email for a fleet-wide analytics failure. PURE — the\n * caller (the `report --due` cron) sends it best-effort via Resend only when\n * {@link assessAnalyticsAlert} fires. `dashboardUrl` is the fleet homepage link.\n */\nexport function composeAnalyticsAlertEmail(\n h: AnalyticsRunHealth,\n dashboardUrl: string,\n): { subject: string; html: string } {\n const subject = `⚠ Fleet analytics enrichment failing — ${h.softFailedSites}/${h.configuredSites} sites`;\n const { reason } = assessAnalyticsAlert(h);\n const html = `<p><strong>${escapeHtml(reason)}</strong></p>\n<p>This usually means the Google Workspace user the service account impersonates can no longer read the GA4 / Search Console properties. Reports still send — but with blank analytics — until the subject is restored.</p>\n<p>Next step: follow the GA/Search subject runbook (<code>docs/runbooks/ga-search-role-account-cutover.md</code>) to restore or move the subject, then re-run <code>reddoor-maint report --due</code> and confirm the warning clears.</p>\n<p><a href=\"${escapeHtml(dashboardUrl)}\">Open the fleet dashboard →</a></p>`;\n return { subject, html };\n}\n","import { openBase, readAirtableConfig, type AirtableBase } from \"../../reports/airtable/client.js\";\nimport {\n listWebsites,\n siteSlug,\n updateNextDueDates,\n type WebsiteRow,\n} from \"../../reports/airtable/websites.js\";\nimport { listAllReports, type ReportRow } from \"../../reports/airtable/reports.js\";\nimport { findDueReports, nextDueDate, reportPeriodKey } from \"../../reports/due.js\";\nimport { draftReportForSite } from \"../../reports/draft.js\";\nimport { reportTier } from \"../../reports/queue.js\";\nimport { readGaConfig } from \"../../reports/ga/config.js\";\nimport {\n assessAnalyticsAlert,\n composeAnalyticsAlertEmail,\n type AnalyticsRunHealth,\n} from \"../../alerts/analytics-health.js\";\nimport type { ReportType } from \"../../reports/types.js\";\nimport { operatorEmail } from \"../../util/operator.js\";\n\nexport type ReportCommandOptions = {\n due?: boolean;\n preview?: boolean;\n enrich?: boolean;\n sendReady?: boolean;\n digest?: boolean;\n type?: string;\n cwd?: string;\n};\n\n/**\n * Summary line for a drafted report, reflecting the single-queue outcome. `queued === false`\n * means a higher-or-equal-tier report was already pending for the site, so this draft was\n * created but deliberately left OUT of the approve queue. A non-empty `supersededIds` means it\n * un-queued that many lower-tier drafts. `null` is the previewOnly path (no Airtable queue).\n */\nfunction draftLine(\n reportId: string | undefined,\n queued: boolean | null,\n supersededIds: string[],\n verb = \"drafted\",\n): string {\n const id = reportId ?? \"(unknown)\";\n if (queued === false) {\n return `• ${verb} but NOT queued: ${id} — a higher-or-equal-tier report is already pending approval`;\n }\n const sup =\n supersededIds.length > 0\n ? ` (superseded ${supersededIds.length} lower-tier draft${supersededIds.length > 1 ? \"s\" : \"\"})`\n : \"\";\n return `✓ ${verb}: ${id}${sup}`;\n}\n\n/**\n * Parse the single-site `--type` flag. Only Maintenance and Testing are draftable\n * this way — Launch has the `launch <site>` command and Announcement has\n * `announce <site>`, each with its own purpose-built flow. Case-insensitive;\n * defaults to Maintenance (the historical single-site behaviour). Throws an\n * exitCode-2 usage error on anything else. PURE.\n */\nexport function parseSingleSiteReportType(raw: string | undefined): ReportType {\n if (raw === undefined || raw.trim() === \"\") return \"Maintenance\";\n const norm = raw.trim().toLowerCase();\n if (norm === \"maintenance\") return \"Maintenance\";\n if (norm === \"testing\") return \"Testing\";\n const hint =\n norm === \"launch\"\n ? \" — use the `launch <site>` command\"\n : norm === \"announcement\"\n ? \" — use the `announce <site>` command\"\n : \"\";\n throw Object.assign(\n new Error(`--type must be Maintenance or Testing (got ${JSON.stringify(raw)})${hint}`),\n { exitCode: 2 },\n );\n}\n\n/** Dashboard origin for digest /s/<slug> links. DASHBOARD_BASE_URL overrides the\n * production default; the trailing slash (if any) is trimmed by runDigest. */\nfunction dashboardBaseUrl(): string {\n return process.env.DASHBOARD_BASE_URL?.trim() || \"https://reddoor-maintenance.netlify.app\";\n}\n\nexport async function runReportCommand(\n slug: string | undefined,\n opts: ReportCommandOptions,\n): Promise<{ output: string; code: number }> {\n if (opts.digest) {\n const { runDigest } = await import(\"../../reports/digest.js\");\n return runDigest({ baseUrl: dashboardBaseUrl() });\n }\n\n if (opts.sendReady) {\n const { sendApprovedReports } = await import(\"../../reports/send/orchestrate.js\");\n return sendApprovedReports();\n }\n\n if (opts.due) {\n return runDueDraft();\n }\n\n if (slug) {\n // Validate the type BEFORE any Airtable access so a bad --type fails fast (and\n // without needing credentials).\n const reportType = parseSingleSiteReportType(opts.type);\n return runSingleSiteDraft(slug, {\n previewOnly: Boolean(opts.preview),\n enrich: Boolean(opts.enrich),\n reportType,\n });\n }\n\n throw Object.assign(\n new Error(\n \"Usage: reddoor-maint report [<slug>] [--type <Maintenance|Testing>] [--due] [--preview] [--enrich] [--send-ready] [--digest]\",\n ),\n {\n exitCode: 2,\n },\n );\n}\n\nasync function runDueDraft(): Promise<{ output: string; code: number }> {\n const base = openBase(readAirtableConfig());\n const result = await draftDueReports(base, new Date());\n await alertOnFleetAnalyticsFailure(result.health);\n return { output: result.output, code: result.code };\n}\n\n/** Best-effort: when a draft run's GA/Search soft-failures look FLEET-WIDE (the shared\n * GA_SUBJECT lost access — see assessAnalyticsAlert), email the operator one alert.\n * NEVER throws — a Resend or config hiccup must not fail the nightly draft cron; the\n * per-site `⚠ GA skipped` warnings + the run-output line still carry the signal. The\n * daily idempotency key dedupes multiple runs in one day (Resend dedupes 24h). */\nasync function alertOnFleetAnalyticsFailure(health: AnalyticsRunHealth): Promise<void> {\n if (!assessAnalyticsAlert(health).fire) return;\n try {\n const to = operatorEmail();\n const { subject, html } = composeAnalyticsAlertEmail(health, dashboardBaseUrl());\n const { defaultResendClient } = await import(\"../../reports/send/resend.js\");\n await defaultResendClient().send({\n from: \"Reddoor Reports <reports@reddoorla.com>\",\n to: [to],\n subject,\n html,\n idempotencyKey: `analytics-alert-${new Date().toISOString().slice(0, 10)}`,\n });\n console.warn(`⚠ ${subject} — operator alerted (${to})`);\n } catch (e) {\n console.warn(`⚠ analytics-failure alert send failed: ${(e as Error).message}`);\n }\n}\n\n/**\n * Write each site's code-computed next-maintenance / next-testing date back to Airtable\n * (date-only, or null when there's no schedule), so the \"next\" dates shown there derive\n * from the SAME `nextDueDate` the scheduler uses — replacing the old Airtable formula +\n * automation. Best-effort and per-site isolated: a missing `Next … at` column or one bad\n * row warns and is skipped, never aborting the nightly draft run.\n */\nasync function writeNextDueDates(\n base: AirtableBase,\n websites: WebsiteRow[],\n reports: ReportRow[],\n today: Date,\n): Promise<void> {\n const ymd = (d: Date | null): string | null => (d ? d.toISOString().slice(0, 10) : null);\n for (const site of websites) {\n try {\n await updateNextDueDates(base, site.id, {\n maintenanceAt: ymd(nextDueDate(site, reports, \"Maintenance\", today)),\n testingAt: ymd(nextDueDate(site, reports, \"Testing\", today)),\n });\n } catch (e) {\n console.warn(`⚠ next-due write skipped for ${site.name}: ${(e as Error).message}`);\n }\n }\n}\n\nexport async function draftDueReports(\n base: AirtableBase,\n today: Date,\n): Promise<{ output: string; code: number; health: AnalyticsRunHealth }> {\n const websites = await listWebsites(base);\n // ONE unfiltered fetch for the whole fleet. Per-site queries can't be pushed to\n // Airtable anyway (linked-record fields aren't formula-filterable by record id),\n // and findDueReports + the period guard below match on siteId in memory.\n const reports = await listAllReports(base);\n\n // Refresh every site's code-owned next-due dates first, so they stay current even on\n // a run where nothing is due (the early return below).\n await writeNextDueDates(base, websites, reports, today);\n\n const due = findDueReports(websites, reports, today);\n\n // GA/Search enrichment is configured globally (the impersonation subject) AND\n // per-site (a GA4 property or a search query). `gaConfigured` is the global half;\n // the per-site half is checked as each draft runs, to build the fleet-wide\n // analytics-failure alert's denominator (see alertOnFleetAnalyticsFailure).\n const gaConfigured = readGaConfig() !== null;\n // Truthy (not `!== null`) to mirror fetchGaUsers/fetchSearch's own gate exactly\n // (`!siteRow.ga4PropertyId`), so an empty-string cell counts as not-configured in\n // BOTH places and can't inflate the alert denominator.\n const isAnalyticsConfigured = (s: WebsiteRow): boolean =>\n gaConfigured && Boolean(s.ga4PropertyId || s.searchQuery);\n\n if (due.length === 0) {\n return {\n output: \"No reports due.\",\n code: 0,\n health: { softFailedSites: 0, configuredSites: 0 },\n };\n }\n\n const lines: string[] = [];\n let softFailedSites = 0;\n let searchDefaultMisses = 0;\n let searchPropertiesMissing = 0;\n let gaConfiguredSites = 0;\n let skipped = 0;\n for (const item of due) {\n // Idempotency: a re-run must not re-draft a (site, type) already drafted this\n // recurrence. The dueDate's YYYY-MM is the stable per-cycle key. Match against the\n // reports we already fetched — no extra query on the hot path.\n const period = reportPeriodKey(item.dueDate);\n const existing = reports.find(\n (r) => r.siteId === item.site.id && r.reportType === item.reportType && r.period === period,\n );\n\n // A row already exists for THIS period. Two cases:\n // - Draft ready → truly done, skip (the idempotent re-run path).\n // - NOT ready → a crash between createDraft and setDraftReady wedged it: the\n // row exists (so we never re-draft) yet it's never sendable (listSendable\n // needs Draft ready). COMPLETE it in place instead of skipping forever —\n // re-render → re-upload the HTML → flip Draft ready on the EXISTING row.\n if (existing) {\n if (existing.draftReady) {\n skipped++;\n lines.push(`• skipped (already drafted ${period}): ${item.site.name} ${item.reportType}`);\n continue;\n }\n // A not-ready row is normally a crash between createDraft and setDraftReady — re-complete\n // it in place. BUT queueDraft also clears Draft ready on rows it supersedes/blocks, and\n // those must NOT be re-completed: doing so would re-render and APPEND a duplicate HTML\n // attachment every nightly run, only to be re-blocked. Distinguish the two: if a\n // higher-or-equal-tier report is still pending for this site, this row was intentionally\n // un-queued (not crashed) — skip it until the blocker is sent/approved or the month rolls.\n const blockedByPending = reports.some(\n (r) =>\n r.siteId === item.site.id &&\n r.id !== existing.id &&\n r.sentAt === null &&\n r.draftReady &&\n reportTier(r.reportType) >= reportTier(item.reportType),\n );\n if (blockedByPending) {\n skipped++;\n lines.push(\n `• skipped (superseded — a higher-or-equal-tier report is pending): ${item.site.name} ${item.reportType}`,\n );\n continue;\n }\n try {\n const result = await draftReportForSite(base, item.site, item.reportType, {\n period,\n completeRowId: existing.id,\n existingRow: existing,\n });\n existing.draftReady = result.queued === true;\n lines.push(\n draftLine(\n result.reportRow?.reportId ?? existing.reportId,\n result.queued,\n result.supersededIds,\n \"completed half-made draft\",\n ),\n );\n if (isAnalyticsConfigured(item.site)) gaConfiguredSites++;\n if (result.softFailures.length > 0) softFailedSites++;\n if (result.searchDefaultMissed) searchDefaultMisses++;\n if (result.searchPropertyMissing) searchPropertiesMissing++;\n } catch (e) {\n lines.push(`✗ failed: ${item.site.name} ${item.reportType} — ${(e as Error).message}`);\n }\n continue;\n }\n\n // Pile-up guard: don't accrue a fresh new-period draft every recurrence for a\n // site nobody ever approves. The period key follows the DUE month, so each\n // recurrence wants a new (later-period) draft — but if a PRIOR draft is still\n // pending approval, a new one just stacks. Skip creating the new one while an\n // earlier-period draft for this (site, type) sits ready-but-unsent.\n //\n // `r.draftReady` is load-bearing: a draft a higher tier SUPERSEDED has\n // draftReady=false and never gets a Sent at, so without this clause it would\n // match (sentAt null + earlier period) and block EVERY future draft for the\n // site forever. Pending-approval means draftReady=true AND sentAt=null.\n const pendingEarlier = reports.find(\n (r) =>\n r.siteId === item.site.id &&\n r.reportType === item.reportType &&\n r.draftReady &&\n r.sentAt === null &&\n r.period !== null &&\n r.period < period,\n );\n if (pendingEarlier) {\n skipped++;\n lines.push(\n `• skipped: ${item.site.name} ${item.reportType} already has an unsent ${pendingEarlier.period} draft pending approval`,\n );\n continue;\n }\n\n try {\n // Pass the SAME key the guard searches by, so the stamped Period always\n // matches a future run's reportPeriodKey(dueDate) — even if this run lags\n // into a later month than the dueDate.\n const result = await draftReportForSite(base, item.site, item.reportType, { period });\n lines.push(draftLine(result.reportRow?.reportId, result.queued, result.supersededIds));\n // Keep the in-memory snapshot current so the guard's `.some()` check on the\n // NEXT iteration of this same run catches a row we JUST created — rather than\n // relying on findDueReports never emitting two items for the same (site, type).\n if (result.reportRow) reports.push(result.reportRow);\n // Count sites (not individual GA/Search failures) so a fleet-wide enrichment\n // outage is one obvious line at the bottom, not 200 buried console.warns.\n if (isAnalyticsConfigured(item.site)) gaConfiguredSites++;\n if (result.softFailures.length > 0) softFailedSites++;\n if (result.searchDefaultMissed) searchDefaultMisses++;\n if (result.searchPropertyMissing) searchPropertiesMissing++;\n } catch (e) {\n lines.push(`✗ failed: ${item.site.name} ${item.reportType} — ${(e as Error).message}`);\n }\n }\n if (skipped > 0) {\n lines.push(`• ${skipped} already drafted or pending this period`);\n }\n if (softFailedSites > 0) {\n lines.push(\n `⚠ ${softFailedSites} site${softFailedSites === 1 ? \"\" : \"s\"} had GA/Search enrichment fail — drafted with blank analytics; check the logs above`,\n );\n }\n if (searchDefaultMisses > 0) {\n lines.push(\n `⚑ ${searchDefaultMisses} site${searchDefaultMisses === 1 ? \"\" : \"s\"} returned no Search Console data for their name — set an explicit \"Search query\" in Airtable to track brand presence.`,\n );\n }\n if (searchPropertiesMissing > 0) {\n lines.push(\n `⚑ ${searchPropertiesMissing} site${searchPropertiesMissing === 1 ? \"\" : \"s\"} matched NO Search Console property — verify the domain property exists and the service account has access (a \"Search query\" change cannot fix this).`,\n );\n }\n return {\n output: lines.join(\"\\n\"),\n code: lines.some((l) => l.startsWith(\"✗\")) ? 1 : 0,\n health: { softFailedSites, configuredSites: gaConfiguredSites },\n };\n}\n\nasync function runSingleSiteDraft(\n slug: string,\n opts: { previewOnly: boolean; enrich: boolean; reportType: ReportType },\n): Promise<{ output: string; code: number }> {\n const base = openBase(readAirtableConfig());\n const websites = await listWebsites(base);\n const site = websites.find((w) => siteSlug(w.name) === slug);\n if (!site) {\n throw Object.assign(new Error(`No Websites row matched slug \"${slug}\"`), { exitCode: 2 });\n }\n const result = await draftReportForSite(opts.previewOnly ? null : base, site, opts.reportType, {\n previewOnly: opts.previewOnly,\n // Only forced on. Left undefined, draftReportForSite keeps its default\n // (enrich iff there is a base), so the real drafting path is untouched.\n ...(opts.enrich ? { enrich: true } : {}),\n });\n if (opts.previewOnly) {\n return { output: `Preview written to ${result.htmlPath}`, code: 0 };\n }\n return {\n output: draftLine(\n result.reportRow?.reportId,\n result.queued,\n result.supersededIds,\n \"Draft created\",\n ),\n code: 0,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-ZMIPG6TR.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveSites
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-7J53SUT6.js";
|
|
16
16
|
import "./chunk-73UFRZKY.js";
|
|
17
17
|
import "./chunk-GASBX52O.js";
|
|
18
18
|
import "./chunk-VRWUL4TR.js";
|
|
@@ -62,4 +62,4 @@ async function runSelfUpdatingCommand(site, opts) {
|
|
|
62
62
|
export {
|
|
63
63
|
runSelfUpdatingCommand
|
|
64
64
|
};
|
|
65
|
-
//# sourceMappingURL=self-updating-
|
|
65
|
+
//# sourceMappingURL=self-updating-PPQVV6UA.js.map
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildReportDataForSite,
|
|
3
3
|
scoresFromRow
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GZNBCHAZ.js";
|
|
5
|
+
import {
|
|
6
|
+
operatorEmail
|
|
7
|
+
} from "./chunk-5ML7FMBD.js";
|
|
5
8
|
import {
|
|
6
9
|
ELIGIBLE_STATUSES
|
|
7
10
|
} from "./chunk-D4FVAIEJ.js";
|
|
8
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-MGR2H7F4.js";
|
|
9
12
|
import "./chunk-62VF32IC.js";
|
|
10
13
|
import "./chunk-37S6L6G4.js";
|
|
11
14
|
import {
|
|
@@ -13,7 +16,7 @@ import {
|
|
|
13
16
|
parseAddresses,
|
|
14
17
|
prepareHeaderImage,
|
|
15
18
|
renderReportEmail
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-COZPL62X.js";
|
|
17
20
|
import "./chunk-GECESMVS.js";
|
|
18
21
|
import "./chunk-6QRLRT3P.js";
|
|
19
22
|
import {
|
|
@@ -30,7 +33,7 @@ import "./chunk-U5SZ4FOP.js";
|
|
|
30
33
|
import {
|
|
31
34
|
listWebsites,
|
|
32
35
|
siteSlug
|
|
33
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-577HCGZO.js";
|
|
34
37
|
import {
|
|
35
38
|
openBase,
|
|
36
39
|
readAirtableConfig
|
|
@@ -43,7 +46,7 @@ import { dirname } from "path";
|
|
|
43
46
|
var FROM_ADDRESS = "Reddoor Reports <reports@reddoorla.com>";
|
|
44
47
|
var REPLY_TO = "info@reddoorla.com";
|
|
45
48
|
function resolveRecipients(to) {
|
|
46
|
-
const operator =
|
|
49
|
+
const operator = operatorEmail();
|
|
47
50
|
const parsed = to ? parseAddresses(to) : null;
|
|
48
51
|
const list = parsed ?? [operator];
|
|
49
52
|
for (const addr of list) {
|
|
@@ -162,4 +165,4 @@ async function runSelftestCommand(kind, site, opts) {
|
|
|
162
165
|
export {
|
|
163
166
|
runSelftestCommand
|
|
164
167
|
};
|
|
165
|
-
//# sourceMappingURL=selftest-
|
|
168
|
+
//# sourceMappingURL=selftest-CQ6NOX52.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/recipes/selftest-email.ts","../src/cli/commands/selftest.ts"],"sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { openBase, readAirtableConfig } from \"../reports/airtable/client.js\";\nimport type { AirtableBase } from \"../reports/airtable/client.js\";\nimport { listWebsites, siteSlug } from \"../reports/airtable/websites.js\";\nimport { ELIGIBLE_STATUSES } from \"../reports/due.js\";\nimport type { WebsiteRow } from \"../reports/airtable/websites.js\";\nimport { fetchAttachmentBytes } from \"../reports/airtable/attachments.js\";\nimport { prepareHeaderImage } from \"../reports/maintenance-email/header-image.js\";\nimport { buildReportDataForSite, scoresFromRow } from \"../reports/report-data.js\";\nimport { renderReportEmail } from \"../reports/send/render-email.js\";\nimport { defaultResendClient, type ResendClient } from \"../reports/send/resend.js\";\nimport { parseAddresses, isProbablyEmail } from \"../reports/send/orchestrate.js\";\nimport { operatorEmail } from \"../util/operator.js\";\nimport type { ReportType } from \"../reports/types.js\";\n\nconst FROM_ADDRESS = \"Reddoor Reports <reports@reddoorla.com>\";\nconst REPLY_TO = \"info@reddoorla.com\";\n\nexport type SelftestEmailDeps = {\n /** Airtable handle (read-only here). Defaults to the live base from credentials. */\n base?: AirtableBase;\n /** Resend client. Defaults to the real client. */\n resend?: ResendClient;\n /** Single-site slug. Mutually exclusive with `all`. */\n site?: string;\n /** All `maintenance` sites (one email each). Mutually exclusive with `site`. */\n all?: boolean;\n /** Report type to preview. Default \"Announcement\". */\n type?: ReportType;\n /** Raw `--to` (comma- or newline-separated). Default: the operator inbox. */\n to?: string;\n /** Render only; write reports/<slug>/selftest-<type>.html, never send. */\n dryRun?: boolean;\n /** Single timestamp driving the window + completedOn. */\n now?: Date;\n};\n\nexport type SelftestEmailSiteResult =\n | { site: string; status: \"sent\" | \"dry-run\"; subject: string; recipients: string[] }\n | { site: string; status: \"skipped\"; reason: string }\n | { site: string; status: \"error\"; message: string };\n\nexport type SelftestEmailResult = { results: SelftestEmailSiteResult[] };\n\n/** Resolve the recipient list: explicit `--to` (validated) else the operator default. */\nfunction resolveRecipients(to: string | undefined): string[] {\n const operator = operatorEmail();\n const parsed = to ? parseAddresses(to) : null;\n const list = parsed ?? [operator];\n for (const addr of list) {\n if (!isProbablyEmail(addr)) {\n throw Object.assign(new Error(`--to has a malformed address: ${addr}`), { exitCode: 2 });\n }\n }\n return list;\n}\n\n/**\n * Send (or dry-render) a single report email per target site to the operator/`--to`, with NO\n * Airtable side effects (no draft, queue, or stamp). Mirrors the production render+send via the\n * shared `renderReportEmail` seam, so the preview matches a real send. One bad site never aborts\n * `--all` (per-site try/catch). Sites missing stored scores or a header image are skipped.\n */\nexport async function selftestEmail(deps: SelftestEmailDeps): Promise<SelftestEmailResult> {\n const base = deps.base ?? openBase(readAirtableConfig());\n const resend = deps.resend ?? defaultResendClient();\n const type: ReportType = deps.type ?? \"Announcement\";\n const now = deps.now ?? new Date();\n const recipients = resolveRecipients(deps.to);\n\n const websites = await listWebsites(base);\n let targets: WebsiteRow[];\n if (deps.all) {\n // The report-eligible set (maintenance + hosting), not a hard-coded \"maintenance\" —\n // the latter silently excluded hosting sites and implied a type↔status coupling that\n // doesn't exist (the requested --type drives the rendered template; single-site mode\n // applies no status filter at all).\n targets = websites.filter((w) => w.status !== null && ELIGIBLE_STATUSES.has(w.status));\n } else if (deps.site) {\n const wanted = siteSlug(deps.site);\n targets = websites.filter((w) => siteSlug(w.name) === wanted);\n } else {\n throw Object.assign(new Error(\"Provide a site slug or --all\"), { exitCode: 2 });\n }\n\n const results: SelftestEmailSiteResult[] = [];\n for (const w of targets) {\n try {\n const scores = scoresFromRow(w);\n if (!scores) {\n results.push({ site: w.name, status: \"skipped\", reason: \"missing Lighthouse scores\" });\n continue;\n }\n if (!w.headerImage) {\n results.push({ site: w.name, status: \"skipped\", reason: \"no Header image\" });\n continue;\n }\n const original = await fetchAttachmentBytes(w.headerImage.url);\n const header = await prepareHeaderImage(original.bytes);\n const slug = siteSlug(w.name);\n const reportData = await buildReportDataForSite(w, type, now, { scores, header });\n const { html, attachments, subject } = await renderReportEmail(reportData, {\n header,\n cidName: `${slug}-header`,\n });\n\n if (deps.dryRun) {\n const path = `reports/${slug}/selftest-${type.toLowerCase()}.html`;\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, html, \"utf-8\");\n results.push({ site: w.name, status: \"dry-run\", subject, recipients });\n continue;\n }\n\n await resend.send({\n from: FROM_ADDRESS,\n to: recipients,\n replyTo: REPLY_TO,\n subject,\n html,\n attachments,\n });\n results.push({ site: w.name, status: \"sent\", subject, recipients });\n } catch (err) {\n results.push({\n site: w.name,\n status: \"error\",\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return { results };\n}\n","import { selftestEmail, type SelftestEmailSiteResult } from \"../../recipes/selftest-email.js\";\nimport type { ReportType } from \"../../reports/types.js\";\n\nexport type SelftestCommandOptions = {\n type?: string;\n to?: string;\n all?: boolean;\n dryRun?: boolean;\n cwd?: string;\n};\n\nconst TYPES: Record<string, ReportType> = {\n announcement: \"Announcement\",\n maintenance: \"Maintenance\",\n testing: \"Testing\",\n launch: \"Launch\",\n};\n\nfunction formatResult(r: SelftestEmailSiteResult): string {\n if (r.status === \"skipped\") return `[${r.site}] skipped — ${r.reason}`;\n if (r.status === \"error\") return `[${r.site}] error: ${r.message}`;\n return `[${r.site}] ${r.status} — \"${r.subject}\" → ${r.recipients.join(\", \")}`;\n}\n\n/**\n * `selftest <kind> [site]` — operator self-tests. The only kind today is `email`: preview a\n * report email for one site (or `--all` maintenance sites) to the operator/`--to`, with no\n * Airtable side effects. Validates kind/type and the site-xor-all rule before doing any work.\n */\nexport async function runSelftestCommand(\n kind: string,\n site: string | undefined,\n opts: SelftestCommandOptions,\n): Promise<{ output: string; code: number }> {\n if (kind !== \"email\") {\n return { output: `Unknown selftest kind '${kind}'. Supported: email`, code: 2 };\n }\n if (Boolean(site) === Boolean(opts.all)) {\n return { output: \"Provide exactly one of <site> or --all.\", code: 2 };\n }\n const typeKey = (opts.type ?? \"announcement\").toLowerCase();\n const type = TYPES[typeKey];\n if (!type) {\n return {\n output: `Unknown --type '${opts.type}'. Supported: ${Object.keys(TYPES).join(\", \")}`,\n code: 2,\n };\n }\n\n try {\n const { results } = await selftestEmail({\n ...(site ? { site } : {}),\n ...(opts.all ? { all: true } : {}),\n type,\n ...(opts.to ? { to: opts.to } : {}),\n ...(opts.dryRun ? { dryRun: true } : {}),\n });\n const output =\n results.length === 0 ? \"No matching sites.\" : results.map(formatResult).join(\"\\n\");\n const code = results.some((r) => r.status === \"error\") ? 1 : 0;\n return { output, code };\n } catch (err) {\n const e = err as { message?: string; exitCode?: number };\n return { output: e.message ?? String(err), code: e.exitCode ?? 1 };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-ZMIPG6TR.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveSites
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7J53SUT6.js";
|
|
12
12
|
import {
|
|
13
13
|
smokeSuite
|
|
14
14
|
} from "./chunk-R4AB6GCT.js";
|
|
@@ -51,4 +51,4 @@ async function runSmokeSuiteCommand(site, opts) {
|
|
|
51
51
|
export {
|
|
52
52
|
runSmokeSuiteCommand
|
|
53
53
|
};
|
|
54
|
-
//# sourceMappingURL=smoke-suite-
|
|
54
|
+
//# sourceMappingURL=smoke-suite-OBWNPALQ.js.map
|
|
@@ -41,7 +41,7 @@ async function rescoreNewSubmissions(db, opts) {
|
|
|
41
41
|
async function loadSiteNames() {
|
|
42
42
|
try {
|
|
43
43
|
const { openBase, readAirtableConfig } = await import("./client-EPVO3FEH.js");
|
|
44
|
-
const { listWebsites } = await import("./websites-
|
|
44
|
+
const { listWebsites } = await import("./websites-SADZR4XQ.js");
|
|
45
45
|
const sites = await listWebsites(openBase(readAirtableConfig()));
|
|
46
46
|
return new Map(sites.map((s) => [s.id, s.name]));
|
|
47
47
|
} catch (err) {
|
|
@@ -119,4 +119,4 @@ export {
|
|
|
119
119
|
rescoreNewSubmissions,
|
|
120
120
|
runSubmissionsCommand
|
|
121
121
|
};
|
|
122
|
-
//# sourceMappingURL=submissions-
|
|
122
|
+
//# sourceMappingURL=submissions-GJ6ITBRH.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-ZMIPG6TR.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveSites
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7J53SUT6.js";
|
|
12
12
|
import {
|
|
13
13
|
svelteCodemods
|
|
14
14
|
} from "./chunk-LS6QPANO.js";
|
|
@@ -51,4 +51,4 @@ async function runSvelteCodemodsCommand(site, opts) {
|
|
|
51
51
|
export {
|
|
52
52
|
runSvelteCodemodsCommand
|
|
53
53
|
};
|
|
54
|
-
//# sourceMappingURL=svelte-codemods-
|
|
54
|
+
//# sourceMappingURL=svelte-codemods-ZOBDHIES.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-ZMIPG6TR.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveSites
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7J53SUT6.js";
|
|
12
12
|
import {
|
|
13
13
|
ALL_CONFIG_NAMES,
|
|
14
14
|
CANONICAL_GITIGNORE_ENTRIES,
|
|
@@ -113,4 +113,4 @@ async function runSyncConfigsCommand(site, opts) {
|
|
|
113
113
|
export {
|
|
114
114
|
runSyncConfigsCommand
|
|
115
115
|
};
|
|
116
|
-
//# sourceMappingURL=sync-configs-
|
|
116
|
+
//# sourceMappingURL=sync-configs-CJXUX6MD.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-ZMIPG6TR.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveSites
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7J53SUT6.js";
|
|
12
12
|
import {
|
|
13
13
|
upgradeSvelte4to5
|
|
14
14
|
} from "./chunk-ICXV25N7.js";
|
|
@@ -60,4 +60,4 @@ async function runUpgradeCommand(upgradeName, site, opts = {}) {
|
|
|
60
60
|
export {
|
|
61
61
|
runUpgradeCommand
|
|
62
62
|
};
|
|
63
|
-
//# sourceMappingURL=upgrade-
|
|
63
|
+
//# sourceMappingURL=upgrade-WLX27UPC.js.map
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
updateScores,
|
|
32
32
|
updateSecurityCounts,
|
|
33
33
|
updateSiteField
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-577HCGZO.js";
|
|
35
35
|
export {
|
|
36
36
|
ACTIVE_STATUSES,
|
|
37
37
|
ARCHIVED_STATUSES,
|
|
@@ -66,4 +66,4 @@ export {
|
|
|
66
66
|
updateSecurityCounts,
|
|
67
67
|
updateSiteField
|
|
68
68
|
};
|
|
69
|
-
//# sourceMappingURL=websites-
|
|
69
|
+
//# sourceMappingURL=websites-SADZR4XQ.js.map
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
formatFleetWriteSummary,
|
|
3
3
|
writeAuditsToAirtable,
|
|
4
4
|
writeFleetAuditsToAirtable
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-3YXDSCM6.js";
|
|
6
|
+
import "./chunk-PBWDDDQH.js";
|
|
7
7
|
import "./chunk-5L3FPQIJ.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-577HCGZO.js";
|
|
9
9
|
export {
|
|
10
10
|
formatFleetWriteSummary,
|
|
11
11
|
writeAuditsToAirtable,
|
|
12
12
|
writeFleetAuditsToAirtable
|
|
13
13
|
};
|
|
14
|
-
//# sourceMappingURL=write-audits-to-airtable-
|
|
14
|
+
//# sourceMappingURL=write-audits-to-airtable-7PH75YWY.js.map
|
package/package.json
CHANGED