Skip to content

Commit 3925f8c

Browse files
fix(core): vendor superjson to fix ESM/CJS compatibility (#2949)
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 <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2949"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
1 parent 01208fd commit 3925f8c

File tree

29 files changed

+1463
-28
lines changed

29 files changed

+1463
-28
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@trigger.dev/core": patch
3+
---
4+
5+
fix: vendor superjson to fix ESM/CJS compatibility
6+
7+
Bundle superjson 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.

.github/workflows/pr_checks.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ jobs:
2929
with:
3030
package: cli-v3
3131
secrets: inherit
32+
33+
sdk-compat:
34+
uses: ./.github/workflows/sdk-compat.yml
35+
secrets: inherit

.github/workflows/sdk-compat.yml

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
name: "🔌 SDK Compatibility Tests"
2+
3+
permissions:
4+
contents: read
5+
6+
on:
7+
workflow_call:
8+
9+
jobs:
10+
node-compat:
11+
name: "Node.js ${{ matrix.node }} (${{ matrix.os }})"
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os: [ubuntu-latest]
17+
node: ["20.20", "22.12"]
18+
19+
steps:
20+
- name: ⬇️ Checkout repo
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
25+
- name: ⎔ Setup pnpm
26+
uses: pnpm/action-setup@v4
27+
with:
28+
version: 10.23.0
29+
30+
- name: ⎔ Setup node
31+
uses: buildjet/setup-node@v4
32+
with:
33+
node-version: ${{ matrix.node }}
34+
cache: "pnpm"
35+
36+
- name: 📥 Download deps
37+
run: pnpm install --frozen-lockfile
38+
39+
- name: 📀 Generate Prisma Client
40+
run: pnpm run generate
41+
42+
- name: 🔨 Build SDK dependencies
43+
shell: bash
44+
run: pnpm run build --filter '@trigger.dev/sdk^...'
45+
46+
- name: 🔨 Build SDK
47+
shell: bash
48+
run: pnpm run build --filter '@trigger.dev/sdk'
49+
50+
- name: 🧪 Run SDK Compatibility Tests
51+
shell: bash
52+
run: pnpm --filter @internal/sdk-compat-tests test
53+
54+
bun-compat:
55+
name: "Bun Runtime"
56+
runs-on: ubuntu-latest
57+
steps:
58+
- name: ⬇️ Checkout repo
59+
uses: actions/checkout@v4
60+
with:
61+
fetch-depth: 0
62+
63+
- name: ⎔ Setup pnpm
64+
uses: pnpm/action-setup@v4
65+
with:
66+
version: 10.23.0
67+
68+
- name: ⎔ Setup node
69+
uses: buildjet/setup-node@v4
70+
with:
71+
node-version: 20.20.0
72+
cache: "pnpm"
73+
74+
- name: 🥟 Setup Bun
75+
uses: oven-sh/setup-bun@v2
76+
with:
77+
bun-version: latest
78+
79+
- name: 📥 Download deps
80+
run: pnpm install --frozen-lockfile
81+
82+
- name: 📀 Generate Prisma Client
83+
run: pnpm run generate
84+
85+
- name: 🔨 Build SDK dependencies
86+
run: pnpm run build --filter @trigger.dev/sdk^...
87+
88+
- name: 🔨 Build SDK
89+
run: pnpm run build --filter @trigger.dev/sdk
90+
91+
- name: 🧪 Run Bun Compatibility Test
92+
working-directory: internal-packages/sdk-compat-tests/src/fixtures/bun
93+
run: bun run test.ts
94+
95+
deno-compat:
96+
name: "Deno Runtime"
97+
runs-on: ubuntu-latest
98+
steps:
99+
- name: ⬇️ Checkout repo
100+
uses: actions/checkout@v4
101+
with:
102+
fetch-depth: 0
103+
104+
- name: ⎔ Setup pnpm
105+
uses: pnpm/action-setup@v4
106+
with:
107+
version: 10.23.0
108+
109+
- name: ⎔ Setup node
110+
uses: buildjet/setup-node@v4
111+
with:
112+
node-version: 20.20.0
113+
cache: "pnpm"
114+
115+
- name: 🦕 Setup Deno
116+
uses: denoland/setup-deno@v2
117+
with:
118+
deno-version: v2.x
119+
120+
- name: 📥 Download deps
121+
run: pnpm install --frozen-lockfile
122+
123+
- name: 📀 Generate Prisma Client
124+
run: pnpm run generate
125+
126+
- name: 🔨 Build SDK dependencies
127+
run: pnpm run build --filter @trigger.dev/sdk^...
128+
129+
- name: 🔨 Build SDK
130+
run: pnpm run build --filter @trigger.dev/sdk
131+
132+
- name: 🔗 Link node_modules for Deno fixture
133+
working-directory: internal-packages/sdk-compat-tests/src/fixtures/deno
134+
run: ln -s ../../../../../node_modules node_modules
135+
136+
- name: 🧪 Run Deno Compatibility Test
137+
working-directory: internal-packages/sdk-compat-tests/src/fixtures/deno
138+
run: deno run --allow-read --allow-env --allow-sys test.ts
139+
140+
cloudflare-compat:
141+
name: "Cloudflare Workers"
142+
runs-on: ubuntu-latest
143+
steps:
144+
- name: ⬇️ Checkout repo
145+
uses: actions/checkout@v4
146+
with:
147+
fetch-depth: 0
148+
149+
- name: ⎔ Setup pnpm
150+
uses: pnpm/action-setup@v4
151+
with:
152+
version: 10.23.0
153+
154+
- name: ⎔ Setup node
155+
uses: buildjet/setup-node@v4
156+
with:
157+
node-version: 20.20.0
158+
cache: "pnpm"
159+
160+
- name: 📥 Download deps
161+
run: pnpm install --frozen-lockfile
162+
163+
- name: 📀 Generate Prisma Client
164+
run: pnpm run generate
165+
166+
- name: 🔨 Build SDK dependencies
167+
run: pnpm run build --filter @trigger.dev/sdk^...
168+
169+
- name: 🔨 Build SDK
170+
run: pnpm run build --filter @trigger.dev/sdk
171+
172+
- name: 📥 Install Cloudflare fixture deps
173+
working-directory: internal-packages/sdk-compat-tests/src/fixtures/cloudflare-worker
174+
run: pnpm install
175+
176+
- name: 🧪 Run Cloudflare Workers Compatibility Test (dry-run)
177+
working-directory: internal-packages/sdk-compat-tests/src/fixtures/cloudflare-worker
178+
run: npx wrangler deploy --dry-run --outdir dist

.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
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "@internal/sdk-compat-tests",
3+
"private": true,
4+
"version": "0.0.1",
5+
"type": "module",
6+
"scripts": {
7+
"test": "vitest",
8+
"test:watch": "vitest",
9+
"typecheck": "tsc --noEmit"
10+
},
11+
"dependencies": {
12+
"@trigger.dev/sdk": "workspace:*"
13+
},
14+
"devDependencies": {
15+
"esbuild": "^0.24.0",
16+
"execa": "^9.3.0",
17+
"typescript": "^5.5.0",
18+
"vitest": "3.1.4"
19+
}
20+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "bun-fixture",
3+
"private": true,
4+
"type": "module"
5+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Bun Import Test Fixture
3+
*
4+
* Tests that the SDK works correctly with Bun runtime.
5+
* Bun has high Node.js compatibility but uses its own module resolver.
6+
*/
7+
8+
import { task, logger, schedules, runs, configure, queue, retry, wait } from "@trigger.dev/sdk";
9+
10+
// Validate exports exist
11+
const checks: [string, boolean][] = [
12+
["task", typeof task === "function"],
13+
["logger", typeof logger === "object" && typeof logger.info === "function"],
14+
["schedules", typeof schedules === "object"],
15+
["runs", typeof runs === "object"],
16+
["configure", typeof configure === "function"],
17+
["queue", typeof queue === "function"],
18+
["retry", typeof retry === "object"],
19+
["wait", typeof wait === "object"],
20+
];
21+
22+
let failed = false;
23+
for (const [name, passed] of checks) {
24+
if (!passed) {
25+
console.error(`FAIL: ${name} export check failed`);
26+
failed = true;
27+
}
28+
}
29+
30+
// Test task definition with types
31+
interface Payload {
32+
message: string;
33+
}
34+
35+
const myTask = task({
36+
id: "bun-test-task",
37+
run: async (payload: Payload) => {
38+
return { received: payload.message };
39+
},
40+
});
41+
42+
if (myTask.id !== "bun-test-task") {
43+
console.error(`FAIL: task.id mismatch`);
44+
failed = true;
45+
}
46+
47+
// Test queue definition
48+
const myQueue = queue({
49+
name: "bun-test-queue",
50+
concurrencyLimit: 5,
51+
});
52+
53+
if (!myQueue) {
54+
console.error(`FAIL: queue creation failed`);
55+
failed = true;
56+
}
57+
58+
if (failed) {
59+
process.exit(1);
60+
}
61+
62+
console.log("SUCCESS: Bun imports validated");
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "cjs-require-fixture",
3+
"private": true
4+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* CJS Require Test Fixture
3+
*
4+
* This file validates that the SDK can be required using CommonJS syntax.
5+
* This is critical for:
6+
* - Node.js < 22.12.0 (where require(ESM) is not enabled by default)
7+
* - AWS Lambda (intentionally disables require(ESM))
8+
* - Legacy Node.js applications
9+
*/
10+
11+
// Test main export
12+
const sdk = require("@trigger.dev/sdk");
13+
14+
// Test /v3 subpath
15+
const sdkV3 = require("@trigger.dev/sdk/v3");
16+
17+
// Validate exports exist
18+
const checks = [
19+
["task", typeof sdk.task === "function"],
20+
["taskV3", typeof sdkV3.task === "function"],
21+
["logger", typeof sdk.logger === "object" && typeof sdk.logger.info === "function"],
22+
["schedules", typeof sdk.schedules === "object"],
23+
["runs", typeof sdk.runs === "object"],
24+
["configure", typeof sdk.configure === "function"],
25+
["queue", typeof sdk.queue === "function"],
26+
["retry", typeof sdk.retry === "object"],
27+
["wait", typeof sdk.wait === "object"],
28+
["metadata", typeof sdk.metadata === "object"],
29+
["tags", typeof sdk.tags === "object"],
30+
];
31+
32+
let failed = false;
33+
for (const [name, passed] of checks) {
34+
if (!passed) {
35+
console.error(`FAIL: ${name} export check failed`);
36+
failed = true;
37+
}
38+
}
39+
40+
// Test task definition works
41+
const myTask = sdk.task({
42+
id: "cjs-test-task",
43+
run: async (payload) => {
44+
return { received: payload };
45+
},
46+
});
47+
48+
if (myTask.id !== "cjs-test-task") {
49+
console.error(`FAIL: task.id mismatch: expected "cjs-test-task", got "${myTask.id}"`);
50+
failed = true;
51+
}
52+
53+
if (failed) {
54+
process.exit(1);
55+
}
56+
57+
console.log("SUCCESS: All CJS requires validated");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "cloudflare-worker-fixture",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"build": "wrangler deploy --dry-run --outdir dist"
7+
},
8+
"devDependencies": {
9+
"wrangler": "^3.0.0"
10+
}
11+
}

0 commit comments

Comments
 (0)