netlify-cli 17.10.0 → 17.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -142,7 +142,7 @@ export default async function handler({ config, directory, errorExit, func, meta
142
142
  }
143
143
  else {
144
144
  // We must use esbuild for certain file extensions.
145
- const mustTranspile = ['.js', '.ts', '.mts', '.cts'].includes(path.extname(func.mainFile));
145
+ const mustTranspile = ['.mjs', '.ts', '.mts', '.cts'].includes(path.extname(func.mainFile));
146
146
  const mustUseEsbuild = hasTypeModule || mustTranspile;
147
147
  if (mustUseEsbuild && !functionsConfig['*'].nodeBundler) {
148
148
  functionsConfig['*'].nodeBundler = 'esbuild';
@@ -3,7 +3,6 @@ import { dirname, extname, join, resolve } from 'path';
3
3
  import { platform } from 'process';
4
4
  import { findUp } from 'find-up';
5
5
  import toml from 'toml';
6
- // @ts-expect-error TS(7034) FIXME: Variable 'execa' implicitly has type 'any' in some... Remove this comment to see the full error message
7
6
  import execa from '../../../../utils/execa.js';
8
7
  import { SERVE_FUNCTIONS_FOLDER } from '../../../../utils/functions/functions.js';
9
8
  import { getPathInProject } from '../../../settings.js';
@@ -18,7 +17,6 @@ const build = async ({ func }) => {
18
17
  const crateName = await getCrateName(functionDirectory);
19
18
  const binaryName = `${crateName}${isWindows ? '.exe' : ''}`;
20
19
  const binaryPath = join(targetDirectory, 'debug', binaryName);
21
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
22
20
  await execa('cargo', ['build', '--target-dir', targetDirectory], {
23
21
  cwd: functionDirectory,
24
22
  });
@@ -25,20 +25,31 @@ const buildClientContext = function (headers) {
25
25
  const parts = headers.authorization.split(' ');
26
26
  if (parts.length !== 2 || parts[0] !== 'Bearer')
27
27
  return;
28
+ const identity = {
29
+ url: 'https://netlify-dev-locally-emulated-identity.netlify.com/.netlify/identity',
30
+ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGRldiIsInRlc3REYXRhIjoiTkVUTElGWV9ERVZfTE9DQUxMWV9FTVVMQVRFRF9JREVOVElUWSJ9.2eSDqUOZAOBsx39FHFePjYj12k0LrxldvGnlvDu3GMI',
31
+ // you can decode this with https://jwt.io/
32
+ // just says
33
+ // {
34
+ // "source": "netlify dev",
35
+ // "testData": "NETLIFY_DEV_LOCALLY_EMULATED_IDENTITY"
36
+ // }
37
+ };
38
+ // This data is available on both the context root and under custom.netlify for retro-compatibility.
39
+ // In the future it will only be available in custom.netlify.
40
+ // @ts-expect-error
41
+ const user = jwtDecode(parts[1]);
42
+ const netlifyContext = JSON.stringify({
43
+ identity: identity,
44
+ user: user,
45
+ });
28
46
  try {
29
47
  return {
30
- identity: {
31
- url: 'https://netlify-dev-locally-emulated-identity.netlify.com/.netlify/identity',
32
- token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGRldiIsInRlc3REYXRhIjoiTkVUTElGWV9ERVZfTE9DQUxMWV9FTVVMQVRFRF9JREVOVElUWSJ9.2eSDqUOZAOBsx39FHFePjYj12k0LrxldvGnlvDu3GMI',
33
- // you can decode this with https://jwt.io/
34
- // just says
35
- // {
36
- // "source": "netlify dev",
37
- // "testData": "NETLIFY_DEV_LOCALLY_EMULATED_IDENTITY"
38
- // }
48
+ identity: identity,
49
+ user: user,
50
+ custom: {
51
+ netlify: Buffer.from(netlifyContext).toString('base64'),
39
52
  },
40
- // @ts-expect-error
41
- user: jwtDecode(parts[1]),
42
53
  };
43
54
  }
44
55
  catch {
@@ -1,8 +1,7 @@
1
1
  import boxen from 'boxen';
2
2
  import { chalk, log, NETLIFYDEVLOG } from './command-helpers.js';
3
- // @ts-expect-error TS(7031) FIXME: Binding element 'url' implicitly has an 'any' type... Remove this comment to see the full error message
4
- export const printBanner = ({ url }) => {
5
- const banner = chalk.bold(`${NETLIFYDEVLOG} Server now ready on ${url}`);
3
+ export const printBanner = (options) => {
4
+ const banner = chalk.bold(`${NETLIFYDEVLOG} Server now ready on ${options.url}`);
6
5
  log(boxen(banner, {
7
6
  padding: 1,
8
7
  margin: 1,
@@ -3,28 +3,19 @@ import inquirer from 'inquirer';
3
3
  import { chalk, log } from './command-helpers.js';
4
4
  /**
5
5
  * Filters the inquirer settings based on the input
6
- * @param {ReturnType<typeof formatSettingsArrForInquirer>} scriptInquirerOptions
7
- * @param {string} input
8
6
  */
9
- // @ts-expect-error TS(7006) FIXME: Parameter 'scriptInquirerOptions' implicitly has a... Remove this comment to see the full error message
10
7
  const filterSettings = function (scriptInquirerOptions, input) {
11
- // @ts-expect-error TS(7006) FIXME: Parameter 'scriptInquirerOption' implicitly has an... Remove this comment to see the full error message
12
8
  const filterOptions = scriptInquirerOptions.map((scriptInquirerOption) => scriptInquirerOption.name);
13
9
  // TODO: remove once https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1394 is fixed
14
10
  // eslint-disable-next-line unicorn/no-array-method-this-argument
15
11
  const filteredSettings = fuzzy.filter(input, filterOptions);
16
12
  const filteredSettingNames = new Set(filteredSettings.map((filteredSetting) => (input ? filteredSetting.string : filteredSetting)));
17
- // @ts-expect-error TS(7006) FIXME: Parameter 't' implicitly has an 'any' type.
18
13
  return scriptInquirerOptions.filter((t) => filteredSettingNames.has(t.name));
19
14
  };
20
- /** @typedef {import('@netlify/build-info').Settings} Settings */
21
15
  /**
22
- * @param {Settings[]} settings
23
- * @param {'dev' | 'build'} type The type of command (dev or build)
16
+ * Formats the settings to present it as an array for the inquirer input so that it can choose one
24
17
  */
25
- // @ts-expect-error TS(7006) FIXME: Parameter 'settings' implicitly has an 'any' type.
26
18
  const formatSettingsArrForInquirer = function (settings, type = 'dev') {
27
- // @ts-expect-error TS(7006) FIXME: Parameter 'setting' implicitly has an 'any' type.
28
19
  return settings.map((setting) => {
29
20
  const cmd = type === 'dev' ? setting.devCommand : setting.buildCommand;
30
21
  return {
@@ -35,13 +26,26 @@ const formatSettingsArrForInquirer = function (settings, type = 'dev') {
35
26
  });
36
27
  };
37
28
  /**
38
- * Uses @netlify/build-info to detect the dev settings and port based on the framework
29
+ * Detects and filters the build setting for a project and a command
30
+ */
31
+ export async function detectBuildSettings(command) {
32
+ const { project, workspacePackage } = command;
33
+ const buildSettings = await project.getBuildSettings(project.workspace ? workspacePackage : '');
34
+ return buildSettings
35
+ .filter((setting) => {
36
+ if (project.workspace && project.relativeBaseDirectory && setting.packagePath) {
37
+ return project.relativeBaseDirectory.startsWith(setting.packagePath);
38
+ }
39
+ return true;
40
+ })
41
+ .filter((setting) => setting.devCommand);
42
+ }
43
+ /**
44
+ * Uses `@netlify/build-info` to detect the dev settings and port based on the framework
39
45
  * and the build system that is used.
40
- * @param {import('../commands/base-command.js').default} command
41
- * @param {'dev' | 'build'} type The type of command (dev or build)
42
- * @returns {Promise<Settings | undefined>}
46
+ * @param command The base command
47
+ * @param type The type of command (dev or build)
43
48
  */
44
- // @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type.
45
49
  export const detectFrameworkSettings = async (command, type = 'dev') => {
46
50
  const { relConfigFilePath } = command.netlify;
47
51
  const settings = await detectBuildSettings(command);
@@ -49,16 +53,14 @@ export const detectFrameworkSettings = async (command, type = 'dev') => {
49
53
  return settings[0];
50
54
  }
51
55
  if (settings.length > 1) {
52
- /** multiple matching detectors, make the user choose */
56
+ // multiple matching detectors, make the user choose
53
57
  const scriptInquirerOptions = formatSettingsArrForInquirer(settings, type);
54
- /** @type {{chosenSettings: Settings}} */
55
58
  const { chosenSettings } = await inquirer.prompt({
56
59
  name: 'chosenSettings',
57
60
  message: `Multiple possible ${type} commands found`,
58
- // @ts-expect-error TS(2769) FIXME: No overload matches this call.
61
+ // @ts-expect-error is not known by the types as it uses the autocomplete plugin
59
62
  type: 'autocomplete',
60
- // @ts-expect-error TS(7006) FIXME: Parameter '_' implicitly has an 'any' type.
61
- source(/** @type {string} */ _, input = '') {
63
+ source(_, input = '') {
62
64
  if (!input)
63
65
  return scriptInquirerOptions;
64
66
  // only show filtered results
@@ -78,22 +80,3 @@ command = "${chosenSettings.devCommand}"
78
80
  return chosenSettings;
79
81
  }
80
82
  };
81
- /**
82
- * Detects and filters the build setting for a project and a command
83
- * @param {import('../commands/base-command.js').default} command
84
- */
85
- // @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type.
86
- export const detectBuildSettings = async (command) => {
87
- const { project, workspacePackage } = command;
88
- const buildSettings = await project.getBuildSettings(project.workspace ? workspacePackage : '');
89
- return (buildSettings
90
- // @ts-expect-error TS(7006) FIXME: Parameter 'setting' implicitly has an 'any' type.
91
- .filter((setting) => {
92
- if (project.workspace && project.relativeBaseDirectory && setting.packagePath) {
93
- return project.relativeBaseDirectory.startsWith(setting.packagePath);
94
- }
95
- return true;
96
- })
97
- // @ts-expect-error TS(7006) FIXME: Parameter 'setting' implicitly has an 'any' type.
98
- .filter((setting) => setting.devCommand));
99
- };
@@ -158,22 +158,14 @@ export const warn = (message = '') => {
158
158
  const bang = chalk.yellow(BANG);
159
159
  log(` ${bang} Warning: ${message}`);
160
160
  };
161
- /**
162
- * throws an error or log it
163
- * @param {unknown} message
164
- * @param {object} [options]
165
- * @param {boolean} [options.exit]
166
- */
161
+ /** Throws an error or logs it */
167
162
  export const error = (message = '', options = {}) => {
168
- const err =
169
- // @ts-expect-error TS(2358) FIXME: The left-hand side of an 'instanceof' expression m... Remove this comment to see the full error message
170
- message instanceof Error
163
+ const err = message instanceof Error
171
164
  ? message
172
165
  : // eslint-disable-next-line unicorn/no-nested-ternary
173
166
  typeof message === 'string'
174
167
  ? new Error(message)
175
- : /** @type {Error} */ { message, stack: undefined, name: 'Error' };
176
- // @ts-expect-error TS(2339) FIXME: Property 'exit' does not exist on type '{}'.
168
+ : { message, stack: undefined, name: 'Error' };
177
169
  if (options.exit === false) {
178
170
  const bang = chalk.red(BANG);
179
171
  if (process.env.DEBUG) {
@@ -139,11 +139,8 @@ const handleStaticServer = async ({ devConfig, flags, workingDir }) => {
139
139
  };
140
140
  /**
141
141
  * Retrieves the settings from a framework
142
- * @param {import('@netlify/build-info').Settings} [settings]
143
- * @returns {import('./types.js').BaseServerSettings | undefined}
144
142
  */
145
- // @ts-expect-error TS(7006) FIXME: Parameter 'settings' implicitly has an 'any' type.
146
- const getSettingsFromDetectedSettings = (settings) => {
143
+ const getSettingsFromDetectedSettings = (command, settings) => {
147
144
  if (!settings) {
148
145
  return;
149
146
  }
@@ -155,7 +152,8 @@ const getSettingsFromDetectedSettings = (settings) => {
155
152
  framework: settings.framework.name,
156
153
  env: settings.env,
157
154
  pollingStrategies: settings.pollingStrategies,
158
- plugins: getPluginsToAutoInstall(settings.plugins_from_config_file, settings.plugins_recommended),
155
+ plugins: getPluginsToAutoInstall(command, settings.plugins_from_config_file, settings.plugins_recommended),
156
+ clearPublishDirectory: settings.clearPublishDirectory,
159
157
  };
160
158
  };
161
159
  /**
@@ -190,55 +188,35 @@ const handleCustomFramework = ({ devConfig, workingDir }) => {
190
188
  * @param {string} config.workingDir
191
189
  * @param {Partial<import('./types.js').BaseServerSettings>=} config.frameworkSettings
192
190
  */
193
- // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
194
- const mergeSettings = async ({ devConfig, frameworkSettings = {}, workingDir }) => {
195
- // @ts-expect-error TS(2339) FIXME: Property 'command' does not exist on type '{}'.
191
+ const mergeSettings = async ({ devConfig, frameworkSettings = {}, workingDir, }) => {
196
192
  const command = devConfig.command || frameworkSettings.command;
197
- // @ts-expect-error TS(2339) FIXME: Property 'frameworkPort' does not exist on type '{... Remove this comment to see the full error message
198
193
  const frameworkPort = devConfig.targetPort || frameworkSettings.frameworkPort;
199
- // if the framework doesn't start a server, we use a static one
200
194
  const useStaticServer = !(command && frameworkPort);
201
195
  return {
202
- // @ts-expect-error TS(2339) FIXME: Property 'baseDirectory' does not exist on type '{... Remove this comment to see the full error message
203
196
  baseDirectory: devConfig.base || frameworkSettings.baseDirectory,
204
197
  command,
205
198
  frameworkPort: useStaticServer ? await getStaticServerPort({ devConfig }) : frameworkPort,
206
- // @ts-expect-error TS(2339) FIXME: Property 'dist' does not exist on type '{}'.
207
199
  dist: devConfig.publish || frameworkSettings.dist || getDefaultDist(workingDir),
208
- // @ts-expect-error TS(2339) FIXME: Property 'framework' does not exist on type '{}'.
209
200
  framework: frameworkSettings.framework,
210
- // @ts-expect-error TS(2339) FIXME: Property 'env' does not exist on type '{}'.
211
201
  env: frameworkSettings.env,
212
- // @ts-expect-error TS(2339) FIXME: Property 'pollingStrategies' does not exist on typ... Remove this comment to see the full error message
213
202
  pollingStrategies: frameworkSettings.pollingStrategies || [],
214
203
  useStaticServer,
204
+ clearPublishDirectory: frameworkSettings.clearPublishDirectory,
215
205
  };
216
206
  };
217
207
  /**
218
208
  * Handles a forced framework and retrieves the settings for it
219
- * @param {object} config
220
- * @param {import('../commands/dev/types.js').DevConfig} config.devConfig
221
- * @param {import('@netlify/build-info').Project} config.project
222
- * @param {string} config.workingDir
223
- * @param {string=} config.workspacePackage
224
- * @returns {Promise<import('./types.js').BaseServerSettings>}
225
209
  */
226
- // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
227
- const handleForcedFramework = async ({ devConfig, project, workingDir, workspacePackage }) => {
210
+ const handleForcedFramework = async (options) => {
228
211
  // this throws if `devConfig.framework` is not a supported framework
229
- const framework = await getFramework(devConfig.framework, project);
230
- const settings = await getSettings(framework, project, workspacePackage || '');
231
- const frameworkSettings = getSettingsFromDetectedSettings(settings);
232
- return mergeSettings({ devConfig, workingDir, frameworkSettings });
212
+ const framework = await getFramework(options.devConfig.framework, options.project);
213
+ const settings = await getSettings(framework, options.project, options.workspacePackage || '');
214
+ const frameworkSettings = getSettingsFromDetectedSettings(options.command, settings);
215
+ return mergeSettings({ devConfig: options.devConfig, workingDir: options.workingDir, frameworkSettings });
233
216
  };
234
217
  /**
235
218
  * Get the server settings based on the flags and the devConfig
236
- * @param {import('../commands/dev/types.js').DevConfig} devConfig
237
- * @param {import('commander').OptionValues} flags
238
- * @param {import('../commands/base-command.js').default} command
239
- * @returns {Promise<import('./types.js').ServerSettings>}
240
219
  */
241
- // @ts-expect-error TS(7006) FIXME: Parameter 'devConfig' implicitly has an 'any' type... Remove this comment to see the full error message
242
220
  const detectServerSettings = async (devConfig, flags, command) => {
243
221
  validateProperty(devConfig, 'framework', 'string');
244
222
  /** @type {Partial<import('./types.js').BaseServerSettings>} */
@@ -251,7 +229,7 @@ const detectServerSettings = async (devConfig, flags, command) => {
251
229
  // this is the default CLI behavior
252
230
  const runDetection = !hasCommandAndTargetPort(devConfig);
253
231
  const frameworkSettings = runDetection
254
- ? getSettingsFromDetectedSettings(await detectFrameworkSettings(command, 'dev'))
232
+ ? getSettingsFromDetectedSettings(command, await detectFrameworkSettings(command, 'dev'))
255
233
  : undefined;
256
234
  if (frameworkSettings === undefined && runDetection) {
257
235
  log(`${NETLIFYDEVWARN} No app server detected. Using simple static server`);
@@ -273,6 +251,7 @@ const detectServerSettings = async (devConfig, flags, command) => {
273
251
  validateFrameworkConfig({ devConfig });
274
252
  // this is when the user explicitly configures a framework, e.g. `framework = "gatsby"`
275
253
  settings = await handleForcedFramework({
254
+ command,
276
255
  devConfig,
277
256
  project: command.project,
278
257
  workingDir: command.workingDir,
@@ -2,10 +2,7 @@ import { env } from 'process';
2
2
  import execaLib from 'execa';
3
3
  // This is a thin layer on top of `execa` that allows consumers to provide an
4
4
  // alternative path to the module location, making it easier to mock its logic
5
- // in tests (see `tests/utils/mock-execa.js`).
6
- /**
7
- * @type {import('execa')}
8
- */
5
+ // in tests (see `tests/utils/moc
9
6
  // eslint-disable-next-line import/no-mutable-exports
10
7
  let execa;
11
8
  if (env.NETLIFY_CLI_EXECA_PATH) {
@@ -7,14 +7,8 @@
7
7
  * Instead, we return that the feature flag is enabled if it isn't
8
8
  * specifically set to false in the response
9
9
  * @param {*} siteInfo
10
- * @param {string} flagName
11
10
  *
12
11
  * @returns {boolean}
13
12
  */
14
13
  // @ts-expect-error TS(7006) FIXME: Parameter 'flagName' implicitly has an 'any' type.
15
- export const isFeatureFlagEnabled = (flagName, siteInfo) => {
16
- if (siteInfo.feature_flags && siteInfo.feature_flags[flagName] !== false) {
17
- return true;
18
- }
19
- return false;
20
- };
14
+ export const isFeatureFlagEnabled = (flagName, siteInfo) => Boolean(siteInfo.feature_flags && siteInfo.feature_flags[flagName] !== false);
@@ -1,3 +1,4 @@
1
+ import { rm } from 'node:fs/promises';
1
2
  import waitPort from 'wait-port';
2
3
  import { startSpinner, stopSpinner } from '../lib/spinner.js';
3
4
  import { error, exit, log, NETLIFYDEVERR, NETLIFYDEVLOG } from './command-helpers.js';
@@ -5,19 +6,10 @@ import { runCommand } from './shell.js';
5
6
  import { startStaticServer } from './static-server.js';
6
7
  // 10 minutes
7
8
  const FRAMEWORK_PORT_TIMEOUT = 6e5;
8
- /**
9
- * @typedef StartReturnObject
10
- * @property {4 | 6 | undefined=} ipVersion The version the open port was found on
11
- */
12
9
  /**
13
10
  * Start a static server if the `useStaticServer` is provided or a framework specific server
14
- * @param {object} config
15
- * @param {import('./types.js').ServerSettings} config.settings
16
- * @param {string} config.cwd
17
- * @returns {Promise<StartReturnObject>}
18
11
  */
19
- // @ts-expect-error TS(7031) FIXME: Binding element 'cwd' implicitly has an 'any' type... Remove this comment to see the full error message
20
- export const startFrameworkServer = async function ({ cwd, settings }) {
12
+ export const startFrameworkServer = async function ({ cwd, settings, }) {
21
13
  if (settings.useStaticServer) {
22
14
  if (settings.command) {
23
15
  runCommand(settings.command, { env: settings.env, cwd });
@@ -29,10 +21,14 @@ export const startFrameworkServer = async function ({ cwd, settings }) {
29
21
  const spinner = startSpinner({
30
22
  text: `Waiting for framework port ${settings.frameworkPort}. This can be configured using the 'targetPort' property in the netlify.toml`,
31
23
  });
24
+ if (settings.clearPublishDirectory && settings.dist) {
25
+ await rm(settings.dist, { recursive: true, force: true });
26
+ }
32
27
  runCommand(settings.command, { env: settings.env, spinner, cwd });
33
28
  let port;
34
29
  try {
35
30
  port = await waitPort({
31
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
36
32
  port: settings.frameworkPort,
37
33
  host: 'localhost',
38
34
  output: 'silent',
@@ -7,35 +7,32 @@ import { normalizeBackslash } from '../../lib/path.js';
7
7
  import { detectBuildSettings } from '../build-info.js';
8
8
  import { chalk, error as failAndExit, log, warn } from '../command-helpers.js';
9
9
  import { getRecommendPlugins, getUIPlugins } from './plugins.js';
10
- // these plugins represent runtimes that are
11
- // expected to be "automatically" installed. Even though
12
- // they can be installed on package/toml, we always
13
- // want them installed in the site settings. When installed
14
- // there our build will automatically install the latest without
15
- // user management of the versioning.
16
- const pluginsToAlwaysInstall = new Set(['@netlify/plugin-nextjs']);
10
+ const formatTitle = (title) => chalk.cyan(title);
17
11
  /**
18
12
  * Retrieve a list of plugins to auto install
19
- * @param {string[]=} pluginsInstalled
20
- * @param {string[]=} pluginsRecommended
13
+ * @param pluginsToAlwaysInstall these plugins represent runtimes that are
14
+ * expected to be "automatically" installed. Even though
15
+ * they can be installed on package/toml, we always
16
+ * want them installed in the site settings. When installed
17
+ * there our build will automatically install the latest without
18
+ * user management of the versioning.
19
+ * @param pluginsInstalled
20
+ * @param pluginsRecommended
21
21
  * @returns
22
22
  */
23
- export const getPluginsToAutoInstall = (pluginsInstalled = [], pluginsRecommended = []) => pluginsRecommended.reduce((acc, plugin) => pluginsInstalled.includes(plugin) && !pluginsToAlwaysInstall.has(plugin) ? acc : [...acc, plugin],
24
- /** @type {string[]} */ []);
25
- /**
26
- *
27
- * @param {Partial<import('@netlify/build-info').Settings>} settings
28
- * @param {*} config
29
- * @param {import('../../commands/base-command.js').default} command
30
- */
31
- // @ts-expect-error TS(7006) FIXME: Parameter 'settings' implicitly has an 'any' type.
23
+ export const getPluginsToAutoInstall = (command, pluginsInstalled = [], pluginsRecommended = []) => {
24
+ const nextRuntime = '@netlify/plugin-nextjs';
25
+ const pluginsToAlwaysInstall = new Set([nextRuntime]);
26
+ return pluginsRecommended.reduce((acc, plugin) => pluginsInstalled.includes(plugin) && !pluginsToAlwaysInstall.has(plugin) ? acc : [...acc, plugin], []);
27
+ };
32
28
  const normalizeSettings = (settings, config, command) => {
33
- const plugins = getPluginsToAutoInstall(settings.plugins_from_config_file, settings.plugins_recommended);
29
+ const plugins = getPluginsToAutoInstall(command, settings.plugins_from_config_file, settings.plugins_recommended);
34
30
  const recommendedPlugins = getRecommendPlugins(plugins, config);
35
31
  return {
36
32
  defaultBaseDir: settings.baseDirectory ?? command.project.relativeBaseDirectory ?? '',
37
33
  defaultBuildCmd: config.build.command || settings.buildCommand,
38
34
  defaultBuildDir: settings.dist,
35
+ // @ts-expect-error types need to be fixed on @netlify/build
39
36
  defaultFunctionsDir: config.build.functions || 'netlify/functions',
40
37
  recommendedPlugins,
41
38
  };
@@ -75,21 +72,14 @@ const getPromptInputs = ({ defaultBaseDir, defaultBuildCmd, defaultBuildDir }) =
75
72
  ].filter(Boolean);
76
73
  return inputs.filter(Boolean);
77
74
  };
78
- /**
79
- * @param {object} param0
80
- * @param {*} param0.config
81
- * @param {import('../../commands/base-command.js').default} param0.command
82
- */
83
- // @ts-expect-error TS(7031) FIXME: Binding element 'command' implicitly has an 'any' ... Remove this comment to see the full error message
84
75
  export const getBuildSettings = async ({ command, config }) => {
85
76
  const settings = await detectBuildSettings(command);
86
77
  // TODO: add prompt for asking to choose the build command
87
- /** @type {Partial<import('@netlify/build-info').Settings>} */
88
78
  // eslint-disable-next-line unicorn/explicit-length-check
89
79
  const setting = settings.length > 0 ? settings[0] : {};
90
80
  const { defaultBaseDir, defaultBuildCmd, defaultBuildDir, defaultFunctionsDir, recommendedPlugins } = await normalizeSettings(setting, config, command);
91
81
  if (recommendedPlugins.length !== 0 && setting.framework?.name) {
92
- log(`Configuring ${formatTitle(setting.framework?.name)} runtime...`);
82
+ log(`Configuring ${formatTitle(setting.framework.name)} runtime...`);
93
83
  log();
94
84
  }
95
85
  const { baseDir, buildCmd, buildDir } = await inquirer.prompt(getPromptInputs({
@@ -174,11 +164,6 @@ export const formatErrorMessage = ({ error, message }) => {
174
164
  const errorMessage = error.json ? `${error.message} - ${JSON.stringify(error.json)}` : error.message;
175
165
  return `${message} with error: ${chalk.red(errorMessage)}`;
176
166
  };
177
- /**
178
- * @param {string} title
179
- */
180
- // @ts-expect-error TS(7006) FIXME: Parameter 'title' implicitly has an 'any' type.
181
- const formatTitle = (title) => chalk.cyan(title);
182
167
  // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
183
168
  export const createDeployKey = async ({ api }) => {
184
169
  try {
@@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid';
6
6
  import { fetchLatestVersion, shouldFetchLatestVersion } from '../lib/exec-fetcher.js';
7
7
  import { getPathInHome } from '../lib/settings.js';
8
8
  import { NETLIFYDEVERR, NETLIFYDEVLOG, chalk, log } from './command-helpers.js';
9
- // @ts-expect-error TS(7034) FIXME: Variable 'execa' implicitly has type 'any' in some... Remove this comment to see the full error message
10
9
  import execa from './execa.js';
11
10
  const PACKAGE_NAME = 'live-tunnel-client';
12
11
  const EXEC_NAME = PACKAGE_NAME;
@@ -45,7 +44,6 @@ const connectTunnel = function ({ localPort, netlifyApiToken, session }) {
45
44
  args.push('-v');
46
45
  log(execPath, args);
47
46
  }
48
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
49
47
  const ps = execa(execPath, args, { stdio: 'inherit' });
50
48
  // @ts-expect-error TS(7006) FIXME: Parameter 'code' implicitly has an 'any' type.
51
49
  ps.on('close', (code) => process.exit(code));
@@ -1,9 +1,7 @@
1
1
  import semver from 'semver';
2
- // @ts-expect-error TS(7034) FIXME: Variable 'execa' implicitly has type 'any' in some... Remove this comment to see the full error message
3
2
  import execa from '../execa.js';
4
3
  export const checkLFSFilters = async function () {
5
4
  try {
6
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
7
5
  const { stdout } = await execa('git', ['config', '--get-regexp', 'filter.lfs']);
8
6
  return stdout.length !== 0;
9
7
  }
@@ -13,7 +11,6 @@ export const checkLFSFilters = async function () {
13
11
  };
14
12
  const getHelperVersion = async function () {
15
13
  try {
16
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
17
14
  const { stdout } = await execa('git-credential-netlify', ['version']);
18
15
  return stdout;
19
16
  }
@@ -28,7 +25,6 @@ export const checkHelperVersion = async function () {
28
25
  };
29
26
  export const checkGitVersion = async function () {
30
27
  try {
31
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
32
28
  const { stdout } = await execa('git', ['--version']);
33
29
  return stdout.split(' ').pop();
34
30
  }
@@ -38,7 +34,6 @@ export const checkGitVersion = async function () {
38
34
  };
39
35
  const getLFSVersion = async function () {
40
36
  try {
41
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
42
37
  const { stdout } = await execa('git-lfs', ['version']);
43
38
  return stdout;
44
39
  }
@@ -35,7 +35,6 @@ export const validateTemplate = async ({ ghToken, templateName }) => {
35
35
  const data = await response.json();
36
36
  return { exists: true, isTemplate: data.is_template };
37
37
  };
38
- // @ts-expect-error TS(7006) FIXME: Parameter 'templateName' implicitly has an 'any' t... Remove this comment to see the full error message
39
38
  export const createRepo = async (templateName, ghToken, siteName) => {
40
39
  const resp = await fetch(`https://api.github.com/repos/${templateName}/generate`, {
41
40
  method: 'POST',
@@ -3,7 +3,6 @@ import { dirname, join } from 'path';
3
3
  import process, { version as nodejsVersion } from 'process';
4
4
  import { fileURLToPath } from 'url';
5
5
  import { isCI } from 'ci-info';
6
- // @ts-expect-error TS(7034) FIXME: Variable 'execa' implicitly has type 'any' in some... Remove this comment to see the full error message
7
6
  import execa from '../execa.js';
8
7
  import getGlobalConfig from '../get-global-config.js';
9
8
  import { cliVersion } from './utils.js';
@@ -46,7 +45,6 @@ export const reportError = async function (error, config = {}) {
46
45
  });
47
46
  // spawn detached child process to handle send and wait for the http request to finish
48
47
  // otherwise it can get canceled
49
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
50
48
  await execa(process.execPath, [join(dirPath, 'request.js'), options], {
51
49
  detached: true,
52
50
  stdio: 'ignore',
@@ -2,32 +2,24 @@ import { dirname, join } from 'path';
2
2
  import process, { version as nodejsVersion } from 'process';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { isCI } from 'ci-info';
5
- // @ts-expect-error TS(7034) FIXME: Variable 'execa' implicitly has type 'any' in some... Remove this comment to see the full error message
6
5
  import execa from '../execa.js';
7
6
  import getGlobalConfig from '../get-global-config.js';
8
7
  import { isTelemetryDisabled, cliVersion } from './utils.js';
9
8
  import isValidEventName from './validation.js';
10
9
  const dirPath = dirname(fileURLToPath(import.meta.url));
11
- /**
12
- * @param {'track' | 'identify'} type
13
- * @param {object} payload
14
- */
15
- // @ts-expect-error TS(7006) FIXME: Parameter 'type' implicitly has an 'any' type.
16
10
  function send(type, payload) {
17
11
  const requestFile = join(dirPath, 'request.js');
18
12
  const options = JSON.stringify({
19
13
  data: payload,
20
14
  type,
21
15
  });
22
- const args = /** @type {const} */ [process.execPath, [requestFile, options]];
16
+ const args = [process.execPath, [requestFile, options]];
23
17
  if (process.env.NETLIFY_TEST_TELEMETRY_WAIT === 'true') {
24
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
25
18
  return execa(...args, {
26
19
  stdio: 'inherit',
27
20
  });
28
21
  }
29
22
  // spawn detached child process to handle send
30
- // @ts-expect-error TS(7005) FIXME: Variable 'execa' implicitly has an 'any' type.
31
23
  execa(...args, {
32
24
  detached: true,
33
25
  stdio: 'ignore',
@@ -46,10 +38,7 @@ const eventConfig = {
46
38
  };
47
39
  /**
48
40
  * Tracks a custom event with the provided payload
49
- * @param {string} eventName
50
- * @param {{status?: string, duration?: number, [key: string]: unknown}} [payload]
51
41
  */
52
- // @ts-expect-error TS(7006) FIXME: Parameter 'eventName' implicitly has an 'any' type... Remove this comment to see the full error message
53
42
  export async function track(eventName, payload = {}) {
54
43
  if (isCI) {
55
44
  return;
@@ -69,7 +58,6 @@ export async function track(eventName, payload = {}) {
69
58
  if (!isValid(eventName, eventConfig)) {
70
59
  return false;
71
60
  }
72
- // @ts-expect-error TS(2339) FIXME: Property 'duration' does not exist on type '{}'.
73
61
  const { duration, status, ...properties } = payload;
74
62
  const defaultData = {
75
63
  event: eventName,
@@ -81,14 +69,6 @@ export async function track(eventName, payload = {}) {
81
69
  };
82
70
  return send('track', defaultData);
83
71
  }
84
- /**
85
- * @param {object} payload
86
- * @param {string} payload.name
87
- * @param {string} payload.email
88
- * @param {string} payload.userId
89
- * @returns
90
- */
91
- // @ts-expect-error TS(7006) FIXME: Parameter 'payload' implicitly has an 'any' type.
92
72
  export async function identify(payload) {
93
73
  if (isCI) {
94
74
  return;