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.
- package/README.md +2 -138
- package/npm-shrinkwrap.json +76 -76
- 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 -99
- 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
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { PollingStrategy, NetlifyTOML } from '@netlify/build-info'
|
|
2
|
+
|
|
3
|
+
import type { FrameworkNames } from '../../utils/types'
|
|
4
|
+
|
|
5
|
+
/** The configuration specified in the netlify.toml under [build] */
|
|
6
|
+
export type BuildConfig = NonNullable<NetlifyTOML['build']>
|
|
7
|
+
|
|
8
|
+
export type DevConfig = NonNullable<NetlifyTOML['dev']> & {
|
|
9
|
+
framework: FrameworkNames
|
|
10
|
+
/** Directory of the functions */
|
|
11
|
+
functions?: string
|
|
12
|
+
publish?: string
|
|
13
|
+
/** Port to serve the functions */
|
|
14
|
+
port: number
|
|
15
|
+
live: boolean
|
|
16
|
+
/** The base directory from the [build] section of the configuration file */
|
|
17
|
+
base?: string
|
|
18
|
+
staticServerPort?: number
|
|
19
|
+
functionsPort?: number
|
|
20
|
+
autoLaunch?: boolean
|
|
21
|
+
https?: {
|
|
22
|
+
keyFile: string
|
|
23
|
+
certFile: string
|
|
24
|
+
}
|
|
25
|
+
envFiles?: string[]
|
|
26
|
+
|
|
27
|
+
jwtSecret: string
|
|
28
|
+
jwtRolePath: string
|
|
29
|
+
pollingStrategies?: PollingStrategy[]
|
|
30
|
+
}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { chalk, error as logError, log } from '../../utils/command-helpers.mjs';
|
|
2
|
+
import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../../utils/env/index.mjs';
|
|
3
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type.
|
|
5
4
|
const safeGetSite = async (api, siteId) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
5
|
+
try {
|
|
6
|
+
const data = await api.getSite({ siteId });
|
|
7
|
+
return { data };
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
return { error };
|
|
11
|
+
}
|
|
12
|
+
};
|
|
14
13
|
/**
|
|
15
14
|
* The env:clone command
|
|
16
15
|
* @param {string} siteIdA Site (From)
|
|
@@ -19,207 +18,181 @@ const safeGetSite = async (api, siteId) => {
|
|
|
19
18
|
* @param {import('../base-command.mjs').default} command
|
|
20
19
|
* @returns {Promise<boolean>}
|
|
21
20
|
*/
|
|
21
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
22
22
|
const envClone = async (options, command) => {
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (!success) {
|
|
66
|
-
return false
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
log(`Successfully cloned environment variables from ${chalk.green(siteFrom.name)} to ${chalk.green(siteTo.name)}`)
|
|
70
|
-
|
|
71
|
-
return true
|
|
72
|
-
}
|
|
73
|
-
|
|
23
|
+
const { api, site } = command.netlify;
|
|
24
|
+
if (!site.id && !options.from) {
|
|
25
|
+
log('Please include the source site Id as the `--from` option, or run `netlify link` to link this folder to a Netlify site');
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const siteId = {
|
|
29
|
+
from: options.from || site.id,
|
|
30
|
+
to: options.to,
|
|
31
|
+
};
|
|
32
|
+
const [{ data: siteFrom, error: errorFrom }, { data: siteTo, error: errorTo }] = await Promise.all([
|
|
33
|
+
safeGetSite(api, siteId.from),
|
|
34
|
+
safeGetSite(api, siteId.to),
|
|
35
|
+
]);
|
|
36
|
+
if (errorFrom) {
|
|
37
|
+
logError(`Can't find site with id ${chalk.bold(siteId.from)}. Please make sure the site exists.`);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (errorTo) {
|
|
41
|
+
logError(`Can't find site with id ${chalk.bold(siteId.to)}. Please make sure the site exists.`);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
// determine if siteFrom and/or siteTo is on Envelope
|
|
45
|
+
let method;
|
|
46
|
+
if (!siteFrom.use_envelope && !siteTo.use_envelope) {
|
|
47
|
+
method = mongoToMongo;
|
|
48
|
+
}
|
|
49
|
+
else if (!siteFrom.use_envelope && siteTo.use_envelope) {
|
|
50
|
+
method = mongoToEnvelope;
|
|
51
|
+
}
|
|
52
|
+
else if (siteFrom.use_envelope && !siteTo.use_envelope) {
|
|
53
|
+
method = envelopeToMongo;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
method = envelopeToEnvelope;
|
|
57
|
+
}
|
|
58
|
+
const success = await method({ api, siteFrom, siteTo });
|
|
59
|
+
if (!success) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
log(`Successfully cloned environment variables from ${chalk.green(siteFrom.name)} to ${chalk.green(siteTo.name)}`);
|
|
63
|
+
return true;
|
|
64
|
+
};
|
|
74
65
|
/**
|
|
75
66
|
* Copies the env from a site not configured with Envelope to a different site not configured with Envelope
|
|
76
67
|
* @returns {Promise<boolean>}
|
|
77
68
|
*/
|
|
69
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
78
70
|
const mongoToMongo = async ({ api, siteFrom, siteTo }) => {
|
|
79
|
-
|
|
80
|
-
{
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
await api.updateSite({
|
|
101
|
-
siteId: siteTo.id,
|
|
102
|
-
body: {
|
|
103
|
-
build_settings: {
|
|
104
|
-
env: mergedEnv,
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
return true
|
|
110
|
-
}
|
|
111
|
-
|
|
71
|
+
const [{ build_settings: { env: envFrom = {} }, }, { build_settings: { env: envTo = {} }, },] = [siteFrom, siteTo];
|
|
72
|
+
if (Object.keys(envFrom).length === 0) {
|
|
73
|
+
log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
// Merge from site A to site B
|
|
77
|
+
const mergedEnv = {
|
|
78
|
+
...envTo,
|
|
79
|
+
...envFrom,
|
|
80
|
+
};
|
|
81
|
+
// Apply environment variable updates
|
|
82
|
+
await api.updateSite({
|
|
83
|
+
siteId: siteTo.id,
|
|
84
|
+
body: {
|
|
85
|
+
build_settings: {
|
|
86
|
+
env: mergedEnv,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
return true;
|
|
91
|
+
};
|
|
112
92
|
/**
|
|
113
93
|
* Copies the env from a site not configured with Envelope to a site configured with Envelope
|
|
114
94
|
* @returns {Promise<boolean>}
|
|
115
95
|
*/
|
|
96
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
116
97
|
const mongoToEnvelope = async ({ api, siteFrom, siteTo }) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return true
|
|
143
|
-
}
|
|
144
|
-
|
|
98
|
+
const envFrom = siteFrom.build_settings.env || {};
|
|
99
|
+
const keysFrom = Object.keys(envFrom);
|
|
100
|
+
if (Object.keys(envFrom).length === 0) {
|
|
101
|
+
log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`);
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const accountId = siteTo.account_slug;
|
|
105
|
+
const siteId = siteTo.id;
|
|
106
|
+
const envelopeTo = await api.getEnvVars({ accountId, siteId });
|
|
107
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
108
|
+
const envVarsToDelete = envelopeTo.filter(({ key }) => keysFrom.includes(key));
|
|
109
|
+
// delete marked env vars in parallel
|
|
110
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
111
|
+
await Promise.all(envVarsToDelete.map(({ key }) => api.deleteEnvVar({ accountId, siteId, key })));
|
|
112
|
+
// hit create endpoint
|
|
113
|
+
const body = translateFromMongoToEnvelope(envFrom);
|
|
114
|
+
try {
|
|
115
|
+
await api.createEnvVars({ accountId, siteId, body });
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
|
|
119
|
+
throw error.json ? error.json.msg : error;
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
145
123
|
/**
|
|
146
124
|
* Copies the env from a site configured with Envelope to a site not configured with Envelope
|
|
147
125
|
* @returns {Promise<boolean>}
|
|
148
126
|
*/
|
|
127
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
149
128
|
const envelopeToMongo = async ({ api, siteFrom, siteTo }) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
},
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
return true
|
|
177
|
-
}
|
|
178
|
-
|
|
129
|
+
const envelopeVariables = await api.getEnvVars({ accountId: siteFrom.account_slug, siteId: siteFrom.id });
|
|
130
|
+
const envFrom = translateFromEnvelopeToMongo(envelopeVariables);
|
|
131
|
+
if (Object.keys(envFrom).length === 0) {
|
|
132
|
+
log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`);
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const envTo = siteTo.build_settings.env || {};
|
|
136
|
+
// Merge from site A to site B
|
|
137
|
+
const mergedEnv = {
|
|
138
|
+
...envTo,
|
|
139
|
+
...envFrom,
|
|
140
|
+
};
|
|
141
|
+
// Apply environment variable updates
|
|
142
|
+
await api.updateSite({
|
|
143
|
+
siteId: siteTo.id,
|
|
144
|
+
body: {
|
|
145
|
+
build_settings: {
|
|
146
|
+
env: mergedEnv,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
return true;
|
|
151
|
+
};
|
|
179
152
|
/**
|
|
180
153
|
* Copies the env from a site configured with Envelope to a different site configured with Envelope
|
|
181
154
|
* @returns {Promise<boolean>}
|
|
182
155
|
*/
|
|
156
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
183
157
|
const envelopeToEnvelope = async ({ api, siteFrom, siteTo }) => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
158
|
+
const [envelopeFrom, envelopeTo] = await Promise.all([
|
|
159
|
+
api.getEnvVars({ accountId: siteFrom.account_slug, siteId: siteFrom.id }),
|
|
160
|
+
api.getEnvVars({ accountId: siteTo.account_slug, siteId: siteTo.id }),
|
|
161
|
+
]);
|
|
162
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
163
|
+
const keysFrom = envelopeFrom.map(({ key }) => key);
|
|
164
|
+
if (keysFrom.length === 0) {
|
|
165
|
+
log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`);
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
const accountId = siteTo.account_slug;
|
|
169
|
+
const siteId = siteTo.id;
|
|
170
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
171
|
+
const envVarsToDelete = envelopeTo.filter(({ key }) => keysFrom.includes(key));
|
|
172
|
+
// delete marked env vars in parallel
|
|
173
|
+
// @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
174
|
+
await Promise.all(envVarsToDelete.map(({ key }) => api.deleteEnvVar({ accountId, siteId, key })));
|
|
175
|
+
// hit create endpoint
|
|
176
|
+
try {
|
|
177
|
+
await api.createEnvVars({ accountId, siteId, body: envelopeFrom });
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
|
|
181
|
+
throw error.json ? error.json.msg : error;
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
};
|
|
212
185
|
/**
|
|
213
186
|
* Creates the `netlify env:clone` command
|
|
214
187
|
* @param {import('../base-command.mjs').default} program
|
|
215
188
|
* @returns
|
|
216
189
|
*/
|
|
217
|
-
|
|
218
|
-
|
|
190
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type.
|
|
191
|
+
export const createEnvCloneCommand = (program) => program
|
|
219
192
|
.command('env:clone')
|
|
220
193
|
.alias('env:migrate')
|
|
221
194
|
.option('-f, --from <from>', 'Site ID (From)')
|
|
222
195
|
.requiredOption('-t, --to <to>', 'Site ID (To)')
|
|
223
196
|
.description(`Clone environment variables from one site to another`)
|
|
224
197
|
.addExamples(['netlify env:clone --to <to-site-id>', 'netlify env:clone --to <to-site-id> --from <from-site-id>'])
|
|
225
|
-
.action(envClone)
|
|
198
|
+
.action(envClone);
|
|
@@ -1,85 +1,66 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs'
|
|
5
|
-
import { AVAILABLE_CONTEXTS, getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs'
|
|
6
|
-
|
|
1
|
+
import { Option } from 'commander';
|
|
2
|
+
import { chalk, error, log, logJson } from '../../utils/command-helpers.mjs';
|
|
3
|
+
import { AVAILABLE_CONTEXTS, getEnvelopeEnv, normalizeContext } from '../../utils/env/index.mjs';
|
|
7
4
|
/**
|
|
8
5
|
* The env:get command
|
|
9
6
|
* @param {string} name Environment variable name
|
|
10
7
|
* @param {import('commander').OptionValues} options
|
|
11
8
|
* @param {import('../base-command.mjs').default} command
|
|
12
9
|
*/
|
|
10
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
|
13
11
|
const envGet = async (name, options, command) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
if (!value) {
|
|
46
|
-
const contextType = AVAILABLE_CONTEXTS.includes(context) ? 'context' : 'branch'
|
|
47
|
-
const withContext = `in the ${chalk.magenta(context)} ${contextType}`
|
|
48
|
-
const withScope = scope === 'any' ? '' : ` and the ${chalk.magenta(scope)} scope`
|
|
49
|
-
log(`No value set ${withContext}${withScope} for environment variable ${chalk.yellow(name)}`)
|
|
50
|
-
return false
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
log(value)
|
|
54
|
-
}
|
|
55
|
-
|
|
12
|
+
const { context, scope } = options;
|
|
13
|
+
const { api, cachedConfig, site } = command.netlify;
|
|
14
|
+
const siteId = site.id;
|
|
15
|
+
if (!siteId) {
|
|
16
|
+
log('No site id found, please run inside a site folder or `netlify link`');
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const { siteInfo } = cachedConfig;
|
|
20
|
+
let { env } = cachedConfig;
|
|
21
|
+
if (siteInfo.use_envelope) {
|
|
22
|
+
env = await getEnvelopeEnv({ api, context, env, key: name, scope, siteInfo });
|
|
23
|
+
}
|
|
24
|
+
else if (context !== 'dev' || scope !== 'any') {
|
|
25
|
+
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`);
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const { value } = env[name] || {};
|
|
29
|
+
// Return json response for piping commands
|
|
30
|
+
if (options.json) {
|
|
31
|
+
logJson(value ? { [name]: value } : {});
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (!value) {
|
|
35
|
+
const contextType = AVAILABLE_CONTEXTS.includes(context) ? 'context' : 'branch';
|
|
36
|
+
const withContext = `in the ${chalk.magenta(context)} ${contextType}`;
|
|
37
|
+
const withScope = scope === 'any' ? '' : ` and the ${chalk.magenta(scope)} scope`;
|
|
38
|
+
log(`No value set ${withContext}${withScope} for environment variable ${chalk.yellow(name)}`);
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
log(value);
|
|
42
|
+
};
|
|
56
43
|
/**
|
|
57
44
|
* Creates the `netlify env:get` command
|
|
58
45
|
* @param {import('../base-command.mjs').default} program
|
|
59
46
|
* @returns
|
|
60
47
|
*/
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type.
|
|
49
|
+
export const createEnvGetCommand = (program) => program
|
|
63
50
|
.command('env:get')
|
|
64
51
|
.argument('<name>', 'Environment variable name')
|
|
65
|
-
.option(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
'dev',
|
|
70
|
-
)
|
|
71
|
-
.addOption(
|
|
72
|
-
new Option('-s, --scope <scope>', 'Specify a scope')
|
|
73
|
-
.choices(['builds', 'functions', 'post-processing', 'runtime', 'any'])
|
|
74
|
-
.default('any'),
|
|
75
|
-
)
|
|
52
|
+
.option('-c, --context <context>', 'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")', normalizeContext, 'dev')
|
|
53
|
+
.addOption(new Option('-s, --scope <scope>', 'Specify a scope')
|
|
54
|
+
.choices(['builds', 'functions', 'post-processing', 'runtime', 'any'])
|
|
55
|
+
.default('any'))
|
|
76
56
|
.addExamples([
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
57
|
+
'netlify env:get MY_VAR # get value for MY_VAR in dev context',
|
|
58
|
+
'netlify env:get MY_VAR --context production',
|
|
59
|
+
'netlify env:get MY_VAR --context branch:staging',
|
|
60
|
+
'netlify env:get MY_VAR --scope functions',
|
|
61
|
+
])
|
|
82
62
|
.description('Get resolved value of specified environment variable (includes netlify.toml)')
|
|
63
|
+
// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
|
83
64
|
.action(async (name, options, command) => {
|
|
84
|
-
|
|
85
|
-
|
|
65
|
+
await envGet(name, options, command);
|
|
66
|
+
});
|