From 95cc3cdfc80767fee48bdd7b67196537ee7c44f1 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 11:49:32 -0500 Subject: [PATCH 01/67] feat: convert addon-auth --- src/commands/addons/addons-auth.mts | 33 ++++++----------------------- src/commands/addons/addons.mts | 14 +++++++++--- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/commands/addons/addons-auth.mts b/src/commands/addons/addons-auth.mts index 5845cddd36a..4c8902ef035 100644 --- a/src/commands/addons/addons-auth.mts +++ b/src/commands/addons/addons-auth.mts @@ -1,17 +1,13 @@ - + +import { OptionValues } from 'commander' + import { ADDON_VALIDATION, prepareAddonCommand } from '../../utils/addons/prepare.mjs' import { exit, log } from '../../utils/command-helpers.mjs' import openBrowser from '../../utils/open-browser.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The addons:auth command - * @param {string} addonName - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message -const addonsAuth = async (addonName, options, command) => { + +export const addonsAuth = async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addon } = await prepareAddonCommand({ command, addonName, @@ -32,20 +28,3 @@ const addonsAuth = async (addonName, options, command) => { await openBrowser({ url: addon.auth_url }) exit() } - -/** - * Creates the `netlify addons:auth` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createAddonsAuthCommand = (program) => - program - .command('addons:auth', { hidden: true }) - .alias('addon:auth') - .argument('', 'Add-on slug') - .description('Login to add-on provider') - // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message - .action(async (addonName, options, command) => { - await addonsAuth(addonName, options, command) - }) diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index 307787b3ea7..091fd0aa919 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -1,5 +1,4 @@ - -import { createAddonsAuthCommand } from './addons-auth.mjs' + import { createAddonsConfigCommand } from './addons-config.mjs' import { createAddonsCreateCommand } from './addons-create.mjs' import { createAddonsDeleteCommand } from './addons-delete.mjs' @@ -22,7 +21,16 @@ const addons = (options, command) => { */ // @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. export const createAddonsCommand = (program) => { - createAddonsAuthCommand(program) + program + .command('addons:auth', { hidden: true }) + .alias('addon:auth') + .argument('', 'Add-on slug') + .description('Login to add-on provider') + // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message + .action(async (addonName, options, command) => { + const { addonsAuth } = await import('./addons-auth.mjs') + await addonsAuth(addonName, options, command) + }) createAddonsConfigCommand(program) createAddonsCreateCommand(program) createAddonsDeleteCommand(program) From 86029125cb1fc29ece28b7b7816dc6f187550bb6 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:01:25 -0500 Subject: [PATCH 02/67] feat: convert addons:config --- src/commands/addons/addons-config.mts | 33 ++++----------------------- src/commands/addons/addons.mts | 29 +++++++++++++++-------- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/commands/addons/addons-config.mts b/src/commands/addons/addons-config.mts index ea9f6754aca..b22b90d170c 100644 --- a/src/commands/addons/addons-config.mts +++ b/src/commands/addons/addons-config.mts @@ -1,4 +1,5 @@ - + +import { OptionValues } from 'commander' import inquirer from 'inquirer' import isEmpty from 'lodash/isEmpty.js' @@ -10,6 +11,7 @@ import { renderConfigValues } from '../../utils/addons/render.mjs' import { missingConfigValues, requiredConfigValues, updateConfigValues } from '../../utils/addons/validation.mjs' import { chalk, error, log } from '../../utils/command-helpers.mjs' import { parseRawFlags } from '../../utils/parse-raw-flags.mjs' +import BaseCommand from '../base-command.mjs' // @ts-expect-error TS(7031) FIXME: Binding element 'addonName' implicitly has an 'any... Remove this comment to see the full error message const update = async function ({ addonName, api, currentConfig, instanceId, newConfig, siteId }) { @@ -39,15 +41,7 @@ const update = async function ({ addonName, api, currentConfig, instanceId, newC } } -/** - * The addons:config command - * @param {string} addonName - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message -const addonsConfig = async (addonName, options, command) => { +export const addonsConfig = async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addon, manifest, siteData } = await prepareAddonCommand({ command, addonName, @@ -165,22 +159,3 @@ const addonsConfig = async (addonName, options, command) => { }) } } - -/** - * Creates the `netlify addons:config` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createAddonsConfigCommand = (program) => - program - .command('addons:config', { hidden: true }) - .alias('addon:config') - .argument('', 'Add-on namespace') - .description('Configure add-on settings') - // allow for any flags. Handy for variadic configuration options - .allowUnknownOption(true) - // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message - .action(async (addonName, options, command) => { - await addonsConfig(addonName, options, command) - }) diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index 091fd0aa919..1fbe38caa6c 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -1,16 +1,14 @@ -import { createAddonsConfigCommand } from './addons-config.mjs' +import { OptionValues } from 'commander' + +import BaseCommand from '../base-command.mjs' + import { createAddonsCreateCommand } from './addons-create.mjs' import { createAddonsDeleteCommand } from './addons-delete.mjs' import { createAddonsListCommand } from './addons-list.mjs' -/** - * The addons command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const addons = (options, command) => { + +const addons = (options: OptionValues, command: BaseCommand) => { command.help() } @@ -31,7 +29,20 @@ export const createAddonsCommand = (program) => { const { addonsAuth } = await import('./addons-auth.mjs') await addonsAuth(addonName, options, command) }) - createAddonsConfigCommand(program) + + program + .command('addons:config', { hidden: true }) + .alias('addon:config') + .argument('', 'Add-on namespace') + .description('Configure add-on settings') + // allow for any flags. Handy for variadic configuration options + .allowUnknownOption(true) + // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message + .action(async (addonName, options, command) => { + const { addonsConfig } = await import('./addons-config.mjs') + await addonsConfig(addonName, options, command) + }) + createAddonsCreateCommand(program) createAddonsDeleteCommand(program) createAddonsListCommand(program) From 0c7d81bb520c052a69ccfb09f4c27fa7ade60c62 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:03:43 -0500 Subject: [PATCH 03/67] feat: convert addons:create --- src/commands/addons/addons-create.mts | 37 ++++----------------------- src/commands/addons/addons.mts | 18 +++++++++++-- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/src/commands/addons/addons-create.mts b/src/commands/addons/addons-create.mts index 5dc9520a6d2..c032b489284 100644 --- a/src/commands/addons/addons-create.mts +++ b/src/commands/addons/addons-create.mts @@ -1,4 +1,5 @@ - + +import { OptionValues } from 'commander' import inquirer from 'inquirer' import isEmpty from 'lodash/isEmpty.js' @@ -8,6 +9,7 @@ import { renderConfigValues, renderMissingValues } from '../../utils/addons/rend import { missingConfigValues, requiredConfigValues, updateConfigValues } from '../../utils/addons/validation.mjs' import { chalk, error, log } from '../../utils/command-helpers.mjs' import { parseRawFlags } from '../../utils/parse-raw-flags.mjs' +import BaseCommand from '../base-command.mjs' // @ts-expect-error TS(7031) FIXME: Binding element 'addonName' implicitly has an 'any... Remove this comment to see the full error message const createAddon = async ({ addonName, api, config, siteData, siteId }) => { @@ -28,15 +30,8 @@ const createAddon = async ({ addonName, api, config, siteData, siteId }) => { } } -/** - * The addons:create command - * @param {string} addonName - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message -const addonsCreate = async (addonName, options, command) => { + +export const addonsCreate = async (addonName: string, options: OptionValues, command: BaseCommand) => { const { manifest, siteData } = await prepareAddonCommand({ command, addonName, @@ -112,25 +107,3 @@ const addonsCreate = async (addonName, options, command) => { await createAddon({ api, siteId, addonName, config: configValues, siteData }) } - -/** - * Creates the `netlify addons:create` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createAddonsCreateCommand = (program) => - program - .command('addons:create', { hidden: true }) - .alias('addon:create') - .argument('', 'Add-on namespace') - .description( - `Add an add-on extension to your site -Add-ons are a way to extend the functionality of your Netlify site`, - ) - // allow for any flags. Handy for variadic configuration options - .allowUnknownOption(true) - // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message - .action(async (addonName, options, command) => { - await addonsCreate(addonName, options, command) - }) diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index 1fbe38caa6c..8c449df9f08 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -3,7 +3,6 @@ import { OptionValues } from 'commander' import BaseCommand from '../base-command.mjs' -import { createAddonsCreateCommand } from './addons-create.mjs' import { createAddonsDeleteCommand } from './addons-delete.mjs' import { createAddonsListCommand } from './addons-list.mjs' @@ -43,7 +42,22 @@ export const createAddonsCommand = (program) => { await addonsConfig(addonName, options, command) }) - createAddonsCreateCommand(program) + program + .command('addons:create', { hidden: true }) + .alias('addon:create') + .argument('', 'Add-on namespace') + .description( + `Add an add-on extension to your site +Add-ons are a way to extend the functionality of your Netlify site`, + ) + // allow for any flags. Handy for variadic configuration options + .allowUnknownOption(true) + // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message + .action(async (addonName, options, command) => { + const { addonsCreate } = await import('./addons-create.mjs') + await addonsCreate(addonName, options, command) + }) + createAddonsDeleteCommand(program) createAddonsListCommand(program) From 9ecf1c307c482c8db7fbb053f20b8f1212c666d4 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:09:08 -0500 Subject: [PATCH 04/67] feat: convert addons:delete --- src/commands/addons/addons-auth.mts | 1 - src/commands/addons/addons-create.mts | 1 - src/commands/addons/addons-delete.mts | 29 +++------------------------ src/commands/addons/addons.mts | 18 +++++++++++++---- 4 files changed, 17 insertions(+), 32 deletions(-) diff --git a/src/commands/addons/addons-auth.mts b/src/commands/addons/addons-auth.mts index 4c8902ef035..307bdfb8bbd 100644 --- a/src/commands/addons/addons-auth.mts +++ b/src/commands/addons/addons-auth.mts @@ -1,4 +1,3 @@ - import { OptionValues } from 'commander' import { ADDON_VALIDATION, prepareAddonCommand } from '../../utils/addons/prepare.mjs' diff --git a/src/commands/addons/addons-create.mts b/src/commands/addons/addons-create.mts index c032b489284..cd4b6d0a439 100644 --- a/src/commands/addons/addons-create.mts +++ b/src/commands/addons/addons-create.mts @@ -1,4 +1,3 @@ - import { OptionValues } from 'commander' import inquirer from 'inquirer' import isEmpty from 'lodash/isEmpty.js' diff --git a/src/commands/addons/addons-delete.mts b/src/commands/addons/addons-delete.mts index 71967918636..6e92a1b95aa 100644 --- a/src/commands/addons/addons-delete.mts +++ b/src/commands/addons/addons-delete.mts @@ -1,17 +1,11 @@ - +import { OptionValues } from 'commander' import inquirer from 'inquirer' import { ADDON_VALIDATION, prepareAddonCommand } from '../../utils/addons/prepare.mjs' import { error, exit, log } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The addons:delete command - * @param {string} addonName - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message -const addonsDelete = async (addonName, options, command) => { +export const addonsDelete = async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addon } = await prepareAddonCommand({ command, addonName, @@ -41,20 +35,3 @@ const addonsDelete = async (addonName, options, command) => { error(error_.message) } } - -/** - * Creates the `netlify addons:delete` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createAddonsDeleteCommand = (program) => - program - .command('addons:delete', { hidden: true }) - .alias('addon:delete') - .argument('', 'Add-on namespace') - .description( - `Remove an add-on extension to your site\nAdd-ons are a way to extend the functionality of your Netlify site`, - ) - .option('-f, --force', 'delete without prompting (useful for CI)') - .action(addonsDelete) diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index 8c449df9f08..b11c8382a0e 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -23,7 +23,6 @@ export const createAddonsCommand = (program) => { .alias('addon:auth') .argument('', 'Add-on slug') .description('Login to add-on provider') - // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message .action(async (addonName, options, command) => { const { addonsAuth } = await import('./addons-auth.mjs') await addonsAuth(addonName, options, command) @@ -36,7 +35,6 @@ export const createAddonsCommand = (program) => { .description('Configure add-on settings') // allow for any flags. Handy for variadic configuration options .allowUnknownOption(true) - // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message .action(async (addonName, options, command) => { const { addonsConfig } = await import('./addons-config.mjs') await addonsConfig(addonName, options, command) @@ -52,13 +50,25 @@ Add-ons are a way to extend the functionality of your Netlify site`, ) // allow for any flags. Handy for variadic configuration options .allowUnknownOption(true) - // @ts-expect-error TS(7006) FIXME: Parameter 'addonName' implicitly has an 'any' type... Remove this comment to see the full error message .action(async (addonName, options, command) => { const { addonsCreate } = await import('./addons-create.mjs') await addonsCreate(addonName, options, command) }) - createAddonsDeleteCommand(program) + program + .command('addons:delete', { hidden: true }) + .alias('addon:delete') + .argument('', 'Add-on namespace') + .description( + `Remove an add-on extension to your site\nAdd-ons are a way to extend the functionality of your Netlify site`, + ) + .option('-f, --force', 'delete without prompting (useful for CI)') + .action(async (addonName, options, command) => { + const { addonsDelete } = await import('./addons-delete.mjs') + await addonsDelete(addonName, options, command) + }) + + createAddonsListCommand(program) return program From 4f6d088158da0f11c8d8998f0ef47d02c4b88cc7 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:10:56 -0500 Subject: [PATCH 05/67] feat: convert addons:list --- src/commands/addons/addons-list.mts | 14 ++++---------- src/commands/addons/addons.mts | 15 +++++++++------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/commands/addons/addons-list.mts b/src/commands/addons/addons-list.mts index f3d1726d127..ed83c900f1d 100644 --- a/src/commands/addons/addons-list.mts +++ b/src/commands/addons/addons-list.mts @@ -1,18 +1,12 @@ - - import AsciiTable from 'ascii-table' +import { OptionValues } from 'commander' import { prepareAddonCommand } from '../../utils/addons/prepare.mjs' import { log, logJson } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The addons:list command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const addonsList = async (options, command) => { + +export const addonsList = async (options: OptionValues, command: BaseCommand) => { // @ts-expect-error TS(2345) FIXME: Argument of type '{ command: any; }' is not assign... Remove this comment to see the full error message const { addons, siteData } = await prepareAddonCommand({ command }) // Return json response for piping commands diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index b11c8382a0e..20f08eaac04 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -1,12 +1,7 @@ - import { OptionValues } from 'commander' import BaseCommand from '../base-command.mjs' -import { createAddonsDeleteCommand } from './addons-delete.mjs' -import { createAddonsListCommand } from './addons-list.mjs' - - const addons = (options: OptionValues, command: BaseCommand) => { command.help() } @@ -69,7 +64,15 @@ Add-ons are a way to extend the functionality of your Netlify site`, }) - createAddonsListCommand(program) + program + .command('addons:list', { hidden: true }) + .alias('addon:list') + .description(`List currently installed add-ons for site`) + .option('--json', 'Output add-on data as JSON') + .action(async (options, command) => { + const {addonsList} = await import('./addons-list.mjs') + await addonsList(options, command) + }) return program .command('addons', { hidden: true }) From a5ff2866446852a1d1c336685762008a381deb75 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:26:32 -0500 Subject: [PATCH 06/67] feat: convert api --- src/commands/api/api.mts | 34 ++++------------------------------ src/commands/api/index.mts | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/commands/api/api.mts b/src/commands/api/api.mts index a4a2f72f010..a4195de4de2 100644 --- a/src/commands/api/api.mts +++ b/src/commands/api/api.mts @@ -1,18 +1,12 @@ - - import AsciiTable from 'ascii-table' +import { OptionValues } from 'commander' import { methods } from 'netlify' import { chalk, error, exit, log, logJson } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The api command - * @param {string} apiMethod - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'apiMethod' implicitly has an 'any' type... Remove this comment to see the full error message -const apiCommand = async (apiMethod, options, command) => { + +export const apiCommand = async (apiMethod: string, options: OptionValues, command: BaseCommand) => { const { api } = command.netlify if (options.list) { @@ -52,23 +46,3 @@ const apiCommand = async (apiMethod, options, command) => { } } -/** - * Creates the `netlify api` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createApiCommand = (program) => - program - .command('api') - .argument('[apiMethod]', 'Open API method to run') - .description( - `Run any Netlify API method -For more information on available methods checkout https://open-api.netlify.com/ or run '${chalk.grey( - 'netlify api --list', - )}'`, - ) - .option('-d, --data ', 'Data to use') - .option('--list', 'List out available API methods', false) - .addExamples(['netlify api --list', `netlify api getSite --data '{ "site_id": "123456" }'`]) - .action(apiCommand) diff --git a/src/commands/api/index.mts b/src/commands/api/index.mts index effb6d2e3b2..390d6bc4e02 100644 --- a/src/commands/api/index.mts +++ b/src/commands/api/index.mts @@ -1 +1,20 @@ -export { createApiCommand } from './api.mjs' +import { chalk } from '../../utils/command-helpers.mjs' +import BaseCommand from "../base-command.mjs"; + +export const createApiCommand = (program: BaseCommand) => + program + .command('api') + .argument('[apiMethod]', 'Open API method to run') + .description( + `Run any Netlify API method +For more information on available methods checkout https://open-api.netlify.com/ or run '${chalk.grey( + 'netlify api --list', + )}'`, + ) + .option('-d, --data ', 'Data to use') + .option('--list', 'List out available API methods', false) + .addExamples(['netlify api --list', `netlify api getSite --data '{ "site_id": "123456" }'`]) + .action(async (apiMethod, options, command) => { + const { apiCommand } = await import('./api.mjs') + await apiCommand(apiMethod, options, command ) + } ) From ac0044795ae50f208518fcf5b7fa0f52882ae63a Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:28:40 -0500 Subject: [PATCH 07/67] feat: types --- src/commands/addons/addons.mts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index 20f08eaac04..cab8c8aeb1c 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -18,7 +18,7 @@ export const createAddonsCommand = (program) => { .alias('addon:auth') .argument('', 'Add-on slug') .description('Login to add-on provider') - .action(async (addonName, options, command) => { + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addonsAuth } = await import('./addons-auth.mjs') await addonsAuth(addonName, options, command) }) @@ -30,7 +30,7 @@ export const createAddonsCommand = (program) => { .description('Configure add-on settings') // allow for any flags. Handy for variadic configuration options .allowUnknownOption(true) - .action(async (addonName, options, command) => { + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addonsConfig } = await import('./addons-config.mjs') await addonsConfig(addonName, options, command) }) @@ -45,7 +45,7 @@ Add-ons are a way to extend the functionality of your Netlify site`, ) // allow for any flags. Handy for variadic configuration options .allowUnknownOption(true) - .action(async (addonName, options, command) => { + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addonsCreate } = await import('./addons-create.mjs') await addonsCreate(addonName, options, command) }) @@ -58,7 +58,7 @@ Add-ons are a way to extend the functionality of your Netlify site`, `Remove an add-on extension to your site\nAdd-ons are a way to extend the functionality of your Netlify site`, ) .option('-f, --force', 'delete without prompting (useful for CI)') - .action(async (addonName, options, command) => { + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addonsDelete } = await import('./addons-delete.mjs') await addonsDelete(addonName, options, command) }) @@ -69,7 +69,7 @@ Add-ons are a way to extend the functionality of your Netlify site`, .alias('addon:list') .description(`List currently installed add-ons for site`) .option('--json', 'Output add-on data as JSON') - .action(async (options, command) => { + .action(async (options: OptionValues, command: BaseCommand) => { const {addonsList} = await import('./addons-list.mjs') await addonsList(options, command) }) From b0eed4b4c7e32cf6913dad4cdb0304c810055220 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:35:50 -0500 Subject: [PATCH 08/67] feat: convert build, and types --- src/commands/addons/addons.mts | 8 +------- src/commands/build/build.mts | 37 ++++++---------------------------- src/commands/build/index.mts | 23 ++++++++++++++++++++- 3 files changed, 29 insertions(+), 39 deletions(-) diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index cab8c8aeb1c..326b65d6731 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -6,13 +6,7 @@ const addons = (options: OptionValues, command: BaseCommand) => { command.help() } -/** - * Creates the `netlify addons` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createAddonsCommand = (program) => { +export const createAddonsCommand = (program: BaseCommand) => { program .command('addons:auth', { hidden: true }) .alias('addon:auth') diff --git a/src/commands/build/build.mts b/src/commands/build/build.mts index 2195df3b665..a78324e0651 100644 --- a/src/commands/build/build.mts +++ b/src/commands/build/build.mts @@ -1,10 +1,10 @@ - -import process from 'process' +import { OptionValues } from 'commander' import { getBuildOptions, runBuild } from '../../lib/build.mjs' import { detectFrameworkSettings } from '../../utils/build-info.mjs' import { error, exit, getToken } from '../../utils/command-helpers.mjs' -import { getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs' +import { getEnvelopeEnv } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' /** * @param {import('../../lib/build.mjs').BuildConfig} options @@ -33,13 +33,8 @@ const injectEnv = async function (command, { api, buildOptions, context, siteInf } } -/** - * The build command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const build = async (options, command) => { + +export const build = async (options: OptionValues, command: BaseCommand) => { const { cachedConfig, siteInfo } = command.netlify command.setAnalyticsPayload({ dry: options.dry }) // Retrieve Netlify Build options @@ -53,12 +48,12 @@ const build = async (options, command) => { cachedConfig.config.build.commandOrigin = 'heuristics' } - // @ts-expect-error TS(2345) FIXME: Argument of type '{ cachedConfig: any; packagePath... Remove this comment to see the full error message const buildOptions = await getBuildOptions({ cachedConfig, packagePath: command.workspacePackage, currentDir: command.workingDir, token, + // @ts-expect-error TS(2740) options, }) @@ -74,23 +69,3 @@ const build = async (options, command) => { exit(exitCode) } -/** - * Creates the `netlify build` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createBuildCommand = (program) => - program - .command('build') - .description('Build on your local machine') - .option( - '--context ', - 'Specify a build context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - process.env.CONTEXT || 'production', - ) - .option('--dry', 'Dry run: show instructions without running them', false) - .option('-o, --offline', 'disables any features that require network access', false) - .addExamples(['netlify build']) - .action(build) diff --git a/src/commands/build/index.mts b/src/commands/build/index.mts index 23e97d8a017..90a0a7e33c6 100644 --- a/src/commands/build/index.mts +++ b/src/commands/build/index.mts @@ -1 +1,22 @@ -export { createBuildCommand } from './build.mjs' +import process from 'process' + +import { normalizeContext } from '../../utils/env/index.mjs' +import BaseCommand from "../base-command.mjs"; + +export const createBuildCommand = (program: BaseCommand) => + program + .command('build') + .description('Build on your local machine') + .option( + '--context ', + 'Specify a build context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + process.env.CONTEXT || 'production', + ) + .option('--dry', 'Dry run: show instructions without running them', false) + .option('-o, --offline', 'disables any features that require network access', false) + .addExamples(['netlify build']) + .action(async(options, command) => { + const { build } = await import('./build.mjs') + await build(options, command ) + }) From 86e80166748be09390386f83e07c4caa1a3643ba Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 12:55:19 -0500 Subject: [PATCH 09/67] feat: convert blobs:delelte --- src/commands/blobs/blobs-delete.mts | 19 +------------------ src/commands/blobs/blobs.mts | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/commands/blobs/blobs-delete.mts b/src/commands/blobs/blobs-delete.mts index 30f61d256cb..94973bd2b5e 100644 --- a/src/commands/blobs/blobs-delete.mts +++ b/src/commands/blobs/blobs-delete.mts @@ -1,12 +1,11 @@ import { getStore } from '@netlify/blobs' import { chalk, error as printError } from '../../utils/command-helpers.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' /** * The blobs:delete command */ -const blobsDelete = async (storeName: string, key: string, _options: Record, command: any) => { +export const blobsDelete = async (storeName: string, key: string, _options: Record, command: any) => { const { api, siteInfo } = command.netlify const store = getStore({ apiURL: `${api.scheme}://${api.host}`, @@ -21,19 +20,3 @@ const blobsDelete = async (storeName: string, key: string, _options: Record - program - .command('blobs:delete') - .description(`(Beta) Deletes an object with a given key, if it exists, from a Netlify Blobs store`) - .argument('', 'Name of the store') - .argument('', 'Object key') - .alias('blob:delete') - .hook('preAction', requiresSiteInfo) - .action(blobsDelete) diff --git a/src/commands/blobs/blobs.mts b/src/commands/blobs/blobs.mts index a443c44781a..54b27a7b4fb 100644 --- a/src/commands/blobs/blobs.mts +++ b/src/commands/blobs/blobs.mts @@ -1,4 +1,8 @@ -import { createBlobsDeleteCommand } from './blobs-delete.mjs' +import { OptionValues } from 'commander' + +import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from '../base-command.mjs' + import { createBlobsGetCommand } from './blobs-get.mjs' import { createBlobsListCommand } from './blobs-list.mjs' import { createBlobsSetCommand } from './blobs-set.mjs' @@ -6,15 +10,25 @@ import { createBlobsSetCommand } from './blobs-set.mjs' /** * The blobs command */ -const blobs = (_options: Record, command: any) => { +const blobs = (_options: OptionValues, command: BaseCommand) => { command.help() } /** * Creates the `netlify blobs` command */ -export const createBlobsCommand = (program: any) => { - createBlobsDeleteCommand(program) +export const createBlobsCommand = (program: BaseCommand) => { + program + .command('blobs:delete') + .description(`(Beta) Deletes an object with a given key, if it exists, from a Netlify Blobs store`) + .argument('', 'Name of the store') + .argument('', 'Object key') + .alias('blob:delete') + .hook('preAction', requiresSiteInfo) + .action(async (storeName: string, key: string, _options: OptionValues, command: BaseCommand) => { + const { blobsDelete } = await import('./blobs-delete.mjs') + await blobsDelete(storeName, key, _options, command) + }) createBlobsGetCommand(program) createBlobsListCommand(program) createBlobsSetCommand(program) From 4dc736c7208349953ea3b908bf4f2d11112b50d7 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 13:33:35 -0500 Subject: [PATCH 10/67] feat: convert blobs:get --- src/commands/blobs/blobs-get.mts | 24 +++--------------------- src/commands/blobs/blobs.mts | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/commands/blobs/blobs-get.mts b/src/commands/blobs/blobs-get.mts index c6cd890e666..ae28737d64e 100644 --- a/src/commands/blobs/blobs-get.mts +++ b/src/commands/blobs/blobs-get.mts @@ -2,15 +2,13 @@ import { promises as fs } from 'fs' import { resolve } from 'path' import { getStore } from '@netlify/blobs' +import { OptionValues } from 'commander' import { chalk, error as printError } from '../../utils/command-helpers.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from '../base-command.mjs' -interface Options { - output?: string -} -const blobsGet = async (storeName: string, key: string, options: Options, command: any) => { +export const blobsGet = async (storeName: string, key: string, options: OptionValues, command: BaseCommand) => { const { api, siteInfo } = command.netlify const { output } = options const store = getStore({ @@ -40,19 +38,3 @@ const blobsGet = async (storeName: string, key: string, options: Options, comman console.log(blob) } } - -/** - * Creates the `netlify blobs:get` command - */ -export const createBlobsGetCommand = (program: any) => - program - .command('blobs:get') - .description( - `(Beta) Reads an object with a given key from a Netlify Blobs store and, if it exists, prints the content to the terminal or saves it to a file`, - ) - .argument('', 'Name of the store') - .argument('', 'Object key') - .option('-o, --output ', 'Defines the filesystem path where the blob data should be persisted') - .alias('blob:get') - .hook('preAction', requiresSiteInfo) - .action(blobsGet) diff --git a/src/commands/blobs/blobs.mts b/src/commands/blobs/blobs.mts index 54b27a7b4fb..3c9dbf3d867 100644 --- a/src/commands/blobs/blobs.mts +++ b/src/commands/blobs/blobs.mts @@ -3,7 +3,6 @@ import { OptionValues } from 'commander' import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import BaseCommand from '../base-command.mjs' -import { createBlobsGetCommand } from './blobs-get.mjs' import { createBlobsListCommand } from './blobs-list.mjs' import { createBlobsSetCommand } from './blobs-set.mjs' @@ -29,7 +28,23 @@ export const createBlobsCommand = (program: BaseCommand) => { const { blobsDelete } = await import('./blobs-delete.mjs') await blobsDelete(storeName, key, _options, command) }) - createBlobsGetCommand(program) + + + program + .command('blobs:get') + .description( + `(Beta) Reads an object with a given key from a Netlify Blobs store and, if it exists, prints the content to the terminal or saves it to a file`, + ) + .argument('', 'Name of the store') + .argument('', 'Object key') + .option('-o, --output ', 'Defines the filesystem path where the blob data should be persisted') + .alias('blob:get') + .hook('preAction', requiresSiteInfo) + .action(async(storeName: string, key: string, options: OptionValues, command: BaseCommand) => { + const { blobsGet } = await import('./blobs-get.mjs') + await blobsGet(storeName, key, options, command) + }) + createBlobsListCommand(program) createBlobsSetCommand(program) From 3aa900202fa65283e2e3d2f4d62b9b8377bcb15a Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 13:37:10 -0500 Subject: [PATCH 11/67] feat: convert blobs:list --- src/commands/blobs/blobs-get.mts | 5 ++++- src/commands/blobs/blobs-list.mts | 28 ++++------------------------ src/commands/blobs/blobs.mts | 23 ++++++++++++++++++++--- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/commands/blobs/blobs-get.mts b/src/commands/blobs/blobs-get.mts index ae28737d64e..43cd2a402a1 100644 --- a/src/commands/blobs/blobs-get.mts +++ b/src/commands/blobs/blobs-get.mts @@ -7,8 +7,11 @@ import { OptionValues } from 'commander' import { chalk, error as printError } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' +interface Options extends OptionValues { + output?: string +} -export const blobsGet = async (storeName: string, key: string, options: OptionValues, command: BaseCommand) => { +export const blobsGet = async (storeName: string, key: string, options: Options, command: BaseCommand) => { const { api, siteInfo } = command.netlify const { output } = options const store = getStore({ diff --git a/src/commands/blobs/blobs-list.mts b/src/commands/blobs/blobs-list.mts index 10fbf5de1a1..41e47b76d05 100644 --- a/src/commands/blobs/blobs-list.mts +++ b/src/commands/blobs/blobs-list.mts @@ -1,16 +1,17 @@ import { getStore } from '@netlify/blobs' import AsciiTable from 'ascii-table' +import { OptionValues } from 'commander' import { chalk, error as printError, log, logJson } from '../../utils/command-helpers.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from '../base-command.mjs' -interface Options { +interface Options extends OptionValues { directories?: boolean json?: boolean prefix?: string } -const blobsList = async (storeName: string, options: Options, command: any) => { +export const blobsList = async (storeName: string, options: Options, command: BaseCommand) => { const { api, siteInfo } = command.netlify const store = getStore({ apiURL: `${api.scheme}://${api.host}`, @@ -48,24 +49,3 @@ const blobsList = async (storeName: string, options: Options, command: any) => { return printError(`Could not list blobs from store ${chalk.yellow(storeName)}`) } } - -/** - * Creates the `netlify blobs:list` command - */ -export const createBlobsListCommand = (program: any) => - program - .command('blobs:list') - .description(`(Beta) Lists objects in a Netlify Blobs store`) - .argument('', 'Name of the store') - .option( - '-d, --directories', - `Indicates that keys with the '/' character should be treated as directories, returning a list of sub-directories at a given level rather than all the keys inside them`, - ) - .option( - '-p, --prefix ', - `A string for filtering down the entries; when specified, only the entries whose key starts with that prefix are returned`, - ) - .option('--json', `Output list contents as JSON`) - .alias('blob:list') - .hook('preAction', requiresSiteInfo) - .action(blobsList) diff --git a/src/commands/blobs/blobs.mts b/src/commands/blobs/blobs.mts index 3c9dbf3d867..cff1ab5e9f9 100644 --- a/src/commands/blobs/blobs.mts +++ b/src/commands/blobs/blobs.mts @@ -3,7 +3,6 @@ import { OptionValues } from 'commander' import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import BaseCommand from '../base-command.mjs' -import { createBlobsListCommand } from './blobs-list.mjs' import { createBlobsSetCommand } from './blobs-set.mjs' /** @@ -29,7 +28,6 @@ export const createBlobsCommand = (program: BaseCommand) => { await blobsDelete(storeName, key, _options, command) }) - program .command('blobs:get') .description( @@ -45,7 +43,26 @@ export const createBlobsCommand = (program: BaseCommand) => { await blobsGet(storeName, key, options, command) }) - createBlobsListCommand(program) + program + .command('blobs:list') + .description(`(Beta) Lists objects in a Netlify Blobs store`) + .argument('', 'Name of the store') + .option( + '-d, --directories', + `Indicates that keys with the '/' character should be treated as directories, returning a list of sub-directories at a given level rather than all the keys inside them`, + ) + .option( + '-p, --prefix ', + `A string for filtering down the entries; when specified, only the entries whose key starts with that prefix are returned`, + ) + .option('--json', `Output list contents as JSON`) + .alias('blob:list') + .hook('preAction', requiresSiteInfo) + .action(async(storeName: string, options: OptionValues, command: BaseCommand) => { + const { blobsList } = await import('./blobs-list.mjs') + await blobsList(storeName, options, command) + }) + createBlobsSetCommand(program) return program From 263d1075acf4279c0f6b0d8d3f29ff4765943ec9 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 13:40:55 -0500 Subject: [PATCH 12/67] feat: convert blobs:set --- src/commands/blobs/blobs-set.mts | 23 ++++------------------- src/commands/blobs/blobs.mts | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/commands/blobs/blobs-set.mts b/src/commands/blobs/blobs-set.mts index 477f064629c..84b9a72ffea 100644 --- a/src/commands/blobs/blobs-set.mts +++ b/src/commands/blobs/blobs-set.mts @@ -2,16 +2,18 @@ import { promises as fs } from 'fs' import { resolve } from 'path' import { getStore } from '@netlify/blobs' +import { OptionValues } from 'commander' import { chalk, error as printError, isNodeError } from '../../utils/command-helpers.mjs' import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from '../base-command.mjs' -interface Options { +interface Options extends OptionValues { input?: string } // eslint-disable-next-line max-params -const blobsSet = async (storeName: string, key: string, valueParts: string[], options: Options, command: any) => { +export const blobsSet = async (storeName: string, key: string, valueParts: string[], options: Options, command: BaseCommand) => { const { api, siteInfo } = command.netlify const { input } = options const store = getStore({ @@ -57,20 +59,3 @@ const blobsSet = async (storeName: string, key: string, valueParts: string[], op return printError(`Could not set blob ${chalk.yellow(key)} in store ${chalk.yellow(storeName)}`) } } - -/** - * Creates the `netlify blobs:set` command - */ -export const createBlobsSetCommand = (program: any) => - program - .command('blobs:set') - .description( - `(Beta) Writes to a Netlify Blobs store an object with the data provided in the command or the contents of a file defined by the 'input' parameter`, - ) - .argument('', 'Name of the store') - .argument('', 'Object key') - .argument('[value...]', 'Object value') - .option('-i, --input ', 'Defines the filesystem path where the blob data should be read from') - .alias('blob:set') - .hook('preAction', requiresSiteInfo) - .action(blobsSet) diff --git a/src/commands/blobs/blobs.mts b/src/commands/blobs/blobs.mts index cff1ab5e9f9..d6e42f58744 100644 --- a/src/commands/blobs/blobs.mts +++ b/src/commands/blobs/blobs.mts @@ -3,8 +3,6 @@ import { OptionValues } from 'commander' import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import BaseCommand from '../base-command.mjs' -import { createBlobsSetCommand } from './blobs-set.mjs' - /** * The blobs command */ @@ -63,7 +61,22 @@ export const createBlobsCommand = (program: BaseCommand) => { await blobsList(storeName, options, command) }) - createBlobsSetCommand(program) + program + .command('blobs:set') + .description( + `(Beta) Writes to a Netlify Blobs store an object with the data provided in the command or the contents of a file defined by the 'input' parameter`, + ) + .argument('', 'Name of the store') + .argument('', 'Object key') + .argument('[value...]', 'Object value') + .option('-i, --input ', 'Defines the filesystem path where the blob data should be read from') + .alias('blob:set') + .hook('preAction', requiresSiteInfo) + // eslint-disable-next-line max-params + .action(async(storeName: string, key: string, valueParts: string[], options: OptionValues, command: BaseCommand) => { + const { blobsSet } = await import('./blobs-set.mjs') + await blobsSet(storeName, key, valueParts, options, command) + }) return program .command('blobs') From 197f996089d5c6b9aadcd817b54655df4c950c33 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 13:43:19 -0500 Subject: [PATCH 13/67] feat: remove import --- src/commands/blobs/blobs-set.mts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commands/blobs/blobs-set.mts b/src/commands/blobs/blobs-set.mts index 84b9a72ffea..72caaa4a99e 100644 --- a/src/commands/blobs/blobs-set.mts +++ b/src/commands/blobs/blobs-set.mts @@ -5,7 +5,6 @@ import { getStore } from '@netlify/blobs' import { OptionValues } from 'commander' import { chalk, error as printError, isNodeError } from '../../utils/command-helpers.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import BaseCommand from '../base-command.mjs' interface Options extends OptionValues { From 3819fe5132a3806a1e9fc50f61a738244a640ec6 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 13:54:16 -0500 Subject: [PATCH 14/67] feat: convert completion --- src/commands/completion/completion.mts | 57 ++++++++------------------ src/commands/completion/index.mts | 34 ++++++++++++++- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/src/commands/completion/completion.mts b/src/commands/completion/completion.mts index bb0d68b3dff..1c4ab95f262 100644 --- a/src/commands/completion/completion.mts +++ b/src/commands/completion/completion.mts @@ -1,22 +1,24 @@ import { dirname, join } from 'path' import { fileURLToPath } from 'url' +import { OptionValues } from 'commander' // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'tabt... Remove this comment to see the full error message import { install, uninstall } from 'tabtab' import { generateAutocompletion } from '../../lib/completion/index.mjs' +import { error } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' const completer = join(dirname(fileURLToPath(import.meta.url)), '../../lib/completion/script.mjs') -/** - * The completion:generate command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const completionGenerate = async (options, command) => { +export const completionGenerate = async (options: OptionValues, command: BaseCommand) => { const { parent } = command + if (!parent) { + error(`There has been an error generating the completion script.`) + return + } + generateAutocompletion(parent) await install({ @@ -27,37 +29,12 @@ const completionGenerate = async (options, command) => { console.log(`Completion for ${parent.name()} successful installed!`) } -/** - * Creates the `netlify completion` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createCompletionCommand = (program) => { - program - .command('completion:install') - .alias('completion:generate') - .description('Generates completion script for your preferred shell') - .action(completionGenerate) - - program - .command('completion:uninstall', { hidden: true }) - .alias('completion:remove') - .description('Uninstalls the installed completions') - .addExamples(['netlify completion:uninstall']) - // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. - .action(async (options, command) => { - await uninstall({ - name: command.parent.name(), - }) - }) - - return program - .command('completion') - .description('Generate shell completion script\nRun this command to see instructions for your shell.') - .addExamples(['netlify completion:install']) - // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. - .action((options, command) => { - command.help() - }) +export const completionUninstall = async (options: OptionValues, command: BaseCommand) => { + if (!command.parent) { + error(`There has been an error deleting the completion script.`) + return + } + await uninstall({ + name: command.parent.name(), + }) } diff --git a/src/commands/completion/index.mts b/src/commands/completion/index.mts index 225f54ded06..d3b967125ee 100644 --- a/src/commands/completion/index.mts +++ b/src/commands/completion/index.mts @@ -1 +1,33 @@ -export { createCompletionCommand } from './completion.mjs' +import { OptionValues } from "commander" + +import BaseCommand from "../base-command.mjs" + + +export const createCompletionCommand = (program: BaseCommand) => { + program + .command('completion:install') + .alias('completion:generate') + .description('Generates completion script for your preferred shell') + .action(async(options: OptionValues, command: BaseCommand) => { + const { completionGenerate } = await import('./completion.mjs') + await completionGenerate(options, command) + }) + + program + .command('completion:uninstall', { hidden: true }) + .alias('completion:remove') + .description('Uninstalls the installed completions') + .addExamples(['netlify completion:uninstall']) + .action(async(options: OptionValues, command: BaseCommand) => { + const { completionUninstall } = await import('./completion.mjs') + await completionUninstall(options, command) + }) + + return program + .command('completion') + .description('Generate shell completion script\nRun this command to see instructions for your shell.') + .addExamples(['netlify completion:install']) + .action((options: OptionValues, command: BaseCommand) => { + command.help() + }) +} From 0f8344079e807be2e0bc2ab3895b414b92a31ee9 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:00:05 -0500 Subject: [PATCH 15/67] feat: convert deploy --- src/commands/deploy/deploy.mts | 138 +-------------------------------- src/commands/deploy/index.mts | 129 +++++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 136 deletions(-) diff --git a/src/commands/deploy/deploy.mts b/src/commands/deploy/deploy.mts index bd416fe9d38..d18ddcc63e0 100644 --- a/src/commands/deploy/deploy.mts +++ b/src/commands/deploy/deploy.mts @@ -1,9 +1,8 @@ import { stat } from 'fs/promises' import { basename, resolve } from 'path' -import { env } from 'process' import { runCoreSteps } from '@netlify/build' -import { Option } from 'commander' +import { OptionValues } from 'commander' import inquirer from 'inquirer' import isEmpty from 'lodash/isEmpty.js' import isObject from 'lodash/isObject.js' @@ -35,6 +34,7 @@ import { deploySite } from '../../utils/deploy/deploy-site.mjs' import { getEnvelopeEnv } from '../../utils/env/index.mjs' import { getFunctionsManifestPath, getInternalFunctionsDir } from '../../utils/functions/index.mjs' import openBrowser from '../../utils/open-browser.mjs' +import BaseCommand from '../base-command.mjs' import { link } from '../link/index.mjs' import { sitesCreate } from '../sites/index.mjs' @@ -702,13 +702,7 @@ const prepAndRunDeploy = async ({ return results } -/** - * The deploy command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -export const deploy = async (options, command) => { +export const deploy = async (options: OptionValues, command: BaseCommand) => { const { workingDir } = command const { api, site, siteInfo } = command.netlify const alias = options.alias || options.branch @@ -826,129 +820,3 @@ export const deploy = async (options, command) => { } } -/** - * Creates the `netlify deploy` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createDeployCommand = (program) => - program - .command('deploy') - .description( - `Create a new deploy from the contents of a folder -Deploys from the build settings found in the netlify.toml file, or settings from the API. - -The following environment variables can be used to override configuration file lookups and prompts: - -- \`NETLIFY_AUTH_TOKEN\` - an access token to use when authenticating commands. Keep this value private. -- \`NETLIFY_SITE_ID\` - override any linked site in the current working directory. - -Lambda functions in the function folder can be in the following configurations for deployment: - - -Built Go binaries: ------------------- - -\`\`\` -functions/ -└── nameOfGoFunction -\`\`\` - -Build binaries of your Go language functions into the functions folder as part of your build process. - - -Single file Node.js functions: ------------------------------ - -Build dependency bundled Node.js lambda functions with tools like netlify-lambda, webpack or browserify into the function folder as part of your build process. - -\`\`\` -functions/ -└── nameOfBundledNodeJSFunction.js -\`\`\` - -Unbundled Node.js functions that have dependencies outside or inside of the functions folder: ---------------------------------------------------------------------------------------------- - -You can ship unbundled Node.js functions with the CLI, utilizing top level project dependencies, or a nested package.json. -If you use nested dependencies, be sure to populate the nested node_modules as part of your build process before deploying using npm or yarn. - -\`\`\` -project/ -├── functions -│ ├── functionName/ -│ │ ├── functionName.js (Note the folder and the function name need to match) -│ │ ├── package.json -│ │ └── node_modules/ -│ └── unbundledFunction.js -├── package.json -├── netlify.toml -└── node_modules/ -\`\`\` - -Any mix of these configurations works as well. - - -Node.js function entry points ------------------------------ - -Function entry points are determined by the file name and name of the folder they are in: - -\`\`\` -functions/ -├── aFolderlessFunctionEntrypoint.js -└── functionName/ - ├── notTheEntryPoint.js - └── functionName.js -\`\`\` - -Support for package.json's main field, and intrinsic index.js entrypoints are coming soon.`, - ) - .option('-d, --dir ', 'Specify a folder to deploy') - .option('-f, --functions ', 'Specify a functions folder to deploy') - .option('-p, --prod', 'Deploy to production', false) - .addOption( - new Option( - '--prodIfUnlocked', - 'Old, prefer --prod-if-unlocked. Deploy to production if unlocked, create a draft otherwise', - ) - .default(false) - .hideHelp(true), - ) - .option('--prod-if-unlocked', 'Deploy to production if unlocked, create a draft otherwise', false) - .option( - '--alias ', - 'Specifies the alias for deployment, the string at the beginning of the deploy subdomain. Useful for creating predictable deployment URLs. Avoid setting an alias string to the same value as a deployed branch. `alias` doesn’t create a branch deploy and can’t be used in conjunction with the branch subdomain feature. Maximum 37 characters.', - ) - .option( - '-b, --branch ', - 'Serves the same functionality as --alias. Deprecated and will be removed in future versions', - ) - .option('-o, --open', 'Open site after deploy', false) - .option('-m, --message ', 'A short message to include in the deploy log') - .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) - .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) - .option('--json', 'Output deployment data as JSON') - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('--timeout ', 'Timeout to wait for deployment to finish', (value) => Number.parseInt(value)) - .option('--trigger', 'Trigger a new build of your site on Netlify without uploading local files') - .option('--build', 'Run build command before deploying') - .option('--context ', 'Context to use when resolving build configuration') - .option( - '--skip-functions-cache', - 'Ignore any functions created as part of a previous `build` or `deploy` commands, forcing them to be bundled again as part of the deployment', - false, - ) - .addExamples([ - 'netlify deploy', - 'netlify deploy --site my-first-site', - 'netlify deploy --prod', - 'netlify deploy --prod --open', - 'netlify deploy --prod-if-unlocked', - 'netlify deploy --message "A message with an $ENV_VAR"', - 'netlify deploy --auth $NETLIFY_AUTH_TOKEN', - 'netlify deploy --trigger', - 'netlify deploy --build --context deploy-preview', - ]) - .action(deploy) diff --git a/src/commands/deploy/index.mts b/src/commands/deploy/index.mts index bf1ce8a84d3..3b0fc5d51e9 100644 --- a/src/commands/deploy/index.mts +++ b/src/commands/deploy/index.mts @@ -1 +1,128 @@ -export { createDeployCommand } from './deploy.mjs' +import { env } from 'process' + +import { Option, OptionValues } from 'commander' + +import BaseCommand from '../base-command.mjs' + +export const createDeployCommand = (program: BaseCommand) => + program + .command('deploy') + .description( + `Create a new deploy from the contents of a folder +Deploys from the build settings found in the netlify.toml file, or settings from the API. + +The following environment variables can be used to override configuration file lookups and prompts: + +- \`NETLIFY_AUTH_TOKEN\` - an access token to use when authenticating commands. Keep this value private. +- \`NETLIFY_SITE_ID\` - override any linked site in the current working directory. + +Lambda functions in the function folder can be in the following configurations for deployment: + + +Built Go binaries: +------------------ + +\`\`\` +functions/ +└── nameOfGoFunction +\`\`\` + +Build binaries of your Go language functions into the functions folder as part of your build process. + + +Single file Node.js functions: +----------------------------- + +Build dependency bundled Node.js lambda functions with tools like netlify-lambda, webpack or browserify into the function folder as part of your build process. + +\`\`\` +functions/ +└── nameOfBundledNodeJSFunction.js +\`\`\` + +Unbundled Node.js functions that have dependencies outside or inside of the functions folder: +--------------------------------------------------------------------------------------------- + +You can ship unbundled Node.js functions with the CLI, utilizing top level project dependencies, or a nested package.json. +If you use nested dependencies, be sure to populate the nested node_modules as part of your build process before deploying using npm or yarn. + +\`\`\` +project/ +├── functions +│ ├── functionName/ +│ │ ├── functionName.js (Note the folder and the function name need to match) +│ │ ├── package.json +│ │ └── node_modules/ +│ └── unbundledFunction.js +├── package.json +├── netlify.toml +└── node_modules/ +\`\`\` + +Any mix of these configurations works as well. + + +Node.js function entry points +----------------------------- + +Function entry points are determined by the file name and name of the folder they are in: + +\`\`\` +functions/ +├── aFolderlessFunctionEntrypoint.js +└── functionName/ + ├── notTheEntryPoint.js + └── functionName.js +\`\`\` + +Support for package.json's main field, and intrinsic index.js entrypoints are coming soon.`, + ) + .option('-d, --dir ', 'Specify a folder to deploy') + .option('-f, --functions ', 'Specify a functions folder to deploy') + .option('-p, --prod', 'Deploy to production', false) + .addOption( + new Option( + '--prodIfUnlocked', + 'Old, prefer --prod-if-unlocked. Deploy to production if unlocked, create a draft otherwise', + ) + .default(false) + .hideHelp(true), + ) + .option('--prod-if-unlocked', 'Deploy to production if unlocked, create a draft otherwise', false) + .option( + '--alias ', + 'Specifies the alias for deployment, the string at the beginning of the deploy subdomain. Useful for creating predictable deployment URLs. Avoid setting an alias string to the same value as a deployed branch. `alias` doesn’t create a branch deploy and can’t be used in conjunction with the branch subdomain feature. Maximum 37 characters.', + ) + .option( + '-b, --branch ', + 'Serves the same functionality as --alias. Deprecated and will be removed in future versions', + ) + .option('-o, --open', 'Open site after deploy', false) + .option('-m, --message ', 'A short message to include in the deploy log') + .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) + .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) + .option('--json', 'Output deployment data as JSON') + .option('--timeout ', 'Timeout to wait for deployment to finish', (value) => Number.parseInt(value)) + .option('--trigger', 'Trigger a new build of your site on Netlify without uploading local files') + .option('--build', 'Run build command before deploying') + .option('--context ', 'Context to use when resolving build configuration') + .option( + '--skip-functions-cache', + 'Ignore any functions created as part of a previous `build` or `deploy` commands, forcing them to be bundled again as part of the deployment', + false, + ) + .addExamples([ + 'netlify deploy', + 'netlify deploy --site my-first-site', + 'netlify deploy --prod', + 'netlify deploy --prod --open', + 'netlify deploy --prod-if-unlocked', + 'netlify deploy --message "A message with an $ENV_VAR"', + 'netlify deploy --auth $NETLIFY_AUTH_TOKEN', + 'netlify deploy --trigger', + 'netlify deploy --build --context deploy-preview', + ]) + .action(async (options: OptionValues, command: BaseCommand) => { + const { deploy } = await import('./deploy.mjs') + await deploy(options, command) + }) From e56e4c0c335b9892ccb38be9e6d9cd1e45a00406 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:15:14 -0500 Subject: [PATCH 16/67] feat: convert dev --- src/commands/dev/dev-exec.mts | 36 ++------ src/commands/dev/dev.mts | 150 +-------------------------------- src/commands/dev/index.mts | 152 +++++++++++++++++++++++++++++++++- 3 files changed, 160 insertions(+), 178 deletions(-) diff --git a/src/commands/dev/dev-exec.mts b/src/commands/dev/dev-exec.mts index 14b333e9325..460895f952d 100644 --- a/src/commands/dev/dev-exec.mts +++ b/src/commands/dev/dev-exec.mts @@ -1,15 +1,12 @@ +import { OptionValues } from 'commander' import execa from 'execa' import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.mjs' -import { getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs' +import { getEnvelopeEnv } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The dev:exec command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'cmd' implicitly has an 'any' type. -const devExec = async (cmd, options, command) => { + +export const devExec = async (cmd:string, options: OptionValues, command: BaseCommand) => { const { api, cachedConfig, config, site, siteInfo } = command.netlify let { env } = cachedConfig @@ -24,26 +21,3 @@ const devExec = async (cmd, options, command) => { stdio: 'inherit', }) } - -/** - * Creates the `netlify dev:exec` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createDevExecCommand = (program) => - program - .command('dev:exec') - .argument('<...cmd>', `the command that should be executed`) - .option( - '--context ', - 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - 'dev', - ) - .description( - 'Exec command\nRuns a command within the netlify dev environment, e.g. with env variables from any installed addons', - ) - .allowExcessArguments(true) - .addExamples(['netlify dev:exec npm run bootstrap']) - .action(devExec) diff --git a/src/commands/dev/dev.mts b/src/commands/dev/dev.mts index a06670bf808..7c969b80057 100644 --- a/src/commands/dev/dev.mts +++ b/src/commands/dev/dev.mts @@ -1,14 +1,12 @@ - import process from 'process' -import { Option } from 'commander' +import { OptionValues } from 'commander' import { getBlobsContext } from '../../lib/blobs/blobs.mjs' import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.mjs' import { startFunctionsServer } from '../../lib/functions/server.mjs' import { printBanner } from '../../utils/banner.mjs' import { - BANG, chalk, log, NETLIFYDEV, @@ -19,16 +17,15 @@ import { } from '../../utils/command-helpers.mjs' import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.mjs' import { getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.mjs' -import { getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs' +import { getEnvelopeEnv } from '../../utils/env/index.mjs' import { ensureNetlifyIgnore } from '../../utils/gitignore.mjs' import { getLiveTunnelSlug, startLiveTunnel } from '../../utils/live-tunnel.mjs' import openBrowser from '../../utils/open-browser.mjs' import { generateInspectSettings, startProxyServer } from '../../utils/proxy-server.mjs' import { getProxyUrl } from '../../utils/proxy.mjs' import { runDevTimeline } from '../../utils/run-build.mjs' -import { getGeoCountryArgParser } from '../../utils/validation.mjs' +import BaseCommand from '../base-command.mjs' -import { createDevExecCommand } from './dev-exec.mjs' /** * @@ -69,33 +66,8 @@ const handleLiveTunnel = async ({ api, options, settings, site, state }) => { } } -/** - * @param {string} args - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'args' implicitly has an 'any' type. -const validateShortFlagArgs = (args) => { - if (args.startsWith('=')) { - throw new Error( - `Short flag options like -e or -E don't support the '=' sign - ${chalk.red(BANG)} Supported formats: - netlify dev -e - netlify dev -e 127.0.0.1:9229 - netlify dev -e127.0.0.1:9229 - netlify dev -E - netlify dev -E 127.0.0.1:9229 - netlify dev -E127.0.0.1:9229`, - ) - } - return args -} -/** - * The dev command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const dev = async (options, command) => { +export const dev = async (options: OptionValues, command: BaseCommand) => { log(`${NETLIFYDEV}`) const { api, cachedConfig, config, repositoryRoot, site, siteInfo, state } = command.netlify config.dev = { ...config.dev } @@ -239,117 +211,3 @@ const dev = async (options, command) => { printBanner({ url }) } - -/** - * Creates the `netlify dev` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createDevCommand = (program) => { - createDevExecCommand(program) - - return program - .command('dev') - .alias('develop') - .description( - `Local dev server\nThe dev command will run a local dev server with Netlify's proxy and redirect rules`, - ) - .option('-c ,--command ', 'command to run') - .option( - '--context ', - 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - ) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) - .addOption( - new Option('--targetPort ', 'Old, prefer --target-port. Port of target app server') - .argParser((value) => Number.parseInt(value)) - .hideHelp(true), - ) - .addOption(new Option('--no-open', 'disables the automatic opening of a browser window')) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('--target-port ', 'port of target app server', (value) => Number.parseInt(value)) - .option('--framework ', 'framework to use. Defaults to #auto which automatically detects a framework') - .option('-d ,--dir ', 'dir with static files') - .option('-f ,--functions ', 'specify a functions folder to serve') - .option('-o ,--offline', 'disables any features that require network access') - .option( - '-l, --live [subdomain]', - 'start a public live session; optionally, supply a subdomain to generate a custom URL', - false, - ) - .addOption( - new Option('--functionsPort ', 'Old, prefer --functions-port. Port of functions server') - .argParser((value) => Number.parseInt(value)) - .hideHelp(true), - ) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) - .addOption( - new Option( - '--geo ', - 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location', - ) - .choices(['cache', 'mock', 'update']) - .default('cache'), - ) - .addOption( - new Option( - '--country ', - 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)', - ).argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR')), - ) - .addOption( - new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') - .argParser((value) => Number.parseInt(value)) - .hideHelp(), - ) - .addOption( - new Option( - '-e, --edgeInspect [address]', - 'Old, prefer --edge-inspect. Enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', - ) - .conflicts('edgeInspectBrk') - .argParser(validateShortFlagArgs) - .hideHelp(true), - ) - .addOption( - new Option( - '-e, --edge-inspect [address]', - 'enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', - ) - .conflicts('edgeInspectBrk') - .argParser(validateShortFlagArgs), - ) - .addOption( - new Option( - '-E, --edgeInspectBrk [address]', - 'Old, prefer --edge-inspect-brk. Enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', - ) - .conflicts('edgeInspect') - .hideHelp(true) - .argParser(validateShortFlagArgs), - ) - .addOption( - new Option( - '-E, --edge-inspect-brk [address]', - 'enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', - ) - .conflicts('edgeInspect') - .argParser(validateShortFlagArgs), - ) - .addExamples([ - 'netlify dev', - 'netlify dev -d public', - 'netlify dev -c "hugo server -w" --target-port 1313', - 'netlify dev --context production', - 'netlify dev --edge-inspect', - 'netlify dev --edge-inspect=127.0.0.1:9229', - 'netlify dev --edge-inspect-brk', - 'netlify dev --edge-inspect-brk=127.0.0.1:9229', - 'BROWSER=none netlify dev # disable browser auto opening', - ]) - .action(dev) -} diff --git a/src/commands/dev/index.mts b/src/commands/dev/index.mts index 0c3f7f7f51a..3f9a3f53d59 100644 --- a/src/commands/dev/index.mts +++ b/src/commands/dev/index.mts @@ -1 +1,151 @@ -export { createDevCommand } from './dev.mjs' +import { Option, OptionValues } from 'commander' + +import { + BANG, + chalk, +} from '../../utils/command-helpers.mjs' +import { normalizeContext } from '../../utils/env/index.mjs' +import { getGeoCountryArgParser } from '../../utils/validation.mjs' +import BaseCommand from '../base-command.mjs' + +const validateShortFlagArgs = (args: string) => { + if (args.startsWith('=')) { + throw new Error( + `Short flag options like -e or -E don't support the '=' sign + ${chalk.red(BANG)} Supported formats: + netlify dev -e + netlify dev -e 127.0.0.1:9229 + netlify dev -e127.0.0.1:9229 + netlify dev -E + netlify dev -E 127.0.0.1:9229 + netlify dev -E127.0.0.1:9229`, + ) + } + return args +} + +export const createDevCommand = (program: BaseCommand) => { + program + .command('dev:exec') + .argument('<...cmd>', `the command that should be executed`) + .option( + '--context ', + 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + 'dev', + ) + .description( + 'Exec command\nRuns a command within the netlify dev environment, e.g. with env variables from any installed addons', + ) + .allowExcessArguments(true) + .addExamples(['netlify dev:exec npm run bootstrap']) + .action(async (cmd:string, options: OptionValues, command: BaseCommand) => { + const { devExec } = await import('./dev-exec.mjs') + await devExec(cmd, options, command) + }) + + + return program + .command('dev') + .alias('develop') + .description( + `Local dev server\nThe dev command will run a local dev server with Netlify's proxy and redirect rules`, + ) + .option('-c ,--command ', 'command to run') + .option( + '--context ', + 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + ) + .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) + .addOption( + new Option('--targetPort ', 'Old, prefer --target-port. Port of target app server') + .argParser((value) => Number.parseInt(value)) + .hideHelp(true), + ) + .addOption(new Option('--no-open', 'disables the automatic opening of a browser window')) + .option('--target-port ', 'port of target app server', (value) => Number.parseInt(value)) + .option('--framework ', 'framework to use. Defaults to #auto which automatically detects a framework') + .option('-d ,--dir ', 'dir with static files') + .option('-f ,--functions ', 'specify a functions folder to serve') + .option('-o ,--offline', 'disables any features that require network access') + .option( + '-l, --live [subdomain]', + 'start a public live session; optionally, supply a subdomain to generate a custom URL', + false, + ) + .addOption( + new Option('--functionsPort ', 'Old, prefer --functions-port. Port of functions server') + .argParser((value) => Number.parseInt(value)) + .hideHelp(true), + ) + .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) + .addOption( + new Option( + '--geo ', + 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location', + ) + .choices(['cache', 'mock', 'update']) + .default('cache'), + ) + .addOption( + new Option( + '--country ', + 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)', + ).argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR')), + ) + .addOption( + new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') + .argParser((value) => Number.parseInt(value)) + .hideHelp(), + ) + .addOption( + new Option( + '-e, --edgeInspect [address]', + 'Old, prefer --edge-inspect. Enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', + ) + .conflicts('edgeInspectBrk') + .argParser(validateShortFlagArgs) + .hideHelp(true), + ) + .addOption( + new Option( + '-e, --edge-inspect [address]', + 'enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', + ) + .conflicts('edgeInspectBrk') + .argParser(validateShortFlagArgs), + ) + .addOption( + new Option( + '-E, --edgeInspectBrk [address]', + 'Old, prefer --edge-inspect-brk. Enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', + ) + .conflicts('edgeInspect') + .hideHelp(true) + .argParser(validateShortFlagArgs), + ) + .addOption( + new Option( + '-E, --edge-inspect-brk [address]', + 'enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', + ) + .conflicts('edgeInspect') + .argParser(validateShortFlagArgs), + ) + .addExamples([ + 'netlify dev', + 'netlify dev -d public', + 'netlify dev -c "hugo server -w" --target-port 1313', + 'netlify dev --context production', + 'netlify dev --edge-inspect', + 'netlify dev --edge-inspect=127.0.0.1:9229', + 'netlify dev --edge-inspect-brk', + 'netlify dev --edge-inspect-brk=127.0.0.1:9229', + 'BROWSER=none netlify dev # disable browser auto opening', + ]) + .action(async (options: OptionValues, command: BaseCommand) => { + const { dev } = await import('./dev.mjs') + await dev(options, command) + }) +} From 24b05e20317624b7d9acc6c70d99f27c5152c558 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:25:29 -0500 Subject: [PATCH 17/67] feat: convert env:get --- src/commands/env/env-get.mts | 48 ++++---------------------------- src/commands/env/env.mts | 53 ++++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 60 deletions(-) diff --git a/src/commands/env/env-get.mts b/src/commands/env/env-get.mts index f59901a12ce..57bce0fbd3d 100644 --- a/src/commands/env/env-get.mts +++ b/src/commands/env/env-get.mts @@ -1,16 +1,11 @@ -import { Option } from 'commander' +import { OptionValues } from 'commander' import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' -import { AVAILABLE_CONTEXTS, getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs' +import { AVAILABLE_CONTEXTS, getEnvelopeEnv } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The env:get command - * @param {string} name Environment variable name - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. -const envGet = async (name, options, command) => { + +export const envGet = async (name: string, options: OptionValues, command: BaseCommand) => { const { context, scope } = options const { api, cachedConfig, site } = command.netlify const siteId = site.id @@ -52,36 +47,3 @@ const envGet = async (name, options, command) => { log(value) } - -/** - * Creates the `netlify env:get` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createEnvGetCommand = (program) => - program - .command('env:get') - .argument('', 'Environment variable name') - .option( - '-c, --context ', - 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - 'dev', - ) - .addOption( - new Option('-s, --scope ', 'Specify a scope') - .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) - .default('any'), - ) - .addExamples([ - 'netlify env:get MY_VAR # get value for MY_VAR in dev context', - 'netlify env:get MY_VAR --context production', - 'netlify env:get MY_VAR --context branch:staging', - 'netlify env:get MY_VAR --scope functions', - ]) - .description('Get resolved value of specified environment variable (includes netlify.toml)') - // @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. - .action(async (name, options, command) => { - await envGet(name, options, command) - }) diff --git a/src/commands/env/env.mts b/src/commands/env/env.mts index d89e6c687b5..b9f5893d281 100644 --- a/src/commands/env/env.mts +++ b/src/commands/env/env.mts @@ -1,29 +1,48 @@ - + +import { OptionValues, Option } from 'commander' + +import { normalizeContext } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' + import { createEnvCloneCommand } from './env-clone.mjs' -import { createEnvGetCommand } from './env-get.mjs' import { createEnvImportCommand } from './env-import.mjs' import { createEnvListCommand } from './env-list.mjs' import { createEnvSetCommand } from './env-set.mjs' import { createEnvUnsetCommand } from './env-unset.mjs' -/** - * The env command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const env = (options, command) => { + +const env = (options: OptionValues, command: BaseCommand) => { command.help() } -/** - * Creates the `netlify env` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createEnvCommand = (program) => { - createEnvGetCommand(program) + +export const createEnvCommand = (program: BaseCommand) => { + program + .command('env:get') + .argument('', 'Environment variable name') + .option( + '-c, --context ', + 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + 'dev', + ) + .addOption( + new Option('-s, --scope ', 'Specify a scope') + .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) + .default('any'), + ) + .addExamples([ + 'netlify env:get MY_VAR # get value for MY_VAR in dev context', + 'netlify env:get MY_VAR --context production', + 'netlify env:get MY_VAR --context branch:staging', + 'netlify env:get MY_VAR --scope functions', + ]) + .description('Get resolved value of specified environment variable (includes netlify.toml)') + .action(async (name: string, options: OptionValues, command: BaseCommand) => { + const { envGet } = await import('./env-get.mjs') + await envGet(name, options, command) + }) + createEnvImportCommand(program) createEnvListCommand(program) createEnvSetCommand(program) From 443e21f6ddb853c2851bc3e217c302855ad47b57 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:27:49 -0500 Subject: [PATCH 18/67] feat: convert env:import --- src/commands/env/env-import.mts | 130 ++++++++++++-------------------- src/commands/env/env.mts | 25 +++++- 2 files changed, 70 insertions(+), 85 deletions(-) diff --git a/src/commands/env/env-import.mts b/src/commands/env/env-import.mts index b017e180dc3..cd01d8e54c0 100644 --- a/src/commands/env/env-import.mts +++ b/src/commands/env/env-import.mts @@ -1,65 +1,15 @@ - + import { readFile } from 'fs/promises' - + import AsciiTable from 'ascii-table' -import { Option } from 'commander' +import { OptionValues } from 'commander' import dotenv from 'dotenv' import { exit, log, logJson } from '../../utils/command-helpers.mjs' import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The env:import command - * @param {string} fileName .env file to import - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'fileName' implicitly has an 'any' type. -const envImport = async (fileName, options, command) => { - const { api, cachedConfig, site } = command.netlify - const siteId = site.id - - if (!siteId) { - log('No site id found, please run inside a site folder or `netlify link`') - return false - } - - let importedEnv = {} - try { - const envFileContents = await readFile(fileName, 'utf-8') - importedEnv = dotenv.parse(envFileContents) - } catch (error) { - // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. - log(error.message) - exit(1) - } - - if (Object.keys(importedEnv).length === 0) { - log(`No environment variables found in file ${fileName} to import`) - return false - } - - const { siteInfo } = cachedConfig - - const importIntoService = siteInfo.use_envelope ? importIntoEnvelope : importIntoMongo - const finalEnv = await importIntoService({ api, importedEnv, options, siteInfo }) - - // Return new environment variables of site if using json flag - if (options.json) { - logJson(finalEnv) - return false - } - - // List newly imported environment variables in a table - log(`site: ${siteInfo.name}`) - const table = new AsciiTable(`Imported environment variables`) - - table.setHeading('Key', 'Value') - table.addRowMatrix(Object.entries(importedEnv)) - log(table.toString()) -} /** * Updates the imported env in the site record @@ -128,31 +78,47 @@ const importIntoEnvelope = async ({ api, importedEnv, options, siteInfo }) => { } } -/** - * Creates the `netlify env:import` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createEnvImportCommand = (program) => - program - .command('env:import') - .argument('', '.env file to import') - .addOption( - new Option( - '-r --replaceExisting', - 'Old, prefer --replace-existing. Replace all existing variables instead of merging them with the current ones', - ) - .default(false) - .hideHelp(true), - ) - .option( - '-r, --replace-existing', - 'Replace all existing variables instead of merging them with the current ones', - false, - ) - .description('Import and set environment variables from .env file') - // @ts-expect-error TS(7006) FIXME: Parameter 'fileName' implicitly has an 'any' type. - .action(async (fileName, options, command) => { - await envImport(fileName, options, command) - }) + +export const envImport = async (fileName: string, options: OptionValues, command: BaseCommand) => { + const { api, cachedConfig, site } = command.netlify + const siteId = site.id + + if (!siteId) { + log('No site id found, please run inside a site folder or `netlify link`') + return false + } + + let importedEnv = {} + try { + const envFileContents = await readFile(fileName, 'utf-8') + importedEnv = dotenv.parse(envFileContents) + } catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + log(error.message) + exit(1) + } + + if (Object.keys(importedEnv).length === 0) { + log(`No environment variables found in file ${fileName} to import`) + return false + } + + const { siteInfo } = cachedConfig + + const importIntoService = siteInfo.use_envelope ? importIntoEnvelope : importIntoMongo + const finalEnv = await importIntoService({ api, importedEnv, options, siteInfo }) + + // Return new environment variables of site if using json flag + if (options.json) { + logJson(finalEnv) + return false + } + + // List newly imported environment variables in a table + log(`site: ${siteInfo.name}`) + const table = new AsciiTable(`Imported environment variables`) + + table.setHeading('Key', 'Value') + table.addRowMatrix(Object.entries(importedEnv)) + log(table.toString()) +} diff --git a/src/commands/env/env.mts b/src/commands/env/env.mts index b9f5893d281..4c3e10658a7 100644 --- a/src/commands/env/env.mts +++ b/src/commands/env/env.mts @@ -5,7 +5,6 @@ import { normalizeContext } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' import { createEnvCloneCommand } from './env-clone.mjs' -import { createEnvImportCommand } from './env-import.mjs' import { createEnvListCommand } from './env-list.mjs' import { createEnvSetCommand } from './env-set.mjs' import { createEnvUnsetCommand } from './env-unset.mjs' @@ -15,7 +14,6 @@ const env = (options: OptionValues, command: BaseCommand) => { command.help() } - export const createEnvCommand = (program: BaseCommand) => { program .command('env:get') @@ -43,7 +41,28 @@ export const createEnvCommand = (program: BaseCommand) => { await envGet(name, options, command) }) - createEnvImportCommand(program) + program + .command('env:import') + .argument('', '.env file to import') + .addOption( + new Option( + '-r --replaceExisting', + 'Old, prefer --replace-existing. Replace all existing variables instead of merging them with the current ones', + ) + .default(false) + .hideHelp(true), + ) + .option( + '-r, --replace-existing', + 'Replace all existing variables instead of merging them with the current ones', + false, + ) + .description('Import and set environment variables from .env file') + .action(async (fileName: string, options: OptionValues, command: BaseCommand) => { + const {envImport} = await import('./env-import.mjs') + await envImport(fileName, options, command) + }) + createEnvListCommand(program) createEnvSetCommand(program) createEnvUnsetCommand(program) From d54ad4ba95222de6fb465efec0be625f523f132c Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:29:27 -0500 Subject: [PATCH 19/67] feat: convert env:list --- src/commands/env/env-list.mts | 50 +++-------------------------------- src/commands/env/env.mts | 29 ++++++++++++++++++-- 2 files changed, 31 insertions(+), 48 deletions(-) diff --git a/src/commands/env/env-list.mts b/src/commands/env/env-list.mts index b6bf9853fa7..9aa29349245 100644 --- a/src/commands/env/env-list.mts +++ b/src/commands/env/env-list.mts @@ -1,13 +1,13 @@ import ansiEscapes from 'ansi-escapes' - import AsciiTable from 'ascii-table' import { isCI } from 'ci-info' -import { Option } from 'commander' +import { OptionValues } from 'commander' import inquirer from 'inquirer' import logUpdate from 'log-update' import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' -import { AVAILABLE_CONTEXTS, getEnvelopeEnv, getHumanReadableScopes, normalizeContext } from '../../utils/env/index.mjs' +import { AVAILABLE_CONTEXTS, getEnvelopeEnv, getHumanReadableScopes } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' const MASK_LENGTH = 50 const MASK = '*'.repeat(MASK_LENGTH) @@ -34,14 +34,7 @@ const getTable = ({ environment, hideValues, scopesColumn }) => { return table.toString() } -/** - * The env:list command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const envList = async (options, command) => { +export const envList = async (options: OptionValues, command: BaseCommand) => { const { context, scope } = options const { api, cachedConfig, site } = command.netlify const siteId = site.id @@ -126,38 +119,3 @@ const envList = async (options, command) => { log(`${chalk.cyan('?')} Show values? ${chalk.cyan('Yes')}`) } } - -/** - * Creates the `netlify env:list` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createEnvListCommand = (program) => - program - .command('env:list') - .option( - '-c, --context ', - 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - 'dev', - ) - .option('--json', 'Output environment variables as JSON') - .addOption(new Option('--plain', 'Output environment variables as plaintext').conflicts('json')) - .addOption( - new Option('-s, --scope ', 'Specify a scope') - .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) - .default('any'), - ) - .addExamples([ - 'netlify env:list # list variables with values in the dev context and with any scope', - 'netlify env:list --context production', - 'netlify env:list --context branch:staging', - 'netlify env:list --scope functions', - 'netlify env:list --plain', - ]) - .description('Lists resolved environment variables for site (includes netlify.toml)') - // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. - .action(async (options, command) => { - await envList(options, command) - }) diff --git a/src/commands/env/env.mts b/src/commands/env/env.mts index 4c3e10658a7..5d5406967d1 100644 --- a/src/commands/env/env.mts +++ b/src/commands/env/env.mts @@ -5,7 +5,6 @@ import { normalizeContext } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' import { createEnvCloneCommand } from './env-clone.mjs' -import { createEnvListCommand } from './env-list.mjs' import { createEnvSetCommand } from './env-set.mjs' import { createEnvUnsetCommand } from './env-unset.mjs' @@ -63,7 +62,33 @@ export const createEnvCommand = (program: BaseCommand) => { await envImport(fileName, options, command) }) - createEnvListCommand(program) + program + .command('env:list') + .option( + '-c, --context ', + 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + 'dev', + ) + .option('--json', 'Output environment variables as JSON') + .addOption(new Option('--plain', 'Output environment variables as plaintext').conflicts('json')) + .addOption( + new Option('-s, --scope ', 'Specify a scope') + .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) + .default('any'), + ) + .addExamples([ + 'netlify env:list # list variables with values in the dev context and with any scope', + 'netlify env:list --context production', + 'netlify env:list --context branch:staging', + 'netlify env:list --scope functions', + 'netlify env:list --plain', + ]) + .description('Lists resolved environment variables for site (includes netlify.toml)') + .action(async (options: OptionValues, command: BaseCommand) => { + const {envList} = await import('./env-list.mjs') + await envList(options, command) + }) createEnvSetCommand(program) createEnvUnsetCommand(program) createEnvCloneCommand(program) From 068f730f64cba08ad2a578aaae4c476c5874ec39 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:32:29 -0500 Subject: [PATCH 20/67] feat: convert env:set --- src/commands/env/env-set.mts | 149 ++++++++++++----------------------- src/commands/env/env.mts | 39 ++++++++- 2 files changed, 87 insertions(+), 101 deletions(-) diff --git a/src/commands/env/env-set.mts b/src/commands/env/env-set.mts index 7b2bc0878a5..8d1f407f7d4 100644 --- a/src/commands/env/env-set.mts +++ b/src/commands/env/env-set.mts @@ -1,70 +1,14 @@ - -import { Option } from 'commander' + +import { OptionValues } from 'commander' import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' import { AVAILABLE_CONTEXTS, AVAILABLE_SCOPES, - normalizeContext, translateFromEnvelopeToMongo, } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The env:set command - * @param {string} key Environment variable key - * @param {string} value Value to set to - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. -const envSet = async (key, value, options, command) => { - const { context, scope, secret } = options - - const { api, cachedConfig, site } = command.netlify - const siteId = site.id - - if (!siteId) { - log('No site id found, please run inside a site folder or `netlify link`') - return false - } - - const { siteInfo } = cachedConfig - let finalEnv - - // Get current environment variables set in the UI - if (siteInfo.use_envelope) { - finalEnv = await setInEnvelope({ api, siteInfo, key, value, context, scope, secret }) - } else if (context || scope) { - error( - `To specify a context or scope, please run ${chalk.yellow( - 'netlify open:admin', - )} to open the Netlify UI and opt in to the new environment variables experience from Site settings`, - ) - return false - } else { - finalEnv = await setInMongo({ api, siteInfo, key, value }) - } - - if (!finalEnv) { - return false - } - - // Return new environment variables of site if using json flag - if (options.json) { - logJson(finalEnv) - return false - } - - const withScope = scope ? ` scoped to ${chalk.white(scope)}` : '' - const withSecret = secret ? ` as a ${chalk.blue('secret')}` : '' - const contextType = AVAILABLE_CONTEXTS.includes(context || 'all') ? 'context' : 'branch' - log( - `Set environment variable ${chalk.yellow( - `${key}${value && !secret ? `=${value}` : ''}`, - )}${withScope}${withSecret} in the ${chalk.magenta(context || 'all')} ${contextType}`, - ) -} /** * Updates the env for a site record with a new key/value pair @@ -192,44 +136,51 @@ const setInEnvelope = async ({ api, context, key, scope, secret, siteInfo, value } } -/** - * Creates the `netlify env:set` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createEnvSetCommand = (program) => - program - .command('env:set') - .argument('', 'Environment variable key') - .argument('[value]', 'Value to set to', '') - .option( - '-c, --context ', - 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev") (default: all contexts)', - // spread over an array for variadic options - // @ts-expect-error TS(7006) FIXME: Parameter 'context' implicitly has an 'any' type. - (context, previous = []) => [...previous, normalizeContext(context)], - ) - .addOption( - new Option('-s, --scope ', 'Specify a scope (default: all scopes)').choices([ - 'builds', - 'functions', - 'post-processing', - 'runtime', - ]), + +export const envSet = async (key: string, value: string, options: OptionValues, command: BaseCommand) => { + const { context, scope, secret } = options + + const { api, cachedConfig, site } = command.netlify + const siteId = site.id + + if (!siteId) { + log('No site id found, please run inside a site folder or `netlify link`') + return false + } + + const { siteInfo } = cachedConfig + let finalEnv + + // Get current environment variables set in the UI + if (siteInfo.use_envelope) { + finalEnv = await setInEnvelope({ api, siteInfo, key, value, context, scope, secret }) + } else if (context || scope) { + error( + `To specify a context or scope, please run ${chalk.yellow( + 'netlify open:admin', + )} to open the Netlify UI and opt in to the new environment variables experience from Site settings`, ) - .option('--secret', 'Indicate whether the environment variable value can be read again.') - .description('Set value of environment variable') - .addExamples([ - 'netlify env:set VAR_NAME value # set in all contexts and scopes', - 'netlify env:set VAR_NAME value --context production', - 'netlify env:set VAR_NAME value --context production deploy-preview', - 'netlify env:set VAR_NAME value --context production --secret', - 'netlify env:set VAR_NAME value --scope builds', - 'netlify env:set VAR_NAME value --scope builds functions', - 'netlify env:set VAR_NAME --secret # convert existing variable to secret', - ]) - // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. - .action(async (key, value, options, command) => { - await envSet(key, value, options, command) - }) + return false + } else { + finalEnv = await setInMongo({ api, siteInfo, key, value }) + } + + if (!finalEnv) { + return false + } + + // Return new environment variables of site if using json flag + if (options.json) { + logJson(finalEnv) + return false + } + + const withScope = scope ? ` scoped to ${chalk.white(scope)}` : '' + const withSecret = secret ? ` as a ${chalk.blue('secret')}` : '' + const contextType = AVAILABLE_CONTEXTS.includes(context || 'all') ? 'context' : 'branch' + log( + `Set environment variable ${chalk.yellow( + `${key}${value && !secret ? `=${value}` : ''}`, + )}${withScope}${withSecret} in the ${chalk.magenta(context || 'all')} ${contextType}`, + ) +} diff --git a/src/commands/env/env.mts b/src/commands/env/env.mts index 5d5406967d1..0a0afd390c2 100644 --- a/src/commands/env/env.mts +++ b/src/commands/env/env.mts @@ -5,7 +5,6 @@ import { normalizeContext } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' import { createEnvCloneCommand } from './env-clone.mjs' -import { createEnvSetCommand } from './env-set.mjs' import { createEnvUnsetCommand } from './env-unset.mjs' @@ -89,7 +88,43 @@ export const createEnvCommand = (program: BaseCommand) => { const {envList} = await import('./env-list.mjs') await envList(options, command) }) - createEnvSetCommand(program) + + program + .command('env:set') + .argument('', 'Environment variable key') + .argument('[value]', 'Value to set to', '') + .option( + '-c, --context ', + 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev") (default: all contexts)', + // spread over an array for variadic options + // @ts-expect-error TS(7006) FIXME: Parameter 'context' implicitly has an 'any' type. + (context, previous = []) => [...previous, normalizeContext(context)], + ) + .addOption( + new Option('-s, --scope ', 'Specify a scope (default: all scopes)').choices([ + 'builds', + 'functions', + 'post-processing', + 'runtime', + ]), + ) + .option('--secret', 'Indicate whether the environment variable value can be read again.') + .description('Set value of environment variable') + .addExamples([ + 'netlify env:set VAR_NAME value # set in all contexts and scopes', + 'netlify env:set VAR_NAME value --context production', + 'netlify env:set VAR_NAME value --context production deploy-preview', + 'netlify env:set VAR_NAME value --context production --secret', + 'netlify env:set VAR_NAME value --scope builds', + 'netlify env:set VAR_NAME value --scope builds functions', + 'netlify env:set VAR_NAME --secret # convert existing variable to secret', + ]) + .action(async (key: string, value:string, options: OptionValues, command: BaseCommand) => { + const {envSet} = await import('./env-set.mjs') + await envSet(key, value, options, command) + }) + + createEnvUnsetCommand(program) createEnvCloneCommand(program) From 079e097bb547da0f656ef0936db553709153621e Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:34:07 -0500 Subject: [PATCH 21/67] feat: convert env:unset --- src/commands/env/env-unset.mts | 112 ++++++++++++--------------------- src/commands/env/env.mts | 24 ++++++- 2 files changed, 62 insertions(+), 74 deletions(-) diff --git a/src/commands/env/env-unset.mts b/src/commands/env/env-unset.mts index c5ab1f41671..a796deddc13 100644 --- a/src/commands/env/env-unset.mts +++ b/src/commands/env/env-unset.mts @@ -1,50 +1,9 @@ - -import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' -import { AVAILABLE_CONTEXTS, normalizeContext, translateFromEnvelopeToMongo } from '../../utils/env/index.mjs' - -/** - * The env:unset command - * @param {string} key Environment variable key - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. -const envUnset = async (key, options, command) => { - const { context } = options - const { api, cachedConfig, site } = command.netlify - const siteId = site.id - - if (!siteId) { - log('No site id found, please run inside a site folder or `netlify link`') - return false - } - - const { siteInfo } = cachedConfig - - let finalEnv - if (siteInfo.use_envelope) { - finalEnv = await unsetInEnvelope({ api, context, siteInfo, key }) - } else if (context) { - error( - `To specify a context, please run ${chalk.yellow( - 'netlify open:admin', - )} to open the Netlify UI and opt in to the new environment variables experience from Site settings`, - ) - return false - } else { - finalEnv = await unsetInMongo({ api, siteInfo, key }) - } - // Return new environment variables of site if using json flag - if (options.json) { - logJson(finalEnv) - return false - } +import { OptionValues } from 'commander' - const contextType = AVAILABLE_CONTEXTS.includes(context || 'all') ? 'context' : 'branch' - log(`Unset environment variable ${chalk.yellow(key)} in the ${chalk.magenta(context || 'all')} ${contextType}`) -} +import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' +import { AVAILABLE_CONTEXTS, normalizeContext, translateFromEnvelopeToMongo } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' /** * Deletes a given key from the env of a site record @@ -134,31 +93,40 @@ const unsetInEnvelope = async ({ api, context, key, siteInfo }) => { return env } -/** - * Creates the `netlify env:unset` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createEnvUnsetCommand = (program) => - program - .command('env:unset') - .aliases(['env:delete', 'env:remove']) - .argument('', 'Environment variable key') - .option( - '-c, --context ', - 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev") (default: all contexts)', - // spread over an array for variadic options - // @ts-expect-error TS(7006) FIXME: Parameter 'context' implicitly has an 'any' type. - (context, previous = []) => [...previous, normalizeContext(context)], + +export const envUnset = async (key: string, options: OptionValues, command: BaseCommand) => { + const { context } = options + const { api, cachedConfig, site } = command.netlify + const siteId = site.id + + if (!siteId) { + log('No site id found, please run inside a site folder or `netlify link`') + return false + } + + const { siteInfo } = cachedConfig + + let finalEnv + if (siteInfo.use_envelope) { + finalEnv = await unsetInEnvelope({ api, context, siteInfo, key }) + } else if (context) { + error( + `To specify a context, please run ${chalk.yellow( + 'netlify open:admin', + )} to open the Netlify UI and opt in to the new environment variables experience from Site settings`, ) - .addExamples([ - 'netlify env:unset VAR_NAME # unset in all contexts', - 'netlify env:unset VAR_NAME --context production', - 'netlify env:unset VAR_NAME --context production deploy-preview', - ]) - .description('Unset an environment variable which removes it from the UI') - // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. - .action(async (key, options, command) => { - await envUnset(key, options, command) - }) + return false + } else { + finalEnv = await unsetInMongo({ api, siteInfo, key }) + } + + // Return new environment variables of site if using json flag + if (options.json) { + logJson(finalEnv) + return false + } + + const contextType = AVAILABLE_CONTEXTS.includes(context || 'all') ? 'context' : 'branch' + log(`Unset environment variable ${chalk.yellow(key)} in the ${chalk.magenta(context || 'all')} ${contextType}`) +} + diff --git a/src/commands/env/env.mts b/src/commands/env/env.mts index 0a0afd390c2..903099187eb 100644 --- a/src/commands/env/env.mts +++ b/src/commands/env/env.mts @@ -5,7 +5,6 @@ import { normalizeContext } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' import { createEnvCloneCommand } from './env-clone.mjs' -import { createEnvUnsetCommand } from './env-unset.mjs' const env = (options: OptionValues, command: BaseCommand) => { @@ -125,7 +124,28 @@ export const createEnvCommand = (program: BaseCommand) => { }) - createEnvUnsetCommand(program) + program + .command('env:unset') + .aliases(['env:delete', 'env:remove']) + .argument('', 'Environment variable key') + .option( + '-c, --context ', + 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev") (default: all contexts)', + // spread over an array for variadic options + // @ts-expect-error TS(7006) FIXME: Parameter 'context' implicitly has an 'any' type. + (context, previous = []) => [...previous, normalizeContext(context)], + ) + .addExamples([ + 'netlify env:unset VAR_NAME # unset in all contexts', + 'netlify env:unset VAR_NAME --context production', + 'netlify env:unset VAR_NAME --context production deploy-preview', + ]) + .description('Unset an environment variable which removes it from the UI') + .action(async (key: string, options: OptionValues, command: BaseCommand) => { + const {envUnset} = await import('./env-unset.mjs') + await envUnset(key, options, command) + }) + createEnvCloneCommand(program) return program From 81c0e28a6e1dc4e6af10aef2772e34a4ae0c3dfd Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:36:56 -0500 Subject: [PATCH 22/67] feat: convert env:clone --- src/commands/env/env-clone.mts | 205 +++++++++++++++------------------ src/commands/env/env.mts | 15 ++- 2 files changed, 104 insertions(+), 116 deletions(-) diff --git a/src/commands/env/env-clone.mts b/src/commands/env/env-clone.mts index 74b475f11fc..0fc041d05b7 100644 --- a/src/commands/env/env-clone.mts +++ b/src/commands/env/env-clone.mts @@ -1,6 +1,9 @@ - + +import { OptionValues } from 'commander' + import { chalk, error as logError, log } from '../../utils/command-helpers.mjs' import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../../utils/env/index.mjs' +import BaseCommand from '../base-command.mjs' // @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type. const safeGetSite = async (api, siteId) => { @@ -11,68 +14,80 @@ const safeGetSite = async (api, siteId) => { return { error } } } - /** - * The env:clone command - * @param {string} siteIdA Site (From) - * @param {string} siteIdB Site (To) - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command + * Copies the env from a site configured with Envelope to a site not configured with Envelope * @returns {Promise} */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const envClone = async (options, command) => { - const { api, site } = command.netlify +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const envelopeToMongo = async ({ api, siteFrom, siteTo }) => { + const envelopeVariables = await api.getEnvVars({ accountId: siteFrom.account_slug, siteId: siteFrom.id }) + const envFrom = translateFromEnvelopeToMongo(envelopeVariables) - if (!site.id && !options.from) { - log( - 'Please include the source site Id as the `--from` option, or run `netlify link` to link this folder to a Netlify site', - ) + if (Object.keys(envFrom).length === 0) { + log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`) return false } - const siteId = { - from: options.from || site.id, - to: options.to, + const envTo = siteTo.build_settings.env || {} + + // Merge from site A to site B + const mergedEnv = { + ...envTo, + ...envFrom, } - const [{ data: siteFrom, error: errorFrom }, { data: siteTo, error: errorTo }] = await Promise.all([ - safeGetSite(api, siteId.from), - safeGetSite(api, siteId.to), + // Apply environment variable updates + await api.updateSite({ + siteId: siteTo.id, + body: { + build_settings: { + env: mergedEnv, + }, + }, + }) + + return true +} + +/** + * Copies the env from a site configured with Envelope to a different site configured with Envelope + * @returns {Promise} + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const envelopeToEnvelope = async ({ api, siteFrom, siteTo }) => { + const [envelopeFrom, envelopeTo] = await Promise.all([ + api.getEnvVars({ accountId: siteFrom.account_slug, siteId: siteFrom.id }), + api.getEnvVars({ accountId: siteTo.account_slug, siteId: siteTo.id }), ]) - if (errorFrom) { - logError(`Can't find site with id ${chalk.bold(siteId.from)}. Please make sure the site exists.`) - return false - } + // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message + const keysFrom = envelopeFrom.map(({ key }) => key) - if (errorTo) { - logError(`Can't find site with id ${chalk.bold(siteId.to)}. Please make sure the site exists.`) + if (keysFrom.length === 0) { + log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`) return false } - // determine if siteFrom and/or siteTo is on Envelope - let method - if (!siteFrom.use_envelope && !siteTo.use_envelope) { - method = mongoToMongo - } else if (!siteFrom.use_envelope && siteTo.use_envelope) { - method = mongoToEnvelope - } else if (siteFrom.use_envelope && !siteTo.use_envelope) { - method = envelopeToMongo - } else { - method = envelopeToEnvelope - } - const success = await method({ api, siteFrom, siteTo }) + const accountId = siteTo.account_slug + const siteId = siteTo.id + // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message + const envVarsToDelete = envelopeTo.filter(({ key }) => keysFrom.includes(key)) + // 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 + await Promise.all(envVarsToDelete.map(({ key }) => api.deleteEnvVar({ accountId, siteId, key }))) - if (!success) { - return false + // hit create endpoint + try { + await api.createEnvVars({ accountId, siteId, body: envelopeFrom }) + } catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + throw error.json ? error.json.msg : error } - log(`Successfully cloned environment variables from ${chalk.green(siteFrom.name)} to ${chalk.green(siteTo.name)}`) - return true } + /** * Copies the env from a site not configured with Envelope to a different site not configured with Envelope * @returns {Promise} @@ -149,91 +164,55 @@ const mongoToEnvelope = async ({ api, siteFrom, siteTo }) => { return true } -/** - * Copies the env from a site configured with Envelope to a site not configured with Envelope - * @returns {Promise} - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message -const envelopeToMongo = async ({ api, siteFrom, siteTo }) => { - const envelopeVariables = await api.getEnvVars({ accountId: siteFrom.account_slug, siteId: siteFrom.id }) - const envFrom = translateFromEnvelopeToMongo(envelopeVariables) - if (Object.keys(envFrom).length === 0) { - log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`) +export const envClone = async (options: OptionValues, command: BaseCommand) => { + const { api, site } = command.netlify + + if (!site.id && !options.from) { + log( + 'Please include the source site Id as the `--from` option, or run `netlify link` to link this folder to a Netlify site', + ) return false } - const envTo = siteTo.build_settings.env || {} - - // Merge from site A to site B - const mergedEnv = { - ...envTo, - ...envFrom, + const siteId = { + from: options.from || site.id, + to: options.to, } - // Apply environment variable updates - await api.updateSite({ - siteId: siteTo.id, - body: { - build_settings: { - env: mergedEnv, - }, - }, - }) - - return true -} - -/** - * Copies the env from a site configured with Envelope to a different site configured with Envelope - * @returns {Promise} - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message -const envelopeToEnvelope = async ({ api, siteFrom, siteTo }) => { - const [envelopeFrom, envelopeTo] = await Promise.all([ - api.getEnvVars({ accountId: siteFrom.account_slug, siteId: siteFrom.id }), - api.getEnvVars({ accountId: siteTo.account_slug, siteId: siteTo.id }), + const [{ data: siteFrom, error: errorFrom }, { data: siteTo, error: errorTo }] = await Promise.all([ + safeGetSite(api, siteId.from), + safeGetSite(api, siteId.to), ]) - // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message - const keysFrom = envelopeFrom.map(({ key }) => key) + if (errorFrom) { + logError(`Can't find site with id ${chalk.bold(siteId.from)}. Please make sure the site exists.`) + return false + } - if (keysFrom.length === 0) { - log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`) + if (errorTo) { + logError(`Can't find site with id ${chalk.bold(siteId.to)}. Please make sure the site exists.`) return false } - const accountId = siteTo.account_slug - const siteId = siteTo.id - // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message - const envVarsToDelete = envelopeTo.filter(({ key }) => keysFrom.includes(key)) - // 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 - await Promise.all(envVarsToDelete.map(({ key }) => api.deleteEnvVar({ accountId, siteId, key }))) + // determine if siteFrom and/or siteTo is on Envelope + let method + if (!siteFrom.use_envelope && !siteTo.use_envelope) { + method = mongoToMongo + } else if (!siteFrom.use_envelope && siteTo.use_envelope) { + method = mongoToEnvelope + } else if (siteFrom.use_envelope && !siteTo.use_envelope) { + method = envelopeToMongo + } else { + method = envelopeToEnvelope + } + const success = await method({ api, siteFrom, siteTo }) - // hit create endpoint - try { - await api.createEnvVars({ accountId, siteId, body: envelopeFrom }) - } catch (error) { - // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. - throw error.json ? error.json.msg : error + if (!success) { + return false } + log(`Successfully cloned environment variables from ${chalk.green(siteFrom.name)} to ${chalk.green(siteTo.name)}`) + return true } - -/** - * Creates the `netlify env:clone` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createEnvCloneCommand = (program) => - program - .command('env:clone') - .alias('env:migrate') - .option('-f, --from ', 'Site ID (From)') - .requiredOption('-t, --to ', 'Site ID (To)') - .description(`Clone environment variables from one site to another`) - .addExamples(['netlify env:clone --to ', 'netlify env:clone --to --from ']) - .action(envClone) diff --git a/src/commands/env/env.mts b/src/commands/env/env.mts index 903099187eb..1adc131702e 100644 --- a/src/commands/env/env.mts +++ b/src/commands/env/env.mts @@ -4,8 +4,6 @@ import { OptionValues, Option } from 'commander' import { normalizeContext } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' -import { createEnvCloneCommand } from './env-clone.mjs' - const env = (options: OptionValues, command: BaseCommand) => { command.help() @@ -146,7 +144,18 @@ export const createEnvCommand = (program: BaseCommand) => { await envUnset(key, options, command) }) - createEnvCloneCommand(program) + program + .command('env:clone') + .alias('env:migrate') + .option('-f, --from ', 'Site ID (From)') + .requiredOption('-t, --to ', 'Site ID (To)') + .description(`Clone environment variables from one site to another`) + .addExamples(['netlify env:clone --to ', 'netlify env:clone --to --from ']) + .action(async (options: OptionValues, command: BaseCommand) => { + const {envClone} = await import('./env-clone.mjs') + await envClone(options, command) + }) + return program .command('env') From bd351d411166a3ebb63db395c8f7b1b2ad88e003 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:50:35 -0500 Subject: [PATCH 23/67] feat: convert functions:build --- src/commands/functions/functions-build.mts | 28 ++++-------------- src/commands/functions/functions.mts | 34 +++++++++++----------- 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/src/commands/functions/functions-build.mts b/src/commands/functions/functions-build.mts index 1ee96b123a8..c1b3e23f441 100644 --- a/src/commands/functions/functions-build.mts +++ b/src/commands/functions/functions-build.mts @@ -1,18 +1,15 @@ - + import { mkdir } from 'fs/promises' import { zipFunctions } from '@netlify/zip-it-and-ship-it' +import { OptionValues } from 'commander' import { NETLIFYDEVERR, NETLIFYDEVLOG, exit, log } from '../../utils/command-helpers.mjs' import { getFunctionsDir } from '../../utils/functions/index.mjs' +import BaseCommand from '../base-command.mjs' + -/** - * The functions:build command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const functionsBuild = async (options, command) => { +export const functionsBuild = async (options: OptionValues, command: BaseCommand) => { const { config } = command.netlify const src = options.src || config.build.functionsSource @@ -44,18 +41,3 @@ const functionsBuild = async (options, command) => { zipFunctions(src, dst, { skipGo: true }) log(`${NETLIFYDEVLOG} Functions built to `, dst) } - -/** - * Creates the `netlify functions:build` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createFunctionsBuildCommand = (program) => - program - .command('functions:build') - .alias('function:build') - .description('Build functions locally') - .option('-f, --functions ', 'Specify a functions directory to build to') - .option('-s, --src ', 'Specify the source directory for the functions') - .action(functionsBuild) diff --git a/src/commands/functions/functions.mts b/src/commands/functions/functions.mts index f24daca4a09..1089e40e4e6 100644 --- a/src/commands/functions/functions.mts +++ b/src/commands/functions/functions.mts @@ -1,30 +1,30 @@ - + +import { OptionValues } from 'commander' + import { chalk } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' -import { createFunctionsBuildCommand } from './functions-build.mjs' import { createFunctionsCreateCommand } from './functions-create.mjs' import { createFunctionsInvokeCommand } from './functions-invoke.mjs' import { createFunctionsListCommand } from './functions-list.mjs' import { createFunctionsServeCommand } from './functions-serve.mjs' -/** - * The functions command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const functions = (options, command) => { +const functions = (options: OptionValues, command: BaseCommand) => { command.help() } -/** - * Creates the `netlify functions` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createFunctionsCommand = (program) => { - createFunctionsBuildCommand(program) +export const createFunctionsCommand = (program: BaseCommand) => { + program + .command('functions:build') + .alias('function:build') + .description('Build functions locally') + .option('-f, --functions ', 'Specify a functions directory to build to') + .option('-s, --src ', 'Specify the source directory for the functions') + .action(async(options: OptionValues, command: BaseCommand) => { + const { functionsBuild } = await import('./functions-build.mjs') + await functionsBuild(options, command) + }) + createFunctionsCreateCommand(program) createFunctionsInvokeCommand(program) createFunctionsListCommand(program) From c3c01405584c8ae6b5b1cb5c113a7852e9d7273f Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:53:10 -0500 Subject: [PATCH 24/67] feat: convert functions:create --- src/commands/functions/functions-create.mts | 36 +++------------------ src/commands/functions/functions.mts | 21 ++++++++++-- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/commands/functions/functions-create.mts b/src/commands/functions/functions-create.mts index 09927b58612..18517649c0c 100644 --- a/src/commands/functions/functions-create.mts +++ b/src/commands/functions/functions-create.mts @@ -1,4 +1,4 @@ - + import cp from 'child_process' import fs from 'fs' import { mkdir, readdir, unlink } from 'fs/promises' @@ -8,6 +8,7 @@ import process from 'process' import { fileURLToPath, pathToFileURL } from 'url' import { promisify } from 'util' +import { OptionValues } from 'commander' // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'copy... Remove this comment to see the full error message import copyTemplateDirOriginal from 'copy-template-dir' import { findUp } from 'find-up' @@ -24,6 +25,7 @@ import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.mjs' // @ts-expect-error TS(7034) FIXME: Variable 'execa' implicitly has type 'any' in some... Remove this comment to see the full error message import execa from '../../utils/execa.mjs' import { readRepoURL, validateRepoURL } from '../../utils/read-repo-url.mjs' +import BaseCommand from '../base-command.mjs' const copyTemplateDir = promisify(copyTemplateDirOriginal) @@ -745,14 +747,8 @@ const ensureFunctionPathIsOk = function (functionsDir, name) { return functionPath } -/** - * The functions:create command - * @param {string} name - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. -const functionsCreate = async (name, options, command) => { + +export const functionsCreate = async (name: string, options: OptionValues, command: BaseCommand) => { const functionType = await selectTypeOfFunc() const functionsDir = functionType === 'edge' ? await ensureEdgeFuncDirExists(command) : await ensureFunctionDirExists(command) @@ -761,25 +757,3 @@ const functionsCreate = async (name, options, command) => { const mainFunc = options.url ? downloadFromURL : scaffoldFromTemplate await mainFunc(command, options, name, functionsDir, functionType) } - -/** - * Creates the `netlify functions:create` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createFunctionsCreateCommand = (program) => - program - .command('functions:create') - .alias('function:create') - .argument('[name]', 'name of your new function file inside your functions directory') - .description('Create a new function locally') - .option('-n, --name ', 'function name') - .option('-u, --url ', 'pull template from URL') - .option('-l, --language ', 'function language') - .addExamples([ - 'netlify functions:create', - 'netlify functions:create hello-world', - 'netlify functions:create --name hello-world', - ]) - .action(functionsCreate) diff --git a/src/commands/functions/functions.mts b/src/commands/functions/functions.mts index 1089e40e4e6..4cc914aadbc 100644 --- a/src/commands/functions/functions.mts +++ b/src/commands/functions/functions.mts @@ -4,7 +4,6 @@ import { OptionValues } from 'commander' import { chalk } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' -import { createFunctionsCreateCommand } from './functions-create.mjs' import { createFunctionsInvokeCommand } from './functions-invoke.mjs' import { createFunctionsListCommand } from './functions-list.mjs' import { createFunctionsServeCommand } from './functions-serve.mjs' @@ -25,7 +24,25 @@ export const createFunctionsCommand = (program: BaseCommand) => { await functionsBuild(options, command) }) - createFunctionsCreateCommand(program) + program + .command('functions:create') + .alias('function:create') + .argument('[name]', 'name of your new function file inside your functions directory') + .description('Create a new function locally') + .option('-n, --name ', 'function name') + .option('-u, --url ', 'pull template from URL') + .option('-l, --language ', 'function language') + .addExamples([ + 'netlify functions:create', + 'netlify functions:create hello-world', + 'netlify functions:create --name hello-world', + ]) + .action(async(name: string, options: OptionValues, command: BaseCommand) => { + const { functionsCreate } = await import('./functions-create.mjs') + await functionsCreate(name, options, command) + }) + + createFunctionsInvokeCommand(program) createFunctionsListCommand(program) createFunctionsServeCommand(program) From 21db90475f0010694d0324a241a77e2cabd34dc5 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:55:20 -0500 Subject: [PATCH 25/67] feat: convert functions:invoke --- src/commands/functions/functions-invoke.mts | 54 ++------------------- src/commands/functions/functions.mts | 39 ++++++++++++++- 2 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/commands/functions/functions-invoke.mts b/src/commands/functions/functions-invoke.mts index cd270098b3c..e3ba4dce4fd 100644 --- a/src/commands/functions/functions-invoke.mts +++ b/src/commands/functions/functions-invoke.mts @@ -1,14 +1,16 @@ - + import fs from 'fs' import { createRequire } from 'module' import path from 'path' +import { OptionValues } from 'commander' import inquirer from 'inquirer' // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'node... Remove this comment to see the full error message import fetch from 'node-fetch' import { NETLIFYDEVWARN, chalk, error, exit } from '../../utils/command-helpers.mjs' import { BACKGROUND, CLOCKWORK_USERAGENT, getFunctions } from '../../utils/functions/index.mjs' +import BaseCommand from '../base-command.mjs' const require = createRequire(import.meta.url) @@ -144,14 +146,7 @@ const getFunctionToTrigger = function (options, argumentName) { return argumentName } -/** - * The functions:invoke command - * @param {string} nameArgument - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'nameArgument' implicitly has an 'any' t... Remove this comment to see the full error message -const functionsInvoke = async (nameArgument, options, command) => { +export const functionsInvoke = async (nameArgument: string, options: OptionValues, command: BaseCommand) => { const { config, relConfigFilePath } = command.netlify const functionsDir = options.functions || (config.dev && config.dev.functions) || config.functionsDirectory @@ -245,44 +240,3 @@ const functionsInvoke = async (nameArgument, options, command) => { error(`Ran into an error invoking your function: ${error_.message}`) } } - -/** - * Creates the `netlify functions:invoke` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createFunctionsInvokeCommand = (program) => - program - .command('functions:invoke') - .alias('function:trigger') - .argument('[name]', 'function name to invoke') - .description( - `Trigger a function while in netlify dev with simulated data, good for testing function calls including Netlify's Event Triggered Functions`, - ) - .option('-n, --name ', 'function name to invoke') - .option('-f, --functions ', 'Specify a functions folder to parse, overriding netlify.toml') - .option('-q, --querystring ', 'Querystring to add to your function invocation') - .option('-p, --payload ', 'Supply POST payload in stringified json, or a path to a json file') - // TODO: refactor to not need the `undefined` state by removing the --identity flag (value `identity` will be then always defined to true or false) - .option( - '--identity', - 'simulate Netlify Identity authentication JWT. pass --identity to affirm unauthenticated request', - ) - .option( - '--no-identity', - 'simulate Netlify Identity authentication JWT. pass --no-identity to affirm unauthenticated request', - ) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('--port ', 'Port where netlify dev is accessible. e.g. 8888', (value) => Number.parseInt(value)) - .addExamples([ - 'netlify functions:invoke', - 'netlify functions:invoke myfunction', - 'netlify functions:invoke --name myfunction', - 'netlify functions:invoke --name myfunction --identity', - 'netlify functions:invoke --name myfunction --no-identity', - `netlify functions:invoke myfunction --payload '{"foo": 1}'`, - 'netlify functions:invoke myfunction --querystring "foo=1', - 'netlify functions:invoke myfunction --payload "./pathTo.json"', - ]) - .action(functionsInvoke) diff --git a/src/commands/functions/functions.mts b/src/commands/functions/functions.mts index 4cc914aadbc..a79f7b70485 100644 --- a/src/commands/functions/functions.mts +++ b/src/commands/functions/functions.mts @@ -4,7 +4,6 @@ import { OptionValues } from 'commander' import { chalk } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' -import { createFunctionsInvokeCommand } from './functions-invoke.mjs' import { createFunctionsListCommand } from './functions-list.mjs' import { createFunctionsServeCommand } from './functions-serve.mjs' @@ -43,7 +42,43 @@ export const createFunctionsCommand = (program: BaseCommand) => { }) - createFunctionsInvokeCommand(program) + program + .command('functions:invoke') + .alias('function:trigger') + .argument('[name]', 'function name to invoke') + .description( + `Trigger a function while in netlify dev with simulated data, good for testing function calls including Netlify's Event Triggered Functions`, + ) + .option('-n, --name ', 'function name to invoke') + .option('-f, --functions ', 'Specify a functions folder to parse, overriding netlify.toml') + .option('-q, --querystring ', 'Querystring to add to your function invocation') + .option('-p, --payload ', 'Supply POST payload in stringified json, or a path to a json file') + // TODO: refactor to not need the `undefined` state by removing the --identity flag (value `identity` will be then always defined to true or false) + .option( + '--identity', + 'simulate Netlify Identity authentication JWT. pass --identity to affirm unauthenticated request', + ) + .option( + '--no-identity', + 'simulate Netlify Identity authentication JWT. pass --no-identity to affirm unauthenticated request', + ) + .option('--port ', 'Port where netlify dev is accessible. e.g. 8888', (value) => Number.parseInt(value)) + .addExamples([ + 'netlify functions:invoke', + 'netlify functions:invoke myfunction', + 'netlify functions:invoke --name myfunction', + 'netlify functions:invoke --name myfunction --identity', + 'netlify functions:invoke --name myfunction --no-identity', + `netlify functions:invoke myfunction --payload '{"foo": 1}'`, + 'netlify functions:invoke myfunction --querystring "foo=1', + 'netlify functions:invoke myfunction --payload "./pathTo.json"', + ]) + .action(async(name: string, options: OptionValues, command: BaseCommand) => { + const { functionsInvoke } = await import('./functions-invoke.mjs') + await functionsInvoke(name, options, command) + }) + + createFunctionsListCommand(program) createFunctionsServeCommand(program) From 836382773769d4a96bff9ab195a2920c23bb9747 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:56:55 -0500 Subject: [PATCH 26/67] feat: convert functions:list --- src/commands/functions/functions-list.mts | 32 +++-------------------- src/commands/functions/functions.mts | 20 ++++++++++++-- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/commands/functions/functions-list.mts b/src/commands/functions/functions-list.mts index 60839a4042a..ac2a08f49d4 100644 --- a/src/commands/functions/functions-list.mts +++ b/src/commands/functions/functions-list.mts @@ -1,8 +1,9 @@ import AsciiTable from 'ascii-table' +import { OptionValues } from 'commander' import { exit, log, logJson } from '../../utils/command-helpers.mjs' import { getFunctions, getFunctionsDir } from '../../utils/functions/index.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from '../base-command.mjs' // @ts-expect-error TS(7006) FIXME: Parameter 'deployedFunctions' implicitly has an 'a... Remove this comment to see the full error message const normalizeFunction = function (deployedFunctions, { name, urlPath: url }) { @@ -11,13 +12,7 @@ const normalizeFunction = function (deployedFunctions, { name, urlPath: url }) { return { name, url, isDeployed } } -/** - * The functions:list command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const functionsList = async (options, command) => { +export const functionsList = async (options: OptionValues, command: BaseCommand) => { const { config, relConfigFilePath, siteInfo } = command.netlify const deploy = siteInfo.published_deploy || {} @@ -55,24 +50,3 @@ const functionsList = async (options, command) => { }) log(table.toString()) } - -/** - * Creates the `netlify functions:list` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createFunctionsListCommand = (program) => - program - .command('functions:list') - .alias('function:list') - .description( - `List functions that exist locally -Helpful for making sure that you have formatted your functions correctly - -NOT the same as listing the functions that have been deployed. For that info you need to go to your Netlify deploy log.`, - ) - .option('-f, --functions ', 'Specify a functions directory to list') - .option('--json', 'Output function data as JSON') - .hook('preAction', requiresSiteInfo) - .action(functionsList) diff --git a/src/commands/functions/functions.mts b/src/commands/functions/functions.mts index a79f7b70485..8c91b2d79c9 100644 --- a/src/commands/functions/functions.mts +++ b/src/commands/functions/functions.mts @@ -2,9 +2,9 @@ import { OptionValues } from 'commander' import { chalk } from '../../utils/command-helpers.mjs' +import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import BaseCommand from '../base-command.mjs' -import { createFunctionsListCommand } from './functions-list.mjs' import { createFunctionsServeCommand } from './functions-serve.mjs' const functions = (options: OptionValues, command: BaseCommand) => { @@ -79,7 +79,23 @@ export const createFunctionsCommand = (program: BaseCommand) => { }) - createFunctionsListCommand(program) + program + .command('functions:list') + .alias('function:list') + .description( + `List functions that exist locally +Helpful for making sure that you have formatted your functions correctly + +NOT the same as listing the functions that have been deployed. For that info you need to go to your Netlify deploy log.`, + ) + .option('-f, --functions ', 'Specify a functions directory to list') + .option('--json', 'Output function data as JSON') + .hook('preAction', requiresSiteInfo) + .action(async(options: OptionValues, command: BaseCommand) => { + const { functionsList } = await import('./functions-list.mjs') + await functionsList(options, command) + }) + createFunctionsServeCommand(program) const name = chalk.greenBright('`functions`') From 3896e25d776cb971e41db7900686571c00f2cbee Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 14:58:14 -0500 Subject: [PATCH 27/67] feat: convert functions: serve --- src/commands/functions/functions-serve.mts | 31 +++++----------------- src/commands/functions/functions.mts | 15 ++++++++--- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/commands/functions/functions-serve.mts b/src/commands/functions/functions-serve.mts index 4c56c9d8aff..af30337f69a 100644 --- a/src/commands/functions/functions-serve.mts +++ b/src/commands/functions/functions-serve.mts @@ -1,21 +1,19 @@ - + import { join } from 'path' +import { OptionValues } from 'commander' + import { startFunctionsServer } from '../../lib/functions/server.mjs' import { printBanner } from '../../utils/banner.mjs' import { acquirePort, getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.mjs' import { getFunctionsDir } from '../../utils/functions/index.mjs' import { getProxyUrl } from '../../utils/proxy.mjs' +import BaseCommand from '../base-command.mjs' const DEFAULT_PORT = 9999 -/** - * The functions:serve command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const functionsServe = async (options, command) => { + +export const functionsServe = async (options: OptionValues, command: BaseCommand) => { const { api, config, site, siteInfo, state } = command.netlify const functionsDir = getFunctionsDir({ options, config }, join('netlify', 'functions')) @@ -63,20 +61,3 @@ const functionsServe = async (options, command) => { printBanner({ url }) } -/** - * Creates the `netlify functions:serve` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createFunctionsServeCommand = (program) => - program - .command('functions:serve') - .alias('function:serve') - .description('Serve functions locally') - .option('-f, --functions ', 'Specify a functions directory to serve') - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('-p, --port ', 'Specify a port for the functions server', (value) => Number.parseInt(value)) - .option('-o, --offline', 'disables any features that require network access') - .addHelpText('after', 'Helpful for debugging functions.') - .action(functionsServe) diff --git a/src/commands/functions/functions.mts b/src/commands/functions/functions.mts index 8c91b2d79c9..44cfffb4d44 100644 --- a/src/commands/functions/functions.mts +++ b/src/commands/functions/functions.mts @@ -5,8 +5,6 @@ import { chalk } from '../../utils/command-helpers.mjs' import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import BaseCommand from '../base-command.mjs' -import { createFunctionsServeCommand } from './functions-serve.mjs' - const functions = (options: OptionValues, command: BaseCommand) => { command.help() } @@ -96,7 +94,18 @@ NOT the same as listing the functions that have been deployed. For that info you await functionsList(options, command) }) - createFunctionsServeCommand(program) + program + .command('functions:serve') + .alias('function:serve') + .description('Serve functions locally') + .option('-f, --functions ', 'Specify a functions directory to serve') + .option('-p, --port ', 'Specify a port for the functions server', (value) => Number.parseInt(value)) + .option('-o, --offline', 'disables any features that require network access') + .addHelpText('after', 'Helpful for debugging functions.') + .action(async(options: OptionValues, command: BaseCommand) => { + const { functionsServe } = await import('./functions-serve.mjs') + await functionsServe(options, command) + }) const name = chalk.greenBright('`functions`') From bbad02cf18ac2fe515b0be1d276bfab475204866 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:04:42 -0500 Subject: [PATCH 28/67] feat: convert init --- src/commands/init/index.mts | 24 +++++++++++++++++++++++- src/commands/init/init.mts | 36 ++++-------------------------------- src/commands/watch/watch.mts | 4 ++-- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/commands/init/index.mts b/src/commands/init/index.mts index 33095fb1bcc..96f608a9cc7 100644 --- a/src/commands/init/index.mts +++ b/src/commands/init/index.mts @@ -1 +1,23 @@ -export { createInitCommand, init } from './init.mjs' +import { Option, OptionValues } from "commander"; + +import BaseCommand from "../base-command.mjs"; + +export const createInitCommand = (program: BaseCommand) => + program + .command('init') + .description( + 'Configure continuous deployment for a new or existing site. To create a new site without continuous deployment, use `netlify sites:create`', + ) + .option('-m, --manual', 'Manually configure a git remote for CI') + .option('--force', 'Reinitialize CI hooks if the linked site is already configured to use CI') + .addOption( + new Option( + '--gitRemoteName ', + 'Old, prefer --git-remote-name. Name of Git remote to use. e.g. "origin"', + ).hideHelp(true), + ) + .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') + .action(async(options: OptionValues, command: BaseCommand) => { + const { init } = await import('./init.mjs') + await init(options, command) + }) diff --git a/src/commands/init/init.mts b/src/commands/init/init.mts index e5e03667ff5..6fcaaf509ca 100644 --- a/src/commands/init/init.mts +++ b/src/commands/init/init.mts @@ -1,5 +1,5 @@ - -import { Option } from 'commander' + +import { Option, OptionValues } from 'commander' import inquirer from 'inquirer' import isEmpty from 'lodash/isEmpty.js' @@ -8,6 +8,7 @@ import getRepoData from '../../utils/get-repo-data.mjs' import { ensureNetlifyIgnore } from '../../utils/gitignore.mjs' import { configureRepo } from '../../utils/init/config.mjs' import { track } from '../../utils/telemetry/index.mjs' +import BaseCommand from '../base-command.mjs' import { link } from '../link/index.mjs' import { sitesCreate } from '../sites/index.mjs' @@ -181,13 +182,7 @@ const logExistingRepoSetupAndExit = ({ repoUrl, siteName }) => { exit() } -/** - * The init command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -export const init = async (options, command) => { +export const init = async (options: OptionValues, command: BaseCommand) => { command.setAnalyticsPayload({ manual: options.manual, force: options.force }) const { repositoryRoot, state } = command.netlify @@ -228,26 +223,3 @@ export const init = async (options, command) => { return siteInfo } - -/** - * Creates the `netlify init` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createInitCommand = (program) => - program - .command('init') - .description( - 'Configure continuous deployment for a new or existing site. To create a new site without continuous deployment, use `netlify sites:create`', - ) - .option('-m, --manual', 'Manually configure a git remote for CI') - .option('--force', 'Reinitialize CI hooks if the linked site is already configured to use CI') - .addOption( - new Option( - '--gitRemoteName ', - 'Old, prefer --git-remote-name. Name of Git remote to use. e.g. "origin"', - ).hideHelp(true), - ) - .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') - .action(init) diff --git a/src/commands/watch/watch.mts b/src/commands/watch/watch.mts index 36074c30b0d..f019d5178ed 100644 --- a/src/commands/watch/watch.mts +++ b/src/commands/watch/watch.mts @@ -1,10 +1,10 @@ - + import pWaitFor from 'p-wait-for' import prettyjson from 'prettyjson' import { startSpinner, stopSpinner } from '../../lib/spinner.mjs' import { chalk, error, log } from '../../utils/command-helpers.mjs' -import { init } from '../init/index.mjs' +import { init } from '../init/init.mjs' // 1 second const INIT_WAIT = 1e3 From 36ca6a8c2895152452701c0a4b8d0c9461cd08d9 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:06:51 -0500 Subject: [PATCH 29/67] chore: format --- src/commands/init/init.mts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/init/init.mts b/src/commands/init/init.mts index 6fcaaf509ca..c034951f151 100644 --- a/src/commands/init/init.mts +++ b/src/commands/init/init.mts @@ -1,5 +1,5 @@ -import { Option, OptionValues } from 'commander' +import { OptionValues } from 'commander' import inquirer from 'inquirer' import isEmpty from 'lodash/isEmpty.js' From 3519b19b302f91ba8309c30750cd8bba8c49e10a Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:11:46 -0500 Subject: [PATCH 30/67] feat: convert integration --- src/commands/integration/deploy.mts | 30 ++++------------------- src/commands/integration/index.mts | 37 ++++++++++++++++------------- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/src/commands/integration/deploy.mts b/src/commands/integration/deploy.mts index 984bbd80ce7..5cc8bf60e73 100644 --- a/src/commands/integration/deploy.mts +++ b/src/commands/integration/deploy.mts @@ -2,6 +2,7 @@ import fs from 'fs' import { resolve } from 'path' import { exit, env } from 'process' +import { OptionValues } from 'commander' import inquirer from 'inquirer' // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'js-y... Remove this comment to see the full error message import yaml from 'js-yaml' @@ -12,6 +13,7 @@ import { z } from 'zod' import { getBuildOptions } from '../../lib/build.mjs' import { getToken, chalk, log } from '../../utils/command-helpers.mjs' import { getSiteInformation } from '../../utils/dev.mjs' +import BaseCommand from '../base-command.mjs' import { checkOptions } from '../build/build.mjs' import { deploy as siteDeploy } from '../deploy/deploy.mjs' @@ -390,24 +392,19 @@ export const getConfiguration = (workingDir) => { exit(1) } } -/** - * The deploy command for Netlify Integrations - * @param {import('commander').OptionValues} options - * * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const deploy = async (options, command) => { + +export const deploy = async (options: OptionValues, command: BaseCommand) => { const { api, cachedConfig, site, siteInfo } = command.netlify const { id: siteId } = site // @ts-expect-error TS(2554) FIXME: Expected 1 arguments, but got 0. const [token] = await getToken() const workingDir = resolve(command.workingDir) - // @ts-expect-error TS(2345) FIXME: Argument of type '{ cachedConfig: any; packagePath... Remove this comment to see the full error message const buildOptions = await getBuildOptions({ cachedConfig, packagePath: command.workspacePackage, currentDir: command.workingDir, token, + // @ts-expect-error TS(2740) options, }) @@ -464,20 +461,3 @@ const deploy = async (options, command) => { )} https://ntl.fyi/create-private-integration`, ) } - -/** - * Creates the `netlify int deploy` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createDeployCommand = (program) => - program - .command('integration:deploy') - .alias('int:deploy') - .description('Register, build, and deploy a private integration on Netlify') - .option('-p, --prod', 'Deploy to production', false) - .option('-b, --build', 'Build the integration', false) - .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) - .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) - .action(deploy) diff --git a/src/commands/integration/index.mts b/src/commands/integration/index.mts index 2d703d83571..6099c5c6f03 100644 --- a/src/commands/integration/index.mts +++ b/src/commands/integration/index.mts @@ -1,23 +1,28 @@ -import { createDeployCommand } from './deploy.mjs' +import { env } from 'process' -/** - * The int command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const integrations = (options, command) => { +import { OptionValues } from 'commander' + +import BaseCommand from "../base-command.mjs" + +const integrations = (options: OptionValues, command: BaseCommand) => { command.help() } -/** - * Creates the `netlify integration` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createIntegrationCommand = (program) => { - createDeployCommand(program) + +export const createIntegrationCommand = (program: BaseCommand) => { + program + .command('integration:deploy') + .alias('int:deploy') + .description('Register, build, and deploy a private integration on Netlify') + .option('-p, --prod', 'Deploy to production', false) + .option('-b, --build', 'Build the integration', false) + .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) + .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) + .action(async(options: OptionValues, command: BaseCommand) => { + const { deploy } = await import('./deploy.mjs') + await deploy(options, command) + }) + return program .command('integration') From 8b9c32fb6d853673de52bdfa2047f93ef277d9f8 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:14:28 -0500 Subject: [PATCH 31/67] feat: convert link --- src/commands/deploy/deploy.mts | 2 +- src/commands/init/init.mts | 2 +- src/commands/link/index.mts | 24 ++++++++++++++++++- src/commands/link/link.mts | 36 ++++------------------------- src/commands/sites/sites-create.mts | 4 ++-- 5 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/commands/deploy/deploy.mts b/src/commands/deploy/deploy.mts index d18ddcc63e0..28491653831 100644 --- a/src/commands/deploy/deploy.mts +++ b/src/commands/deploy/deploy.mts @@ -35,7 +35,7 @@ import { getEnvelopeEnv } from '../../utils/env/index.mjs' import { getFunctionsManifestPath, getInternalFunctionsDir } from '../../utils/functions/index.mjs' import openBrowser from '../../utils/open-browser.mjs' import BaseCommand from '../base-command.mjs' -import { link } from '../link/index.mjs' +import { link } from '../link/link.mjs' import { sitesCreate } from '../sites/index.mjs' // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message diff --git a/src/commands/init/init.mts b/src/commands/init/init.mts index c034951f151..0d86bcddc43 100644 --- a/src/commands/init/init.mts +++ b/src/commands/init/init.mts @@ -9,7 +9,7 @@ import { ensureNetlifyIgnore } from '../../utils/gitignore.mjs' import { configureRepo } from '../../utils/init/config.mjs' import { track } from '../../utils/telemetry/index.mjs' import BaseCommand from '../base-command.mjs' -import { link } from '../link/index.mjs' +import { link } from '../link/link.mjs' import { sitesCreate } from '../sites/index.mjs' // @ts-expect-error TS(7031) FIXME: Binding element 'siteInfo' implicitly has an 'any'... Remove this comment to see the full error message diff --git a/src/commands/link/index.mts b/src/commands/link/index.mts index 73a196158d0..cc15cd4913d 100644 --- a/src/commands/link/index.mts +++ b/src/commands/link/index.mts @@ -1 +1,23 @@ -export { createLinkCommand, link } from './link.mjs' +import { Option, OptionValues } from "commander"; + +import BaseCommand from "../base-command.mjs"; + + +export const createLinkCommand = (program: BaseCommand) => + program + .command('link') + .description('Link a local repo or project folder to an existing site on Netlify') + .option('--id ', 'ID of site to link to') + .option('--name ', 'Name of site to link to') + .addOption( + new Option( + '--gitRemoteName ', + 'Old, prefer --git-remote-name. Name of Git remote to use. e.g. "origin"', + ).hideHelp(true), + ) + .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') + .addExamples(['netlify link', 'netlify link --id 123-123-123-123', 'netlify link --name my-site-name']) + .action(async (options: OptionValues, command: BaseCommand) => { + const { link } = await import('./link.mjs') + await link(options, command) + }) diff --git a/src/commands/link/link.mts b/src/commands/link/link.mts index b1c1270ee11..0e4aeede281 100644 --- a/src/commands/link/link.mts +++ b/src/commands/link/link.mts @@ -1,5 +1,5 @@ - -import { Option } from 'commander' + +import { Option, OptionValues } from 'commander' import inquirer from 'inquirer' import isEmpty from 'lodash/isEmpty.js' @@ -8,6 +8,7 @@ import { chalk, error, exit, log } from '../../utils/command-helpers.mjs' import getRepoData from '../../utils/get-repo-data.mjs' import { ensureNetlifyIgnore } from '../../utils/gitignore.mjs' import { track } from '../../utils/telemetry/index.mjs' +import BaseCommand from '../base-command.mjs' /** * @@ -250,13 +251,8 @@ or run ${chalk.cyanBright('netlify sites:create')} to create a site.`) return site } -/** - * The link command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -export const link = async (options, command) => { + +export const link = async (options: OptionValues, command: BaseCommand) => { await command.authenticate() const { @@ -348,25 +344,3 @@ export const link = async (options, command) => { } return siteData } - -/** - * Creates the `netlify link` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLinkCommand = (program) => - program - .command('link') - .description('Link a local repo or project folder to an existing site on Netlify') - .option('--id ', 'ID of site to link to') - .option('--name ', 'Name of site to link to') - .addOption( - new Option( - '--gitRemoteName ', - 'Old, prefer --git-remote-name. Name of Git remote to use. e.g. "origin"', - ).hideHelp(true), - ) - .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') - .addExamples(['netlify link', 'netlify link --id 123-123-123-123', 'netlify link --name my-site-name']) - .action(link) diff --git a/src/commands/sites/sites-create.mts b/src/commands/sites/sites-create.mts index 26d1403f515..93b4468b976 100644 --- a/src/commands/sites/sites-create.mts +++ b/src/commands/sites/sites-create.mts @@ -1,4 +1,4 @@ - + import { InvalidArgumentError } from 'commander' import inquirer from 'inquirer' import pick from 'lodash/pick.js' @@ -8,7 +8,7 @@ import { chalk, error, log, logJson, warn } from '../../utils/command-helpers.mj import getRepoData from '../../utils/get-repo-data.mjs' import { configureRepo } from '../../utils/init/config.mjs' import { track } from '../../utils/telemetry/index.mjs' -import { link } from '../link/index.mjs' +import { link } from '../link/link.mjs' // @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. export const getSiteNameInput = async (name) => { From fe01541b103c5d9b9d14da37a3de6c33474bd16f Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:19:47 -0500 Subject: [PATCH 32/67] feat: convert lm:info --- src/commands/lm/lm-info.mts | 13 ++----------- src/commands/lm/lm.mts | 34 +++++++++++++++++----------------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/commands/lm/lm-info.mts b/src/commands/lm/lm-info.mts index 052670a8b4f..afa06aee907 100644 --- a/src/commands/lm/lm-info.mts +++ b/src/commands/lm/lm-info.mts @@ -1,4 +1,4 @@ - + import { Listr } from 'listr2' import { @@ -11,7 +11,7 @@ import { /** * The lm:info command */ -const lmInfo = async () => { +export const lmInfo = async () => { const steps = [ checkGitVersionStep, checkGitLFSVersionStep, @@ -31,12 +31,3 @@ const lmInfo = async () => { // an error is already reported when a task fails } } - -/** - * Creates the `netlify lm:info` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLmInfoCommand = (program) => - program.command('lm:info', { hidden: true }).description('Show large media requirements information.').action(lmInfo) diff --git a/src/commands/lm/lm.mts b/src/commands/lm/lm.mts index 992464d669e..f681a904100 100644 --- a/src/commands/lm/lm.mts +++ b/src/commands/lm/lm.mts @@ -1,27 +1,27 @@ - -import { createLmInfoCommand } from './lm-info.mjs' + +import { OptionValues } from 'commander' + +import BaseCommand from '../base-command.mjs' + import { createLmInstallCommand } from './lm-install.mjs' import { createLmSetupCommand } from './lm-setup.mjs' import { createLmUninstallCommand } from './lm-uninstall.mjs' -/** - * The lm command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const lm = (options, command) => { + +const lm = (options: OptionValues, command: BaseCommand) => { command.help() } -/** - * Creates the `netlify lm` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLmCommand = (program) => { - createLmInfoCommand(program) + +export const createLmCommand = (program: BaseCommand) => { + program + .command('lm:info', { hidden: true }) + .description('Show large media requirements information.') + .action(async () => { + const { lmInfo } = await import('./lm-info.mjs') + await lmInfo() + }) + createLmInstallCommand(program) createLmSetupCommand(program) createLmUninstallCommand(program) From 7c4258aaccd2e211aa34ae7e337ba3fc2c4ad558 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:21:41 -0500 Subject: [PATCH 33/67] feat: convert lm:install --- src/commands/lm/lm-install.mts | 30 +++++------------------------- src/commands/lm/lm.mts | 17 ++++++++++++++--- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/commands/lm/lm-install.mts b/src/commands/lm/lm-install.mts index 6bf6b17edeb..b8ef857badb 100644 --- a/src/commands/lm/lm-install.mts +++ b/src/commands/lm/lm-install.mts @@ -1,33 +1,13 @@ - + +import { OptionValues } from 'commander' + import { installPlatform } from '../../utils/lm/install.mjs' import { printBanner } from '../../utils/lm/ui.mjs' -/** - * The lm:install command - * @param {import('commander').OptionValues} options - */ -// @ts-expect-error TS(7031) FIXME: Binding element 'force' implicitly has an 'any' ty... Remove this comment to see the full error message -const lmInstall = async ({ force }) => { + +export const lmInstall = async ({ force }: OptionValues) => { const installed = await installPlatform({ force }) if (installed) { printBanner(force) } } - -/** - * Creates the `netlify lm:install` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLmInstallCommand = (program) => - program - .command('lm:install', { hidden: true }) - .alias('lm:init') - .description( - `Configures your computer to use Netlify Large Media -It installs the required credentials helper for Git, -and configures your Git environment with the right credentials.`, - ) - .option('-f, --force', 'Force the credentials helper installation') - .action(lmInstall) diff --git a/src/commands/lm/lm.mts b/src/commands/lm/lm.mts index f681a904100..aadec6d3ea0 100644 --- a/src/commands/lm/lm.mts +++ b/src/commands/lm/lm.mts @@ -3,7 +3,6 @@ import { OptionValues } from 'commander' import BaseCommand from '../base-command.mjs' -import { createLmInstallCommand } from './lm-install.mjs' import { createLmSetupCommand } from './lm-setup.mjs' import { createLmUninstallCommand } from './lm-uninstall.mjs' @@ -12,7 +11,6 @@ const lm = (options: OptionValues, command: BaseCommand) => { command.help() } - export const createLmCommand = (program: BaseCommand) => { program .command('lm:info', { hidden: true }) @@ -22,7 +20,20 @@ export const createLmCommand = (program: BaseCommand) => { await lmInfo() }) - createLmInstallCommand(program) + program + .command('lm:install', { hidden: true }) + .alias('lm:init') + .description( + `Configures your computer to use Netlify Large Media +It installs the required credentials helper for Git, +and configures your Git environment with the right credentials.`, + ) + .option('-f, --force', 'Force the credentials helper installation') + .action(async (options: OptionValues) => { + const { lmInstall } = await import('./lm-install.mjs') + await lmInstall(options) + }) + createLmSetupCommand(program) createLmUninstallCommand(program) From b1f8e3464bf151fb91dcfbea9f91301963c96ba8 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:22:47 -0500 Subject: [PATCH 34/67] feat: convert lm:setup --- src/commands/lm/lm-setup.mts | 28 +++++----------------------- src/commands/lm/lm.mts | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/commands/lm/lm-setup.mts b/src/commands/lm/lm-setup.mts index de1df6fc2b0..d0b8324b268 100644 --- a/src/commands/lm/lm-setup.mts +++ b/src/commands/lm/lm-setup.mts @@ -1,4 +1,5 @@ - + +import { OptionValues } from 'commander' import { Listr } from 'listr2' import { error } from '../../utils/command-helpers.mjs' @@ -7,6 +8,7 @@ import execa from '../../utils/execa.mjs' import { installPlatform } from '../../utils/lm/install.mjs' import { checkHelperVersion } from '../../utils/lm/requirements.mjs' import { printBanner } from '../../utils/lm/ui.mjs' +import BaseCommand from '../base-command.mjs' // @ts-expect-error TS(7031) FIXME: Binding element 'force' implicitly has an 'any' ty... Remove this comment to see the full error message const installHelperIfMissing = async function ({ force }) { @@ -56,13 +58,8 @@ const configureLFSURL = async function (siteId, api) { return execa('git', ['config', '-f', '.lfsconfig', 'lfs.url', url]) } -/** - * The lm:setup command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const lmSetup = async (options, command) => { + +export const lmSetup = async (options: OptionValues, command: BaseCommand) => { await command.authenticate() const { api, site } = command.netlify @@ -97,18 +94,3 @@ const lmSetup = async (options, command) => { printBanner(options.forceInstall) } } - -/** - * Creates the `netlify lm:setup` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLmSetupCommand = (program) => - program - .command('lm:setup', { hidden: true }) - .description('Configures your site to use Netlify Large Media') - .option('-s, --skip-install', 'Skip the credentials helper installation check') - .option('-f, --force-install', 'Force the credentials helper installation') - .addHelpText('after', 'It runs the install command if you have not installed the dependencies yet.') - .action(lmSetup) diff --git a/src/commands/lm/lm.mts b/src/commands/lm/lm.mts index aadec6d3ea0..814c75e8dd1 100644 --- a/src/commands/lm/lm.mts +++ b/src/commands/lm/lm.mts @@ -3,7 +3,6 @@ import { OptionValues } from 'commander' import BaseCommand from '../base-command.mjs' -import { createLmSetupCommand } from './lm-setup.mjs' import { createLmUninstallCommand } from './lm-uninstall.mjs' @@ -34,7 +33,18 @@ and configures your Git environment with the right credentials.`, await lmInstall(options) }) - createLmSetupCommand(program) + program + .command('lm:setup', { hidden: true }) + .description('Configures your site to use Netlify Large Media') + .option('-s, --skip-install', 'Skip the credentials helper installation check') + .option('-f, --force-install', 'Force the credentials helper installation') + .addHelpText('after', 'It runs the install command if you have not installed the dependencies yet.') + .action(async (options: OptionValues, command: BaseCommand) => { + const { lmSetup } = await import('./lm-setup.mjs') + await lmSetup(options, command) + }) + + createLmUninstallCommand(program) program From 03f6033595f295b5f57e8c965b0a1ee6d0430b50 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:23:59 -0500 Subject: [PATCH 35/67] feat: convert lm:uninstall --- src/commands/lm/lm-uninstall.mts | 19 ++----------------- src/commands/lm/lm.mts | 13 ++++++++++--- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/commands/lm/lm-uninstall.mts b/src/commands/lm/lm-uninstall.mts index c62e22c23d8..c6b19d1053f 100644 --- a/src/commands/lm/lm-uninstall.mts +++ b/src/commands/lm/lm-uninstall.mts @@ -1,24 +1,9 @@ - + import { uninstall } from '../../utils/lm/install.mjs' /** * The lm:uninstall command */ -const lmUninstall = async () => { +export const lmUninstall = async () => { await uninstall() } - -/** - * Creates the `netlify lm:uninstall` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLmUninstallCommand = (program) => - program - .command('lm:uninstall', { hidden: true }) - .alias('lm:remove') - .description( - 'Uninstalls Netlify git credentials helper and cleans up any related configuration changes made by the install command.', - ) - .action(lmUninstall) diff --git a/src/commands/lm/lm.mts b/src/commands/lm/lm.mts index 814c75e8dd1..6c1d431cf90 100644 --- a/src/commands/lm/lm.mts +++ b/src/commands/lm/lm.mts @@ -3,8 +3,6 @@ import { OptionValues } from 'commander' import BaseCommand from '../base-command.mjs' -import { createLmUninstallCommand } from './lm-uninstall.mjs' - const lm = (options: OptionValues, command: BaseCommand) => { command.help() @@ -45,7 +43,16 @@ and configures your Git environment with the right credentials.`, }) - createLmUninstallCommand(program) + program + .command('lm:uninstall', { hidden: true }) + .alias('lm:remove') + .description( + 'Uninstalls Netlify git credentials helper and cleans up any related configuration changes made by the install command.', + ) + .action(async() => { + const { lmUninstall } = await import('./lm-uninstall.mjs') + await lmUninstall() + }) program .command('lm', { hidden: true }) From 9730c7d9dea7c1acf8bd089429431625f3958ed4 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:26:31 -0500 Subject: [PATCH 36/67] feat: convert login --- src/commands/login/index.mts | 17 ++++++++++++++++- src/commands/login/login.mts | 30 ++++++------------------------ src/commands/switch/switch.mts | 4 ++-- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/commands/login/index.mts b/src/commands/login/index.mts index b44a218b46b..eeb8f4a3fa9 100644 --- a/src/commands/login/index.mts +++ b/src/commands/login/index.mts @@ -1 +1,16 @@ -export { createLoginCommand, login } from './login.mjs' +import { OptionValues } from 'commander' + +import BaseCommand from '../base-command.mjs' + +export const createLoginCommand = (program: BaseCommand) => + program + .command('login') + .description( + `Login to your Netlify account +Opens a web browser to acquire an OAuth token.`, + ) + .option('--new', 'Login to new Netlify account') + .action(async (options: OptionValues, command: BaseCommand) => { + const { login } = await import('./login.mjs') + await login(options, command) + }) diff --git a/src/commands/login/login.mts b/src/commands/login/login.mts index 73451e51fe3..e0e85a733bd 100644 --- a/src/commands/login/login.mts +++ b/src/commands/login/login.mts @@ -1,5 +1,8 @@ - + +import { OptionValues } from 'commander' + import { chalk, exit, getToken, log } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' // @ts-expect-error TS(7006) FIXME: Parameter 'location' implicitly has an 'any' type. const msg = function (location) { @@ -15,13 +18,8 @@ const msg = function (location) { } } -/** - * The login command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -export const login = async (options, command) => { + +export const login = async (options: OptionValues, command: BaseCommand) => { // @ts-expect-error TS(2554) FIXME: Expected 1 arguments, but got 0. const [accessToken, location] = await getToken() @@ -41,19 +39,3 @@ export const login = async (options, command) => { await command.expensivelyAuthenticate() } - -/** - * Creates the `netlify login` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLoginCommand = (program) => - program - .command('login') - .description( - `Login to your Netlify account -Opens a web browser to acquire an OAuth token.`, - ) - .option('--new', 'Login to new Netlify account') - .action(login) diff --git a/src/commands/switch/switch.mts b/src/commands/switch/switch.mts index b7a2ca702b7..39e56fcc30d 100644 --- a/src/commands/switch/switch.mts +++ b/src/commands/switch/switch.mts @@ -1,8 +1,8 @@ - + import inquirer from 'inquirer' import { chalk, log } from '../../utils/command-helpers.mjs' -import { login } from '../login/index.mjs' +import { login } from '../login/login.mjs' const LOGIN_NEW = 'I would like to login to a new account' From 178665178c5bcaa93bc515203b568f40c0d238a4 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:28:02 -0500 Subject: [PATCH 37/67] feat: convert logout --- src/commands/logout/index.mts | 13 ++++++++++++- src/commands/logout/logout.mts | 23 ++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/commands/logout/index.mts b/src/commands/logout/index.mts index e5f53890358..0df6d3ffe21 100644 --- a/src/commands/logout/index.mts +++ b/src/commands/logout/index.mts @@ -1 +1,12 @@ -export { createLogoutCommand } from './logout.mjs' +import { OptionValues } from "commander"; + +import BaseCommand from "../base-command.mjs"; + +export const createLogoutCommand = (program: BaseCommand) => + program + .command('logout', { hidden: true }) + .description('Logout of your Netlify account') + .action(async (options: OptionValues, command: BaseCommand) => { + const { logout } = await import('./logout.mjs') + await logout(options, command) + }) diff --git a/src/commands/logout/logout.mts b/src/commands/logout/logout.mts index d7efe299063..dec43d24053 100644 --- a/src/commands/logout/logout.mts +++ b/src/commands/logout/logout.mts @@ -1,14 +1,12 @@ - + +import { OptionValues } from 'commander' + import { exit, getToken, log } from '../../utils/command-helpers.mjs' import { track } from '../../utils/telemetry/index.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The logout command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const logout = async (options, command) => { + +export const logout = async (options: OptionValues, command: BaseCommand) => { // @ts-expect-error TS(2554) FIXME: Expected 1 arguments, but got 0. const [accessToken, location] = await getToken() @@ -34,12 +32,3 @@ const logout = async (options, command) => { log(`Logging you out of Netlify. Come back soon!`) } - -/** - * Creates the `netlify logout` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createLogoutCommand = (program) => - program.command('logout', { hidden: true }).description('Logout of your Netlify account').action(logout) From 7d02439353a106aa66eed980d254d4f5542bc133 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:29:41 -0500 Subject: [PATCH 38/67] feat: convert logs:deploy --- src/commands/logs/build.mts | 9 +-------- src/commands/logs/index.mts | 13 +++++++++++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/commands/logs/build.mts b/src/commands/logs/build.mts index f4b38673b4f..e39f42fa1be 100644 --- a/src/commands/logs/build.mts +++ b/src/commands/logs/build.mts @@ -32,7 +32,7 @@ export function getName({ deploy, userId }: { deploy: any; userId: string }) { return `(${deploy.id.slice(0, 7)}) ${normalisedName}` } -const logsBuild = async (options: OptionValues, command: BaseCommand) => { +export const logsBuild = async (options: OptionValues, command: BaseCommand) => { await command.authenticate() const client = command.netlify.api const { site } = command.netlify @@ -83,10 +83,3 @@ const logsBuild = async (options: OptionValues, command: BaseCommand) => { log('---') }) } - -export const createLogsBuildCommand = (program: BaseCommand) => - program - .command('logs:deploy') - .alias('logs:build') - .description('(Beta) Stream the logs of deploys currently being built to the console') - .action(logsBuild) diff --git a/src/commands/logs/index.mts b/src/commands/logs/index.mts index 9ab5f2dacb5..d42e3067eec 100644 --- a/src/commands/logs/index.mts +++ b/src/commands/logs/index.mts @@ -1,10 +1,19 @@ +import { OptionValues } from 'commander' + import BaseCommand from '../base-command.mjs' -import { createLogsBuildCommand } from './build.mjs' import { createLogsFunctionCommand } from './functions.mjs' export const createLogsCommand = (program: BaseCommand) => { - createLogsBuildCommand(program) + program + .command('logs:deploy') + .alias('logs:build') + .description('(Beta) Stream the logs of deploys currently being built to the console') + .action(async (options: OptionValues, command: BaseCommand) => { + const { logsBuild } = await import('./build.mjs') + await logsBuild(options, command) + }) + createLogsFunctionCommand(program) return program From 29788c517c4a82a7af970ef36c2b040b51c78a6e Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:32:17 -0500 Subject: [PATCH 39/67] feat: convert logs:functions --- src/commands/logs/functions.mts | 11 +---------- src/commands/logs/index.mts | 13 +++++++++++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/commands/logs/functions.mts b/src/commands/logs/functions.mts index 68b0c3a8676..c61874e9e93 100644 --- a/src/commands/logs/functions.mts +++ b/src/commands/logs/functions.mts @@ -25,7 +25,7 @@ function getLog(logData: { level: string; message: string }) { return `${logString} ${logData.message}` } -const logsFunction = async (functionName: string | undefined, options: OptionValues, command: BaseCommand) => { +export const logsFunction = async (functionName: string | undefined, options: OptionValues, command: BaseCommand) => { const client = command.netlify.api const { site } = command.netlify const { id: siteId } = site @@ -80,12 +80,3 @@ const logsFunction = async (functionName: string | undefined, options: OptionVal log(err) }) } - -export const createLogsFunctionCommand = (program: BaseCommand) => - program - .command('logs:function') - .alias('logs:functions') - .addArgument(new Argument('[functionName]', 'Name of the function to stream logs for')) - .addExamples(['netlify logs:function my-function', 'netlify logs:function']) - .description('(Beta) Stream netlify function logs to the console') - .action(logsFunction) diff --git a/src/commands/logs/index.mts b/src/commands/logs/index.mts index d42e3067eec..cafb781da3b 100644 --- a/src/commands/logs/index.mts +++ b/src/commands/logs/index.mts @@ -1,4 +1,4 @@ -import { OptionValues } from 'commander' +import { OptionValues, Argument } from 'commander' import BaseCommand from '../base-command.mjs' @@ -14,7 +14,16 @@ export const createLogsCommand = (program: BaseCommand) => { await logsBuild(options, command) }) - createLogsFunctionCommand(program) + program + .command('logs:function') + .alias('logs:functions') + .addArgument(new Argument('[functionName]', 'Name of the function to stream logs for')) + .addExamples(['netlify logs:function my-function', 'netlify logs:function']) + .description('(Beta) Stream netlify function logs to the console') + .action(async (functionName: string | undefined, options: OptionValues, command: BaseCommand) => { + const { logsFunction } = await import('./functions.mjs') + await logsFunction(functionName, options, command) + }) return program .command('logs') From 0d5d00e4c96bc84f765b57de0c2920e659f4da59 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:37:35 -0500 Subject: [PATCH 40/67] feat: convert open --- src/commands/logs/index.mts | 2 -- src/commands/open/index.mts | 39 +++++++++++++++++++++++++++++++- src/commands/open/open-admin.mts | 27 ++++------------------ src/commands/open/open-site.mts | 27 ++++------------------ src/commands/open/open.mts | 35 ++++++---------------------- 5 files changed, 55 insertions(+), 75 deletions(-) diff --git a/src/commands/logs/index.mts b/src/commands/logs/index.mts index cafb781da3b..db51847944b 100644 --- a/src/commands/logs/index.mts +++ b/src/commands/logs/index.mts @@ -2,8 +2,6 @@ import { OptionValues, Argument } from 'commander' import BaseCommand from '../base-command.mjs' -import { createLogsFunctionCommand } from './functions.mjs' - export const createLogsCommand = (program: BaseCommand) => { program .command('logs:deploy') diff --git a/src/commands/open/index.mts b/src/commands/open/index.mts index 47e2ca89df9..446d14228f5 100644 --- a/src/commands/open/index.mts +++ b/src/commands/open/index.mts @@ -1 +1,38 @@ -export { createOpenCommand } from './open.mjs' +import { OptionValues } from "commander" + +import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from "../base-command.mjs" + +export const createOpenCommand = (program: BaseCommand) => { + program + .command('open:admin') + .description('Opens current site admin UI in Netlify') + .addExamples(['netlify open:admin']) + .hook('preAction', requiresSiteInfo) + .action(async (options: OptionValues, command: BaseCommand) => { + const { openAdmin } = await import('./open-admin.mjs') + await openAdmin(options, command) + }) + + program + .command('open:site') + .description('Opens current site url in browser') + .addExamples(['netlify open:site']) + .hook('preAction', requiresSiteInfo) + .action(async (options: OptionValues, command: BaseCommand) => { + const { openSite } = await import('./open-site.mjs') + await openSite(options, command) + }) + + + return program + .command('open') + .description(`Open settings for the site linked to the current folder`) + .option('--site', 'Open site') + .option('--admin', 'Open Netlify site') + .addExamples(['netlify open --site', 'netlify open --admin', 'netlify open:admin', 'netlify open:site']) + .action(async (options: OptionValues, command: BaseCommand) => { + const { open } = await import('./open.mjs') + await open(options, command) + }) +} diff --git a/src/commands/open/open-admin.mts b/src/commands/open/open-admin.mts index a0b8ee8998d..c66c9bdad2b 100644 --- a/src/commands/open/open-admin.mts +++ b/src/commands/open/open-admin.mts @@ -1,14 +1,11 @@ +import { OptionValues } from 'commander' + import { exit, log } from '../../utils/command-helpers.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import openBrowser from '../../utils/open-browser.mjs' +import BaseCommand from '../base-command.mjs' + -/** - * The open:admin command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -export const openAdmin = async (options, command) => { +export const openAdmin = async (options: OptionValues, command: BaseCommand) => { const { siteInfo } = command.netlify await command.authenticate() @@ -20,17 +17,3 @@ export const openAdmin = async (options, command) => { await openBrowser({ url: siteInfo.admin_url }) exit() } - -/** - * Creates the `netlify open:admin` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createOpenAdminCommand = (program) => - program - .command('open:admin') - .description('Opens current site admin UI in Netlify') - .addExamples(['netlify open:admin']) - .hook('preAction', requiresSiteInfo) - .action(openAdmin) diff --git a/src/commands/open/open-site.mts b/src/commands/open/open-site.mts index e644c91454d..7b25268e3d7 100644 --- a/src/commands/open/open-site.mts +++ b/src/commands/open/open-site.mts @@ -1,14 +1,11 @@ +import { OptionValues } from 'commander' + import { exit, log } from '../../utils/command-helpers.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' import openBrowser from '../../utils/open-browser.mjs' +import BaseCommand from '../base-command.mjs' + -/** - * The open:site command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -export const openSite = async (options, command) => { +export const openSite = async (options: OptionValues, command: BaseCommand) => { const { siteInfo } = command.netlify await command.authenticate() @@ -21,17 +18,3 @@ export const openSite = async (options, command) => { await openBrowser({ url }) exit() } - -/** - * Creates the `netlify open:site` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createOpenSiteCommand = (program) => - program - .command('open:site') - .description('Opens current site url in browser') - .addExamples(['netlify open:site']) - .hook('preAction', requiresSiteInfo) - .action(openSite) diff --git a/src/commands/open/open.mts b/src/commands/open/open.mts index 7a2699dddb0..0fbd85ac219 100644 --- a/src/commands/open/open.mts +++ b/src/commands/open/open.mts @@ -1,15 +1,13 @@ +import { OptionValues } from 'commander' + import { log } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' + +import { openAdmin } from './open-admin.mjs' +import { openSite } from './open-site.mjs' -import { createOpenAdminCommand, openAdmin } from './open-admin.mjs' -import { createOpenSiteCommand, openSite } from './open-site.mjs' -/** - * The open command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const open = async (options, command) => { +export const open = async (options: OptionValues, command: BaseCommand) => { if (!options.site || !options.admin) { log(command.helpInformation()) } @@ -20,22 +18,3 @@ const open = async (options, command) => { // Default open netlify admin await openAdmin(options, command) } - -/** - * Creates the `netlify open` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createOpenCommand = (program) => { - createOpenAdminCommand(program) - createOpenSiteCommand(program) - - return program - .command('open') - .description(`Open settings for the site linked to the current folder`) - .option('--site', 'Open site') - .option('--admin', 'Open Netlify site') - .addExamples(['netlify open --site', 'netlify open --admin', 'netlify open:admin', 'netlify open:site']) - .action(open) -} From 33e0dfcbba8e88a65b554fc8c8920d2f549a42cf Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:43:31 -0500 Subject: [PATCH 41/67] feat: convert recipes --- src/commands/recipes/index.mts | 26 ++++++++++++- src/commands/recipes/recipes-list.mts | 19 ++-------- src/commands/recipes/recipes.mts | 48 +++++++----------------- src/lib/edge-functions/editor-helper.mts | 2 +- 4 files changed, 42 insertions(+), 53 deletions(-) diff --git a/src/commands/recipes/index.mts b/src/commands/recipes/index.mts index 21dc9803d84..8e6750c29ad 100644 --- a/src/commands/recipes/index.mts +++ b/src/commands/recipes/index.mts @@ -1 +1,25 @@ -export { createRecipesCommand, runRecipe } from './recipes.mjs' +import { OptionValues } from "commander" + +import BaseCommand from "../base-command.mjs" + +export const createRecipesCommand = (program: BaseCommand) => { + program + .command('recipes:list') + .description(`List the recipes available to create and modify files in a project`) + .addExamples(['netlify recipes:list']) + .action(async () => { + const { recipesListCommand } = await import('./recipes-list.mjs') + await recipesListCommand() + }) + + return program + .command('recipes') + .argument('[name]', 'name of the recipe') + .description(`Create and modify files in a project using pre-defined recipes`) + .option('-n, --name ', 'recipe name to use') + .addExamples(['netlify recipes my-recipe', 'netlify recipes --name my-recipe']) + .action(async (recipeName: string, options: OptionValues, command: BaseCommand) => { + const { recipesCommand } = await import('./recipes.mjs') + await recipesCommand(recipeName, options, command) + }) +} diff --git a/src/commands/recipes/recipes-list.mts b/src/commands/recipes/recipes-list.mts index d10aa8b9a2b..44f9cf30acd 100644 --- a/src/commands/recipes/recipes-list.mts +++ b/src/commands/recipes/recipes-list.mts @@ -1,5 +1,5 @@ - - + + import AsciiTable from 'ascii-table' import { listRecipes } from './common.mjs' @@ -7,7 +7,7 @@ import { listRecipes } from './common.mjs' /** * The recipes:list command */ -const recipesListCommand = async () => { +export const recipesListCommand = async () => { const recipes = await listRecipes() const table = new AsciiTable(`Usage: netlify recipes `) @@ -19,16 +19,3 @@ const recipesListCommand = async () => { console.log(table.toString()) } - -/** - * Creates the `netlify recipes:list` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createRecipesListCommand = (program) => - program - .command('recipes:list') - .description(`List the recipes available to create and modify files in a project`) - .addExamples(['netlify recipes:list']) - .action(recipesListCommand) diff --git a/src/commands/recipes/recipes.mts b/src/commands/recipes/recipes.mts index c64d32ef883..4e77419652d 100644 --- a/src/commands/recipes/recipes.mts +++ b/src/commands/recipes/recipes.mts @@ -1,24 +1,27 @@ - + import { basename } from 'path' +import { OptionValues } from 'commander' import { closest } from 'fastest-levenshtein' import inquirer from 'inquirer' import { NETLIFYDEVERR, chalk, log } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' import { getRecipe, listRecipes } from './common.mjs' -import { createRecipesListCommand } from './recipes-list.mjs' const SUGGESTION_TIMEOUT = 1e4 -/** - * The recipes command - * @param {string} recipeName - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7023) FIXME: 'recipesCommand' implicitly has return type 'any' ... Remove this comment to see the full error message -const recipesCommand = async (recipeName, options, command) => { + +// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message +export const runRecipe = async ({ config, recipeName, repositoryRoot }) => { + const recipe = await getRecipe(recipeName) + + return recipe.run({ config, repositoryRoot }) +} + + +export const recipesCommand = async (recipeName: string, options: OptionValues, command: BaseCommand): Promise => { const { config, repositoryRoot } = command.netlify const sanitizedRecipeName = basename(recipeName || '').toLowerCase() @@ -65,28 +68,3 @@ const recipesCommand = async (recipeName, options, command) => { } } } - -// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message -export const runRecipe = async ({ config, recipeName, repositoryRoot }) => { - const recipe = await getRecipe(recipeName) - - return recipe.run({ config, repositoryRoot }) -} - -/** - * Creates the `netlify recipes` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createRecipesCommand = (program) => { - createRecipesListCommand(program) - - program - .command('recipes') - .argument('[name]', 'name of the recipe') - .description(`Create and modify files in a project using pre-defined recipes`) - .option('-n, --name ', 'recipe name to use') - .addExamples(['netlify recipes my-recipe', 'netlify recipes --name my-recipe']) - .action(recipesCommand) -} diff --git a/src/lib/edge-functions/editor-helper.mts b/src/lib/edge-functions/editor-helper.mts index 2e96b789cd1..f0b094db077 100644 --- a/src/lib/edge-functions/editor-helper.mts +++ b/src/lib/edge-functions/editor-helper.mts @@ -2,7 +2,7 @@ import { env } from 'process' import inquirer from 'inquirer' -import { runRecipe } from '../../commands/recipes/index.mjs' +import { runRecipe } from '../../commands/recipes/recipes.mjs' const STATE_PROMPT_PROPERTY = 'promptVSCodeSettings' From 998df3d9312fd06d022d4ecfaa52189352dd7cca Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:46:25 -0500 Subject: [PATCH 42/67] feat: convert serve --- src/commands/main.mts | 2 +- src/commands/serve/index.mts | 52 ++++++++++++++++++++++++++- src/commands/serve/serve.mts | 70 ++++-------------------------------- 3 files changed, 59 insertions(+), 65 deletions(-) diff --git a/src/commands/main.mts b/src/commands/main.mts index b480cee0ab4..fca6fb5e353 100644 --- a/src/commands/main.mts +++ b/src/commands/main.mts @@ -32,7 +32,7 @@ import { createLogoutCommand } from './logout/index.mjs' import { createLogsCommand } from './logs/index.mjs' import { createOpenCommand } from './open/index.mjs' import { createRecipesCommand } from './recipes/index.mjs' -import { createServeCommand } from './serve/serve.mjs' +import { createServeCommand } from './serve/index.mjs' import { createSitesCommand } from './sites/index.mjs' import { createStatusCommand } from './status/index.mjs' import { createSwitchCommand } from './switch/index.mjs' diff --git a/src/commands/serve/index.mts b/src/commands/serve/index.mts index c0419589fbf..bd04792936b 100644 --- a/src/commands/serve/index.mts +++ b/src/commands/serve/index.mts @@ -1 +1,51 @@ -export { createServeCommand } from './serve.mjs' +import { Option } from "commander"; + +import { normalizeContext } from '../../utils/env/index.mjs' +import { getGeoCountryArgParser } from '../../utils/validation.mjs' +import BaseCommand from "../base-command.mjs"; + +export const createServeCommand = (program: BaseCommand) => + program + .command('serve') + .description( + 'Build the site for production and serve locally. This does not watch the code for changes, so if you need to rebuild your site then you must exit and run `serve` again.', + ) + .option( + '--context ', + 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + ) + .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) + .option('-d ,--dir ', 'dir with static files') + .option('-f ,--functions ', 'specify a functions folder to serve') + .option('-o ,--offline', 'disables any features that require network access') + .addOption( + new Option('--functionsPort ', 'Old, prefer --functions-port. Port of functions server') + .argParser((value) => Number.parseInt(value)) + .hideHelp(true), + ) + .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) + .addOption( + new Option( + '--geo ', + 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location', + ) + .choices(['cache', 'mock', 'update']) + .default('cache'), + ) + .addOption( + new Option( + '--country ', + 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)', + ).argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR')), + ) + .addOption( + new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') + .argParser((value) => Number.parseInt(value)) + .hideHelp(), + ) + .addExamples(['netlify serve', 'BROWSER=none netlify serve # disable browser auto opening']) + .action(async (options: Option, command: BaseCommand) => { + const { serve } = await import('./serve.mjs') + await serve(options, command) + }) diff --git a/src/commands/serve/serve.mts b/src/commands/serve/serve.mts index 5fb31ba10f5..83e4d3ac3ef 100644 --- a/src/commands/serve/serve.mts +++ b/src/commands/serve/serve.mts @@ -1,7 +1,7 @@ - + import process from 'process' -import { Option } from 'commander' +import { OptionValues } from 'commander' import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.mjs' import { startFunctionsServer } from '../../lib/functions/server.mjs' @@ -17,21 +17,16 @@ import { } from '../../utils/command-helpers.mjs' import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.mjs' import { getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.mjs' -import { getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs' +import { getEnvelopeEnv } from '../../utils/env/index.mjs' import { getInternalFunctionsDir } from '../../utils/functions/functions.mjs' import { ensureNetlifyIgnore } from '../../utils/gitignore.mjs' import openBrowser from '../../utils/open-browser.mjs' import { generateInspectSettings, startProxyServer } from '../../utils/proxy-server.mjs' import { runBuildTimeline } from '../../utils/run-build.mjs' -import { getGeoCountryArgParser } from '../../utils/validation.mjs' - -/** - * The serve command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const serve = async (options, command) => { +import BaseCommand from '../base-command.mjs' + + +export const serve = async (options: OptionValues, command: BaseCommand) => { const { api, cachedConfig, config, repositoryRoot, site, siteInfo, state } = command.netlify config.dev = { ...config.dev } config.build = { ...config.build } @@ -160,54 +155,3 @@ const serve = async (options, command) => { printBanner({ url }) } - -/** - * Creates the `netlify serve` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createServeCommand = (program) => - program - .command('serve') - .description( - 'Build the site for production and serve locally. This does not watch the code for changes, so if you need to rebuild your site then you must exit and run `serve` again.', - ) - .option( - '--context ', - 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - ) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) - .option('-d ,--dir ', 'dir with static files') - .option('-f ,--functions ', 'specify a functions folder to serve') - .option('-o ,--offline', 'disables any features that require network access') - .addOption( - new Option('--functionsPort ', 'Old, prefer --functions-port. Port of functions server') - .argParser((value) => Number.parseInt(value)) - .hideHelp(true), - ) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) - .addOption( - new Option( - '--geo ', - 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location', - ) - .choices(['cache', 'mock', 'update']) - .default('cache'), - ) - .addOption( - new Option( - '--country ', - 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)', - ).argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR')), - ) - .addOption( - new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') - .argParser((value) => Number.parseInt(value)) - .hideHelp(), - ) - .addExamples(['netlify serve', 'BROWSER=none netlify serve # disable browser auto opening']) - .action(serve) From 95ecbb7a57926999c75a972a405a55e8172753ed Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:51:10 -0500 Subject: [PATCH 43/67] feat: convert sites:create --- src/commands/deploy/deploy.mts | 2 +- src/commands/init/init.mts | 2 +- src/commands/sites/index.mts | 1 - src/commands/sites/sites-create.mts | 48 +++-------------------- src/commands/sites/sites.mts | 59 ++++++++++++++++++++--------- 5 files changed, 49 insertions(+), 63 deletions(-) diff --git a/src/commands/deploy/deploy.mts b/src/commands/deploy/deploy.mts index 28491653831..b05b782c87c 100644 --- a/src/commands/deploy/deploy.mts +++ b/src/commands/deploy/deploy.mts @@ -36,7 +36,7 @@ import { getFunctionsManifestPath, getInternalFunctionsDir } from '../../utils/f import openBrowser from '../../utils/open-browser.mjs' import BaseCommand from '../base-command.mjs' import { link } from '../link/link.mjs' -import { sitesCreate } from '../sites/index.mjs' +import { sitesCreate } from '../sites/sites-create.mjs' // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message const triggerDeploy = async ({ api, options, siteData, siteId }) => { diff --git a/src/commands/init/init.mts b/src/commands/init/init.mts index 0d86bcddc43..25fa9d8fda8 100644 --- a/src/commands/init/init.mts +++ b/src/commands/init/init.mts @@ -10,7 +10,7 @@ import { configureRepo } from '../../utils/init/config.mjs' import { track } from '../../utils/telemetry/index.mjs' import BaseCommand from '../base-command.mjs' import { link } from '../link/link.mjs' -import { sitesCreate } from '../sites/index.mjs' +import { sitesCreate } from '../sites/sites-create.mjs' // @ts-expect-error TS(7031) FIXME: Binding element 'siteInfo' implicitly has an 'any'... Remove this comment to see the full error message const persistState = ({ siteInfo, state }) => { diff --git a/src/commands/sites/index.mts b/src/commands/sites/index.mts index 97b314b5738..6443a7a815a 100644 --- a/src/commands/sites/index.mts +++ b/src/commands/sites/index.mts @@ -1,2 +1 @@ -export { sitesCreate } from './sites-create.mjs' export { createSitesCommand } from './sites.mjs' diff --git a/src/commands/sites/sites-create.mts b/src/commands/sites/sites-create.mts index 93b4468b976..b431fb9bef2 100644 --- a/src/commands/sites/sites-create.mts +++ b/src/commands/sites/sites-create.mts @@ -1,6 +1,6 @@ -import { InvalidArgumentError } from 'commander' -import inquirer from 'inquirer' +import { OptionValues } from 'commander' +import inquirer, { BaseChoiceMap } from 'inquirer' import pick from 'lodash/pick.js' import prettyjson from 'prettyjson' @@ -8,6 +8,7 @@ import { chalk, error, log, logJson, warn } from '../../utils/command-helpers.mj import getRepoData from '../../utils/get-repo-data.mjs' import { configureRepo } from '../../utils/init/config.mjs' import { track } from '../../utils/telemetry/index.mjs' +import BaseCommand from '../base-command.mjs' import { link } from '../link/link.mjs' // @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. @@ -28,13 +29,8 @@ export const getSiteNameInput = async (name) => { return { name } } -/** - * The sites:create command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -export const sitesCreate = async (options, command) => { + +export const sitesCreate = async (options: OptionValues, command: BaseCommand) => { const { api } = command.netlify await command.authenticate() @@ -160,37 +156,3 @@ export const sitesCreate = async (options, command) => { return site } -const MAX_SITE_NAME_LENGTH = 63 -// @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. -const validateName = function (value) { - // netlify sites:create --name - if (typeof value === 'string' && value.length > MAX_SITE_NAME_LENGTH) { - throw new InvalidArgumentError(`--name should be less than 64 characters, input length: ${value.length}`) - } - - return value -} - -/** - * Creates the `netlify sites:create` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createSitesCreateCommand = (program) => - program - .command('sites:create') - .description( - `Create an empty site (advanced) -Create a blank site that isn't associated with any git remote. Will link the site to the current working directory.`, - ) - .option('-n, --name ', 'name of site', validateName) - .option('-a, --account-slug ', 'account slug to create the site under') - .option('-c, --with-ci', 'initialize CI hooks during site creation') - .option('-m, --manual', 'force manual CI setup. Used --with-ci flag') - .option('--disable-linking', 'create the site without linking it to current directory') - .addHelpText( - 'after', - `Create a blank site that isn't associated with any git remote. Will link the site to the current working directory.`, - ) - .action(sitesCreate) diff --git a/src/commands/sites/sites.mts b/src/commands/sites/sites.mts index 69728fa3f21..08806f39cd0 100644 --- a/src/commands/sites/sites.mts +++ b/src/commands/sites/sites.mts @@ -1,27 +1,52 @@ - + +import { OptionValues , InvalidArgumentError } from 'commander' + +import BaseCommand from '../base-command.mjs' + import { createSitesFromTemplateCommand } from './sites-create-template.mjs' -import { createSitesCreateCommand } from './sites-create.mjs' import { createSitesDeleteCommand } from './sites-delete.mjs' import { createSitesListCommand } from './sites-list.mjs' -/** - * The sites command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const sites = (options, command) => { +const MAX_SITE_NAME_LENGTH = 63 +// @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. + + +const validateName = function (value) { + // netlify sites:create --name + if (typeof value === 'string' && value.length > MAX_SITE_NAME_LENGTH) { + throw new InvalidArgumentError(`--name should be less than 64 characters, input length: ${value.length}`) + } + + return value +} + +const sites = (options: OptionValues, command: BaseCommand) => { command.help() } -/** - * Creates the `netlify sites` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createSitesCommand = (program) => { - createSitesCreateCommand(program) + +export const createSitesCommand = (program: BaseCommand) => { + program + .command('sites:create') + .description( + `Create an empty site (advanced) +Create a blank site that isn't associated with any git remote. Will link the site to the current working directory.`, + ) + .option('-n, --name ', 'name of site', validateName) + .option('-a, --account-slug ', 'account slug to create the site under') + .option('-c, --with-ci', 'initialize CI hooks during site creation') + .option('-m, --manual', 'force manual CI setup. Used --with-ci flag') + .option('--disable-linking', 'create the site without linking it to current directory') + .addHelpText( + 'after', + `Create a blank site that isn't associated with any git remote. Will link the site to the current working directory.`, + ) + .action(async (options: OptionValues, command: BaseCommand) => { + const { sitesCreate } = await import('./sites-create.mjs') + await sitesCreate(options, command) + }) + + createSitesFromTemplateCommand(program) createSitesListCommand(program) createSitesDeleteCommand(program) From fee8cbb7cfc5701ba22034d5810cc64a9b4dc91f Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:52:22 -0500 Subject: [PATCH 44/67] feat: convert sites:create-template --- src/commands/sites/sites-create-template.mts | 40 +++----------------- src/commands/sites/sites.mts | 24 +++++++++++- 2 files changed, 27 insertions(+), 37 deletions(-) diff --git a/src/commands/sites/sites-create-template.mts b/src/commands/sites/sites-create-template.mts index 90b7977c8d7..311bb947ae3 100644 --- a/src/commands/sites/sites-create-template.mts +++ b/src/commands/sites/sites-create-template.mts @@ -1,5 +1,6 @@ - + +import { OptionValues } from 'commander' import inquirer from 'inquirer' import pick from 'lodash/pick.js' // @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'pars... Remove this comment to see the full error message @@ -14,6 +15,7 @@ import { getGitHubToken } from '../../utils/init/config-github.mjs' import { configureRepo } from '../../utils/init/config.mjs' import { createRepo, getTemplatesFromGitHub, validateTemplate } from '../../utils/sites/utils.mjs' import { track } from '../../utils/telemetry/index.mjs' +import BaseCommand from '../base-command.mjs' import { getSiteNameInput } from './sites-create.mjs' @@ -67,14 +69,8 @@ const getTemplateName = async ({ ghToken, options, repository }) => { // @ts-expect-error TS(7031) FIXME: Binding element 'options' implicitly has an 'any' ... Remove this comment to see the full error message const getGitHubLink = ({ options, templateName }) => options.url || `https://github.com/${templateName}` -/** - * The sites:create-template command - * @param repository {string} - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'repository' implicitly has an 'any' typ... Remove this comment to see the full error message -const sitesCreateTemplate = async (repository, options, command) => { + +export const sitesCreateTemplate = async (repository: string, options: OptionValues, command: BaseCommand) => { const { api } = command.netlify await command.authenticate() @@ -258,29 +254,3 @@ const sitesCreateTemplate = async (repository, options, command) => { return site } - -/** - * Creates the `netlify sites:create-template` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createSitesFromTemplateCommand = (program) => - program - .command('sites:create-template') - .description( - `(Beta) Create a site from a starter template -Create a site from a starter template.`, - ) - .option('-n, --name [name]', 'name of site') - .option('-u, --url [url]', 'template url') - .option('-a, --account-slug [slug]', 'account slug to create the site under') - .option('-c, --with-ci', 'initialize CI hooks during site creation') - .argument('[repository]', 'repository to use as starter template') - .addHelpText('after', `(Beta) Create a site from starter template.`) - .addExamples([ - 'netlify sites:create-template', - 'netlify sites:create-template nextjs-blog-theme', - 'netlify sites:create-template my-github-profile/my-template', - ]) - .action(sitesCreateTemplate) diff --git a/src/commands/sites/sites.mts b/src/commands/sites/sites.mts index 08806f39cd0..e493a89a0d5 100644 --- a/src/commands/sites/sites.mts +++ b/src/commands/sites/sites.mts @@ -3,7 +3,6 @@ import { OptionValues , InvalidArgumentError } from 'commander' import BaseCommand from '../base-command.mjs' -import { createSitesFromTemplateCommand } from './sites-create-template.mjs' import { createSitesDeleteCommand } from './sites-delete.mjs' import { createSitesListCommand } from './sites-list.mjs' @@ -47,7 +46,28 @@ Create a blank site that isn't associated with any git remote. Will link the sit }) - createSitesFromTemplateCommand(program) + program + .command('sites:create-template') + .description( + `(Beta) Create a site from a starter template +Create a site from a starter template.`, + ) + .option('-n, --name [name]', 'name of site') + .option('-u, --url [url]', 'template url') + .option('-a, --account-slug [slug]', 'account slug to create the site under') + .option('-c, --with-ci', 'initialize CI hooks during site creation') + .argument('[repository]', 'repository to use as starter template') + .addHelpText('after', `(Beta) Create a site from starter template.`) + .addExamples([ + 'netlify sites:create-template', + 'netlify sites:create-template nextjs-blog-theme', + 'netlify sites:create-template my-github-profile/my-template', + ]) + .action(async (repository: string, options: OptionValues, command: BaseCommand) => { + const { sitesCreateTemplate } = await import('./sites-create-template.mjs') + await sitesCreateTemplate(repository, options, command) + }) + createSitesListCommand(program) createSitesDeleteCommand(program) From 653de4be73cc44907f44e1dcf1fa294882bd3e19 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:54:04 -0500 Subject: [PATCH 45/67] feat: convert sites:list --- src/commands/sites/sites-list.mts | 30 ++++++------------------------ src/commands/sites/sites.mts | 15 +++++++++++---- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/commands/sites/sites-list.mts b/src/commands/sites/sites-list.mts index a3edbef24fc..f906f55eacc 100644 --- a/src/commands/sites/sites-list.mts +++ b/src/commands/sites/sites-list.mts @@ -1,16 +1,13 @@ - + +import { OptionValues } from 'commander' + import { listSites } from '../../lib/api.mjs' import { startSpinner, stopSpinner } from '../../lib/spinner.mjs' import { chalk, log, logJson } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' + -/** - * The sites:list command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - * @returns {Promise<{ id: any; name: any; ssl_url: any; account_name: any; }|boolean>} - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const sitesList = async (options, command) => { +export const sitesList = async (options: OptionValues, command: BaseCommand) => { const { api } = command.netlify /** @type {import('ora').Ora} */ let spinner @@ -78,18 +75,3 @@ Count: ${logSites.length} }) } } - -/** - * Creates the `netlify sites:list` command - * @param {import('../base-command.mjs').default} program - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createSitesListCommand = (program) => - program - .command('sites:list') - .description('List all sites you have access to') - .option('--json', 'Output site data as JSON') - // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. - .action(async (options, command) => { - await sitesList(options, command) - }) diff --git a/src/commands/sites/sites.mts b/src/commands/sites/sites.mts index e493a89a0d5..79c465992db 100644 --- a/src/commands/sites/sites.mts +++ b/src/commands/sites/sites.mts @@ -4,12 +4,10 @@ import { OptionValues , InvalidArgumentError } from 'commander' import BaseCommand from '../base-command.mjs' import { createSitesDeleteCommand } from './sites-delete.mjs' -import { createSitesListCommand } from './sites-list.mjs' const MAX_SITE_NAME_LENGTH = 63 -// @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. - +// @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. const validateName = function (value) { // netlify sites:create --name if (typeof value === 'string' && value.length > MAX_SITE_NAME_LENGTH) { @@ -68,7 +66,16 @@ Create a site from a starter template.`, await sitesCreateTemplate(repository, options, command) }) - createSitesListCommand(program) + program + .command('sites:list') + .description('List all sites you have access to') + .option('--json', 'Output site data as JSON') + .action(async (options: OptionValues, command: BaseCommand) => { + const {sitesList} = await import('./sites-list.mjs') + await sitesList(options, command) + }) + + createSitesDeleteCommand(program) return program From b47bf77b268b89f6846362c9064dda31f5906121 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:55:16 -0500 Subject: [PATCH 46/67] feat: convert sites:delete --- src/commands/sites/sites-delete.mts | 29 +++++------------------------ src/commands/sites/sites.mts | 14 ++++++++++---- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/src/commands/sites/sites-delete.mts b/src/commands/sites/sites-delete.mts index 9d600324724..fb3daa9399d 100644 --- a/src/commands/sites/sites-delete.mts +++ b/src/commands/sites/sites-delete.mts @@ -1,16 +1,12 @@ - + +import { OptionValues } from 'commander' import inquirer from 'inquirer' import { chalk, error, exit, log } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' + -/** - * The sites:delete command - * @param {string} siteId - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'siteId' implicitly has an 'any' type. -const sitesDelete = async (siteId, options, command) => { +export const sitesDelete = async (siteId: string, options: OptionValues, command: BaseCommand) => { command.setAnalyticsPayload({ force: options.force }) const { api, site } = command.netlify @@ -90,18 +86,3 @@ const sitesDelete = async (siteId, options, command) => { } log(`Site "${siteId}" successfully deleted!`) } - -/** - * Creates the `netlify sites:delete` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createSitesDeleteCommand = (program) => - program - .command('sites:delete') - .description('Delete a site\nThis command will permanently delete the site on Netlify. Use with caution.') - .argument('', 'Site ID to delete.') - .option('-f, --force', 'delete without prompting (useful for CI)') - .addExamples(['netlify sites:delete 1234-3262-1211']) - .action(sitesDelete) diff --git a/src/commands/sites/sites.mts b/src/commands/sites/sites.mts index 79c465992db..a501a4097b6 100644 --- a/src/commands/sites/sites.mts +++ b/src/commands/sites/sites.mts @@ -3,8 +3,6 @@ import { OptionValues , InvalidArgumentError } from 'commander' import BaseCommand from '../base-command.mjs' -import { createSitesDeleteCommand } from './sites-delete.mjs' - const MAX_SITE_NAME_LENGTH = 63 // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. @@ -75,8 +73,16 @@ Create a site from a starter template.`, await sitesList(options, command) }) - - createSitesDeleteCommand(program) + program + .command('sites:delete') + .description('Delete a site\nThis command will permanently delete the site on Netlify. Use with caution.') + .argument('', 'Site ID to delete.') + .option('-f, --force', 'delete without prompting (useful for CI)') + .addExamples(['netlify sites:delete 1234-3262-1211']) + .action(async (siteId: string, options: OptionValues, command: BaseCommand) => { + const { sitesDelete } = await import('./sites-delete.mjs') + await sitesDelete(siteId, options, command) + }) return program .command('sites') From 2934bcad3f752d864f016fb65ca2c4cf570b3d37 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:57:51 -0500 Subject: [PATCH 47/67] feat: convert status --- src/commands/status/index.mts | 25 +++++++++++++++++++++++- src/commands/status/status-hooks.mts | 27 +++++--------------------- src/commands/status/status.mts | 29 ++++------------------------ 3 files changed, 33 insertions(+), 48 deletions(-) diff --git a/src/commands/status/index.mts b/src/commands/status/index.mts index 7a588663b6f..6e1c1d4d4e3 100644 --- a/src/commands/status/index.mts +++ b/src/commands/status/index.mts @@ -1 +1,24 @@ -export { createStatusCommand } from './status.mjs' +import { OptionValues } from "commander" + +import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from "../base-command.mjs" + +export const createStatusCommand = (program: BaseCommand) => { + program + .command('status:hooks') + .description('Print hook information of the linked site') + .hook('preAction', requiresSiteInfo) + .action(async (options: OptionValues, command: BaseCommand) => { + const { statusHooks } = await import('./status-hooks.mjs') + await statusHooks(options, command) + }) + + return program + .command('status') + .description('Print status information') + .option('--verbose', 'Output system info') + .action(async (options: OptionValues, command: BaseCommand) => { + const { status } = await import('./status.mjs') + await status(options, command) + }) +} diff --git a/src/commands/status/status-hooks.mts b/src/commands/status/status-hooks.mts index 633a303f267..3ee06a9873d 100644 --- a/src/commands/status/status-hooks.mts +++ b/src/commands/status/status-hooks.mts @@ -1,16 +1,12 @@ - + +import { OptionValues } from 'commander' import prettyjson from 'prettyjson' import { log } from '../../utils/command-helpers.mjs' -import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' +import BaseCommand from '../base-command.mjs' + -/** - * The status:hooks command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const statusHooks = async (options, command) => { +export const statusHooks = async (options: OptionValues, command: BaseCommand) => { const { api, siteInfo } = command.netlify await command.authenticate() @@ -39,16 +35,3 @@ Site Hook Status │ ─────────────────┘`) log(prettyjson.render(data)) } - -/** - * Creates the `netlify status:hooks` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createStatusHooksCommand = (program) => - program - .command('status:hooks') - .description('Print hook information of the linked site') - .hook('preAction', requiresSiteInfo) - .action(statusHooks) diff --git a/src/commands/status/status.mts b/src/commands/status/status.mts index 3aae4e470f1..4af63107d2c 100644 --- a/src/commands/status/status.mts +++ b/src/commands/status/status.mts @@ -1,17 +1,12 @@ import clean from 'clean-deep' +import { OptionValues } from 'commander' import prettyjson from 'prettyjson' import { chalk, error, exit, getToken, log, logJson, warn } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' -import { createStatusHooksCommand } from './status-hooks.mjs' -/** - * The status command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const status = async (options, command) => { +export const status = async (options: OptionValues, command: BaseCommand) => { const { api, globalConfig, site } = command.netlify const current = globalConfig.get('userId') // @ts-expect-error TS(2554) FIXME: Expected 1 arguments, but got 0. @@ -34,7 +29,7 @@ const status = async (options, command) => { let user try { - ;[accounts, user] = await Promise.all([api.listAccountsForUser(), api.getCurrentUser()]) + [accounts, user] = await Promise.all([api.listAccountsForUser(), api.getCurrentUser()]) } catch (error_) { // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. if (error_.status === 401) { @@ -115,19 +110,3 @@ const status = async (options, command) => { ) log() } - -/** - * Creates the `netlify status` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createStatusCommand = (program) => { - createStatusHooksCommand(program) - - return program - .command('status') - .description('Print status information') - .option('--verbose', 'Output system info') - .action(status) -} From 1f17237d4e36dddf098f391b13cbe49401087bae Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 15:59:53 -0500 Subject: [PATCH 48/67] feat: convert switch --- src/commands/switch/index.mts | 13 ++++++++++++- src/commands/switch/switch.mts | 20 ++++---------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/commands/switch/index.mts b/src/commands/switch/index.mts index 05ca35787da..9d2b7b1b798 100644 --- a/src/commands/switch/index.mts +++ b/src/commands/switch/index.mts @@ -1 +1,12 @@ -export { createSwitchCommand } from './switch.mjs' +import { OptionValues } from "commander"; + +import BaseCommand from "../base-command.mjs"; + +export const createSwitchCommand = (program: BaseCommand) => + program + .command('switch') + .description('Switch your active Netlify account') + .action(async (options: OptionValues, command: BaseCommand) => { + const { switchCommand } = await import('./switch.mjs') + await switchCommand(options, command) + }) diff --git a/src/commands/switch/switch.mts b/src/commands/switch/switch.mts index 39e56fcc30d..411943a4acb 100644 --- a/src/commands/switch/switch.mts +++ b/src/commands/switch/switch.mts @@ -1,18 +1,15 @@ +import { OptionValues } from 'commander' import inquirer from 'inquirer' import { chalk, log } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' import { login } from '../login/login.mjs' const LOGIN_NEW = 'I would like to login to a new account' -/** - * The switch command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const switchCommand = async (options, command) => { + +export const switchCommand = async (options: OptionValues, command: BaseCommand) => { const availableUsersChoices = Object.values(command.netlify.globalConfig.get('users') || {}).reduce( (prev, current) => // @ts-expect-error TS(2769) FIXME: No overload matches this call. @@ -44,12 +41,3 @@ const switchCommand = async (options, command) => { log(`You're now using ${chalk.bold(selectedAccount[1])}.`) } } - -/** - * Creates the `netlify switch` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createSwitchCommand = (program) => - program.command('switch').description('Switch your active Netlify account').action(switchCommand) From 5b0994430bb37b4a6ab102beaccd81f05b023da9 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 16:01:22 -0500 Subject: [PATCH 49/67] feat: convert unlink --- src/commands/unlink/index.mts | 13 ++++++++++++- src/commands/unlink/unlink.mts | 23 ++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/commands/unlink/index.mts b/src/commands/unlink/index.mts index 6f38cdb9344..682aee96c69 100644 --- a/src/commands/unlink/index.mts +++ b/src/commands/unlink/index.mts @@ -1 +1,12 @@ -export { createUnlinkCommand } from './unlink.mjs' +import { OptionValues } from "commander"; + +import BaseCommand from "../base-command.mjs"; + +export const createUnlinkCommand = (program: BaseCommand) => + program. + command('unlink') + .description('Unlink a local folder from a Netlify site') + .action(async (options: OptionValues, command: BaseCommand) => { + const { unlink } = await import('./unlink.mjs') + await unlink(options, command) + }) diff --git a/src/commands/unlink/unlink.mts b/src/commands/unlink/unlink.mts index fa330fbffc9..1ef823a503f 100644 --- a/src/commands/unlink/unlink.mts +++ b/src/commands/unlink/unlink.mts @@ -1,14 +1,12 @@ - + +import { OptionValues } from 'commander' + import { exit, log } from '../../utils/command-helpers.mjs' import { track } from '../../utils/telemetry/index.mjs' +import BaseCommand from '../base-command.mjs' -/** - * The unlink command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const unlink = async (options, command) => { + +export const unlink = async (options: OptionValues, command: BaseCommand) => { const { site, siteInfo, state } = command.netlify const siteId = site.id @@ -31,12 +29,3 @@ const unlink = async (options, command) => { log('Unlinked site') } } - -/** - * Creates the `netlify unlink` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createUnlinkCommand = (program) => - program.command('unlink').description('Unlink a local folder from a Netlify site').action(unlink) From 91b4cdbb41b59ab7957cd2a05a4f157a25d014b7 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 16:02:45 -0500 Subject: [PATCH 50/67] feat: convert watch --- src/commands/watch/index.mts | 14 +++++++++++++- src/commands/watch/watch.mts | 24 ++++-------------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/commands/watch/index.mts b/src/commands/watch/index.mts index 2b79f8fa9c8..505cfb58fbe 100644 --- a/src/commands/watch/index.mts +++ b/src/commands/watch/index.mts @@ -1 +1,13 @@ -export { createWatchCommand } from './watch.mjs' +import { OptionValues } from "commander"; + +import BaseCommand from "../base-command.mjs"; + +export const createWatchCommand = (program: BaseCommand) => + program + .command('watch') + .description('Watch for site deploy to finish') + .addExamples([`netlify watch`, `git push && netlify watch`]) + .action(async (options: OptionValues, command: BaseCommand) => { + const { watch } = await import('./watch.mjs') + await watch(options, command) + }) diff --git a/src/commands/watch/watch.mts b/src/commands/watch/watch.mts index f019d5178ed..ef865cd8163 100644 --- a/src/commands/watch/watch.mts +++ b/src/commands/watch/watch.mts @@ -1,9 +1,11 @@ +import { OptionValues } from 'commander' import pWaitFor from 'p-wait-for' import prettyjson from 'prettyjson' import { startSpinner, stopSpinner } from '../../lib/spinner.mjs' import { chalk, error, log } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' import { init } from '../init/init.mjs' // 1 second @@ -55,13 +57,8 @@ const waitForBuildFinish = async function (api, siteId, spinner) { return firstPass } -/** - * The watch command - * @param {import('commander').OptionValues} options - * @param {import('../base-command.mjs').default} command - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. -const watch = async (options, command) => { + +export const watch = async (options: OptionValues, command: BaseCommand) => { await command.authenticate() const client = command.netlify.api let siteId = command.netlify.site.id @@ -123,16 +120,3 @@ const watch = async (options, command) => { error(error_) } } - -/** - * Creates the `netlify watch` command - * @param {import('../base-command.mjs').default} program - * @returns - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. -export const createWatchCommand = (program) => - program - .command('watch') - .description('Watch for site deploy to finish') - .addExamples([`netlify watch`, `git push && netlify watch`]) - .action(watch) From 3062f12f5dafd346ab2588515ae2d14951d9459a Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 16:25:08 -0500 Subject: [PATCH 51/67] test: fix test for sites:create-template --- src/commands/sites/sites.mts | 47 ++++++++++--------- .../integration/commands/sites/sites.test.ts | 4 +- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/commands/sites/sites.mts b/src/commands/sites/sites.mts index a501a4097b6..de3fccd9c74 100644 --- a/src/commands/sites/sites.mts +++ b/src/commands/sites/sites.mts @@ -19,6 +19,30 @@ const sites = (options: OptionValues, command: BaseCommand) => { command.help() } +export const createSitesFromTemplateCommand = (program: BaseCommand) => { + program + .command('sites:create-template') + .description( + `(Beta) Create a site from a starter template +Create a site from a starter template.`, + ) + .option('-n, --name [name]', 'name of site') + .option('-u, --url [url]', 'template url') + .option('-a, --account-slug [slug]', 'account slug to create the site under') + .option('-c, --with-ci', 'initialize CI hooks during site creation') + .argument('[repository]', 'repository to use as starter template') + .addHelpText('after', `(Beta) Create a site from starter template.`) + .addExamples([ + 'netlify sites:create-template', + 'netlify sites:create-template nextjs-blog-theme', + 'netlify sites:create-template my-github-profile/my-template', + ]) + .action(async (repository: string, options: OptionValues, command: BaseCommand) => { + const { sitesCreateTemplate } = await import('./sites-create-template.mjs') + await sitesCreateTemplate(repository, options, command) + }) +} + export const createSitesCommand = (program: BaseCommand) => { program @@ -41,28 +65,7 @@ Create a blank site that isn't associated with any git remote. Will link the sit await sitesCreate(options, command) }) - - program - .command('sites:create-template') - .description( - `(Beta) Create a site from a starter template -Create a site from a starter template.`, - ) - .option('-n, --name [name]', 'name of site') - .option('-u, --url [url]', 'template url') - .option('-a, --account-slug [slug]', 'account slug to create the site under') - .option('-c, --with-ci', 'initialize CI hooks during site creation') - .argument('[repository]', 'repository to use as starter template') - .addHelpText('after', `(Beta) Create a site from starter template.`) - .addExamples([ - 'netlify sites:create-template', - 'netlify sites:create-template nextjs-blog-theme', - 'netlify sites:create-template my-github-profile/my-template', - ]) - .action(async (repository: string, options: OptionValues, command: BaseCommand) => { - const { sitesCreateTemplate } = await import('./sites-create-template.mjs') - await sitesCreateTemplate(repository, options, command) - }) + createSitesFromTemplateCommand(program) program .command('sites:list') diff --git a/tests/integration/commands/sites/sites.test.ts b/tests/integration/commands/sites/sites.test.ts index 4d357c4a65f..a95d88798f9 100644 --- a/tests/integration/commands/sites/sites.test.ts +++ b/tests/integration/commands/sites/sites.test.ts @@ -6,10 +6,12 @@ import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest' import BaseCommand from '../../../../src/commands/base-command.mjs' import { - createSitesFromTemplateCommand, fetchTemplates, } from '../../../../src/commands/sites/sites-create-template.mjs' import { createSitesCreateCommand } from '../../../../src/commands/sites/sites-create.mjs' +import { + createSitesFromTemplateCommand +} from '../../../../src/commands/sites/sites.mjs' import { getGitHubToken } from '../../../../src/utils/init/config-github.mjs' import { createRepo, getTemplatesFromGitHub } from '../../../../src/utils/sites/utils.mjs' import { getEnvironmentVariables, withMockApi } from '../../utils/mock-api.mjs' From b725a603b0d124f76dceff41b683e990a1b99bb9 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 16:27:43 -0500 Subject: [PATCH 52/67] test: fix tests for logs: --- src/commands/logs/index.mts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/commands/logs/index.mts b/src/commands/logs/index.mts index db51847944b..057d866dcc5 100644 --- a/src/commands/logs/index.mts +++ b/src/commands/logs/index.mts @@ -2,7 +2,7 @@ import { OptionValues, Argument } from 'commander' import BaseCommand from '../base-command.mjs' -export const createLogsCommand = (program: BaseCommand) => { +export const createLogsBuildCommand = (program: BaseCommand) => { program .command('logs:deploy') .alias('logs:build') @@ -11,7 +11,9 @@ export const createLogsCommand = (program: BaseCommand) => { const { logsBuild } = await import('./build.mjs') await logsBuild(options, command) }) +} +export const createLogsFunctionCommand = (program: BaseCommand) => { program .command('logs:function') .alias('logs:functions') @@ -22,6 +24,13 @@ export const createLogsCommand = (program: BaseCommand) => { const { logsFunction } = await import('./functions.mjs') await logsFunction(functionName, options, command) }) + } + +export const createLogsCommand = (program: BaseCommand) => { + + createLogsBuildCommand(program) + + createLogsFunctionCommand(program) return program .command('logs') From aef5612f53b106f95da26edaac2dbd1c458d663c Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 16:29:25 -0500 Subject: [PATCH 53/67] test: sites:create --- src/commands/sites/sites.mts | 8 ++++++-- tests/integration/commands/sites/sites.test.ts | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/commands/sites/sites.mts b/src/commands/sites/sites.mts index de3fccd9c74..7bcd754e359 100644 --- a/src/commands/sites/sites.mts +++ b/src/commands/sites/sites.mts @@ -43,8 +43,7 @@ Create a site from a starter template.`, }) } - -export const createSitesCommand = (program: BaseCommand) => { +export const createSitesCreateCommand = (program: BaseCommand) => { program .command('sites:create') .description( @@ -64,7 +63,12 @@ Create a blank site that isn't associated with any git remote. Will link the sit const { sitesCreate } = await import('./sites-create.mjs') await sitesCreate(options, command) }) + } + + +export const createSitesCommand = (program: BaseCommand) => { + createSitesCreateCommand(program) createSitesFromTemplateCommand(program) program diff --git a/tests/integration/commands/sites/sites.test.ts b/tests/integration/commands/sites/sites.test.ts index a95d88798f9..388688e5ac6 100644 --- a/tests/integration/commands/sites/sites.test.ts +++ b/tests/integration/commands/sites/sites.test.ts @@ -8,8 +8,7 @@ import BaseCommand from '../../../../src/commands/base-command.mjs' import { fetchTemplates, } from '../../../../src/commands/sites/sites-create-template.mjs' -import { createSitesCreateCommand } from '../../../../src/commands/sites/sites-create.mjs' -import { +import { createSitesCreateCommand , createSitesFromTemplateCommand } from '../../../../src/commands/sites/sites.mjs' import { getGitHubToken } from '../../../../src/utils/init/config-github.mjs' From be1b204681bdf01b5353f9e90634bdc8f63b229e Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 16:57:25 -0500 Subject: [PATCH 54/67] test: loogs --- tests/integration/commands/logs/build.test.ts | 2 +- tests/integration/commands/logs/functions.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/commands/logs/build.test.ts b/tests/integration/commands/logs/build.test.ts index 7a3f5ffc377..22ebc0268e4 100644 --- a/tests/integration/commands/logs/build.test.ts +++ b/tests/integration/commands/logs/build.test.ts @@ -1,7 +1,7 @@ import { Mock, afterEach, beforeEach, describe, expect, test, vi } from 'vitest' import BaseCommand from '../../../../src/commands/base-command.mjs' -import { createLogsBuildCommand } from '../../../../src/commands/logs/build.mjs' +import { createLogsBuildCommand } from '../../../../src/commands/logs/index.mjs' import { getWebSocket } from '../../../../src/utils/websockets/index.mjs' import { startMockApi } from '../../utils/mock-api-vitest.js' import { getEnvironmentVariables } from '../../utils/mock-api.mjs' diff --git a/tests/integration/commands/logs/functions.test.ts b/tests/integration/commands/logs/functions.test.ts index 16318747b42..b349f5269e1 100644 --- a/tests/integration/commands/logs/functions.test.ts +++ b/tests/integration/commands/logs/functions.test.ts @@ -1,7 +1,7 @@ import { Mock, afterEach, beforeEach, describe, expect, test, vi } from 'vitest' import BaseCommand from '../../../../src/commands/base-command.mjs' -import { createLogsFunctionCommand } from '../../../../src/commands/logs/functions.mjs' +import { createLogsFunctionCommand } from '../../../../src/commands/logs/index.mjs' import { getWebSocket } from '../../../../src/utils/websockets/index.mjs' import { startMockApi } from '../../utils/mock-api-vitest.ts' import { getEnvironmentVariables } from '../../utils/mock-api.mjs' From 8a50759f792c037a6499b46a95161aa0460a2248 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Thu, 16 Nov 2023 17:00:04 -0500 Subject: [PATCH 55/67] test: integration --- src/commands/integration/index.mts | 29 ++++++++++--------- .../commands/integration/deploy.test.ts | 5 ++-- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/commands/integration/index.mts b/src/commands/integration/index.mts index 6099c5c6f03..aa9170d64c3 100644 --- a/src/commands/integration/index.mts +++ b/src/commands/integration/index.mts @@ -8,21 +8,24 @@ const integrations = (options: OptionValues, command: BaseCommand) => { command.help() } - -export const createIntegrationCommand = (program: BaseCommand) => { +export const createIntegrationDeployCommand = (program: BaseCommand) => { program - .command('integration:deploy') - .alias('int:deploy') - .description('Register, build, and deploy a private integration on Netlify') - .option('-p, --prod', 'Deploy to production', false) - .option('-b, --build', 'Build the integration', false) - .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) - .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) - .action(async(options: OptionValues, command: BaseCommand) => { - const { deploy } = await import('./deploy.mjs') - await deploy(options, command) - }) + .command('integration:deploy') + .alias('int:deploy') + .description('Register, build, and deploy a private integration on Netlify') + .option('-p, --prod', 'Deploy to production', false) + .option('-b, --build', 'Build the integration', false) + .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) + .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) + .action(async(options: OptionValues, command: BaseCommand) => { + const { deploy } = await import('./deploy.mjs') + await deploy(options, command) + }) +} + +export const createIntegrationCommand = (program: BaseCommand) => { + createIntegrationDeployCommand(program) return program .command('integration') diff --git a/tests/integration/commands/integration/deploy.test.ts b/tests/integration/commands/integration/deploy.test.ts index 602bfda2fc2..1b1d2e8e7df 100644 --- a/tests/integration/commands/integration/deploy.test.ts +++ b/tests/integration/commands/integration/deploy.test.ts @@ -4,7 +4,8 @@ import { beforeEach, describe, expect, test, vi } from 'vitest' import BaseCommand from '../../../../src/commands/base-command.mjs' import { deploy as siteDeploy } from '../../../../src/commands/deploy/deploy.mjs' -import { areScopesEqual, createDeployCommand } from '../../../../src/commands/integration/deploy.mjs' +import { areScopesEqual } from '../../../../src/commands/integration/deploy.mjs' +import { createIntegrationDeployCommand } from '../../../../src/commands/integration/index.mjs' import { getEnvironmentVariables, withMockApi } from '../../utils/mock-api.mjs' import { withSiteBuilder } from '../../utils/site-builder.mjs' @@ -86,7 +87,7 @@ describe(`integration:deploy`, () => { Object.assign(process.env, envVars) const program = new BaseCommand('netlify') - createDeployCommand(program) + createIntegrationDeployCommand(program) const simulatedArgv = ['', '', 'integration:deploy'] try { From ca739d559feb93ae82cf76f2d3fd817f95a111a9 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Fri, 17 Nov 2023 09:05:38 -0500 Subject: [PATCH 56/67] chore: prettier --- src/commands/addons/addons-auth.mts | 1 - src/commands/addons/addons-create.mts | 1 - src/commands/addons/addons-list.mts | 1 - src/commands/addons/addons.mts | 99 ++++++++++---------- src/commands/api/api.mts | 2 - src/commands/api/index.mts | 8 +- src/commands/blobs/blobs-set.mts | 8 +- src/commands/blobs/blobs.mts | 20 ++-- src/commands/build/build.mts | 4 +- src/commands/build/index.mts | 6 +- src/commands/completion/index.mts | 9 +- src/commands/deploy/deploy.mts | 1 - src/commands/dev/dev-exec.mts | 3 +- src/commands/dev/dev.mts | 2 - src/commands/dev/index.mts | 42 ++++----- src/commands/env/env-clone.mts | 3 - src/commands/env/env-get.mts | 1 - src/commands/env/env-import.mts | 2 - src/commands/env/env-set.mts | 9 +- src/commands/env/env-unset.mts | 3 - src/commands/env/env.mts | 74 +++++++-------- src/commands/functions/functions-build.mts | 1 - src/commands/functions/functions-create.mts | 1 - src/commands/functions/functions-serve.mts | 2 - src/commands/functions/functions.mts | 47 +++++----- src/commands/init/index.mts | 6 +- src/commands/integration/deploy.mts | 2 +- src/commands/integration/index.mts | 25 +++-- src/commands/link/index.mts | 5 +- src/commands/link/link.mts | 1 - src/commands/lm/lm-install.mts | 1 - src/commands/lm/lm-setup.mts | 1 - src/commands/lm/lm.mts | 38 ++++---- src/commands/login/login.mts | 1 - src/commands/logout/index.mts | 16 ++-- src/commands/logout/logout.mts | 1 - src/commands/logs/index.mts | 17 ++-- src/commands/open/index.mts | 21 ++--- src/commands/open/open-admin.mts | 1 - src/commands/open/open-site.mts | 1 - src/commands/open/open.mts | 1 - src/commands/recipes/index.mts | 4 +- src/commands/recipes/recipes.mts | 2 - src/commands/serve/index.mts | 6 +- src/commands/serve/serve.mts | 1 - src/commands/sites/sites-create-template.mts | 1 - src/commands/sites/sites-create.mts | 2 - src/commands/sites/sites-delete.mts | 1 - src/commands/sites/sites-list.mts | 1 - src/commands/sites/sites.mts | 50 +++++----- src/commands/status/index.mts | 4 +- src/commands/status/status-hooks.mts | 1 - src/commands/status/status.mts | 1 - src/commands/switch/index.mts | 16 ++-- src/commands/switch/switch.mts | 1 - src/commands/unlink/index.mts | 18 ++-- src/commands/unlink/unlink.mts | 1 - src/commands/watch/index.mts | 4 +- src/commands/watch/watch.mts | 1 - 59 files changed, 269 insertions(+), 334 deletions(-) diff --git a/src/commands/addons/addons-auth.mts b/src/commands/addons/addons-auth.mts index 307bdfb8bbd..39776122f3f 100644 --- a/src/commands/addons/addons-auth.mts +++ b/src/commands/addons/addons-auth.mts @@ -5,7 +5,6 @@ import { exit, log } from '../../utils/command-helpers.mjs' import openBrowser from '../../utils/open-browser.mjs' import BaseCommand from '../base-command.mjs' - export const addonsAuth = async (addonName: string, options: OptionValues, command: BaseCommand) => { const { addon } = await prepareAddonCommand({ command, diff --git a/src/commands/addons/addons-create.mts b/src/commands/addons/addons-create.mts index cd4b6d0a439..8bace53b587 100644 --- a/src/commands/addons/addons-create.mts +++ b/src/commands/addons/addons-create.mts @@ -29,7 +29,6 @@ const createAddon = async ({ addonName, api, config, siteData, siteId }) => { } } - export const addonsCreate = async (addonName: string, options: OptionValues, command: BaseCommand) => { const { manifest, siteData } = await prepareAddonCommand({ command, diff --git a/src/commands/addons/addons-list.mts b/src/commands/addons/addons-list.mts index ed83c900f1d..a2ddaea427f 100644 --- a/src/commands/addons/addons-list.mts +++ b/src/commands/addons/addons-list.mts @@ -5,7 +5,6 @@ import { prepareAddonCommand } from '../../utils/addons/prepare.mjs' import { log, logJson } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' - export const addonsList = async (options: OptionValues, command: BaseCommand) => { // @ts-expect-error TS(2345) FIXME: Argument of type '{ command: any; }' is not assign... Remove this comment to see the full error message const { addons, siteData } = await prepareAddonCommand({ command }) diff --git a/src/commands/addons/addons.mts b/src/commands/addons/addons.mts index 326b65d6731..5329ef1b82b 100644 --- a/src/commands/addons/addons.mts +++ b/src/commands/addons/addons.mts @@ -8,65 +8,64 @@ const addons = (options: OptionValues, command: BaseCommand) => { export const createAddonsCommand = (program: BaseCommand) => { program - .command('addons:auth', { hidden: true }) - .alias('addon:auth') - .argument('', 'Add-on slug') - .description('Login to add-on provider') - .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { - const { addonsAuth } = await import('./addons-auth.mjs') - await addonsAuth(addonName, options, command) - }) + .command('addons:auth', { hidden: true }) + .alias('addon:auth') + .argument('', 'Add-on slug') + .description('Login to add-on provider') + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { + const { addonsAuth } = await import('./addons-auth.mjs') + await addonsAuth(addonName, options, command) + }) program - .command('addons:config', { hidden: true }) - .alias('addon:config') - .argument('', 'Add-on namespace') - .description('Configure add-on settings') - // allow for any flags. Handy for variadic configuration options - .allowUnknownOption(true) - .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { - const { addonsConfig } = await import('./addons-config.mjs') - await addonsConfig(addonName, options, command) - }) + .command('addons:config', { hidden: true }) + .alias('addon:config') + .argument('', 'Add-on namespace') + .description('Configure add-on settings') + // allow for any flags. Handy for variadic configuration options + .allowUnknownOption(true) + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { + const { addonsConfig } = await import('./addons-config.mjs') + await addonsConfig(addonName, options, command) + }) program - .command('addons:create', { hidden: true }) - .alias('addon:create') - .argument('', 'Add-on namespace') - .description( - `Add an add-on extension to your site + .command('addons:create', { hidden: true }) + .alias('addon:create') + .argument('', 'Add-on namespace') + .description( + `Add an add-on extension to your site Add-ons are a way to extend the functionality of your Netlify site`, - ) - // allow for any flags. Handy for variadic configuration options - .allowUnknownOption(true) - .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { - const { addonsCreate } = await import('./addons-create.mjs') - await addonsCreate(addonName, options, command) - }) + ) + // allow for any flags. Handy for variadic configuration options + .allowUnknownOption(true) + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { + const { addonsCreate } = await import('./addons-create.mjs') + await addonsCreate(addonName, options, command) + }) program - .command('addons:delete', { hidden: true }) - .alias('addon:delete') - .argument('', 'Add-on namespace') - .description( - `Remove an add-on extension to your site\nAdd-ons are a way to extend the functionality of your Netlify site`, - ) - .option('-f, --force', 'delete without prompting (useful for CI)') - .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { - const { addonsDelete } = await import('./addons-delete.mjs') - await addonsDelete(addonName, options, command) - }) - + .command('addons:delete', { hidden: true }) + .alias('addon:delete') + .argument('', 'Add-on namespace') + .description( + `Remove an add-on extension to your site\nAdd-ons are a way to extend the functionality of your Netlify site`, + ) + .option('-f, --force', 'delete without prompting (useful for CI)') + .action(async (addonName: string, options: OptionValues, command: BaseCommand) => { + const { addonsDelete } = await import('./addons-delete.mjs') + await addonsDelete(addonName, options, command) + }) program - .command('addons:list', { hidden: true }) - .alias('addon:list') - .description(`List currently installed add-ons for site`) - .option('--json', 'Output add-on data as JSON') - .action(async (options: OptionValues, command: BaseCommand) => { - const {addonsList} = await import('./addons-list.mjs') - await addonsList(options, command) - }) + .command('addons:list', { hidden: true }) + .alias('addon:list') + .description(`List currently installed add-ons for site`) + .option('--json', 'Output add-on data as JSON') + .action(async (options: OptionValues, command: BaseCommand) => { + const { addonsList } = await import('./addons-list.mjs') + await addonsList(options, command) + }) return program .command('addons', { hidden: true }) diff --git a/src/commands/api/api.mts b/src/commands/api/api.mts index a4195de4de2..c18db056120 100644 --- a/src/commands/api/api.mts +++ b/src/commands/api/api.mts @@ -5,7 +5,6 @@ import { methods } from 'netlify' import { chalk, error, exit, log, logJson } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' - export const apiCommand = async (apiMethod: string, options: OptionValues, command: BaseCommand) => { const { api } = command.netlify @@ -45,4 +44,3 @@ export const apiCommand = async (apiMethod: string, options: OptionValues, comma error(error_) } } - diff --git a/src/commands/api/index.mts b/src/commands/api/index.mts index 390d6bc4e02..8f321c82018 100644 --- a/src/commands/api/index.mts +++ b/src/commands/api/index.mts @@ -1,5 +1,5 @@ -import { chalk } from '../../utils/command-helpers.mjs' -import BaseCommand from "../base-command.mjs"; +import { chalk } from '../../utils/command-helpers.mjs' +import BaseCommand from '../base-command.mjs' export const createApiCommand = (program: BaseCommand) => program @@ -16,5 +16,5 @@ For more information on available methods checkout https://open-api.netlify.com/ .addExamples(['netlify api --list', `netlify api getSite --data '{ "site_id": "123456" }'`]) .action(async (apiMethod, options, command) => { const { apiCommand } = await import('./api.mjs') - await apiCommand(apiMethod, options, command ) - } ) + await apiCommand(apiMethod, options, command) + }) diff --git a/src/commands/blobs/blobs-set.mts b/src/commands/blobs/blobs-set.mts index 72caaa4a99e..7667371d08e 100644 --- a/src/commands/blobs/blobs-set.mts +++ b/src/commands/blobs/blobs-set.mts @@ -12,7 +12,13 @@ interface Options extends OptionValues { } // eslint-disable-next-line max-params -export const blobsSet = async (storeName: string, key: string, valueParts: string[], options: Options, command: BaseCommand) => { +export const blobsSet = async ( + storeName: string, + key: string, + valueParts: string[], + options: Options, + command: BaseCommand, +) => { const { api, siteInfo } = command.netlify const { input } = options const store = getStore({ diff --git a/src/commands/blobs/blobs.mts b/src/commands/blobs/blobs.mts index d6e42f58744..14b77d483c7 100644 --- a/src/commands/blobs/blobs.mts +++ b/src/commands/blobs/blobs.mts @@ -26,7 +26,7 @@ export const createBlobsCommand = (program: BaseCommand) => { await blobsDelete(storeName, key, _options, command) }) - program + program .command('blobs:get') .description( `(Beta) Reads an object with a given key from a Netlify Blobs store and, if it exists, prints the content to the terminal or saves it to a file`, @@ -36,12 +36,12 @@ export const createBlobsCommand = (program: BaseCommand) => { .option('-o, --output ', 'Defines the filesystem path where the blob data should be persisted') .alias('blob:get') .hook('preAction', requiresSiteInfo) - .action(async(storeName: string, key: string, options: OptionValues, command: BaseCommand) => { + .action(async (storeName: string, key: string, options: OptionValues, command: BaseCommand) => { const { blobsGet } = await import('./blobs-get.mjs') await blobsGet(storeName, key, options, command) }) - program + program .command('blobs:list') .description(`(Beta) Lists objects in a Netlify Blobs store`) .argument('', 'Name of the store') @@ -56,12 +56,12 @@ export const createBlobsCommand = (program: BaseCommand) => { .option('--json', `Output list contents as JSON`) .alias('blob:list') .hook('preAction', requiresSiteInfo) - .action(async(storeName: string, options: OptionValues, command: BaseCommand) => { + .action(async (storeName: string, options: OptionValues, command: BaseCommand) => { const { blobsList } = await import('./blobs-list.mjs') await blobsList(storeName, options, command) }) - program + program .command('blobs:set') .description( `(Beta) Writes to a Netlify Blobs store an object with the data provided in the command or the contents of a file defined by the 'input' parameter`, @@ -73,10 +73,12 @@ export const createBlobsCommand = (program: BaseCommand) => { .alias('blob:set') .hook('preAction', requiresSiteInfo) // eslint-disable-next-line max-params - .action(async(storeName: string, key: string, valueParts: string[], options: OptionValues, command: BaseCommand) => { - const { blobsSet } = await import('./blobs-set.mjs') - await blobsSet(storeName, key, valueParts, options, command) - }) + .action( + async (storeName: string, key: string, valueParts: string[], options: OptionValues, command: BaseCommand) => { + const { blobsSet } = await import('./blobs-set.mjs') + await blobsSet(storeName, key, valueParts, options, command) + }, + ) return program .command('blobs') diff --git a/src/commands/build/build.mts b/src/commands/build/build.mts index a78324e0651..0102feda682 100644 --- a/src/commands/build/build.mts +++ b/src/commands/build/build.mts @@ -33,7 +33,6 @@ const injectEnv = async function (command, { api, buildOptions, context, siteInf } } - export const build = async (options: OptionValues, command: BaseCommand) => { const { cachedConfig, siteInfo } = command.netlify command.setAnalyticsPayload({ dry: options.dry }) @@ -53,7 +52,7 @@ export const build = async (options: OptionValues, command: BaseCommand) => { packagePath: command.workspacePackage, currentDir: command.workingDir, token, - // @ts-expect-error TS(2740) + // @ts-expect-error TS(2740) options, }) @@ -68,4 +67,3 @@ export const build = async (options: OptionValues, command: BaseCommand) => { const { exitCode } = await runBuild(buildOptions) exit(exitCode) } - diff --git a/src/commands/build/index.mts b/src/commands/build/index.mts index 90a0a7e33c6..7d4d29157c0 100644 --- a/src/commands/build/index.mts +++ b/src/commands/build/index.mts @@ -1,7 +1,7 @@ import process from 'process' import { normalizeContext } from '../../utils/env/index.mjs' -import BaseCommand from "../base-command.mjs"; +import BaseCommand from '../base-command.mjs' export const createBuildCommand = (program: BaseCommand) => program @@ -16,7 +16,7 @@ export const createBuildCommand = (program: BaseCommand) => .option('--dry', 'Dry run: show instructions without running them', false) .option('-o, --offline', 'disables any features that require network access', false) .addExamples(['netlify build']) - .action(async(options, command) => { + .action(async (options, command) => { const { build } = await import('./build.mjs') - await build(options, command ) + await build(options, command) }) diff --git a/src/commands/completion/index.mts b/src/commands/completion/index.mts index d3b967125ee..38884810821 100644 --- a/src/commands/completion/index.mts +++ b/src/commands/completion/index.mts @@ -1,14 +1,13 @@ -import { OptionValues } from "commander" - -import BaseCommand from "../base-command.mjs" +import { OptionValues } from 'commander' +import BaseCommand from '../base-command.mjs' export const createCompletionCommand = (program: BaseCommand) => { program .command('completion:install') .alias('completion:generate') .description('Generates completion script for your preferred shell') - .action(async(options: OptionValues, command: BaseCommand) => { + .action(async (options: OptionValues, command: BaseCommand) => { const { completionGenerate } = await import('./completion.mjs') await completionGenerate(options, command) }) @@ -18,7 +17,7 @@ export const createCompletionCommand = (program: BaseCommand) => { .alias('completion:remove') .description('Uninstalls the installed completions') .addExamples(['netlify completion:uninstall']) - .action(async(options: OptionValues, command: BaseCommand) => { + .action(async (options: OptionValues, command: BaseCommand) => { const { completionUninstall } = await import('./completion.mjs') await completionUninstall(options, command) }) diff --git a/src/commands/deploy/deploy.mts b/src/commands/deploy/deploy.mts index b05b782c87c..5a11852c848 100644 --- a/src/commands/deploy/deploy.mts +++ b/src/commands/deploy/deploy.mts @@ -819,4 +819,3 @@ export const deploy = async (options: OptionValues, command: BaseCommand) => { exit() } } - diff --git a/src/commands/dev/dev-exec.mts b/src/commands/dev/dev-exec.mts index 460895f952d..ec52ec0bd01 100644 --- a/src/commands/dev/dev-exec.mts +++ b/src/commands/dev/dev-exec.mts @@ -5,8 +5,7 @@ import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.mjs' import { getEnvelopeEnv } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' - -export const devExec = async (cmd:string, options: OptionValues, command: BaseCommand) => { +export const devExec = async (cmd: string, options: OptionValues, command: BaseCommand) => { const { api, cachedConfig, config, site, siteInfo } = command.netlify let { env } = cachedConfig diff --git a/src/commands/dev/dev.mts b/src/commands/dev/dev.mts index 7c969b80057..6c9d94d8c8a 100644 --- a/src/commands/dev/dev.mts +++ b/src/commands/dev/dev.mts @@ -26,7 +26,6 @@ import { getProxyUrl } from '../../utils/proxy.mjs' import { runDevTimeline } from '../../utils/run-build.mjs' import BaseCommand from '../base-command.mjs' - /** * * @param {object} config @@ -66,7 +65,6 @@ const handleLiveTunnel = async ({ api, options, settings, site, state }) => { } } - export const dev = async (options: OptionValues, command: BaseCommand) => { log(`${NETLIFYDEV}`) const { api, cachedConfig, config, repositoryRoot, site, siteInfo, state } = command.netlify diff --git a/src/commands/dev/index.mts b/src/commands/dev/index.mts index 3f9a3f53d59..9a62614538d 100644 --- a/src/commands/dev/index.mts +++ b/src/commands/dev/index.mts @@ -1,10 +1,7 @@ import { Option, OptionValues } from 'commander' -import { - BANG, - chalk, -} from '../../utils/command-helpers.mjs' -import { normalizeContext } from '../../utils/env/index.mjs' +import { BANG, chalk } from '../../utils/command-helpers.mjs' +import { normalizeContext } from '../../utils/env/index.mjs' import { getGeoCountryArgParser } from '../../utils/validation.mjs' import BaseCommand from '../base-command.mjs' @@ -26,24 +23,23 @@ const validateShortFlagArgs = (args: string) => { export const createDevCommand = (program: BaseCommand) => { program - .command('dev:exec') - .argument('<...cmd>', `the command that should be executed`) - .option( - '--context ', - 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - 'dev', - ) - .description( - 'Exec command\nRuns a command within the netlify dev environment, e.g. with env variables from any installed addons', - ) - .allowExcessArguments(true) - .addExamples(['netlify dev:exec npm run bootstrap']) - .action(async (cmd:string, options: OptionValues, command: BaseCommand) => { - const { devExec } = await import('./dev-exec.mjs') - await devExec(cmd, options, command) - }) - + .command('dev:exec') + .argument('<...cmd>', `the command that should be executed`) + .option( + '--context ', + 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + 'dev', + ) + .description( + 'Exec command\nRuns a command within the netlify dev environment, e.g. with env variables from any installed addons', + ) + .allowExcessArguments(true) + .addExamples(['netlify dev:exec npm run bootstrap']) + .action(async (cmd: string, options: OptionValues, command: BaseCommand) => { + const { devExec } = await import('./dev-exec.mjs') + await devExec(cmd, options, command) + }) return program .command('dev') diff --git a/src/commands/env/env-clone.mts b/src/commands/env/env-clone.mts index 0fc041d05b7..fdd5bbc7108 100644 --- a/src/commands/env/env-clone.mts +++ b/src/commands/env/env-clone.mts @@ -1,4 +1,3 @@ - import { OptionValues } from 'commander' import { chalk, error as logError, log } from '../../utils/command-helpers.mjs' @@ -87,7 +86,6 @@ const envelopeToEnvelope = async ({ api, siteFrom, siteTo }) => { return true } - /** * Copies the env from a site not configured with Envelope to a different site not configured with Envelope * @returns {Promise} @@ -164,7 +162,6 @@ const mongoToEnvelope = async ({ api, siteFrom, siteTo }) => { return true } - export const envClone = async (options: OptionValues, command: BaseCommand) => { const { api, site } = command.netlify diff --git a/src/commands/env/env-get.mts b/src/commands/env/env-get.mts index 57bce0fbd3d..a16a05e78ef 100644 --- a/src/commands/env/env-get.mts +++ b/src/commands/env/env-get.mts @@ -4,7 +4,6 @@ import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' import { AVAILABLE_CONTEXTS, getEnvelopeEnv } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' - export const envGet = async (name: string, options: OptionValues, command: BaseCommand) => { const { context, scope } = options const { api, cachedConfig, site } = command.netlify diff --git a/src/commands/env/env-import.mts b/src/commands/env/env-import.mts index 063eaf8948b..6c8bdf4250f 100644 --- a/src/commands/env/env-import.mts +++ b/src/commands/env/env-import.mts @@ -8,7 +8,6 @@ import { exit, log, logJson } from '../../utils/command-helpers.mjs' import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' - /** * Updates the imported env in the site record * @returns {Promise} @@ -76,7 +75,6 @@ const importIntoEnvelope = async ({ api, importedEnv, options, siteInfo }) => { } } - export const envImport = async (fileName: string, options: OptionValues, command: BaseCommand) => { const { api, cachedConfig, site } = command.netlify const siteId = site.id diff --git a/src/commands/env/env-set.mts b/src/commands/env/env-set.mts index 8d1f407f7d4..92a25536341 100644 --- a/src/commands/env/env-set.mts +++ b/src/commands/env/env-set.mts @@ -1,15 +1,9 @@ - import { OptionValues } from 'commander' import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' -import { - AVAILABLE_CONTEXTS, - AVAILABLE_SCOPES, - translateFromEnvelopeToMongo, -} from '../../utils/env/index.mjs' +import { AVAILABLE_CONTEXTS, AVAILABLE_SCOPES, translateFromEnvelopeToMongo } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' - /** * Updates the env for a site record with a new key/value pair * @returns {Promise} @@ -136,7 +130,6 @@ const setInEnvelope = async ({ api, context, key, scope, secret, siteInfo, value } } - export const envSet = async (key: string, value: string, options: OptionValues, command: BaseCommand) => { const { context, scope, secret } = options diff --git a/src/commands/env/env-unset.mts b/src/commands/env/env-unset.mts index a796deddc13..8615e2c7ed2 100644 --- a/src/commands/env/env-unset.mts +++ b/src/commands/env/env-unset.mts @@ -1,4 +1,3 @@ - import { OptionValues } from 'commander' import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs' @@ -93,7 +92,6 @@ const unsetInEnvelope = async ({ api, context, key, siteInfo }) => { return env } - export const envUnset = async (key: string, options: OptionValues, command: BaseCommand) => { const { context } = options const { api, cachedConfig, site } = command.netlify @@ -129,4 +127,3 @@ export const envUnset = async (key: string, options: OptionValues, command: Base const contextType = AVAILABLE_CONTEXTS.includes(context || 'all') ? 'context' : 'branch' log(`Unset environment variable ${chalk.yellow(key)} in the ${chalk.magenta(context || 'all')} ${contextType}`) } - diff --git a/src/commands/env/env.mts b/src/commands/env/env.mts index 1adc131702e..cf58e55d1a3 100644 --- a/src/commands/env/env.mts +++ b/src/commands/env/env.mts @@ -1,40 +1,38 @@ - import { OptionValues, Option } from 'commander' -import { normalizeContext } from '../../utils/env/index.mjs' +import { normalizeContext } from '../../utils/env/index.mjs' import BaseCommand from '../base-command.mjs' - const env = (options: OptionValues, command: BaseCommand) => { command.help() } export const createEnvCommand = (program: BaseCommand) => { program - .command('env:get') - .argument('', 'Environment variable name') - .option( - '-c, --context ', - 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - 'dev', - ) - .addOption( - new Option('-s, --scope ', 'Specify a scope') - .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) - .default('any'), - ) - .addExamples([ - 'netlify env:get MY_VAR # get value for MY_VAR in dev context', - 'netlify env:get MY_VAR --context production', - 'netlify env:get MY_VAR --context branch:staging', - 'netlify env:get MY_VAR --scope functions', - ]) - .description('Get resolved value of specified environment variable (includes netlify.toml)') - .action(async (name: string, options: OptionValues, command: BaseCommand) => { - const { envGet } = await import('./env-get.mjs') - await envGet(name, options, command) - }) + .command('env:get') + .argument('', 'Environment variable name') + .option( + '-c, --context ', + 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + 'dev', + ) + .addOption( + new Option('-s, --scope ', 'Specify a scope') + .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) + .default('any'), + ) + .addExamples([ + 'netlify env:get MY_VAR # get value for MY_VAR in dev context', + 'netlify env:get MY_VAR --context production', + 'netlify env:get MY_VAR --context branch:staging', + 'netlify env:get MY_VAR --scope functions', + ]) + .description('Get resolved value of specified environment variable (includes netlify.toml)') + .action(async (name: string, options: OptionValues, command: BaseCommand) => { + const { envGet } = await import('./env-get.mjs') + await envGet(name, options, command) + }) program .command('env:import') @@ -54,11 +52,11 @@ export const createEnvCommand = (program: BaseCommand) => { ) .description('Import and set environment variables from .env file') .action(async (fileName: string, options: OptionValues, command: BaseCommand) => { - const {envImport} = await import('./env-import.mjs') + const { envImport } = await import('./env-import.mjs') await envImport(fileName, options, command) }) - program + program .command('env:list') .option( '-c, --context ', @@ -82,11 +80,11 @@ export const createEnvCommand = (program: BaseCommand) => { ]) .description('Lists resolved environment variables for site (includes netlify.toml)') .action(async (options: OptionValues, command: BaseCommand) => { - const {envList} = await import('./env-list.mjs') + const { envList } = await import('./env-list.mjs') await envList(options, command) }) - program + program .command('env:set') .argument('', 'Environment variable key') .argument('[value]', 'Value to set to', '') @@ -116,13 +114,12 @@ export const createEnvCommand = (program: BaseCommand) => { 'netlify env:set VAR_NAME value --scope builds functions', 'netlify env:set VAR_NAME --secret # convert existing variable to secret', ]) - .action(async (key: string, value:string, options: OptionValues, command: BaseCommand) => { - const {envSet} = await import('./env-set.mjs') + .action(async (key: string, value: string, options: OptionValues, command: BaseCommand) => { + const { envSet } = await import('./env-set.mjs') await envSet(key, value, options, command) }) - - program + program .command('env:unset') .aliases(['env:delete', 'env:remove']) .argument('', 'Environment variable key') @@ -140,11 +137,11 @@ export const createEnvCommand = (program: BaseCommand) => { ]) .description('Unset an environment variable which removes it from the UI') .action(async (key: string, options: OptionValues, command: BaseCommand) => { - const {envUnset} = await import('./env-unset.mjs') + const { envUnset } = await import('./env-unset.mjs') await envUnset(key, options, command) }) - program + program .command('env:clone') .alias('env:migrate') .option('-f, --from ', 'Site ID (From)') @@ -152,11 +149,10 @@ export const createEnvCommand = (program: BaseCommand) => { .description(`Clone environment variables from one site to another`) .addExamples(['netlify env:clone --to ', 'netlify env:clone --to --from ']) .action(async (options: OptionValues, command: BaseCommand) => { - const {envClone} = await import('./env-clone.mjs') + const { envClone } = await import('./env-clone.mjs') await envClone(options, command) }) - return program .command('env') .description('Control environment variables for the current site') diff --git a/src/commands/functions/functions-build.mts b/src/commands/functions/functions-build.mts index f293aa41918..800a4e8d841 100644 --- a/src/commands/functions/functions-build.mts +++ b/src/commands/functions/functions-build.mts @@ -7,7 +7,6 @@ import { NETLIFYDEVERR, NETLIFYDEVLOG, exit, log } from '../../utils/command-hel import { getFunctionsDir } from '../../utils/functions/index.mjs' import BaseCommand from '../base-command.mjs' - export const functionsBuild = async (options: OptionValues, command: BaseCommand) => { const { config } = command.netlify diff --git a/src/commands/functions/functions-create.mts b/src/commands/functions/functions-create.mts index b8308e295fd..e7a29377715 100644 --- a/src/commands/functions/functions-create.mts +++ b/src/commands/functions/functions-create.mts @@ -750,7 +750,6 @@ const ensureFunctionPathIsOk = function (functionsDir, name) { return functionPath } - export const functionsCreate = async (name: string, options: OptionValues, command: BaseCommand) => { const functionType = await selectTypeOfFunc() const functionsDir = diff --git a/src/commands/functions/functions-serve.mts b/src/commands/functions/functions-serve.mts index a9f1a81557e..3d4d9b282cb 100644 --- a/src/commands/functions/functions-serve.mts +++ b/src/commands/functions/functions-serve.mts @@ -11,7 +11,6 @@ import BaseCommand from '../base-command.mjs' const DEFAULT_PORT = 9999 - export const functionsServe = async (options: OptionValues, command: BaseCommand) => { const { api, config, site, siteInfo, state } = command.netlify @@ -59,4 +58,3 @@ export const functionsServe = async (options: OptionValues, command: BaseCommand const url = getProxyUrl({ port: functionsPort }) printBanner({ url }) } - diff --git a/src/commands/functions/functions.mts b/src/commands/functions/functions.mts index 44cfffb4d44..7db507c491a 100644 --- a/src/commands/functions/functions.mts +++ b/src/commands/functions/functions.mts @@ -1,4 +1,3 @@ - import { OptionValues } from 'commander' import { chalk } from '../../utils/command-helpers.mjs' @@ -16,29 +15,28 @@ export const createFunctionsCommand = (program: BaseCommand) => { .description('Build functions locally') .option('-f, --functions ', 'Specify a functions directory to build to') .option('-s, --src ', 'Specify the source directory for the functions') - .action(async(options: OptionValues, command: BaseCommand) => { + .action(async (options: OptionValues, command: BaseCommand) => { const { functionsBuild } = await import('./functions-build.mjs') await functionsBuild(options, command) }) program - .command('functions:create') - .alias('function:create') - .argument('[name]', 'name of your new function file inside your functions directory') - .description('Create a new function locally') - .option('-n, --name ', 'function name') - .option('-u, --url ', 'pull template from URL') - .option('-l, --language ', 'function language') - .addExamples([ - 'netlify functions:create', - 'netlify functions:create hello-world', - 'netlify functions:create --name hello-world', - ]) - .action(async(name: string, options: OptionValues, command: BaseCommand) => { - const { functionsCreate } = await import('./functions-create.mjs') - await functionsCreate(name, options, command) - }) - + .command('functions:create') + .alias('function:create') + .argument('[name]', 'name of your new function file inside your functions directory') + .description('Create a new function locally') + .option('-n, --name ', 'function name') + .option('-u, --url ', 'pull template from URL') + .option('-l, --language ', 'function language') + .addExamples([ + 'netlify functions:create', + 'netlify functions:create hello-world', + 'netlify functions:create --name hello-world', + ]) + .action(async (name: string, options: OptionValues, command: BaseCommand) => { + const { functionsCreate } = await import('./functions-create.mjs') + await functionsCreate(name, options, command) + }) program .command('functions:invoke') @@ -71,13 +69,12 @@ export const createFunctionsCommand = (program: BaseCommand) => { 'netlify functions:invoke myfunction --querystring "foo=1', 'netlify functions:invoke myfunction --payload "./pathTo.json"', ]) - .action(async(name: string, options: OptionValues, command: BaseCommand) => { + .action(async (name: string, options: OptionValues, command: BaseCommand) => { const { functionsInvoke } = await import('./functions-invoke.mjs') await functionsInvoke(name, options, command) }) - - program + program .command('functions:list') .alias('function:list') .description( @@ -89,12 +86,12 @@ NOT the same as listing the functions that have been deployed. For that info you .option('-f, --functions ', 'Specify a functions directory to list') .option('--json', 'Output function data as JSON') .hook('preAction', requiresSiteInfo) - .action(async(options: OptionValues, command: BaseCommand) => { + .action(async (options: OptionValues, command: BaseCommand) => { const { functionsList } = await import('./functions-list.mjs') await functionsList(options, command) }) - program + program .command('functions:serve') .alias('function:serve') .description('Serve functions locally') @@ -102,7 +99,7 @@ NOT the same as listing the functions that have been deployed. For that info you .option('-p, --port ', 'Specify a port for the functions server', (value) => Number.parseInt(value)) .option('-o, --offline', 'disables any features that require network access') .addHelpText('after', 'Helpful for debugging functions.') - .action(async(options: OptionValues, command: BaseCommand) => { + .action(async (options: OptionValues, command: BaseCommand) => { const { functionsServe } = await import('./functions-serve.mjs') await functionsServe(options, command) }) diff --git a/src/commands/init/index.mts b/src/commands/init/index.mts index 96f608a9cc7..49b4f18a0b5 100644 --- a/src/commands/init/index.mts +++ b/src/commands/init/index.mts @@ -1,6 +1,6 @@ -import { Option, OptionValues } from "commander"; +import { Option, OptionValues } from 'commander' -import BaseCommand from "../base-command.mjs"; +import BaseCommand from '../base-command.mjs' export const createInitCommand = (program: BaseCommand) => program @@ -17,7 +17,7 @@ export const createInitCommand = (program: BaseCommand) => ).hideHelp(true), ) .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') - .action(async(options: OptionValues, command: BaseCommand) => { + .action(async (options: OptionValues, command: BaseCommand) => { const { init } = await import('./init.mjs') await init(options, command) }) diff --git a/src/commands/integration/deploy.mts b/src/commands/integration/deploy.mts index e67aab077ab..103097e9674 100644 --- a/src/commands/integration/deploy.mts +++ b/src/commands/integration/deploy.mts @@ -404,7 +404,7 @@ export const deploy = async (options: OptionValues, command: BaseCommand) => { packagePath: command.workspacePackage, currentDir: command.workingDir, token, - // @ts-expect-error TS(2740) + // @ts-expect-error TS(2740) options, }) diff --git a/src/commands/integration/index.mts b/src/commands/integration/index.mts index aa9170d64c3..e77471d9077 100644 --- a/src/commands/integration/index.mts +++ b/src/commands/integration/index.mts @@ -2,7 +2,7 @@ import { env } from 'process' import { OptionValues } from 'commander' -import BaseCommand from "../base-command.mjs" +import BaseCommand from '../base-command.mjs' const integrations = (options: OptionValues, command: BaseCommand) => { command.help() @@ -10,18 +10,17 @@ const integrations = (options: OptionValues, command: BaseCommand) => { export const createIntegrationDeployCommand = (program: BaseCommand) => { program - .command('integration:deploy') - .alias('int:deploy') - .description('Register, build, and deploy a private integration on Netlify') - .option('-p, --prod', 'Deploy to production', false) - .option('-b, --build', 'Build the integration', false) - .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) - .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) - .action(async(options: OptionValues, command: BaseCommand) => { - const { deploy } = await import('./deploy.mjs') - await deploy(options, command) - }) - + .command('integration:deploy') + .alias('int:deploy') + .description('Register, build, and deploy a private integration on Netlify') + .option('-p, --prod', 'Deploy to production', false) + .option('-b, --build', 'Build the integration', false) + .option('-a, --auth ', 'Netlify auth token to deploy with', env.NETLIFY_AUTH_TOKEN) + .option('-s, --site ', 'A site name or ID to deploy to', env.NETLIFY_SITE_ID) + .action(async (options: OptionValues, command: BaseCommand) => { + const { deploy } = await import('./deploy.mjs') + await deploy(options, command) + }) } export const createIntegrationCommand = (program: BaseCommand) => { diff --git a/src/commands/link/index.mts b/src/commands/link/index.mts index cc15cd4913d..b2fe2d89120 100644 --- a/src/commands/link/index.mts +++ b/src/commands/link/index.mts @@ -1,7 +1,6 @@ -import { Option, OptionValues } from "commander"; - -import BaseCommand from "../base-command.mjs"; +import { Option, OptionValues } from 'commander' +import BaseCommand from '../base-command.mjs' export const createLinkCommand = (program: BaseCommand) => program diff --git a/src/commands/link/link.mts b/src/commands/link/link.mts index 29b1bfb6bb0..8f6a834eb14 100644 --- a/src/commands/link/link.mts +++ b/src/commands/link/link.mts @@ -250,7 +250,6 @@ or run ${chalk.cyanBright('netlify sites:create')} to create a site.`) return site } - export const link = async (options: OptionValues, command: BaseCommand) => { await command.authenticate() diff --git a/src/commands/lm/lm-install.mts b/src/commands/lm/lm-install.mts index 3f3b9cd050b..104d46dcda5 100644 --- a/src/commands/lm/lm-install.mts +++ b/src/commands/lm/lm-install.mts @@ -3,7 +3,6 @@ import { OptionValues } from 'commander' import { installPlatform } from '../../utils/lm/install.mjs' import { printBanner } from '../../utils/lm/ui.mjs' - export const lmInstall = async ({ force }: OptionValues) => { const installed = await installPlatform({ force }) if (installed) { diff --git a/src/commands/lm/lm-setup.mts b/src/commands/lm/lm-setup.mts index 7c56083ffe3..5215040adf6 100644 --- a/src/commands/lm/lm-setup.mts +++ b/src/commands/lm/lm-setup.mts @@ -57,7 +57,6 @@ const configureLFSURL = async function (siteId, api) { return execa('git', ['config', '-f', '.lfsconfig', 'lfs.url', url]) } - export const lmSetup = async (options: OptionValues, command: BaseCommand) => { await command.authenticate() diff --git a/src/commands/lm/lm.mts b/src/commands/lm/lm.mts index 11701be5e12..7e1e30773e8 100644 --- a/src/commands/lm/lm.mts +++ b/src/commands/lm/lm.mts @@ -2,33 +2,32 @@ import { OptionValues } from 'commander' import BaseCommand from '../base-command.mjs' - const lm = (options: OptionValues, command: BaseCommand) => { command.help() } export const createLmCommand = (program: BaseCommand) => { program - .command('lm:info', { hidden: true }) - .description('Show large media requirements information.') - .action(async () => { - const { lmInfo } = await import('./lm-info.mjs') - await lmInfo() - }) + .command('lm:info', { hidden: true }) + .description('Show large media requirements information.') + .action(async () => { + const { lmInfo } = await import('./lm-info.mjs') + await lmInfo() + }) program - .command('lm:install', { hidden: true }) - .alias('lm:init') - .description( - `Configures your computer to use Netlify Large Media + .command('lm:install', { hidden: true }) + .alias('lm:init') + .description( + `Configures your computer to use Netlify Large Media It installs the required credentials helper for Git, and configures your Git environment with the right credentials.`, - ) - .option('-f, --force', 'Force the credentials helper installation') - .action(async (options: OptionValues) => { - const { lmInstall } = await import('./lm-install.mjs') - await lmInstall(options) - }) + ) + .option('-f, --force', 'Force the credentials helper installation') + .action(async (options: OptionValues) => { + const { lmInstall } = await import('./lm-install.mjs') + await lmInstall(options) + }) program .command('lm:setup', { hidden: true }) @@ -41,14 +40,13 @@ and configures your Git environment with the right credentials.`, await lmSetup(options, command) }) - - program + program .command('lm:uninstall', { hidden: true }) .alias('lm:remove') .description( 'Uninstalls Netlify git credentials helper and cleans up any related configuration changes made by the install command.', ) - .action(async() => { + .action(async () => { const { lmUninstall } = await import('./lm-uninstall.mjs') await lmUninstall() }) diff --git a/src/commands/login/login.mts b/src/commands/login/login.mts index 85cbb80e410..d1fcd3c8938 100644 --- a/src/commands/login/login.mts +++ b/src/commands/login/login.mts @@ -17,7 +17,6 @@ const msg = function (location) { } } - export const login = async (options: OptionValues, command: BaseCommand) => { // @ts-expect-error TS(2554) FIXME: Expected 1 arguments, but got 0. const [accessToken, location] = await getToken() diff --git a/src/commands/logout/index.mts b/src/commands/logout/index.mts index 0df6d3ffe21..469ca8212e4 100644 --- a/src/commands/logout/index.mts +++ b/src/commands/logout/index.mts @@ -1,12 +1,12 @@ -import { OptionValues } from "commander"; +import { OptionValues } from 'commander' -import BaseCommand from "../base-command.mjs"; +import BaseCommand from '../base-command.mjs' export const createLogoutCommand = (program: BaseCommand) => program - .command('logout', { hidden: true }) - .description('Logout of your Netlify account') - .action(async (options: OptionValues, command: BaseCommand) => { - const { logout } = await import('./logout.mjs') - await logout(options, command) - }) + .command('logout', { hidden: true }) + .description('Logout of your Netlify account') + .action(async (options: OptionValues, command: BaseCommand) => { + const { logout } = await import('./logout.mjs') + await logout(options, command) + }) diff --git a/src/commands/logout/logout.mts b/src/commands/logout/logout.mts index ef53522d75b..485b22cfea8 100644 --- a/src/commands/logout/logout.mts +++ b/src/commands/logout/logout.mts @@ -4,7 +4,6 @@ import { exit, getToken, log } from '../../utils/command-helpers.mjs' import { track } from '../../utils/telemetry/index.mjs' import BaseCommand from '../base-command.mjs' - export const logout = async (options: OptionValues, command: BaseCommand) => { // @ts-expect-error TS(2554) FIXME: Expected 1 arguments, but got 0. const [accessToken, location] = await getToken() diff --git a/src/commands/logs/index.mts b/src/commands/logs/index.mts index 057d866dcc5..8e42c5cab9f 100644 --- a/src/commands/logs/index.mts +++ b/src/commands/logs/index.mts @@ -4,13 +4,13 @@ import BaseCommand from '../base-command.mjs' export const createLogsBuildCommand = (program: BaseCommand) => { program - .command('logs:deploy') - .alias('logs:build') - .description('(Beta) Stream the logs of deploys currently being built to the console') - .action(async (options: OptionValues, command: BaseCommand) => { - const { logsBuild } = await import('./build.mjs') - await logsBuild(options, command) - }) + .command('logs:deploy') + .alias('logs:build') + .description('(Beta) Stream the logs of deploys currently being built to the console') + .action(async (options: OptionValues, command: BaseCommand) => { + const { logsBuild } = await import('./build.mjs') + await logsBuild(options, command) + }) } export const createLogsFunctionCommand = (program: BaseCommand) => { @@ -24,10 +24,9 @@ export const createLogsFunctionCommand = (program: BaseCommand) => { const { logsFunction } = await import('./functions.mjs') await logsFunction(functionName, options, command) }) - } +} export const createLogsCommand = (program: BaseCommand) => { - createLogsBuildCommand(program) createLogsFunctionCommand(program) diff --git a/src/commands/open/index.mts b/src/commands/open/index.mts index 446d14228f5..ca62242171d 100644 --- a/src/commands/open/index.mts +++ b/src/commands/open/index.mts @@ -1,18 +1,18 @@ -import { OptionValues } from "commander" +import { OptionValues } from 'commander' import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' -import BaseCommand from "../base-command.mjs" +import BaseCommand from '../base-command.mjs' export const createOpenCommand = (program: BaseCommand) => { program - .command('open:admin') - .description('Opens current site admin UI in Netlify') - .addExamples(['netlify open:admin']) - .hook('preAction', requiresSiteInfo) - .action(async (options: OptionValues, command: BaseCommand) => { - const { openAdmin } = await import('./open-admin.mjs') - await openAdmin(options, command) - }) + .command('open:admin') + .description('Opens current site admin UI in Netlify') + .addExamples(['netlify open:admin']) + .hook('preAction', requiresSiteInfo) + .action(async (options: OptionValues, command: BaseCommand) => { + const { openAdmin } = await import('./open-admin.mjs') + await openAdmin(options, command) + }) program .command('open:site') @@ -24,7 +24,6 @@ export const createOpenCommand = (program: BaseCommand) => { await openSite(options, command) }) - return program .command('open') .description(`Open settings for the site linked to the current folder`) diff --git a/src/commands/open/open-admin.mts b/src/commands/open/open-admin.mts index c66c9bdad2b..c2278ddfb9e 100644 --- a/src/commands/open/open-admin.mts +++ b/src/commands/open/open-admin.mts @@ -4,7 +4,6 @@ import { exit, log } from '../../utils/command-helpers.mjs' import openBrowser from '../../utils/open-browser.mjs' import BaseCommand from '../base-command.mjs' - export const openAdmin = async (options: OptionValues, command: BaseCommand) => { const { siteInfo } = command.netlify diff --git a/src/commands/open/open-site.mts b/src/commands/open/open-site.mts index 7b25268e3d7..4cdeda7083a 100644 --- a/src/commands/open/open-site.mts +++ b/src/commands/open/open-site.mts @@ -4,7 +4,6 @@ import { exit, log } from '../../utils/command-helpers.mjs' import openBrowser from '../../utils/open-browser.mjs' import BaseCommand from '../base-command.mjs' - export const openSite = async (options: OptionValues, command: BaseCommand) => { const { siteInfo } = command.netlify diff --git a/src/commands/open/open.mts b/src/commands/open/open.mts index 0fbd85ac219..f60ce9bebdc 100644 --- a/src/commands/open/open.mts +++ b/src/commands/open/open.mts @@ -6,7 +6,6 @@ import BaseCommand from '../base-command.mjs' import { openAdmin } from './open-admin.mjs' import { openSite } from './open-site.mjs' - export const open = async (options: OptionValues, command: BaseCommand) => { if (!options.site || !options.admin) { log(command.helpInformation()) diff --git a/src/commands/recipes/index.mts b/src/commands/recipes/index.mts index 8e6750c29ad..cc183282192 100644 --- a/src/commands/recipes/index.mts +++ b/src/commands/recipes/index.mts @@ -1,6 +1,6 @@ -import { OptionValues } from "commander" +import { OptionValues } from 'commander' -import BaseCommand from "../base-command.mjs" +import BaseCommand from '../base-command.mjs' export const createRecipesCommand = (program: BaseCommand) => { program diff --git a/src/commands/recipes/recipes.mts b/src/commands/recipes/recipes.mts index 99ffb29878d..e248c2df561 100644 --- a/src/commands/recipes/recipes.mts +++ b/src/commands/recipes/recipes.mts @@ -11,7 +11,6 @@ import { getRecipe, listRecipes } from './common.mjs' const SUGGESTION_TIMEOUT = 1e4 - // @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message export const runRecipe = async ({ config, recipeName, repositoryRoot }) => { const recipe = await getRecipe(recipeName) @@ -19,7 +18,6 @@ export const runRecipe = async ({ config, recipeName, repositoryRoot }) => { return recipe.run({ config, repositoryRoot }) } - export const recipesCommand = async (recipeName: string, options: OptionValues, command: BaseCommand): Promise => { const { config, repositoryRoot } = command.netlify const sanitizedRecipeName = basename(recipeName || '').toLowerCase() diff --git a/src/commands/serve/index.mts b/src/commands/serve/index.mts index bd04792936b..4a002d32d0c 100644 --- a/src/commands/serve/index.mts +++ b/src/commands/serve/index.mts @@ -1,8 +1,8 @@ -import { Option } from "commander"; +import { Option } from 'commander' -import { normalizeContext } from '../../utils/env/index.mjs' +import { normalizeContext } from '../../utils/env/index.mjs' import { getGeoCountryArgParser } from '../../utils/validation.mjs' -import BaseCommand from "../base-command.mjs"; +import BaseCommand from '../base-command.mjs' export const createServeCommand = (program: BaseCommand) => program diff --git a/src/commands/serve/serve.mts b/src/commands/serve/serve.mts index 8744d806476..669ec07bd7e 100644 --- a/src/commands/serve/serve.mts +++ b/src/commands/serve/serve.mts @@ -24,7 +24,6 @@ import { generateInspectSettings, startProxyServer } from '../../utils/proxy-ser import { runBuildTimeline } from '../../utils/run-build.mjs' import BaseCommand from '../base-command.mjs' - export const serve = async (options: OptionValues, command: BaseCommand) => { const { api, cachedConfig, config, repositoryRoot, site, siteInfo, state } = command.netlify config.dev = { ...config.dev } diff --git a/src/commands/sites/sites-create-template.mts b/src/commands/sites/sites-create-template.mts index 37a6518a65b..3856595942f 100644 --- a/src/commands/sites/sites-create-template.mts +++ b/src/commands/sites/sites-create-template.mts @@ -69,7 +69,6 @@ const getTemplateName = async ({ ghToken, options, repository }) => { // @ts-expect-error TS(7031) FIXME: Binding element 'options' implicitly has an 'any' ... Remove this comment to see the full error message const getGitHubLink = ({ options, templateName }) => options.url || `https://github.com/${templateName}` - export const sitesCreateTemplate = async (repository: string, options: OptionValues, command: BaseCommand) => { const { api } = command.netlify diff --git a/src/commands/sites/sites-create.mts b/src/commands/sites/sites-create.mts index 8e41e6a287d..6e2e77d4141 100644 --- a/src/commands/sites/sites-create.mts +++ b/src/commands/sites/sites-create.mts @@ -28,7 +28,6 @@ export const getSiteNameInput = async (name) => { return { name } } - export const sitesCreate = async (options: OptionValues, command: BaseCommand) => { const { api } = command.netlify @@ -154,4 +153,3 @@ export const sitesCreate = async (options: OptionValues, command: BaseCommand) = return site } - diff --git a/src/commands/sites/sites-delete.mts b/src/commands/sites/sites-delete.mts index e982532ddd0..370175e3398 100644 --- a/src/commands/sites/sites-delete.mts +++ b/src/commands/sites/sites-delete.mts @@ -4,7 +4,6 @@ import inquirer from 'inquirer' import { chalk, error, exit, log } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' - export const sitesDelete = async (siteId: string, options: OptionValues, command: BaseCommand) => { command.setAnalyticsPayload({ force: options.force }) diff --git a/src/commands/sites/sites-list.mts b/src/commands/sites/sites-list.mts index a3de86eeed2..399da20a73d 100644 --- a/src/commands/sites/sites-list.mts +++ b/src/commands/sites/sites-list.mts @@ -5,7 +5,6 @@ import { startSpinner, stopSpinner } from '../../lib/spinner.mjs' import { chalk, log, logJson } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' - export const sitesList = async (options: OptionValues, command: BaseCommand) => { const { api } = command.netlify /** @type {import('ora').Ora} */ diff --git a/src/commands/sites/sites.mts b/src/commands/sites/sites.mts index 911db66010d..ac48feaed3d 100644 --- a/src/commands/sites/sites.mts +++ b/src/commands/sites/sites.mts @@ -1,4 +1,4 @@ -import { OptionValues , InvalidArgumentError } from 'commander' +import { OptionValues, InvalidArgumentError } from 'commander' import BaseCommand from '../base-command.mjs' @@ -44,42 +44,40 @@ Create a site from a starter template.`, export const createSitesCreateCommand = (program: BaseCommand) => { program - .command('sites:create') - .description( - `Create an empty site (advanced) + .command('sites:create') + .description( + `Create an empty site (advanced) Create a blank site that isn't associated with any git remote. Will link the site to the current working directory.`, - ) - .option('-n, --name ', 'name of site', validateName) - .option('-a, --account-slug ', 'account slug to create the site under') - .option('-c, --with-ci', 'initialize CI hooks during site creation') - .option('-m, --manual', 'force manual CI setup. Used --with-ci flag') - .option('--disable-linking', 'create the site without linking it to current directory') - .addHelpText( - 'after', - `Create a blank site that isn't associated with any git remote. Will link the site to the current working directory.`, - ) - .action(async (options: OptionValues, command: BaseCommand) => { - const { sitesCreate } = await import('./sites-create.mjs') - await sitesCreate(options, command) - }) - } - + ) + .option('-n, --name ', 'name of site', validateName) + .option('-a, --account-slug ', 'account slug to create the site under') + .option('-c, --with-ci', 'initialize CI hooks during site creation') + .option('-m, --manual', 'force manual CI setup. Used --with-ci flag') + .option('--disable-linking', 'create the site without linking it to current directory') + .addHelpText( + 'after', + `Create a blank site that isn't associated with any git remote. Will link the site to the current working directory.`, + ) + .action(async (options: OptionValues, command: BaseCommand) => { + const { sitesCreate } = await import('./sites-create.mjs') + await sitesCreate(options, command) + }) +} export const createSitesCommand = (program: BaseCommand) => { + createSitesCreateCommand(program) + createSitesFromTemplateCommand(program) - createSitesCreateCommand(program) - createSitesFromTemplateCommand(program) - - program + program .command('sites:list') .description('List all sites you have access to') .option('--json', 'Output site data as JSON') .action(async (options: OptionValues, command: BaseCommand) => { - const {sitesList} = await import('./sites-list.mjs') + const { sitesList } = await import('./sites-list.mjs') await sitesList(options, command) }) - program + program .command('sites:delete') .description('Delete a site\nThis command will permanently delete the site on Netlify. Use with caution.') .argument('', 'Site ID to delete.') diff --git a/src/commands/status/index.mts b/src/commands/status/index.mts index 6e1c1d4d4e3..4993d1fe780 100644 --- a/src/commands/status/index.mts +++ b/src/commands/status/index.mts @@ -1,7 +1,7 @@ -import { OptionValues } from "commander" +import { OptionValues } from 'commander' import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs' -import BaseCommand from "../base-command.mjs" +import BaseCommand from '../base-command.mjs' export const createStatusCommand = (program: BaseCommand) => { program diff --git a/src/commands/status/status-hooks.mts b/src/commands/status/status-hooks.mts index a74f3c63d35..9c6a2076e92 100644 --- a/src/commands/status/status-hooks.mts +++ b/src/commands/status/status-hooks.mts @@ -4,7 +4,6 @@ import prettyjson from 'prettyjson' import { log } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' - export const statusHooks = async (options: OptionValues, command: BaseCommand) => { const { api, siteInfo } = command.netlify diff --git a/src/commands/status/status.mts b/src/commands/status/status.mts index 6a331ba05f9..01a78c94596 100644 --- a/src/commands/status/status.mts +++ b/src/commands/status/status.mts @@ -5,7 +5,6 @@ import prettyjson from 'prettyjson' import { chalk, error, exit, getToken, log, logJson, warn } from '../../utils/command-helpers.mjs' import BaseCommand from '../base-command.mjs' - export const status = async (options: OptionValues, command: BaseCommand) => { const { api, globalConfig, site, siteInfo } = command.netlify const current = globalConfig.get('userId') diff --git a/src/commands/switch/index.mts b/src/commands/switch/index.mts index 9d2b7b1b798..6a085c48447 100644 --- a/src/commands/switch/index.mts +++ b/src/commands/switch/index.mts @@ -1,12 +1,12 @@ -import { OptionValues } from "commander"; +import { OptionValues } from 'commander' -import BaseCommand from "../base-command.mjs"; +import BaseCommand from '../base-command.mjs' export const createSwitchCommand = (program: BaseCommand) => program - .command('switch') - .description('Switch your active Netlify account') - .action(async (options: OptionValues, command: BaseCommand) => { - const { switchCommand } = await import('./switch.mjs') - await switchCommand(options, command) - }) + .command('switch') + .description('Switch your active Netlify account') + .action(async (options: OptionValues, command: BaseCommand) => { + const { switchCommand } = await import('./switch.mjs') + await switchCommand(options, command) + }) diff --git a/src/commands/switch/switch.mts b/src/commands/switch/switch.mts index 74f225ad496..a77d77a1160 100644 --- a/src/commands/switch/switch.mts +++ b/src/commands/switch/switch.mts @@ -7,7 +7,6 @@ import { login } from '../login/login.mjs' const LOGIN_NEW = 'I would like to login to a new account' - export const switchCommand = async (options: OptionValues, command: BaseCommand) => { const availableUsersChoices = Object.values(command.netlify.globalConfig.get('users') || {}).reduce( (prev, current) => diff --git a/src/commands/unlink/index.mts b/src/commands/unlink/index.mts index 682aee96c69..b1c1250c235 100644 --- a/src/commands/unlink/index.mts +++ b/src/commands/unlink/index.mts @@ -1,12 +1,12 @@ -import { OptionValues } from "commander"; +import { OptionValues } from 'commander' -import BaseCommand from "../base-command.mjs"; +import BaseCommand from '../base-command.mjs' export const createUnlinkCommand = (program: BaseCommand) => - program. - command('unlink') - .description('Unlink a local folder from a Netlify site') - .action(async (options: OptionValues, command: BaseCommand) => { - const { unlink } = await import('./unlink.mjs') - await unlink(options, command) - }) + program + .command('unlink') + .description('Unlink a local folder from a Netlify site') + .action(async (options: OptionValues, command: BaseCommand) => { + const { unlink } = await import('./unlink.mjs') + await unlink(options, command) + }) diff --git a/src/commands/unlink/unlink.mts b/src/commands/unlink/unlink.mts index ef616b787c9..a5316e524dc 100644 --- a/src/commands/unlink/unlink.mts +++ b/src/commands/unlink/unlink.mts @@ -4,7 +4,6 @@ import { exit, log } from '../../utils/command-helpers.mjs' import { track } from '../../utils/telemetry/index.mjs' import BaseCommand from '../base-command.mjs' - export const unlink = async (options: OptionValues, command: BaseCommand) => { const { site, siteInfo, state } = command.netlify const siteId = site.id diff --git a/src/commands/watch/index.mts b/src/commands/watch/index.mts index 505cfb58fbe..8ceeb882e76 100644 --- a/src/commands/watch/index.mts +++ b/src/commands/watch/index.mts @@ -1,6 +1,6 @@ -import { OptionValues } from "commander"; +import { OptionValues } from 'commander' -import BaseCommand from "../base-command.mjs"; +import BaseCommand from '../base-command.mjs' export const createWatchCommand = (program: BaseCommand) => program diff --git a/src/commands/watch/watch.mts b/src/commands/watch/watch.mts index 57ef45c56af..ae8b146509c 100644 --- a/src/commands/watch/watch.mts +++ b/src/commands/watch/watch.mts @@ -56,7 +56,6 @@ const waitForBuildFinish = async function (api, siteId, spinner) { return firstPass } - export const watch = async (options: OptionValues, command: BaseCommand) => { await command.authenticate() const client = command.netlify.api From a9dbed419a95490bc2ceb99950e5f68d5b037ee2 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Fri, 17 Nov 2023 13:52:20 -0500 Subject: [PATCH 57/67] chore: up timeout for start dev server in test utils --- tests/integration/utils/dev-server.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/utils/dev-server.mjs b/tests/integration/utils/dev-server.mjs index 745efc5bdf1..8d5086ecf10 100644 --- a/tests/integration/utils/dev-server.mjs +++ b/tests/integration/utils/dev-server.mjs @@ -143,8 +143,8 @@ export const startDevServer = async (options, expectFailure) => { } } -// 240 seconds -const SERVER_START_TIMEOUT = 24e4 +// 600 seconds +const SERVER_START_TIMEOUT = 60e4 export const withDevServer = async (options, testHandler, expectFailure = false) => { let server From 6fd791785640a41945aa526b73caba3e3caf759e Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Fri, 17 Nov 2023 14:24:37 -0500 Subject: [PATCH 58/67] chore: return to original value --- tests/integration/utils/dev-server.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/utils/dev-server.mjs b/tests/integration/utils/dev-server.mjs index 8d5086ecf10..745efc5bdf1 100644 --- a/tests/integration/utils/dev-server.mjs +++ b/tests/integration/utils/dev-server.mjs @@ -143,8 +143,8 @@ export const startDevServer = async (options, expectFailure) => { } } -// 600 seconds -const SERVER_START_TIMEOUT = 60e4 +// 240 seconds +const SERVER_START_TIMEOUT = 24e4 export const withDevServer = async (options, testHandler, expectFailure = false) => { let server From d655ea18c580d49ef72c4da86a365674e6ac1fc1 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Fri, 17 Nov 2023 14:44:13 -0500 Subject: [PATCH 59/67] chore: try await execa --- tests/integration/utils/dev-server.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/utils/dev-server.mjs b/tests/integration/utils/dev-server.mjs index 745efc5bdf1..d62bb2b1f54 100644 --- a/tests/integration/utils/dev-server.mjs +++ b/tests/integration/utils/dev-server.mjs @@ -57,7 +57,7 @@ const startServer = async ({ baseArgs.push('--context', context) } - const ps = execa(cliPath, [...baseArgs, ...args], getExecaOptions({ cwd, env })) + const ps = await execa(cliPath, [...baseArgs, ...args], getExecaOptions({ cwd, env })) if (process.env.DEBUG_TESTS) { ps.stderr.pipe(process.stderr) From a4c7e2e906cd21a72c9f4a7c0ba25d169c4d5224 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Fri, 17 Nov 2023 15:03:56 -0500 Subject: [PATCH 60/67] feat: nope, not that --- tests/integration/utils/dev-server.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/utils/dev-server.mjs b/tests/integration/utils/dev-server.mjs index d62bb2b1f54..745efc5bdf1 100644 --- a/tests/integration/utils/dev-server.mjs +++ b/tests/integration/utils/dev-server.mjs @@ -57,7 +57,7 @@ const startServer = async ({ baseArgs.push('--context', context) } - const ps = await execa(cliPath, [...baseArgs, ...args], getExecaOptions({ cwd, env })) + const ps = execa(cliPath, [...baseArgs, ...args], getExecaOptions({ cwd, env })) if (process.env.DEBUG_TESTS) { ps.stderr.pipe(process.stderr) From 3f10923bc30b59465df7ccc7cfe68cdaa9627271 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Tue, 21 Nov 2023 17:24:47 -0500 Subject: [PATCH 61/67] chore: merge conflict stuff --- package-lock.json | 10 +++------- src/commands/deploy/deploy.ts | 4 ++-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1a120ca230..d0e7351c28c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12882,8 +12882,8 @@ } }, "node_modules/eslint-plugin-workspace": { - "resolved": "tools/lint-rules", - "link": true + "resolved": "file:tools/lint-rules", + "dev": true }, "node_modules/eslint-plugin-you-dont-need-lodash-underscore": { "version": "6.12.0", @@ -24896,10 +24896,6 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } - }, - "tools/lint-rules": { - "name": "eslint-plugin-workspace", - "dev": true } }, "dependencies": { @@ -33779,7 +33775,7 @@ } }, "eslint-plugin-workspace": { - "version": "file:tools/lint-rules" + "dev": true }, "eslint-plugin-you-dont-need-lodash-underscore": { "version": "6.12.0", diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 8a91af419a1..a4299b5ce07 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -35,8 +35,8 @@ import { getEnvelopeEnv } from '../../utils/env/index.js' import { getFunctionsManifestPath, getInternalFunctionsDir } from '../../utils/functions/index.js' import openBrowser from '../../utils/open-browser.js' import BaseCommand from '../base-command.js' -import { link } from '../link/index.js' -import { sitesCreate } from '../sites/index.js' +import { link } from '../link/link.js' +import { sitesCreate } from '../sites/sites-create.js' // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message const triggerDeploy = async ({ api, options, siteData, siteId }) => { From 56693481ab755d0babe36398a8bb6b6c34b604e2 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Tue, 21 Nov 2023 17:36:01 -0500 Subject: [PATCH 62/67] chore: package lock from main --- package-lock.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d0e7351c28c..a1a120ca230 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12882,8 +12882,8 @@ } }, "node_modules/eslint-plugin-workspace": { - "resolved": "file:tools/lint-rules", - "dev": true + "resolved": "tools/lint-rules", + "link": true }, "node_modules/eslint-plugin-you-dont-need-lodash-underscore": { "version": "6.12.0", @@ -24896,6 +24896,10 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "tools/lint-rules": { + "name": "eslint-plugin-workspace", + "dev": true } }, "dependencies": { @@ -33775,7 +33779,7 @@ } }, "eslint-plugin-workspace": { - "dev": true + "version": "file:tools/lint-rules" }, "eslint-plugin-you-dont-need-lodash-underscore": { "version": "6.12.0", From a712bf9d7cd2bfd180fb353086307f2266a05d39 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Tue, 21 Nov 2023 17:50:15 -0500 Subject: [PATCH 63/67] chore: merge conflict stuff --- src/commands/logs/functions.ts | 13 ++----------- src/commands/logs/index.ts | 13 +++++++++++-- src/commands/logs/log-levels.ts | 11 +++++++++++ 3 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 src/commands/logs/log-levels.ts diff --git a/src/commands/logs/functions.ts b/src/commands/logs/functions.ts index 6862435a287..e966114db60 100644 --- a/src/commands/logs/functions.ts +++ b/src/commands/logs/functions.ts @@ -5,17 +5,8 @@ import { chalk, log } from '../../utils/command-helpers.js' import { getWebSocket } from '../../utils/websockets/index.js' import type BaseCommand from '../base-command.js' -// Source: Source: https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced -export const LOG_LEVELS = { - TRACE: 'TRACE', - DEBUG: 'DEBUG', - INFO: 'INFO', - WARN: 'WARN', - ERROR: 'ERROR', - FATAL: 'FATAL', -} -const LOG_LEVELS_LIST = Object.values(LOG_LEVELS).map((level) => level.toLowerCase()) -const CLI_LOG_LEVEL_CHOICES_STRING = LOG_LEVELS_LIST.map((level) => ` ${level}`) +import { CLI_LOG_LEVEL_CHOICES_STRING, LOG_LEVELS, LOG_LEVELS_LIST } from './log-levels.js' + function getLog(logData: { level: string; message: string }) { let logString = '' diff --git a/src/commands/logs/index.ts b/src/commands/logs/index.ts index 44a55770b24..54d682cf341 100644 --- a/src/commands/logs/index.ts +++ b/src/commands/logs/index.ts @@ -1,7 +1,9 @@ -import { OptionValues, Argument } from 'commander' +import { Option, OptionValues, Argument } from 'commander' import BaseCommand from '../base-command.js' +import { CLI_LOG_LEVEL_CHOICES_STRING } from './log-levels.js' + export const createLogsBuildCommand = (program: BaseCommand) => { program .command('logs:deploy') @@ -17,8 +19,15 @@ export const createLogsFunctionCommand = (program: BaseCommand) => { program .command('logs:function') .alias('logs:functions') + .addOption( + new Option('-l, --level ', `Log levels to stream. Choices are:${CLI_LOG_LEVEL_CHOICES_STRING}`), + ) .addArgument(new Argument('[functionName]', 'Name of the function to stream logs for')) - .addExamples(['netlify logs:function my-function', 'netlify logs:function']) + .addExamples([ + 'netlify logs:function', + 'netlify logs:function my-function', + 'netlify logs:function my-function -l info warn', + ]) .description('(Beta) Stream netlify function logs to the console') .action(async (functionName: string | undefined, options: OptionValues, command: BaseCommand) => { const { logsFunction } = await import('./functions.js') diff --git a/src/commands/logs/log-levels.ts b/src/commands/logs/log-levels.ts new file mode 100644 index 00000000000..22110a3cede --- /dev/null +++ b/src/commands/logs/log-levels.ts @@ -0,0 +1,11 @@ +// Source: Source: https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced +export const LOG_LEVELS = { + TRACE: 'TRACE', + DEBUG: 'DEBUG', + INFO: 'INFO', + WARN: 'WARN', + ERROR: 'ERROR', + FATAL: 'FATAL', +} +export const LOG_LEVELS_LIST = Object.values(LOG_LEVELS).map((level) => level.toLowerCase()) +export const CLI_LOG_LEVEL_CHOICES_STRING = LOG_LEVELS_LIST.map((level) => ` ${level}`) From 4854f864e51330f83b544d1b08eaff7aa7bd3060 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Wed, 22 Nov 2023 09:26:48 -0500 Subject: [PATCH 64/67] test: fix test import --- tests/integration/commands/logs/functions.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration/commands/logs/functions.test.ts b/tests/integration/commands/logs/functions.test.ts index d8cc7f215f9..00b2179b7fc 100644 --- a/tests/integration/commands/logs/functions.test.ts +++ b/tests/integration/commands/logs/functions.test.ts @@ -1,7 +1,8 @@ import { Mock, afterEach, beforeEach, describe, expect, test, vi } from 'vitest' import BaseCommand from '../../../../src/commands/base-command.js' -import { LOG_LEVELS, createLogsFunctionCommand } from '../../../../src/commands/logs/functions.js' +import { LOG_LEVELS } from '../../../../src/commands/logs/functions.js' +import { createLogsFunctionCommand } from '../../../../src/commands/logs/index.js' import { log } from '../../../../src/utils/command-helpers.js' import { getWebSocket } from '../../../../src/utils/websockets/index.js' import { startMockApi } from '../../utils/mock-api-vitest.ts' From c811a491e1d9f4a7507652b74a26d4117f8ab54c Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Wed, 22 Nov 2023 12:17:37 -0500 Subject: [PATCH 65/67] test: fix wrong import --- tests/integration/commands/logs/functions.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/commands/logs/functions.test.ts b/tests/integration/commands/logs/functions.test.ts index 00b2179b7fc..e5834bd03fd 100644 --- a/tests/integration/commands/logs/functions.test.ts +++ b/tests/integration/commands/logs/functions.test.ts @@ -1,8 +1,8 @@ import { Mock, afterEach, beforeEach, describe, expect, test, vi } from 'vitest' import BaseCommand from '../../../../src/commands/base-command.js' -import { LOG_LEVELS } from '../../../../src/commands/logs/functions.js' import { createLogsFunctionCommand } from '../../../../src/commands/logs/index.js' +import { LOG_LEVELS } from '../../../../src/commands/logs/log-levels.js' import { log } from '../../../../src/utils/command-helpers.js' import { getWebSocket } from '../../../../src/utils/websockets/index.js' import { startMockApi } from '../../utils/mock-api-vitest.ts' From 33fe45c7f163f74b633cd5fd4995455f54893824 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Wed, 22 Nov 2023 14:25:01 -0500 Subject: [PATCH 66/67] chore: revert dev because dev server tests are timing out, moving to another issue --- src/commands/dev/dev-exec.ts | 19 ++++- src/commands/dev/dev.ts | 132 ++++++++++++++++++++++++++++++- src/commands/dev/index.ts | 148 +---------------------------------- 3 files changed, 150 insertions(+), 149 deletions(-) diff --git a/src/commands/dev/dev-exec.ts b/src/commands/dev/dev-exec.ts index 1804d7a263a..e526892f9b0 100644 --- a/src/commands/dev/dev-exec.ts +++ b/src/commands/dev/dev-exec.ts @@ -2,7 +2,7 @@ import { OptionValues } from 'commander' import execa from 'execa' import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.js' -import { getEnvelopeEnv } from '../../utils/env/index.js' +import { getEnvelopeEnv, normalizeContext } from '../../utils/env/index.js' import BaseCommand from '../base-command.js' export const devExec = async (cmd: string, options: OptionValues, command: BaseCommand) => { @@ -20,3 +20,20 @@ export const devExec = async (cmd: string, options: OptionValues, command: BaseC stdio: 'inherit', }) } + +export const createDevExecCommand = (program: BaseCommand) => + program + .command('dev:exec') + .argument('<...cmd>', `the command that should be executed`) + .option( + '--context ', + 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + 'dev', + ) + .description( + 'Exec command\nRuns a command within the netlify dev environment, e.g. with env variables from any installed addons', + ) + .allowExcessArguments(true) + .addExamples(['netlify dev:exec npm run bootstrap']) + .action(devExec) diff --git a/src/commands/dev/dev.ts b/src/commands/dev/dev.ts index d9396c5a7fc..67b94f075b8 100644 --- a/src/commands/dev/dev.ts +++ b/src/commands/dev/dev.ts @@ -17,15 +17,18 @@ import { } from '../../utils/command-helpers.js' import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.js' import { getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.js' -import { getEnvelopeEnv } from '../../utils/env/index.js' +import { getEnvelopeEnv, normalizeContext } from '../../utils/env/index.js' import { ensureNetlifyIgnore } from '../../utils/gitignore.js' import { getLiveTunnelSlug, startLiveTunnel } from '../../utils/live-tunnel.js' import openBrowser from '../../utils/open-browser.js' import { generateInspectSettings, startProxyServer } from '../../utils/proxy-server.js' import { getProxyUrl } from '../../utils/proxy.js' import { runDevTimeline } from '../../utils/run-build.js' +import { getGeoCountryArgParser } from '../../utils/validation.js' import BaseCommand from '../base-command.js' +import { createDevExecCommand } from './dev-exec.js' + /** * * @param {object} config @@ -65,6 +68,22 @@ const handleLiveTunnel = async ({ api, options, settings, site, state }) => { } } +const validateShortFlagArgs = (args: string) => { + if (args.startsWith('=')) { + throw new Error( + `Short flag options like -e or -E don't support the '=' sign + ${chalk.red(BANG)} Supported formats: + netlify dev -e + netlify dev -e 127.0.0.1:9229 + netlify dev -e127.0.0.1:9229 + netlify dev -E + netlify dev -E 127.0.0.1:9229 + netlify dev -E127.0.0.1:9229`, + ) + } + return args +} + export const dev = async (options: OptionValues, command: BaseCommand) => { log(`${NETLIFYDEV}`) const { api, cachedConfig, config, repositoryRoot, site, siteInfo, state } = command.netlify @@ -209,3 +228,114 @@ export const dev = async (options: OptionValues, command: BaseCommand) => { printBanner({ url }) } + + +export const createDevCommand = (program: BaseCommand) => { + createDevExecCommand(program) + + return ( + program + .command('dev') + .alias('develop') + .description( + `Local dev server\nThe dev command will run a local dev server with Netlify's proxy and redirect rules`, + ) + .option('-c ,--command ', 'command to run') + .option( + '--context ', + 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', + normalizeContext, + ) + // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. + .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) + .addOption( + new Option('--targetPort ', 'Old, prefer --target-port. Port of target app server') + .argParser((value) => Number.parseInt(value)) + .hideHelp(true), + ) + .addOption(new Option('--no-open', 'disables the automatic opening of a browser window')) + // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. + .option('--target-port ', 'port of target app server', (value) => Number.parseInt(value)) + .option('--framework ', 'framework to use. Defaults to #auto which automatically detects a framework') + .option('-d ,--dir ', 'dir with static files') + .option('-f ,--functions ', 'specify a functions folder to serve') + .option('-o ,--offline', 'disables any features that require network access') + .option( + '-l, --live [subdomain]', + 'start a public live session; optionally, supply a subdomain to generate a custom URL', + false, + ) + .addOption( + new Option('--functionsPort ', 'Old, prefer --functions-port. Port of functions server') + .argParser((value) => Number.parseInt(value)) + .hideHelp(true), + ) + // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. + .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) + .addOption( + new Option( + '--geo ', + 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location', + ) + .choices(['cache', 'mock', 'update']) + .default('cache'), + ) + .addOption( + new Option( + '--country ', + 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)', + ).argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR')), + ) + .addOption( + new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') + .argParser((value) => Number.parseInt(value)) + .hideHelp(), + ) + .addOption( + new Option( + '-e, --edgeInspect [address]', + 'Old, prefer --edge-inspect. Enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', + ) + .conflicts('edgeInspectBrk') + .argParser(validateShortFlagArgs) + .hideHelp(true), + ) + .addOption( + new Option( + '-e, --edge-inspect [address]', + 'enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', + ) + .conflicts('edgeInspectBrk') + .argParser(validateShortFlagArgs), + ) + .addOption( + new Option( + '-E, --edgeInspectBrk [address]', + 'Old, prefer --edge-inspect-brk. Enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', + ) + .conflicts('edgeInspect') + .hideHelp(true) + .argParser(validateShortFlagArgs), + ) + .addOption( + new Option( + '-E, --edge-inspect-brk [address]', + 'enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', + ) + .conflicts('edgeInspect') + .argParser(validateShortFlagArgs), + ) + .addExamples([ + 'netlify dev', + 'netlify dev -d public', + 'netlify dev -c "hugo server -w" --target-port 1313', + 'netlify dev --context production', + 'netlify dev --edge-inspect', + 'netlify dev --edge-inspect=127.0.0.1:9229', + 'netlify dev --edge-inspect-brk', + 'netlify dev --edge-inspect-brk=127.0.0.1:9229', + 'BROWSER=none netlify dev # disable browser auto opening', + ]) + .action(dev) + ) +} diff --git a/src/commands/dev/index.ts b/src/commands/dev/index.ts index 5326120ecc5..f70de52f5ef 100644 --- a/src/commands/dev/index.ts +++ b/src/commands/dev/index.ts @@ -1,147 +1 @@ -import { Option, OptionValues } from 'commander' - -import { BANG, chalk } from '../../utils/command-helpers.js' -import { normalizeContext } from '../../utils/env/index.js' -import { getGeoCountryArgParser } from '../../utils/validation.js' -import BaseCommand from '../base-command.js' - -const validateShortFlagArgs = (args: string) => { - if (args.startsWith('=')) { - throw new Error( - `Short flag options like -e or -E don't support the '=' sign - ${chalk.red(BANG)} Supported formats: - netlify dev -e - netlify dev -e 127.0.0.1:9229 - netlify dev -e127.0.0.1:9229 - netlify dev -E - netlify dev -E 127.0.0.1:9229 - netlify dev -E127.0.0.1:9229`, - ) - } - return args -} - -export const createDevCommand = (program: BaseCommand) => { - program - .command('dev:exec') - .argument('<...cmd>', `the command that should be executed`) - .option( - '--context ', - 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - 'dev', - ) - .description( - 'Exec command\nRuns a command within the netlify dev environment, e.g. with env variables from any installed addons', - ) - .allowExcessArguments(true) - .addExamples(['netlify dev:exec npm run bootstrap']) - .action(async (cmd: string, options: OptionValues, command: BaseCommand) => { - const { devExec } = await import('./dev-exec.js') - await devExec(cmd, options, command) - }) - - return program - .command('dev') - .alias('develop') - .description( - `Local dev server\nThe dev command will run a local dev server with Netlify's proxy and redirect rules`, - ) - .option('-c ,--command ', 'command to run') - .option( - '--context ', - 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', - normalizeContext, - ) - .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) - .addOption( - new Option('--targetPort ', 'Old, prefer --target-port. Port of target app server') - .argParser((value) => Number.parseInt(value)) - .hideHelp(true), - ) - .addOption(new Option('--no-open', 'disables the automatic opening of a browser window')) - .option('--target-port ', 'port of target app server', (value) => Number.parseInt(value)) - .option('--framework ', 'framework to use. Defaults to #auto which automatically detects a framework') - .option('-d ,--dir ', 'dir with static files') - .option('-f ,--functions ', 'specify a functions folder to serve') - .option('-o ,--offline', 'disables any features that require network access') - .option( - '-l, --live [subdomain]', - 'start a public live session; optionally, supply a subdomain to generate a custom URL', - false, - ) - .addOption( - new Option('--functionsPort ', 'Old, prefer --functions-port. Port of functions server') - .argParser((value) => Number.parseInt(value)) - .hideHelp(true), - ) - .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) - .addOption( - new Option( - '--geo ', - 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location', - ) - .choices(['cache', 'mock', 'update']) - .default('cache'), - ) - .addOption( - new Option( - '--country ', - 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)', - ).argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR')), - ) - .addOption( - new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') - .argParser((value) => Number.parseInt(value)) - .hideHelp(), - ) - .addOption( - new Option( - '-e, --edgeInspect [address]', - 'Old, prefer --edge-inspect. Enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', - ) - .conflicts('edgeInspectBrk') - .argParser(validateShortFlagArgs) - .hideHelp(true), - ) - .addOption( - new Option( - '-e, --edge-inspect [address]', - 'enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format', - ) - .conflicts('edgeInspectBrk') - .argParser(validateShortFlagArgs), - ) - .addOption( - new Option( - '-E, --edgeInspectBrk [address]', - 'Old, prefer --edge-inspect-brk. Enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', - ) - .conflicts('edgeInspect') - .hideHelp(true) - .argParser(validateShortFlagArgs), - ) - .addOption( - new Option( - '-E, --edge-inspect-brk [address]', - 'enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format', - ) - .conflicts('edgeInspect') - .argParser(validateShortFlagArgs), - ) - .addExamples([ - 'netlify dev', - 'netlify dev -d public', - 'netlify dev -c "hugo server -w" --target-port 1313', - 'netlify dev --context production', - 'netlify dev --edge-inspect', - 'netlify dev --edge-inspect=127.0.0.1:9229', - 'netlify dev --edge-inspect-brk', - 'netlify dev --edge-inspect-brk=127.0.0.1:9229', - 'BROWSER=none netlify dev # disable browser auto opening', - ]) - .action(async (options: OptionValues, command: BaseCommand) => { - const { dev } = await import('./dev.js') - await dev(options, command) - }) -} +export { createDevCommand } from './dev.js' From 8a11d17deac687b1fa3eadda7f3f0f43f4897b27 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Wed, 22 Nov 2023 14:28:25 -0500 Subject: [PATCH 67/67] chore: missing things --- src/commands/dev/dev.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/commands/dev/dev.ts b/src/commands/dev/dev.ts index 67b94f075b8..016e4a7f8a9 100644 --- a/src/commands/dev/dev.ts +++ b/src/commands/dev/dev.ts @@ -1,12 +1,13 @@ import process from 'process' -import { OptionValues } from 'commander' +import { OptionValues, Option } from 'commander' import { getBlobsContext } from '../../lib/blobs/blobs.js' import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js' import { startFunctionsServer } from '../../lib/functions/server.js' import { printBanner } from '../../utils/banner.js' import { + BANG, chalk, log, NETLIFYDEV, @@ -246,7 +247,6 @@ export const createDevCommand = (program: BaseCommand) => { 'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")', normalizeContext, ) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) .addOption( new Option('--targetPort ', 'Old, prefer --target-port. Port of target app server') @@ -254,7 +254,6 @@ export const createDevCommand = (program: BaseCommand) => { .hideHelp(true), ) .addOption(new Option('--no-open', 'disables the automatic opening of a browser window')) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. .option('--target-port ', 'port of target app server', (value) => Number.parseInt(value)) .option('--framework ', 'framework to use. Defaults to #auto which automatically detects a framework') .option('-d ,--dir ', 'dir with static files') @@ -270,7 +269,6 @@ export const createDevCommand = (program: BaseCommand) => { .argParser((value) => Number.parseInt(value)) .hideHelp(true), ) - // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) .addOption( new Option(