netlify-cli 15.10.0-rc.1 → 15.11.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 +5 -6
- package/npm-shrinkwrap.json +3 -6
- package/package.json +2 -1
- package/src/commands/base-command.mjs +116 -295
- package/src/commands/build/build.mjs +1 -9
- package/src/commands/deploy/deploy.mjs +9 -23
- package/src/commands/dev/dev.mjs +17 -22
- package/src/commands/functions/functions-create.mjs +89 -118
- package/src/commands/functions/functions-invoke.mjs +7 -10
- package/src/commands/functions/functions-list.mjs +2 -2
- package/src/commands/init/init.mjs +1 -1
- package/src/commands/link/link.mjs +5 -5
- package/src/commands/serve/serve.mjs +6 -10
- package/src/commands/sites/sites-create-template.mjs +1 -1
- package/src/commands/sites/sites-create.mjs +1 -1
- package/src/lib/edge-functions/internal.mjs +3 -5
- package/src/lib/edge-functions/proxy.mjs +3 -27
- package/src/lib/functions/netlify-function.mjs +26 -1
- package/src/lib/functions/registry.mjs +14 -26
- package/src/lib/functions/runtimes/js/worker.mjs +1 -1
- package/src/lib/spinner.mjs +1 -1
- package/src/recipes/vscode/index.mjs +6 -24
- package/src/utils/command-helpers.mjs +7 -16
- package/src/utils/detect-server-settings.mjs +245 -133
- package/src/utils/framework-server.mjs +5 -6
- package/src/utils/functions/functions.mjs +5 -8
- package/src/utils/get-repo-data.mjs +6 -5
- package/src/utils/init/config-github.mjs +2 -2
- package/src/utils/init/config-manual.mjs +7 -24
- package/src/utils/init/frameworks.mjs +23 -0
- package/src/utils/init/utils.mjs +63 -62
- package/src/utils/proxy-server.mjs +4 -7
- package/src/utils/proxy.mjs +3 -4
- package/src/utils/read-repo-url.mjs +0 -4
- package/src/utils/run-build.mjs +32 -58
- package/src/utils/shell.mjs +7 -24
- package/src/utils/state-config.mjs +1 -5
- package/src/utils/static-server.mjs +0 -4
- package/src/utils/build-info.mjs +0 -100
|
@@ -5,12 +5,7 @@ import { exit, log } from '../command-helpers.mjs'
|
|
|
5
5
|
|
|
6
6
|
import { createDeployKey, getBuildSettings, saveNetlifyToml, setupSite } from './utils.mjs'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
* Prompts for granting the netlify ssh public key access to your repo
|
|
10
|
-
* @param {object} deployKey
|
|
11
|
-
* @param {string} deployKey.public_key
|
|
12
|
-
*/
|
|
13
|
-
const addDeployKey = async (deployKey) => {
|
|
8
|
+
const addDeployKey = async ({ deployKey }) => {
|
|
14
9
|
log('\nGive this Netlify SSH public key access to your repository:\n')
|
|
15
10
|
log(`\n${deployKey.public_key}\n\n`)
|
|
16
11
|
|
|
@@ -28,11 +23,6 @@ const addDeployKey = async (deployKey) => {
|
|
|
28
23
|
}
|
|
29
24
|
}
|
|
30
25
|
|
|
31
|
-
/**
|
|
32
|
-
* @param {object} config
|
|
33
|
-
* @param {Awaited<ReturnType<import('../../utils/get-repo-data.mjs').default>>} config.repoData
|
|
34
|
-
* @returns {Promise<string>}
|
|
35
|
-
*/
|
|
36
26
|
const getRepoPath = async ({ repoData }) => {
|
|
37
27
|
const { repoPath } = await inquirer.prompt([
|
|
38
28
|
{
|
|
@@ -40,9 +30,6 @@ const getRepoPath = async ({ repoData }) => {
|
|
|
40
30
|
name: 'repoPath',
|
|
41
31
|
message: 'The SSH URL of the remote git repo:',
|
|
42
32
|
default: repoData.url,
|
|
43
|
-
/**
|
|
44
|
-
* @param {string} url
|
|
45
|
-
*/
|
|
46
33
|
validate: (url) => SSH_URL_REGEXP.test(url) || 'The URL provided does not use the SSH protocol',
|
|
47
34
|
},
|
|
48
35
|
])
|
|
@@ -50,11 +37,7 @@ const getRepoPath = async ({ repoData }) => {
|
|
|
50
37
|
return repoPath
|
|
51
38
|
}
|
|
52
39
|
|
|
53
|
-
|
|
54
|
-
* @param {string} deployHook
|
|
55
|
-
* @returns
|
|
56
|
-
*/
|
|
57
|
-
const addDeployHook = async (deployHook) => {
|
|
40
|
+
const addDeployHook = async ({ deployHook }) => {
|
|
58
41
|
log('\nConfigure the following webhook for your repository:\n')
|
|
59
42
|
log(`\n${deployHook}\n\n`)
|
|
60
43
|
const { deployHookAdded } = await inquirer.prompt([
|
|
@@ -72,14 +55,14 @@ const addDeployHook = async (deployHook) => {
|
|
|
72
55
|
/**
|
|
73
56
|
* @param {object} config
|
|
74
57
|
* @param {import('../../commands/base-command.mjs').default} config.command
|
|
75
|
-
* @param {
|
|
58
|
+
* @param {*} config.repoData
|
|
76
59
|
* @param {string} config.siteId
|
|
77
60
|
*/
|
|
78
61
|
export default async function configManual({ command, repoData, siteId }) {
|
|
79
62
|
const { netlify } = command
|
|
80
63
|
const {
|
|
81
64
|
api,
|
|
82
|
-
cachedConfig: { configPath },
|
|
65
|
+
cachedConfig: { configPath, env },
|
|
83
66
|
config,
|
|
84
67
|
repositoryRoot,
|
|
85
68
|
site: { root: siteRoot },
|
|
@@ -89,12 +72,12 @@ export default async function configManual({ command, repoData, siteId }) {
|
|
|
89
72
|
repositoryRoot,
|
|
90
73
|
siteRoot,
|
|
91
74
|
config,
|
|
92
|
-
|
|
75
|
+
env,
|
|
93
76
|
})
|
|
94
77
|
await saveNetlifyToml({ repositoryRoot, config, configPath, baseDir, buildCmd, buildDir, functionsDir })
|
|
95
78
|
|
|
96
79
|
const deployKey = await createDeployKey({ api })
|
|
97
|
-
await addDeployKey(deployKey)
|
|
80
|
+
await addDeployKey({ deployKey })
|
|
98
81
|
|
|
99
82
|
const repoPath = await getRepoPath({ repoData })
|
|
100
83
|
const repo = {
|
|
@@ -116,7 +99,7 @@ export default async function configManual({ command, repoData, siteId }) {
|
|
|
116
99
|
configPlugins: config.plugins,
|
|
117
100
|
pluginsToInstall,
|
|
118
101
|
})
|
|
119
|
-
const deployHookAdded = await addDeployHook(updatedSite.deploy_hook)
|
|
102
|
+
const deployHookAdded = await addDeployHook({ deployHook: updatedSite.deploy_hook })
|
|
120
103
|
if (!deployHookAdded) {
|
|
121
104
|
exit()
|
|
122
105
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { listFrameworks } from '@netlify/framework-info'
|
|
3
|
+
|
|
4
|
+
export const getFrameworkInfo = async ({ baseDirectory, nodeVersion }) => {
|
|
5
|
+
const frameworks = await listFrameworks({ projectDir: baseDirectory, nodeVersion })
|
|
6
|
+
// several frameworks can be detected - first one has highest priority
|
|
7
|
+
if (frameworks.length !== 0) {
|
|
8
|
+
const [
|
|
9
|
+
{
|
|
10
|
+
build: { commands, directory },
|
|
11
|
+
name,
|
|
12
|
+
plugins,
|
|
13
|
+
},
|
|
14
|
+
] = frameworks
|
|
15
|
+
return {
|
|
16
|
+
frameworkName: name,
|
|
17
|
+
frameworkBuildCommand: commands[0],
|
|
18
|
+
frameworkBuildDir: directory,
|
|
19
|
+
frameworkPlugins: plugins,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return {}
|
|
23
|
+
}
|
package/src/utils/init/utils.mjs
CHANGED
|
@@ -1,72 +1,64 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { writeFile } from 'fs/promises'
|
|
3
3
|
import path from 'path'
|
|
4
|
+
import process from 'process'
|
|
4
5
|
|
|
5
6
|
import cleanDeep from 'clean-deep'
|
|
6
7
|
import inquirer from 'inquirer'
|
|
7
8
|
|
|
8
9
|
import { fileExistsAsync } from '../../lib/fs.mjs'
|
|
9
10
|
import { normalizeBackslash } from '../../lib/path.mjs'
|
|
10
|
-
import { detectBuildSettings } from '../build-info.mjs'
|
|
11
11
|
import { chalk, error as failAndExit, log, warn } from '../command-helpers.mjs'
|
|
12
12
|
|
|
13
|
+
import { getFrameworkInfo } from './frameworks.mjs'
|
|
14
|
+
import { detectNodeVersion } from './node-version.mjs'
|
|
13
15
|
import { getRecommendPlugins, getUIPlugins } from './plugins.mjs'
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export const getPluginsToAutoInstall = (pluginsInstalled = [], pluginsRecommended = []) =>
|
|
30
|
-
pluginsRecommended.reduce(
|
|
31
|
-
(acc, plugin) =>
|
|
32
|
-
pluginsInstalled.includes(plugin) && !pluginsToAlwaysInstall.has(plugin) ? acc : [...acc, plugin],
|
|
33
|
-
|
|
34
|
-
/** @type {string[]} */ ([]),
|
|
35
|
-
)
|
|
17
|
+
const normalizeDir = ({ baseDirectory, defaultValue, dir }) => {
|
|
18
|
+
if (dir === undefined) {
|
|
19
|
+
return defaultValue
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const relativeDir = path.relative(baseDirectory, dir)
|
|
23
|
+
return relativeDir || defaultValue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const getDefaultBase = ({ baseDirectory, repositoryRoot }) => {
|
|
27
|
+
if (baseDirectory !== repositoryRoot && baseDirectory.startsWith(repositoryRoot)) {
|
|
28
|
+
return path.relative(repositoryRoot, baseDirectory)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const recommendedPlugins = getRecommendPlugins(
|
|
32
|
+
const getDefaultSettings = ({
|
|
33
|
+
baseDirectory,
|
|
34
|
+
config,
|
|
35
|
+
frameworkBuildCommand,
|
|
36
|
+
frameworkBuildDir,
|
|
37
|
+
frameworkPlugins,
|
|
38
|
+
repositoryRoot,
|
|
39
|
+
}) => {
|
|
40
|
+
const recommendedPlugins = getRecommendPlugins(frameworkPlugins, config)
|
|
41
|
+
const {
|
|
42
|
+
command: defaultBuildCmd = frameworkBuildCommand,
|
|
43
|
+
functions: defaultFunctionsDir,
|
|
44
|
+
publish: defaultBuildDir = frameworkBuildDir,
|
|
45
|
+
} = config.build
|
|
46
46
|
|
|
47
47
|
return {
|
|
48
|
-
defaultBaseDir:
|
|
49
|
-
defaultBuildCmd
|
|
50
|
-
defaultBuildDir:
|
|
51
|
-
defaultFunctionsDir:
|
|
48
|
+
defaultBaseDir: getDefaultBase({ repositoryRoot, baseDirectory }),
|
|
49
|
+
defaultBuildCmd,
|
|
50
|
+
defaultBuildDir: normalizeDir({ baseDirectory, dir: defaultBuildDir, defaultValue: '.' }),
|
|
51
|
+
defaultFunctionsDir: normalizeDir({ baseDirectory, dir: defaultFunctionsDir, defaultValue: 'netlify/functions' }),
|
|
52
52
|
recommendedPlugins,
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
/**
|
|
57
|
-
*
|
|
58
|
-
* @param {object} param0
|
|
59
|
-
* @param {string} param0.defaultBaseDir
|
|
60
|
-
* @param {string} param0.defaultBuildCmd
|
|
61
|
-
* @param {string=} param0.defaultBuildDir
|
|
62
|
-
* @returns
|
|
63
|
-
*/
|
|
64
56
|
const getPromptInputs = ({ defaultBaseDir, defaultBuildCmd, defaultBuildDir }) => {
|
|
65
57
|
const inputs = [
|
|
66
58
|
defaultBaseDir !== undefined && {
|
|
67
59
|
type: 'input',
|
|
68
60
|
name: 'baseDir',
|
|
69
|
-
message: 'Base directory
|
|
61
|
+
message: 'Base directory (e.g. projects/frontend):',
|
|
70
62
|
default: defaultBaseDir,
|
|
71
63
|
},
|
|
72
64
|
{
|
|
@@ -87,22 +79,34 @@ const getPromptInputs = ({ defaultBaseDir, defaultBuildCmd, defaultBuildDir }) =
|
|
|
87
79
|
return inputs.filter(Boolean)
|
|
88
80
|
}
|
|
89
81
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
82
|
+
// `repositoryRoot === siteRoot` means the base directory wasn't detected by @netlify/config, so we use cwd()
|
|
83
|
+
const getBaseDirectory = ({ repositoryRoot, siteRoot }) =>
|
|
84
|
+
path.normalize(repositoryRoot) === path.normalize(siteRoot) ? process.cwd() : siteRoot
|
|
85
|
+
|
|
86
|
+
export const getBuildSettings = async ({ config, env, repositoryRoot, siteRoot }) => {
|
|
87
|
+
const baseDirectory = getBaseDirectory({ repositoryRoot, siteRoot })
|
|
88
|
+
const nodeVersion = await detectNodeVersion({ baseDirectory, env })
|
|
89
|
+
const {
|
|
90
|
+
frameworkBuildCommand,
|
|
91
|
+
frameworkBuildDir,
|
|
92
|
+
frameworkName,
|
|
93
|
+
frameworkPlugins = [],
|
|
94
|
+
} = await getFrameworkInfo({
|
|
95
|
+
baseDirectory,
|
|
96
|
+
nodeVersion,
|
|
97
|
+
})
|
|
101
98
|
const { defaultBaseDir, defaultBuildCmd, defaultBuildDir, defaultFunctionsDir, recommendedPlugins } =
|
|
102
|
-
await
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
99
|
+
await getDefaultSettings({
|
|
100
|
+
repositoryRoot,
|
|
101
|
+
config,
|
|
102
|
+
baseDirectory,
|
|
103
|
+
frameworkBuildCommand,
|
|
104
|
+
frameworkBuildDir,
|
|
105
|
+
frameworkPlugins,
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
if (recommendedPlugins.length !== 0) {
|
|
109
|
+
log(`Configuring ${formatTitle(frameworkName)} runtime...`)
|
|
106
110
|
log()
|
|
107
111
|
}
|
|
108
112
|
|
|
@@ -195,9 +199,6 @@ export const formatErrorMessage = ({ error, message }) => {
|
|
|
195
199
|
return `${message} with error: ${chalk.red(errorMessage)}`
|
|
196
200
|
}
|
|
197
201
|
|
|
198
|
-
/**
|
|
199
|
-
* @param {string} title
|
|
200
|
-
*/
|
|
201
202
|
const formatTitle = (title) => chalk.cyan(title)
|
|
202
203
|
|
|
203
204
|
export const createDeployKey = async ({ api }) => {
|
|
@@ -36,21 +36,19 @@ export const generateInspectSettings = (edgeInspect, edgeInspectBrk) => {
|
|
|
36
36
|
/**
|
|
37
37
|
*
|
|
38
38
|
* @param {object} params
|
|
39
|
-
* @param {string=} params.accountId
|
|
40
39
|
* @param {*} params.addonsUrls
|
|
41
|
-
* @param {import('../commands/
|
|
40
|
+
* @param {import('../commands/base-command.mjs').NetlifyOptions["config"]} params.config
|
|
42
41
|
* @param {string} [params.configPath] An override for the Netlify config path
|
|
43
42
|
* @param {boolean} params.debug
|
|
44
|
-
* @param {import('../commands/
|
|
43
|
+
* @param {import('../commands/base-command.mjs').NetlifyOptions["cachedConfig"]['env']} params.env
|
|
45
44
|
* @param {InspectSettings} params.inspectSettings
|
|
46
45
|
* @param {() => Promise<object>} params.getUpdatedConfig
|
|
47
46
|
* @param {string} params.geolocationMode
|
|
48
47
|
* @param {string} params.geoCountry
|
|
49
48
|
* @param {*} params.settings
|
|
50
49
|
* @param {boolean} params.offline
|
|
51
|
-
* @param {
|
|
50
|
+
* @param {*} params.site
|
|
52
51
|
* @param {*} params.siteInfo
|
|
53
|
-
* @param {string} params.projectDir
|
|
54
52
|
* @param {import('./state-config.mjs').default} params.state
|
|
55
53
|
* @returns
|
|
56
54
|
*/
|
|
@@ -66,7 +64,6 @@ export const startProxyServer = async ({
|
|
|
66
64
|
getUpdatedConfig,
|
|
67
65
|
inspectSettings,
|
|
68
66
|
offline,
|
|
69
|
-
projectDir,
|
|
70
67
|
settings,
|
|
71
68
|
site,
|
|
72
69
|
siteInfo,
|
|
@@ -83,7 +80,7 @@ export const startProxyServer = async ({
|
|
|
83
80
|
getUpdatedConfig,
|
|
84
81
|
inspectSettings,
|
|
85
82
|
offline,
|
|
86
|
-
projectDir,
|
|
83
|
+
projectDir: site.root,
|
|
87
84
|
settings,
|
|
88
85
|
state,
|
|
89
86
|
siteInfo,
|
package/src/utils/proxy.mjs
CHANGED
|
@@ -375,6 +375,7 @@ 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
|
|
378
379
|
req.__expectHeader = req.headers.expect
|
|
379
380
|
delete req.headers.expect
|
|
380
381
|
}
|
|
@@ -401,7 +402,9 @@ const initializeProxy = async function ({ configPath, distDir, env, host, port,
|
|
|
401
402
|
handleProxyRequest(req, proxyReq)
|
|
402
403
|
}
|
|
403
404
|
|
|
405
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
404
406
|
if (req.__expectHeader) {
|
|
407
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
405
408
|
proxyReq.setHeader('Expect', req.__expectHeader)
|
|
406
409
|
}
|
|
407
410
|
if (req.originalBody) {
|
|
@@ -596,10 +599,6 @@ const onRequest = async (
|
|
|
596
599
|
proxy.web(req, res, options)
|
|
597
600
|
}
|
|
598
601
|
|
|
599
|
-
/**
|
|
600
|
-
* @param {import('./types.js').ServerSettings} settings
|
|
601
|
-
* @returns
|
|
602
|
-
*/
|
|
603
602
|
export const getProxyUrl = function (settings) {
|
|
604
603
|
const scheme = settings.https ? 'https' : 'http'
|
|
605
604
|
return `${scheme}://localhost:${settings.port}`
|
|
@@ -7,7 +7,6 @@ import fetch from 'node-fetch'
|
|
|
7
7
|
const GITHUB = 'GitHub'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @param {string} _url
|
|
11
10
|
* Takes a url like https://github.com/netlify-labs/all-the-functions/tree/master/functions/9-using-middleware
|
|
12
11
|
* and returns https://api.github.com/repos/netlify-labs/all-the-functions/contents/functions/9-using-middleware
|
|
13
12
|
*/
|
|
@@ -37,9 +36,6 @@ const getRepoURLContents = async function (repoHost, ownerAndRepo, contentsPath)
|
|
|
37
36
|
throw new Error('unsupported host ', repoHost)
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
/**
|
|
41
|
-
* @param {string} _url
|
|
42
|
-
*/
|
|
43
39
|
export const validateRepoURL = function (_url) {
|
|
44
40
|
// TODO: use `url.URL()` instead
|
|
45
41
|
// eslint-disable-next-line n/no-deprecated-api
|
package/src/utils/run-build.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { promises as fs } from 'fs'
|
|
3
|
-
import path
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import process from 'process'
|
|
4
5
|
|
|
5
6
|
import { INTERNAL_EDGE_FUNCTIONS_FOLDER } from '../lib/edge-functions/consts.mjs'
|
|
6
7
|
import { getPathInProject } from '../lib/settings.mjs'
|
|
@@ -11,14 +12,10 @@ import { INTERNAL_FUNCTIONS_FOLDER } from './functions/index.mjs'
|
|
|
11
12
|
|
|
12
13
|
const netlifyBuildPromise = import('@netlify/build')
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* @param {string} destinationFolder The folder where it should be copied to either the root of the repo or a package inside a monorepo
|
|
19
|
-
*/
|
|
20
|
-
const copyConfig = async (configPath, destinationFolder) => {
|
|
21
|
-
const newConfigPath = path.resolve(destinationFolder, getPathInProject(['netlify.toml']))
|
|
15
|
+
// Copies `netlify.toml`, if one is defined, into the `.netlify` internal
|
|
16
|
+
// directory and returns the path to its new location.
|
|
17
|
+
const copyConfig = async ({ configPath, siteRoot }) => {
|
|
18
|
+
const newConfigPath = path.resolve(siteRoot, getPathInProject(['netlify.toml']))
|
|
22
19
|
|
|
23
20
|
try {
|
|
24
21
|
await fs.copyFile(configPath, newConfigPath)
|
|
@@ -29,9 +26,6 @@ const copyConfig = async (configPath, destinationFolder) => {
|
|
|
29
26
|
return newConfigPath
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
/**
|
|
33
|
-
* @param {string} basePath
|
|
34
|
-
*/
|
|
35
29
|
const cleanInternalDirectory = async (basePath) => {
|
|
36
30
|
const ops = [INTERNAL_FUNCTIONS_FOLDER, INTERNAL_EDGE_FUNCTIONS_FOLDER, 'netlify.toml'].map((name) => {
|
|
37
31
|
const fullPath = path.resolve(basePath, getPathInProject([name]))
|
|
@@ -42,52 +36,38 @@ const cleanInternalDirectory = async (basePath) => {
|
|
|
42
36
|
await Promise.all(ops)
|
|
43
37
|
}
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
39
|
+
const getBuildOptions = ({
|
|
40
|
+
cachedConfig,
|
|
41
|
+
options: { configPath, context, cwd = process.cwd(), debug, dry, offline, quiet, saveConfig },
|
|
42
|
+
}) => ({
|
|
43
|
+
cachedConfig,
|
|
44
|
+
configPath,
|
|
45
|
+
siteId: cachedConfig.siteInfo.id,
|
|
46
|
+
token: cachedConfig.token,
|
|
47
|
+
dry,
|
|
48
|
+
debug,
|
|
49
|
+
context,
|
|
50
|
+
mode: 'cli',
|
|
51
|
+
telemetry: false,
|
|
52
|
+
buffer: false,
|
|
53
|
+
offline,
|
|
54
|
+
cwd,
|
|
55
|
+
quiet,
|
|
56
|
+
saveConfig,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const runNetlifyBuild = async ({ cachedConfig, env, options, settings, site, timeline = 'build' }) => {
|
|
58
60
|
const { default: buildSite, startDev } = await netlifyBuildPromise
|
|
59
|
-
|
|
60
|
-
const sharedOptions = {
|
|
61
|
+
const sharedOptions = getBuildOptions({
|
|
61
62
|
cachedConfig,
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
63
|
+
options,
|
|
64
|
+
})
|
|
77
65
|
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
|
-
|
|
85
66
|
const { ipVersion } = await startFrameworkServer({
|
|
86
67
|
settings: {
|
|
87
68
|
...settings,
|
|
88
69
|
...settingsOverrides,
|
|
89
70
|
},
|
|
90
|
-
cwd,
|
|
91
71
|
})
|
|
92
72
|
|
|
93
73
|
settings.frameworkHost = ipVersion === 6 ? '::1' : '127.0.0.1'
|
|
@@ -100,7 +80,7 @@ export const runNetlifyBuild = async ({ command, env = {}, options, settings, ti
|
|
|
100
80
|
|
|
101
81
|
// Copy `netlify.toml` into the internal directory. This will be the new
|
|
102
82
|
// location of the config file for the duration of the command.
|
|
103
|
-
const tempConfigPath = await copyConfig(cachedConfig.configPath,
|
|
83
|
+
const tempConfigPath = await copyConfig({ configPath: cachedConfig.configPath, siteRoot: site.root })
|
|
104
84
|
const buildSiteOptions = {
|
|
105
85
|
...sharedOptions,
|
|
106
86
|
outputConfigPath: tempConfigPath,
|
|
@@ -138,19 +118,13 @@ export const runNetlifyBuild = async ({ command, env = {}, options, settings, ti
|
|
|
138
118
|
// Run Netlify Build using the `startDev` entry point.
|
|
139
119
|
const { error: startDevError, success } = await startDev(devCommand, startDevOptions)
|
|
140
120
|
|
|
141
|
-
if (!success
|
|
121
|
+
if (!success) {
|
|
142
122
|
error(`Could not start local development server\n\n${startDevError.message}\n\n${startDevError.stack}`)
|
|
143
123
|
}
|
|
144
124
|
|
|
145
125
|
return {}
|
|
146
126
|
}
|
|
147
127
|
|
|
148
|
-
/**
|
|
149
|
-
* @param {Omit<Parameters<typeof runNetlifyBuild>[0], 'timeline'>} options
|
|
150
|
-
*/
|
|
151
128
|
export const runDevTimeline = (options) => runNetlifyBuild({ ...options, timeline: 'dev' })
|
|
152
129
|
|
|
153
|
-
/**
|
|
154
|
-
* @param {Omit<Parameters<typeof runNetlifyBuild>[0], 'timeline'>} options
|
|
155
|
-
*/
|
|
156
130
|
export const runBuildTimeline = (options) => runNetlifyBuild({ ...options, timeline: 'build' })
|
package/src/utils/shell.mjs
CHANGED
|
@@ -40,26 +40,17 @@ const cleanupBeforeExit = async ({ exitCode }) => {
|
|
|
40
40
|
/**
|
|
41
41
|
* Run a command and pipe stdout, stderr and stdin
|
|
42
42
|
* @param {string} command
|
|
43
|
-
* @param {
|
|
44
|
-
* @param {import('ora').Ora|null} [options.spinner]
|
|
45
|
-
* @param {NodeJS.ProcessEnv} [options.env]
|
|
46
|
-
* @param {string} [options.cwd]
|
|
43
|
+
* @param {NodeJS.ProcessEnv} env
|
|
47
44
|
* @returns {execa.ExecaChildProcess<string>}
|
|
48
45
|
*/
|
|
49
|
-
export const runCommand = (command,
|
|
50
|
-
const { cwd, env = {}, spinner = null } = options
|
|
46
|
+
export const runCommand = (command, env = {}, spinner = null) => {
|
|
51
47
|
const commandProcess = execa.command(command, {
|
|
52
48
|
preferLocal: true,
|
|
53
49
|
// we use reject=false to avoid rejecting synchronously when the command doesn't exist
|
|
54
50
|
reject: false,
|
|
55
|
-
env
|
|
56
|
-
// we want always colorful terminal outputs
|
|
57
|
-
FORCE_COLOR: 'true',
|
|
58
|
-
...env,
|
|
59
|
-
},
|
|
51
|
+
env,
|
|
60
52
|
// windowsHide needs to be false for child process to terminate properly on Windows
|
|
61
53
|
windowsHide: false,
|
|
62
|
-
cwd,
|
|
63
54
|
})
|
|
64
55
|
|
|
65
56
|
// This ensures that an active spinner stays at the bottom of the commandline
|
|
@@ -91,16 +82,15 @@ export const runCommand = (command, options = {}) => {
|
|
|
91
82
|
const [commandWithoutArgs] = command.split(' ')
|
|
92
83
|
if (result.failed && isNonExistingCommandError({ command: commandWithoutArgs, error: result })) {
|
|
93
84
|
log(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
)} exists`,
|
|
85
|
+
NETLIFYDEVERR,
|
|
86
|
+
`Failed running command: ${command}. Please verify ${chalk.magenta(`'${commandWithoutArgs}'`)} exists`,
|
|
97
87
|
)
|
|
98
88
|
} else {
|
|
99
89
|
const errorMessage = result.failed
|
|
100
90
|
? `${NETLIFYDEVERR} ${result.shortMessage}`
|
|
101
91
|
: `${NETLIFYDEVWARN} "${command}" exited with code ${result.exitCode}`
|
|
102
92
|
|
|
103
|
-
log(
|
|
93
|
+
log(`${errorMessage}. Shutting down Netlify Dev server`)
|
|
104
94
|
}
|
|
105
95
|
|
|
106
96
|
return await cleanupBeforeExit({ exitCode: 1 })
|
|
@@ -110,13 +100,6 @@ export const runCommand = (command, options = {}) => {
|
|
|
110
100
|
return commandProcess
|
|
111
101
|
}
|
|
112
102
|
|
|
113
|
-
/**
|
|
114
|
-
*
|
|
115
|
-
* @param {object} config
|
|
116
|
-
* @param {string} config.command
|
|
117
|
-
* @param {*} config.error
|
|
118
|
-
* @returns
|
|
119
|
-
*/
|
|
120
103
|
const isNonExistingCommandError = ({ command, error: commandError }) => {
|
|
121
104
|
// `ENOENT` is only returned for non Windows systems
|
|
122
105
|
// See https://github.com/sindresorhus/execa/pull/447
|
|
@@ -125,7 +108,7 @@ const isNonExistingCommandError = ({ command, error: commandError }) => {
|
|
|
125
108
|
}
|
|
126
109
|
|
|
127
110
|
// if the command is a package manager we let it report the error
|
|
128
|
-
if (['yarn', 'npm'
|
|
111
|
+
if (['yarn', 'npm'].includes(command)) {
|
|
129
112
|
return false
|
|
130
113
|
}
|
|
131
114
|
|
|
@@ -11,11 +11,7 @@ import { getPathInProject } from '../lib/settings.mjs'
|
|
|
11
11
|
const STATE_PATH = getPathInProject(['state.json'])
|
|
12
12
|
const permissionError = "You don't have access to this file."
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
* Finds location of `.netlify/state.json`
|
|
16
|
-
* @param {string} cwd
|
|
17
|
-
* @returns {string}
|
|
18
|
-
*/
|
|
14
|
+
// Finds location of `.netlify/state.json`
|
|
19
15
|
const findStatePath = (cwd) => {
|
|
20
16
|
const statePath = findUpSync([STATE_PATH], { cwd })
|
|
21
17
|
|
|
@@ -6,10 +6,6 @@ import Fastify from 'fastify'
|
|
|
6
6
|
|
|
7
7
|
import { log, NETLIFYDEVLOG } from './command-helpers.mjs'
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* @param {object} config
|
|
11
|
-
* @param {import('./types.js').ServerSettings} config.settings
|
|
12
|
-
*/
|
|
13
9
|
export const startStaticServer = async ({ settings }) => {
|
|
14
10
|
const server = Fastify()
|
|
15
11
|
const rootPath = path.resolve(settings.dist)
|