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,13 +1,9 @@
1
- // @ts-check
2
- import { readFile } from 'fs/promises'
3
-
4
- import AsciiTable from 'ascii-table'
5
- import { Option } from 'commander'
6
- import dotenv from 'dotenv'
7
-
8
- import { exit, log, logJson } from '../../utils/command-helpers.mjs'
9
- import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../../utils/env/index.mjs'
10
-
1
+ import { readFile } from 'fs/promises';
2
+ import AsciiTable from 'ascii-table';
3
+ import { Option } from 'commander';
4
+ import dotenv from 'dotenv';
5
+ import { exit, log, logJson } from '../../utils/command-helpers.mjs';
6
+ import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../../utils/env/index.mjs';
11
7
  /**
12
8
  * The env:import command
13
9
  * @param {string} fileName .env file to import
@@ -15,132 +11,117 @@ import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../.
15
11
  * @param {import('../base-command.mjs').default} command
16
12
  * @returns {Promise<boolean>}
17
13
  */
14
+ // @ts-expect-error TS(7006) FIXME: Parameter 'fileName' implicitly has an 'any' type.
18
15
  const envImport = async (fileName, options, command) => {
19
- const { api, cachedConfig, site } = command.netlify
20
- const siteId = site.id
21
-
22
- if (!siteId) {
23
- log('No site id found, please run inside a site folder or `netlify link`')
24
- return false
25
- }
26
-
27
- let importedEnv = {}
28
- try {
29
- const envFileContents = await readFile(fileName, 'utf-8')
30
- importedEnv = dotenv.parse(envFileContents)
31
- } catch (error) {
32
- log(error.message)
33
- exit(1)
34
- }
35
-
36
- if (Object.keys(importedEnv).length === 0) {
37
- log(`No environment variables found in file ${fileName} to import`)
38
- return false
39
- }
40
-
41
- const { siteInfo } = cachedConfig
42
-
43
- const importIntoService = siteInfo.use_envelope ? importIntoEnvelope : importIntoMongo
44
- const finalEnv = await importIntoService({ api, importedEnv, options, siteInfo })
45
-
46
- // Return new environment variables of site if using json flag
47
- if (options.json) {
48
- logJson(finalEnv)
49
- return false
50
- }
51
-
52
- // List newly imported environment variables in a table
53
- log(`site: ${siteInfo.name}`)
54
- const table = new AsciiTable(`Imported environment variables`)
55
-
56
- table.setHeading('Key', 'Value')
57
- table.addRowMatrix(Object.entries(importedEnv))
58
- log(table.toString())
59
- }
60
-
16
+ const { api, cachedConfig, site } = command.netlify;
17
+ const siteId = site.id;
18
+ if (!siteId) {
19
+ log('No site id found, please run inside a site folder or `netlify link`');
20
+ return false;
21
+ }
22
+ let importedEnv = {};
23
+ try {
24
+ const envFileContents = await readFile(fileName, 'utf-8');
25
+ importedEnv = dotenv.parse(envFileContents);
26
+ }
27
+ catch (error) {
28
+ // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
29
+ log(error.message);
30
+ exit(1);
31
+ }
32
+ if (Object.keys(importedEnv).length === 0) {
33
+ log(`No environment variables found in file ${fileName} to import`);
34
+ return false;
35
+ }
36
+ const { siteInfo } = cachedConfig;
37
+ const importIntoService = siteInfo.use_envelope ? importIntoEnvelope : importIntoMongo;
38
+ const finalEnv = await importIntoService({ api, importedEnv, options, siteInfo });
39
+ // Return new environment variables of site if using json flag
40
+ if (options.json) {
41
+ logJson(finalEnv);
42
+ return false;
43
+ }
44
+ // List newly imported environment variables in a table
45
+ log(`site: ${siteInfo.name}`);
46
+ const table = new AsciiTable(`Imported environment variables`);
47
+ table.setHeading('Key', 'Value');
48
+ table.addRowMatrix(Object.entries(importedEnv));
49
+ log(table.toString());
50
+ };
61
51
  /**
62
52
  * Updates the imported env in the site record
63
53
  * @returns {Promise<object>}
64
54
  */
55
+ // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
65
56
  const importIntoMongo = async ({ api, importedEnv, options, siteInfo }) => {
66
- const { env = {} } = siteInfo.build_settings
67
- const siteId = siteInfo.id
68
-
69
- const finalEnv = options.replaceExisting ? importedEnv : { ...env, ...importedEnv }
70
-
71
- // Apply environment variable updates
72
- await api.updateSite({
73
- siteId,
74
- body: {
75
- build_settings: {
76
- // Only set imported variables if --replaceExisting or otherwise merge
77
- // imported ones with the current environment variables.
78
- env: finalEnv,
79
- },
80
- },
81
- })
82
-
83
- return finalEnv
84
- }
85
-
57
+ const { env = {} } = siteInfo.build_settings;
58
+ const siteId = siteInfo.id;
59
+ const finalEnv = options.replaceExisting ? importedEnv : { ...env, ...importedEnv };
60
+ // Apply environment variable updates
61
+ await api.updateSite({
62
+ siteId,
63
+ body: {
64
+ build_settings: {
65
+ // Only set imported variables if --replaceExisting or otherwise merge
66
+ // imported ones with the current environment variables.
67
+ env: finalEnv,
68
+ },
69
+ },
70
+ });
71
+ return finalEnv;
72
+ };
86
73
  /**
87
74
  * Saves the imported env in the Envelope service
88
75
  * @returns {Promise<object>}
89
76
  */
77
+ // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
90
78
  const importIntoEnvelope = async ({ api, importedEnv, options, siteInfo }) => {
91
- // fetch env vars
92
- const accountId = siteInfo.account_slug
93
- const siteId = siteInfo.id
94
- const dotEnvKeys = Object.keys(importedEnv)
95
- const envelopeVariables = await api.getEnvVars({ accountId, siteId })
96
- const envelopeKeys = envelopeVariables.map(({ key }) => key)
97
-
98
- // if user intends to replace all existing env vars
99
- // either replace; delete all existing env vars on the site
100
- // or, merge; delete only the existing env vars that would collide with new .env entries
101
- const keysToDelete = options.replaceExisting ? envelopeKeys : envelopeKeys.filter((key) => dotEnvKeys.includes(key))
102
-
103
- // delete marked env vars in parallel
104
- await Promise.all(keysToDelete.map((key) => api.deleteEnvVar({ accountId, siteId, key })))
105
-
106
- // hit create endpoint
107
- const body = translateFromMongoToEnvelope(importedEnv)
108
- try {
109
- await api.createEnvVars({ accountId, siteId, body })
110
- } catch (error) {
111
- throw error.json ? error.json.msg : error
112
- }
113
-
114
- // return final env to aid in --json output (for testing)
115
- return {
116
- ...translateFromEnvelopeToMongo(envelopeVariables.filter(({ key }) => !keysToDelete.includes(key))),
117
- ...importedEnv,
118
- }
119
- }
120
-
79
+ // fetch env vars
80
+ const accountId = siteInfo.account_slug;
81
+ const siteId = siteInfo.id;
82
+ const dotEnvKeys = Object.keys(importedEnv);
83
+ const envelopeVariables = await api.getEnvVars({ accountId, siteId });
84
+ // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
85
+ const envelopeKeys = envelopeVariables.map(({ key }) => key);
86
+ // if user intends to replace all existing env vars
87
+ // either replace; delete all existing env vars on the site
88
+ // or, merge; delete only the existing env vars that would collide with new .env entries
89
+ // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type.
90
+ const keysToDelete = options.replaceExisting ? envelopeKeys : envelopeKeys.filter((key) => dotEnvKeys.includes(key));
91
+ // delete marked env vars in parallel
92
+ // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type.
93
+ await Promise.all(keysToDelete.map((key) => api.deleteEnvVar({ accountId, siteId, key })));
94
+ // hit create endpoint
95
+ const body = translateFromMongoToEnvelope(importedEnv);
96
+ try {
97
+ await api.createEnvVars({ accountId, siteId, body });
98
+ }
99
+ catch (error) {
100
+ // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
101
+ throw error.json ? error.json.msg : error;
102
+ }
103
+ // return final env to aid in --json output (for testing)
104
+ return {
105
+ // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
106
+ ...translateFromEnvelopeToMongo(envelopeVariables.filter(({ key }) => !keysToDelete.includes(key))),
107
+ ...importedEnv,
108
+ };
109
+ };
121
110
  /**
122
111
  * Creates the `netlify env:import` command
123
112
  * @param {import('../base-command.mjs').default} program
124
113
  * @returns
125
114
  */
126
- export const createEnvImportCommand = (program) =>
127
- program
115
+ // @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type.
116
+ export const createEnvImportCommand = (program) => program
128
117
  .command('env:import')
129
118
  .argument('<fileName>', '.env file to import')
130
- .addOption(
131
- new Option(
132
- '-r --replaceExisting',
133
- 'Old, prefer --replace-existing. Replace all existing variables instead of merging them with the current ones',
134
- )
135
- .default(false)
136
- .hideHelp(true),
137
- )
138
- .option(
139
- '-r, --replace-existing',
140
- 'Replace all existing variables instead of merging them with the current ones',
141
- false,
142
- )
119
+ .addOption(new Option('-r --replaceExisting', 'Old, prefer --replace-existing. Replace all existing variables instead of merging them with the current ones')
120
+ .default(false)
121
+ .hideHelp(true))
122
+ .option('-r, --replace-existing', 'Replace all existing variables instead of merging them with the current ones', false)
143
123
  .description('Import and set environment variables from .env file')
124
+ // @ts-expect-error TS(7006) FIXME: Parameter 'fileName' implicitly has an 'any' type.
144
125
  .action(async (fileName, options, command) => {
145
- await envImport(fileName, options, command)
146
- })
126
+ await envImport(fileName, options, command);
127
+ });
@@ -1,154 +1,129 @@
1
- // @ts-check
2
- import ansiEscapes from 'ansi-escapes'
3
- import AsciiTable from 'ascii-table'
4
- import { isCI } from 'ci-info'
5
- import { Option } from 'commander'
6
- import inquirer from 'inquirer'
7
- import logUpdate from 'log-update'
8
-
9
- import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs'
10
- import { AVAILABLE_CONTEXTS, getEnvelopeEnv, getHumanReadableScopes, normalizeContext } from '../../utils/env/index.mjs'
11
-
12
- const MASK_LENGTH = 50
13
- const MASK = '*'.repeat(MASK_LENGTH)
14
-
1
+ import ansiEscapes from 'ansi-escapes';
2
+ import AsciiTable from 'ascii-table';
3
+ import { isCI } from 'ci-info';
4
+ import { Option } from 'commander';
5
+ import inquirer from 'inquirer';
6
+ import logUpdate from 'log-update';
7
+ import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs';
8
+ import { AVAILABLE_CONTEXTS, getEnvelopeEnv, getHumanReadableScopes, normalizeContext } from '../../utils/env/index.mjs';
9
+ const MASK_LENGTH = 50;
10
+ const MASK = '*'.repeat(MASK_LENGTH);
11
+ // @ts-expect-error TS(7031) FIXME: Binding element 'environment' implicitly has an 'a... Remove this comment to see the full error message
15
12
  const getTable = ({ environment, hideValues, scopesColumn }) => {
16
- const table = new AsciiTable(`Environment variables`)
17
- const headings = ['Key', 'Value', scopesColumn && 'Scope'].filter(Boolean)
18
- table.setHeading(...headings)
19
- table.addRowMatrix(
20
- Object.entries(environment).map(([key, variable]) =>
21
- [
13
+ const table = new AsciiTable(`Environment variables`);
14
+ const headings = ['Key', 'Value', scopesColumn && 'Scope'].filter(Boolean);
15
+ table.setHeading(...headings);
16
+ table.addRowMatrix(Object.entries(environment).map(([key, variable]) => [
22
17
  // Key
23
18
  key,
24
19
  // Value
20
+ // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
25
21
  hideValues ? MASK : variable.value || ' ',
26
22
  // Scope
23
+ // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
27
24
  scopesColumn && getHumanReadableScopes(variable.scopes),
28
- ].filter(Boolean),
29
- ),
30
- )
31
- return table.toString()
32
- }
33
-
25
+ ].filter(Boolean)));
26
+ return table.toString();
27
+ };
34
28
  /**
35
29
  * The env:list command
36
30
  * @param {import('commander').OptionValues} options
37
31
  * @param {import('../base-command.mjs').default} command
38
32
  * @returns {Promise<boolean>}
39
33
  */
34
+ // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
40
35
  const envList = async (options, command) => {
41
- const { context, scope } = options
42
- const { api, cachedConfig, site } = command.netlify
43
- const siteId = site.id
44
-
45
- if (!siteId) {
46
- log('No site id found, please run inside a site folder or `netlify link`')
47
- return false
48
- }
49
-
50
- const { env, siteInfo } = cachedConfig
51
- const isUsingEnvelope = siteInfo.use_envelope
52
- let environment = env
53
-
54
- if (isUsingEnvelope) {
55
- environment = await getEnvelopeEnv({ api, context, env, scope, siteInfo })
56
- } else if (context !== 'dev' || scope !== 'any') {
57
- error(
58
- `To specify a context or scope, please run ${chalk.yellow(
59
- 'netlify open:admin',
60
- )} to open the Netlify UI and opt in to the new environment variables experience from Site settings`,
61
- )
62
- return false
63
- }
64
-
65
- // filter out general sources
66
- environment = Object.fromEntries(
67
- Object.entries(environment).filter(([, variable]) => variable.sources[0] !== 'general'),
68
- )
69
-
70
- // Return json response for piping commands
71
- if (options.json) {
72
- const envDictionary = Object.fromEntries(
73
- Object.entries(environment).map(([key, variable]) => [key, variable.value]),
74
- )
75
- logJson(envDictionary)
76
- return false
77
- }
78
-
79
- if (options.plain) {
80
- const plaintext = Object.entries(environment)
81
- .map(([key, variable]) => `${key}=${variable.value}`)
82
- .join('\n')
83
- log(plaintext)
84
- return false
85
- }
86
-
87
- const forSite = `for site ${chalk.green(siteInfo.name)}`
88
- const contextType = AVAILABLE_CONTEXTS.includes(context) ? 'context' : 'branch'
89
- const withContext = isUsingEnvelope ? `in the ${chalk.magenta(options.context)} ${contextType}` : ''
90
- const withScope = isUsingEnvelope && scope !== 'any' ? `and ${chalk.yellow(options.scope)} scope` : ''
91
- if (Object.keys(environment).length === 0) {
92
- log(`No environment variables set ${forSite} ${withContext} ${withScope}`)
93
- return false
94
- }
95
-
96
- // List environment in a table
97
- const count = Object.keys(environment).length
98
- log(`${count} environment variable${count === 1 ? '' : 's'} ${forSite} ${withContext} ${withScope}`)
99
-
100
- if (isCI) {
101
- log(getTable({ environment, hideValues: false, scopesColumn: isUsingEnvelope }))
102
- return false
103
- }
104
-
105
- logUpdate(getTable({ environment, hideValues: true, scopesColumn: isUsingEnvelope }))
106
- const { showValues } = await inquirer.prompt([
107
- {
108
- type: 'confirm',
109
- name: 'showValues',
110
- message: 'Show values?',
111
- default: false,
112
- },
113
- ])
114
-
115
- if (showValues) {
116
- // since inquirer adds a prompt, we need to account for it when printing the table again
117
- log(ansiEscapes.eraseLines(3))
118
- logUpdate(getTable({ environment, hideValues: false, scopesColumn: isUsingEnvelope }))
119
- log(`${chalk.cyan('?')} Show values? ${chalk.cyan('Yes')}`)
120
- }
121
- }
122
-
36
+ const { context, scope } = options;
37
+ const { api, cachedConfig, site } = command.netlify;
38
+ const siteId = site.id;
39
+ if (!siteId) {
40
+ log('No site id found, please run inside a site folder or `netlify link`');
41
+ return false;
42
+ }
43
+ const { env, siteInfo } = cachedConfig;
44
+ const isUsingEnvelope = siteInfo.use_envelope;
45
+ let environment = env;
46
+ if (isUsingEnvelope) {
47
+ environment = await getEnvelopeEnv({ api, context, env, scope, siteInfo });
48
+ }
49
+ else if (context !== 'dev' || scope !== 'any') {
50
+ error(`To specify a context or scope, please run ${chalk.yellow('netlify open:admin')} to open the Netlify UI and opt in to the new environment variables experience from Site settings`);
51
+ return false;
52
+ }
53
+ // filter out general sources
54
+ environment = Object.fromEntries(
55
+ // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
56
+ Object.entries(environment).filter(([, variable]) => variable.sources[0] !== 'general'));
57
+ // Return json response for piping commands
58
+ if (options.json) {
59
+ const envDictionary = Object.fromEntries(
60
+ // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
61
+ Object.entries(environment).map(([key, variable]) => [key, variable.value]));
62
+ logJson(envDictionary);
63
+ return false;
64
+ }
65
+ if (options.plain) {
66
+ const plaintext = Object.entries(environment)
67
+ // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
68
+ .map(([key, variable]) => `${key}=${variable.value}`)
69
+ .join('\n');
70
+ log(plaintext);
71
+ return false;
72
+ }
73
+ const forSite = `for site ${chalk.green(siteInfo.name)}`;
74
+ const contextType = AVAILABLE_CONTEXTS.includes(context) ? 'context' : 'branch';
75
+ const withContext = isUsingEnvelope ? `in the ${chalk.magenta(options.context)} ${contextType}` : '';
76
+ const withScope = isUsingEnvelope && scope !== 'any' ? `and ${chalk.yellow(options.scope)} scope` : '';
77
+ if (Object.keys(environment).length === 0) {
78
+ log(`No environment variables set ${forSite} ${withContext} ${withScope}`);
79
+ return false;
80
+ }
81
+ // List environment in a table
82
+ const count = Object.keys(environment).length;
83
+ log(`${count} environment variable${count === 1 ? '' : 's'} ${forSite} ${withContext} ${withScope}`);
84
+ if (isCI) {
85
+ log(getTable({ environment, hideValues: false, scopesColumn: isUsingEnvelope }));
86
+ return false;
87
+ }
88
+ logUpdate(getTable({ environment, hideValues: true, scopesColumn: isUsingEnvelope }));
89
+ const { showValues } = await inquirer.prompt([
90
+ {
91
+ type: 'confirm',
92
+ name: 'showValues',
93
+ message: 'Show values?',
94
+ default: false,
95
+ },
96
+ ]);
97
+ if (showValues) {
98
+ // since inquirer adds a prompt, we need to account for it when printing the table again
99
+ log(ansiEscapes.eraseLines(3));
100
+ logUpdate(getTable({ environment, hideValues: false, scopesColumn: isUsingEnvelope }));
101
+ log(`${chalk.cyan('?')} Show values? ${chalk.cyan('Yes')}`);
102
+ }
103
+ };
123
104
  /**
124
105
  * Creates the `netlify env:list` command
125
106
  * @param {import('../base-command.mjs').default} program
126
107
  * @returns
127
108
  */
128
- export const createEnvListCommand = (program) =>
129
- program
109
+ // @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type.
110
+ export const createEnvListCommand = (program) => program
130
111
  .command('env:list')
131
- .option(
132
- '-c, --context <context>',
133
- 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")',
134
- normalizeContext,
135
- 'dev',
136
- )
112
+ .option('-c, --context <context>', 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', normalizeContext, 'dev')
137
113
  .option('--json', 'Output environment variables as JSON')
138
114
  .addOption(new Option('--plain', 'Output environment variables as plaintext').conflicts('json'))
139
- .addOption(
140
- new Option('-s, --scope <scope>', 'Specify a scope')
141
- .choices(['builds', 'functions', 'post-processing', 'runtime', 'any'])
142
- .default('any'),
143
- )
115
+ .addOption(new Option('-s, --scope <scope>', 'Specify a scope')
116
+ .choices(['builds', 'functions', 'post-processing', 'runtime', 'any'])
117
+ .default('any'))
144
118
  .addExamples([
145
- 'netlify env:list # list variables with values in the dev context and with any scope',
146
- 'netlify env:list --context production',
147
- 'netlify env:list --context branch:staging',
148
- 'netlify env:list --scope functions',
149
- 'netlify env:list --plain',
150
- ])
119
+ 'netlify env:list # list variables with values in the dev context and with any scope',
120
+ 'netlify env:list --context production',
121
+ 'netlify env:list --context branch:staging',
122
+ 'netlify env:list --scope functions',
123
+ 'netlify env:list --plain',
124
+ ])
151
125
  .description('Lists resolved environment variables for site (includes netlify.toml)')
126
+ // @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
152
127
  .action(async (options, command) => {
153
- await envList(options, command)
154
- })
128
+ await envList(options, command);
129
+ });