Skip to content

Commit

Permalink
fix: refactored prompts and tests messages
Browse files Browse the repository at this point in the history
Co-authored-by: Thomas Lane <163203257+tlane25@users.noreply.github.com>
Co-authored-by: Thomas Lane <tlane25@users.noreply.github.com>
  • Loading branch information
3 people committed Oct 22, 2024
1 parent 469691c commit f6aa58d
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 155 deletions.
6 changes: 6 additions & 0 deletions src/commands/base-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ export default class BaseCommand extends Command {
// eslint-disable-next-line workspace/no-process-cwd
workingDir = process.cwd()

/**
* Determines if the command is scripted or not.
* If the command is scripted (SHLVL is greater than 1 or CI/CONTINUOUS_INTEGRATION is true) then some commands
* might behave differently.
*/
scriptedCommand = Boolean(process.env.SHLVL !== '1' || process.env.CI || process.env.CONTINUOUS_INTEGRATION)
/**
* The workspace root if inside a mono repository.
* Must not be the repository root!
Expand Down
12 changes: 9 additions & 3 deletions src/commands/blobs/blobs-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { getStore } from '@netlify/blobs'
import { OptionValues } from 'commander'

import { chalk, error as printError, isNodeError, log } from '../../utils/command-helpers.js'
import { blobSetPrompts } from '../../utils/prompts/blob-set-prompt.js'
import { promptBlobSetOverwrite } from '../../utils/prompts/blob-set-prompt.js'
import BaseCommand from '../base-command.js'

interface Options extends OptionValues {
input?: string
force?: string
force?: string | boolean
}

export const blobsSet = async (
Expand All @@ -20,6 +20,12 @@ export const blobsSet = async (
options: Options,
command: BaseCommand,
) => {

// Prevents prompts from blocking scripted commands
if (command.scriptedCommand){
options.force = true
}

const { api, siteInfo } = command.netlify
const { force, input } = options
const store = getStore({
Expand Down Expand Up @@ -61,7 +67,7 @@ export const blobsSet = async (
const existingValue = await store.get(key)

if (existingValue) {
await blobSetPrompts(key, storeName)
await promptBlobSetOverwrite(key, storeName)
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/commands/env/env-clone.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OptionValues } from 'commander'

import { chalk, log, error as logError } from '../../utils/command-helpers.js'
import { envClonePrompts } from '../../utils/prompts/env-clone-prompt.js'
import { promptEnvCloneOverwrite } from '../../utils/prompts/env-clone-prompt.js'
import BaseCommand from '../base-command.js'

// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type.
Expand Down Expand Up @@ -39,7 +39,7 @@ const cloneEnvVars = async ({ api, force, siteFrom, siteTo }): Promise<boolean>
const envVarsToDelete = envelopeTo.filter(({ key }) => keysFrom.includes(key))

if (envVarsToDelete.length !== 0 && Boolean(force) === false) {
await envClonePrompts(siteTo.id, envVarsToDelete)
await promptEnvCloneOverwrite(siteTo.id, envVarsToDelete)
}
// delete marked env vars in parallel
// @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
Expand All @@ -56,6 +56,12 @@ const cloneEnvVars = async ({ api, force, siteFrom, siteTo }): Promise<boolean>
}

export const envClone = async (options: OptionValues, command: BaseCommand) => {

// Prevents prompts from blocking scripted commands
if (command.scriptedCommand){
options.force = true
}

const { api, site } = command.netlify
const { force } = options

Expand Down
6 changes: 6 additions & 0 deletions src/commands/env/env-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ const setInEnvelope = async ({ api, context, force, key, scope, secret, siteInfo
}

export const envSet = async (key: string, value: string, options: OptionValues, command: BaseCommand) => {

// Prevents prompts from blocking scripted commands
if (command.scriptedCommand){
options.force = true
}

const { context, force, scope, secret } = options
const { api, cachedConfig, site } = command.netlify
const siteId = site.id
Expand Down
6 changes: 6 additions & 0 deletions src/commands/env/env-unset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ const unsetInEnvelope = async ({ api, context, force, key, siteInfo }) => {
}

export const envUnset = async (key: string, options: OptionValues, command: BaseCommand) => {

// Prevents prompts from blocking scripted commands
if (command.scriptedCommand){
options.force = true
}

const { context, force } = options
const { api, cachedConfig, site } = command.netlify
const siteId = site.id
Expand Down
19 changes: 10 additions & 9 deletions src/utils/prompts/blob-set-prompt.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { chalk, log } from '../command-helpers.js'

import { confirmPrompt } from './confirm-prompt.js'
import { destructiveCommandMessages } from './prompt-messages.js'

export const promptBlobSetOverwrite = async (key: string, storeName: string): Promise<void> => {
const { overwriteNoticeMessage } = destructiveCommandMessages
const { generateWarningMessage, overwriteConfirmationMessage } = destructiveCommandMessages.blobSet

const warningMessage = generateWarningMessage(storeName)

const generateBlobWarningMessage = (key: string, storeName: string): void => {
log()
log(`${chalk.redBright('Warning')}: The following blob key already exists in store ${chalk.cyan(storeName)}:`)
log(warningMessage)
log()
log(`${chalk.bold(key)}`)
log()
log(`This operation will ${chalk.redBright('overwrite')} the existing value.`)
log(`${chalk.yellowBright('Notice')}: To overwrite without this warning, you can use the --force flag.`)
}

export const blobSetPrompts = async (key: string, storeName: string): Promise<void> => {
generateBlobWarningMessage(key, storeName)
await confirmPrompt('Do you want to proceed with overwriting this blob key existing value?')
log(overwriteNoticeMessage)
await confirmPrompt(overwriteConfirmationMessage)
}
61 changes: 23 additions & 38 deletions src/utils/prompts/env-clone-prompt.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,34 @@
import { chalk, log } from '../command-helpers.js'
import { log } from '../command-helpers.js'
import { EnvVar } from '../types.js'

import { confirmPrompt } from './confirm-prompt.js'
import { destructiveCommandMessages } from './prompt-messages.js'

type User = {
id: string
email: string
avatar_url: string
full_name: string
}
export const generateEnvVarsList = (envVarsToDelete: EnvVar[]) => envVarsToDelete.map((envVar) => envVar.key)

type EnvVar = {
key: string
scopes: string[]
values: Record<string, any>[]
updated_at: string
updated_by: User
is_secret: boolean
}
/**
* Prompts the user to confirm overwriting environment variables on a site.
*
* @param {string} siteId - The ID of the site.
* @param {EnvVar[]} existingEnvVars - The environment variables that already exist on the site.
* @returns {Promise<void>} A promise that resolves when the user has confirmed the overwriting of the variables.
*/
export async function promptEnvCloneOverwrite(siteId: string, existingEnvVars: EnvVar[]): Promise<void> {
const { overwriteNoticeMessage } = destructiveCommandMessages
const { generateWarningMessage, noticeEnvVarsMessage, overwriteConfirmationMessage } =
destructiveCommandMessages.envClone

const existingEnvVarKeys = generateEnvVarsList(existingEnvVars)
const warningMessage = generateWarningMessage(siteId)

const generateSetMessage = (envVarsToDelete: EnvVar[], siteId: string): void => {
log()
log(
`${chalk.redBright(
'Warning',
)}: The following environment variables are already set on the site with ID ${chalk.bgBlueBright(
siteId,
)}. They will be overwritten!`,
)
log(warningMessage)
log()

log(`${chalk.yellowBright('Notice')}: The following variables will be overwritten:`)
log(noticeEnvVarsMessage)
log()
envVarsToDelete.forEach((envVar) => {
log(envVar.key)
})

existingEnvVarKeys.forEach(log)
log()
log(
`${chalk.yellowBright(
'Notice',
)}: To overwrite the existing variables without confirmation prompts, pass the --force flag.`,
)
}
log(overwriteNoticeMessage)

export const envClonePrompts = async (siteId: string, envVarsToDelete: EnvVar[]): Promise<void> => {
generateSetMessage(envVarsToDelete, siteId)
await confirmPrompt('Do you want to proceed with overwriting these variables?')
await confirmPrompt(overwriteConfirmationMessage)
}
35 changes: 12 additions & 23 deletions src/utils/prompts/env-set-prompts.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
import { chalk, log } from '../command-helpers.js'
import { log } from '../command-helpers.js'

import { confirmPrompt } from './confirm-prompt.js'

export const generateSetMessage = (variableName: string) => ({
warningMessage: `${chalk.redBright('Warning')}: The environment variable ${chalk.bgBlueBright(
variableName,
)} already exists!`,
noticeMessage: `${chalk.yellowBright(
'Notice',
)}: To overwrite the existing variable without confirmation, pass the -f or --force flag.`,
confirmMessage: 'The environment variable already exists. Do you want to overwrite it?',
})
import { destructiveCommandMessages } from './prompt-messages.js'

/**
* Generates warning, notice and confirm messages when trying to set an env variable
* that already exists.
* Prompts the user to confirm overwriting an existing environment variable.
*
* @param {string} key - The key of the environment variable that already exists
* @returns {Object} An object with the following properties:
* - warning: A warning message to be displayed to the user
* - notice: A notice message to be displayed to the user
* - confirm: A confirmation prompt to ask the user if they want to overwrite the existing variable
* @param {string} existingKey - The key of the existing environment variable.
* @returns {Promise<void>} A promise that resolves when the user confirms overwriting the variable.
*/
export const promptOverwriteEnvVariable = async (key: string): Promise<void> => {
const { confirmMessage, noticeMessage, warningMessage } = generateSetMessage(key)
export const promptOverwriteEnvVariable = async (existingKey: string): Promise<void> => {
const { overwriteNoticeMessage } = destructiveCommandMessages
const { generateWarningMessage, overwriteConfirmationMessage } = destructiveCommandMessages.envSet

const warningMessage = generateWarningMessage(existingKey)

log()
log(warningMessage)
log()
log(noticeMessage)
log()
await confirmPrompt(confirmMessage)
log(overwriteNoticeMessage)
await confirmPrompt(overwriteConfirmationMessage)
}
37 changes: 37 additions & 0 deletions src/utils/prompts/prompt-messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { chalk } from '../command-helpers.js'
import { EnvVar } from '../types.js'

export const destructiveCommandMessages = {
overwriteNoticeMessage: `${chalk.yellowBright(
'Notice',
)}: To overwrite without this warning, you can use the --force flag.`,

blobSet: {
generateWarningMessage: (storeName: string) =>
`${chalk.redBright('Warning')}: The blob key already exists in store ${chalk.cyan(storeName)}.`,
overwriteConfirmationMessage: 'Do you want to proceed with overwriting this blob key existing value?',
},

envSet: {
generateWarningMessage: (variableName: string) =>
`${chalk.redBright('Warning')}: The environment variable ${chalk.bgBlueBright(variableName)} already exists.`,
overwriteConfirmationMessage: 'The environment variable already exists. Do you want to overwrite it?',
},

envUnset: {
generateWarningMessage: (variableName: string) =>
`${chalk.redBright('Warning')}: The environment variable ${chalk.bgBlueBright(variableName)} already exists!`,
overwriteConfirmationMessage: 'The environment variable already exists. Do you want to overwrite it?',
},

envClone: {
generateWarningMessage: (siteId: string) =>
`${chalk.redBright(
'Warning',
)}: The following environment variables are already set on the site with ID ${chalk.bgBlueBright(
siteId,
)}. They will be overwritten!`,
noticeEnvVarsMessage: `${chalk.yellowBright('Notice')}: The following variables will be overwritten:`,
overwriteConfirmationMessage: 'The environment variables already exist. Do you want to overwrite them?',
},
}
25 changes: 10 additions & 15 deletions src/utils/prompts/unset-set-prompts.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import { chalk, log } from '../command-helpers.js'
import { log } from '../command-helpers.js'

import { confirmPrompt } from './confirm-prompt.js'

export const generateUnsetMessage = (variableName: string) => ({
warningMessage: `${chalk.redBright('Warning')}: The environment variable ${chalk.bgBlueBright(
variableName,
)} already exists!`,
noticeMessage: `${chalk.yellowBright(
'Notice',
)}: To overwrite the existing variable without confirmation, pass the -f or --force flag.`,
confirmMessage: 'The environment variable already exists. Do you want to overwrite it?',
})
import { destructiveCommandMessages } from './prompt-messages.js'

/**
* Logs a warning and prompts user to confirm overwriting an existing environment variable
*
* @param {string} key - The key of the environment variable that already exists
* @returns {Promise<void>} A promise that resolves when the user has confirmed overwriting the variable
*/
export const promptOverwriteEnvVariable = async (key: string): Promise<void> => {
const { confirmMessage, noticeMessage, warningMessage } = generateUnsetMessage(key)
export const promptOverwriteEnvVariable = async (existingKey: string): Promise<void> => {
const { overwriteNoticeMessage } = destructiveCommandMessages
const { generateWarningMessage, overwriteConfirmationMessage } = destructiveCommandMessages.envUnset

const warningMessage = generateWarningMessage(existingKey)

log(warningMessage)
log()
log(noticeMessage)
await confirmPrompt(confirmMessage)
log(overwriteNoticeMessage)
await confirmPrompt(overwriteConfirmationMessage)
}
14 changes: 14 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,17 @@ export interface Request extends IncomingMessage {
export type Rewriter = (req: Request) => Match | null

export type TokenLocation = 'env' | 'flag' | 'config' | 'not found'

export type EnvVar = {
key: string
scopes: string[]
values: EnvVarValue[]
updated_at: string
is_secret: boolean
}

type EnvVarValue = {
id: string
context: string
value: string
}
Loading

0 comments on commit f6aa58d

Please sign in to comment.