Skip to content

Commit

Permalink
Merge branch 'main' into refactor/centralize-chakra-ui-theme-extensio…
Browse files Browse the repository at this point in the history
…n-and-allow-typescript
  • Loading branch information
Philzen authored Dec 29, 2024
2 parents 9b23c2a + 70a6bb8 commit 84d5f21
Show file tree
Hide file tree
Showing 18 changed files with 201 additions and 127 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli-helpers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
23 changes: 15 additions & 8 deletions packages/cli-helpers/src/auth/authTasks.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -467,7 +468,8 @@ export const generateAuthApiFiles = <Renderer extends typeof ListrRenderer>(
// 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<boolean>({
type: 'confirm',
message: `Overwrite existing ${filesToOverwrite.join(', ')}?`,
initial: false,
Expand All @@ -492,22 +494,24 @@ export const generateAuthApiFiles = <Renderer extends typeof ListrRenderer>(
},
}
}
/**
* 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<string, string>) {
return Object.keys(filesMap)
.filter((filePath) => fs.existsSync(filePath))
.map((filePath) => filePath.replace(getPaths().base, ''))
}

export const addAuthConfigToGqlApi = <Renderer extends typeof ListrRenderer>(
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<AuthGeneratorCtx, Renderer>,
_task: ListrTaskWrapper<AuthGeneratorCtx, Renderer, FallbackRenderer>,
) => {
if (graphFunctionDoesExist()) {
addApiConfig({
Expand Down Expand Up @@ -535,14 +539,17 @@ export interface AuthGeneratorCtx {
force: boolean
}

export const setAuthSetupMode = <Renderer extends typeof ListrRenderer>(
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<AuthGeneratorCtx, Renderer>,
task: ListrTaskWrapper<AuthGeneratorCtx, Renderer, FallbackRenderer>,
) => {
if (force) {
ctx.setupMode = 'FORCE'
Expand Down
4 changes: 3 additions & 1 deletion packages/cli-helpers/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ export const writeFile = <Renderer extends typeof ListrRenderer>(
{ 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<never, Renderer> = {} as ListrTaskWrapper<
task: ListrTaskWrapper<never, Renderer, Renderer> = {} as ListrTaskWrapper<
never,
Renderer,
Renderer
>,
) => {
Expand Down Expand Up @@ -152,6 +153,7 @@ export const writeFilesTask = <Renderer extends typeof ListrRenderer>(
_ctx: never,
task: ListrTaskWrapper<
never,
ListrGetRendererClassFromValue<Renderer>,
ListrGetRendererClassFromValue<Renderer>
>,
) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli-packages/dataMigrate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
102 changes: 61 additions & 41 deletions packages/cli/src/__tests__/Listr2Mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import type * as Listr from 'listr2'
import type { vi } from 'vitest'

type Ctx = Record<string, any>
type TRenderer = typeof Listr.ListrRenderer

type EnquirerPromptOptions = Parameters<Enquirer['prompt']>[0]
type Function = { length: number; name: string }
type PlainPromptOptions = ReturnType<Extract<EnquirerPromptOptions, Function>>
type ListrPromptOptions = Parameters<
Listr.ListrTaskWrapper<Ctx, typeof Listr.ListrRenderer>['prompt']
Listr.ListrTaskWrapper<Ctx, TRenderer, TRenderer>['prompt']
>[0]

function isSupportedOptionsType(
Expand All @@ -25,7 +26,7 @@ function isSupportedOptionsType(
}

class Listr2TaskWrapper {
task: Listr.ListrTask<Ctx, typeof Listr.ListrRenderer>
task: Listr.ListrTask<Ctx, TRenderer>
promptOutput: string

// This is part of Listr.TaskWrapper, but we don't need it
Expand All @@ -36,7 +37,7 @@ class Listr2TaskWrapper {
task,
options,
}: {
task: Listr.ListrTask<Ctx, typeof Listr.ListrRenderer>
task: Listr.ListrTask<Ctx, TRenderer>
options?: Record<PropertyKey, any> | undefined
}) {
this.task = task
Expand Down Expand Up @@ -75,56 +76,65 @@ 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
>,
)
}

async prompt<T extends object = any>(options: ListrPromptOptions) {
const enquirer = Listr2Mock.mockPrompt
? { prompt: Listr2Mock.mockPrompt }
: this.listrOptions?.injectWrapper?.enquirer
public prompt(..._args: any[]) {
const ctxEnquirer = this.listrOptions?.ctx?.enquirer

if (!enquirer) {
throw new Error('Enquirer instance not available')
}

if (!isSupportedOptionsType(options)) {
console.error('Unsupported prompt options', options)
throw new Error('Unsupported prompt options type')
}
const run = async <T extends object = any>(options: ListrPromptOptions) => {
const enquirer = Listr2Mock.mockPrompt
? { prompt: Listr2Mock.mockPrompt }
: ctxEnquirer

const enquirerOptions = !Array.isArray(options)
? [{ ...options, name: 'default' }]
: options
if (!enquirer) {
throw new Error('Enquirer instance not available')
}

if (enquirerOptions.length === 1) {
enquirerOptions[0].name = 'default'
}
if (!isSupportedOptionsType(options)) {
console.error('Unsupported prompt options', options)
throw new Error('Unsupported prompt options type')
}

const response = await enquirer.prompt(enquirerOptions)
const enquirerOptions = !Array.isArray(options)
? [{ ...options, name: 'default' }]
: options

if (enquirerOptions.length === 1) {
if (typeof response !== 'object') {
throw new Error(
'Expected an object response from prompt().\n' +
'Make sure you\'re returning `{ default: "value" }` if you\'re ' +
'mocking the prompt return value',
)
if (enquirerOptions.length === 1) {
enquirerOptions[0].name = 'default'
}

if ('default' in response) {
// The type cast here isn't great. But Listr2 itself also type cast
// the response (but they cast it to `any`)
// https://github.com/listr2/listr2/blob/b4f544ebce9582f56b2b42fdbe834d70678ce966/packages/prompt-adapter-enquirer/src/prompt.ts#L74
return response.default as T
const response = await enquirer.prompt(enquirerOptions)

if (enquirerOptions.length === 1) {
if (typeof response !== 'object') {
throw new Error(
'Expected an object response from prompt().\n' +
'Make sure you\'re returning `{ default: "value" }` if you\'re ' +
'mocking the prompt return value',
)
}

if ('default' in response) {
// The type cast here isn't great. But Listr2 itself also type cast
// the response (but they cast it to `any`)
// https://github.com/listr2/listr2/blob/b4f544ebce9582f56b2b42fdbe834d70678ce966/packages/prompt-adapter-enquirer/src/prompt.ts#L74
return response.default as T
}
}

return response
}

return response
return {
run,
}
}

skip(msg: string) {
Expand All @@ -151,13 +161,16 @@ export class Listr2Mock {
tasks: Listr.ListrTask<Ctx, typeof Listr.ListrRenderer>[],
options?: Listr.ListrOptions,
) {
this.ctx = {}
this.ctx = options?.ctx || {}
this.tasks = tasks.map((task) => new Listr2TaskWrapper({ task, options }))
}

async run() {
Listr2Mock.executedTaskTitles = []
Listr2Mock.skippedTaskTitles = []
async run(
executedTaskTitles: string[] = [],
skippedTaskTitles: string[] = [],
) {
Listr2Mock.executedTaskTitles = executedTaskTitles
Listr2Mock.skippedTaskTitles = skippedTaskTitles

for (const task of this.tasks) {
const skip =
Expand All @@ -178,7 +191,14 @@ export class Listr2Mock {
continue
}

await task.run(this.ctx, task)
const runReturnValue = await task.run(this.ctx, task)

if (runReturnValue instanceof Listr2Mock) {
await runReturnValue.run(
Listr2Mock.executedTaskTitles,
Listr2Mock.skippedTaskTitles,
)
}

// storing the title after running the task in case the task
// modifies its own title
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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)...',
Expand All @@ -126,7 +127,7 @@ export const handler = async ({ force, verbose }) => {
)}`,
].join('\n')
},
options: { persistentOutput: true },
rendererOptions: { persistentOutput: true },
},
addApiPackages(opentelemetryPackages),
]
Expand Down Expand Up @@ -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?',
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/experimental/setupRscHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const handler = async ({ force, verbose }) => {
}
}
},
options: { persistentOutput: true },
rendererOptions: { persistentOutput: true },
},
{
title: `Overwriting entry.client${ext}...`,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from 'path'

import { ListrEnquirerPromptAdapter } from '@listr2/prompt-adapter-enquirer'
import fs from 'fs-extra'
import { Listr } from 'listr2'

Expand Down Expand Up @@ -72,7 +73,7 @@ export const handler = async ({ force, verbose }) => {
}
}
},
options: { persistentOutput: true },
rendererOptions: { persistentOutput: true },
},
{
title: `Adding entry.client${ext}...`,
Expand All @@ -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}?`,
})
Expand All @@ -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}...`,
Expand Down
Loading

0 comments on commit 84d5f21

Please sign in to comment.