🌳
pt0/nextF/deployF/doesMakeReqToGqlF.mts
1import { chromium } from 'playwright'
6const healthgqlMemoH = new Map<string, {result: boolean | string, atMs: number}>()
8declare global {
9 var __healthallBatchCtx: {getStore: () => unknown} | undefined
12const isInBatchMode = () => {
13 try {
14 const healthallMod = globalThis.__healthallBatchCtx
15 return healthallMod?.getStore() !== undefined
16 } catch {
17 return false
18 }
21const getMemoizedResult = (cacheKey: string): boolean | string | undefined => {
22 if (!isInBatchMode()) return undefined
23 const cached = healthgqlMemoH.get(cacheKey)
24 if (!cached) return undefined
25 if (Date.now() - cached.atMs > 60 * 1000) {
26 healthgqlMemoH.delete(cacheKey)
27 return undefined
28 }
29 return cached.result
32const setMemoizedResult = (cacheKey: string, result: boolean | string) => {
33 if (!isInBatchMode()) return
34 healthgqlMemoH.set(cacheKey, { result, atMs: Date.now() })
37const playwrightTimeoutMs = 30000
39export const doesMakeReqToGql = async (url: string, opts: {needleString?: string, expectNoErrors?: boolean, diagnostics?: Record<string, unknown>} = {}) => {
40 const { needleString, expectNoErrors = true, diagnostics } = opts
41 const cacheKey = `${url}|${needleString}|${expectNoErrors}`
42 const memoized = getMemoizedResult(cacheKey)
43 if (memoized !== undefined) {
44 betLog({ memoizedHealthgql: url })
45 return memoized
46 }
48 let didMakeGqlRequest: boolean | string = false
49 let gqlRespHadError = false
50 let gqlRespErrSnip = ''
51 let gqlRequestSent = false
52 let timedOut = false
54 const browser = await chromium.launch()
56 try {
57 const context = await browser.newContext()
58 const page = await context.newPage()
60 const pendingResponses: Promise<void>[] = []
61 page.on('response', (response) => {
62 const responseUrl = response.url()
63 if (responseUrl.includes(apiGqlPath)) {
64 gqlRequestSent = true
65 const handleResponse = async () => {
66 try {
67 const gqlResponseBody = await response.text()
68 if (gqlResponseBody.includes('"errors"')) {
69 const isApqProtocol = gqlResponseBody.includes('PERSISTED_QUERY_NOT_FOUND')
70 || gqlResponseBody.includes('PERSISTED_QUERY_NOT_SUPPORTED')
71 if (!isApqProtocol) {
72 gqlRespHadError = true
73 gqlRespErrSnip = gqlResponseBody.slice(0, 300)
74 }
75 }
76 if (needleString) {
77 if (gqlResponseBody.includes(needleString)) {
78 didMakeGqlRequest = needleString
79 }
80 } else {
81 didMakeGqlRequest = true
82 }
83 } catch (_ignoreRespReadErr) {}
84 }
85 pendingResponses.push(handleResponse())
86 }
87 })
89 try {
90 await page.goto(url, { timeout: playwrightTimeoutMs })
91 await page.waitForLoadState('networkidle', { timeout: playwrightTimeoutMs })
92 } catch (_ignoreNavErr) {
93 timedOut = true
94 }
96 await Promise.all(pendingResponses)
97 await context.close()
99 const result = (expectNoErrors && gqlRespHadError) ? false : didMakeGqlRequest
100 if (diagnostics) Object.assign(diagnostics, {timedOut, gqlRequestSent, gqlRespHadError, gqlRespErrSnip})
101 setMemoizedResult(cacheKey, result)
103 return result
104 } catch (error) {
105 return false
106 } finally {
107 await browser.close()
108 }