netlify-cli 17.3.1 → 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.
- package/README.md +3 -139
- package/npm-shrinkwrap.json +82 -82
- package/package.json +16 -15
- package/src/commands/addons/addons-auth.mjs +27 -30
- package/src/commands/addons/addons-config.mjs +145 -154
- package/src/commands/addons/addons-create.mjs +94 -108
- package/src/commands/addons/addons-delete.mjs +36 -41
- package/src/commands/addons/addons-list.mjs +38 -42
- package/src/commands/addons/addons.mjs +26 -28
- package/src/commands/addons/index.mjs +1 -1
- package/src/commands/api/api.mjs +45 -53
- package/src/commands/api/index.mjs +1 -1
- package/src/commands/base-command.mjs +597 -684
- package/src/commands/blobs/blobs-delete.mjs +35 -0
- package/src/commands/blobs/blobs-get.mjs +44 -0
- package/src/commands/blobs/blobs-list.mjs +48 -0
- package/src/commands/blobs/blobs-set.mjs +54 -0
- package/src/commands/blobs/blobs.mjs +32 -0
- package/src/commands/blobs/index.mjs +1 -0
- package/src/commands/build/build.mjs +55 -67
- package/src/commands/build/index.mjs +1 -1
- package/src/commands/completion/completion.mjs +41 -46
- package/src/commands/completion/index.mjs +1 -1
- package/src/commands/deploy/deploy.mjs +675 -710
- package/src/commands/deploy/index.mjs +1 -1
- package/src/commands/dev/dev-exec.mjs +20 -32
- package/src/commands/dev/dev.mjs +217 -302
- package/src/commands/dev/index.mjs +1 -1
- package/src/commands/dev/types.d.ts +30 -0
- package/src/commands/env/env-clone.mjs +157 -184
- package/src/commands/env/env-get.mjs +49 -68
- package/src/commands/env/env-import.mjs +100 -119
- package/src/commands/env/env-list.mjs +104 -129
- package/src/commands/env/env-set.mjs +160 -185
- package/src/commands/env/env-unset.mjs +104 -122
- package/src/commands/env/env.mjs +28 -30
- package/src/commands/env/index.mjs +1 -1
- package/src/commands/functions/functions-build.mjs +29 -41
- package/src/commands/functions/functions-create.mjs +533 -601
- package/src/commands/functions/functions-invoke.mjs +193 -216
- package/src/commands/functions/functions-list.mjs +45 -55
- package/src/commands/functions/functions-serve.mjs +51 -61
- package/src/commands/functions/functions.mjs +26 -32
- package/src/commands/functions/index.mjs +1 -1
- package/src/commands/index.mjs +2 -2
- package/src/commands/init/index.mjs +1 -1
- package/src/commands/init/init.mjs +138 -167
- package/src/commands/integration/deploy.mjs +337 -399
- package/src/commands/integration/index.mjs +12 -13
- package/src/commands/link/index.mjs +1 -1
- package/src/commands/link/link.mjs +298 -317
- package/src/commands/lm/index.mjs +1 -1
- package/src/commands/lm/lm-info.mjs +23 -31
- package/src/commands/lm/lm-install.mjs +13 -17
- package/src/commands/lm/lm-setup.mjs +80 -84
- package/src/commands/lm/lm-uninstall.mjs +7 -12
- package/src/commands/lm/lm.mjs +18 -22
- package/src/commands/login/index.mjs +1 -1
- package/src/commands/login/login.mjs +35 -41
- package/src/commands/logout/index.mjs +1 -1
- package/src/commands/logout/logout.mjs +25 -31
- package/src/commands/main.mjs +166 -201
- package/src/commands/open/index.mjs +1 -1
- package/src/commands/open/open-admin.mjs +15 -18
- package/src/commands/open/open-site.mjs +16 -19
- package/src/commands/open/open.mjs +24 -27
- package/src/commands/recipes/common.mjs +23 -34
- package/src/commands/recipes/index.mjs +1 -1
- package/src/commands/recipes/recipes-list.mjs +13 -20
- package/src/commands/recipes/recipes.mjs +59 -72
- package/src/commands/serve/index.mjs +1 -1
- package/src/commands/serve/serve.mjs +142 -189
- package/src/commands/sites/index.mjs +2 -2
- package/src/commands/sites/sites-create-template.mjs +214 -236
- package/src/commands/sites/sites-create.mjs +145 -157
- package/src/commands/sites/sites-delete.mjs +75 -81
- package/src/commands/sites/sites-list.mjs +63 -66
- package/src/commands/sites/sites.mjs +18 -20
- package/src/commands/status/index.mjs +1 -1
- package/src/commands/status/status-hooks.mjs +32 -34
- package/src/commands/status/status.mjs +99 -106
- package/src/commands/switch/index.mjs +1 -1
- package/src/commands/switch/switch.mjs +32 -37
- package/src/commands/types.d.ts +31 -0
- package/src/commands/unlink/index.mjs +1 -1
- package/src/commands/unlink/unlink.mjs +23 -29
- package/src/commands/watch/index.mjs +1 -1
- package/src/commands/watch/watch.mjs +91 -105
- package/src/functions-templates/javascript/hello/{{name}}.js +2 -3
- package/src/lib/account.mjs +4 -5
- package/src/lib/api.mjs +22 -20
- package/src/lib/blobs/blobs.mjs +36 -45
- package/src/lib/build.mjs +82 -85
- package/src/lib/completion/constants.mjs +2 -4
- package/src/lib/completion/generate-autocompletion.mjs +33 -36
- package/src/lib/completion/get-autocompletion.mjs +31 -35
- package/src/lib/completion/index.mjs +1 -1
- package/src/lib/completion/script.mjs +12 -19
- package/src/lib/edge-functions/bootstrap.mjs +3 -5
- package/src/lib/edge-functions/consts.mjs +9 -10
- package/src/lib/edge-functions/deploy.mjs +28 -34
- package/src/lib/edge-functions/editor-helper.mjs +29 -42
- package/src/lib/edge-functions/headers.mjs +24 -26
- package/src/lib/edge-functions/internal.mjs +38 -44
- package/src/lib/edge-functions/proxy.mjs +229 -228
- package/src/lib/edge-functions/registry.mjs +473 -574
- package/src/lib/exec-fetcher.mjs +115 -122
- package/src/lib/fs.mjs +28 -27
- package/src/lib/functions/background.mjs +16 -20
- package/src/lib/functions/config.mjs +12 -9
- package/src/lib/functions/form-submissions-handler.mjs +143 -149
- package/src/lib/functions/local-proxy.mjs +40 -44
- package/src/lib/functions/memoized-build.mjs +19 -21
- package/src/lib/functions/netlify-function.mjs +269 -249
- package/src/lib/functions/registry.mjs +509 -568
- package/src/lib/functions/runtimes/go/index.mjs +62 -71
- package/src/lib/functions/runtimes/index.mjs +8 -15
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.mjs +55 -64
- package/src/lib/functions/runtimes/js/builders/zisi.mjs +135 -154
- package/src/lib/functions/runtimes/js/constants.mjs +1 -1
- package/src/lib/functions/runtimes/js/index.mjs +92 -109
- package/src/lib/functions/runtimes/js/worker.mjs +43 -45
- package/src/lib/functions/runtimes/rust/index.mjs +64 -73
- package/src/lib/functions/scheduled.mjs +70 -88
- package/src/lib/functions/server.mjs +269 -327
- package/src/lib/functions/synchronous.mjs +118 -147
- package/src/lib/functions/utils.mjs +38 -46
- package/src/lib/geo-location.mjs +69 -81
- package/src/lib/http-agent.mjs +87 -90
- package/src/lib/images/proxy.mjs +97 -89
- package/src/lib/log.mjs +6 -9
- package/src/lib/path.mjs +2 -1
- package/src/lib/render-error-template.mjs +19 -20
- package/src/lib/settings.mjs +17 -19
- package/src/lib/spinner.mjs +21 -23
- package/src/lib/string.mjs +4 -2
- package/src/recipes/vscode/index.mjs +69 -85
- package/src/recipes/vscode/settings.mjs +53 -58
- package/src/utils/addons/compare.mjs +31 -32
- package/src/utils/addons/diffs/index.mjs +16 -17
- package/src/utils/addons/diffs/options.mjs +99 -101
- package/src/utils/addons/prepare.mjs +100 -97
- package/src/utils/addons/prompts.mjs +73 -76
- package/src/utils/addons/render.mjs +33 -36
- package/src/utils/addons/validation.mjs +19 -15
- package/src/utils/banner.mjs +11 -16
- package/src/utils/build-info.mjs +65 -66
- package/src/utils/command-helpers.mjs +185 -199
- package/src/utils/create-deferred.mjs +9 -12
- package/src/utils/create-stream-promise.mjs +54 -47
- package/src/utils/deploy/constants.mjs +9 -11
- package/src/utils/deploy/deploy-site.mjs +162 -182
- package/src/utils/deploy/hash-config.mjs +21 -21
- package/src/utils/deploy/hash-files.mjs +34 -38
- package/src/utils/deploy/hash-fns.mjs +149 -154
- package/src/utils/deploy/hasher-segments.mjs +58 -52
- package/src/utils/deploy/upload-files.mjs +99 -113
- package/src/utils/deploy/util.mjs +85 -91
- package/src/utils/detect-server-settings.mjs +236 -268
- package/src/utils/dev.mjs +163 -178
- package/src/utils/dot-env.mjs +37 -42
- package/src/utils/env/index.mjs +148 -148
- package/src/utils/execa.mjs +9 -13
- package/src/utils/feature-flags.mjs +6 -5
- package/src/utils/framework-server.mjs +43 -52
- package/src/utils/functions/constants.mjs +1 -1
- package/src/utils/functions/functions.mjs +30 -40
- package/src/utils/functions/get-functions.mjs +28 -29
- package/src/utils/functions/index.mjs +3 -3
- package/src/utils/get-global-config.mjs +33 -36
- package/src/utils/get-package-json.mjs +14 -15
- package/src/utils/get-repo-data.mjs +54 -64
- package/src/utils/get-site.mjs +14 -14
- package/src/utils/gh-auth.mjs +79 -100
- package/src/utils/gitignore.mjs +37 -40
- package/src/utils/headers.mjs +33 -35
- package/src/utils/hooks/requires-site-info.mjs +26 -22
- package/src/utils/init/config-github.mjs +207 -219
- package/src/utils/init/config-manual.mjs +83 -100
- package/src/utils/init/config.mjs +25 -26
- package/src/utils/init/node-version.mjs +23 -30
- package/src/utils/init/plugins.mjs +12 -8
- package/src/utils/init/utils.mjs +152 -172
- package/src/utils/live-tunnel.mjs +118 -141
- package/src/utils/lm/install.mjs +220 -259
- package/src/utils/lm/requirements.mjs +54 -63
- package/src/utils/lm/steps.mjs +31 -31
- package/src/utils/lm/ui.mjs +13 -20
- package/src/utils/open-browser.mjs +31 -32
- package/src/utils/parse-raw-flags.mjs +39 -35
- package/src/utils/proxy-server.mjs +84 -71
- package/src/utils/proxy.mjs +696 -750
- package/src/utils/read-repo-url.mjs +48 -47
- package/src/utils/redirects.mjs +49 -49
- package/src/utils/request-id.mjs +2 -4
- package/src/utils/rules-proxy.mjs +96 -100
- package/src/utils/run-build.mjs +109 -132
- package/src/utils/shell.mjs +99 -106
- package/src/utils/sign-redirect.mjs +14 -14
- package/src/utils/sites/utils.mjs +48 -55
- package/src/utils/state-config.mjs +101 -101
- package/src/utils/static-server.mjs +28 -34
- package/src/utils/telemetry/index.mjs +2 -2
- package/src/utils/telemetry/report-error.mjs +45 -49
- package/src/utils/telemetry/request.mjs +36 -43
- package/src/utils/telemetry/telemetry.mjs +90 -105
- package/src/utils/telemetry/utils.mjs +5 -6
- package/src/utils/telemetry/validation.mjs +55 -53
- package/src/utils/types.d.ts +46 -0
- package/src/utils/validation.mjs +10 -13
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
127
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
146
|
-
|
|
126
|
+
await envImport(fileName, options, command);
|
|
127
|
+
});
|
|
@@ -1,154 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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
|
-
|
|
141
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
154
|
-
|
|
128
|
+
await envList(options, command);
|
|
129
|
+
});
|