netlify-cli 11.0.0 → 11.1.0-rc.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/npm-shrinkwrap.json +58 -9
- package/package.json +2 -2
- package/src/commands/build/build.js +7 -2
- package/src/commands/dev/dev-exec.js +6 -6
- package/src/commands/dev/dev.js +6 -4
- package/src/commands/env/env-get.js +12 -5
- package/src/commands/env/env-list.js +12 -5
- package/src/commands/env/env-set.js +19 -11
- package/src/commands/env/env-unset.js +21 -15
- package/src/utils/env/index.js +49 -15
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
|
-
"version": "11.0.0",
|
|
3
|
+
"version": "11.1.0-rc.0",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "netlify-cli",
|
|
9
|
-
"version": "11.0.0",
|
|
9
|
+
"version": "11.1.0-rc.0",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@netlify/build": "^27.14.0",
|
|
14
14
|
"@netlify/config": "^18.2.0",
|
|
15
|
-
"@netlify/edge-bundler": "^1.
|
|
15
|
+
"@netlify/edge-bundler": "^1.13.0",
|
|
16
16
|
"@netlify/framework-info": "^9.2.0",
|
|
17
17
|
"@netlify/local-functions-proxy": "^1.1.1",
|
|
18
18
|
"@netlify/plugins-list": "^6.39.0",
|
|
@@ -2343,9 +2343,9 @@
|
|
|
2343
2343
|
}
|
|
2344
2344
|
},
|
|
2345
2345
|
"node_modules/@netlify/edge-bundler": {
|
|
2346
|
-
"version": "1.
|
|
2347
|
-
"resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-1.
|
|
2348
|
-
"integrity": "sha512-
|
|
2346
|
+
"version": "1.13.0",
|
|
2347
|
+
"resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-1.13.0.tgz",
|
|
2348
|
+
"integrity": "sha512-5LDNouZP2tUt3m6NyKkEgor9PycIEq7wxUgrRSpiUcZVV7CNU/CUxxpXJb11/wEFq2bWZp3/xqzxqbR7vpqFNg==",
|
|
2349
2349
|
"dependencies": {
|
|
2350
2350
|
"common-path-prefix": "^3.0.0",
|
|
2351
2351
|
"del": "^6.0.0",
|
|
@@ -2354,6 +2354,7 @@
|
|
|
2354
2354
|
"glob-to-regexp": "^0.4.1",
|
|
2355
2355
|
"node-fetch": "^3.1.1",
|
|
2356
2356
|
"node-stream-zip": "^1.15.0",
|
|
2357
|
+
"p-retry": "^5.1.1",
|
|
2357
2358
|
"p-wait-for": "^4.1.0",
|
|
2358
2359
|
"path-key": "^4.0.0",
|
|
2359
2360
|
"semver": "^7.3.5",
|
|
@@ -4353,6 +4354,11 @@
|
|
|
4353
4354
|
"@types/node": "*"
|
|
4354
4355
|
}
|
|
4355
4356
|
},
|
|
4357
|
+
"node_modules/@types/retry": {
|
|
4358
|
+
"version": "0.12.1",
|
|
4359
|
+
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
|
|
4360
|
+
"integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g=="
|
|
4361
|
+
},
|
|
4356
4362
|
"node_modules/@types/semver": {
|
|
4357
4363
|
"version": "7.3.9",
|
|
4358
4364
|
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz",
|
|
@@ -17355,6 +17361,21 @@
|
|
|
17355
17361
|
"url": "https://github.com/sponsors/sindresorhus"
|
|
17356
17362
|
}
|
|
17357
17363
|
},
|
|
17364
|
+
"node_modules/p-retry": {
|
|
17365
|
+
"version": "5.1.1",
|
|
17366
|
+
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-5.1.1.tgz",
|
|
17367
|
+
"integrity": "sha512-i69WkEU5ZAL8mrmdmVviWwU+DN+IUF8f4sSJThoJ3z5A7Nn5iuO5ROX3Boye0u+uYQLOSfgFl7SuFZCjlAVbQA==",
|
|
17368
|
+
"dependencies": {
|
|
17369
|
+
"@types/retry": "0.12.1",
|
|
17370
|
+
"retry": "^0.13.1"
|
|
17371
|
+
},
|
|
17372
|
+
"engines": {
|
|
17373
|
+
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
|
17374
|
+
},
|
|
17375
|
+
"funding": {
|
|
17376
|
+
"url": "https://github.com/sponsors/sindresorhus"
|
|
17377
|
+
}
|
|
17378
|
+
},
|
|
17358
17379
|
"node_modules/p-timeout": {
|
|
17359
17380
|
"version": "4.1.0",
|
|
17360
17381
|
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
|
|
@@ -19173,6 +19194,14 @@
|
|
|
19173
19194
|
"node": ">=0.12"
|
|
19174
19195
|
}
|
|
19175
19196
|
},
|
|
19197
|
+
"node_modules/retry": {
|
|
19198
|
+
"version": "0.13.1",
|
|
19199
|
+
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
|
|
19200
|
+
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
|
|
19201
|
+
"engines": {
|
|
19202
|
+
"node": ">= 4"
|
|
19203
|
+
}
|
|
19204
|
+
},
|
|
19176
19205
|
"node_modules/reusify": {
|
|
19177
19206
|
"version": "1.0.4",
|
|
19178
19207
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
|
@@ -24046,9 +24075,9 @@
|
|
|
24046
24075
|
}
|
|
24047
24076
|
},
|
|
24048
24077
|
"@netlify/edge-bundler": {
|
|
24049
|
-
"version": "1.
|
|
24050
|
-
"resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-1.
|
|
24051
|
-
"integrity": "sha512-
|
|
24078
|
+
"version": "1.13.0",
|
|
24079
|
+
"resolved": "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-1.13.0.tgz",
|
|
24080
|
+
"integrity": "sha512-5LDNouZP2tUt3m6NyKkEgor9PycIEq7wxUgrRSpiUcZVV7CNU/CUxxpXJb11/wEFq2bWZp3/xqzxqbR7vpqFNg==",
|
|
24052
24081
|
"requires": {
|
|
24053
24082
|
"common-path-prefix": "^3.0.0",
|
|
24054
24083
|
"del": "^6.0.0",
|
|
@@ -24057,6 +24086,7 @@
|
|
|
24057
24086
|
"glob-to-regexp": "^0.4.1",
|
|
24058
24087
|
"node-fetch": "^3.1.1",
|
|
24059
24088
|
"node-stream-zip": "^1.15.0",
|
|
24089
|
+
"p-retry": "^5.1.1",
|
|
24060
24090
|
"p-wait-for": "^4.1.0",
|
|
24061
24091
|
"path-key": "^4.0.0",
|
|
24062
24092
|
"semver": "^7.3.5",
|
|
@@ -25377,6 +25407,11 @@
|
|
|
25377
25407
|
"@types/node": "*"
|
|
25378
25408
|
}
|
|
25379
25409
|
},
|
|
25410
|
+
"@types/retry": {
|
|
25411
|
+
"version": "0.12.1",
|
|
25412
|
+
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
|
|
25413
|
+
"integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g=="
|
|
25414
|
+
},
|
|
25380
25415
|
"@types/semver": {
|
|
25381
25416
|
"version": "7.3.9",
|
|
25382
25417
|
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz",
|
|
@@ -35173,6 +35208,15 @@
|
|
|
35173
35208
|
"resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz",
|
|
35174
35209
|
"integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q=="
|
|
35175
35210
|
},
|
|
35211
|
+
"p-retry": {
|
|
35212
|
+
"version": "5.1.1",
|
|
35213
|
+
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-5.1.1.tgz",
|
|
35214
|
+
"integrity": "sha512-i69WkEU5ZAL8mrmdmVviWwU+DN+IUF8f4sSJThoJ3z5A7Nn5iuO5ROX3Boye0u+uYQLOSfgFl7SuFZCjlAVbQA==",
|
|
35215
|
+
"requires": {
|
|
35216
|
+
"@types/retry": "0.12.1",
|
|
35217
|
+
"retry": "^0.13.1"
|
|
35218
|
+
}
|
|
35219
|
+
},
|
|
35176
35220
|
"p-timeout": {
|
|
35177
35221
|
"version": "4.1.0",
|
|
35178
35222
|
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
|
|
@@ -36530,6 +36574,11 @@
|
|
|
36530
36574
|
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
|
36531
36575
|
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
|
|
36532
36576
|
},
|
|
36577
|
+
"retry": {
|
|
36578
|
+
"version": "0.13.1",
|
|
36579
|
+
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
|
|
36580
|
+
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="
|
|
36581
|
+
},
|
|
36533
36582
|
"reusify": {
|
|
36534
36583
|
"version": "1.0.4",
|
|
36535
36584
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
3
|
"description": "Netlify command line tool",
|
|
4
|
-
"version": "11.0.0",
|
|
4
|
+
"version": "11.1.0-rc.0",
|
|
5
5
|
"author": "Netlify Inc.",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"@whitep4nth3r (https://twitter.com/whitep4nth3r)",
|
|
@@ -224,7 +224,7 @@
|
|
|
224
224
|
"dependencies": {
|
|
225
225
|
"@netlify/build": "^27.14.0",
|
|
226
226
|
"@netlify/config": "^18.2.0",
|
|
227
|
-
"@netlify/edge-bundler": "^1.
|
|
227
|
+
"@netlify/edge-bundler": "^1.13.0",
|
|
228
228
|
"@netlify/framework-info": "^9.2.0",
|
|
229
229
|
"@netlify/local-functions-proxy": "^1.1.1",
|
|
230
230
|
"@netlify/plugins-list": "^6.39.0",
|
|
@@ -2,7 +2,7 @@ const process = require('process')
|
|
|
2
2
|
|
|
3
3
|
// @ts-check
|
|
4
4
|
const { getBuildOptions, runBuild } = require('../../lib/build')
|
|
5
|
-
const { error, exit, generateNetlifyGraphJWT, getEnvelopeEnv, getToken } = require('../../utils')
|
|
5
|
+
const { error, exit, generateNetlifyGraphJWT, getEnvelopeEnv, getToken, normalizeContext } = require('../../utils')
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @param {import('../../lib/build').BuildConfig} options
|
|
@@ -85,7 +85,12 @@ const createBuildCommand = (program) =>
|
|
|
85
85
|
program
|
|
86
86
|
.command('build')
|
|
87
87
|
.description('(Beta) Build on your local machine')
|
|
88
|
-
.option(
|
|
88
|
+
.option(
|
|
89
|
+
'--context <context>',
|
|
90
|
+
'Specify a build context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")',
|
|
91
|
+
normalizeContext,
|
|
92
|
+
process.env.CONTEXT || 'production',
|
|
93
|
+
)
|
|
89
94
|
.option('--dry', 'Dry run: show instructions without running them', false)
|
|
90
95
|
.option('-o, --offline', 'disables any features that require network access', false)
|
|
91
96
|
.addExamples(['netlify build'])
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
const { Option } = require('commander')
|
|
2
1
|
const execa = require('execa')
|
|
3
2
|
|
|
4
|
-
const { getEnvelopeEnv, injectEnvVariables } = require('../../utils')
|
|
3
|
+
const { getEnvelopeEnv, injectEnvVariables, normalizeContext } = require('../../utils')
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* The dev:exec command
|
|
@@ -32,10 +31,11 @@ const createDevExecCommand = (program) =>
|
|
|
32
31
|
program
|
|
33
32
|
.command('dev:exec')
|
|
34
33
|
.argument('<...cmd>', `the command that should be executed`)
|
|
35
|
-
.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
.option(
|
|
35
|
+
'--context <context>',
|
|
36
|
+
'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")',
|
|
37
|
+
normalizeContext,
|
|
38
|
+
'dev',
|
|
39
39
|
)
|
|
40
40
|
.description(
|
|
41
41
|
'Exec command\nRuns a command within the netlify dev environment, e.g. with env variables from any installed addons',
|
package/src/commands/dev/dev.js
CHANGED
|
@@ -44,6 +44,7 @@ const {
|
|
|
44
44
|
injectEnvVariables,
|
|
45
45
|
log,
|
|
46
46
|
normalizeConfig,
|
|
47
|
+
normalizeContext,
|
|
47
48
|
openBrowser,
|
|
48
49
|
processOnExit,
|
|
49
50
|
startLiveTunnel,
|
|
@@ -675,10 +676,11 @@ const createDevCommand = (program) => {
|
|
|
675
676
|
`Local dev server\nThe dev command will run a local dev server with Netlify's proxy and redirect rules`,
|
|
676
677
|
)
|
|
677
678
|
.option('-c ,--command <command>', 'command to run')
|
|
678
|
-
.
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
679
|
+
.option(
|
|
680
|
+
'--context <context>',
|
|
681
|
+
'Specify a deploy context or branch for environment variables (contexts: "production", "deploy-preview", "branch-deploy", "dev")',
|
|
682
|
+
normalizeContext,
|
|
683
|
+
'dev',
|
|
682
684
|
)
|
|
683
685
|
.option('-p ,--port <port>', 'port of netlify dev', (value) => Number.parseInt(value))
|
|
684
686
|
.option('--targetPort <port>', 'port of target app server', (value) => Number.parseInt(value))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
const { Option } = require('commander')
|
|
3
3
|
|
|
4
|
-
const { chalk, error, getEnvelopeEnv, log, logJson } = require('../../utils')
|
|
4
|
+
const { chalk, error, getEnvelopeEnv, log, logJson, normalizeContext } = require('../../utils')
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The env:get command
|
|
@@ -60,16 +60,23 @@ const createEnvGetCommand = (program) =>
|
|
|
60
60
|
program
|
|
61
61
|
.command('env:get')
|
|
62
62
|
.argument('<name>', 'Environment variable name')
|
|
63
|
-
.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
.option(
|
|
64
|
+
'-c, --context <context>',
|
|
65
|
+
'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")',
|
|
66
|
+
normalizeContext,
|
|
67
|
+
'dev',
|
|
67
68
|
)
|
|
68
69
|
.addOption(
|
|
69
70
|
new Option('-s, --scope <scope>', 'Specify a scope')
|
|
70
71
|
.choices(['builds', 'functions', 'post_processing', 'runtime', 'any'])
|
|
71
72
|
.default('any'),
|
|
72
73
|
)
|
|
74
|
+
.addExamples([
|
|
75
|
+
'netlify env:get MY_VAR # get value for MY_VAR in dev context',
|
|
76
|
+
'netlify env:get --context production',
|
|
77
|
+
'netlify env:get --context branch:staging',
|
|
78
|
+
'netlify env:get --scope functions',
|
|
79
|
+
])
|
|
73
80
|
.description('Get resolved value of specified environment variable (includes netlify.toml)')
|
|
74
81
|
.action(async (name, options, command) => {
|
|
75
82
|
await envGet(name, options, command)
|
|
@@ -5,7 +5,7 @@ const { Option } = require('commander')
|
|
|
5
5
|
const inquirer = require('inquirer')
|
|
6
6
|
const isEmpty = require('lodash/isEmpty')
|
|
7
7
|
|
|
8
|
-
const { chalk, error, getEnvelopeEnv, getHumanReadableScopes, log, logJson } = require('../../utils')
|
|
8
|
+
const { chalk, error, getEnvelopeEnv, getHumanReadableScopes, log, logJson, normalizeContext } = require('../../utils')
|
|
9
9
|
|
|
10
10
|
const [logUpdatePromise, ansiEscapesPromise] = [import('log-update'), import('ansi-escapes')]
|
|
11
11
|
|
|
@@ -122,16 +122,23 @@ const envList = async (options, command) => {
|
|
|
122
122
|
const createEnvListCommand = (program) =>
|
|
123
123
|
program
|
|
124
124
|
.command('env:list')
|
|
125
|
-
.
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
.option(
|
|
126
|
+
'-c, --context <context>',
|
|
127
|
+
'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev")',
|
|
128
|
+
normalizeContext,
|
|
129
|
+
'dev',
|
|
129
130
|
)
|
|
130
131
|
.addOption(
|
|
131
132
|
new Option('-s, --scope <scope>', 'Specify a scope')
|
|
132
133
|
.choices(['builds', 'functions', 'post_processing', 'runtime', 'any'])
|
|
133
134
|
.default('any'),
|
|
134
135
|
)
|
|
136
|
+
.addExamples([
|
|
137
|
+
'netlify env:list # list dev context and any scope',
|
|
138
|
+
'netlify env:list --context production',
|
|
139
|
+
'netlify env:list --context branch:staging',
|
|
140
|
+
'netlify env:list --scope functions',
|
|
141
|
+
])
|
|
135
142
|
.description('Lists resolved environment variables for site (includes netlify.toml)')
|
|
136
143
|
.action(async (options, command) => {
|
|
137
144
|
await envList(options, command)
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
const { Option } = require('commander')
|
|
3
3
|
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const {
|
|
5
|
+
AVAILABLE_CONTEXTS,
|
|
6
|
+
AVAILABLE_SCOPES,
|
|
7
|
+
chalk,
|
|
8
|
+
error,
|
|
9
|
+
log,
|
|
10
|
+
logJson,
|
|
11
|
+
normalizeContext,
|
|
12
|
+
translateFromEnvelopeToMongo,
|
|
13
|
+
} = require('../../utils')
|
|
7
14
|
|
|
8
15
|
/**
|
|
9
16
|
* The env:set command
|
|
@@ -93,7 +100,10 @@ const setInEnvelope = async ({ api, context, key, scope, siteInfo, value }) => {
|
|
|
93
100
|
const contexts = context || ['all']
|
|
94
101
|
const scopes = scope || AVAILABLE_SCOPES
|
|
95
102
|
|
|
96
|
-
|
|
103
|
+
// if the passed context is unknown, it is actually a branch name
|
|
104
|
+
let values = contexts.map((ctx) =>
|
|
105
|
+
AVAILABLE_CONTEXTS.includes(ctx) ? { context: ctx, value } : { context: 'branch', context_parameter: ctx, value },
|
|
106
|
+
)
|
|
97
107
|
|
|
98
108
|
const existing = envelopeVariables.find((envVar) => envVar.key === key)
|
|
99
109
|
|
|
@@ -144,13 +154,11 @@ const createEnvSetCommand = (program) =>
|
|
|
144
154
|
.command('env:set')
|
|
145
155
|
.argument('<key>', 'Environment variable key')
|
|
146
156
|
.argument('[value]', 'Value to set to', '')
|
|
147
|
-
.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
'dev',
|
|
153
|
-
]),
|
|
157
|
+
.option(
|
|
158
|
+
'-c, --context <context...>',
|
|
159
|
+
'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev") (default: all contexts)',
|
|
160
|
+
// spread over an array for variadic options
|
|
161
|
+
(context, previous = []) => [...previous, normalizeContext(context)],
|
|
154
162
|
)
|
|
155
163
|
.addOption(
|
|
156
164
|
new Option('-s, --scope <scope...>', 'Specify a scope (default: all scopes)').choices([
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
const { Option } = require('commander')
|
|
2
|
-
|
|
3
1
|
// @ts-check
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
const {
|
|
3
|
+
AVAILABLE_CONTEXTS,
|
|
4
|
+
chalk,
|
|
5
|
+
error,
|
|
6
|
+
log,
|
|
7
|
+
logJson,
|
|
8
|
+
normalizeContext,
|
|
9
|
+
translateFromEnvelopeToMongo,
|
|
10
|
+
} = require('../../utils')
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* The env:unset command
|
|
@@ -98,8 +102,10 @@ const unsetInEnvelope = async ({ api, context, key, siteInfo }) => {
|
|
|
98
102
|
const params = { accountId, siteId, key }
|
|
99
103
|
try {
|
|
100
104
|
if (context) {
|
|
101
|
-
// if context(s) are passed, delete the matching contexts, and the `all` context
|
|
102
|
-
const values = variable.values.filter((val) =>
|
|
105
|
+
// if context(s) are passed, delete the matching contexts / branches, and the `all` context
|
|
106
|
+
const values = variable.values.filter((val) =>
|
|
107
|
+
[...contexts, 'all'].includes(val.context_parameter || val.context),
|
|
108
|
+
)
|
|
103
109
|
if (values) {
|
|
104
110
|
await Promise.all(values.map((value) => api.deleteEnvVarValue({ ...params, id: value.id })))
|
|
105
111
|
// if this was the `all` context, we need to create 3 values in the other contexts
|
|
@@ -107,7 +113,9 @@ const unsetInEnvelope = async ({ api, context, key, siteInfo }) => {
|
|
|
107
113
|
const newContexts = AVAILABLE_CONTEXTS.filter((ctx) => !context.includes(ctx))
|
|
108
114
|
const allValue = values[0].value
|
|
109
115
|
await Promise.all(
|
|
110
|
-
newContexts
|
|
116
|
+
newContexts
|
|
117
|
+
.filter((ctx) => ctx !== 'all')
|
|
118
|
+
.map((ctx) => api.setEnvVarValue({ ...params, body: { context: ctx, value: allValue } })),
|
|
111
119
|
)
|
|
112
120
|
}
|
|
113
121
|
}
|
|
@@ -134,13 +142,11 @@ const createEnvUnsetCommand = (program) =>
|
|
|
134
142
|
.command('env:unset')
|
|
135
143
|
.aliases(['env:delete', 'env:remove'])
|
|
136
144
|
.argument('<key>', 'Environment variable key')
|
|
137
|
-
.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
'dev',
|
|
143
|
-
]),
|
|
145
|
+
.option(
|
|
146
|
+
'-c, --context <context...>',
|
|
147
|
+
'Specify a deploy context or branch (contexts: "production", "deploy-preview", "branch-deploy", "dev") (default: all contexts)',
|
|
148
|
+
// spread over an array for variadic options
|
|
149
|
+
(context, previous = []) => [...previous, normalizeContext(context)],
|
|
144
150
|
)
|
|
145
151
|
.addExamples([
|
|
146
152
|
'netlify env:unset VAR_NAME # unset in all contexts',
|
package/src/utils/env/index.js
CHANGED
|
@@ -1,10 +1,39 @@
|
|
|
1
|
+
const AVAILABLE_CONTEXTS = ['all', 'production', 'deploy-preview', 'branch-deploy', 'dev']
|
|
2
|
+
const AVAILABLE_SCOPES = ['builds', 'functions', 'runtime', 'post_processing']
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {string|undefined} context - The deploy context or branch of the environment variable value
|
|
6
|
+
* @returns {Array<string|undefined>} The normalized context or branch name
|
|
7
|
+
*/
|
|
8
|
+
const normalizeContext = (context) => {
|
|
9
|
+
if (!context) {
|
|
10
|
+
return context
|
|
11
|
+
}
|
|
12
|
+
const CONTEXT_SYNONYMS = {
|
|
13
|
+
dp: 'deploy-preview',
|
|
14
|
+
prod: 'production',
|
|
15
|
+
}
|
|
16
|
+
context = context.replace(/^branch:/, '')
|
|
17
|
+
if (CONTEXT_SYNONYMS[context]) {
|
|
18
|
+
context = CONTEXT_SYNONYMS[context]
|
|
19
|
+
}
|
|
20
|
+
return context
|
|
21
|
+
}
|
|
22
|
+
|
|
1
23
|
/**
|
|
2
24
|
* Finds a matching environment variable value from a given context
|
|
3
25
|
* @param {Array<object>} values - An array of environment variable values from Envelope
|
|
4
|
-
* @param {
|
|
5
|
-
* @returns {object<context: enum<dev,branch-deploy,deploy-preview,production>, value: string>} The matching environment variable value object
|
|
26
|
+
* @param {string} context - The deploy context or branch of the environment variable value
|
|
27
|
+
* @returns {object<context: enum<dev,branch-deploy,deploy-preview,production,branch>, context_parameter: <string>, value: string>} The matching environment variable value object
|
|
6
28
|
*/
|
|
7
|
-
const
|
|
29
|
+
const findValueInValues = (values, context) =>
|
|
30
|
+
values.find((val) => {
|
|
31
|
+
if (!AVAILABLE_CONTEXTS.includes(context)) {
|
|
32
|
+
// the "context" option passed in is actually the name of a branch
|
|
33
|
+
return ['branch', 'all'].includes(val.context) && val.context_parameter === context
|
|
34
|
+
}
|
|
35
|
+
return [context, 'all'].includes(val.context)
|
|
36
|
+
})
|
|
8
37
|
|
|
9
38
|
/**
|
|
10
39
|
* Finds environment variables that match a given source
|
|
@@ -45,7 +74,7 @@ const fetchEnvelopeItems = async function ({ accountId, api, key, siteId }) {
|
|
|
45
74
|
|
|
46
75
|
/**
|
|
47
76
|
* Filters and sorts data from Envelope by a given context and/or scope
|
|
48
|
-
* @param {
|
|
77
|
+
* @param {string} context - The deploy context or branch of the environment variable value
|
|
49
78
|
* @param {Array<object>} envelopeItems - An array of environment variables from the Envelope service
|
|
50
79
|
* @param {enum<any,builds,functions,runtime,post_processing>} scope - The scope of the environment variables
|
|
51
80
|
* @param {enum<general,account,addons,ui,configFile>} source - The source of the environment variable
|
|
@@ -58,7 +87,8 @@ const fetchEnvelopeItems = async function ({ accountId, api, key, siteId }) {
|
|
|
58
87
|
* value: 'bar',
|
|
59
88
|
* },
|
|
60
89
|
* BAZ: {
|
|
61
|
-
* context: '
|
|
90
|
+
* context: 'branch',
|
|
91
|
+
* branch: 'staging',
|
|
62
92
|
* scopes: ['runtime'],
|
|
63
93
|
* sources: ['account'],
|
|
64
94
|
* value: 'bang',
|
|
@@ -68,18 +98,19 @@ const fetchEnvelopeItems = async function ({ accountId, api, key, siteId }) {
|
|
|
68
98
|
const formatEnvelopeData = ({ context = 'dev', envelopeItems = [], scope = 'any', source }) =>
|
|
69
99
|
envelopeItems
|
|
70
100
|
// filter by context
|
|
71
|
-
.filter(({ values }) => Boolean(
|
|
101
|
+
.filter(({ values }) => Boolean(findValueInValues(values, context)))
|
|
72
102
|
// filter by scope
|
|
73
103
|
.filter(({ scopes }) => (scope === 'any' ? true : scopes.includes(scope)))
|
|
74
104
|
// sort alphabetically, case insensitive
|
|
75
105
|
.sort((left, right) => (left.key.toLowerCase() < right.key.toLowerCase() ? -1 : 1))
|
|
76
106
|
// format the data
|
|
77
107
|
.reduce((acc, cur) => {
|
|
78
|
-
const { context: ctx, value } =
|
|
108
|
+
const { context: ctx, context_parameter: branch, value } = findValueInValues(cur.values, context)
|
|
79
109
|
return {
|
|
80
110
|
...acc,
|
|
81
111
|
[cur.key]: {
|
|
82
112
|
context: ctx,
|
|
113
|
+
branch,
|
|
83
114
|
scopes: cur.scopes,
|
|
84
115
|
sources: [source],
|
|
85
116
|
value,
|
|
@@ -90,7 +121,7 @@ const formatEnvelopeData = ({ context = 'dev', envelopeItems = [], scope = 'any'
|
|
|
90
121
|
/**
|
|
91
122
|
* Collects env vars from multiple sources and arranges them in the correct order of precedence
|
|
92
123
|
* @param {object} api - The api singleton object
|
|
93
|
-
* @param {
|
|
124
|
+
* @param {string} context - The deploy context or branch of the environment variable
|
|
94
125
|
* @param {object} env - The dictionary of environment variables
|
|
95
126
|
* @param {string} key - If present, fetch a single key (case-sensitive)
|
|
96
127
|
* @param {enum<any,builds,functions,runtime,post_processing>} scope - The scope of the environment variables
|
|
@@ -130,7 +161,7 @@ const getEnvelopeEnv = async ({ api, context = 'dev', env, key = '', scope = 'an
|
|
|
130
161
|
* @returns {string} A human-readable, comma-separated list of scopes
|
|
131
162
|
*/
|
|
132
163
|
const getHumanReadableScopes = (scopes) => {
|
|
133
|
-
const
|
|
164
|
+
const HUMAN_SCOPES = {
|
|
134
165
|
builds: 'Builds',
|
|
135
166
|
functions: 'Functions',
|
|
136
167
|
post_processing: 'Post processing',
|
|
@@ -141,11 +172,11 @@ const getHumanReadableScopes = (scopes) => {
|
|
|
141
172
|
// env vars specified in netlify.toml are present in the `builds` and `post_processing` scope
|
|
142
173
|
return 'Builds, Post processing'
|
|
143
174
|
}
|
|
144
|
-
if (scopes.length === Object.keys(
|
|
175
|
+
if (scopes.length === Object.keys(HUMAN_SCOPES).length) {
|
|
145
176
|
// shorthand instead of listing every available scope
|
|
146
177
|
return 'All'
|
|
147
178
|
}
|
|
148
|
-
return scopes.map((scope) =>
|
|
179
|
+
return scopes.map((scope) => HUMAN_SCOPES[scope]).join(', ')
|
|
149
180
|
}
|
|
150
181
|
|
|
151
182
|
/**
|
|
@@ -156,7 +187,7 @@ const getHumanReadableScopes = (scopes) => {
|
|
|
156
187
|
const translateFromMongoToEnvelope = (env = {}) => {
|
|
157
188
|
const envVars = Object.entries(env).map(([key, value]) => ({
|
|
158
189
|
key,
|
|
159
|
-
scopes:
|
|
190
|
+
scopes: AVAILABLE_SCOPES,
|
|
160
191
|
values: [
|
|
161
192
|
{
|
|
162
193
|
context: 'all',
|
|
@@ -171,14 +202,14 @@ const translateFromMongoToEnvelope = (env = {}) => {
|
|
|
171
202
|
/**
|
|
172
203
|
* Translates an Envelope env into a Mongo env
|
|
173
204
|
* @param {Array<object>} envVars - The array of Envelope env vars
|
|
174
|
-
* @param {
|
|
205
|
+
* @param {string} context - The deploy context or branch of the environment variable
|
|
175
206
|
* @returns {object} The env object as compatible with Mongo
|
|
176
207
|
*/
|
|
177
208
|
const translateFromEnvelopeToMongo = (envVars = [], context = 'dev') =>
|
|
178
209
|
envVars
|
|
179
210
|
.sort((left, right) => (left.key.toLowerCase() < right.key.toLowerCase() ? -1 : 1))
|
|
180
211
|
.reduce((acc, cur) => {
|
|
181
|
-
const envVar = cur.values.find((val) => [context, 'all'].includes(val.context))
|
|
212
|
+
const envVar = cur.values.find((val) => [context, 'all'].includes(val.context_parameter || val.context))
|
|
182
213
|
if (envVar && envVar.value) {
|
|
183
214
|
return {
|
|
184
215
|
...acc,
|
|
@@ -189,11 +220,14 @@ const translateFromEnvelopeToMongo = (envVars = [], context = 'dev') =>
|
|
|
189
220
|
}, {})
|
|
190
221
|
|
|
191
222
|
module.exports = {
|
|
192
|
-
|
|
223
|
+
AVAILABLE_CONTEXTS,
|
|
224
|
+
AVAILABLE_SCOPES,
|
|
225
|
+
findValueInValues,
|
|
193
226
|
filterEnvBySource,
|
|
194
227
|
formatEnvelopeData,
|
|
195
228
|
getEnvelopeEnv,
|
|
196
229
|
getHumanReadableScopes,
|
|
230
|
+
normalizeContext,
|
|
197
231
|
translateFromEnvelopeToMongo,
|
|
198
232
|
translateFromMongoToEnvelope,
|
|
199
233
|
}
|