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.
- package/npm-shrinkwrap.json +8 -9
- package/package.json +1 -2
- package/src/commands/base-command.js +47 -102
- package/src/commands/dev/dev.js +0 -1
- package/src/commands/functions/functions-create.js +0 -4
- package/src/commands/link/link.js +0 -5
- package/src/commands/lm/lm-setup.js +0 -2
- package/src/commands/main.js +0 -2
- package/src/commands/serve/serve.js +0 -1
- package/src/commands/sites/sites-create-template.js +0 -3
- package/src/lib/exec-fetcher.js +0 -2
- package/src/lib/functions/local-proxy.js +1 -3
- package/src/lib/functions/netlify-function.js +1 -1
- package/src/lib/functions/runtimes/go/index.js +0 -3
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.js +10 -10
- package/src/lib/functions/runtimes/js/builders/zisi.js +1 -1
- package/src/lib/functions/runtimes/rust/index.js +0 -2
- package/src/lib/functions/server.js +22 -11
- package/src/utils/banner.js +2 -3
- package/src/utils/build-info.js +22 -39
- package/src/utils/command-helpers.js +3 -11
- package/src/utils/detect-server-settings.js +12 -33
- package/src/utils/execa.js +1 -4
- package/src/utils/feature-flags.js +1 -7
- package/src/utils/framework-server.js +6 -10
- package/src/utils/init/utils.js +17 -32
- package/src/utils/live-tunnel.js +0 -2
- package/src/utils/lm/requirements.js +0 -5
- package/src/utils/sites/utils.js +0 -1
- package/src/utils/telemetry/report-error.js +0 -2
- package/src/utils/telemetry/telemetry.js +1 -21
|
@@ -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 = ['.
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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 {
|
package/src/utils/banner.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import boxen from 'boxen';
|
|
2
2
|
import { chalk, log, NETLIFYDEVLOG } from './command-helpers.js';
|
|
3
|
-
|
|
4
|
-
|
|
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,
|
package/src/utils/build-info.js
CHANGED
|
@@ -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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
41
|
-
* @param
|
|
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
|
-
|
|
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
|
|
61
|
+
// @ts-expect-error is not known by the types as it uses the autocomplete plugin
|
|
59
62
|
type: 'autocomplete',
|
|
60
|
-
|
|
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
|
-
:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
package/src/utils/execa.js
CHANGED
|
@@ -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/
|
|
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
|
-
|
|
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',
|
package/src/utils/init/utils.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
20
|
-
*
|
|
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 = []) =>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
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 {
|
package/src/utils/live-tunnel.js
CHANGED
|
@@ -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
|
}
|
package/src/utils/sites/utils.js
CHANGED
|
@@ -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 =
|
|
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;
|