From 57ffbebfc8ad74c6cd7d3413a9df7944a8855ef3 Mon Sep 17 00:00:00 2001 From: gibbyb Date: Fri, 27 Mar 2026 02:22:11 -0500 Subject: [PATCH] Add patch for usesend so we can use up to date package! --- bun.lock | 4 +- package.json | 3 +- packages/backend/package.json | 2 +- scripts/patch-usesend.mjs | 102 ++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 scripts/patch-usesend.mjs diff --git a/bun.lock b/bun.lock index da2aace..3bcf733 100644 --- a/bun.lock +++ b/bun.lock @@ -113,7 +113,7 @@ "convex": "catalog:convex", "react": "catalog:react19", "react-dom": "catalog:react19", - "usesend-js": "1.5.7", + "usesend-js": "1.6.3", "zod": "catalog:", }, "devDependencies": { @@ -3316,7 +3316,7 @@ "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], - "usesend-js": ["usesend-js@1.5.7", "", { "dependencies": { "@react-email/render": "^1.0.6", "react": "^19.1.0" } }, "sha512-eCxTECV8IEumdkXRXOKzQOqf2+0UKWr3hg0Bl0kE8muUz/T0PSkLXMc3ZZl3YpIX2ThmeSLqXIXGNyFwZoksxg=="], + "usesend-js": ["usesend-js@1.6.3", "", { "dependencies": { "@react-email/render": "^1.0.6", "react": "^19.1.0" } }, "sha512-HKhW4F+RbAnp6izWxo2sjISmxhYQvxAjAsBFvdn0P25oVnZ8kXTMjvEqKyvkhgRrzXALu0N6NUyQjVOdOsjnoA=="], "utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="], diff --git a/package.json b/package.json index 3a28683..1bb3c69 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,8 @@ "lint": "turbo run lint --continue -- --cache --cache-location .cache/.eslintcache", "lint:fix": "turbo run lint --continue -- --fix --cache --cache-location .cache/.eslintcache", "lint:ws": "bunx sherif@latest", - "postinstall": "bun lint:ws", + "patch:usesend": "node scripts/patch-usesend.mjs", + "postinstall": "bun patch:usesend && bun lint:ws", "typecheck": "turbo run typecheck", "ui-add": "turbo run ui-add", "android": "expo run:android", diff --git a/packages/backend/package.json b/packages/backend/package.json index f3ce7a5..a581674 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -29,7 +29,7 @@ "convex": "catalog:convex", "react": "catalog:react19", "react-dom": "catalog:react19", - "usesend-js": "1.5.7", + "usesend-js": "^1.6.3", "zod": "catalog:" }, "devDependencies": { diff --git a/scripts/patch-usesend.mjs b/scripts/patch-usesend.mjs new file mode 100644 index 0000000..0d32c59 --- /dev/null +++ b/scripts/patch-usesend.mjs @@ -0,0 +1,102 @@ +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) => { + 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();