Files
convex-monorepo-payload/scripts/patch-usesend.mjs
T
Gabriel Brown 1af6b43b1a Update dependencies and fix what the new lint rules caught
Every package moves to its newest in-major version, plus React 19.3, @convex-dev/auth 0.0.96 and next-plausible 4. The backend declares @auth/core and generates sign-in codes without oslo, which @convex-dev/auth no longer pulls in. The UseSend patch now actually removes the crypto import Convex refuses to bundle. The stricter react-hooks and typescript-eslint rules flagged the carousel, chart, image crop and mobile hook, which now pass.
2026-10-01 14:41:58 -04:00

112 lines
3.5 KiB
JavaScript

import { readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const usesendDir = path.join(__dirname, '..', 'node_modules', 'usesend-js');
const ensureReplacement = (content, searchValue, replaceValue, filePath) => {
// Removal step (empty replacement): it's already applied once the search
// snippet is gone. Guard on searchValue, not replaceValue — every string
// "includes" the empty string, which would make this a silent no-op.
if (replaceValue === '') {
return content.includes(searchValue)
? content.replace(searchValue, replaceValue)
: content;
}
if (content.includes(replaceValue)) {
return content;
}
if (!content.includes(searchValue)) {
throw new Error(`Expected snippet not found in ${filePath}`);
}
return content.replace(searchValue, replaceValue);
};
const patchFile = async (relativePath, replacements) => {
const filePath = path.join(usesendDir, relativePath);
let content = await readFile(filePath, 'utf8');
for (const [searchValue, replaceValue] of replacements) {
content = ensureReplacement(
content,
searchValue,
replaceValue,
relativePath,
);
}
await writeFile(filePath, content);
};
const patchUseSend = async () => {
const packageJsonPath = path.join(usesendDir, 'package.json');
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'));
if (packageJson.version !== '1.6.3') {
console.log(
`Skipping UseSend patch for version ${packageJson.version ?? 'unknown'}.`,
);
return;
}
const runtimeHelper = `function getNodeCrypto() {
const builtinModuleLoader = globalThis.process?.getBuiltinModule;
if (typeof builtinModuleLoader === "function") {
const nodeCrypto = builtinModuleLoader("node:crypto");
if (nodeCrypto) {
return nodeCrypto;
}
}
throw new WebhookVerificationError(
"UNSUPPORTED_RUNTIME",
"Webhook verification requires a Node.js runtime with node:crypto support"
);
}
`;
await patchFile('dist/index.mjs', [
['import { createHmac, timingSafeEqual } from "crypto";\n', ''],
[
'function computeSignature(secret, timestamp, body) {\n',
`${runtimeHelper}function computeSignature(secret, timestamp, body) {\n`,
],
[
' const hmac = createHmac("sha256", secret);\n',
' const { createHmac } = getNodeCrypto();\n const hmac = createHmac("sha256", secret);\n',
],
[
'function safeEqual(a, b) {\n',
'function safeEqual(a, b) {\n const { timingSafeEqual } = getNodeCrypto();\n',
],
]);
await patchFile('dist/index.js', [
['var import_crypto = require("crypto");\n', ''],
[
'function computeSignature(secret, timestamp, body) {\n',
`${runtimeHelper}function computeSignature(secret, timestamp, body) {\n`,
],
[
' const hmac = (0, import_crypto.createHmac)("sha256", secret);\n',
' const { createHmac } = getNodeCrypto();\n const hmac = createHmac("sha256", secret);\n',
],
[
'function safeEqual(a, b) {\n',
'function safeEqual(a, b) {\n const { timingSafeEqual } = getNodeCrypto();\n',
],
[
' return (0, import_crypto.timingSafeEqual)(aBuf, bBuf);\n',
' return timingSafeEqual(aBuf, bBuf);\n',
],
]);
console.log('Patched usesend-js 1.6.3 for Convex-compatible bundling.');
};
await patchUseSend();