@@ -4,6 +4,9 @@ import { EOL } from 'os'
4
4
import path from 'path'
5
5
import process from 'process'
6
6
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'
7
10
import { getFramework , listFrameworks } from '@netlify/framework-info'
8
11
import fuzzy from 'fuzzy'
9
12
import getPort from 'get-port'
@@ -12,6 +15,7 @@ import isPlainObject from 'is-plain-obj'
12
15
import { NETLIFYDEVWARN , chalk , log } from './command-helpers.mjs'
13
16
import { acquirePort } from './dev.mjs'
14
17
import { getInternalFunctionsDir } from './functions/functions.mjs'
18
+ import { reportError } from './telemetry/report-error.mjs'
15
19
16
20
const formatProperty = ( str ) => chalk . magenta ( `'${ str } '` )
17
21
const formatValue = ( str ) => chalk . green ( `'${ str } '` )
@@ -112,10 +116,10 @@ const getStaticServerPort = async ({ devConfig }) => {
112
116
/**
113
117
*
114
118
* @param {object } param0
115
- * @param {import('../commands/dev/types').DevConfig } param0.devConfig
119
+ * @param {import('../commands/dev/types.js ').DevConfig } param0.devConfig
116
120
* @param {import('commander').OptionValues } param0.options
117
121
* @param {string } param0.projectDir
118
- * @returns {Promise<import('./types').BaseServerSettings> }
122
+ * @returns {Promise<import('./types.js ').BaseServerSettings> }
119
123
*/
120
124
const handleStaticServer = async ( { devConfig, options, projectDir } ) => {
121
125
validateNumberProperty ( { devConfig, property : 'staticServerPort' } )
@@ -152,8 +156,8 @@ const handleStaticServer = async ({ devConfig, options, projectDir }) => {
152
156
153
157
/**
154
158
* Retrieves the settings from a framework
155
- * @param {import('./types').FrameworkInfo } framework
156
- * @returns {import('./types').BaseServerSettings }
159
+ * @param {import('./types.js ').FrameworkInfo } framework
160
+ * @returns {import('./types.js ').BaseServerSettings }
157
161
*/
158
162
const getSettingsFromFramework = ( framework ) => {
159
163
const {
@@ -182,6 +186,71 @@ const getSettingsFromFramework = (framework) => {
182
186
183
187
const hasDevCommand = ( framework ) => Array . isArray ( framework . dev . commands ) && framework . dev . commands . length !== 0
184
188
189
+ /**
190
+ * The new build setting detection with build systems and frameworks combined
191
+ * @param {string } projectDir
192
+ */
193
+ const detectSettings = async ( projectDir ) => {
194
+ const fs = new NodeFS ( )
195
+ const project = new Project ( fs , projectDir )
196
+
197
+ return await project . getBuildSettings ( )
198
+ }
199
+
200
+ /**
201
+ *
202
+ * @param {import('./types.js').BaseServerSettings | undefined } frameworkSettings
203
+ * @param {import('@netlify/build-info').Settings[] } newSettings
204
+ * @param {Record<string, Record<string, any>> } [metadata]
205
+ */
206
+ const detectChangesInNewSettings = ( frameworkSettings , newSettings , metadata ) => {
207
+ /** @type {string[] } */
208
+ const message = [ '' ]
209
+ const [ setting ] = newSettings
210
+
211
+ if ( frameworkSettings ?. framework !== setting ?. framework ) {
212
+ message . push (
213
+ `- Framework does not match:` ,
214
+ ` [old]: ${ frameworkSettings ?. framework } ` ,
215
+ ` [new]: ${ setting ?. framework } ` ,
216
+ '' ,
217
+ )
218
+ }
219
+
220
+ if ( frameworkSettings ?. command !== setting ?. devCommand ) {
221
+ message . push (
222
+ `- command does not match:` ,
223
+ ` [old]: ${ frameworkSettings ?. command } ` ,
224
+ ` [new]: ${ setting ?. devCommand } ` ,
225
+ '' ,
226
+ )
227
+ }
228
+
229
+ if ( frameworkSettings ?. dist !== setting ?. dist ) {
230
+ message . push ( `- dist does not match:` , ` [old]: ${ frameworkSettings ?. dist } ` , ` [new]: ${ setting ?. dist } ` , '' )
231
+ }
232
+
233
+ if ( frameworkSettings ?. frameworkPort !== setting ?. frameworkPort ) {
234
+ message . push (
235
+ `- frameworkPort does not match:` ,
236
+ ` [old]: ${ frameworkSettings ?. frameworkPort } ` ,
237
+ ` [new]: ${ setting ?. frameworkPort } ` ,
238
+ '' ,
239
+ )
240
+ }
241
+
242
+ if ( message . length !== 0 ) {
243
+ reportError (
244
+ {
245
+ name : 'NewSettingsDetectionMismatch' ,
246
+ errorMessage : 'New Settings detection does not match old one' ,
247
+ message : message . join ( '\n' ) ,
248
+ } ,
249
+ { severity : 'info' , metadata } ,
250
+ )
251
+ }
252
+ }
253
+
185
254
const detectFrameworkSettings = async ( { projectDir } ) => {
186
255
const projectFrameworks = await listFrameworks ( { projectDir } )
187
256
const frameworks = projectFrameworks . filter ( ( framework ) => hasDevCommand ( framework ) )
@@ -224,7 +293,7 @@ const hasCommandAndTargetPort = ({ devConfig }) => devConfig.command && devConfi
224
293
/**
225
294
* Creates settings for the custom framework
226
295
* @param {* } param0
227
- * @returns {import('./types').BaseServerSettings }
296
+ * @returns {import('./types.js ').BaseServerSettings }
228
297
*/
229
298
const handleCustomFramework = ( { devConfig } ) => {
230
299
if ( ! hasCommandAndTargetPort ( { devConfig } ) ) {
@@ -271,7 +340,7 @@ const mergeSettings = async ({ devConfig, frameworkSettings = {} }) => {
271
340
/**
272
341
* Handles a forced framework and retrieves the settings for it
273
342
* @param {* } param0
274
- * @returns {Promise<import('./types').BaseServerSettings> }
343
+ * @returns {Promise<import('./types.js ').BaseServerSettings> }
275
344
*/
276
345
const handleForcedFramework = async ( { devConfig, projectDir } ) => {
277
346
// this throws if `devConfig.framework` is not a supported framework
@@ -281,15 +350,16 @@ const handleForcedFramework = async ({ devConfig, projectDir }) => {
281
350
282
351
/**
283
352
* Get the server settings based on the flags and the devConfig
284
- * @param {import('../commands/dev/types').DevConfig } devConfig
353
+ * @param {import('../commands/dev/types.js ').DevConfig } devConfig
285
354
* @param {import('commander').OptionValues } options
286
355
* @param {string } projectDir
287
- * @returns {Promise<import('./types').ServerSettings> }
356
+ * @param {Record<string, Record<string, any>> } [metadata]
357
+ * @returns {Promise<import('./types.js').ServerSettings> }
288
358
*/
289
- const detectServerSettings = async ( devConfig , options , projectDir ) => {
359
+ const detectServerSettings = async ( devConfig , options , projectDir , metadata ) => {
290
360
validateStringProperty ( { devConfig, property : 'framework' } )
291
361
292
- /** @type {Partial<import('./types').BaseServerSettings> } */
362
+ /** @type {Partial<import('./types.js ').BaseServerSettings> } */
293
363
let settings = { }
294
364
295
365
if ( options . dir || devConfig . framework === '#static' ) {
@@ -300,6 +370,19 @@ const detectServerSettings = async (devConfig, options, projectDir) => {
300
370
301
371
const runDetection = ! hasCommandAndTargetPort ( { devConfig } )
302
372
const frameworkSettings = runDetection ? await detectFrameworkSettings ( { projectDir } ) : undefined
373
+ const newSettings = runDetection ? await detectSettings ( projectDir ) : undefined
374
+
375
+ // just report differences in the settings
376
+ detectChangesInNewSettings ( frameworkSettings , newSettings || [ ] , {
377
+ ...metadata ,
378
+ settings : {
379
+ projectDir,
380
+ devConfig,
381
+ options,
382
+ old : frameworkSettings ,
383
+ settings : newSettings ,
384
+ } ,
385
+ } )
303
386
304
387
if ( frameworkSettings === undefined && runDetection ) {
305
388
log ( `${ NETLIFYDEVWARN } No app server detected. Using simple static server` )
@@ -368,7 +451,7 @@ const formatSettingsArrForInquirer = function (frameworks) {
368
451
* Returns a copy of the provided config with any plugins provided by the
369
452
* server settings
370
453
* @param {* } config
371
- * @param {Partial<import('./types').ServerSettings> } settings
454
+ * @param {Partial<import('./types.js ').ServerSettings> } settings
372
455
* @returns {* } Modified config
373
456
*/
374
457
export const getConfigWithPlugins = ( config , settings ) => {
0 commit comments