Skip to content

Commit a13fb21

Browse files
committed
feat(build): add bundle-api script for Vercel serverless API pre-bundling
1 parent b193de5 commit a13fb21

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

apps/studio/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@
6969
"tailwindcss": "^4.2.2",
7070
"typescript": "^5.0.0",
7171
"vite": "^8.0.1",
72-
"vitest": "^4.1.0"
72+
"vitest": "^4.1.0",
73+
"esbuild": "^0.25.0"
7374
},
7475
"msw": {
7576
"workerDirectory": [

apps/studio/scripts/bundle-api.mjs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Pre-bundles the Vercel serverless API function.
3+
*
4+
* Vercel's @vercel/node builder resolves pnpm workspace packages via symlinks,
5+
* which can cause esbuild to resolve to TypeScript source files rather than
6+
* compiled dist output — producing ERR_MODULE_NOT_FOUND at runtime.
7+
*
8+
* This script bundles api/index.ts with all @objectstack/* workspace packages
9+
* inlined, while keeping third-party npm packages external (they resolve
10+
* normally from node_modules at runtime).
11+
*
12+
* Run from the apps/studio directory during the Vercel build step.
13+
*/
14+
15+
import { build } from 'esbuild';
16+
import { unlinkSync } from 'node:fs';
17+
18+
await build({
19+
entryPoints: ['api/index.ts'],
20+
bundle: true,
21+
platform: 'node',
22+
format: 'esm',
23+
target: 'es2020',
24+
outfile: 'api/index.mjs',
25+
sourcemap: true,
26+
// Maintain proper __dirname / import.meta.url behaviour
27+
define: {},
28+
plugins: [{
29+
name: 'externalize-non-workspace',
30+
setup(build) {
31+
build.onResolve({ filter: /.*/ }, (args) => {
32+
// Bundle relative imports (../src/lib/*, ../objectstack.config.js, etc.)
33+
if (args.path.startsWith('.') || args.path.startsWith('/')) return null;
34+
// Bundle @objectstack/* workspace packages inline
35+
if (args.path.startsWith('@objectstack/')) return null;
36+
// Externalize everything else (npm packages, node builtins)
37+
return { path: args.path, external: true };
38+
});
39+
},
40+
}],
41+
});
42+
43+
// Remove the TypeScript source so Vercel only sees the compiled .mjs
44+
unlinkSync('api/index.ts');
45+
46+
console.log('[bundle-api] Bundled api/index.ts → api/index.mjs');

apps/studio/vercel.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "https://openapi.vercel.sh/vercel.json",
33
"framework": "vite",
44
"installCommand": "cd ../.. && pnpm install",
5-
"buildCommand": "cd ../.. && pnpm turbo run build --filter=@objectstack/studio",
5+
"buildCommand": "cd ../.. && pnpm turbo run build --filter=@objectstack/studio && cd apps/studio && node scripts/bundle-api.mjs",
66
"outputDirectory": "dist",
77
"build": {
88
"env": {

0 commit comments

Comments
 (0)