diff --git a/next.config.js b/next.config.js
index d02ef9bb..56e52d0c 100644
--- a/next.config.js
+++ b/next.config.js
@@ -2,6 +2,18 @@
const nextConfig = {
productionBrowserSourceMaps: true,
+ // Compile the sanitize-html chain into the build: Vercel's runtime
+ // require() cannot load ESM-only packages like htmlparser2 >=11
+ // (it runs node with --no-experimental-require-module).
+ transpilePackages: [
+ "sanitize-html",
+ "htmlparser2",
+ "domelementtype",
+ "domhandler",
+ "domutils",
+ "entities",
+ ],
+
turbopack: {
rules: {
"*.svg": {
diff --git a/package.json b/package.json
index 7bb4b307..56fa0b7b 100644
--- a/package.json
+++ b/package.json
@@ -87,7 +87,7 @@
"recharts": "^2.15.4",
"rehype-raw": "^7.0.0",
"remark-gfm": "4.0.1",
- "sanitize-html": "2.17.5",
+ "sanitize-html": "2.17.7",
"swr": "^2.5.1",
"viem": "^2.56.3",
"wagmi": "^2.19.5",
diff --git a/pages/api/health.tsx b/pages/api/health.tsx
index 73120af1..f6630492 100644
--- a/pages/api/health.tsx
+++ b/pages/api/health.tsx
@@ -23,9 +23,22 @@ const health = async (req: NextApiRequest, res: NextApiResponse) => {
const allHealthy = subgraphOk;
+ // DEBUG (remove before merge): report the runtime and whether the
+ // sanitize-html require chain loads on it.
+ let sanitizeHtmlLoads: string;
+ try {
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
+ const s = require("sanitize-html");
+ sanitizeHtmlLoads = `ok (sanitized: ${s("x")})`;
+ } catch (e) {
+ sanitizeHtmlLoads = `LOAD FAILED: ${(e as Error).message}`;
+ }
+
const response = {
status: allHealthy ? "healthy" : "degraded",
timestamp: new Date().toISOString(),
+ nodeVersion: process.version,
+ sanitizeHtml: sanitizeHtmlLoads,
checks: {
subgraph: subgraphOk ? "ok" : "error",
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d2091d73..b3855361 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -148,8 +148,8 @@ importers:
specifier: 4.0.1
version: 4.0.1
sanitize-html:
- specifier: 2.17.5
- version: 2.17.5
+ specifier: 2.17.7
+ version: 2.17.7
swr:
specifier: ^2.5.1
version: 2.5.1(react@19.2.1)
@@ -5701,16 +5701,32 @@ packages:
dom-serializer@2.0.0:
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+ dom-serializer@3.1.1:
+ resolution: {integrity: sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==}
+ engines: {node: '>=20.19.0'}
+
domelementtype@2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+ domelementtype@3.0.0:
+ resolution: {integrity: sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==}
+ engines: {node: '>=20.19.0'}
+
domhandler@5.0.3:
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
engines: {node: '>= 4'}
+ domhandler@6.0.1:
+ resolution: {integrity: sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==}
+ engines: {node: '>=20.19.0'}
+
domutils@3.2.2:
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
+ domutils@4.0.2:
+ resolution: {integrity: sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==}
+ engines: {node: '>=20.19.0'}
+
dot-case@3.0.4:
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
@@ -5799,6 +5815,10 @@ packages:
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
engines: {node: '>=0.12'}
+ entities@8.0.0:
+ resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==}
+ engines: {node: '>=20.19.0'}
+
error-ex@1.3.4:
resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
@@ -6495,6 +6515,10 @@ packages:
htmlparser2@10.1.0:
resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
+ htmlparser2@12.0.0:
+ resolution: {integrity: sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==}
+ engines: {node: '>=20.19.0'}
+
http-errors@2.0.1:
resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
engines: {node: '>= 0.8'}
@@ -8583,8 +8607,9 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
- sanitize-html@2.17.5:
- resolution: {integrity: sha512-ZmU1joGRrvoyctKIiuwUxqR6moLoU2Wk+2bMccN6f7UwhAmwYDvWziqPxRDDN2Qip62NqnIrVrT9akbL6Wretg==}
+ sanitize-html@2.17.7:
+ resolution: {integrity: sha512-PGtEkc9cbnedU3s9TmzDbpsZ8w086g/0Q8k8/oIO1NLNU3i5k9yn835CrjJSajp1KMmkisbO1qPXxNKO3welAg==}
+ engines: {node: '>=22.12.0'}
sax@1.6.1:
resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==}
@@ -17186,18 +17211,36 @@ snapshots:
domhandler: 5.0.3
entities: 4.5.0
+ dom-serializer@3.1.1:
+ dependencies:
+ domelementtype: 3.0.0
+ domhandler: 6.0.1
+ entities: 8.0.0
+
domelementtype@2.3.0: {}
+ domelementtype@3.0.0: {}
+
domhandler@5.0.3:
dependencies:
domelementtype: 2.3.0
+ domhandler@6.0.1:
+ dependencies:
+ domelementtype: 3.0.0
+
domutils@3.2.2:
dependencies:
dom-serializer: 2.0.0
domelementtype: 2.3.0
domhandler: 5.0.3
+ domutils@4.0.2:
+ dependencies:
+ dom-serializer: 3.1.1
+ domelementtype: 3.0.0
+ domhandler: 6.0.1
+
dot-case@3.0.4:
dependencies:
no-case: 3.0.4
@@ -17297,6 +17340,8 @@ snapshots:
entities@7.0.1: {}
+ entities@8.0.0: {}
+
error-ex@1.3.4:
dependencies:
is-arrayish: 0.2.1
@@ -18332,6 +18377,13 @@ snapshots:
domutils: 3.2.2
entities: 7.0.1
+ htmlparser2@12.0.0:
+ dependencies:
+ domelementtype: 3.0.0
+ domhandler: 6.0.1
+ domutils: 4.0.2
+ entities: 8.0.0
+
http-errors@2.0.1:
dependencies:
depd: 2.0.0
@@ -21051,11 +21103,11 @@ snapshots:
safer-buffer@2.1.2: {}
- sanitize-html@2.17.5:
+ sanitize-html@2.17.7:
dependencies:
deepmerge: 4.3.1
escape-string-regexp: 4.0.0
- htmlparser2: 10.1.0
+ htmlparser2: 12.0.0
is-plain-object: 5.1.0
launder: 1.7.1
parse-srcset: 1.0.2