From bbaa958c419fb1e3bd179a9351c13cd65b5c8b0a Mon Sep 17 00:00:00 2001 From: Philippe Serhal Date: Tue, 1 Apr 2025 16:58:22 -0400 Subject: [PATCH 1/4] fix: actually populate auth `user` field We were reading from the wrong property. --- src/utils/build-info.ts | 3 +-- src/utils/gh-auth.ts | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/build-info.ts b/src/utils/build-info.ts index 6edcabaec99..7eca80bb0e1 100644 --- a/src/utils/build-info.ts +++ b/src/utils/build-info.ts @@ -4,9 +4,8 @@ import fuzzy from 'fuzzy' import inquirer from 'inquirer' import type BaseCommand from '../commands/base-command.js' -import type { DefaultConfig } from '../lib/build.js' - import { chalk, log } from './command-helpers.js' +import type { DefaultConfig } from '../lib/build.js' /** * Filters the inquirer settings based on the input diff --git a/src/utils/gh-auth.ts b/src/utils/gh-auth.ts index 9c6b52ff7fa..ec5ee491352 100644 --- a/src/utils/gh-auth.ts +++ b/src/utils/gh-auth.ts @@ -105,8 +105,9 @@ const authWithToken = async (): Promise => { } const octokit = new Octokit({ auth: `token ${token}` }) - // @ts-expect-error -- XXX(serhalp): actual bug - fixed in stacked PR - const { login: user } = await octokit.users.getAuthenticated() + const { + data: { login: user }, + } = await octokit.users.getAuthenticated() return { token, user, provider: 'github' } } From 66b24927c5119996973c8588bb2ad41a6317db1d Mon Sep 17 00:00:00 2001 From: Philippe Serhal Date: Wed, 9 Apr 2025 08:55:45 -0400 Subject: [PATCH 2/4] build: fix suppressed eslint errors --- eslint_temporary_suppressions.js | 11 ----------- src/commands/base-command.ts | 2 +- src/utils/gh-auth.ts | 20 ++++++++++---------- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/eslint_temporary_suppressions.js b/eslint_temporary_suppressions.js index 3076d862193..618d1722ec8 100644 --- a/eslint_temporary_suppressions.js +++ b/eslint_temporary_suppressions.js @@ -952,17 +952,6 @@ export default [ '@typescript-eslint/restrict-template-expressions': 'off', }, }, - { - files: ['src/utils/gh-auth.ts'], - rules: { - '@typescript-eslint/no-unsafe-assignment': 'off', - '@typescript-eslint/restrict-template-expressions': 'off', - '@typescript-eslint/prefer-nullish-coalescing': 'off', - '@typescript-eslint/no-unsafe-return': 'off', - '@typescript-eslint/no-unsafe-call': 'off', - '@typescript-eslint/no-unsafe-member-access': 'off', - }, - }, { files: ['src/utils/gitignore.ts'], rules: { diff --git a/src/commands/base-command.ts b/src/commands/base-command.ts index 9637e1df2cd..482a4457505 100644 --- a/src/commands/base-command.ts +++ b/src/commands/base-command.ts @@ -401,7 +401,7 @@ export default class BaseCommand extends Command { } async expensivelyAuthenticate() { - const webUI = process.env.NETLIFY_WEB_UI || 'https://app.netlify.com' + const webUI = process.env.NETLIFY_WEB_UI ?? 'https://app.netlify.com' log(`Logging into your Netlify account...`) // Create ticket for auth diff --git a/src/utils/gh-auth.ts b/src/utils/gh-auth.ts index ec5ee491352..7140e77fa8f 100644 --- a/src/utils/gh-auth.ts +++ b/src/utils/gh-auth.ts @@ -21,9 +21,9 @@ export interface Token { const promptForAuthMethod = async () => { const authChoiceNetlify = 'Authorize with GitHub through app.netlify.com' const authChoiceToken = 'Authorize with a GitHub personal access token' - const authChoices = [authChoiceNetlify, authChoiceToken] + const authChoices = [authChoiceNetlify, authChoiceToken] as const - const { authMethod } = await inquirer.prompt([ + const { authMethod } = (await inquirer.prompt([ { type: 'list', name: 'authMethod', @@ -32,7 +32,7 @@ const promptForAuthMethod = async () => { 'What would you like to do?', choices: authChoices, }, - ]) + ])) as { authMethod: typeof authChoices[number] } return authMethod === authChoiceNetlify } @@ -53,7 +53,7 @@ export const authWithNetlify = async (): Promise => { `${ "Logged in" + "

Logged in

You're now logged into Netlify CLI with your " - }${parameters.get('provider')} credentials. Please close this window.

`, + }${parameters.get('provider') ?? ''} credentials. Please close this window.

`, ) server.close() return @@ -70,9 +70,9 @@ export const authWithNetlify = async (): Promise => { }) }) - const webUI = process.env.NETLIFY_WEB_UI || 'https://app.netlify.com' + const webUI = process.env.NETLIFY_WEB_UI ?? 'https://app.netlify.com' const urlParams = new URLSearchParams({ - host: `http://localhost:${port}`, + host: `http://localhost:${port.toString()}`, provider: 'github', }) const url = `${webUI}/cli?${urlParams.toString()}` @@ -82,15 +82,15 @@ export const authWithNetlify = async (): Promise => { return deferredPromise } -const getPersonalAccessToken = async () => { - const { token } = await inquirer.prompt([ +const getPersonalAccessToken = async (): Promise<{ token: string }> => { + const { token } = (await inquirer.prompt([ { type: 'password', name: 'token', message: 'Your GitHub personal access token:', - filter: (input) => input.trim(), + filter: (input: string) => input.trim(), }, - ]) + ])) as { token: string } return { token } } From c264287d3f7ded1b3407872e49f50dfb34e8e55f Mon Sep 17 00:00:00 2001 From: Philippe Serhal Date: Mon, 14 Apr 2025 17:32:32 -0400 Subject: [PATCH 3/4] fix: revert change of empty string `NETLIFY_WEB_UI` handling --- src/commands/base-command.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/base-command.ts b/src/commands/base-command.ts index 482a4457505..9637e1df2cd 100644 --- a/src/commands/base-command.ts +++ b/src/commands/base-command.ts @@ -401,7 +401,7 @@ export default class BaseCommand extends Command { } async expensivelyAuthenticate() { - const webUI = process.env.NETLIFY_WEB_UI ?? 'https://app.netlify.com' + const webUI = process.env.NETLIFY_WEB_UI || 'https://app.netlify.com' log(`Logging into your Netlify account...`) // Create ticket for auth From fa9d57c2552cafea1799a4de629df730ba1eecec Mon Sep 17 00:00:00 2001 From: Philippe Serhal Date: Tue, 15 Apr 2025 11:53:06 -0400 Subject: [PATCH 4/4] refactor: use inquirer.prompt generic --- src/commands/init/init.ts | 10 +++++----- src/utils/gh-auth.ts | 8 ++++---- src/utils/init/config-manual.ts | 8 ++++---- src/utils/init/utils.ts | 8 ++++++-- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/commands/init/init.ts b/src/commands/init/init.ts index c2481b16264..a0968358ff3 100644 --- a/src/commands/init/init.ts +++ b/src/commands/init/init.ts @@ -114,14 +114,14 @@ git remote add origin https://github.com/YourUserName/RepoName.git const NEW_SITE_NO_GIT = 'Yes, create and deploy site manually' const NO_ABORT = 'No, I will connect this directory with GitHub first' - const { noGitRemoteChoice } = (await inquirer.prompt([ + const { noGitRemoteChoice } = await inquirer.prompt<{ noGitRemoteChoice: typeof NEW_SITE_NO_GIT | typeof NO_ABORT }>([ { type: 'list', name: 'noGitRemoteChoice', message: 'Do you want to create a Netlify site without a git repository?', choices: [NEW_SITE_NO_GIT, NO_ABORT], }, - ])) as { noGitRemoteChoice: typeof NEW_SITE_NO_GIT | typeof NO_ABORT } + ]) if (noGitRemoteChoice === NEW_SITE_NO_GIT) { return await createNewSiteAndExit({ state, command }) @@ -138,15 +138,15 @@ const createOrLinkSiteToRepo = async (command: BaseCommand) => { const initializeOpts = [EXISTING_SITE, NEW_SITE] as const - const { initChoice } = (await inquirer.prompt([ + // TODO(serhalp): inquirer should infer the choice type here, but doesn't. Fix. + const { initChoice } = await inquirer.prompt<{ initChoice: typeof initializeOpts[number] }>([ { type: 'list', name: 'initChoice', message: 'What would you like to do?', choices: initializeOpts, }, - // TODO(serhalp): inquirer should infer the choice type here, but doesn't. Fix. - ])) as { initChoice: typeof initializeOpts[number] } + ]) // create site or search for one if (initChoice === NEW_SITE) { diff --git a/src/utils/gh-auth.ts b/src/utils/gh-auth.ts index 7140e77fa8f..7d8c5d07b59 100644 --- a/src/utils/gh-auth.ts +++ b/src/utils/gh-auth.ts @@ -23,7 +23,7 @@ const promptForAuthMethod = async () => { const authChoiceToken = 'Authorize with a GitHub personal access token' const authChoices = [authChoiceNetlify, authChoiceToken] as const - const { authMethod } = (await inquirer.prompt([ + const { authMethod } = await inquirer.prompt<{ authMethod: typeof authChoices[number] }>([ { type: 'list', name: 'authMethod', @@ -32,7 +32,7 @@ const promptForAuthMethod = async () => { 'What would you like to do?', choices: authChoices, }, - ])) as { authMethod: typeof authChoices[number] } + ]) return authMethod === authChoiceNetlify } @@ -83,14 +83,14 @@ export const authWithNetlify = async (): Promise => { } const getPersonalAccessToken = async (): Promise<{ token: string }> => { - const { token } = (await inquirer.prompt([ + const { token } = await inquirer.prompt<{ token: string }>([ { type: 'password', name: 'token', message: 'Your GitHub personal access token:', filter: (input: string) => input.trim(), }, - ])) as { token: string } + ]) return { token } } diff --git a/src/utils/init/config-manual.ts b/src/utils/init/config-manual.ts index 7ebdffd332e..0b1011b50c8 100644 --- a/src/utils/init/config-manual.ts +++ b/src/utils/init/config-manual.ts @@ -28,7 +28,7 @@ const addDeployKey = async (deployKey: DeployKey) => { } const getRepoPath = async ({ repoData }: { repoData: RepoData }): Promise => { - const { repoPath } = (await inquirer.prompt([ + const { repoPath } = await inquirer.prompt<{ repoPath: string }>([ { type: 'input', name: 'repoPath', @@ -36,7 +36,7 @@ const getRepoPath = async ({ repoData }: { repoData: RepoData }): Promise (SSH_URL_REGEXP.test(url) ? true : 'The URL provided does not use the SSH protocol'), }, - ])) as { repoPath: string } + ]) return repoPath } @@ -44,14 +44,14 @@ const getRepoPath = async ({ repoData }: { repoData: RepoData }): Promise => { log('\nConfigure the following webhook for your repository:\n') log(`\n${deployHook}\n\n`) - const { deployHookAdded } = (await inquirer.prompt([ + const { deployHookAdded } = await inquirer.prompt<{ deployHookAdded: boolean }>([ { type: 'confirm', name: 'deployHookAdded', message: 'Continue?', default: true, }, - ])) as { deployHookAdded: boolean } + ]) return deployHookAdded } diff --git a/src/utils/init/utils.ts b/src/utils/init/utils.ts index 95a39e33ae9..3d15fd02580 100644 --- a/src/utils/init/utils.ts +++ b/src/utils/init/utils.ts @@ -105,13 +105,17 @@ export const getBuildSettings = async ({ log() } - const { baseDir, buildCmd, buildDir } = (await inquirer.prompt( + const { baseDir, buildCmd, buildDir } = await inquirer.prompt<{ + baseDir?: string | undefined + buildCmd: string + buildDir: string + }>( getPromptInputs({ defaultBaseDir, defaultBuildCmd, defaultBuildDir, }), - )) as { baseDir?: string | undefined; buildCmd: string; buildDir: string } + ) const pluginsToInstall = recommendedPlugins.map((plugin) => ({ package: plugin })) const normalizedBaseDir = baseDir ? normalizeBackslash(baseDir) : undefined