From b95b7b31e70a20f644bc5f8ff404b43832a8d019 Mon Sep 17 00:00:00 2001 From: Taesu <166604494+bytaesu@users.noreply.github.com> Date: Thu, 3 Sep 2026 18:21:20 +0000 Subject: [PATCH] fix(cli): skip empty dependency installs (#11140) --- .changeset/calm-tools-skip-empty-installs.md | 5 +++ .../cli/src/utils/install-dependencies.ts | 11 +++++-- .../cli/test/install-dependencies.test.ts | 32 +++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 .changeset/calm-tools-skip-empty-installs.md diff --git a/.changeset/calm-tools-skip-empty-installs.md b/.changeset/calm-tools-skip-empty-installs.md new file mode 100644 index 0000000000..b64ae88c9b --- /dev/null +++ b/.changeset/calm-tools-skip-empty-installs.md @@ -0,0 +1,5 @@ +--- +"auth": patch +--- + +Allow `auth init` to finish when a generated setup has no dependencies in one of its install groups, and preserve useful package-manager output when an installation fails. diff --git a/packages/cli/src/utils/install-dependencies.ts b/packages/cli/src/utils/install-dependencies.ts index 642133ea7e..bca0f04592 100644 --- a/packages/cli/src/utils/install-dependencies.ts +++ b/packages/cli/src/utils/install-dependencies.ts @@ -76,12 +76,19 @@ export function installDependencies({ flags.push(flag); } } - const command = `${installCommand}${flags.length > 0 ? ` ${flags.join(" ")}` : ""} ${Array.isArray(dependencies) ? dependencies.join(" ") : dependencies}`; + const dependencyList = Array.isArray(dependencies) + ? dependencies + : [dependencies]; + if (dependencyList.length === 0) { + return Promise.resolve(true); + } + const command = `${installCommand}${flags.length > 0 ? ` ${flags.join(" ")}` : ""} ${dependencyList.join(" ")}`; return new Promise((resolve, reject) => { exec(command, { cwd }, (error, stdout, stderr) => { if (error) { - reject(new Error(stderr)); + const message = stderr.trim() || stdout.trim() || error.message; + reject(new Error(message, { cause: error })); return; } resolve(true); diff --git a/packages/cli/test/install-dependencies.test.ts b/packages/cli/test/install-dependencies.test.ts index c7ef5c6d3b..f14eb97082 100644 --- a/packages/cli/test/install-dependencies.test.ts +++ b/packages/cli/test/install-dependencies.test.ts @@ -131,6 +131,18 @@ describe("installDependencies", () => { }, ); + testWithTmpDir("should skip empty dependency lists", async ({ tmp }) => { + const result = await installDependencies({ + dependencies: [], + packageManager: "pnpm", + cwd: tmp, + type: "dev", + }); + + expect(result).toBe(true); + expect(mockExec).not.toHaveBeenCalled(); + }); + testWithTmpDir( "should run pnpm add with --save-catalog for catalog dependencies", async ({ tmp }) => { @@ -315,6 +327,26 @@ describe("installDependencies", () => { }, ); + testWithTmpDir( + "should reject with stdout when stderr is empty", + async ({ tmp }) => { + const execError = Object.assign(new Error("Command failed"), { code: 1 }); + mockExec.mockImplementation((_cmd, _opts, callback) => { + if (callback) { + callback(execError, "missing package name", ""); + } + return {} as ReturnType; + }); + + const promise = installDependencies({ + dependencies: "invalid-package", + packageManager: "pnpm", + cwd: tmp, + }); + await expect(promise).rejects.toThrow("missing package name"); + }, + ); + testWithTmpDir("should pass cwd to exec", async ({ tmp }) => { await installDependencies({ dependencies: "better-auth",