From 6017fa7865a334ac1a6960b8028ce2040b3d888f Mon Sep 17 00:00:00 2001 From: Kfir Strikovsky Date: Wed, 18 Feb 2026 14:20:38 +0200 Subject: [PATCH 1/2] bump clack to v1 --- bun.lock | 6 ++--- package.json | 2 +- src/cli/commands/connectors/oauth-prompt.ts | 25 +++++++-------------- src/cli/utils/runTask.ts | 2 +- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/bun.lock b/bun.lock index 88b8bc9f..8375efc2 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "name": "base44", "devDependencies": { "@biomejs/biome": "^2.0.0", - "@clack/prompts": "^0.11.0", + "@clack/prompts": "^1.0.1", "@types/bun": "^1.2.15", "@types/common-tags": "^1.8.4", "@types/cors": "^2.8.19", @@ -67,9 +67,9 @@ "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.14", "", { "os": "win32", "cpu": "x64" }, "sha512-oizCjdyQ3WJEswpb3Chdngeat56rIdSYK12JI3iI11Mt5T5EXcZ7WLuowzEaFPNJ3zmOQFliMN8QY1Pi+qsfdQ=="], - "@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="], + "@clack/core": ["@clack/core@1.0.1", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-WKeyK3NOBwDOzagPR5H08rFk9D/WuN705yEbuZvKqlkmoLM2woKtXb10OO2k1NoSU4SFG947i2/SCYh+2u5e4g=="], - "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], + "@clack/prompts": ["@clack/prompts@1.0.1", "", { "dependencies": { "@clack/core": "1.0.1", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-/42G73JkuYdyWZ6m8d/CJtBrGl1Hegyc7Fy78m5Ob+jF85TOUmLR5XLce/U3LxYAw0kJ8CT5aI99RIvPHcGp/Q=="], "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], diff --git a/package.json b/package.json index b0a9931c..262aae1a 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ }, "devDependencies": { "@biomejs/biome": "^2.0.0", - "@clack/prompts": "^0.11.0", + "@clack/prompts": "^1.0.1", "@types/bun": "^1.2.15", "@types/common-tags": "^1.8.4", "@types/cors": "^2.8.19", diff --git a/src/cli/commands/connectors/oauth-prompt.ts b/src/cli/commands/connectors/oauth-prompt.ts index 7c22ca82..7852a5a7 100644 --- a/src/cli/commands/connectors/oauth-prompt.ts +++ b/src/cli/commands/connectors/oauth-prompt.ts @@ -32,27 +32,20 @@ interface OAuthPromptOptions { skipPrompt?: boolean; } -/** - * Clack's block() puts stdin in raw mode where Ctrl+C calls process.exit(0) - * directly instead of emitting SIGINT. We override process.exit temporarily - * so Ctrl+C/Esc skips the current connector instead of killing the process. - */ async function runOAuthFlowWithSkip( connector: PendingOAuthResult, ): Promise { await open(connector.redirectUrl); - // Mutated inside the pWaitFor callback — use `as` to prevent TS narrowing let finalStatus = "PENDING" as OAuthFlowStatus; let skipped = false; - const s = spinner(); - - const originalExit = process.exit; - process.exit = (() => { - skipped = true; - s.stop(`${connector.type} skipped`); - }) as unknown as typeof process.exit; + const s = spinner({ + onCancel: () => { + skipped = true; + }, + cancelMessage: `${connector.type} skipped`, + }); s.start(`Waiting for ${connector.type} authorization... (Esc to skip)`); @@ -82,15 +75,13 @@ async function runOAuthFlowWithSkip( throw err; } } finally { - process.exit = originalExit; - if (!skipped) { if (finalStatus === "ACTIVE") { s.stop(`${connector.type} authorization complete`); } else if (finalStatus === "FAILED") { - s.stop(`${connector.type} authorization failed`); + s.error(`${connector.type} authorization failed`); } else { - s.stop(`${connector.type} authorization timed out`); + s.error(`${connector.type} authorization timed out`); } } } diff --git a/src/cli/utils/runTask.ts b/src/cli/utils/runTask.ts index 3f1b90c4..f9732227 100644 --- a/src/cli/utils/runTask.ts +++ b/src/cli/utils/runTask.ts @@ -56,7 +56,7 @@ export async function runTask( s.stop(options?.successMessage || startMessage); return result; } catch (error) { - s.stop(options?.errorMessage || "Failed"); + s.error(options?.errorMessage || "Failed"); throw error; } } From af96549404a59df3558ed92df12047b5f26392ee Mon Sep 17 00:00:00 2001 From: Kfir Strikovsky Date: Wed, 18 Feb 2026 14:32:16 +0200 Subject: [PATCH 2/2] small fixes --- src/cli/commands/connectors/oauth-prompt.ts | 37 ++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/cli/commands/connectors/oauth-prompt.ts b/src/cli/commands/connectors/oauth-prompt.ts index 7852a5a7..288ddb39 100644 --- a/src/cli/commands/connectors/oauth-prompt.ts +++ b/src/cli/commands/connectors/oauth-prompt.ts @@ -32,6 +32,11 @@ interface OAuthPromptOptions { skipPrompt?: boolean; } +/** + * Clack's block() puts stdin in raw mode where Ctrl+C/Esc calls process.exit(0) + * directly instead of emitting SIGINT. We override process.exit temporarily + * so Ctrl+C/Esc skips the current connector instead of killing the process. + */ async function runOAuthFlowWithSkip( connector: PendingOAuthResult, ): Promise { @@ -40,12 +45,12 @@ async function runOAuthFlowWithSkip( let finalStatus = "PENDING" as OAuthFlowStatus; let skipped = false; - const s = spinner({ - onCancel: () => { - skipped = true; - }, - cancelMessage: `${connector.type} skipped`, - }); + const s = spinner(); + + const originalExit = process.exit; + process.exit = (() => { + skipped = true; + }) as unknown as typeof process.exit; s.start(`Waiting for ${connector.type} authorization... (Esc to skip)`); @@ -75,14 +80,16 @@ async function runOAuthFlowWithSkip( throw err; } } finally { - if (!skipped) { - if (finalStatus === "ACTIVE") { - s.stop(`${connector.type} authorization complete`); - } else if (finalStatus === "FAILED") { - s.error(`${connector.type} authorization failed`); - } else { - s.error(`${connector.type} authorization timed out`); - } + process.exit = originalExit; + + if (skipped) { + s.cancel(`${connector.type} skipped`); + } else if (finalStatus === "ACTIVE") { + s.stop(`${connector.type} authorization complete`); + } else if (finalStatus === "FAILED") { + s.error(`${connector.type} authorization failed`); + } else { + s.error(`${connector.type} authorization timed out`); } } @@ -126,7 +133,7 @@ export async function promptOAuthFlows( for (const connector of pending) { try { - log.info(`\nOpening browser for ${connector.type}...`); + log.info(`Opening browser for ${connector.type}...`); const status = await runOAuthFlowWithSkip(connector); outcomes.set(connector.type, status); } catch (err) {