diff --git a/package.json b/package.json index a934eb508708..98e7d3a89053 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "jest": "29.7.0", "jscodeshift": "17.0.0", "lerna": "8.1.9", - "listr2": "6.6.1", + "listr2": "7.0.2", "make-dir-cli": "4.0.0", "msw": "1.3.4", "ncp": "2.0.0", diff --git a/packages/cli-helpers/package.json b/packages/cli-helpers/package.json index aa12f613dc8b..5ea781262c8b 100644 --- a/packages/cli-helpers/package.json +++ b/packages/cli-helpers/package.json @@ -62,7 +62,7 @@ "dotenv": "16.4.7", "dotenv-defaults": "5.0.2", "execa": "5.1.1", - "listr2": "6.6.1", + "listr2": "7.0.2", "lodash": "4.17.21", "pascalcase": "1.0.0", "prettier": "3.4.2", diff --git a/packages/cli-helpers/src/auth/authTasks.ts b/packages/cli-helpers/src/auth/authTasks.ts index b81e3122570b..b27a1871b049 100644 --- a/packages/cli-helpers/src/auth/authTasks.ts +++ b/packages/cli-helpers/src/auth/authTasks.ts @@ -1,6 +1,7 @@ import fs from 'fs' import path from 'path' +import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import type { ListrRenderer, ListrTask, ListrTaskWrapper } from 'listr2' import { getConfig, resolveFile } from '@redwoodjs/project-config' @@ -467,7 +468,8 @@ export const generateAuthApiFiles = ( // Confirm that we're about to overwrite some files const filesToOverwrite = findExistingFiles(filesRecord) - const overwrite = await task.prompt({ + const prompt = task.prompt(ListrEnquirerPromptAdapter) + const overwrite = await prompt.run({ type: 'confirm', message: `Overwrite existing ${filesToOverwrite.join(', ')}?`, initial: false, @@ -492,22 +494,24 @@ export const generateAuthApiFiles = ( }, } } -/** - * Returns a map of file names (not full paths) that already exist - */ + +/** Returns a map of file names (not full paths) that already exist */ function findExistingFiles(filesMap: Record) { return Object.keys(filesMap) .filter((filePath) => fs.existsSync(filePath)) .map((filePath) => filePath.replace(getPaths().base, '')) } -export const addAuthConfigToGqlApi = ( +export const addAuthConfigToGqlApi = < + Renderer extends typeof ListrRenderer, + FallbackRenderer extends typeof ListrRenderer, +>( authDecoderImport?: string, ) => ({ title: 'Adding auth config to GraphQL API...', task: ( ctx: AuthGeneratorCtx, - _task: ListrTaskWrapper, + _task: ListrTaskWrapper, ) => { if (graphFunctionDoesExist()) { addApiConfig({ @@ -535,14 +539,17 @@ export interface AuthGeneratorCtx { force: boolean } -export const setAuthSetupMode = ( +export const setAuthSetupMode = < + Renderer extends typeof ListrRenderer, + FallbackRenderer extends typeof ListrRenderer, +>( force: boolean, ) => { return { title: 'Checking project for existing auth...', task: async ( ctx: AuthGeneratorCtx, - task: ListrTaskWrapper, + task: ListrTaskWrapper, ) => { if (force) { ctx.setupMode = 'FORCE' diff --git a/packages/cli-helpers/src/lib/index.ts b/packages/cli-helpers/src/lib/index.ts index e9232e5bb5bb..3fd0158173f0 100644 --- a/packages/cli-helpers/src/lib/index.ts +++ b/packages/cli-helpers/src/lib/index.ts @@ -106,8 +106,9 @@ export const writeFile = ( { existingFiles = 'FAIL' }: { existingFiles?: ExistingFiles } = {}, // TODO: Remove type cast by finding all places `writeFile` is used and // making sure a proper task is passed in - task: ListrTaskWrapper = {} as ListrTaskWrapper< + task: ListrTaskWrapper = {} as ListrTaskWrapper< never, + Renderer, Renderer >, ) => { @@ -152,6 +153,7 @@ export const writeFilesTask = ( _ctx: never, task: ListrTaskWrapper< never, + ListrGetRendererClassFromValue, ListrGetRendererClassFromValue >, ) => { diff --git a/packages/cli-packages/dataMigrate/package.json b/packages/cli-packages/dataMigrate/package.json index 346e5660199d..12eead2cd5db 100644 --- a/packages/cli-packages/dataMigrate/package.json +++ b/packages/cli-packages/dataMigrate/package.json @@ -31,7 +31,7 @@ "dotenv-defaults": "5.0.2", "execa": "5.1.1", "fs-extra": "11.2.0", - "listr2": "6.6.1", + "listr2": "7.0.2", "terminal-link": "2.1.1", "yargs": "17.7.2" }, diff --git a/packages/cli/package.json b/packages/cli/package.json index e03b6da87036..9a1fbfb17d8d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@babel/runtime-corejs3": "7.25.7", + "@listr2/prompt-adapter-enquirer": "2.0.12", "@opentelemetry/api": "1.8.0", "@opentelemetry/core": "1.22.0", "@opentelemetry/exporter-trace-otlp-http": "0.49.1", @@ -64,7 +65,7 @@ "humanize-string": "2.1.0", "jscodeshift": "17.0.0", "latest-version": "5.1.0", - "listr2": "6.6.1", + "listr2": "7.0.2", "lodash": "4.17.21", "pascalcase": "1.0.0", "pluralize": "8.0.0", diff --git a/packages/cli/src/__tests__/Listr2Mock.ts b/packages/cli/src/__tests__/Listr2Mock.ts index 805b93a6e969..0365162b0fca 100644 --- a/packages/cli/src/__tests__/Listr2Mock.ts +++ b/packages/cli/src/__tests__/Listr2Mock.ts @@ -8,7 +8,11 @@ type EnquirerPromptOptions = Parameters[0] type Function = { length: number; name: string } type PlainPromptOptions = ReturnType> type ListrPromptOptions = Parameters< - Listr.ListrTaskWrapper['prompt'] + Listr.ListrTaskWrapper< + Ctx, + typeof Listr.ListrRenderer, + typeof Listr.ListrRenderer + >['prompt'] >[0] function isSupportedOptionsType( @@ -75,9 +79,10 @@ class Listr2TaskWrapper { ctx, // TODO: fix this by removing the type casts. // The reason we have to do this is because of private fields in - // Listr.ListrTaskWrapper + // Listr.ListrTaskWrapper (this was at least the case for Listr2 v6) task as unknown as Listr.ListrTaskWrapper< Ctx, + typeof Listr.ListrRenderer, typeof Listr.ListrRenderer >, ) @@ -86,7 +91,7 @@ class Listr2TaskWrapper { async prompt(options: ListrPromptOptions) { const enquirer = Listr2Mock.mockPrompt ? { prompt: Listr2Mock.mockPrompt } - : this.listrOptions?.injectWrapper?.enquirer + : this.listrOptions?.ctx?.enquirer if (!enquirer) { throw new Error('Enquirer instance not available') diff --git a/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js b/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js index 88885f472fcb..bf95532bfdc0 100644 --- a/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js +++ b/packages/cli/src/commands/experimental/setupOpentelemetryHandler.js @@ -1,5 +1,6 @@ import path from 'path' +import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import execa from 'execa' import fs from 'fs-extra' import { Listr } from 'listr2' @@ -103,7 +104,7 @@ export const handler = async ({ force, verbose }) => { )}`, ].join('\n') }, - options: { persistentOutput: true }, + rendererOptions: { persistentOutput: true }, }, { title: 'Notice: GraphQL function update (server file)...', @@ -126,7 +127,7 @@ export const handler = async ({ force, verbose }) => { )}`, ].join('\n') }, - options: { persistentOutput: true }, + rendererOptions: { persistentOutput: true }, }, addApiPackages(opentelemetryPackages), ] @@ -193,7 +194,8 @@ export const handler = async ({ force, verbose }) => { { title: 'Confirmation', task: async (_ctx, task) => { - const confirmation = await task.prompt({ + const prompt = task.prompt(ListrEnquirerPromptAdapter) + const confirmation = await prompt.run({ type: 'Confirm', message: 'OpenTelemetry support is experimental. Continue?', }) diff --git a/packages/cli/src/commands/experimental/setupReactCompilerHandler.js b/packages/cli/src/commands/experimental/setupReactCompilerHandler.js index 61cf4bd26fd1..f117184cda7b 100644 --- a/packages/cli/src/commands/experimental/setupReactCompilerHandler.js +++ b/packages/cli/src/commands/experimental/setupReactCompilerHandler.js @@ -84,7 +84,7 @@ export const handler = async ({ force, verbose }) => { } } }, - options: { persistentOutput: true }, + rendererOptions: { persistentOutput: true }, }, // We are using two different yarn commands here which is fine because they're operating on different // workspaces - web and the root diff --git a/packages/cli/src/commands/experimental/setupRscHandler.js b/packages/cli/src/commands/experimental/setupRscHandler.js index 89dd58196971..c7d5e59eb479 100644 --- a/packages/cli/src/commands/experimental/setupRscHandler.js +++ b/packages/cli/src/commands/experimental/setupRscHandler.js @@ -76,7 +76,7 @@ export const handler = async ({ force, verbose }) => { } } }, - options: { persistentOutput: true }, + rendererOptions: { persistentOutput: true }, }, { title: `Overwriting entry.client${ext}...`, diff --git a/packages/cli/src/commands/experimental/setupStreamingSsrHandler.js b/packages/cli/src/commands/experimental/setupStreamingSsrHandler.js index da38fc3858b1..c85bdd7401d2 100644 --- a/packages/cli/src/commands/experimental/setupStreamingSsrHandler.js +++ b/packages/cli/src/commands/experimental/setupStreamingSsrHandler.js @@ -1,5 +1,6 @@ import path from 'path' +import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import fs from 'fs-extra' import { Listr } from 'listr2' @@ -72,7 +73,7 @@ export const handler = async ({ force, verbose }) => { } } }, - options: { persistentOutput: true }, + rendererOptions: { persistentOutput: true }, }, { title: `Adding entry.client${ext}...`, @@ -94,7 +95,8 @@ export const handler = async ({ force, verbose }) => { let overwriteExisting = force if (!force) { - overwriteExisting = await task.prompt({ + const prompt = task.prompt(ListrEnquirerPromptAdapter) + overwriteExisting = await prompt.run({ type: 'Confirm', message: `Overwrite ${entryClientPath}?`, }) @@ -109,7 +111,7 @@ export const handler = async ({ force, verbose }) => { writeFile(entryClientPath, entryClientContent, { overwriteExisting }) }, - options: { persistentOutput: true }, + rendererOptions: { persistentOutput: true }, }, { title: `Adding entry.server${ext}...`, diff --git a/packages/cli/src/commands/generate/dbAuth/dbAuth.js b/packages/cli/src/commands/generate/dbAuth/dbAuth.js index 58ebfbf18600..d6ef1f9100ba 100644 --- a/packages/cli/src/commands/generate/dbAuth/dbAuth.js +++ b/packages/cli/src/commands/generate/dbAuth/dbAuth.js @@ -1,5 +1,6 @@ import path from 'path' +import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import { camelCase } from 'camel-case' import Enquirer from 'enquirer' import execa from 'execa' @@ -286,7 +287,11 @@ const tasks = ({ ) return } - usernameLabel = await subtask.prompt({ + + console.log('subctx', subctx) + + const prompt = subtask.prompt(ListrEnquirerPromptAdapter) + usernameLabel = await prompt.run({ type: 'input', name: 'username', message: 'What would you like the username label to be:', @@ -304,7 +309,8 @@ const tasks = ({ ) return } - passwordLabel = await subtask.prompt({ + const prompt = subtask.prompt(ListrEnquirerPromptAdapter) + passwordLabel = await prompt.run({ type: 'input', name: 'password', message: 'What would you like the password label to be:', @@ -353,10 +359,13 @@ const tasks = ({ return } - const response = await task.prompt({ + const prompt = task.prompt(ListrEnquirerPromptAdapter) + const response = await prompt.run({ type: 'confirm', name: 'answer', - message: `Enable WebAuthn support (TouchID/FaceID) on LoginPage? See https://redwoodjs.com/docs/auth/dbAuth#webAuthn`, + message: + 'Enable WebAuthn support (TouchID/FaceID) on LoginPage? See ' + + 'https://redwoodjs.com/docs/auth/dbAuth#webAuthn', default: false, }) @@ -415,7 +424,7 @@ const tasks = ({ { silentRendererCondition: () => listr2?.silentRendererCondition, rendererOptions: { collapseSubtasks: false }, - injectWrapper: { enquirer: enquirer || new Enquirer() }, + ctx: { enquirer: enquirer || new Enquirer() }, exitOnError: true, }, ) diff --git a/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js b/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js index 710463d8e6f9..e8ce95182058 100644 --- a/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js +++ b/packages/cli/src/commands/setup/ui/libraries/tailwindcss.js @@ -1,5 +1,6 @@ import path from 'path' +import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import execa from 'execa' import fs from 'fs-extra' import { outputFileSync } from 'fs-extra' @@ -252,9 +253,10 @@ export const handler = async ({ force, install }) => { ) }, task: async (_ctx, task) => { + const prompt = task.prompt(ListrEnquirerPromptAdapter) const overrideScaffoldCss = force || - (await task.prompt({ + (await prompt.run({ type: 'Confirm', message: "Do you want to override your 'scaffold.css' to use tailwind classes?", diff --git a/packages/cli/src/commands/upgrade.js b/packages/cli/src/commands/upgrade.js index c628fce0c939..01bdda293c26 100644 --- a/packages/cli/src/commands/upgrade.js +++ b/packages/cli/src/commands/upgrade.js @@ -1,5 +1,6 @@ import path from 'path' +import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer' import execa from 'execa' import fs from 'fs-extra' import latestVersion from 'latest-version' @@ -112,7 +113,8 @@ export const handler = async ({ dryRun, tag, verbose, dedupe, yes }) => { return } - const proceed = await task.prompt({ + const prompt = task.prompt(ListrEnquirerPromptAdapter) + const proceed = await prompt.run({ type: 'Confirm', message: 'This will upgrade your RedwoodJS project to the latest version. Do you want to proceed?', @@ -126,6 +128,7 @@ export const handler = async ({ dryRun, tag, verbose, dedupe, yes }) => { return 'Yes' }, }) + if (!proceed) { task.skip('Upgrade cancelled by user.') process.exit(0) diff --git a/yarn.lock b/yarn.lock index 74a0c0310cc1..0ce8e331b8b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5575,6 +5575,15 @@ __metadata: languageName: node linkType: hard +"@listr2/prompt-adapter-enquirer@npm:2.0.12": + version: 2.0.12 + resolution: "@listr2/prompt-adapter-enquirer@npm:2.0.12" + peerDependencies: + enquirer: ">= 2.3.0 < 3" + checksum: 10c0/53bfaac3b71560f009d94dfb107ed00fb9ea36d17ab1ae57680f330f88656e8a836839bb8cdc85478b4e173fb4d9b863097ab1b5d5912d6f0c6cc906cc311606 + languageName: node + linkType: hard + "@lukeed/ms@npm:^2.0.1": version: 2.0.1 resolution: "@lukeed/ms@npm:2.0.1" @@ -8057,7 +8066,7 @@ __metadata: execa: "npm:5.1.1" fs-extra: "npm:11.2.0" jest: "npm:29.7.0" - listr2: "npm:6.6.1" + listr2: "npm:7.0.2" memfs: "npm:4.15.1" terminal-link: "npm:2.1.1" tsx: "npm:4.19.2" @@ -8087,7 +8096,7 @@ __metadata: dotenv: "npm:16.4.7" dotenv-defaults: "npm:5.0.2" execa: "npm:5.1.1" - listr2: "npm:6.6.1" + listr2: "npm:7.0.2" lodash: "npm:4.17.21" pascalcase: "npm:1.0.0" prettier: "npm:3.4.2" @@ -8130,6 +8139,7 @@ __metadata: "@babel/cli": "npm:7.25.7" "@babel/core": "npm:^7.22.20" "@babel/runtime-corejs3": "npm:7.25.7" + "@listr2/prompt-adapter-enquirer": "npm:2.0.12" "@opentelemetry/api": "npm:1.8.0" "@opentelemetry/core": "npm:1.22.0" "@opentelemetry/exporter-trace-otlp-http": "npm:0.49.1" @@ -8167,7 +8177,7 @@ __metadata: humanize-string: "npm:2.1.0" jscodeshift: "npm:17.0.0" latest-version: "npm:5.1.0" - listr2: "npm:6.6.1" + listr2: "npm:7.0.2" lodash: "npm:4.17.21" memfs: "npm:4.15.1" pascalcase: "npm:1.0.0" @@ -21820,9 +21830,9 @@ __metadata: languageName: node linkType: hard -"listr2@npm:6.6.1": - version: 6.6.1 - resolution: "listr2@npm:6.6.1" +"listr2@npm:7.0.2": + version: 7.0.2 + resolution: "listr2@npm:7.0.2" dependencies: cli-truncate: "npm:^3.1.0" colorette: "npm:^2.0.20" @@ -21830,12 +21840,7 @@ __metadata: log-update: "npm:^5.0.1" rfdc: "npm:^1.3.0" wrap-ansi: "npm:^8.1.0" - peerDependencies: - enquirer: ">= 2.3.0 < 3" - peerDependenciesMeta: - enquirer: - optional: true - checksum: 10c0/2abfcd4346b8208e8d406cfe7a058cd10e3238f60de1ee53fa108a507b45b853ceb87e0d1d4ff229bbf6dd6e896262352e0c7a8895b8511cd55fe94304d3921e + checksum: 10c0/37b6501be84ebea66dcce07c5f86c224aff0c01c9fb43f5055cc38a063030281d58198aad0aad481f174438309831ddf5f763b890e820cd7b7b4f4a5dfa229c9 languageName: node linkType: hard @@ -26977,7 +26982,7 @@ __metadata: jest: "npm:29.7.0" jscodeshift: "npm:17.0.0" lerna: "npm:8.1.9" - listr2: "npm:6.6.1" + listr2: "npm:7.0.2" make-dir-cli: "npm:4.0.0" msw: "npm:1.3.4" ncp: "npm:2.0.0"