netlify-cli 17.3.2 → 17.4.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.
Files changed (210) hide show
  1. package/README.md +2 -138
  2. package/npm-shrinkwrap.json +76 -76
  3. package/package.json +16 -15
  4. package/src/commands/addons/addons-auth.mjs +27 -30
  5. package/src/commands/addons/addons-config.mjs +145 -154
  6. package/src/commands/addons/addons-create.mjs +94 -108
  7. package/src/commands/addons/addons-delete.mjs +36 -41
  8. package/src/commands/addons/addons-list.mjs +38 -42
  9. package/src/commands/addons/addons.mjs +26 -28
  10. package/src/commands/addons/index.mjs +1 -1
  11. package/src/commands/api/api.mjs +45 -53
  12. package/src/commands/api/index.mjs +1 -1
  13. package/src/commands/base-command.mjs +597 -684
  14. package/src/commands/blobs/blobs-delete.mjs +35 -0
  15. package/src/commands/blobs/blobs-get.mjs +44 -0
  16. package/src/commands/blobs/blobs-list.mjs +48 -0
  17. package/src/commands/blobs/blobs-set.mjs +54 -0
  18. package/src/commands/blobs/blobs.mjs +32 -0
  19. package/src/commands/blobs/index.mjs +1 -0
  20. package/src/commands/build/build.mjs +55 -67
  21. package/src/commands/build/index.mjs +1 -1
  22. package/src/commands/completion/completion.mjs +41 -46
  23. package/src/commands/completion/index.mjs +1 -1
  24. package/src/commands/deploy/deploy.mjs +675 -710
  25. package/src/commands/deploy/index.mjs +1 -1
  26. package/src/commands/dev/dev-exec.mjs +20 -32
  27. package/src/commands/dev/dev.mjs +217 -302
  28. package/src/commands/dev/index.mjs +1 -1
  29. package/src/commands/dev/types.d.ts +30 -0
  30. package/src/commands/env/env-clone.mjs +157 -184
  31. package/src/commands/env/env-get.mjs +49 -68
  32. package/src/commands/env/env-import.mjs +100 -119
  33. package/src/commands/env/env-list.mjs +104 -129
  34. package/src/commands/env/env-set.mjs +160 -185
  35. package/src/commands/env/env-unset.mjs +104 -122
  36. package/src/commands/env/env.mjs +28 -30
  37. package/src/commands/env/index.mjs +1 -1
  38. package/src/commands/functions/functions-build.mjs +29 -41
  39. package/src/commands/functions/functions-create.mjs +533 -601
  40. package/src/commands/functions/functions-invoke.mjs +193 -216
  41. package/src/commands/functions/functions-list.mjs +45 -55
  42. package/src/commands/functions/functions-serve.mjs +51 -61
  43. package/src/commands/functions/functions.mjs +26 -32
  44. package/src/commands/functions/index.mjs +1 -1
  45. package/src/commands/index.mjs +2 -2
  46. package/src/commands/init/index.mjs +1 -1
  47. package/src/commands/init/init.mjs +138 -167
  48. package/src/commands/integration/deploy.mjs +337 -399
  49. package/src/commands/integration/index.mjs +12 -13
  50. package/src/commands/link/index.mjs +1 -1
  51. package/src/commands/link/link.mjs +298 -317
  52. package/src/commands/lm/index.mjs +1 -1
  53. package/src/commands/lm/lm-info.mjs +23 -31
  54. package/src/commands/lm/lm-install.mjs +13 -17
  55. package/src/commands/lm/lm-setup.mjs +80 -84
  56. package/src/commands/lm/lm-uninstall.mjs +7 -12
  57. package/src/commands/lm/lm.mjs +18 -22
  58. package/src/commands/login/index.mjs +1 -1
  59. package/src/commands/login/login.mjs +35 -41
  60. package/src/commands/logout/index.mjs +1 -1
  61. package/src/commands/logout/logout.mjs +25 -31
  62. package/src/commands/main.mjs +166 -201
  63. package/src/commands/open/index.mjs +1 -1
  64. package/src/commands/open/open-admin.mjs +15 -18
  65. package/src/commands/open/open-site.mjs +16 -19
  66. package/src/commands/open/open.mjs +24 -27
  67. package/src/commands/recipes/common.mjs +23 -34
  68. package/src/commands/recipes/index.mjs +1 -1
  69. package/src/commands/recipes/recipes-list.mjs +13 -20
  70. package/src/commands/recipes/recipes.mjs +59 -72
  71. package/src/commands/serve/index.mjs +1 -1
  72. package/src/commands/serve/serve.mjs +142 -189
  73. package/src/commands/sites/index.mjs +2 -2
  74. package/src/commands/sites/sites-create-template.mjs +214 -236
  75. package/src/commands/sites/sites-create.mjs +145 -157
  76. package/src/commands/sites/sites-delete.mjs +75 -81
  77. package/src/commands/sites/sites-list.mjs +63 -66
  78. package/src/commands/sites/sites.mjs +18 -20
  79. package/src/commands/status/index.mjs +1 -1
  80. package/src/commands/status/status-hooks.mjs +32 -34
  81. package/src/commands/status/status.mjs +99 -106
  82. package/src/commands/switch/index.mjs +1 -1
  83. package/src/commands/switch/switch.mjs +32 -37
  84. package/src/commands/types.d.ts +31 -0
  85. package/src/commands/unlink/index.mjs +1 -1
  86. package/src/commands/unlink/unlink.mjs +23 -29
  87. package/src/commands/watch/index.mjs +1 -1
  88. package/src/commands/watch/watch.mjs +91 -105
  89. package/src/functions-templates/javascript/hello/{{name}}.js +2 -3
  90. package/src/lib/account.mjs +4 -5
  91. package/src/lib/api.mjs +22 -20
  92. package/src/lib/blobs/blobs.mjs +36 -45
  93. package/src/lib/build.mjs +82 -85
  94. package/src/lib/completion/constants.mjs +2 -4
  95. package/src/lib/completion/generate-autocompletion.mjs +33 -36
  96. package/src/lib/completion/get-autocompletion.mjs +31 -35
  97. package/src/lib/completion/index.mjs +1 -1
  98. package/src/lib/completion/script.mjs +12 -19
  99. package/src/lib/edge-functions/bootstrap.mjs +3 -5
  100. package/src/lib/edge-functions/consts.mjs +9 -10
  101. package/src/lib/edge-functions/deploy.mjs +28 -34
  102. package/src/lib/edge-functions/editor-helper.mjs +29 -42
  103. package/src/lib/edge-functions/headers.mjs +24 -26
  104. package/src/lib/edge-functions/internal.mjs +38 -44
  105. package/src/lib/edge-functions/proxy.mjs +229 -228
  106. package/src/lib/edge-functions/registry.mjs +473 -574
  107. package/src/lib/exec-fetcher.mjs +115 -122
  108. package/src/lib/fs.mjs +28 -27
  109. package/src/lib/functions/background.mjs +16 -20
  110. package/src/lib/functions/config.mjs +12 -9
  111. package/src/lib/functions/form-submissions-handler.mjs +143 -149
  112. package/src/lib/functions/local-proxy.mjs +40 -44
  113. package/src/lib/functions/memoized-build.mjs +19 -21
  114. package/src/lib/functions/netlify-function.mjs +269 -249
  115. package/src/lib/functions/registry.mjs +509 -568
  116. package/src/lib/functions/runtimes/go/index.mjs +62 -71
  117. package/src/lib/functions/runtimes/index.mjs +8 -15
  118. package/src/lib/functions/runtimes/js/builders/netlify-lambda.mjs +55 -64
  119. package/src/lib/functions/runtimes/js/builders/zisi.mjs +135 -154
  120. package/src/lib/functions/runtimes/js/constants.mjs +1 -1
  121. package/src/lib/functions/runtimes/js/index.mjs +92 -109
  122. package/src/lib/functions/runtimes/js/worker.mjs +43 -45
  123. package/src/lib/functions/runtimes/rust/index.mjs +64 -73
  124. package/src/lib/functions/scheduled.mjs +70 -88
  125. package/src/lib/functions/server.mjs +269 -327
  126. package/src/lib/functions/synchronous.mjs +118 -147
  127. package/src/lib/functions/utils.mjs +38 -46
  128. package/src/lib/geo-location.mjs +69 -81
  129. package/src/lib/http-agent.mjs +87 -90
  130. package/src/lib/images/proxy.mjs +97 -99
  131. package/src/lib/log.mjs +6 -9
  132. package/src/lib/path.mjs +2 -1
  133. package/src/lib/render-error-template.mjs +19 -20
  134. package/src/lib/settings.mjs +17 -19
  135. package/src/lib/spinner.mjs +21 -23
  136. package/src/lib/string.mjs +4 -2
  137. package/src/recipes/vscode/index.mjs +69 -85
  138. package/src/recipes/vscode/settings.mjs +53 -58
  139. package/src/utils/addons/compare.mjs +31 -32
  140. package/src/utils/addons/diffs/index.mjs +16 -17
  141. package/src/utils/addons/diffs/options.mjs +99 -101
  142. package/src/utils/addons/prepare.mjs +100 -97
  143. package/src/utils/addons/prompts.mjs +73 -76
  144. package/src/utils/addons/render.mjs +33 -36
  145. package/src/utils/addons/validation.mjs +19 -15
  146. package/src/utils/banner.mjs +11 -16
  147. package/src/utils/build-info.mjs +65 -66
  148. package/src/utils/command-helpers.mjs +185 -199
  149. package/src/utils/create-deferred.mjs +9 -12
  150. package/src/utils/create-stream-promise.mjs +54 -47
  151. package/src/utils/deploy/constants.mjs +9 -11
  152. package/src/utils/deploy/deploy-site.mjs +162 -182
  153. package/src/utils/deploy/hash-config.mjs +21 -21
  154. package/src/utils/deploy/hash-files.mjs +34 -38
  155. package/src/utils/deploy/hash-fns.mjs +149 -154
  156. package/src/utils/deploy/hasher-segments.mjs +58 -52
  157. package/src/utils/deploy/upload-files.mjs +99 -113
  158. package/src/utils/deploy/util.mjs +85 -91
  159. package/src/utils/detect-server-settings.mjs +236 -268
  160. package/src/utils/dev.mjs +163 -178
  161. package/src/utils/dot-env.mjs +37 -42
  162. package/src/utils/env/index.mjs +148 -148
  163. package/src/utils/execa.mjs +9 -13
  164. package/src/utils/feature-flags.mjs +6 -5
  165. package/src/utils/framework-server.mjs +43 -52
  166. package/src/utils/functions/constants.mjs +1 -1
  167. package/src/utils/functions/functions.mjs +30 -40
  168. package/src/utils/functions/get-functions.mjs +28 -29
  169. package/src/utils/functions/index.mjs +3 -3
  170. package/src/utils/get-global-config.mjs +33 -36
  171. package/src/utils/get-package-json.mjs +14 -15
  172. package/src/utils/get-repo-data.mjs +54 -64
  173. package/src/utils/get-site.mjs +14 -14
  174. package/src/utils/gh-auth.mjs +79 -100
  175. package/src/utils/gitignore.mjs +37 -40
  176. package/src/utils/headers.mjs +33 -35
  177. package/src/utils/hooks/requires-site-info.mjs +26 -22
  178. package/src/utils/init/config-github.mjs +207 -219
  179. package/src/utils/init/config-manual.mjs +83 -100
  180. package/src/utils/init/config.mjs +25 -26
  181. package/src/utils/init/node-version.mjs +23 -30
  182. package/src/utils/init/plugins.mjs +12 -8
  183. package/src/utils/init/utils.mjs +152 -172
  184. package/src/utils/live-tunnel.mjs +118 -141
  185. package/src/utils/lm/install.mjs +220 -259
  186. package/src/utils/lm/requirements.mjs +54 -63
  187. package/src/utils/lm/steps.mjs +31 -31
  188. package/src/utils/lm/ui.mjs +13 -20
  189. package/src/utils/open-browser.mjs +31 -32
  190. package/src/utils/parse-raw-flags.mjs +39 -35
  191. package/src/utils/proxy-server.mjs +84 -71
  192. package/src/utils/proxy.mjs +696 -750
  193. package/src/utils/read-repo-url.mjs +48 -47
  194. package/src/utils/redirects.mjs +49 -49
  195. package/src/utils/request-id.mjs +2 -4
  196. package/src/utils/rules-proxy.mjs +96 -100
  197. package/src/utils/run-build.mjs +109 -132
  198. package/src/utils/shell.mjs +99 -106
  199. package/src/utils/sign-redirect.mjs +14 -14
  200. package/src/utils/sites/utils.mjs +48 -55
  201. package/src/utils/state-config.mjs +101 -101
  202. package/src/utils/static-server.mjs +28 -34
  203. package/src/utils/telemetry/index.mjs +2 -2
  204. package/src/utils/telemetry/report-error.mjs +45 -49
  205. package/src/utils/telemetry/request.mjs +36 -43
  206. package/src/utils/telemetry/telemetry.mjs +90 -105
  207. package/src/utils/telemetry/utils.mjs +5 -6
  208. package/src/utils/telemetry/validation.mjs +55 -53
  209. package/src/utils/types.d.ts +46 -0
  210. package/src/utils/validation.mjs +10 -13
@@ -1,135 +1,113 @@
1
- // @ts-check
2
- import { readFile } from 'fs/promises'
3
- import { EOL } from 'os'
4
- import { dirname, relative, resolve } from 'path'
5
-
6
- import { getFramework, getSettings } from '@netlify/build-info'
7
- import getPort from 'get-port'
8
-
9
- import { detectFrameworkSettings } from './build-info.mjs'
10
- import { NETLIFYDEVWARN, chalk, log } from './command-helpers.mjs'
11
- import { acquirePort } from './dev.mjs'
12
- import { getInternalFunctionsDir } from './functions/functions.mjs'
13
- import { getPluginsToAutoInstall } from './init/utils.mjs'
14
-
1
+ import { readFile } from 'fs/promises';
2
+ import { EOL } from 'os';
3
+ import { dirname, relative, resolve } from 'path';
4
+ import { getFramework, getSettings } from '@netlify/build-info';
5
+ import getPort from 'get-port';
6
+ import { detectFrameworkSettings } from './build-info.mjs';
7
+ import { NETLIFYDEVWARN, chalk, log } from './command-helpers.mjs';
8
+ import { acquirePort } from './dev.mjs';
9
+ import { getInternalFunctionsDir } from './functions/functions.mjs';
10
+ import { getPluginsToAutoInstall } from './init/utils.mjs';
15
11
  /** @param {string} str */
16
- const formatProperty = (str) => chalk.magenta(`'${str}'`)
12
+ // @ts-expect-error TS(7006) FIXME: Parameter 'str' implicitly has an 'any' type.
13
+ const formatProperty = (str) => chalk.magenta(`'${str}'`);
17
14
  /** @param {string} str */
18
- const formatValue = (str) => chalk.green(`'${str}'`)
19
-
15
+ // @ts-expect-error TS(7006) FIXME: Parameter 'str' implicitly has an 'any' type.
16
+ const formatValue = (str) => chalk.green(`'${str}'`);
20
17
  /**
21
18
  * @param {object} options
22
19
  * @param {string} options.keyFile
23
20
  * @param {string} options.certFile
24
21
  * @returns {Promise<{ key: string, cert: string, keyFilePath: string, certFilePath: string }>}
25
22
  */
23
+ // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
26
24
  const readHttpsSettings = async (options) => {
27
- if (typeof options !== 'object' || !options.keyFile || !options.certFile) {
28
- throw new TypeError(
29
- `https options should be an object with ${formatProperty('keyFile')} and ${formatProperty(
30
- 'certFile',
31
- )} string properties`,
32
- )
33
- }
34
-
35
- const { certFile, keyFile } = options
36
- if (typeof keyFile !== 'string') {
37
- throw new TypeError(`Private key file configuration should be a string`)
38
- }
39
- if (typeof certFile !== 'string') {
40
- throw new TypeError(`Certificate file configuration should be a string`)
41
- }
42
-
43
- const [key, cert] = await Promise.allSettled([readFile(keyFile, 'utf-8'), readFile(certFile, 'utf-8')])
44
-
45
- if (key.status === 'rejected') {
46
- throw new Error(`Error reading private key file: ${key.reason}`)
47
- }
48
- if (cert.status === 'rejected') {
49
- throw new Error(`Error reading certificate file: ${cert.reason}`)
50
- }
51
-
52
- return { key: key.value, cert: cert.value, keyFilePath: resolve(keyFile), certFilePath: resolve(certFile) }
53
- }
54
-
25
+ if (typeof options !== 'object' || !options.keyFile || !options.certFile) {
26
+ throw new TypeError(`https options should be an object with ${formatProperty('keyFile')} and ${formatProperty('certFile')} string properties`);
27
+ }
28
+ const { certFile, keyFile } = options;
29
+ if (typeof keyFile !== 'string') {
30
+ throw new TypeError(`Private key file configuration should be a string`);
31
+ }
32
+ if (typeof certFile !== 'string') {
33
+ throw new TypeError(`Certificate file configuration should be a string`);
34
+ }
35
+ const [key, cert] = await Promise.allSettled([readFile(keyFile, 'utf-8'), readFile(certFile, 'utf-8')]);
36
+ if (key.status === 'rejected') {
37
+ throw new Error(`Error reading private key file: ${key.reason}`);
38
+ }
39
+ if (cert.status === 'rejected') {
40
+ throw new Error(`Error reading certificate file: ${cert.reason}`);
41
+ }
42
+ return { key: key.value, cert: cert.value, keyFilePath: resolve(keyFile), certFilePath: resolve(certFile) };
43
+ };
55
44
  /**
56
45
  * Validates a property inside the devConfig to be of a given type
57
46
  * @param {import('../commands/dev/types.js').DevConfig} devConfig The devConfig
58
47
  * @param {keyof import('../commands/dev/types.js').DevConfig} property The property to validate
59
48
  * @param {'string' | 'number'} type The type it should have
60
49
  */
50
+ // @ts-expect-error TS(7006) FIXME: Parameter 'devConfig' implicitly has an 'any' type... Remove this comment to see the full error message
61
51
  function validateProperty(devConfig, property, type) {
62
- // eslint-disable-next-line valid-typeof
63
- if (devConfig[property] && typeof devConfig[property] !== type) {
64
- const formattedProperty = formatProperty(property)
65
- throw new TypeError(
66
- `Invalid ${formattedProperty} option provided in config. The value of ${formattedProperty} option must be of type ${type}`,
67
- )
68
- }
52
+ // eslint-disable-next-line valid-typeof
53
+ if (devConfig[property] && typeof devConfig[property] !== type) {
54
+ const formattedProperty = formatProperty(property);
55
+ throw new TypeError(`Invalid ${formattedProperty} option provided in config. The value of ${formattedProperty} option must be of type ${type}`);
56
+ }
69
57
  }
70
-
71
58
  /**
72
59
  *
73
60
  * @param {object} config
74
61
  * @param {import('../commands/dev/types.js').DevConfig} config.devConfig
75
62
  */
63
+ // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
76
64
  const validateFrameworkConfig = ({ devConfig }) => {
77
- validateProperty(devConfig, 'command', 'string')
78
- validateProperty(devConfig, 'port', 'number')
79
- validateProperty(devConfig, 'targetPort', 'number')
80
-
81
- if (devConfig.targetPort && devConfig.targetPort === devConfig.port) {
82
- throw new Error(
83
- `${formatProperty('port')} and ${formatProperty(
84
- 'targetPort',
85
- )} options cannot have same values. Please consult the documentation for more details: https://cli.netlify.com/netlify-dev#netlifytoml-dev-block`,
86
- )
87
- }
88
- }
89
-
65
+ validateProperty(devConfig, 'command', 'string');
66
+ validateProperty(devConfig, 'port', 'number');
67
+ validateProperty(devConfig, 'targetPort', 'number');
68
+ if (devConfig.targetPort && devConfig.targetPort === devConfig.port) {
69
+ throw new Error(`${formatProperty('port')} and ${formatProperty('targetPort')} options cannot have same values. Please consult the documentation for more details: https://ntl.fyi/ports-and-netlify-dev`);
70
+ }
71
+ };
90
72
  /**
91
73
  * @param {object} config
92
74
  * @param {import('../commands/dev/types.js').DevConfig} config.devConfig
93
75
  * @param {number=} config.detectedPort
94
76
  */
77
+ // @ts-expect-error TS(7031) FIXME: Binding element 'detectedPort' implicitly has an '... Remove this comment to see the full error message
95
78
  const validateConfiguredPort = ({ detectedPort, devConfig }) => {
96
- if (devConfig.port && devConfig.port === detectedPort) {
97
- const formattedPort = formatProperty('port')
98
- throw new Error(
99
- `The ${formattedPort} option you specified conflicts with the port of your application. Please use a different value for ${formattedPort}`,
100
- )
101
- }
102
- }
103
-
104
- const DEFAULT_PORT = 8888
105
- const DEFAULT_STATIC_PORT = 3999
106
-
79
+ if (devConfig.port && devConfig.port === detectedPort) {
80
+ const formattedPort = formatProperty('port');
81
+ throw new Error(`The ${formattedPort} option you specified conflicts with the port of your application. Please use a different value for ${formattedPort}`);
82
+ }
83
+ };
84
+ const DEFAULT_PORT = 8888;
85
+ const DEFAULT_STATIC_PORT = 3999;
107
86
  /**
108
87
  * Logs a message that it was unable to determine the dist directory and falls back to the workingDir
109
88
  * @param {string} workingDir
110
89
  */
90
+ // @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message
111
91
  const getDefaultDist = (workingDir) => {
112
- log(`${NETLIFYDEVWARN} Unable to determine public folder to serve files from. Using current working directory`)
113
- log(`${NETLIFYDEVWARN} Setup a netlify.toml file with a [dev] section to specify your dev server settings.`)
114
- log(`${NETLIFYDEVWARN} See docs at: https://cli.netlify.com/netlify-dev#project-detection`)
115
- return workingDir
116
- }
117
-
92
+ log(`${NETLIFYDEVWARN} Unable to determine public folder to serve files from. Using current working directory`);
93
+ log(`${NETLIFYDEVWARN} Setup a netlify.toml file with a [dev] section to specify your dev server settings.`);
94
+ log(`${NETLIFYDEVWARN} See docs at: https://cli.netlify.com/netlify-dev#project-detection`);
95
+ return workingDir;
96
+ };
118
97
  /**
119
98
  * @param {object} config
120
99
  * @param {import('../commands/dev/types.js').DevConfig} config.devConfig
121
100
  * @returns {Promise<number>}
122
101
  */
102
+ // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
123
103
  const getStaticServerPort = async ({ devConfig }) => {
124
- const port = await acquirePort({
125
- configuredPort: devConfig.staticServerPort,
126
- defaultPort: DEFAULT_STATIC_PORT,
127
- errorMessage: 'Could not acquire configured static server port',
128
- })
129
-
130
- return port
131
- }
132
-
104
+ const port = await acquirePort({
105
+ configuredPort: devConfig.staticServerPort,
106
+ defaultPort: DEFAULT_STATIC_PORT,
107
+ errorMessage: 'Could not acquire configured static server port',
108
+ });
109
+ return port;
110
+ };
133
111
  /**
134
112
  *
135
113
  * @param {object} config
@@ -138,65 +116,54 @@ const getStaticServerPort = async ({ devConfig }) => {
138
116
  * @param {string} config.workingDir
139
117
  * @returns {Promise<Omit<import('./types.js').BaseServerSettings, 'command'> & {command?: string}>}
140
118
  */
119
+ // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
141
120
  const handleStaticServer = async ({ devConfig, flags, workingDir }) => {
142
- validateProperty(devConfig, 'staticServerPort', 'number')
143
-
144
- if (flags.dir) {
145
- log(`${NETLIFYDEVWARN} Using simple static server because ${formatProperty('--dir')} flag was specified`)
146
- } else if (devConfig.framework === '#static') {
147
- log(
148
- `${NETLIFYDEVWARN} Using simple static server because ${formatProperty(
149
- '[dev.framework]',
150
- )} was set to ${formatValue('#static')}`,
151
- )
152
- }
153
-
154
- if (devConfig.targetPort) {
155
- log(
156
- `${NETLIFYDEVWARN} Ignoring ${formatProperty(
157
- 'targetPort',
158
- )} setting since using a simple static server.${EOL}${NETLIFYDEVWARN} Use --staticServerPort or [dev.staticServerPort] to configure the static server port`,
159
- )
160
- }
161
-
162
- const dist = flags.dir || devConfig.publish || getDefaultDist(workingDir)
163
- log(`${NETLIFYDEVWARN} Running static server from "${relative(dirname(workingDir), dist)}"`)
164
-
165
- const frameworkPort = await getStaticServerPort({ devConfig })
166
- return {
167
- ...(devConfig.command && { command: devConfig.command }),
168
- useStaticServer: true,
169
- frameworkPort,
170
- dist,
171
- }
172
- }
173
-
121
+ validateProperty(devConfig, 'staticServerPort', 'number');
122
+ if (flags.dir) {
123
+ log(`${NETLIFYDEVWARN} Using simple static server because ${formatProperty('--dir')} flag was specified`);
124
+ }
125
+ else if (devConfig.framework === '#static') {
126
+ log(`${NETLIFYDEVWARN} Using simple static server because ${formatProperty('[dev.framework]')} was set to ${formatValue('#static')}`);
127
+ }
128
+ if (devConfig.targetPort) {
129
+ log(`${NETLIFYDEVWARN} Ignoring ${formatProperty('targetPort')} setting since using a simple static server.${EOL}${NETLIFYDEVWARN} Use --staticServerPort or [dev.staticServerPort] to configure the static server port`);
130
+ }
131
+ const dist = flags.dir || devConfig.publish || getDefaultDist(workingDir);
132
+ log(`${NETLIFYDEVWARN} Running static server from "${relative(dirname(workingDir), dist)}"`);
133
+ const frameworkPort = await getStaticServerPort({ devConfig });
134
+ return {
135
+ ...(devConfig.command && { command: devConfig.command }),
136
+ useStaticServer: true,
137
+ frameworkPort,
138
+ dist,
139
+ };
140
+ };
174
141
  /**
175
142
  * Retrieves the settings from a framework
176
143
  * @param {import('@netlify/build-info').Settings} [settings]
177
144
  * @returns {import('./types.js').BaseServerSettings | undefined}
178
145
  */
146
+ // @ts-expect-error TS(7006) FIXME: Parameter 'settings' implicitly has an 'any' type.
179
147
  const getSettingsFromDetectedSettings = (settings) => {
180
- if (!settings) {
181
- return
182
- }
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),
192
- }
193
- }
194
-
148
+ if (!settings) {
149
+ return;
150
+ }
151
+ return {
152
+ baseDirectory: settings.baseDirectory,
153
+ command: settings.devCommand,
154
+ frameworkPort: settings.frameworkPort,
155
+ dist: settings.dist,
156
+ framework: settings.framework.name,
157
+ env: settings.env,
158
+ pollingStrategies: settings.pollingStrategies,
159
+ plugins: getPluginsToAutoInstall(settings.plugins_from_config_file, settings.plugins_recommended),
160
+ };
161
+ };
195
162
  /**
196
163
  * @param {import('../commands/dev/types.js').DevConfig} devConfig
197
164
  */
198
- const hasCommandAndTargetPort = (devConfig) => devConfig.command && devConfig.targetPort
199
-
165
+ // @ts-expect-error TS(7006) FIXME: Parameter 'devConfig' implicitly has an 'any' type... Remove this comment to see the full error message
166
+ const hasCommandAndTargetPort = (devConfig) => devConfig.command && devConfig.targetPort;
200
167
  /**
201
168
  * Creates settings for the custom framework
202
169
  * @param {object} config
@@ -204,23 +171,19 @@ const hasCommandAndTargetPort = (devConfig) => devConfig.command && devConfig.ta
204
171
  * @param {string} config.workingDir
205
172
  * @returns {import('./types.js').BaseServerSettings}
206
173
  */
174
+ // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
207
175
  const handleCustomFramework = ({ devConfig, workingDir }) => {
208
- if (!hasCommandAndTargetPort(devConfig)) {
209
- throw new Error(
210
- `${formatProperty('command')} and ${formatProperty('targetPort')} properties are required when ${formatProperty(
211
- 'framework',
212
- )} is set to ${formatValue('#custom')}`,
213
- )
214
- }
215
- return {
216
- command: devConfig.command,
217
- frameworkPort: devConfig.targetPort,
218
- dist: devConfig.publish || getDefaultDist(workingDir),
219
- framework: '#custom',
220
- pollingStrategies: devConfig.pollingStrategies || [],
221
- }
222
- }
223
-
176
+ if (!hasCommandAndTargetPort(devConfig)) {
177
+ throw new Error(`${formatProperty('command')} and ${formatProperty('targetPort')} properties are required when ${formatProperty('framework')} is set to ${formatValue('#custom')}`);
178
+ }
179
+ return {
180
+ command: devConfig.command,
181
+ frameworkPort: devConfig.targetPort,
182
+ dist: devConfig.publish || getDefaultDist(workingDir),
183
+ framework: '#custom',
184
+ pollingStrategies: devConfig.pollingStrategies || [],
185
+ };
186
+ };
224
187
  /**
225
188
  * Merges the framework settings with the devConfig
226
189
  * @param {object} config
@@ -228,23 +191,30 @@ const handleCustomFramework = ({ devConfig, workingDir }) => {
228
191
  * @param {string} config.workingDir
229
192
  * @param {Partial<import('./types.js').BaseServerSettings>=} config.frameworkSettings
230
193
  */
194
+ // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
231
195
  const mergeSettings = async ({ devConfig, frameworkSettings = {}, workingDir }) => {
232
- const command = devConfig.command || frameworkSettings.command
233
- const frameworkPort = devConfig.targetPort || frameworkSettings.frameworkPort
234
- // if the framework doesn't start a server, we use a static one
235
- const useStaticServer = !(command && frameworkPort)
236
- return {
237
- baseDirectory: devConfig.base || frameworkSettings.baseDirectory,
238
- command,
239
- frameworkPort: useStaticServer ? await getStaticServerPort({ devConfig }) : frameworkPort,
240
- dist: devConfig.publish || frameworkSettings.dist || getDefaultDist(workingDir),
241
- framework: frameworkSettings.framework,
242
- env: frameworkSettings.env,
243
- pollingStrategies: frameworkSettings.pollingStrategies || [],
244
- useStaticServer,
245
- }
246
- }
247
-
196
+ // @ts-expect-error TS(2339) FIXME: Property 'command' does not exist on type '{}'.
197
+ const command = devConfig.command || frameworkSettings.command;
198
+ // @ts-expect-error TS(2339) FIXME: Property 'frameworkPort' does not exist on type '{... Remove this comment to see the full error message
199
+ const frameworkPort = devConfig.targetPort || frameworkSettings.frameworkPort;
200
+ // if the framework doesn't start a server, we use a static one
201
+ const useStaticServer = !(command && frameworkPort);
202
+ return {
203
+ // @ts-expect-error TS(2339) FIXME: Property 'baseDirectory' does not exist on type '{... Remove this comment to see the full error message
204
+ baseDirectory: devConfig.base || frameworkSettings.baseDirectory,
205
+ command,
206
+ frameworkPort: useStaticServer ? await getStaticServerPort({ devConfig }) : frameworkPort,
207
+ // @ts-expect-error TS(2339) FIXME: Property 'dist' does not exist on type '{}'.
208
+ dist: devConfig.publish || frameworkSettings.dist || getDefaultDist(workingDir),
209
+ // @ts-expect-error TS(2339) FIXME: Property 'framework' does not exist on type '{}'.
210
+ framework: frameworkSettings.framework,
211
+ // @ts-expect-error TS(2339) FIXME: Property 'env' does not exist on type '{}'.
212
+ env: frameworkSettings.env,
213
+ // @ts-expect-error TS(2339) FIXME: Property 'pollingStrategies' does not exist on typ... Remove this comment to see the full error message
214
+ pollingStrategies: frameworkSettings.pollingStrategies || [],
215
+ useStaticServer,
216
+ };
217
+ };
248
218
  /**
249
219
  * Handles a forced framework and retrieves the settings for it
250
220
  * @param {object} config
@@ -254,14 +224,14 @@ const mergeSettings = async ({ devConfig, frameworkSettings = {}, workingDir })
254
224
  * @param {string=} config.workspacePackage
255
225
  * @returns {Promise<import('./types.js').BaseServerSettings>}
256
226
  */
227
+ // @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message
257
228
  const handleForcedFramework = async ({ devConfig, project, workingDir, workspacePackage }) => {
258
- // this throws if `devConfig.framework` is not a supported framework
259
- const framework = await getFramework(devConfig.framework, project)
260
- const settings = await getSettings(framework, project, workspacePackage || '')
261
- const frameworkSettings = getSettingsFromDetectedSettings(settings)
262
- return mergeSettings({ devConfig, workingDir, frameworkSettings })
263
- }
264
-
229
+ // this throws if `devConfig.framework` is not a supported framework
230
+ const framework = await getFramework(devConfig.framework, project);
231
+ const settings = await getSettings(framework, project, workspacePackage || '');
232
+ const frameworkSettings = getSettingsFromDetectedSettings(settings);
233
+ return mergeSettings({ devConfig, workingDir, frameworkSettings });
234
+ };
265
235
  /**
266
236
  * Get the server settings based on the flags and the devConfig
267
237
  * @param {import('../commands/dev/types.js').DevConfig} devConfig
@@ -269,70 +239,69 @@ const handleForcedFramework = async ({ devConfig, project, workingDir, workspace
269
239
  * @param {import('../commands/base-command.mjs').default} command
270
240
  * @returns {Promise<import('./types.js').ServerSettings>}
271
241
  */
272
-
242
+ // @ts-expect-error TS(7006) FIXME: Parameter 'devConfig' implicitly has an 'any' type... Remove this comment to see the full error message
273
243
  const detectServerSettings = async (devConfig, flags, command) => {
274
- validateProperty(devConfig, 'framework', 'string')
275
-
276
- /** @type {Partial<import('./types.js').BaseServerSettings>} */
277
- let settings = {}
278
-
279
- if (flags.dir || devConfig.framework === '#static') {
280
- // serving files statically without a framework server
281
- settings = await handleStaticServer({ flags, devConfig, workingDir: command.workingDir })
282
- } else if (devConfig.framework === '#auto') {
283
- // this is the default CLI behavior
284
-
285
- const runDetection = !hasCommandAndTargetPort(devConfig)
286
- const frameworkSettings = runDetection
287
- ? getSettingsFromDetectedSettings(await detectFrameworkSettings(command, 'dev'))
288
- : undefined
289
- if (frameworkSettings === undefined && runDetection) {
290
- log(`${NETLIFYDEVWARN} No app server detected. Using simple static server`)
291
- settings = await handleStaticServer({ flags, devConfig, workingDir: command.workingDir })
292
- } else {
293
- validateFrameworkConfig({ devConfig })
294
-
295
- settings = await mergeSettings({ devConfig, frameworkSettings, workingDir: command.workingDir })
244
+ validateProperty(devConfig, 'framework', 'string');
245
+ /** @type {Partial<import('./types.js').BaseServerSettings>} */
246
+ let settings = {};
247
+ if (flags.dir || devConfig.framework === '#static') {
248
+ // serving files statically without a framework server
249
+ settings = await handleStaticServer({ flags, devConfig, workingDir: command.workingDir });
296
250
  }
297
-
298
- settings.plugins = frameworkSettings?.plugins
299
- } else if (devConfig.framework === '#custom') {
300
- validateFrameworkConfig({ devConfig })
301
- // when the users wants to configure `command` and `targetPort`
302
- settings = handleCustomFramework({ devConfig, workingDir: command.workingDir })
303
- } else if (devConfig.framework) {
304
- validateFrameworkConfig({ devConfig })
305
- // this is when the user explicitly configures a framework, e.g. `framework = "gatsby"`
306
- settings = await handleForcedFramework({
307
- devConfig,
308
- project: command.project,
309
- workingDir: command.workingDir,
310
- workspacePackage: command.workspacePackage,
311
- })
312
- }
313
-
314
- validateConfiguredPort({ devConfig, detectedPort: settings.frameworkPort })
315
-
316
- const acquiredPort = await acquirePort({
317
- configuredPort: devConfig.port,
318
- defaultPort: DEFAULT_PORT,
319
- errorMessage: `Could not acquire required ${formatProperty('port')}`,
320
- })
321
- const functionsDir = devConfig.functions || settings.functions
322
- const internalFunctionsDir = await getInternalFunctionsDir({ base: command.workingDir })
323
- const shouldStartFunctionsServer = Boolean(functionsDir || internalFunctionsDir)
324
-
325
- return {
326
- ...settings,
327
- port: acquiredPort,
328
- jwtSecret: devConfig.jwtSecret || 'secret',
329
- jwtRolePath: devConfig.jwtRolePath || 'app_metadata.authorization.roles',
330
- functions: functionsDir,
331
- ...(shouldStartFunctionsServer && { functionsPort: await getPort({ port: devConfig.functionsPort || 0 }) }),
332
- ...(devConfig.https && { https: await readHttpsSettings(devConfig.https) }),
333
- }
334
- }
335
-
251
+ else if (devConfig.framework === '#auto') {
252
+ // this is the default CLI behavior
253
+ const runDetection = !hasCommandAndTargetPort(devConfig);
254
+ const frameworkSettings = runDetection
255
+ ? getSettingsFromDetectedSettings(await detectFrameworkSettings(command, 'dev'))
256
+ : undefined;
257
+ if (frameworkSettings === undefined && runDetection) {
258
+ log(`${NETLIFYDEVWARN} No app server detected. Using simple static server`);
259
+ settings = await handleStaticServer({ flags, devConfig, workingDir: command.workingDir });
260
+ }
261
+ else {
262
+ validateFrameworkConfig({ devConfig });
263
+ settings = await mergeSettings({ devConfig, frameworkSettings, workingDir: command.workingDir });
264
+ }
265
+ // @ts-expect-error TS(2339) FIXME: Property 'plugins' does not exist on type '{}'.
266
+ settings.plugins = frameworkSettings?.plugins;
267
+ }
268
+ else if (devConfig.framework === '#custom') {
269
+ validateFrameworkConfig({ devConfig });
270
+ // when the users wants to configure `command` and `targetPort`
271
+ settings = handleCustomFramework({ devConfig, workingDir: command.workingDir });
272
+ }
273
+ else if (devConfig.framework) {
274
+ validateFrameworkConfig({ devConfig });
275
+ // this is when the user explicitly configures a framework, e.g. `framework = "gatsby"`
276
+ settings = await handleForcedFramework({
277
+ devConfig,
278
+ project: command.project,
279
+ workingDir: command.workingDir,
280
+ workspacePackage: command.workspacePackage,
281
+ });
282
+ }
283
+ // @ts-expect-error TS(2339) FIXME: Property 'frameworkPort' does not exist on type '{... Remove this comment to see the full error message
284
+ validateConfiguredPort({ devConfig, detectedPort: settings.frameworkPort });
285
+ const acquiredPort = await acquirePort({
286
+ configuredPort: devConfig.port,
287
+ defaultPort: DEFAULT_PORT,
288
+ errorMessage: `Could not acquire required ${formatProperty('port')}`,
289
+ });
290
+ // @ts-expect-error TS(2339) FIXME: Property 'functions' does not exist on type '{}'.
291
+ const functionsDir = devConfig.functions || settings.functions;
292
+ // @ts-expect-error TS(2345) FIXME: Argument of type '{ base: any; }' is not assignabl... Remove this comment to see the full error message
293
+ const internalFunctionsDir = await getInternalFunctionsDir({ base: command.workingDir });
294
+ const shouldStartFunctionsServer = Boolean(functionsDir || internalFunctionsDir);
295
+ return {
296
+ ...settings,
297
+ port: acquiredPort,
298
+ jwtSecret: devConfig.jwtSecret || 'secret',
299
+ jwtRolePath: devConfig.jwtRolePath || 'app_metadata.authorization.roles',
300
+ functions: functionsDir,
301
+ ...(shouldStartFunctionsServer && { functionsPort: await getPort({ port: devConfig.functionsPort || 0 }) }),
302
+ ...(devConfig.https && { https: await readHttpsSettings(devConfig.https) }),
303
+ };
304
+ };
336
305
  /**
337
306
  * Returns a copy of the provided config with any plugins provided by the
338
307
  * server settings
@@ -340,31 +309,30 @@ const detectServerSettings = async (devConfig, flags, command) => {
340
309
  * @param {Partial<import('./types.js').ServerSettings>} settings
341
310
  * @returns {*} Modified config
342
311
  */
312
+ // @ts-expect-error TS(7006) FIXME: Parameter 'config' implicitly has an 'any' type.
343
313
  export const getConfigWithPlugins = (config, settings) => {
344
- if (!settings.plugins) {
345
- return config
346
- }
347
-
348
- // If there are plugins that we should be running for this site, add them
349
- // to the config as if they were declared in netlify.toml. We must check
350
- // whether the plugin has already been added by another source (like the
351
- // TOML file or the UI), as we don't want to run the same plugin twice.
352
- const { plugins: existingPlugins = [] } = config
353
- const existingPluginNames = new Set(existingPlugins.map((plugin) => plugin.package))
354
- const newPlugins = settings.plugins
355
- .map((pluginName) => {
356
- if (existingPluginNames.has(pluginName)) {
357
- return
358
- }
359
-
360
- return { package: pluginName, origin: 'config', inputs: {} }
314
+ if (!settings.plugins) {
315
+ return config;
316
+ }
317
+ // If there are plugins that we should be running for this site, add them
318
+ // to the config as if they were declared in netlify.toml. We must check
319
+ // whether the plugin has already been added by another source (like the
320
+ // TOML file or the UI), as we don't want to run the same plugin twice.
321
+ const { plugins: existingPlugins = [] } = config;
322
+ // @ts-expect-error TS(7006) FIXME: Parameter 'plugin' implicitly has an 'any' type.
323
+ const existingPluginNames = new Set(existingPlugins.map((plugin) => plugin.package));
324
+ const newPlugins = settings.plugins
325
+ // @ts-expect-error TS(7006) FIXME: Parameter 'pluginName' implicitly has an 'any' typ... Remove this comment to see the full error message
326
+ .map((pluginName) => {
327
+ if (existingPluginNames.has(pluginName)) {
328
+ return;
329
+ }
330
+ return { package: pluginName, origin: 'config', inputs: {} };
361
331
  })
362
- .filter(Boolean)
363
-
364
- return {
365
- ...config,
366
- plugins: [...newPlugins, ...config.plugins],
367
- }
368
- }
369
-
370
- export default detectServerSettings
332
+ .filter(Boolean);
333
+ return {
334
+ ...config,
335
+ plugins: [...newPlugins, ...config.plugins],
336
+ };
337
+ };
338
+ export default detectServerSettings;