netlify-cli 15.9.1-rc.0 → 15.10.0-rc.0
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/bin/run.mjs +6 -5
- package/npm-shrinkwrap.json +235 -734
- package/package.json +5 -5
- package/src/commands/base-command.mjs +122 -79
- package/src/commands/build/build.mjs +9 -1
- package/src/commands/deploy/deploy.mjs +1 -0
- package/src/commands/dev/dev.mjs +2 -3
- package/src/commands/functions/functions-create.mjs +118 -86
- package/src/commands/functions/functions-invoke.mjs +2 -2
- package/src/commands/functions/functions-list.mjs +2 -2
- package/src/commands/serve/serve.mjs +4 -6
- package/src/functions-templates/typescript/hello-world/package-lock.json +6 -6
- package/src/lib/edge-functions/bootstrap.mjs +1 -1
- package/src/lib/edge-functions/headers.mjs +1 -0
- package/src/lib/edge-functions/proxy.mjs +1 -0
- package/src/lib/functions/runtimes/js/index.mjs +1 -1
- package/src/lib/functions/runtimes/js/worker.mjs +1 -1
- package/src/recipes/vscode/index.mjs +24 -6
- package/src/utils/build-info.mjs +81 -0
- package/src/utils/detect-server-settings.mjs +26 -87
- package/src/utils/framework-server.mjs +4 -3
- package/src/utils/functions/functions.mjs +1 -5
- package/src/utils/proxy.mjs +0 -3
- package/src/utils/read-repo-url.mjs +4 -0
- package/src/utils/run-build.mjs +40 -65
- package/src/utils/shell.mjs +10 -4
|
@@ -4,11 +4,9 @@ import { EOL } from 'os'
|
|
|
4
4
|
import { dirname, relative, resolve } from 'path'
|
|
5
5
|
|
|
6
6
|
import { getFramework, getSettings } from '@netlify/build-info'
|
|
7
|
-
import fuzzy from 'fuzzy'
|
|
8
7
|
import getPort from 'get-port'
|
|
9
|
-
import inquirer from 'inquirer'
|
|
10
8
|
|
|
11
|
-
import {
|
|
9
|
+
import { detectFrameworkSettings } from './build-info.mjs'
|
|
12
10
|
import { NETLIFYDEVWARN, chalk, log } from './command-helpers.mjs'
|
|
13
11
|
import { acquirePort } from './dev.mjs'
|
|
14
12
|
import { getInternalFunctionsDir } from './functions/functions.mjs'
|
|
@@ -175,53 +173,22 @@ const handleStaticServer = async ({ devConfig, flags, workingDir }) => {
|
|
|
175
173
|
|
|
176
174
|
/**
|
|
177
175
|
* Retrieves the settings from a framework
|
|
178
|
-
* @param {import('@netlify/build-info').Settings} settings
|
|
179
|
-
* @returns {import('./types.js').BaseServerSettings}
|
|
180
|
-
*/
|
|
181
|
-
const getSettingsFromDetectedSettings = (settings) => ({
|
|
182
|
-
command: settings.devCommand,
|
|
183
|
-
frameworkPort: settings.frameworkPort,
|
|
184
|
-
dist: settings.dist,
|
|
185
|
-
framework: settings.framework.name,
|
|
186
|
-
env: settings.env,
|
|
187
|
-
pollingStrategies: settings.pollingStrategies,
|
|
188
|
-
plugins: getPluginsToAutoInstall(settings.plugins_from_config_file, settings.plugins_recommended),
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Uses @netlify/build-info to detect the dev settings and port based on the framework
|
|
193
|
-
* and the build system that is used.
|
|
194
|
-
* @param {import('../commands/base-command.mjs').default} command
|
|
176
|
+
* @param {import('@netlify/build-info').Settings} [settings]
|
|
177
|
+
* @returns {import('./types.js').BaseServerSettings | undefined}
|
|
195
178
|
*/
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return getSettingsFromDetectedSettings(settings[0])
|
|
179
|
+
const getSettingsFromDetectedSettings = (settings) => {
|
|
180
|
+
if (!settings) {
|
|
181
|
+
return
|
|
200
182
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (!input || input === '') {
|
|
211
|
-
return scriptInquirerOptions
|
|
212
|
-
}
|
|
213
|
-
// only show filtered results
|
|
214
|
-
return filterSettings(scriptInquirerOptions, input)
|
|
215
|
-
},
|
|
216
|
-
})
|
|
217
|
-
// TODO: do better logging here with the framework command or port
|
|
218
|
-
log(
|
|
219
|
-
`Add ${formatProperty(
|
|
220
|
-
`framework = "${chosenSettings.framework.id}"`,
|
|
221
|
-
)} to the [dev] section of your netlify.toml to avoid this selection prompt next time`,
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
return getSettingsFromDetectedSettings(chosenSettings)
|
|
183
|
+
return {
|
|
184
|
+
baseDirectory: settings.baseDirectory,
|
|
185
|
+
command: settings.devCommand,
|
|
186
|
+
frameworkPort: settings.frameworkPort,
|
|
187
|
+
dist: settings.dist,
|
|
188
|
+
framework: settings.framework.name,
|
|
189
|
+
env: settings.env,
|
|
190
|
+
pollingStrategies: settings.pollingStrategies,
|
|
191
|
+
plugins: getPluginsToAutoInstall(settings.plugins_from_config_file, settings.plugins_recommended),
|
|
225
192
|
}
|
|
226
193
|
}
|
|
227
194
|
|
|
@@ -262,26 +229,18 @@ const handleCustomFramework = ({ devConfig, workingDir }) => {
|
|
|
262
229
|
* @param {Partial<import('./types.js').BaseServerSettings>=} config.frameworkSettings
|
|
263
230
|
*/
|
|
264
231
|
const mergeSettings = async ({ devConfig, frameworkSettings = {}, workingDir }) => {
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
dist,
|
|
268
|
-
env,
|
|
269
|
-
framework,
|
|
270
|
-
frameworkPort: frameworkDetectedPort,
|
|
271
|
-
pollingStrategies = [],
|
|
272
|
-
} = frameworkSettings
|
|
273
|
-
|
|
274
|
-
const command = devConfig.command || frameworkCommand
|
|
275
|
-
const frameworkPort = devConfig.targetPort || frameworkDetectedPort
|
|
232
|
+
const command = devConfig.command || frameworkSettings.command
|
|
233
|
+
const frameworkPort = devConfig.targetPort || frameworkSettings.frameworkPort
|
|
276
234
|
// if the framework doesn't start a server, we use a static one
|
|
277
235
|
const useStaticServer = !(command && frameworkPort)
|
|
278
236
|
return {
|
|
237
|
+
baseDirectory: devConfig.base || frameworkSettings.baseDirectory,
|
|
279
238
|
command,
|
|
280
239
|
frameworkPort: useStaticServer ? await getStaticServerPort({ devConfig }) : frameworkPort,
|
|
281
|
-
dist: devConfig.publish || dist || getDefaultDist(workingDir),
|
|
282
|
-
framework,
|
|
283
|
-
env,
|
|
284
|
-
pollingStrategies,
|
|
240
|
+
dist: devConfig.publish || frameworkSettings.dist || getDefaultDist(workingDir),
|
|
241
|
+
framework: frameworkSettings.framework,
|
|
242
|
+
env: frameworkSettings.env,
|
|
243
|
+
pollingStrategies: frameworkSettings.pollingStrategies || [],
|
|
285
244
|
useStaticServer,
|
|
286
245
|
}
|
|
287
246
|
}
|
|
@@ -324,12 +283,15 @@ const detectServerSettings = async (devConfig, flags, command) => {
|
|
|
324
283
|
// this is the default CLI behavior
|
|
325
284
|
|
|
326
285
|
const runDetection = !hasCommandAndTargetPort(devConfig)
|
|
327
|
-
const frameworkSettings = runDetection
|
|
286
|
+
const frameworkSettings = runDetection
|
|
287
|
+
? getSettingsFromDetectedSettings(await detectFrameworkSettings(command, 'dev'))
|
|
288
|
+
: undefined
|
|
328
289
|
if (frameworkSettings === undefined && runDetection) {
|
|
329
290
|
log(`${NETLIFYDEVWARN} No app server detected. Using simple static server`)
|
|
330
291
|
settings = await handleStaticServer({ flags, devConfig, workingDir: command.workingDir })
|
|
331
292
|
} else {
|
|
332
293
|
validateFrameworkConfig({ devConfig })
|
|
294
|
+
|
|
333
295
|
settings = await mergeSettings({ devConfig, frameworkSettings, workingDir: command.workingDir })
|
|
334
296
|
}
|
|
335
297
|
|
|
@@ -371,29 +333,6 @@ const detectServerSettings = async (devConfig, flags, command) => {
|
|
|
371
333
|
}
|
|
372
334
|
}
|
|
373
335
|
|
|
374
|
-
const filterSettings = function (scriptInquirerOptions, input) {
|
|
375
|
-
const filterOptions = scriptInquirerOptions.map((scriptInquirerOption) => scriptInquirerOption.name)
|
|
376
|
-
// TODO: remove once https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1394 is fixed
|
|
377
|
-
// eslint-disable-next-line unicorn/no-array-method-this-argument
|
|
378
|
-
const filteredSettings = fuzzy.filter(input, filterOptions)
|
|
379
|
-
const filteredSettingNames = new Set(
|
|
380
|
-
filteredSettings.map((filteredSetting) => (input ? filteredSetting.string : filteredSetting)),
|
|
381
|
-
)
|
|
382
|
-
return scriptInquirerOptions.filter((t) => filteredSettingNames.has(t.name))
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* @param {import('@netlify/build-info').Settings[]} settings
|
|
387
|
-
* @returns
|
|
388
|
-
*/
|
|
389
|
-
const formatSettingsArrForInquirer = function (settings) {
|
|
390
|
-
return settings.map((setting) => ({
|
|
391
|
-
name: `[${chalk.yellow(setting.framework.name)}] '${setting.devCommand}'`,
|
|
392
|
-
value: { ...setting, commands: [setting.devCommand] },
|
|
393
|
-
short: `${setting.name}-${setting.devCommand}`,
|
|
394
|
-
}))
|
|
395
|
-
}
|
|
396
|
-
|
|
397
336
|
/**
|
|
398
337
|
* Returns a copy of the provided config with any plugins provided by the
|
|
399
338
|
* server settings
|
|
@@ -19,12 +19,13 @@ const FRAMEWORK_PORT_TIMEOUT = 6e5
|
|
|
19
19
|
* Start a static server if the `useStaticServer` is provided or a framework specific server
|
|
20
20
|
* @param {object} config
|
|
21
21
|
* @param {import('./types.js').ServerSettings} config.settings
|
|
22
|
+
* @param {string} config.cwd
|
|
22
23
|
* @returns {Promise<StartReturnObject>}
|
|
23
24
|
*/
|
|
24
|
-
export const startFrameworkServer = async function ({ settings }) {
|
|
25
|
+
export const startFrameworkServer = async function ({ cwd, settings }) {
|
|
25
26
|
if (settings.useStaticServer) {
|
|
26
27
|
if (settings.command) {
|
|
27
|
-
runCommand(settings.command, settings.env)
|
|
28
|
+
runCommand(settings.command, { env: settings.env, cwd })
|
|
28
29
|
}
|
|
29
30
|
await startStaticServer({ settings })
|
|
30
31
|
|
|
@@ -37,7 +38,7 @@ export const startFrameworkServer = async function ({ settings }) {
|
|
|
37
38
|
text: `Waiting for framework port ${settings.frameworkPort}. This can be configured using the 'targetPort' property in the netlify.toml`,
|
|
38
39
|
})
|
|
39
40
|
|
|
40
|
-
runCommand(settings.command, settings.env, spinner)
|
|
41
|
+
runCommand(settings.command, { env: settings.env, spinner, cwd })
|
|
41
42
|
|
|
42
43
|
let port
|
|
43
44
|
try {
|
|
@@ -17,11 +17,7 @@ export const SERVE_FUNCTIONS_FOLDER = 'functions-serve'
|
|
|
17
17
|
* @returns {string}
|
|
18
18
|
*/
|
|
19
19
|
export const getFunctionsDir = ({ config, options }, defaultValue) =>
|
|
20
|
-
options.functions ||
|
|
21
|
-
(config.dev && config.dev.functions) ||
|
|
22
|
-
config.functionsDirectory ||
|
|
23
|
-
(config.dev && config.dev.Functions) ||
|
|
24
|
-
defaultValue
|
|
20
|
+
options.functions || config.dev?.functions || config.functionsDirectory || config.dev?.Functions || defaultValue
|
|
25
21
|
|
|
26
22
|
export const getFunctionsManifestPath = async ({ base }) => {
|
|
27
23
|
const path = resolve(base, getPathInProject(['functions', 'manifest.json']))
|
package/src/utils/proxy.mjs
CHANGED
|
@@ -375,7 +375,6 @@ const initializeProxy = async function ({ configPath, distDir, env, host, port,
|
|
|
375
375
|
proxy.before('web', 'stream', (req) => {
|
|
376
376
|
// See https://github.com/http-party/node-http-proxy/issues/1219#issuecomment-511110375
|
|
377
377
|
if (req.headers.expect) {
|
|
378
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
379
378
|
req.__expectHeader = req.headers.expect
|
|
380
379
|
delete req.headers.expect
|
|
381
380
|
}
|
|
@@ -402,9 +401,7 @@ const initializeProxy = async function ({ configPath, distDir, env, host, port,
|
|
|
402
401
|
handleProxyRequest(req, proxyReq)
|
|
403
402
|
}
|
|
404
403
|
|
|
405
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
406
404
|
if (req.__expectHeader) {
|
|
407
|
-
// eslint-disable-next-line no-underscore-dangle
|
|
408
405
|
proxyReq.setHeader('Expect', req.__expectHeader)
|
|
409
406
|
}
|
|
410
407
|
if (req.originalBody) {
|
|
@@ -7,6 +7,7 @@ import fetch from 'node-fetch'
|
|
|
7
7
|
const GITHUB = 'GitHub'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* @param {string} _url
|
|
10
11
|
* Takes a url like https://github.com/netlify-labs/all-the-functions/tree/master/functions/9-using-middleware
|
|
11
12
|
* and returns https://api.github.com/repos/netlify-labs/all-the-functions/contents/functions/9-using-middleware
|
|
12
13
|
*/
|
|
@@ -36,6 +37,9 @@ const getRepoURLContents = async function (repoHost, ownerAndRepo, contentsPath)
|
|
|
36
37
|
throw new Error('unsupported host ', repoHost)
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} _url
|
|
42
|
+
*/
|
|
39
43
|
export const validateRepoURL = function (_url) {
|
|
40
44
|
// TODO: use `url.URL()` instead
|
|
41
45
|
// eslint-disable-next-line n/no-deprecated-api
|
package/src/utils/run-build.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { promises as fs } from 'fs'
|
|
3
|
-
import path from 'path'
|
|
3
|
+
import path, { join } from 'path'
|
|
4
4
|
|
|
5
5
|
import { INTERNAL_EDGE_FUNCTIONS_FOLDER } from '../lib/edge-functions/consts.mjs'
|
|
6
6
|
import { getPathInProject } from '../lib/settings.mjs'
|
|
@@ -14,12 +14,11 @@ const netlifyBuildPromise = import('@netlify/build')
|
|
|
14
14
|
/**
|
|
15
15
|
* Copies `netlify.toml`, if one is defined, into the `.netlify` internal
|
|
16
16
|
* directory and returns the path to its new location.
|
|
17
|
-
* @param {
|
|
18
|
-
* @param {string}
|
|
19
|
-
* @param {string} config.siteRoot
|
|
17
|
+
* @param {string} configPath
|
|
18
|
+
* @param {string} destinationFolder The folder where it should be copied to either the root of the repo or a package inside a monorepo
|
|
20
19
|
*/
|
|
21
|
-
const copyConfig = async (
|
|
22
|
-
const newConfigPath = path.resolve(
|
|
20
|
+
const copyConfig = async (configPath, destinationFolder) => {
|
|
21
|
+
const newConfigPath = path.resolve(destinationFolder, getPathInProject(['netlify.toml']))
|
|
23
22
|
|
|
24
23
|
try {
|
|
25
24
|
await fs.copyFile(configPath, newConfigPath)
|
|
@@ -44,75 +43,51 @@ const cleanInternalDirectory = async (basePath) => {
|
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
|
-
*
|
|
48
|
-
* @param {
|
|
49
|
-
* @param {
|
|
50
|
-
* @param {*}
|
|
51
|
-
* @param {
|
|
52
|
-
* @param {
|
|
53
|
-
* @param {
|
|
54
|
-
* @param {string=} config.options.cwd
|
|
55
|
-
* @param {boolean} config.options.debug
|
|
56
|
-
* @param {boolean} config.options.dry
|
|
57
|
-
* @param {boolean} config.options.offline
|
|
58
|
-
* @param {boolean} config.options.quiet
|
|
59
|
-
* @param {boolean} config.options.saveConfig
|
|
46
|
+
* @param {object} params
|
|
47
|
+
* @param {import('../commands/base-command.mjs').default} params.command
|
|
48
|
+
* @param {import('../commands/base-command.mjs').default} params.command
|
|
49
|
+
* @param {*} params.options The flags of the command
|
|
50
|
+
* @param {import('./types.js').ServerSettings} params.settings
|
|
51
|
+
* @param {NodeJS.ProcessEnv} [params.env]
|
|
52
|
+
* @param {'build' | 'dev'} [params.timeline]
|
|
60
53
|
* @returns
|
|
61
54
|
*/
|
|
62
|
-
const
|
|
63
|
-
cachedConfig,
|
|
64
|
-
options: { configPath, context, debug, dry, offline, quiet, saveConfig },
|
|
65
|
-
projectDir,
|
|
66
|
-
}) => ({
|
|
67
|
-
cachedConfig,
|
|
68
|
-
configPath,
|
|
69
|
-
siteId: cachedConfig.siteInfo.id,
|
|
70
|
-
token: cachedConfig.token,
|
|
71
|
-
dry,
|
|
72
|
-
debug,
|
|
73
|
-
context,
|
|
74
|
-
mode: 'cli',
|
|
75
|
-
telemetry: false,
|
|
76
|
-
buffer: false,
|
|
77
|
-
offline,
|
|
78
|
-
cwd: projectDir,
|
|
79
|
-
quiet,
|
|
80
|
-
saveConfig,
|
|
81
|
-
})
|
|
55
|
+
export const runNetlifyBuild = async ({ command, env = {}, options, settings, timeline = 'build' }) => {
|
|
56
|
+
const { cachedConfig, site } = command.netlify
|
|
82
57
|
|
|
83
|
-
/**
|
|
84
|
-
*
|
|
85
|
-
* @param {object} config
|
|
86
|
-
* @param {*} config.cachedConfig
|
|
87
|
-
* @param {NodeJS.ProcessEnv} config.env
|
|
88
|
-
* @param {*} config.options The flags of the command
|
|
89
|
-
* @param {string} config.projectDir
|
|
90
|
-
* @param {import('./types.js').ServerSettings} config.settings
|
|
91
|
-
* @param {*} config.site
|
|
92
|
-
* @param {'build' | 'dev'} config.timeline
|
|
93
|
-
* @returns
|
|
94
|
-
*/
|
|
95
|
-
export const runNetlifyBuild = async ({
|
|
96
|
-
cachedConfig,
|
|
97
|
-
env,
|
|
98
|
-
options,
|
|
99
|
-
projectDir,
|
|
100
|
-
settings,
|
|
101
|
-
site,
|
|
102
|
-
timeline = 'build',
|
|
103
|
-
}) => {
|
|
104
58
|
const { default: buildSite, startDev } = await netlifyBuildPromise
|
|
105
|
-
|
|
106
|
-
|
|
59
|
+
|
|
60
|
+
const sharedOptions = {
|
|
107
61
|
cachedConfig,
|
|
108
|
-
|
|
109
|
-
|
|
62
|
+
configPath: cachedConfig.configPath,
|
|
63
|
+
siteId: cachedConfig.siteInfo.id,
|
|
64
|
+
token: cachedConfig.token,
|
|
65
|
+
dry: options.dry,
|
|
66
|
+
debug: options.debug,
|
|
67
|
+
context: options.context,
|
|
68
|
+
mode: 'cli',
|
|
69
|
+
telemetry: false,
|
|
70
|
+
buffer: false,
|
|
71
|
+
offline: options.offline,
|
|
72
|
+
cwd: cachedConfig.buildDir,
|
|
73
|
+
quiet: options.quiet,
|
|
74
|
+
saveConfig: options.saveConfig,
|
|
75
|
+
}
|
|
76
|
+
|
|
110
77
|
const devCommand = async (settingsOverrides = {}) => {
|
|
78
|
+
let cwd = command.workingDir
|
|
79
|
+
|
|
80
|
+
if (command.project.workspace?.packages.length) {
|
|
81
|
+
console.log('packages', settings.baseDirectory)
|
|
82
|
+
cwd = join(command.project.jsWorkspaceRoot, settings.baseDirectory || '')
|
|
83
|
+
}
|
|
84
|
+
|
|
111
85
|
const { ipVersion } = await startFrameworkServer({
|
|
112
86
|
settings: {
|
|
113
87
|
...settings,
|
|
114
88
|
...settingsOverrides,
|
|
115
89
|
},
|
|
90
|
+
cwd,
|
|
116
91
|
})
|
|
117
92
|
|
|
118
93
|
settings.frameworkHost = ipVersion === 6 ? '::1' : '127.0.0.1'
|
|
@@ -125,7 +100,7 @@ export const runNetlifyBuild = async ({
|
|
|
125
100
|
|
|
126
101
|
// Copy `netlify.toml` into the internal directory. This will be the new
|
|
127
102
|
// location of the config file for the duration of the command.
|
|
128
|
-
const tempConfigPath = await copyConfig(
|
|
103
|
+
const tempConfigPath = await copyConfig(cachedConfig.configPath, command.workingDir)
|
|
129
104
|
const buildSiteOptions = {
|
|
130
105
|
...sharedOptions,
|
|
131
106
|
outputConfigPath: tempConfigPath,
|
package/src/utils/shell.mjs
CHANGED
|
@@ -40,10 +40,14 @@ const cleanupBeforeExit = async ({ exitCode }) => {
|
|
|
40
40
|
/**
|
|
41
41
|
* Run a command and pipe stdout, stderr and stdin
|
|
42
42
|
* @param {string} command
|
|
43
|
-
* @param {
|
|
43
|
+
* @param {object} options
|
|
44
|
+
* @param {import('ora').Ora|null} [options.spinner]
|
|
45
|
+
* @param {NodeJS.ProcessEnv} [options.env]
|
|
46
|
+
* @param {string} [options.cwd]
|
|
44
47
|
* @returns {execa.ExecaChildProcess<string>}
|
|
45
48
|
*/
|
|
46
|
-
export const runCommand = (command,
|
|
49
|
+
export const runCommand = (command, options = {}) => {
|
|
50
|
+
const { cwd, env = {}, spinner = null } = options
|
|
47
51
|
const commandProcess = execa.command(command, {
|
|
48
52
|
preferLocal: true,
|
|
49
53
|
// we use reject=false to avoid rejecting synchronously when the command doesn't exist
|
|
@@ -55,6 +59,7 @@ export const runCommand = (command, env = {}, spinner = null) => {
|
|
|
55
59
|
},
|
|
56
60
|
// windowsHide needs to be false for child process to terminate properly on Windows
|
|
57
61
|
windowsHide: false,
|
|
62
|
+
cwd,
|
|
58
63
|
})
|
|
59
64
|
|
|
60
65
|
// This ensures that an active spinner stays at the bottom of the commandline
|
|
@@ -86,8 +91,9 @@ export const runCommand = (command, env = {}, spinner = null) => {
|
|
|
86
91
|
const [commandWithoutArgs] = command.split(' ')
|
|
87
92
|
if (result.failed && isNonExistingCommandError({ command: commandWithoutArgs, error: result })) {
|
|
88
93
|
log(
|
|
89
|
-
NETLIFYDEVERR
|
|
90
|
-
|
|
94
|
+
`\n\n${NETLIFYDEVERR} Failed running command: ${command}. Please verify ${chalk.magenta(
|
|
95
|
+
`'${commandWithoutArgs}'`,
|
|
96
|
+
)} exists`,
|
|
91
97
|
)
|
|
92
98
|
} else {
|
|
93
99
|
const errorMessage = result.failed
|