From 36c662be1838f16292cc96a3a41a8aff9f2a2d22 Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Mon, 20 Oct 2025 19:27:43 +0100 Subject: [PATCH 1/3] perf: switch to clack spinner This is an incremental change as part of the wider move to clack. --- packages/astro/package.json | 2 +- packages/astro/src/cli/add/index.ts | 24 ++++++++++-------- packages/astro/src/cli/install-package.ts | 9 ++++--- pnpm-lock.yaml | 31 +++++++++++++++-------- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/packages/astro/package.json b/packages/astro/package.json index 41aab79c95ef..e9d0450ef5ec 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -111,6 +111,7 @@ "@astrojs/markdown-remark": "workspace:*", "@astrojs/telemetry": "workspace:*", "@capsizecss/unpack": "^3.0.0", + "@clack/prompts": "1.0.0-alpha.6", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.2.0", "acorn": "^8.15.0", @@ -164,7 +165,6 @@ "vitefu": "^1.1.1", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", - "yocto-spinner": "^0.2.3", "zod": "^3.25.76", "zod-to-json-schema": "^3.24.6", "zod-to-ts": "^1.2.0" diff --git a/packages/astro/src/cli/add/index.ts b/packages/astro/src/cli/add/index.ts index fbdbfef18b7a..b5adf70ac539 100644 --- a/packages/astro/src/cli/add/index.ts +++ b/packages/astro/src/cli/add/index.ts @@ -10,7 +10,7 @@ import { detect, resolveCommand } from 'package-manager-detector'; import prompts from 'prompts'; import maxSatisfying from 'semver/ranges/max-satisfying.js'; import type yargsParser from 'yargs-parser'; -import yoctoSpinner from 'yocto-spinner'; +import * as clack from '@clack/prompts'; import { loadTSConfig, resolveConfig, @@ -689,7 +689,8 @@ async function tryToInstallIntegrations({ ); if (await askToContinue({ flags })) { - const spinner = yoctoSpinner({ text: 'Installing dependencies...' }).start(); + const spinner = clack.spinner(); + spinner.start('Installing dependencies...'); try { await exec(installCommand.command, [...installCommand.args, ...installSpecifiers], { nodeOptions: { @@ -698,10 +699,10 @@ async function tryToInstallIntegrations({ env: { NODE_ENV: undefined }, }, }); - spinner.success(); + spinner.stop(); return UpdateResult.updated; } catch (err: any) { - spinner.error(); + spinner.stop(undefined, 2); logger.debug('add', 'Error installing dependencies', err); // NOTE: `err.stdout` can be an empty string, so log the full error instead for a more helpful log console.error('\n', err.stdout || err.message, '\n'); @@ -716,7 +717,8 @@ async function validateIntegrations( integrations: string[], flags: yargsParser.Arguments, ): Promise { - const spinner = yoctoSpinner({ text: 'Resolving packages...' }).start(); + const spinner = clack.spinner(); + spinner.start('Resolving packages...'); try { const integrationEntries = await Promise.all( integrations.map(async (integration): Promise => { @@ -734,9 +736,9 @@ async function validateIntegrations( const firstPartyPkgCheck = await fetchPackageJson('@astrojs', name, tag); if (firstPartyPkgCheck instanceof Error) { if (firstPartyPkgCheck.message) { - spinner.warning(yellow(firstPartyPkgCheck.message)); + spinner.message(yellow(firstPartyPkgCheck.message)); } - spinner.warning(yellow(`${bold(integration)} is not an official Astro package.`)); + spinner.message(yellow(`${bold(integration)} is not an official Astro package.`)); if (!(await askToContinue({ flags }))) { throw new Error( `No problem! Find our official integrations at ${cyan( @@ -744,7 +746,7 @@ async function validateIntegrations( )}`, ); } - spinner.start('Resolving with third party packages...'); + spinner.message('Resolving with third party packages...'); pkgType = 'third-party'; } else { pkgType = 'first-party'; @@ -755,7 +757,7 @@ async function validateIntegrations( const thirdPartyPkgCheck = await fetchPackageJson(scope, name, tag); if (thirdPartyPkgCheck instanceof Error) { if (thirdPartyPkgCheck.message) { - spinner.warning(yellow(thirdPartyPkgCheck.message)); + spinner.message(yellow(thirdPartyPkgCheck.message)); } throw new Error(`Unable to fetch ${bold(integration)}. Does the package exist?`); } else { @@ -813,11 +815,11 @@ async function validateIntegrations( }; }), ); - spinner.success(); + spinner.stop(); return integrationEntries; } catch (e) { if (e instanceof Error) { - spinner.error(e.message); + spinner.stop(e.message, 2); process.exit(1); } else { throw e; diff --git a/packages/astro/src/cli/install-package.ts b/packages/astro/src/cli/install-package.ts index 3c931b3e1849..e535bfb688dd 100644 --- a/packages/astro/src/cli/install-package.ts +++ b/packages/astro/src/cli/install-package.ts @@ -4,7 +4,7 @@ import ci from 'ci-info'; import { bold, cyan, dim, magenta } from 'kleur/colors'; import { detect, resolveCommand } from 'package-manager-detector'; import prompts from 'prompts'; -import yoctoSpinner from 'yocto-spinner'; +import * as clack from '@clack/prompts'; import type { Logger } from '../core/logger/core.js'; import { exec } from './exec.js'; @@ -102,7 +102,8 @@ async function installPackage( } if (Boolean(response)) { - const spinner = yoctoSpinner({ text: 'Installing dependencies...' }).start(); + const spinner = clack.spinner(); + spinner.start('Installing dependencies...'); try { await exec(installCommand.command, [...installCommand.args, ...packageNames], { nodeOptions: { @@ -111,12 +112,12 @@ async function installPackage( env: { NODE_ENV: undefined }, }, }); - spinner.success(); + spinner.stop(); return true; } catch (err) { logger.debug('add', 'Error installing dependencies', err); - spinner.error(); + spinner.stop(undefined, 2); return false; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 494761104895..6aef8c0c0481 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -485,6 +485,9 @@ importers: '@capsizecss/unpack': specifier: ^3.0.0 version: 3.0.0 + '@clack/prompts': + specifier: 1.0.0-alpha.6 + version: 1.0.0-alpha.6 '@oslojs/encoding': specifier: ^1.1.0 version: 1.1.0 @@ -644,9 +647,6 @@ importers: yargs-parser: specifier: ^21.1.1 version: 21.1.1 - yocto-spinner: - specifier: ^0.2.3 - version: 0.2.3 zod: specifier: ^3.25.76 version: 3.25.76 @@ -6907,11 +6907,17 @@ packages: '@clack/core@0.3.5': resolution: {integrity: sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ==} + '@clack/core@1.0.0-alpha.6': + resolution: {integrity: sha512-eG5P45+oShFG17u9I1DJzLkXYB1hpUgTLi32EfsMjSHLEqJUR8BOBCVFkdbUX2g08eh/HCi6UxNGpPhaac1LAA==} + '@clack/prompts@0.7.0': resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} bundledDependencies: - is-unicode-supported + '@clack/prompts@1.0.0-alpha.6': + resolution: {integrity: sha512-75NCtYOgDHVBE2nLdKPTDYOaESxO0GLAKC7INREp5VbS988Xua1u+588VaGlcvXiLc/kSwc25Cd+4PeTSpY6QQ==} + '@cloudflare/kv-asset-handler@0.4.0': resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} engines: {node: '>=18.0.0'} @@ -14307,10 +14313,6 @@ packages: resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} engines: {node: '>=12.20'} - yocto-spinner@0.2.3: - resolution: {integrity: sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==} - engines: {node: '>=18.19'} - yoctocolors@2.1.2: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} @@ -14916,12 +14918,23 @@ snapshots: picocolors: 1.1.1 sisteransi: 1.0.5 + '@clack/core@1.0.0-alpha.6': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + '@clack/prompts@0.7.0': dependencies: '@clack/core': 0.3.5 picocolors: 1.1.1 sisteransi: 1.0.5 + '@clack/prompts@1.0.0-alpha.6': + dependencies: + '@clack/core': 1.0.0-alpha.6 + picocolors: 1.1.1 + sisteransi: 1.0.5 + '@cloudflare/kv-asset-handler@0.4.0': dependencies: mime: 3.0.0 @@ -22852,10 +22865,6 @@ snapshots: yocto-queue@1.2.1: {} - yocto-spinner@0.2.3: - dependencies: - yoctocolors: 2.1.2 - yoctocolors@2.1.2: {} youch@3.3.4: From 81e59be6b24d4cfc91026b3f839110be85d38d6b Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Mon, 20 Oct 2025 19:34:26 +0100 Subject: [PATCH 2/3] perf: switch to clack for box rendering Switches to using clack for rendering boxes in the terminal. Part of the wider migration to clack. --- packages/astro/package.json | 1 - packages/astro/src/cli/add/index.ts | 53 +++++++--------- packages/astro/src/cli/install-package.ts | 13 ++-- pnpm-lock.yaml | 76 ----------------------- 4 files changed, 27 insertions(+), 116 deletions(-) diff --git a/packages/astro/package.json b/packages/astro/package.json index e9d0450ef5ec..786bf5382d57 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -117,7 +117,6 @@ "acorn": "^8.15.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", - "boxen": "8.0.1", "ci-info": "^4.3.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", diff --git a/packages/astro/src/cli/add/index.ts b/packages/astro/src/cli/add/index.ts index b5adf70ac539..f06d3ca1d492 100644 --- a/packages/astro/src/cli/add/index.ts +++ b/packages/astro/src/cli/add/index.ts @@ -1,7 +1,7 @@ import fsMod, { existsSync, promises as fs } from 'node:fs'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; -import boxen from 'boxen'; +import * as clack from '@clack/prompts'; import { diffWords } from 'diff'; import { bold, cyan, dim, green, magenta, red, yellow } from 'kleur/colors'; import { type ASTNode, builders, generateCode, loadFile, type ProxifiedModule } from 'magicast'; @@ -10,7 +10,6 @@ import { detect, resolveCommand } from 'package-manager-detector'; import prompts from 'prompts'; import maxSatisfying from 'semver/ranges/max-satisfying.js'; import type yargsParser from 'yargs-parser'; -import * as clack from '@clack/prompts'; import { loadTSConfig, resolveConfig, @@ -363,19 +362,19 @@ export async function add(names: string[], { flags }: AddOptions) { ), ); if (integrations.find((integration) => integration.integrationName === 'tailwind')) { - const code = boxen(getDiffContent('---\n---', "---\nimport '../styles/global.css'\n---")!, { - margin: 0.5, - padding: 0.5, - borderStyle: 'round', - title: 'src/layouts/Layout.astro', - }); logger.warn( 'SKIP_FORMAT', msg.actionRequired( 'You must import your Tailwind stylesheet, e.g. in a shared layout:\n', ), ); - logger.info('SKIP_FORMAT', code + '\n'); + clack.box( + getDiffContent('---\n---', "---\nimport '../styles/global.css'\n---")!, + 'src/layouts/Layout.astro', + { + rounded: true, + }, + ); } } } @@ -561,18 +560,15 @@ async function updateAstroConfig({ return UpdateResult.none; } - const message = `\n${boxen(diff, { - margin: 0.5, - padding: 0.5, - borderStyle: 'round', - title: configURL.pathname.split('/').pop(), - })}\n`; - logger.info( 'SKIP_FORMAT', - `\n ${magenta('Astro will make the following changes to your config file:')}\n${message}`, + `\n ${magenta('Astro will make the following changes to your config file:')}`, ); + clack.box(diff, configURL.pathname.split('/').pop(), { + rounded: true, + }); + if (logAdapterInstructions) { logger.info( 'SKIP_FORMAT', @@ -676,17 +672,15 @@ async function tryToInstallIntegrations({ ); const coloredOutput = `${bold(installCommand.command)} ${installCommand.args.join(' ')} ${cyan(installSpecifiers.join(' '))}`; - const message = `\n${boxen(coloredOutput, { - margin: 0.5, - padding: 0.5, - borderStyle: 'round', - })}\n`; logger.info( 'SKIP_FORMAT', `\n ${magenta('Astro will run the following command:')}\n ${dim( 'If you skip this step, you can always run it yourself later', - )}\n${message}`, + )}`, ); + clack.box(coloredOutput, undefined, { + rounded: true, + }); if (await askToContinue({ flags })) { const spinner = clack.spinner(); @@ -874,18 +868,15 @@ async function updateTSConfig( return UpdateResult.none; } - const message = `\n${boxen(diff, { - margin: 0.5, - padding: 0.5, - borderStyle: 'round', - title: configFileName, - })}\n`; - logger.info( 'SKIP_FORMAT', - `\n ${magenta(`Astro will make the following changes to your ${configFileName}:`)}\n${message}`, + `\n ${magenta(`Astro will make the following changes to your ${configFileName}:`)}`, ); + clack.box(diff, configFileName, { + rounded: true, + }); + // Every major framework, apart from Vue and Svelte requires different `jsxImportSource`, as such it's impossible to config // all of them in the same `tsconfig.json`. However, Vue only need `"jsx": "preserve"` for template intellisense which // can be compatible with some frameworks (ex: Solid) diff --git a/packages/astro/src/cli/install-package.ts b/packages/astro/src/cli/install-package.ts index e535bfb688dd..9d738d92a975 100644 --- a/packages/astro/src/cli/install-package.ts +++ b/packages/astro/src/cli/install-package.ts @@ -1,10 +1,9 @@ import { createRequire } from 'node:module'; -import boxen from 'boxen'; +import * as clack from '@clack/prompts'; import ci from 'ci-info'; import { bold, cyan, dim, magenta } from 'kleur/colors'; import { detect, resolveCommand } from 'package-manager-detector'; import prompts from 'prompts'; -import * as clack from '@clack/prompts'; import type { Logger } from '../core/logger/core.js'; import { exec } from './exec.js'; @@ -75,17 +74,15 @@ async function installPackage( packageNames = packageNames.map((name) => `npm:${name}`); } const coloredOutput = `${bold(installCommand.command)} ${installCommand.args.join(' ')} ${cyan(packageNames.join(' '))}`; - const message = `\n${boxen(coloredOutput, { - margin: 0.5, - padding: 0.5, - borderStyle: 'round', - })}\n`; logger.info( 'SKIP_FORMAT', `\n ${magenta('Astro will run the following command:')}\n ${dim( 'If you skip this step, you can always run it yourself later', - )}\n${message}`, + )}`, ); + clack.box(coloredOutput, undefined, { + rounded: true, + }); let response; if (options.skipAsk) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6aef8c0c0481..19e67e2073e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -503,9 +503,6 @@ importers: axobject-query: specifier: ^4.1.0 version: 4.1.0 - boxen: - specifier: 8.0.1 - version: 8.0.1 ci-info: specifier: ^4.3.0 version: 4.3.1 @@ -9588,9 +9585,6 @@ packages: alpinejs@3.15.0: resolution: {integrity: sha512-lpokA5okCF1BKh10LG8YjqhfpxyHBk4gE7boIgVHltJzYoM7O9nK3M7VlntLEJGsVmu7U/RzUWajmHREGT38Eg==} - ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -9785,10 +9779,6 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - boxen@8.0.1: - resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} - engines: {node: '>=18'} - brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -9857,10 +9847,6 @@ packages: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - camelcase@8.0.0: - resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} - engines: {node: '>=16'} - caniuse-lite@1.0.30001741: resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==} @@ -9930,10 +9916,6 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - cli-boxes@3.0.0: - resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} - engines: {node: '>=10'} - cli-cursor@4.0.0: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -10508,9 +10490,6 @@ packages: emmet@2.4.11: resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==} - emoji-regex@10.5.0: - resolution: {integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -10969,10 +10948,6 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.3.1: - resolution: {integrity: sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==} - engines: {node: '>=18'} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -13287,10 +13262,6 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -14161,10 +14132,6 @@ packages: wicked-good-xpath@1.3.0: resolution: {integrity: sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==} - widest-line@5.0.0: - resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} - engines: {node: '>=18'} - winston-transport@4.9.0: resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} engines: {node: '>= 12.0.0'} @@ -14204,10 +14171,6 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -17487,10 +17450,6 @@ snapshots: dependencies: '@vue/reactivity': 3.1.5 - ansi-align@3.0.1: - dependencies: - string-width: 4.2.3 - ansi-colors@4.1.3: {} ansi-escapes@5.0.0: @@ -17718,17 +17677,6 @@ snapshots: boolbase@1.0.0: {} - boxen@8.0.1: - dependencies: - ansi-align: 3.0.1 - camelcase: 8.0.0 - chalk: 5.6.2 - cli-boxes: 3.0.0 - string-width: 7.2.0 - type-fest: 4.41.0 - widest-line: 5.0.0 - wrap-ansi: 9.0.2 - brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -17795,8 +17743,6 @@ snapshots: camelcase@5.3.1: {} - camelcase@8.0.0: {} - caniuse-lite@1.0.30001741: {} canvas-confetti@1.9.3: {} @@ -17869,8 +17815,6 @@ snapshots: dependencies: consola: 3.4.2 - cli-boxes@3.0.0: {} - cli-cursor@4.0.0: dependencies: restore-cursor: 4.0.0 @@ -18296,8 +18240,6 @@ snapshots: '@emmetio/abbreviation': 2.3.3 '@emmetio/css-abbreviation': 2.1.8 - emoji-regex@10.5.0: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -18913,8 +18855,6 @@ snapshots: get-caller-file@2.0.5: {} - get-east-asian-width@1.3.1: {} - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -21862,12 +21802,6 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.2 - string-width@7.2.0: - dependencies: - emoji-regex: 10.5.0 - get-east-asian-width: 1.3.1 - strip-ansi: 7.1.2 - string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -22693,10 +22627,6 @@ snapshots: wicked-good-xpath@1.3.0: {} - widest-line@5.0.0: - dependencies: - string-width: 7.2.0 - winston-transport@4.9.0: dependencies: logform: 2.7.0 @@ -22763,12 +22693,6 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.2 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.1.2 - wrappy@1.0.2: {} write-file-atomic@5.0.1: From d82cfa1b58736dd6c450fe7569ab13dd27179a81 Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Mon, 20 Oct 2025 19:40:43 +0100 Subject: [PATCH 3/3] perf: switch to clack for confirm prompts Switches to using clack for confirm prompts rather than `prompts` package. Part of the wider clack migration. --- packages/astro/package.json | 2 - packages/astro/src/cli/add/index.ts | 9 ++--- packages/astro/src/cli/info/index.ts | 10 ++--- packages/astro/src/cli/install-package.ts | 12 ++---- packages/db/package.json | 3 +- .../db/src/core/cli/commands/push/index.ts | 10 ++--- pnpm-lock.yaml | 38 ++----------------- 7 files changed, 19 insertions(+), 65 deletions(-) diff --git a/packages/astro/package.json b/packages/astro/package.json index 786bf5382d57..a5fea940df68 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -147,7 +147,6 @@ "p-queue": "^8.1.0", "package-manager-detector": "^1.3.0", "picomatch": "^4.0.3", - "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.2", "shiki": "^3.12.0", @@ -185,7 +184,6 @@ "@types/http-cache-semantics": "^4.0.4", "@types/js-yaml": "^4.0.9", "@types/picomatch": "^3.0.2", - "@types/prompts": "^2.4.9", "@types/semver": "^7.7.0", "@types/yargs-parser": "^21.0.3", "astro-scripts": "workspace:*", diff --git a/packages/astro/src/cli/add/index.ts b/packages/astro/src/cli/add/index.ts index f06d3ca1d492..d56b1ff214ea 100644 --- a/packages/astro/src/cli/add/index.ts +++ b/packages/astro/src/cli/add/index.ts @@ -7,7 +7,6 @@ import { bold, cyan, dim, green, magenta, red, yellow } from 'kleur/colors'; import { type ASTNode, builders, generateCode, loadFile, type ProxifiedModule } from 'magicast'; import { getDefaultExportOptions } from 'magicast/helpers'; import { detect, resolveCommand } from 'package-manager-detector'; -import prompts from 'prompts'; import maxSatisfying from 'semver/ranges/max-satisfying.js'; import type yargsParser from 'yargs-parser'; import { @@ -928,14 +927,12 @@ function parseIntegrationName(spec: string) { async function askToContinue({ flags }: { flags: Flags }): Promise { if (flags.yes || flags.y) return true; - const response = await prompts({ - type: 'confirm', - name: 'askToContinue', + const response = await clack.confirm({ message: 'Continue?', - initial: true, + initialValue: true, }); - return Boolean(response.askToContinue); + return response === true; } function getDiffContent(input: string, output: string): string | null { diff --git a/packages/astro/src/cli/info/index.ts b/packages/astro/src/cli/info/index.ts index 50476df4221f..d9717168b318 100644 --- a/packages/astro/src/cli/info/index.ts +++ b/packages/astro/src/cli/info/index.ts @@ -1,7 +1,7 @@ import { spawn, spawnSync } from 'node:child_process'; import { arch, platform } from 'node:os'; +import * as clack from '@clack/prompts'; import * as colors from 'kleur/colors'; -import prompts from 'prompts'; import { resolveConfig } from '../../core/config/index.js'; import { ASTRO_VERSION } from '../../core/constants.js'; import { apply as applyPolyfill } from '../../core/polyfill.js'; @@ -124,14 +124,12 @@ async function copyToClipboard(text: string, force?: boolean) { } if (!force) { - const { shouldCopy } = await prompts({ - type: 'confirm', - name: 'shouldCopy', + const shouldCopy = await clack.confirm({ message: 'Copy to clipboard?', - initial: true, + initialValue: true, }); - if (!shouldCopy) return; + if (shouldCopy !== true) return; } try { diff --git a/packages/astro/src/cli/install-package.ts b/packages/astro/src/cli/install-package.ts index 9d738d92a975..129083200ea2 100644 --- a/packages/astro/src/cli/install-package.ts +++ b/packages/astro/src/cli/install-package.ts @@ -3,7 +3,6 @@ import * as clack from '@clack/prompts'; import ci from 'ci-info'; import { bold, cyan, dim, magenta } from 'kleur/colors'; import { detect, resolveCommand } from 'package-manager-detector'; -import prompts from 'prompts'; import type { Logger } from '../core/logger/core.js'; import { exec } from './exec.js'; @@ -88,14 +87,11 @@ async function installPackage( if (options.skipAsk) { response = true; } else { - response = ( - await prompts({ - type: 'confirm', - name: 'askToContinue', + response = + (await clack.confirm({ message: 'Continue?', - initial: true, - }) - ).askToContinue; + initialValue: true, + })) === true; } if (Boolean(response)) { diff --git a/packages/db/package.json b/packages/db/package.json index d1eabd4950a6..8a9db90acdda 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -72,18 +72,17 @@ "test:types": "tsc --project test/types/tsconfig.json" }, "dependencies": { + "@clack/prompts": "1.0.0-alpha.6", "@libsql/client": "^0.15.15", "deep-diff": "^1.0.2", "drizzle-orm": "^0.42.0", "kleur": "^4.1.5", "nanoid": "^5.1.6", - "prompts": "^2.4.2", "yargs-parser": "^21.1.1", "zod": "^3.25.76" }, "devDependencies": { "@types/deep-diff": "^1.0.5", - "@types/prompts": "^2.4.9", "@types/yargs-parser": "^21.0.3", "astro": "workspace:*", "astro-scripts": "workspace:*", diff --git a/packages/db/src/core/cli/commands/push/index.ts b/packages/db/src/core/cli/commands/push/index.ts index 663b648119cf..e341134b2a7c 100644 --- a/packages/db/src/core/cli/commands/push/index.ts +++ b/packages/db/src/core/cli/commands/push/index.ts @@ -1,6 +1,6 @@ +import * as clack from '@clack/prompts'; import type { AstroConfig } from 'astro'; import { sql } from 'drizzle-orm'; -import prompts from 'prompts'; import type { Arguments } from 'yargs-parser'; import { MIGRATION_VERSION } from '../../../consts.js'; import { createClient } from '../../../db-client/libsql-node.js'; @@ -42,14 +42,12 @@ export async function cmd({ } if (isForceReset) { - const { begin } = await prompts({ - type: 'confirm', - name: 'begin', + const begin = await clack.confirm({ message: `Reset your database? All of your data will be erased and your schema created from scratch.`, - initial: false, + initialValue: false, }); - if (!begin) { + if (begin !== true) { console.log('Canceled.'); process.exit(0); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19e67e2073e8..56881c7a83f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -593,9 +593,6 @@ importers: picomatch: specifier: ^4.0.3 version: 4.0.3 - prompts: - specifier: ^2.4.2 - version: 2.4.2 rehype: specifier: ^13.0.2 version: 13.0.2 @@ -693,9 +690,6 @@ importers: '@types/picomatch': specifier: ^3.0.2 version: 3.0.2 - '@types/prompts': - specifier: ^2.4.9 - version: 2.4.9 '@types/semver': specifier: ^7.7.0 version: 7.7.1 @@ -4546,6 +4540,9 @@ importers: packages/db: dependencies: + '@clack/prompts': + specifier: 1.0.0-alpha.6 + version: 1.0.0-alpha.6 '@libsql/client': specifier: ^0.15.15 version: 0.15.15 @@ -4561,9 +4558,6 @@ importers: nanoid: specifier: ^5.1.6 version: 5.1.6 - prompts: - specifier: ^2.4.2 - version: 2.4.2 yargs-parser: specifier: ^21.1.1 version: 21.1.1 @@ -4574,9 +4568,6 @@ importers: '@types/deep-diff': specifier: ^1.0.5 version: 1.0.5 - '@types/prompts': - specifier: ^2.4.9 - version: 2.4.9 '@types/yargs-parser': specifier: ^21.0.3 version: 21.0.3 @@ -9177,9 +9168,6 @@ packages: '@types/prismjs@1.26.5': resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} - '@types/prompts@2.4.9': - resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==} - '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} @@ -11446,10 +11434,6 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -12693,10 +12677,6 @@ packages: promise-limit@2.7.0: resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==} - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -16890,11 +16870,6 @@ snapshots: '@types/prismjs@1.26.5': {} - '@types/prompts@2.4.9': - dependencies: - '@types/node': 18.19.124 - kleur: 3.0.3 - '@types/prop-types@15.7.15': {} '@types/react-dom@18.3.7(@types/react@18.3.26)': @@ -19448,8 +19423,6 @@ snapshots: dependencies: json-buffer: 3.0.1 - kleur@3.0.3: {} - kleur@4.1.5: {} knip@5.61.3(@types/node@18.19.124)(typescript@5.9.3): @@ -21004,11 +20977,6 @@ snapshots: promise-limit@2.7.0: {} - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - property-information@6.5.0: {} property-information@7.1.0: {}