Skip to content

Commit 7d93e2a

Browse files
authored
cli: Use the correct build command during deploys. (#41)
1 parent 77b02cf commit 7d93e2a

5 files changed

Lines changed: 95 additions & 3 deletions

File tree

‎docs/reference/config.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ Custom names are used in the deploy manifest and in wrangler binding sync for lo
305305

306306
#### `inference.build`
307307

308-
Override the build command. Useful for frameworks with their own CLIs (Nuxt, Astro) or custom build scripts. If omitted, the CLI uses the framework's default build command.
308+
Override the build command. Useful for frameworks with their own CLIs (Nuxt, Astro) or static apps with custom build scripts. If omitted, the CLI uses the detected default build command for the current app type.
309309

310310
```json
311311
{ "inference": { "build": "nuxt build --preset cloudflare-module" } }

‎packages/void/src/cli/deploy.ts‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,14 @@ export async function runDeploy(root: string, options?: RunDeployOptions): Promi
204204
const gitCommit = options?.skipBuild ? null : getGitCommit(root);
205205

206206
if (preset) {
207+
preset = {
208+
...preset,
209+
buildCommand: resolveStaticBuildCommand(
210+
preset,
211+
voidConfig.inference?.build,
212+
Boolean(options?.dir),
213+
),
214+
};
207215
await runStaticDeploy(
208216
root,
209217
config,
@@ -220,6 +228,15 @@ export async function runDeploy(root: string, options?: RunDeployOptions): Promi
220228
}
221229
}
222230

231+
export function resolveStaticBuildCommand(
232+
preset: StaticPreset,
233+
buildOverride?: string,
234+
hasExplicitDir = false,
235+
): string | null {
236+
if (hasExplicitDir) return null;
237+
return buildOverride ?? preset.buildCommand;
238+
}
239+
223240
async function streamDeploy(
224241
client: PlatformClient,
225242
projectId: string,

‎packages/void/src/cli/preset.ts‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,9 @@ export function detectPreset(
189189

190190
// 4. Vite/Vite+ in deps → static SPA
191191
if (pkg && hasViteLike(pkg)) {
192+
const buildCommand = resolveProjectScriptCommand(root, "build");
192193
return {
193-
buildCommand: resolveProjectCommand(root, "vite build"),
194+
buildCommand: buildCommand ?? resolveProjectCommand(root, "vite build"),
194195
outputDir: resolve(root, "dist"),
195196
appType: "spa",
196197
};
@@ -247,6 +248,31 @@ function getAllDeps(pkg: Record<string, unknown>): Record<string, string> {
247248
};
248249
}
249250

251+
function detectPackageManager(root: string): "pnpm" | "yarn" | "bun" | "npm" {
252+
if (existsSync(join(root, "pnpm-lock.yaml"))) return "pnpm";
253+
if (existsSync(join(root, "yarn.lock"))) return "yarn";
254+
if (existsSync(join(root, "bun.lock")) || existsSync(join(root, "bun.lockb"))) return "bun";
255+
return "npm";
256+
}
257+
258+
function resolveProjectScriptCommand(root: string, scriptName: string): string | null {
259+
const pkg = readPackageJson(root);
260+
const script = pkg?.scripts;
261+
if (!script || typeof script !== "object" || Array.isArray(script)) return null;
262+
if (typeof (script as Record<string, unknown>)[scriptName] !== "string") return null;
263+
264+
switch (detectPackageManager(root)) {
265+
case "pnpm":
266+
return `pnpm ${scriptName}`;
267+
case "yarn":
268+
return `yarn ${scriptName}`;
269+
case "bun":
270+
return `bun run ${scriptName}`;
271+
default:
272+
return `npm run ${scriptName}`;
273+
}
274+
}
275+
250276
function hasViteLike(pkg: Record<string, unknown>): boolean {
251277
const deps = getAllDeps(pkg);
252278
return "vite" in deps || "vite-plus" in deps;

‎packages/void/test/unit/deploy-project.test.ts‎

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
22
import { tmpdir } from "node:os";
33
import { join } from "node:path";
44
import { afterEach, describe, expect, it } from "vitest";
5-
import { resolveDistDir, resolveWorkerDirName } from "../../src/cli/deploy";
5+
import {
6+
resolveDistDir,
7+
resolveStaticBuildCommand,
8+
resolveWorkerDirName,
9+
} from "../../src/cli/deploy";
610
import { FRAMEWORK_PRESETS } from "../../src/cli/preset";
711
import {
812
getRequestedProjectSlug,
@@ -144,6 +148,35 @@ describe("resolveDistDir", () => {
144148
});
145149
});
146150

151+
describe("resolveStaticBuildCommand", () => {
152+
it("uses inference.build when provided", () => {
153+
expect(
154+
resolveStaticBuildCommand(
155+
{
156+
buildCommand: "vite build",
157+
outputDir: "/tmp/dist",
158+
appType: "static",
159+
},
160+
"pnpm build",
161+
),
162+
).toBe("pnpm build");
163+
});
164+
165+
it("keeps explicit --dir deploys buildless even when inference.build is set", () => {
166+
expect(
167+
resolveStaticBuildCommand(
168+
{
169+
buildCommand: null,
170+
outputDir: "/tmp/dist",
171+
appType: "static",
172+
},
173+
"pnpm build",
174+
true,
175+
),
176+
).toBeNull();
177+
});
178+
});
179+
147180
describe("resolveWorkerDirName", () => {
148181
afterEach(() => {
149182
while (tempDirs.length > 0) {

‎packages/void/test/unit/preset.test.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,22 @@ describe("detectPreset", () => {
148148
});
149149
});
150150

151+
it("prefers the project build script for plain Vite SPAs", () => {
152+
const root = setupProject({
153+
pkg: {
154+
dependencies: { vite: "^6.0.0" },
155+
scripts: { build: "vite build && node scripts/postbuild.js" },
156+
},
157+
files: { "pnpm-lock.yaml": "lockfileVersion: '9.0'\n" },
158+
});
159+
const result = detectPreset(root);
160+
expect(result).toEqual({
161+
buildCommand: "pnpm build",
162+
outputDir: resolve(root, "dist"),
163+
appType: "spa",
164+
});
165+
});
166+
151167
it("detects Vite+ SPA (no backend files)", () => {
152168
const root = setupProject({
153169
pkg: { devDependencies: { "vite-plus": "^1.0.0" } },

0 commit comments

Comments
 (0)