@reddoorla/maintenance 0.69.0 → 0.72.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 +15 -14
- package/dist/airtable-U2GTDTK5.js +9 -0
- package/dist/{announce-72R3LRNT.js → announce-HJCGEVJA.js} +6 -6
- package/dist/blux-FKZYMKLF.js +2205 -0
- package/dist/blux-FKZYMKLF.js.map +1 -0
- package/dist/{bump-deps-QNM3H4GI.js → bump-deps-GZEJAUKI.js} +3 -2
- package/dist/bump-deps-GZEJAUKI.js.map +1 -0
- package/dist/chunk-7MJBTV2R.js +145 -0
- package/dist/chunk-7MJBTV2R.js.map +1 -0
- package/dist/{chunk-2DCA7FHZ.js → chunk-7P7YETHG.js} +34 -12
- package/dist/chunk-7P7YETHG.js.map +1 -0
- package/dist/{chunk-42KKVLYN.js → chunk-APTAITXZ.js} +10 -2
- package/dist/chunk-APTAITXZ.js.map +1 -0
- package/dist/{chunk-6G7BC5SN.js → chunk-BHE5CUWI.js} +392 -7
- package/dist/chunk-BHE5CUWI.js.map +1 -0
- package/dist/{chunk-XWPZ46IN.js → chunk-BJCA7O4A.js} +2 -2
- package/dist/{chunk-C3PDS623.js → chunk-BWKK2ZXS.js} +67 -8
- package/dist/chunk-BWKK2ZXS.js.map +1 -0
- package/dist/{chunk-45AUGDFR.js → chunk-D4FVAIEJ.js} +6 -20
- package/dist/chunk-D4FVAIEJ.js.map +1 -0
- package/dist/{chunk-YQMYQAJX.js → chunk-GI4M2AMO.js} +2 -2
- package/dist/{chunk-OTBA7DON.js → chunk-GYNRZCM6.js} +7 -2
- package/dist/chunk-GYNRZCM6.js.map +1 -0
- package/dist/{chunk-6MT5W6UF.js → chunk-HR5SONJC.js} +6 -3
- package/dist/chunk-HR5SONJC.js.map +1 -0
- package/dist/{chunk-6JFOAPW4.js → chunk-JCITWZQR.js} +51 -19
- package/dist/chunk-JCITWZQR.js.map +1 -0
- package/dist/{chunk-GKSXZIMX.js → chunk-JGLAWXUC.js} +77 -3
- package/dist/chunk-JGLAWXUC.js.map +1 -0
- package/dist/{chunk-E2GKKUEX.js → chunk-KLB2OLPW.js} +26 -6
- package/dist/chunk-KLB2OLPW.js.map +1 -0
- package/dist/{chunk-RINXPU3H.js → chunk-KLVMJYZZ.js} +2 -2
- package/dist/chunk-KRDLHAKK.js +17 -0
- package/dist/chunk-KRDLHAKK.js.map +1 -0
- package/dist/{chunk-AESJBEM7.js → chunk-KRHPS3R4.js} +3 -3
- package/dist/{chunk-LYCKN7ZR.js → chunk-LJPCMXR7.js} +8 -5
- package/dist/chunk-LJPCMXR7.js.map +1 -0
- package/dist/{chunk-O6G4HHMF.js → chunk-NRISG4XD.js} +308 -104
- package/dist/chunk-NRISG4XD.js.map +1 -0
- package/dist/chunk-PKVZMFEB.js +315 -0
- package/dist/chunk-PKVZMFEB.js.map +1 -0
- package/dist/chunk-SL24DCGC.js +41 -0
- package/dist/chunk-SL24DCGC.js.map +1 -0
- package/dist/{chunk-A5KYRGQA.js → chunk-SQJ53Z7R.js} +4 -4
- package/dist/cli/bin.js +63 -19
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.d.ts +1 -1
- package/dist/cli/commands/audit.js +11 -9
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/configs/playwright-a11y.d.ts +1 -1
- package/dist/configs/playwright-a11y.js +1 -3
- package/dist/{convert-to-pnpm-XH7NYRVK.js → convert-to-pnpm-SVFDLXZS.js} +3 -2
- package/dist/convert-to-pnpm-SVFDLXZS.js.map +1 -0
- package/dist/{digest-Q2TAQHXF.js → digest-VX7Q4MNF.js} +8 -8
- package/dist/{ensure-site-2PF522VL.js → ensure-site-O7G5ZJS7.js} +2 -2
- package/dist/forms/index.d.ts +5 -2
- package/dist/forms/index.js +22 -9
- package/dist/forms/index.js.map +1 -1
- package/dist/{github-signals-CLQC2IPY.js → github-signals-QVW2LB7N.js} +5 -5
- package/dist/health-endpoint-IYR5VBUT.js +54 -0
- package/dist/health-endpoint-IYR5VBUT.js.map +1 -0
- package/dist/index.d.ts +136 -20
- package/dist/index.js +207 -64
- package/dist/index.js.map +1 -1
- package/dist/{init-UA6D7GKW.js → init-CU6PVZRG.js} +9 -5
- package/dist/init-CU6PVZRG.js.map +1 -0
- package/dist/{launch-AENAS2O2.js → launch-JWXCTJRG.js} +9 -9
- package/dist/{lighthouse-airtable-UBSXKHAQ.js → lighthouse-airtable-J5TLASJC.js} +3 -3
- package/dist/{onboard-X6KJ5Z2V.js → onboard-6UQE5QIO.js} +2 -2
- package/dist/{orchestrate-GADNFGDH.js → orchestrate-ZDH24Z6Y.js} +5 -5
- package/dist/{preflight-D5RQGX4V.js → preflight-BNTMWTPG.js} +7 -7
- package/dist/probe-DJAMLVTT.js +46 -0
- package/dist/probe-DJAMLVTT.js.map +1 -0
- package/dist/recipes/sync-configs.d.ts +1 -1
- package/dist/{renovate-dispatch-LG4RJGDY.js → renovate-dispatch-C3ALLACX.js} +2 -2
- package/dist/{report-3FJ224H5.js → report-YLFSGNWR.js} +12 -12
- package/dist/run-migration-LJNNZWIV.js +205 -0
- package/dist/run-migration-LJNNZWIV.js.map +1 -0
- package/dist/{self-updating-JTTFOJ7Q.js → self-updating-64FNRQB5.js} +2 -2
- package/dist/{selftest-55OJIWEB.js → selftest-7DPNGL6R.js} +12 -9
- package/dist/selftest-7DPNGL6R.js.map +1 -0
- package/dist/smoke-suite-TWILWDSF.js +54 -0
- package/dist/smoke-suite-TWILWDSF.js.map +1 -0
- package/dist/{svelte-codemods-KJLNH6FQ.js → svelte-codemods-RVDTTXFD.js} +3 -2
- package/dist/svelte-codemods-RVDTTXFD.js.map +1 -0
- package/dist/{sync-configs-TIBO6DUJ.js → sync-configs-BUUD6L5Q.js} +3 -2
- package/dist/sync-configs-BUUD6L5Q.js.map +1 -0
- package/dist/{types-Dg4mHvyf.d.ts → types-0jreMCF5.d.ts} +2 -2
- package/dist/{upgrade-TPTE26FG.js → upgrade-HHKWYJRN.js} +3 -2
- package/dist/upgrade-HHKWYJRN.js.map +1 -0
- package/dist/{websites-6YTT5ZTO.js → websites-EH2ULELZ.js} +8 -2
- package/dist/{write-audits-to-airtable-IWOO4FFH.js → write-audits-to-airtable-LZDYTNX5.js} +4 -4
- package/package.json +4 -1
- package/dist/airtable-WGQQ3KAD.js +0 -9
- package/dist/bump-deps-QNM3H4GI.js.map +0 -1
- package/dist/chunk-2DCA7FHZ.js.map +0 -1
- package/dist/chunk-42KKVLYN.js.map +0 -1
- package/dist/chunk-45AUGDFR.js.map +0 -1
- package/dist/chunk-6G7BC5SN.js.map +0 -1
- package/dist/chunk-6JFOAPW4.js.map +0 -1
- package/dist/chunk-6MT5W6UF.js.map +0 -1
- package/dist/chunk-C3PDS623.js.map +0 -1
- package/dist/chunk-E2GKKUEX.js.map +0 -1
- package/dist/chunk-GKSXZIMX.js.map +0 -1
- package/dist/chunk-LYCKN7ZR.js.map +0 -1
- package/dist/chunk-O6G4HHMF.js.map +0 -1
- package/dist/chunk-OTBA7DON.js.map +0 -1
- package/dist/convert-to-pnpm-XH7NYRVK.js.map +0 -1
- package/dist/init-UA6D7GKW.js.map +0 -1
- package/dist/selftest-55OJIWEB.js.map +0 -1
- package/dist/svelte-codemods-KJLNH6FQ.js.map +0 -1
- package/dist/sync-configs-TIBO6DUJ.js.map +0 -1
- package/dist/upgrade-TPTE26FG.js.map +0 -1
- /package/dist/{airtable-WGQQ3KAD.js.map → airtable-U2GTDTK5.js.map} +0 -0
- /package/dist/{announce-72R3LRNT.js.map → announce-HJCGEVJA.js.map} +0 -0
- /package/dist/{chunk-XWPZ46IN.js.map → chunk-BJCA7O4A.js.map} +0 -0
- /package/dist/{chunk-YQMYQAJX.js.map → chunk-GI4M2AMO.js.map} +0 -0
- /package/dist/{chunk-RINXPU3H.js.map → chunk-KLVMJYZZ.js.map} +0 -0
- /package/dist/{chunk-AESJBEM7.js.map → chunk-KRHPS3R4.js.map} +0 -0
- /package/dist/{chunk-A5KYRGQA.js.map → chunk-SQJ53Z7R.js.map} +0 -0
- /package/dist/{digest-Q2TAQHXF.js.map → digest-VX7Q4MNF.js.map} +0 -0
- /package/dist/{ensure-site-2PF522VL.js.map → ensure-site-O7G5ZJS7.js.map} +0 -0
- /package/dist/{github-signals-CLQC2IPY.js.map → github-signals-QVW2LB7N.js.map} +0 -0
- /package/dist/{launch-AENAS2O2.js.map → launch-JWXCTJRG.js.map} +0 -0
- /package/dist/{lighthouse-airtable-UBSXKHAQ.js.map → lighthouse-airtable-J5TLASJC.js.map} +0 -0
- /package/dist/{onboard-X6KJ5Z2V.js.map → onboard-6UQE5QIO.js.map} +0 -0
- /package/dist/{orchestrate-GADNFGDH.js.map → orchestrate-ZDH24Z6Y.js.map} +0 -0
- /package/dist/{preflight-D5RQGX4V.js.map → preflight-BNTMWTPG.js.map} +0 -0
- /package/dist/{renovate-dispatch-LG4RJGDY.js.map → renovate-dispatch-C3ALLACX.js.map} +0 -0
- /package/dist/{report-3FJ224H5.js.map → report-YLFSGNWR.js.map} +0 -0
- /package/dist/{self-updating-JTTFOJ7Q.js.map → self-updating-64FNRQB5.js.map} +0 -0
- /package/dist/{websites-6YTT5ZTO.js.map → websites-EH2ULELZ.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-IWOO4FFH.js.map → write-audits-to-airtable-LZDYTNX5.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
isPendingApproval,
|
|
3
3
|
listReportsForSite,
|
|
4
4
|
setDraftReady
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JCITWZQR.js";
|
|
6
6
|
|
|
7
7
|
// src/reports/queue.ts
|
|
8
8
|
var REPORT_TIER = {
|
|
@@ -35,4 +35,4 @@ export {
|
|
|
35
35
|
reportTier,
|
|
36
36
|
queueDraft
|
|
37
37
|
};
|
|
38
|
-
//# sourceMappingURL=chunk-
|
|
38
|
+
//# sourceMappingURL=chunk-KLVMJYZZ.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/recipes/_prettier.ts
|
|
2
|
+
var PRETTIER_FLAG_NOTE = "could not prettier-format written files (prettier unavailable?) \u2014 verify CI formatting";
|
|
3
|
+
async function formatWithPrettier(spawn, cwd, relPaths) {
|
|
4
|
+
if (relPaths.length === 0) return true;
|
|
5
|
+
try {
|
|
6
|
+
const res = await spawn("pnpm", ["exec", "prettier", "--write", ...relPaths], { cwd });
|
|
7
|
+
return res.code === 0;
|
|
8
|
+
} catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
PRETTIER_FLAG_NOTE,
|
|
15
|
+
formatWithPrettier
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=chunk-KRDLHAKK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/recipes/_prettier.ts"],"sourcesContent":["import type { SpawnFn } from \"../audits/util/spawn.js\";\n\n/** Flag note recipes surface when best-effort formatting couldn't run, so the\n * operator knows to eyeball CI's format check for that site. */\nexport const PRETTIER_FLAG_NOTE =\n \"could not prettier-format written files (prettier unavailable?) — verify CI formatting\";\n\n/**\n * Format recipe-written files with the SITE's own prettier\n * (`pnpm exec prettier --write`), so they match that site's config — quote\n * style, tabs vs spaces, and printWidth all vary across the fleet, and a single\n * hardcoded template style reds the CI format check on the sites that differ.\n *\n * Best-effort by contract: returns `false` (never throws) when prettier isn't\n * installed or exits non-zero, so a recipe can commit the file unformatted and\n * flag it rather than fail the whole rollout. Files in the site's\n * `.prettierignore` are skipped by prettier itself. Returns `true` immediately\n * (no spawn) when `relPaths` is empty, so a recipe that wrote nothing this run\n * doesn't shell out.\n *\n * Only pass paths the recipe actually wrote/changed — never operator files it\n * left untouched, which must not be reformatted.\n */\nexport async function formatWithPrettier(\n spawn: SpawnFn,\n cwd: string,\n relPaths: readonly string[],\n): Promise<boolean> {\n if (relPaths.length === 0) return true;\n try {\n const res = await spawn(\"pnpm\", [\"exec\", \"prettier\", \"--write\", ...relPaths], { cwd });\n return res.code === 0;\n } catch {\n return false;\n }\n}\n"],"mappings":";AAIO,IAAM,qBACX;AAkBF,eAAsB,mBACpB,OACA,KACA,UACkB;AAClB,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,QAAQ,CAAC,QAAQ,YAAY,WAAW,GAAG,QAAQ,GAAG,EAAE,IAAI,CAAC;AACrF,WAAO,IAAI,SAAS;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
approveBlockers
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KLB2OLPW.js";
|
|
4
4
|
import {
|
|
5
5
|
siteSlug
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BWKK2ZXS.js";
|
|
7
7
|
|
|
8
8
|
// src/alerts/digest-collectors.ts
|
|
9
9
|
function dashboardUrl(baseUrl, siteName) {
|
|
@@ -248,4 +248,4 @@ export {
|
|
|
248
248
|
readDigestState,
|
|
249
249
|
writeDigestState
|
|
250
250
|
};
|
|
251
|
-
//# sourceMappingURL=chunk-
|
|
251
|
+
//# sourceMappingURL=chunk-KRHPS3R4.js.map
|
|
@@ -5,6 +5,8 @@ var a11yRoutes = [
|
|
|
5
5
|
{ path: "/dev/animate-in", name: "animate-in demo" }
|
|
6
6
|
];
|
|
7
7
|
var smokeRoutes = [{ path: "/", name: "home" }];
|
|
8
|
+
var smokePort = process.env.REDDOOR_SMOKE_PORT;
|
|
9
|
+
var port = smokePort || "5173";
|
|
8
10
|
var playwrightA11yConfig = defineConfig({
|
|
9
11
|
testDir: "tests",
|
|
10
12
|
testMatch: /.*\.spec\.ts$/,
|
|
@@ -13,7 +15,7 @@ var playwrightA11yConfig = defineConfig({
|
|
|
13
15
|
retries: process.env.CI ? 2 : 0,
|
|
14
16
|
reporter: process.env.CI ? "github" : "list",
|
|
15
17
|
use: {
|
|
16
|
-
baseURL:
|
|
18
|
+
baseURL: `http://localhost:${port}`,
|
|
17
19
|
trace: "on-first-retry"
|
|
18
20
|
},
|
|
19
21
|
projects: [
|
|
@@ -24,8 +26,10 @@ var playwrightA11yConfig = defineConfig({
|
|
|
24
26
|
],
|
|
25
27
|
webServer: {
|
|
26
28
|
// Portable across pnpm and npm sites — pnpm respects `npm run` too.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
// `--strictPort` only when a port was explicitly allocated: fail loudly
|
|
30
|
+
// rather than let vite drift to a free port the baseURL doesn't point at.
|
|
31
|
+
command: smokePort ? `npm run vite:dev -- --port ${smokePort} --strictPort` : "npm run vite:dev",
|
|
32
|
+
url: `http://localhost:${port}/dev/a11y-fixtures`,
|
|
29
33
|
reuseExistingServer: !process.env.CI,
|
|
30
34
|
timeout: 12e4
|
|
31
35
|
}
|
|
@@ -35,7 +39,6 @@ var playwright_a11y_default = playwrightA11yConfig;
|
|
|
35
39
|
export {
|
|
36
40
|
a11yRoutes,
|
|
37
41
|
smokeRoutes,
|
|
38
|
-
playwrightA11yConfig,
|
|
39
42
|
playwright_a11y_default
|
|
40
43
|
};
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
44
|
+
//# sourceMappingURL=chunk-LJPCMXR7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/configs/playwright-a11y.ts"],"sourcesContent":["import { defineConfig, devices, type PlaywrightTestConfig } from \"@playwright/test\";\n\nexport type A11yRoute = { path: string; name: string };\n\nexport const a11yRoutes: A11yRoute[] = [\n { path: \"/dev/a11y-fixtures\", name: \"a11y fixtures\" },\n { path: \"/dev/animate-in\", name: \"animate-in demo\" },\n];\n\n// Routes smoke-loaded for client-side (hydration) errors only — NOT axe-scanned.\n// Catches the class of bug where build + SSR succeed but client hydration throws\n// and blanks the page (data-dynamiq 2026-06-09: a Svelte 4->5 `run()` referenced\n// a `$state` declared after it → TDZ ReferenceError on hydrate). `/` is the one\n// route every site has; real routes carry a11y debt we don't gate on here, so we\n// assert only that they don't crash on hydrate.\nexport const smokeRoutes: A11yRoute[] = [{ path: \"/\", name: \"home\" }];\n\n// R1.1 (health-gate): the central `smoke` audit (src/audits/smoke.ts) allocates\n// a free port and passes it as REDDOOR_SMOKE_PORT so a zombie vite already\n// squatting the default 5173 can't silently hijack the run and green a stale\n// build. The per-site R1.1 config template honors it, but sites whose\n// playwright.config.ts merely re-exports this shared base (pre-R1.1 adopters\n// the smoke-suite recipe flags-but-never-rewrites) would otherwise ignore it —\n// so honor it here too and every re-exporter inherits the port binding on its\n// next package bump. Unset (local `pnpm test:smoke`) → the fixed 5173.\nconst smokePort = process.env.REDDOOR_SMOKE_PORT;\nconst port = smokePort || \"5173\";\n\n// NOTE: default export only — sites consume this as `import base from\n// \"@reddoorla/maintenance/configs/playwright-a11y\"` (or re-export the default).\n// The old `playwrightA11yConfig` named alias had zero importers and was removed.\nconst playwrightA11yConfig: PlaywrightTestConfig = defineConfig({\n testDir: \"tests\",\n testMatch: /.*\\.spec\\.ts$/,\n fullyParallel: true,\n forbidOnly: !!process.env.CI,\n retries: process.env.CI ? 2 : 0,\n reporter: process.env.CI ? \"github\" : \"list\",\n use: {\n baseURL: `http://localhost:${port}`,\n trace: \"on-first-retry\",\n },\n projects: [\n {\n name: \"chromium\",\n use: { ...devices[\"Desktop Chrome\"] },\n },\n ],\n webServer: {\n // Portable across pnpm and npm sites — pnpm respects `npm run` too.\n // `--strictPort` only when a port was explicitly allocated: fail loudly\n // rather than let vite drift to a free port the baseURL doesn't point at.\n command: smokePort\n ? `npm run vite:dev -- --port ${smokePort} --strictPort`\n : \"npm run vite:dev\",\n url: `http://localhost:${port}/dev/a11y-fixtures`,\n reuseExistingServer: !process.env.CI,\n timeout: 120_000,\n },\n});\n\nexport default playwrightA11yConfig;\n"],"mappings":";AAAA,SAAS,cAAc,eAA0C;AAI1D,IAAM,aAA0B;AAAA,EACrC,EAAE,MAAM,sBAAsB,MAAM,gBAAgB;AAAA,EACpD,EAAE,MAAM,mBAAmB,MAAM,kBAAkB;AACrD;AAQO,IAAM,cAA2B,CAAC,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC;AAUpE,IAAM,YAAY,QAAQ,IAAI;AAC9B,IAAM,OAAO,aAAa;AAK1B,IAAM,uBAA6C,aAAa;AAAA,EAC9D,SAAS;AAAA,EACT,WAAW;AAAA,EACX,eAAe;AAAA,EACf,YAAY,CAAC,CAAC,QAAQ,IAAI;AAAA,EAC1B,SAAS,QAAQ,IAAI,KAAK,IAAI;AAAA,EAC9B,UAAU,QAAQ,IAAI,KAAK,WAAW;AAAA,EACtC,KAAK;AAAA,IACH,SAAS,oBAAoB,IAAI;AAAA,IACjC,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA,IACR;AAAA,MACE,MAAM;AAAA,MACN,KAAK,EAAE,GAAG,QAAQ,gBAAgB,EAAE;AAAA,IACtC;AAAA,EACF;AAAA,EACA,WAAW;AAAA;AAAA;AAAA;AAAA,IAIT,SAAS,YACL,8BAA8B,SAAS,kBACvC;AAAA,IACJ,KAAK,oBAAoB,IAAI;AAAA,IAC7B,qBAAqB,CAAC,QAAQ,IAAI;AAAA,IAClC,SAAS;AAAA,EACX;AACF,CAAC;AAED,IAAO,0BAAQ;","names":[]}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
queueDraft
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KLVMJYZZ.js";
|
|
4
4
|
import {
|
|
5
5
|
checklistFor,
|
|
6
6
|
createDraft,
|
|
7
|
+
gatingFields,
|
|
7
8
|
listReportsForSite,
|
|
8
9
|
renderReportHtml,
|
|
9
10
|
resolveCopy,
|
|
10
11
|
uploadAttachment
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JCITWZQR.js";
|
|
12
13
|
import {
|
|
13
14
|
isNetlifyAppUrl
|
|
14
15
|
} from "./chunk-U5SZ4FOP.js";
|
|
15
16
|
import {
|
|
16
17
|
siteSlug,
|
|
17
18
|
updateAnalyticsHealth
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-BWKK2ZXS.js";
|
|
19
20
|
import {
|
|
20
21
|
defaultCredentialsPath
|
|
21
22
|
} from "./chunk-6VAL7XJT.js";
|
|
@@ -23,10 +24,10 @@ import {
|
|
|
23
24
|
// src/reports/ga/config.ts
|
|
24
25
|
import { dirname, join } from "path";
|
|
25
26
|
function readGaConfig() {
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
27
|
+
const subjects = (process.env.GA_SUBJECT ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
28
|
+
if (subjects.length === 0) return null;
|
|
28
29
|
const keyPath = process.env.GA_SA_KEY_PATH?.trim() || join(dirname(defaultCredentialsPath()), "ga-service-account.json");
|
|
29
|
-
return {
|
|
30
|
+
return { subjects, keyPath };
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
// src/reports/draft.ts
|
|
@@ -45,44 +46,65 @@ function isFresh(checkedAt, now) {
|
|
|
45
46
|
var CERT_MIN_DAYS = 14;
|
|
46
47
|
function autoTickChecklist(site, reportType, now, signals) {
|
|
47
48
|
const out = /* @__PURE__ */ new Map();
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
49
|
+
const gating = new Set(gatingFields(reportType));
|
|
50
|
+
for (const item of checklistFor(reportType)) {
|
|
51
|
+
let ev;
|
|
52
|
+
switch (item.field) {
|
|
53
|
+
case "Maint: Google Indexed":
|
|
54
|
+
ev = googleEvidence(now, signals.search);
|
|
55
|
+
break;
|
|
56
|
+
case "Maint: Deploy & Function Health":
|
|
57
|
+
ev = deployEvidence(site, now);
|
|
58
|
+
break;
|
|
59
|
+
case "Maint: CMS Checked":
|
|
60
|
+
ev = cmsEvidence(site, now);
|
|
61
|
+
break;
|
|
62
|
+
case "Maint: Domain, DNS & SSL":
|
|
63
|
+
ev = domainEvidence(site, now);
|
|
64
|
+
break;
|
|
65
|
+
case "Maint: Security Updates":
|
|
66
|
+
ev = securityEvidence(site, now);
|
|
67
|
+
break;
|
|
68
|
+
case "Maint: Uptime Checked":
|
|
69
|
+
ev = uptimeEvidence(site, now);
|
|
70
|
+
break;
|
|
71
|
+
case "Test: Desktop Browsers":
|
|
72
|
+
ev = browserEvidence(
|
|
73
|
+
site.crossbrowserOk,
|
|
74
|
+
site,
|
|
75
|
+
now,
|
|
76
|
+
"Desktop renders cleanly",
|
|
77
|
+
"render errors"
|
|
78
|
+
);
|
|
79
|
+
break;
|
|
80
|
+
case "Test: Mobile Browsers":
|
|
81
|
+
ev = browserEvidence(site.mobileOk, site, now, "Mobile renders cleanly", "overflow/errors");
|
|
82
|
+
break;
|
|
83
|
+
case "Test: Page Titles & Meta":
|
|
84
|
+
ev = titlesEvidence(site, now);
|
|
85
|
+
break;
|
|
86
|
+
case "Test: Links & Navigation": {
|
|
87
|
+
const broken = site.brokenLinks;
|
|
88
|
+
const failNote = broken && broken > 0 ? `${broken} broken link(s)` : "broken links / nav";
|
|
89
|
+
ev = browserEvidence(site.linksOk, site, now, "All internal links resolve", failNote);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
case "Test: Form Functionality":
|
|
93
|
+
ev = formsEvidence(site, now);
|
|
94
|
+
break;
|
|
95
|
+
case "Test: Interactions & Animations":
|
|
96
|
+
ev = interactionsEvidence(site, now);
|
|
97
|
+
break;
|
|
98
|
+
case "Test: Verified After Updates":
|
|
99
|
+
ev = updatesEvidence(site, now);
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
ev = null;
|
|
103
|
+
}
|
|
104
|
+
if (ev === null && gating.has(item.field)) {
|
|
105
|
+
ev = { result: "unknown", checkedAt: null, note: "Not yet measured" };
|
|
106
|
+
}
|
|
107
|
+
if (ev !== null) out.set(item.field, ev);
|
|
86
108
|
}
|
|
87
109
|
return out;
|
|
88
110
|
}
|
|
@@ -144,11 +166,175 @@ function domainEvidence(site, now) {
|
|
|
144
166
|
}
|
|
145
167
|
return { result: "pass", checkedAt: at, note: `Custom domain, valid cert (${days}d left)` };
|
|
146
168
|
}
|
|
169
|
+
function deployEvidence(site, now) {
|
|
170
|
+
if (!site.deployCheckedAt && !site.functionHealthCheckedAt) return null;
|
|
171
|
+
if (!isFresh(site.deployCheckedAt, now) || !isFresh(site.functionHealthCheckedAt, now)) {
|
|
172
|
+
return {
|
|
173
|
+
result: "unknown",
|
|
174
|
+
checkedAt: site.functionHealthCheckedAt ?? site.deployCheckedAt,
|
|
175
|
+
note: "Deploy/function-health check is stale (>3d)"
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const ready = site.deployStatus === "ready";
|
|
179
|
+
const fnOk = site.functionHealth === "pass";
|
|
180
|
+
if (ready && fnOk) {
|
|
181
|
+
return {
|
|
182
|
+
result: "pass",
|
|
183
|
+
checkedAt: site.functionHealthCheckedAt,
|
|
184
|
+
note: "Netlify build ready + functions respond"
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const why = !ready && !fnOk ? "build not ready + functions unhealthy" : !ready ? "build not ready" : "functions unhealthy";
|
|
188
|
+
return {
|
|
189
|
+
result: "fail",
|
|
190
|
+
checkedAt: site.functionHealthCheckedAt,
|
|
191
|
+
note: `Deploy/function-health failing \u2014 ${why}`
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function cmsEvidence(site, now) {
|
|
195
|
+
if (!site.functionHealthCheckedAt) return null;
|
|
196
|
+
const at = site.functionHealthCheckedAt;
|
|
197
|
+
if (!isFresh(at, now)) {
|
|
198
|
+
return { result: "unknown", checkedAt: at, note: "CMS check is stale (>3d)" };
|
|
199
|
+
}
|
|
200
|
+
if (site.cmsReachable === "pass") {
|
|
201
|
+
return { result: "pass", checkedAt: at, note: "Prismic reachable (server-side)" };
|
|
202
|
+
}
|
|
203
|
+
if (site.cmsReachable === "fail") {
|
|
204
|
+
return { result: "fail", checkedAt: at, note: "Prismic unreachable (server-side)" };
|
|
205
|
+
}
|
|
206
|
+
return { result: "unknown", checkedAt: at, note: "CMS reachability not reported" };
|
|
207
|
+
}
|
|
208
|
+
function uptimeEvidence(site, now) {
|
|
209
|
+
if (site.reachableOk === null || !site.browserCheckedAt) return null;
|
|
210
|
+
const at = site.browserCheckedAt;
|
|
211
|
+
if (!isFresh(at, now)) {
|
|
212
|
+
return { result: "unknown", checkedAt: at, note: "Uptime check is stale (>3d)" };
|
|
213
|
+
}
|
|
214
|
+
return site.reachableOk === "pass" ? { result: "pass", checkedAt: at, note: "All sampled routes reachable (point-in-time)" } : { result: "fail", checkedAt: at, note: "One or more sampled routes did not respond 2xx/3xx" };
|
|
215
|
+
}
|
|
216
|
+
function titlesEvidence(site, now) {
|
|
217
|
+
if (site.titleMetaOk === null || !site.browserCheckedAt) return null;
|
|
218
|
+
const at = site.browserCheckedAt;
|
|
219
|
+
if (!isFresh(at, now)) {
|
|
220
|
+
return { result: "unknown", checkedAt: at, note: "Titles/meta check is stale (>3d)" };
|
|
221
|
+
}
|
|
222
|
+
return site.titleMetaOk === "pass" ? { result: "pass", checkedAt: at, note: "Titles + meta present" } : {
|
|
223
|
+
result: "fail",
|
|
224
|
+
checkedAt: at,
|
|
225
|
+
note: "Missing/duplicate title or missing meta description"
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function formsEvidence(site, now) {
|
|
229
|
+
if (!site.formE2eCheckedAt) return null;
|
|
230
|
+
const at = site.formE2eCheckedAt;
|
|
231
|
+
if (!isFresh(at, now)) {
|
|
232
|
+
return { result: "unknown", checkedAt: at, note: "Form E2E check is stale (>3d)" };
|
|
233
|
+
}
|
|
234
|
+
if (site.formE2eOk === "pass") {
|
|
235
|
+
return { result: "pass", checkedAt: at, note: "Synthetic submission succeeded" };
|
|
236
|
+
}
|
|
237
|
+
if (site.formE2eOk === "fail") {
|
|
238
|
+
return { result: "fail", checkedAt: at, note: "Synthetic submission failed" };
|
|
239
|
+
}
|
|
240
|
+
return { result: "n/a", checkedAt: at, note: "No contact form on this site" };
|
|
241
|
+
}
|
|
242
|
+
function interactionsEvidence(site, now) {
|
|
243
|
+
if (site.smokeOk === null || !site.lastSmokeAt) return null;
|
|
244
|
+
const at = site.lastSmokeAt;
|
|
245
|
+
if (!isFresh(at, now)) {
|
|
246
|
+
return { result: "unknown", checkedAt: at, note: "Smoke suite is stale (>3d)" };
|
|
247
|
+
}
|
|
248
|
+
return site.smokeOk === "pass" ? { result: "pass", checkedAt: at, note: "Smoke suite green" } : { result: "fail", checkedAt: at, note: "Smoke suite red" };
|
|
249
|
+
}
|
|
250
|
+
function updatesEvidence(site, now) {
|
|
251
|
+
if (site.defaultBranchCi === null || !site.githubSignalsAt) return null;
|
|
252
|
+
const at = site.githubSignalsAt;
|
|
253
|
+
if (site.defaultBranchCi === "none") {
|
|
254
|
+
return { result: "n/a", checkedAt: at, note: "Repository has no CI" };
|
|
255
|
+
}
|
|
256
|
+
if (!isFresh(at, now)) {
|
|
257
|
+
return { result: "unknown", checkedAt: at, note: "CI signal is stale (>3d)" };
|
|
258
|
+
}
|
|
259
|
+
if (site.defaultBranchCi === "passing") {
|
|
260
|
+
return { result: "pass", checkedAt: at, note: "Default-branch CI green on latest commit" };
|
|
261
|
+
}
|
|
262
|
+
if (site.defaultBranchCi === "failing") {
|
|
263
|
+
return { result: "fail", checkedAt: at, note: "Default-branch CI is failing" };
|
|
264
|
+
}
|
|
265
|
+
return { result: "unknown", checkedAt: at, note: "Default-branch CI is pending" };
|
|
266
|
+
}
|
|
147
267
|
|
|
148
268
|
// src/reports/ga/client.ts
|
|
149
269
|
import { readFileSync } from "fs";
|
|
150
270
|
import { JWT } from "google-auth-library";
|
|
151
271
|
import { BetaAnalyticsDataClient } from "@google-analytics/data";
|
|
272
|
+
|
|
273
|
+
// src/reports/ga/failover.ts
|
|
274
|
+
var AUTH_HTTP_STATUS = /* @__PURE__ */ new Set([401, 403]);
|
|
275
|
+
var AUTH_GRPC_CODES = /* @__PURE__ */ new Set([7, 16]);
|
|
276
|
+
var AUTH_MESSAGE = /permission[_ ]denied|unauthenticated|unauthorized|invalid_grant|access[_ ]denied|forbidden|insufficient permission|status code 40[13]/i;
|
|
277
|
+
var QUOTA_REASONS = /* @__PURE__ */ new Set([
|
|
278
|
+
"userratelimitexceeded",
|
|
279
|
+
"ratelimitexceeded",
|
|
280
|
+
"quotaexceeded",
|
|
281
|
+
"dailylimitexceeded"
|
|
282
|
+
]);
|
|
283
|
+
var QUOTA_MESSAGE = /quota exceeded|rate limit exceeded|user rate limit/i;
|
|
284
|
+
function isAuthShapedError(e) {
|
|
285
|
+
const err = e;
|
|
286
|
+
if (err?.failoverToNextSubject === true) return true;
|
|
287
|
+
if ([err?.status, err?.response?.status].some((s) => AUTH_HTTP_STATUS.has(Number(s))))
|
|
288
|
+
return true;
|
|
289
|
+
if (AUTH_HTTP_STATUS.has(Number(err?.code)) || AUTH_GRPC_CODES.has(Number(err?.code)))
|
|
290
|
+
return true;
|
|
291
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
292
|
+
return AUTH_MESSAGE.test(msg);
|
|
293
|
+
}
|
|
294
|
+
function isFailoverSentinel(e) {
|
|
295
|
+
return e?.failoverToNextSubject === true;
|
|
296
|
+
}
|
|
297
|
+
function isQuotaShapedError(e) {
|
|
298
|
+
const err = e;
|
|
299
|
+
if (err?.failoverToNextSubject === true) return false;
|
|
300
|
+
const reasons = err?.response?.data?.error?.errors;
|
|
301
|
+
if (Array.isArray(reasons) && reasons.length > 0) {
|
|
302
|
+
return reasons.some((r) => r?.reason != null && QUOTA_REASONS.has(r.reason.toLowerCase()));
|
|
303
|
+
}
|
|
304
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
305
|
+
return QUOTA_MESSAGE.test(msg);
|
|
306
|
+
}
|
|
307
|
+
async function withSubjectFailover(subjects, label, attempt) {
|
|
308
|
+
if (subjects.length === 0) throw new Error(`${label}: no impersonation subjects configured`);
|
|
309
|
+
const failed = [];
|
|
310
|
+
let lastRealError;
|
|
311
|
+
let lastSentinel;
|
|
312
|
+
let allQuota = true;
|
|
313
|
+
for (const subject of subjects) {
|
|
314
|
+
try {
|
|
315
|
+
const result = await attempt(subject);
|
|
316
|
+
if (failed.length > 0) {
|
|
317
|
+
console.warn(
|
|
318
|
+
allQuota ? `\u26A0 ${label} subject failover: ${failed.join("; ")} \u2014 succeeded via ${subject} (transient quota/rate-limit, not an access loss).` : `\u26A0 ${label} subject failover: ${failed.join("; ")} \u2014 succeeded via ${subject}. Restore the failing subject's access or drop it from GA_SUBJECT (docs/runbooks/ga-search-role-account-cutover.md).`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
return result;
|
|
322
|
+
} catch (e) {
|
|
323
|
+
if (!isAuthShapedError(e)) throw e;
|
|
324
|
+
failed.push(`${subject} (${e instanceof Error ? e.message : String(e)})`);
|
|
325
|
+
if (isFailoverSentinel(e)) {
|
|
326
|
+
lastSentinel = e;
|
|
327
|
+
allQuota = false;
|
|
328
|
+
} else {
|
|
329
|
+
lastRealError = e;
|
|
330
|
+
if (!isQuotaShapedError(e)) allQuota = false;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
throw lastRealError ?? lastSentinel;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// src/reports/ga/client.ts
|
|
152
338
|
var ANALYTICS_READONLY = "https://www.googleapis.com/auth/analytics.readonly";
|
|
153
339
|
var MS_PER_DAY2 = 864e5;
|
|
154
340
|
function ymd(d) {
|
|
@@ -156,30 +342,32 @@ function ymd(d) {
|
|
|
156
342
|
}
|
|
157
343
|
async function fetchPeriodUsers(query, periodStart, periodEnd) {
|
|
158
344
|
const key = JSON.parse(readFileSync(query.keyPath, "utf8"));
|
|
159
|
-
const authClient = new JWT({
|
|
160
|
-
email: key.client_email,
|
|
161
|
-
key: key.private_key,
|
|
162
|
-
scopes: [ANALYTICS_READONLY],
|
|
163
|
-
subject: query.subject
|
|
164
|
-
});
|
|
165
|
-
const client = new BetaAnalyticsDataClient({ authClient });
|
|
166
345
|
const lengthDays = Math.round((periodEnd.getTime() - periodStart.getTime()) / MS_PER_DAY2);
|
|
167
346
|
const prevEnd = new Date(periodStart.getTime() - MS_PER_DAY2);
|
|
168
347
|
const prevStart = new Date(prevEnd.getTime() - lengthDays * MS_PER_DAY2);
|
|
169
348
|
const property = `properties/${query.propertyId}`;
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
349
|
+
return withSubjectFailover(query.subjects, "GA", async (subject) => {
|
|
350
|
+
const authClient = new JWT({
|
|
351
|
+
email: key.client_email,
|
|
352
|
+
key: key.private_key,
|
|
353
|
+
scopes: [ANALYTICS_READONLY],
|
|
354
|
+
subject
|
|
175
355
|
});
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
356
|
+
const client = new BetaAnalyticsDataClient({ authClient });
|
|
357
|
+
const run = async (start, end) => {
|
|
358
|
+
const [resp] = await client.runReport({
|
|
359
|
+
property,
|
|
360
|
+
dateRanges: [{ startDate: ymd(start), endDate: ymd(end) }],
|
|
361
|
+
metrics: [{ name: "activeUsers" }]
|
|
362
|
+
});
|
|
363
|
+
const raw = resp.rows?.[0]?.metricValues?.[0]?.value ?? "0";
|
|
364
|
+
const n = Number.parseInt(raw, 10);
|
|
365
|
+
return Number.isFinite(n) ? n : 0;
|
|
366
|
+
};
|
|
367
|
+
const current = await run(periodStart, periodEnd);
|
|
368
|
+
const previous = await run(prevStart, prevEnd);
|
|
369
|
+
return { current, previous };
|
|
370
|
+
});
|
|
183
371
|
}
|
|
184
372
|
|
|
185
373
|
// src/reports/search/client.ts
|
|
@@ -221,50 +409,66 @@ function selectBrandPosition(rows, exactQuery) {
|
|
|
221
409
|
if (exact) return exact.position;
|
|
222
410
|
return pickBrandQuery(rows);
|
|
223
411
|
}
|
|
412
|
+
var NoPropertyForSubjectError = class extends Error {
|
|
413
|
+
failoverToNextSubject = true;
|
|
414
|
+
constructor(subject, host) {
|
|
415
|
+
super(`no Search Console property matching ${host} is visible to ${subject}`);
|
|
416
|
+
}
|
|
417
|
+
};
|
|
224
418
|
async function fetchSearchPresence(q, periodStart, periodEnd) {
|
|
225
419
|
const key = JSON.parse(readFileSync2(q.keyPath, "utf8"));
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
{
|
|
256
|
-
|
|
420
|
+
try {
|
|
421
|
+
return await withSubjectFailover(q.subjects, "Search Console", async (subject) => {
|
|
422
|
+
const jwt = new JWT2({
|
|
423
|
+
email: key.client_email,
|
|
424
|
+
key: key.private_key,
|
|
425
|
+
scopes: [WEBMASTERS_READONLY],
|
|
426
|
+
subject
|
|
427
|
+
});
|
|
428
|
+
const explicit = q.property?.trim();
|
|
429
|
+
let candidates;
|
|
430
|
+
if (explicit) {
|
|
431
|
+
candidates = [explicit];
|
|
432
|
+
} else {
|
|
433
|
+
const list = await jwt.request({
|
|
434
|
+
url: `${SC_BASE}/sites`,
|
|
435
|
+
method: "GET"
|
|
436
|
+
});
|
|
437
|
+
candidates = resolvePropertyCandidates(list.data.siteEntry ?? [], q.host);
|
|
438
|
+
if (candidates.length === 0) throw new NoPropertyForSubjectError(subject, q.host);
|
|
439
|
+
}
|
|
440
|
+
for (const property of candidates) {
|
|
441
|
+
const res = await jwt.request({
|
|
442
|
+
url: `${SC_BASE}/sites/${encodeURIComponent(property)}/searchAnalytics/query`,
|
|
443
|
+
method: "POST",
|
|
444
|
+
data: {
|
|
445
|
+
startDate: ymd2(periodStart),
|
|
446
|
+
endDate: ymd2(periodEnd),
|
|
447
|
+
dimensions: ["query"],
|
|
448
|
+
dimensionFilterGroups: [
|
|
449
|
+
{
|
|
450
|
+
filters: [
|
|
451
|
+
{ dimension: "query", operator: "contains", expression: q.query.toLowerCase() }
|
|
452
|
+
]
|
|
453
|
+
}
|
|
454
|
+
],
|
|
455
|
+
rowLimit: BRAND_QUERY_ROW_LIMIT
|
|
257
456
|
}
|
|
258
|
-
|
|
259
|
-
|
|
457
|
+
});
|
|
458
|
+
const pos = selectBrandPosition(res.data.rows ?? [], q.query.toLowerCase());
|
|
459
|
+
if (typeof pos === "number") {
|
|
460
|
+
return {
|
|
461
|
+
foundOnPage1: pos <= PAGE_1_MAX_POSITION,
|
|
462
|
+
position: Math.max(1, Math.round(pos))
|
|
463
|
+
};
|
|
464
|
+
}
|
|
260
465
|
}
|
|
466
|
+
return { foundOnPage1: false, position: null };
|
|
261
467
|
});
|
|
262
|
-
|
|
263
|
-
if (
|
|
264
|
-
|
|
265
|
-
}
|
|
468
|
+
} catch (e) {
|
|
469
|
+
if (e instanceof NoPropertyForSubjectError) return { foundOnPage1: false, position: null };
|
|
470
|
+
throw e;
|
|
266
471
|
}
|
|
267
|
-
return { foundOnPage1: false, position: null };
|
|
268
472
|
}
|
|
269
473
|
|
|
270
474
|
// src/reports/draft.ts
|
|
@@ -392,7 +596,7 @@ async function fetchGaUsers(siteRow, periodStart, periodEnd) {
|
|
|
392
596
|
if (!cfg || !siteRow.ga4PropertyId) return NO_ENRICHMENT;
|
|
393
597
|
try {
|
|
394
598
|
const value = await fetchPeriodUsers(
|
|
395
|
-
{ propertyId: siteRow.ga4PropertyId,
|
|
599
|
+
{ propertyId: siteRow.ga4PropertyId, subjects: cfg.subjects, keyPath: cfg.keyPath },
|
|
396
600
|
periodStart,
|
|
397
601
|
periodEnd
|
|
398
602
|
);
|
|
@@ -409,7 +613,7 @@ async function fetchSearch(siteRow, periodStart, periodEnd) {
|
|
|
409
613
|
const value = await fetchSearchPresence(
|
|
410
614
|
{
|
|
411
615
|
keyPath: cfg.keyPath,
|
|
412
|
-
|
|
616
|
+
subjects: cfg.subjects,
|
|
413
617
|
property: siteRow.searchConsoleProperty ?? void 0,
|
|
414
618
|
host: siteRow.url,
|
|
415
619
|
query: siteRow.searchQuery
|
|
@@ -439,4 +643,4 @@ export {
|
|
|
439
643
|
fetchGaUsers,
|
|
440
644
|
fetchSearch
|
|
441
645
|
};
|
|
442
|
-
//# sourceMappingURL=chunk-
|
|
646
|
+
//# sourceMappingURL=chunk-NRISG4XD.js.map
|