From 5306c3c38f50a68d17c1ec545a9305da74a4790c Mon Sep 17 00:00:00 2001 From: evan Date: Wed, 12 Aug 2026 16:24:14 -0500 Subject: [PATCH] fix(core): collect fields when reusing setup token --- packages/core/src/setup-helpers.test.ts | 35 +++++++++++++++++++++++++ packages/core/src/setup-helpers.ts | 26 +++++++++--------- 2 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 packages/core/src/setup-helpers.test.ts diff --git a/packages/core/src/setup-helpers.test.ts b/packages/core/src/setup-helpers.test.ts new file mode 100644 index 00000000..7618d1e0 --- /dev/null +++ b/packages/core/src/setup-helpers.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it, vi } from 'vitest'; +import { tokenSetup } from './setup-helpers.js'; + +describe('tokenSetup', () => { + it('collects required config fields when reusing an existing token', async () => { + const prompt = vi.fn() + .mockResolvedValueOnce(true) + .mockResolvedValueOnce('-1001234567890'); + const setup = tokenSetup<{ chatId: string }>({ + secretKey: 'TELEGRAM_BOT_TOKEN', + label: 'Telegram', + steps: [], + fields: [ + { key: 'chatId', message: 'Chat ID:', required: true }, + ], + }); + + const result = await setup({ + secret: () => 'existing-token', + setSecret: vi.fn(), + prompt, + open: vi.fn(), + log: vi.fn(), + run: vi.fn(), + platform: process.platform, + env: process.env, + }); + + expect(result).toEqual({ ok: true, config: { chatId: '-1001234567890' } }); + expect(prompt).toHaveBeenNthCalledWith(2, { + type: 'text', + message: 'Chat ID:', + }); + }); +}); diff --git a/packages/core/src/setup-helpers.ts b/packages/core/src/setup-helpers.ts index 09aea2b4..88e017f7 100644 --- a/packages/core/src/setup-helpers.ts +++ b/packages/core/src/setup-helpers.ts @@ -157,28 +157,30 @@ export interface TokenSetupOpts { export function tokenSetup(opts: TokenSetupOpts): SetupFn { return async (ctx) => { const existing = ctx.secret(opts.secretKey); + let reuseExisting = false; if (existing) { - const reuse = await ctx.prompt({ + reuseExisting = await ctx.prompt({ type: 'confirm', message: `${opts.secretKey} already in vault — reuse it?`, initial: true, }); - if (reuse) return { ok: true, config: (opts.config ?? {}) as C }; } - ctx.log(`${opts.label} setup:`); - for (const line of opts.steps) ctx.log(` ${line}`); - if (opts.vendorDocUrl) await ctx.open(opts.vendorDocUrl); + if (!reuseExisting) { + ctx.log(`${opts.label} setup:`); + for (const line of opts.steps) ctx.log(` ${line}`); + if (opts.vendorDocUrl) await ctx.open(opts.vendorDocUrl); - const token = await ctx.prompt({ - type: 'password', - message: `Paste the ${opts.label} API token:`, - }); + const token = await ctx.prompt({ + type: 'password', + message: `Paste the ${opts.label} API token:`, + }); - if (!token) { - return { ok: false, config: (opts.config ?? {}) as C, manual: opts.steps }; + if (!token) { + return { ok: false, config: (opts.config ?? {}) as C, manual: opts.steps }; + } + await ctx.setSecret(opts.secretKey, token); } - await ctx.setSecret(opts.secretKey, token); const configExtras: Record = {}; for (const field of opts.fields ?? []) {