Skip to content

Commit 2d29f7a

Browse files
committed
fix(core): vendor superjson to fix ESM/CJS compatibility
Bundle superjson and its dependency (copy-anything) during build to avoid ERR_REQUIRE_ESM errors on Node.js versions that don't support require(ESM) by default (< 22.12.0) and AWS Lambda which intentionally disables it. - Add scripts/bundle-superjson.mjs to bundle superjson with esbuild - Update build script to bundle vendor files before tshy compilation - Move superjson from dependencies to devDependencies - Update imports to use vendored bundles Fixes #2937 pnpm install
1 parent eeab6bd commit 2d29f7a

File tree

6 files changed

+118
-20
lines changed

6 files changed

+118
-20
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ out/
1515
dist
1616
packages/**/dist
1717

18+
# vendored bundles (generated during build)
19+
packages/**/src/**/vendor
20+
1821
# Tailwind
1922
apps/**/styles/tailwind.css
2023
packages/**/styles/tailwind.css

packages/core/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,11 @@
157157
},
158158
"sideEffects": false,
159159
"scripts": {
160-
"clean": "rimraf dist .tshy .tshy-build .turbo",
160+
"clean": "rimraf dist .tshy .tshy-build .turbo src/v3/vendor",
161161
"update-version": "tsx ../../scripts/updateVersion.ts",
162-
"build": "tshy && pnpm run update-version",
163-
"dev": "tshy --watch",
162+
"bundle-vendor": "node scripts/bundle-superjson.mjs",
163+
"build": "pnpm run bundle-vendor && tshy && node scripts/bundle-superjson.mjs --copy && pnpm run update-version",
164+
"dev": "pnpm run bundle-vendor && tshy --watch",
164165
"typecheck": "tsc --noEmit -p tsconfig.src.json",
165166
"test": "vitest",
166167
"check-exports": "attw --pack ."
@@ -193,7 +194,6 @@
193194
"socket.io": "4.7.4",
194195
"socket.io-client": "4.7.5",
195196
"std-env": "^3.8.1",
196-
"superjson": "^2.2.1",
197197
"tinyexec": "^0.3.2",
198198
"uncrypto": "^0.1.3",
199199
"zod": "3.25.76",
@@ -212,6 +212,7 @@
212212
"defu": "^6.1.4",
213213
"esbuild": "^0.23.0",
214214
"rimraf": "^3.0.2",
215+
"superjson": "^2.2.1",
215216
"ts-essentials": "10.0.1",
216217
"tshy": "^3.0.2",
217218
"tsx": "4.17.0"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* This script bundles superjson and its dependency (copy-anything) into
5+
* vendored CJS and ESM bundles to avoid the ERR_REQUIRE_ESM error.
6+
*
7+
* superjson v2.x is ESM-only, which causes issues on:
8+
* - Node.js versions before 22.12.0 (require(ESM) not enabled by default)
9+
* - AWS Lambda (intentionally disables require(ESM))
10+
*
11+
* Usage:
12+
* node scripts/bundle-superjson.mjs # Bundle to src/v3/vendor
13+
* node scripts/bundle-superjson.mjs --copy # Also copy to dist directories
14+
*/
15+
16+
import * as esbuild from "esbuild";
17+
import { dirname, join } from "node:path";
18+
import { fileURLToPath } from "node:url";
19+
import { readFileSync, mkdirSync, copyFileSync } from "node:fs";
20+
21+
const __dirname = dirname(fileURLToPath(import.meta.url));
22+
const packageRoot = join(__dirname, "..");
23+
const vendorDir = join(packageRoot, "src", "v3", "vendor");
24+
25+
// Get the installed superjson version for the banner
26+
const superjsonPkg = JSON.parse(
27+
readFileSync(join(packageRoot, "node_modules", "superjson", "package.json"), "utf-8")
28+
);
29+
const banner = `/**
30+
* Bundled superjson v${superjsonPkg.version}
31+
*
32+
* This file is auto-generated by scripts/bundle-superjson.mjs
33+
* Do not edit directly - run the script to regenerate.
34+
*
35+
* Original package: https://github.com/flightcontrolhq/superjson
36+
* License: MIT
37+
*/`;
38+
39+
async function bundle() {
40+
// Ensure vendor directory exists
41+
mkdirSync(vendorDir, { recursive: true });
42+
43+
// Bundle for CommonJS
44+
await esbuild.build({
45+
entryPoints: [join(packageRoot, "node_modules", "superjson", "dist", "index.js")],
46+
bundle: true,
47+
format: "cjs",
48+
platform: "node",
49+
target: "node18",
50+
outfile: join(vendorDir, "superjson.cjs"),
51+
banner: { js: banner },
52+
// Don't minify to keep it debuggable
53+
minify: false,
54+
});
55+
56+
// Bundle for ESM
57+
await esbuild.build({
58+
entryPoints: [join(packageRoot, "node_modules", "superjson", "dist", "index.js")],
59+
bundle: true,
60+
format: "esm",
61+
platform: "node",
62+
target: "node18",
63+
outfile: join(vendorDir, "superjson.mjs"),
64+
banner: { js: banner },
65+
minify: false,
66+
});
67+
68+
console.log("Bundled superjson v" + superjsonPkg.version);
69+
console.log(" -> src/v3/vendor/superjson.cjs (CommonJS)");
70+
console.log(" -> src/v3/vendor/superjson.mjs (ESM)");
71+
72+
// Copy to dist directories if --copy flag is passed
73+
if (process.argv.includes("--copy")) {
74+
const distCommonjsVendor = join(packageRoot, "dist", "commonjs", "v3", "vendor");
75+
const distEsmVendor = join(packageRoot, "dist", "esm", "v3", "vendor");
76+
77+
mkdirSync(distCommonjsVendor, { recursive: true });
78+
mkdirSync(distEsmVendor, { recursive: true });
79+
80+
copyFileSync(join(vendorDir, "superjson.cjs"), join(distCommonjsVendor, "superjson.cjs"));
81+
copyFileSync(join(vendorDir, "superjson.mjs"), join(distEsmVendor, "superjson.mjs"));
82+
83+
console.log("Copied to dist directories");
84+
}
85+
}
86+
87+
bundle().catch((err) => {
88+
console.error(err);
89+
process.exit(1);
90+
});
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
// Use vendored superjson bundle to avoid ESM/CJS compatibility issues
2+
// See: https://github.com/triggerdotdev/trigger.dev/issues/2937
13
// @ts-ignore
2-
const { default: superjson } = require("superjson");
4+
const superjson = require("../vendor/superjson.cjs");
35

46
// @ts-ignore
5-
superjson.registerCustom<Buffer, number[]>(
7+
superjson.default.registerCustom<Buffer, number[]>(
68
{
79
isApplicable: (v: unknown): v is Buffer => typeof Buffer === "function" && Buffer.isBuffer(v),
810
serialize: (v: Buffer) => [...v],
@@ -12,4 +14,4 @@ superjson.registerCustom<Buffer, number[]>(
1214
);
1315

1416
// @ts-ignore
15-
module.exports.default = superjson;
17+
module.exports.default = superjson.default;

packages/core/src/v3/imports/superjson.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
// Use vendored superjson bundle to avoid ESM/CJS compatibility issues
2+
// See: https://github.com/triggerdotdev/trigger.dev/issues/2937
13
// @ts-ignore
2-
import superjson from "superjson";
4+
import superjson from "../vendor/superjson.mjs";
35

46
superjson.registerCustom<Buffer, number[]>(
57
{
6-
isApplicable: (v): v is Buffer => typeof Buffer === "function" && Buffer.isBuffer(v),
7-
serialize: (v) => [...v],
8-
deserialize: (v) => Buffer.from(v),
8+
isApplicable: (v: unknown): v is Buffer => typeof Buffer === "function" && Buffer.isBuffer(v),
9+
serialize: (v: Buffer) => [...v],
10+
deserialize: (v: number[]) => Buffer.from(v),
911
},
1012
"buffer"
1113
);

pnpm-lock.yaml

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)