netlify-cli 15.8.1-rc.1 → 15.9.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/npm-shrinkwrap.json +425 -310
- package/package.json +7 -6
- package/src/commands/base-command.mjs +4 -31
- package/src/commands/dev/dev.mjs +13 -12
- package/src/commands/serve/serve.mjs +1 -1
- package/src/functions-templates/javascript/auth-fetch/package-lock.json +6 -6
- package/src/functions-templates/javascript/google-analytics/package-lock.json +6 -6
- package/src/lib/spinner.mjs +1 -1
- package/src/utils/command-helpers.mjs +3 -10
- package/src/utils/detect-server-settings.mjs +132 -124
- package/src/utils/framework-server.mjs +2 -2
- package/src/utils/init/config-github.mjs +2 -2
- package/src/utils/init/config-manual.mjs +7 -24
- package/src/utils/init/frameworks.mjs +15 -11
- package/src/utils/init/utils.mjs +5 -6
- package/src/utils/proxy.mjs +0 -4
- package/src/utils/run-build.mjs +4 -44
- package/src/utils/shell.mjs +2 -13
- package/src/utils/static-server.mjs +0 -4
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { readFile } from 'fs/promises'
|
|
3
3
|
import { EOL } from 'os'
|
|
4
|
-
import path
|
|
4
|
+
import path from 'path'
|
|
5
5
|
import process from 'process'
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { Project } from '@netlify/build-info'
|
|
8
|
+
// eslint-disable-next-line import/extensions, n/no-missing-import
|
|
9
|
+
import { NodeFS } from '@netlify/build-info/node'
|
|
10
|
+
import { getFramework, listFrameworks } from '@netlify/framework-info'
|
|
8
11
|
import fuzzy from 'fuzzy'
|
|
9
12
|
import getPort from 'get-port'
|
|
10
13
|
|
|
11
14
|
import { NETLIFYDEVWARN, chalk, log } from './command-helpers.mjs'
|
|
12
15
|
import { acquirePort } from './dev.mjs'
|
|
13
16
|
import { getInternalFunctionsDir } from './functions/functions.mjs'
|
|
17
|
+
import { reportError } from './telemetry/report-error.mjs'
|
|
14
18
|
|
|
15
|
-
/** @param {string} str */
|
|
16
19
|
const formatProperty = (str) => chalk.magenta(`'${str}'`)
|
|
17
|
-
/** @param {string} str */
|
|
18
20
|
const formatValue = (str) => chalk.green(`'${str}'`)
|
|
19
21
|
|
|
20
|
-
/**
|
|
21
|
-
* @param {object} options
|
|
22
|
-
* @param {string} options.keyFile
|
|
23
|
-
* @param {string} options.certFile
|
|
24
|
-
* @returns {Promise<{ key: string, cert: string, keyFilePath: string, certFilePath: string }>}
|
|
25
|
-
*/
|
|
26
22
|
const readHttpsSettings = async (options) => {
|
|
27
23
|
if (typeof options !== 'object' || !options.keyFile || !options.certFile) {
|
|
28
24
|
throw new TypeError(
|
|
@@ -55,11 +51,6 @@ const readHttpsSettings = async (options) => {
|
|
|
55
51
|
return { key, cert, keyFilePath: path.resolve(keyFile), certFilePath: path.resolve(certFile) }
|
|
56
52
|
}
|
|
57
53
|
|
|
58
|
-
/**
|
|
59
|
-
* @param {object} config
|
|
60
|
-
* @param {import('../commands/dev/types.js').DevConfig} config.devConfig
|
|
61
|
-
* @param {keyof import('../commands/dev/types.js').DevConfig} config.property
|
|
62
|
-
*/
|
|
63
54
|
const validateStringProperty = ({ devConfig, property }) => {
|
|
64
55
|
if (devConfig[property] && typeof devConfig[property] !== 'string') {
|
|
65
56
|
const formattedProperty = formatProperty(property)
|
|
@@ -69,11 +60,6 @@ const validateStringProperty = ({ devConfig, property }) => {
|
|
|
69
60
|
}
|
|
70
61
|
}
|
|
71
62
|
|
|
72
|
-
/**
|
|
73
|
-
* @param {object} config
|
|
74
|
-
* @param {import('../commands/dev/types.js').DevConfig} config.devConfig
|
|
75
|
-
* @param {keyof import('../commands/dev/types.js').DevConfig} config.property
|
|
76
|
-
*/
|
|
77
63
|
const validateNumberProperty = ({ devConfig, property }) => {
|
|
78
64
|
if (devConfig[property] && typeof devConfig[property] !== 'number') {
|
|
79
65
|
const formattedProperty = formatProperty(property)
|
|
@@ -83,11 +69,6 @@ const validateNumberProperty = ({ devConfig, property }) => {
|
|
|
83
69
|
}
|
|
84
70
|
}
|
|
85
71
|
|
|
86
|
-
/**
|
|
87
|
-
*
|
|
88
|
-
* @param {object} config
|
|
89
|
-
* @param {import('../commands/dev/types.js').DevConfig} config.devConfig
|
|
90
|
-
*/
|
|
91
72
|
const validateFrameworkConfig = ({ devConfig }) => {
|
|
92
73
|
validateStringProperty({ devConfig, property: 'command' })
|
|
93
74
|
validateNumberProperty({ devConfig, property: 'port' })
|
|
@@ -102,11 +83,6 @@ const validateFrameworkConfig = ({ devConfig }) => {
|
|
|
102
83
|
}
|
|
103
84
|
}
|
|
104
85
|
|
|
105
|
-
/**
|
|
106
|
-
* @param {object} config
|
|
107
|
-
* @param {import('../commands/dev/types.js').DevConfig} config.devConfig
|
|
108
|
-
* @param {number=} config.detectedPort
|
|
109
|
-
*/
|
|
110
86
|
const validateConfiguredPort = ({ detectedPort, devConfig }) => {
|
|
111
87
|
if (devConfig.port && devConfig.port === detectedPort) {
|
|
112
88
|
const formattedPort = formatProperty('port')
|
|
@@ -126,11 +102,6 @@ const getDefaultDist = () => {
|
|
|
126
102
|
return process.cwd()
|
|
127
103
|
}
|
|
128
104
|
|
|
129
|
-
/**
|
|
130
|
-
* @param {object} config
|
|
131
|
-
* @param {import('../commands/dev/types.js').DevConfig} config.devConfig
|
|
132
|
-
* @returns {Promise<number>}
|
|
133
|
-
*/
|
|
134
105
|
const getStaticServerPort = async ({ devConfig }) => {
|
|
135
106
|
const port = await acquirePort({
|
|
136
107
|
configuredPort: devConfig.staticServerPort,
|
|
@@ -143,10 +114,10 @@ const getStaticServerPort = async ({ devConfig }) => {
|
|
|
143
114
|
|
|
144
115
|
/**
|
|
145
116
|
*
|
|
146
|
-
* @param {object}
|
|
147
|
-
* @param {import('../commands/dev/types.js').DevConfig}
|
|
148
|
-
* @param {import('commander').OptionValues}
|
|
149
|
-
* @param {string}
|
|
117
|
+
* @param {object} param0
|
|
118
|
+
* @param {import('../commands/dev/types.js').DevConfig} param0.devConfig
|
|
119
|
+
* @param {import('commander').OptionValues} param0.options
|
|
120
|
+
* @param {string} param0.projectDir
|
|
150
121
|
* @returns {Promise<import('./types.js').BaseServerSettings>}
|
|
151
122
|
*/
|
|
152
123
|
const handleStaticServer = async ({ devConfig, options, projectDir }) => {
|
|
@@ -182,84 +153,120 @@ const handleStaticServer = async ({ devConfig, options, projectDir }) => {
|
|
|
182
153
|
}
|
|
183
154
|
}
|
|
184
155
|
|
|
185
|
-
// these plugins represent runtimes that are
|
|
186
|
-
// expected to be "automatically" installed. Even though
|
|
187
|
-
// they can be installed on package/toml, we always
|
|
188
|
-
// want them installed in the site settings. When installed
|
|
189
|
-
// there our build will automatically install the latest without
|
|
190
|
-
// user management of the versioning.
|
|
191
|
-
const pluginsToAlwaysInstall = new Set(['@netlify/plugin-nextjs'])
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Retrieve a list of plugins to auto install
|
|
195
|
-
* @param {string[]=} pluginsInstalled
|
|
196
|
-
* @param {string[]=} pluginsRecommended
|
|
197
|
-
* @returns
|
|
198
|
-
*/
|
|
199
|
-
const getPluginsToAutoInstall = (pluginsInstalled = [], pluginsRecommended = []) =>
|
|
200
|
-
pluginsRecommended.reduce(
|
|
201
|
-
(acc, plugin) =>
|
|
202
|
-
pluginsInstalled.includes(plugin) && !pluginsToAlwaysInstall.has(plugin) ? acc : [...acc, plugin],
|
|
203
|
-
// eslint-disable-next-line no-inline-comments
|
|
204
|
-
/** @type {string[]} */ ([]),
|
|
205
|
-
)
|
|
206
|
-
|
|
207
156
|
/**
|
|
208
157
|
* Retrieves the settings from a framework
|
|
209
|
-
* @param {import('
|
|
158
|
+
* @param {import('./types.js').FrameworkInfo} framework
|
|
210
159
|
* @returns {import('./types.js').BaseServerSettings}
|
|
211
160
|
*/
|
|
212
|
-
const
|
|
161
|
+
const getSettingsFromFramework = (framework) => {
|
|
213
162
|
const {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
} =
|
|
163
|
+
build: { directory: dist },
|
|
164
|
+
dev: {
|
|
165
|
+
commands: [command],
|
|
166
|
+
pollingStrategies = [],
|
|
167
|
+
port: frameworkPort,
|
|
168
|
+
},
|
|
169
|
+
env = {},
|
|
170
|
+
name: frameworkName,
|
|
171
|
+
plugins,
|
|
172
|
+
staticAssetsDirectory: staticDir,
|
|
173
|
+
} = framework
|
|
225
174
|
|
|
226
175
|
return {
|
|
227
176
|
command,
|
|
228
177
|
frameworkPort,
|
|
229
|
-
dist,
|
|
178
|
+
dist: staticDir || dist,
|
|
230
179
|
framework: frameworkName,
|
|
231
180
|
env,
|
|
232
|
-
pollingStrategies,
|
|
233
|
-
plugins
|
|
181
|
+
pollingStrategies: pollingStrategies.map(({ name }) => name),
|
|
182
|
+
plugins,
|
|
234
183
|
}
|
|
235
184
|
}
|
|
236
185
|
|
|
186
|
+
const hasDevCommand = (framework) => Array.isArray(framework.dev.commands) && framework.dev.commands.length !== 0
|
|
187
|
+
|
|
237
188
|
/**
|
|
238
|
-
*
|
|
189
|
+
* The new build setting detection with build systems and frameworks combined
|
|
190
|
+
* @param {string} projectDir
|
|
239
191
|
*/
|
|
240
|
-
const
|
|
241
|
-
const
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
192
|
+
const detectSettings = async (projectDir) => {
|
|
193
|
+
const fs = new NodeFS()
|
|
194
|
+
const project = new Project(fs, projectDir)
|
|
195
|
+
|
|
196
|
+
return await project.getBuildSettings()
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
*
|
|
201
|
+
* @param {import('./types.js').BaseServerSettings | undefined} frameworkSettings
|
|
202
|
+
* @param {import('@netlify/build-info').Settings[]} newSettings
|
|
203
|
+
* @param {Record<string, Record<string, any>>} [metadata]
|
|
204
|
+
*/
|
|
205
|
+
const detectChangesInNewSettings = (frameworkSettings, newSettings, metadata) => {
|
|
206
|
+
/** @type {string[]} */
|
|
207
|
+
const message = ['']
|
|
208
|
+
const [setting] = newSettings
|
|
209
|
+
|
|
210
|
+
if (frameworkSettings?.framework !== setting?.framework) {
|
|
211
|
+
message.push(
|
|
212
|
+
`- Framework does not match:`,
|
|
213
|
+
` [old]: ${frameworkSettings?.framework}`,
|
|
214
|
+
` [new]: ${setting?.framework}`,
|
|
215
|
+
'',
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (frameworkSettings?.command !== setting?.devCommand) {
|
|
220
|
+
message.push(
|
|
221
|
+
`- command does not match:`,
|
|
222
|
+
` [old]: ${frameworkSettings?.command}`,
|
|
223
|
+
` [new]: ${setting?.devCommand}`,
|
|
224
|
+
'',
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (frameworkSettings?.dist !== setting?.dist) {
|
|
229
|
+
message.push(`- dist does not match:`, ` [old]: ${frameworkSettings?.dist}`, ` [new]: ${setting?.dist}`, '')
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (frameworkSettings?.frameworkPort !== setting?.frameworkPort) {
|
|
233
|
+
message.push(
|
|
234
|
+
`- frameworkPort does not match:`,
|
|
235
|
+
` [old]: ${frameworkSettings?.frameworkPort}`,
|
|
236
|
+
` [new]: ${setting?.frameworkPort}`,
|
|
237
|
+
'',
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (message.length !== 0) {
|
|
242
|
+
reportError(
|
|
243
|
+
{
|
|
244
|
+
name: 'NewSettingsDetectionMismatch',
|
|
245
|
+
errorMessage: 'New Settings detection does not match old one',
|
|
246
|
+
message: message.join('\n'),
|
|
247
|
+
},
|
|
248
|
+
{ severity: 'info', metadata },
|
|
247
249
|
)
|
|
248
|
-
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const detectFrameworkSettings = async ({ projectDir }) => {
|
|
254
|
+
const projectFrameworks = await listFrameworks({ projectDir })
|
|
255
|
+
const frameworks = projectFrameworks.filter((framework) => hasDevCommand(framework))
|
|
249
256
|
|
|
250
|
-
if (
|
|
251
|
-
return
|
|
257
|
+
if (frameworks.length === 1) {
|
|
258
|
+
return getSettingsFromFramework(frameworks[0])
|
|
252
259
|
}
|
|
253
260
|
|
|
254
|
-
if (
|
|
261
|
+
if (frameworks.length > 1) {
|
|
255
262
|
// performance optimization, load inquirer on demand
|
|
256
263
|
const { default: inquirer } = await import('inquirer')
|
|
257
264
|
const { default: inquirerAutocompletePrompt } = await import('inquirer-autocomplete-prompt')
|
|
258
265
|
/** multiple matching detectors, make the user choose */
|
|
259
266
|
inquirer.registerPrompt('autocomplete', inquirerAutocompletePrompt)
|
|
260
|
-
const scriptInquirerOptions = formatSettingsArrForInquirer(
|
|
261
|
-
const {
|
|
262
|
-
name: '
|
|
267
|
+
const scriptInquirerOptions = formatSettingsArrForInquirer(frameworks)
|
|
268
|
+
const { chosenFramework } = await inquirer.prompt({
|
|
269
|
+
name: 'chosenFramework',
|
|
263
270
|
message: `Multiple possible start commands found`,
|
|
264
271
|
type: 'autocomplete',
|
|
265
272
|
source(_, input) {
|
|
@@ -272,24 +279,19 @@ const detectFrameworkSettings = async (project) => {
|
|
|
272
279
|
})
|
|
273
280
|
log(
|
|
274
281
|
`Add ${formatProperty(
|
|
275
|
-
`framework = "${
|
|
282
|
+
`framework = "${chosenFramework.id}"`,
|
|
276
283
|
)} to the [dev] section of your netlify.toml to avoid this selection prompt next time`,
|
|
277
284
|
)
|
|
278
285
|
|
|
279
|
-
return
|
|
286
|
+
return getSettingsFromFramework(chosenFramework)
|
|
280
287
|
}
|
|
281
288
|
}
|
|
282
289
|
|
|
283
|
-
/**
|
|
284
|
-
* @param {object} config
|
|
285
|
-
* @param {import('../commands/dev/types.js').DevConfig} config.devConfig
|
|
286
|
-
*/
|
|
287
290
|
const hasCommandAndTargetPort = ({ devConfig }) => devConfig.command && devConfig.targetPort
|
|
288
291
|
|
|
289
292
|
/**
|
|
290
293
|
* Creates settings for the custom framework
|
|
291
|
-
* @param {
|
|
292
|
-
* @param {import('../commands/dev/types.js').DevConfig} config.devConfig
|
|
294
|
+
* @param {*} param0
|
|
293
295
|
* @returns {import('./types.js').BaseServerSettings}
|
|
294
296
|
*/
|
|
295
297
|
const handleCustomFramework = ({ devConfig }) => {
|
|
@@ -309,9 +311,6 @@ const handleCustomFramework = ({ devConfig }) => {
|
|
|
309
311
|
}
|
|
310
312
|
}
|
|
311
313
|
|
|
312
|
-
/**
|
|
313
|
-
* @param {{ devConfig: any, frameworkSettings: import('./types.js').BaseServerSettings }} param0
|
|
314
|
-
*/
|
|
315
314
|
const mergeSettings = async ({ devConfig, frameworkSettings = {} }) => {
|
|
316
315
|
const {
|
|
317
316
|
command: frameworkCommand,
|
|
@@ -339,14 +338,12 @@ const mergeSettings = async ({ devConfig, frameworkSettings = {} }) => {
|
|
|
339
338
|
|
|
340
339
|
/**
|
|
341
340
|
* Handles a forced framework and retrieves the settings for it
|
|
342
|
-
* @param {
|
|
341
|
+
* @param {*} param0
|
|
343
342
|
* @returns {Promise<import('./types.js').BaseServerSettings>}
|
|
344
343
|
*/
|
|
345
|
-
const handleForcedFramework = async ({ devConfig,
|
|
344
|
+
const handleForcedFramework = async ({ devConfig, projectDir }) => {
|
|
346
345
|
// this throws if `devConfig.framework` is not a supported framework
|
|
347
|
-
const
|
|
348
|
-
const settings = await getSettings(framework, project, '')
|
|
349
|
-
const frameworkSettings = getSettingsFromDetectedSettings(settings)
|
|
346
|
+
const frameworkSettings = getSettingsFromFramework(await getFramework(devConfig.framework, { projectDir }))
|
|
350
347
|
return mergeSettings({ devConfig, frameworkSettings })
|
|
351
348
|
}
|
|
352
349
|
|
|
@@ -354,12 +351,11 @@ const handleForcedFramework = async ({ devConfig, project }) => {
|
|
|
354
351
|
* Get the server settings based on the flags and the devConfig
|
|
355
352
|
* @param {import('../commands/dev/types.js').DevConfig} devConfig
|
|
356
353
|
* @param {import('commander').OptionValues} options
|
|
357
|
-
* @param {import('@netlify/build-info').Project} project
|
|
358
354
|
* @param {string} projectDir
|
|
355
|
+
* @param {Record<string, Record<string, any>>} [metadata]
|
|
359
356
|
* @returns {Promise<import('./types.js').ServerSettings>}
|
|
360
357
|
*/
|
|
361
|
-
|
|
362
|
-
const detectServerSettings = async (devConfig, options, project, projectDir) => {
|
|
358
|
+
const detectServerSettings = async (devConfig, options, projectDir, metadata) => {
|
|
363
359
|
validateStringProperty({ devConfig, property: 'framework' })
|
|
364
360
|
|
|
365
361
|
/** @type {Partial<import('./types.js').BaseServerSettings>} */
|
|
@@ -372,9 +368,22 @@ const detectServerSettings = async (devConfig, options, project, projectDir) =>
|
|
|
372
368
|
// this is the default CLI behavior
|
|
373
369
|
|
|
374
370
|
const runDetection = !hasCommandAndTargetPort({ devConfig })
|
|
375
|
-
const frameworkSettings = runDetection ? await detectFrameworkSettings(
|
|
371
|
+
const frameworkSettings = runDetection ? await detectFrameworkSettings({ projectDir }) : undefined
|
|
372
|
+
const newSettings = runDetection ? await detectSettings(projectDir) : undefined
|
|
373
|
+
|
|
374
|
+
// just report differences in the settings
|
|
375
|
+
detectChangesInNewSettings(frameworkSettings, newSettings || [], {
|
|
376
|
+
...metadata,
|
|
377
|
+
settings: {
|
|
378
|
+
projectDir,
|
|
379
|
+
devConfig,
|
|
380
|
+
options,
|
|
381
|
+
old: frameworkSettings,
|
|
382
|
+
settings: newSettings,
|
|
383
|
+
},
|
|
384
|
+
})
|
|
376
385
|
|
|
377
|
-
if (frameworkSettings === undefined) {
|
|
386
|
+
if (frameworkSettings === undefined && runDetection) {
|
|
378
387
|
log(`${NETLIFYDEVWARN} No app server detected. Using simple static server`)
|
|
379
388
|
settings = await handleStaticServer({ options, devConfig, projectDir })
|
|
380
389
|
} else {
|
|
@@ -390,7 +399,7 @@ const detectServerSettings = async (devConfig, options, project, projectDir) =>
|
|
|
390
399
|
} else if (devConfig.framework) {
|
|
391
400
|
validateFrameworkConfig({ devConfig })
|
|
392
401
|
// this is when the user explicitly configures a framework, e.g. `framework = "gatsby"`
|
|
393
|
-
settings = await handleForcedFramework({ devConfig,
|
|
402
|
+
settings = await handleForcedFramework({ devConfig, projectDir })
|
|
394
403
|
}
|
|
395
404
|
|
|
396
405
|
validateConfiguredPort({ devConfig, detectedPort: settings.frameworkPort })
|
|
@@ -426,16 +435,15 @@ const filterSettings = function (scriptInquirerOptions, input) {
|
|
|
426
435
|
return scriptInquirerOptions.filter((t) => filteredSettingNames.has(t.name))
|
|
427
436
|
}
|
|
428
437
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}))
|
|
438
|
+
const formatSettingsArrForInquirer = function (frameworks) {
|
|
439
|
+
const formattedArr = frameworks.map((framework) =>
|
|
440
|
+
framework.dev.commands.map((command) => ({
|
|
441
|
+
name: `[${chalk.yellow(framework.name)}] '${command}'`,
|
|
442
|
+
value: { ...framework, commands: [command] },
|
|
443
|
+
short: `${framework.name}-${command}`,
|
|
444
|
+
})),
|
|
445
|
+
)
|
|
446
|
+
return formattedArr.flat()
|
|
439
447
|
}
|
|
440
448
|
|
|
441
449
|
/**
|
|
@@ -18,7 +18,7 @@ const FRAMEWORK_PORT_TIMEOUT = 6e5
|
|
|
18
18
|
/**
|
|
19
19
|
* Start a static server if the `useStaticServer` is provided or a framework specific server
|
|
20
20
|
* @param {object} config
|
|
21
|
-
* @param {import('./types
|
|
21
|
+
* @param {Partial<import('./types').ServerSettings>} config.settings
|
|
22
22
|
* @returns {Promise<StartReturnObject>}
|
|
23
23
|
*/
|
|
24
24
|
export const startFrameworkServer = async function ({ settings }) {
|
|
@@ -46,7 +46,7 @@ export const startFrameworkServer = async function ({ settings }) {
|
|
|
46
46
|
host: 'localhost',
|
|
47
47
|
output: 'silent',
|
|
48
48
|
timeout: FRAMEWORK_PORT_TIMEOUT,
|
|
49
|
-
...(settings.pollingStrategies
|
|
49
|
+
...(settings.pollingStrategies.includes('HTTP') && { protocol: 'http' }),
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
if (!port.open) {
|
|
@@ -207,7 +207,7 @@ export const configGithub = async ({ command, repoName, repoOwner, siteId }) =>
|
|
|
207
207
|
const { netlify } = command
|
|
208
208
|
const {
|
|
209
209
|
api,
|
|
210
|
-
cachedConfig: { configPath },
|
|
210
|
+
cachedConfig: { configPath, env },
|
|
211
211
|
config,
|
|
212
212
|
globalConfig,
|
|
213
213
|
repositoryRoot,
|
|
@@ -220,7 +220,7 @@ export const configGithub = async ({ command, repoName, repoOwner, siteId }) =>
|
|
|
220
220
|
repositoryRoot,
|
|
221
221
|
siteRoot,
|
|
222
222
|
config,
|
|
223
|
-
|
|
223
|
+
env,
|
|
224
224
|
})
|
|
225
225
|
await saveNetlifyToml({ repositoryRoot, config, configPath, baseDir, buildCmd, buildDir, functionsDir })
|
|
226
226
|
|
|
@@ -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
|
}
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
+
import { listFrameworks } from '@netlify/framework-info'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* @returns
|
|
6
|
-
*/
|
|
7
|
-
export const getFrameworkInfo = async ({ project }) => {
|
|
8
|
-
const settings = await project.getBuildSettings()
|
|
4
|
+
export const getFrameworkInfo = async ({ baseDirectory, nodeVersion }) => {
|
|
5
|
+
const frameworks = await listFrameworks({ projectDir: baseDirectory, nodeVersion })
|
|
9
6
|
// several frameworks can be detected - first one has highest priority
|
|
10
|
-
if (
|
|
7
|
+
if (frameworks.length !== 0) {
|
|
8
|
+
const [
|
|
9
|
+
{
|
|
10
|
+
build: { commands, directory },
|
|
11
|
+
name,
|
|
12
|
+
plugins,
|
|
13
|
+
},
|
|
14
|
+
] = frameworks
|
|
11
15
|
return {
|
|
12
|
-
frameworkName:
|
|
13
|
-
frameworkBuildCommand:
|
|
14
|
-
frameworkBuildDir:
|
|
15
|
-
frameworkPlugins:
|
|
16
|
+
frameworkName: name,
|
|
17
|
+
frameworkBuildCommand: commands[0],
|
|
18
|
+
frameworkBuildDir: directory,
|
|
19
|
+
frameworkPlugins: plugins,
|
|
16
20
|
}
|
|
17
21
|
}
|
|
18
22
|
return {}
|
package/src/utils/init/utils.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { normalizeBackslash } from '../../lib/path.mjs'
|
|
|
11
11
|
import { chalk, error as failAndExit, log, warn } from '../command-helpers.mjs'
|
|
12
12
|
|
|
13
13
|
import { getFrameworkInfo } from './frameworks.mjs'
|
|
14
|
+
import { detectNodeVersion } from './node-version.mjs'
|
|
14
15
|
import { getRecommendPlugins, getUIPlugins } from './plugins.mjs'
|
|
15
16
|
|
|
16
17
|
const normalizeDir = ({ baseDirectory, defaultValue, dir }) => {
|
|
@@ -82,19 +83,17 @@ const getPromptInputs = ({ defaultBaseDir, defaultBuildCmd, defaultBuildDir }) =
|
|
|
82
83
|
const getBaseDirectory = ({ repositoryRoot, siteRoot }) =>
|
|
83
84
|
path.normalize(repositoryRoot) === path.normalize(siteRoot) ? process.cwd() : siteRoot
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
* @param {{ config: any, repositoryRoot: any, siteRoot: any, project: import("@netlify/build-info").Project }} param0
|
|
87
|
-
* @returns
|
|
88
|
-
*/
|
|
89
|
-
export const getBuildSettings = async ({ config, project, repositoryRoot, siteRoot }) => {
|
|
86
|
+
export const getBuildSettings = async ({ config, env, repositoryRoot, siteRoot }) => {
|
|
90
87
|
const baseDirectory = getBaseDirectory({ repositoryRoot, siteRoot })
|
|
88
|
+
const nodeVersion = await detectNodeVersion({ baseDirectory, env })
|
|
91
89
|
const {
|
|
92
90
|
frameworkBuildCommand,
|
|
93
91
|
frameworkBuildDir,
|
|
94
92
|
frameworkName,
|
|
95
93
|
frameworkPlugins = [],
|
|
96
94
|
} = await getFrameworkInfo({
|
|
97
|
-
|
|
95
|
+
baseDirectory,
|
|
96
|
+
nodeVersion,
|
|
98
97
|
})
|
|
99
98
|
const { defaultBaseDir, defaultBuildCmd, defaultBuildDir, defaultFunctionsDir, recommendedPlugins } =
|
|
100
99
|
await getDefaultSettings({
|
package/src/utils/proxy.mjs
CHANGED
|
@@ -599,10 +599,6 @@ const onRequest = async (
|
|
|
599
599
|
proxy.web(req, res, options)
|
|
600
600
|
}
|
|
601
601
|
|
|
602
|
-
/**
|
|
603
|
-
* @param {import('./types.js').ServerSettings} settings
|
|
604
|
-
* @returns
|
|
605
|
-
*/
|
|
606
602
|
export const getProxyUrl = function (settings) {
|
|
607
603
|
const scheme = settings.https ? 'https' : 'http'
|
|
608
604
|
return `${scheme}://localhost:${settings.port}`
|