From ed098bebe10e2e9c0d3acd137632340b33d50038 Mon Sep 17 00:00:00 2001 From: UtkarshBhardwaj007 Date: Sat, 13 Jun 2026 16:35:43 +0200 Subject: [PATCH] fix(build): distinguish wrong cwd from missing build strategy detectBuildConfig threw the same 'No build strategy detected' message whether the cwd had no package.json at all or had one with no recognised build. The first case (user one dir above their project, e.g. after `dot mod`) is the common failure and the message sent them to the wrong fix. Split it: when package.json is absent, name the directory and point the user at it (cd in, or --dir ); keep the original message for a present-but-unrecognised package.json. Thread an optional projectDir through DetectInput (populated by loadDetectInput) so the error can name the directory while detect.ts stays pure. --- .changeset/wrong-cwd-build-error.md | 5 ++++ src/utils/build/detect.test.ts | 39 +++++++++++++++++++++++++++++ src/utils/build/detect.ts | 19 ++++++++++++++ src/utils/build/runner.ts | 1 + 4 files changed, 64 insertions(+) create mode 100644 .changeset/wrong-cwd-build-error.md diff --git a/.changeset/wrong-cwd-build-error.md b/.changeset/wrong-cwd-build-error.md new file mode 100644 index 00000000..00b0c073 --- /dev/null +++ b/.changeset/wrong-cwd-build-error.md @@ -0,0 +1,5 @@ +--- +"playground-cli": patch +--- + +Distinguish a wrong working directory from a genuinely unrecognised project in `dot build` / `dot deploy`. When no `package.json` is found, the error now points at the current directory ("Are you in your project directory? cd into it first, or point the command at it with --dir .") instead of the misleading "No build strategy detected" message that suggested editing a package.json that isn't there. diff --git a/src/utils/build/detect.test.ts b/src/utils/build/detect.test.ts index 3ebfb46e..437a80de 100644 --- a/src/utils/build/detect.test.ts +++ b/src/utils/build/detect.test.ts @@ -141,6 +141,45 @@ describe("detectBuildConfig", () => { ), ).toThrow(BuildDetectError); }); + + it("throws a wrong-directory error when package.json is missing entirely", () => { + // A missing package.json almost always means the user is one level + // above their project (e.g. ran `dot mod` then `dot build` from the + // parent). Point them at the cwd, not at editing a package.json that + // isn't there. + expect(() => detectBuildConfig(input({ packageJson: null }))).toThrow(BuildDetectError); + expect(() => detectBuildConfig(input({ packageJson: null }))).toThrow( + /No package\.json found/, + ); + }); + + it("names the project directory in the missing-package.json error", () => { + expect(() => + detectBuildConfig(input({ packageJson: null, projectDir: "/home/me" })), + ).toThrow(/\/home\/me/); + }); + + it("renders the missing-package.json error cleanly when no projectDir is known", () => { + // The dir name is optional, so the fallback must not leak `undefined` + // or a dangling space before the sentence-ending period. + let message = ""; + try { + detectBuildConfig(input({ packageJson: null })); + } catch (err) { + message = (err as Error).message; + } + expect(message).toContain("No package.json found."); + expect(message).not.toMatch(/undefined/); + expect(message).not.toMatch(/ {2}/); + }); + + it("keeps the generic build-strategy error when package.json exists but is unrecognised", () => { + // package.json IS present — the user is in the right place, we just + // can't infer a build. Keep the original guidance. + expect(() => detectBuildConfig(input({ packageJson: { scripts: {} } }))).toThrow( + /No build strategy detected/, + ); + }); }); describe("detectInstallConfig", () => { diff --git a/src/utils/build/detect.ts b/src/utils/build/detect.ts index bf1622b6..316ccc91 100644 --- a/src/utils/build/detect.ts +++ b/src/utils/build/detect.ts @@ -61,6 +61,12 @@ export interface DetectInput { lockfiles: Set; /** Set of additional config-file basenames (e.g. vite.config.ts). */ configFiles: Set; + /** + * Absolute project root the snapshot was taken from, used only to name the + * directory in the missing-package.json error. Optional so unit tests can + * build inputs without a real path. + */ + projectDir?: string; } export class BuildDetectError extends Error { @@ -197,6 +203,19 @@ export function detectBuildConfig(input: DetectInput): BuildConfig { } } + // No package.json at all almost always means the user is a level above + // their project (e.g. ran `dot mod`, then `dot build` from the parent dir). + // Point them at the directory rather than at editing a package.json that + // isn't there — the generic "add a build script" message sends them to the + // wrong fix. + if (!input.packageJson) { + const where = input.projectDir ? ` in ${input.projectDir}` : ""; + throw new BuildDetectError( + `No package.json found${where}. Are you in your project directory? ` + + "cd into it first, or point the command at it with --dir .", + ); + } + throw new BuildDetectError( 'No build strategy detected. Add a "build" script to package.json, or install vite/next/typescript.', ); diff --git a/src/utils/build/runner.ts b/src/utils/build/runner.ts index e84e926b..828a6131 100644 --- a/src/utils/build/runner.ts +++ b/src/utils/build/runner.ts @@ -68,6 +68,7 @@ export function loadDetectInput(projectDir: string): DetectInput { packageJson, lockfiles, configFiles, + projectDir: root, }; }