netlify-cli 8.1.3 → 8.1.4
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 +12 -13
- package/bin/run +38 -2
- package/npm-shrinkwrap.json +1052 -7693
- package/package.json +12 -36
- package/scripts/postinstall.js +13 -0
- package/src/commands/addons/addons-auth.js +50 -0
- package/src/commands/addons/addons-config.js +180 -0
- package/src/commands/addons/addons-create.js +131 -0
- package/src/commands/addons/addons-delete.js +60 -0
- package/src/commands/addons/addons-list.js +62 -0
- package/src/commands/addons/addons.js +44 -0
- package/src/commands/addons/index.js +3 -24
- package/src/commands/api/api.js +75 -0
- package/src/commands/api/index.js +5 -0
- package/src/commands/base-command.js +502 -0
- package/src/commands/build/build.js +58 -0
- package/src/commands/build/index.js +3 -61
- package/src/commands/completion/completion.js +56 -0
- package/src/commands/completion/index.js +5 -0
- package/src/commands/{deploy.js → deploy/deploy.js} +295 -275
- package/src/commands/deploy/index.js +5 -0
- package/src/commands/dev/dev-exec.js +35 -0
- package/src/commands/dev/dev-trace.js +47 -0
- package/src/commands/dev/dev.js +340 -0
- package/src/commands/dev/index.js +3 -335
- package/src/commands/env/env-get.js +51 -0
- package/src/commands/env/env-import.js +93 -0
- package/src/commands/env/env-list.js +63 -0
- package/src/commands/env/env-set.js +67 -0
- package/src/commands/env/env-unset.js +66 -0
- package/src/commands/env/env.js +42 -0
- package/src/commands/env/index.js +3 -23
- package/src/commands/functions/functions-build.js +59 -0
- package/src/commands/functions/{create.js → functions-create.js} +130 -94
- package/src/commands/functions/functions-invoke.js +273 -0
- package/src/commands/functions/functions-list.js +106 -0
- package/src/commands/functions/functions-serve.js +63 -0
- package/src/commands/functions/functions.js +47 -0
- package/src/commands/functions/index.js +3 -45
- package/src/commands/index.js +7 -0
- package/src/commands/init/index.js +6 -0
- package/src/commands/{init.js → init/init.js} +79 -68
- package/src/commands/link/index.js +6 -0
- package/src/{utils/link/link-by-prompt.js → commands/link/link.js} +141 -14
- package/src/commands/lm/index.js +3 -19
- package/src/commands/lm/lm-info.js +42 -0
- package/src/commands/lm/lm-install.js +33 -0
- package/src/commands/lm/lm-setup.js +106 -0
- package/src/commands/lm/lm-uninstall.js +25 -0
- package/src/commands/lm/lm.js +34 -0
- package/src/commands/login/index.js +6 -0
- package/src/commands/login/login.js +55 -0
- package/src/commands/logout/index.js +5 -0
- package/src/commands/logout/logout.js +43 -0
- package/src/commands/main.js +206 -0
- package/src/commands/open/index.js +3 -39
- package/src/commands/open/open-admin.js +60 -0
- package/src/commands/open/open-site.js +53 -0
- package/src/commands/open/open.js +40 -0
- package/src/commands/sites/index.js +5 -20
- package/src/commands/sites/sites-create.js +187 -0
- package/src/commands/sites/sites-delete.js +104 -0
- package/src/commands/sites/sites-list.js +90 -0
- package/src/commands/sites/sites.js +32 -0
- package/src/commands/status/index.js +3 -118
- package/src/commands/status/status-hooks.js +69 -0
- package/src/commands/status/status.js +124 -0
- package/src/commands/switch/index.js +5 -0
- package/src/commands/switch/switch.js +50 -0
- package/src/commands/unlink/index.js +5 -0
- package/src/commands/unlink/unlink.js +48 -0
- package/src/commands/watch/index.js +5 -0
- package/src/commands/watch/watch.js +131 -0
- package/src/functions-templates/javascript/stripe-charge/package-lock.json +6 -6
- package/src/functions-templates/javascript/stripe-subscription/package-lock.json +6 -6
- package/src/lib/build.js +21 -7
- package/src/lib/completion/constants.js +6 -0
- package/src/lib/completion/generate-autocompletion.js +36 -0
- package/src/lib/completion/index.js +5 -0
- package/src/lib/completion/script.js +72 -0
- package/src/lib/exec-fetcher.js +5 -3
- package/src/lib/fs.js +54 -36
- package/src/lib/functions/background.js +1 -1
- package/src/lib/functions/form-submissions-handler.js +2 -1
- package/src/lib/functions/local-proxy.js +2 -1
- package/src/lib/functions/netlify-function.js +4 -1
- package/src/lib/functions/registry.js +4 -6
- package/src/lib/functions/runtimes/go/index.js +2 -1
- package/src/lib/functions/runtimes/js/builders/netlify-lambda.js +6 -4
- package/src/lib/functions/runtimes/js/builders/zisi.js +3 -3
- package/src/lib/functions/runtimes/rust/index.js +4 -3
- package/src/lib/functions/server.js +2 -3
- package/src/lib/functions/synchronous.js +2 -1
- package/src/lib/functions/utils.js +2 -3
- package/src/lib/functions/watcher.js +1 -0
- package/src/lib/http-agent.js +5 -5
- package/src/lib/log.js +2 -1
- package/src/lib/settings.js +16 -1
- package/src/lib/spinner.js +22 -0
- package/src/utils/addons/diffs/index.js +1 -0
- package/src/utils/addons/diffs/options.js +3 -1
- package/src/utils/addons/prepare.js +13 -6
- package/src/utils/addons/prompts.js +2 -1
- package/src/utils/addons/render.js +3 -1
- package/src/utils/command-helpers.js +136 -42
- package/src/utils/create-stream-promise.js +5 -5
- package/src/utils/deferred.js +1 -0
- package/src/utils/deploy/deploy-site.js +1 -1
- package/src/utils/deploy/index.js +4 -0
- package/src/utils/detect-server-settings.js +10 -12
- package/src/utils/dev.js +18 -10
- package/src/utils/dot-env.js +4 -2
- package/src/utils/{edge-handlers.js → functions/edge-handlers.js} +8 -7
- package/src/utils/functions/functions.js +36 -0
- package/src/utils/{get-functions.js → functions/get-functions.js} +2 -1
- package/src/utils/functions/index.js +8 -26
- package/src/utils/get-global-config.js +3 -2
- package/src/utils/get-repo-data.js +8 -1
- package/src/utils/gh-auth.js +1 -0
- package/src/utils/gitignore.js +7 -5
- package/src/utils/headers.js +1 -2
- package/src/utils/index.js +42 -0
- package/src/utils/init/config-github.js +12 -5
- package/src/utils/init/config-manual.js +9 -2
- package/src/utils/init/config.js +13 -7
- package/src/utils/init/frameworks.js +1 -0
- package/src/utils/init/node-version.js +4 -2
- package/src/utils/init/utils.js +10 -6
- package/src/utils/live-tunnel.js +3 -4
- package/src/utils/lm/install.js +10 -15
- package/src/utils/lm/requirements.js +3 -1
- package/src/utils/lm/steps.js +1 -1
- package/src/utils/lm/ui.js +7 -3
- package/src/utils/open-browser.js +8 -2
- package/src/utils/parse-raw-flags.js +4 -4
- package/src/utils/proxy.js +6 -5
- package/src/utils/read-repo-url.js +1 -0
- package/src/utils/redirects.js +2 -2
- package/src/utils/rules-proxy.js +2 -1
- package/src/utils/state-config.js +1 -1
- package/src/utils/telemetry/index.js +2 -113
- package/src/utils/telemetry/request.js +3 -1
- package/src/utils/telemetry/telemetry.js +117 -0
- package/src/utils/telemetry/validation.js +13 -12
- package/src/utils/traffic-mesh.js +3 -3
- package/oclif.manifest.json +0 -1
- package/src/commands/addons/auth.js +0 -42
- package/src/commands/addons/config.js +0 -177
- package/src/commands/addons/create.js +0 -127
- package/src/commands/addons/delete.js +0 -69
- package/src/commands/addons/list.js +0 -54
- package/src/commands/api.js +0 -84
- package/src/commands/dev/exec.js +0 -32
- package/src/commands/dev/trace.js +0 -61
- package/src/commands/env/get.js +0 -44
- package/src/commands/env/import.js +0 -90
- package/src/commands/env/list.js +0 -49
- package/src/commands/env/set.js +0 -64
- package/src/commands/env/unset.js +0 -58
- package/src/commands/functions/build.js +0 -60
- package/src/commands/functions/invoke.js +0 -277
- package/src/commands/functions/list.js +0 -102
- package/src/commands/functions/serve.js +0 -70
- package/src/commands/link.js +0 -133
- package/src/commands/lm/info.js +0 -36
- package/src/commands/lm/install.js +0 -30
- package/src/commands/lm/setup.js +0 -107
- package/src/commands/lm/uninstall.js +0 -17
- package/src/commands/login.js +0 -54
- package/src/commands/logout.js +0 -37
- package/src/commands/open/admin.js +0 -51
- package/src/commands/open/site.js +0 -43
- package/src/commands/sites/create.js +0 -191
- package/src/commands/sites/delete.js +0 -116
- package/src/commands/sites/list.js +0 -84
- package/src/commands/status/hooks.js +0 -60
- package/src/commands/switch.js +0 -44
- package/src/commands/unlink.js +0 -38
- package/src/commands/watch.js +0 -115
- package/src/hooks/init.js +0 -46
- package/src/index.js +0 -25
- package/src/lib/help.js +0 -26
- package/src/utils/chalk.js +0 -16
- package/src/utils/check-command-inputs.js +0 -21
- package/src/utils/command.js +0 -261
- package/src/utils/detect-functions-builder.js +0 -25
- package/src/utils/difference.js +0 -4
- package/src/utils/header.js +0 -18
- package/src/utils/logo.js +0 -11
- package/src/utils/show-help.js +0 -5
- package/src/utils/telemetry/tracked-command.js +0 -51
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
3
|
"description": "Netlify command line tool",
|
|
4
|
-
"version": "8.1.
|
|
4
|
+
"version": "8.1.4",
|
|
5
5
|
"author": "Netlify Inc.",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Mathias Biilmann <matt@netlify.com> (https://twitter.com/biilmann)",
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"/bin",
|
|
18
18
|
"/npm-shrinkwrap.json",
|
|
19
|
-
"/oclif.manifest.json",
|
|
20
19
|
"/scripts/postinstall.js",
|
|
21
20
|
"/src/**/*.js",
|
|
22
21
|
"/src/**/*.sh",
|
|
@@ -58,7 +57,6 @@
|
|
|
58
57
|
"test:dev": "run-s test:init:* test:dev:*",
|
|
59
58
|
"test:ci": "run-s test:ci:*",
|
|
60
59
|
"test:init": "run-s test:init:*",
|
|
61
|
-
"test:init:build": "run-s build:*",
|
|
62
60
|
"test:init:cli-version": "npm run start -- --version",
|
|
63
61
|
"test:init:cli-help": "npm run start -- --help",
|
|
64
62
|
"test:init:eleventy-deps": "npm ci --prefix tests/eleventy-site --no-audit",
|
|
@@ -68,17 +66,16 @@
|
|
|
68
66
|
"test:affected": "node ./tools/affected-test.js",
|
|
69
67
|
"docs": "node ./site/scripts/docs.js",
|
|
70
68
|
"watch": "nyc --reporter=lcov ava --watch",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"postpack": "rm -f oclif.manifest.json && npm i",
|
|
69
|
+
"prepack": "npm prune --prod",
|
|
70
|
+
"postpack": "npm i",
|
|
74
71
|
"site:build": "run-s site:build:*",
|
|
75
72
|
"site:build:install": "cd site && npm ci --no-audit",
|
|
76
73
|
"site:build:assets": "cd site && npm run build",
|
|
77
74
|
"postinstall": "node ./scripts/postinstall.js"
|
|
78
75
|
},
|
|
79
76
|
"config": {
|
|
80
|
-
"eslint": "--ignore-path .gitignore --cache --format=codeframe --max-warnings=0 \"{src,scripts,site,tests,.github}/**/*.{js,md,html}\" \"*.{js,md,html}\" \".*.{js,md,html}\"",
|
|
81
|
-
"prettier": "--ignore-path .gitignore --loglevel=warn \"{src,scripts,site,tests,.github}/**/*.{js,md,yml,json,html}\" \"*.{js,yml,json,html}\" \".*.{js,yml,json,html}\" \"!CHANGELOG.md\" \"!npm-shrinkwrap.json\" \"!.github/**/*.md\""
|
|
77
|
+
"eslint": "--ignore-path .gitignore --cache --format=codeframe --max-warnings=0 \"{src,tools,scripts,site,tests,.github}/**/*.{js,md,html}\" \"*.{js,md,html}\" \".*.{js,md,html}\"",
|
|
78
|
+
"prettier": "--ignore-path .gitignore --loglevel=warn \"{src,tools,scripts,site,tests,.github}/**/*.{js,md,yml,json,html}\" \"*.{js,yml,json,html}\" \".*.{js,yml,json,html}\" \"!CHANGELOG.md\" \"!npm-shrinkwrap.json\" \"!.github/**/*.md\""
|
|
82
79
|
},
|
|
83
80
|
"dependencies": {
|
|
84
81
|
"@netlify/build": "^20.3.1",
|
|
@@ -89,13 +86,6 @@
|
|
|
89
86
|
"@netlify/plugins-list": "^6.2.0",
|
|
90
87
|
"@netlify/routing-local-proxy": "^0.34.1",
|
|
91
88
|
"@netlify/zip-it-and-ship-it": "5.2.0",
|
|
92
|
-
"@oclif/command": "^1.6.1",
|
|
93
|
-
"@oclif/config": "^1.15.1",
|
|
94
|
-
"@oclif/errors": "^1.3.4",
|
|
95
|
-
"@oclif/parser": "^3.8.4",
|
|
96
|
-
"@oclif/plugin-help": "^3.0.0",
|
|
97
|
-
"@oclif/plugin-not-found": "^1.1.4",
|
|
98
|
-
"@oclif/plugin-plugins": "^1.9.3",
|
|
99
89
|
"@octokit/rest": "^18.0.0",
|
|
100
90
|
"@sindresorhus/slugify": "^1.1.0",
|
|
101
91
|
"ansi-styles": "^5.0.0",
|
|
@@ -107,7 +97,7 @@
|
|
|
107
97
|
"chokidar": "^3.0.2",
|
|
108
98
|
"ci-info": "^3.0.0",
|
|
109
99
|
"clean-deep": "^3.0.2",
|
|
110
|
-
"
|
|
100
|
+
"commander": "^8.3.0",
|
|
111
101
|
"concordance": "^5.0.0",
|
|
112
102
|
"configstore": "^5.0.0",
|
|
113
103
|
"content-type": "^1.0.4",
|
|
@@ -142,6 +132,7 @@
|
|
|
142
132
|
"inquirer-autocomplete-prompt": "^1.0.1",
|
|
143
133
|
"is-docker": "^2.0.0",
|
|
144
134
|
"is-plain-obj": "^3.0.0",
|
|
135
|
+
"is-wsl": "^2.2.0",
|
|
145
136
|
"isexe": "^2.0.0",
|
|
146
137
|
"jwt-decode": "^3.0.0",
|
|
147
138
|
"lambda-local": "^2.0.0",
|
|
@@ -160,7 +151,6 @@
|
|
|
160
151
|
"netlify-redirector": "^0.2.1",
|
|
161
152
|
"node-fetch": "^2.6.0",
|
|
162
153
|
"node-version-alias": "^1.0.1",
|
|
163
|
-
"oclif-plugin-completion": "^0.6.0",
|
|
164
154
|
"omit.js": "^2.0.2",
|
|
165
155
|
"open": "^7.0.0",
|
|
166
156
|
"ora": "^5.0.0",
|
|
@@ -179,10 +169,12 @@
|
|
|
179
169
|
"raw-body": "^2.4.1",
|
|
180
170
|
"read-pkg-up": "^7.0.1",
|
|
181
171
|
"resolve": "^1.12.0",
|
|
182
|
-
"semver": "^7.3.
|
|
172
|
+
"semver": "^7.3.5",
|
|
183
173
|
"source-map-support": "^0.5.19",
|
|
184
174
|
"static-server": "^2.2.1",
|
|
175
|
+
"string-similarity": "^4.0.4",
|
|
185
176
|
"strip-ansi-control-characters": "^2.0.0",
|
|
177
|
+
"tabtab": "^3.0.2",
|
|
186
178
|
"tempy": "^1.0.0",
|
|
187
179
|
"through2-filter": "^3.0.0",
|
|
188
180
|
"through2-map": "^3.0.0",
|
|
@@ -200,9 +192,8 @@
|
|
|
200
192
|
"@commitlint/cli": "^15.0.0",
|
|
201
193
|
"@commitlint/config-conventional": "^15.0.0",
|
|
202
194
|
"@netlify/eslint-config-node": "^4.0.0",
|
|
203
|
-
"@oclif/dev-cli": "^1.23.1",
|
|
204
|
-
"@oclif/test": "^2.0.0",
|
|
205
195
|
"ava": "^3.15.0",
|
|
196
|
+
"eslint-plugin-local-rules": "file:tools/eslint-rules",
|
|
206
197
|
"eslint-plugin-sort-destructure-keys": "^1.3.5",
|
|
207
198
|
"fast-glob": "^3.2.7",
|
|
208
199
|
"form-data": "^4.0.0",
|
|
@@ -229,6 +220,7 @@
|
|
|
229
220
|
},
|
|
230
221
|
"ava": {
|
|
231
222
|
"files": [
|
|
223
|
+
"site/**/*.test.js",
|
|
232
224
|
"src/**/*.test.js",
|
|
233
225
|
"tools/**/*.test.js",
|
|
234
226
|
"tests/*.test.js"
|
|
@@ -240,22 +232,6 @@
|
|
|
240
232
|
"tap": false,
|
|
241
233
|
"timeout": "5m"
|
|
242
234
|
},
|
|
243
|
-
"oclif": {
|
|
244
|
-
"bin": "netlify",
|
|
245
|
-
"commands": "./src/commands",
|
|
246
|
-
"helpClass": "./src/lib/help",
|
|
247
|
-
"plugins": [
|
|
248
|
-
"@oclif/plugin-not-found",
|
|
249
|
-
"@oclif/plugin-plugins",
|
|
250
|
-
"@oclif/plugin-help",
|
|
251
|
-
"oclif-plugin-completion"
|
|
252
|
-
],
|
|
253
|
-
"hooks": {
|
|
254
|
-
"init": [
|
|
255
|
-
"./src/hooks/init"
|
|
256
|
-
]
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
235
|
"husky": {
|
|
260
236
|
"hooks": {
|
|
261
237
|
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
const { createMainCommand } = require('../src/commands')
|
|
2
|
+
const { createAutocompletion } = require('../src/lib/completion')
|
|
3
|
+
|
|
1
4
|
const id = (message) => message
|
|
2
5
|
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {string} message
|
|
9
|
+
* @param {Array<chalk['Color'] | chalk['Modifiers']>} styles
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
3
12
|
const format = (message, styles) => {
|
|
4
13
|
let func = id
|
|
5
14
|
try {
|
|
@@ -14,6 +23,10 @@ const format = (message, styles) => {
|
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
const postInstall = () => {
|
|
26
|
+
// create or update the autocompletion definition
|
|
27
|
+
const program = createMainCommand()
|
|
28
|
+
createAutocompletion(program)
|
|
29
|
+
|
|
17
30
|
console.log('')
|
|
18
31
|
console.log(format('Success! Netlify CLI has been installed!', ['greenBright', 'bold', 'underline']))
|
|
19
32
|
console.log('')
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
const { exit, log, openBrowser } = require('../../utils')
|
|
4
|
+
const { ADDON_VALIDATION, prepareAddonCommand } = require('../../utils/addons/prepare')
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The addons:auth command
|
|
8
|
+
* @param {string} addonName
|
|
9
|
+
* @param {import('commander').OptionValues} options
|
|
10
|
+
* @param {import('../base-command').BaseCommand} command
|
|
11
|
+
* @returns {Promise<boolean>}
|
|
12
|
+
*/
|
|
13
|
+
const addonsAuth = async (addonName, options, command) => {
|
|
14
|
+
const { addon } = await prepareAddonCommand({
|
|
15
|
+
command,
|
|
16
|
+
addonName,
|
|
17
|
+
// @ts-ignore when migrating to typescript this should be a const enum
|
|
18
|
+
validation: ADDON_VALIDATION.EXISTS,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
if (!addon.auth_url) {
|
|
22
|
+
log(`No Admin URL found for the "${addonName} add-on"`)
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
log()
|
|
27
|
+
log(`Opening ${addonName} add-on admin URL:`)
|
|
28
|
+
log()
|
|
29
|
+
log(addon.auth_url)
|
|
30
|
+
log()
|
|
31
|
+
await openBrowser({ url: addon.auth_url })
|
|
32
|
+
exit()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates the `netlify addons:auth` command
|
|
37
|
+
* @param {import('../base-command').BaseCommand} program
|
|
38
|
+
* @returns
|
|
39
|
+
*/
|
|
40
|
+
const createAddonsAuthCommand = (program) =>
|
|
41
|
+
program
|
|
42
|
+
.command('addons:auth')
|
|
43
|
+
.alias('addon:auth')
|
|
44
|
+
.argument('<name>', 'Add-on slug')
|
|
45
|
+
.description('Login to add-on provider')
|
|
46
|
+
.action(async (addonName, options, command) => {
|
|
47
|
+
await addonsAuth(addonName, options, command)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
module.exports = { createAddonsAuthCommand }
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const inquirer = require('inquirer')
|
|
3
|
+
const isEmpty = require('lodash/isEmpty')
|
|
4
|
+
|
|
5
|
+
const { chalk, error, log, parseRawFlags } = require('../../utils')
|
|
6
|
+
const compare = require('../../utils/addons/compare')
|
|
7
|
+
const diffValues = require('../../utils/addons/diffs')
|
|
8
|
+
const { ADDON_VALIDATION, prepareAddonCommand } = require('../../utils/addons/prepare')
|
|
9
|
+
const generatePrompts = require('../../utils/addons/prompts')
|
|
10
|
+
const render = require('../../utils/addons/render')
|
|
11
|
+
const { missingConfigValues, requiredConfigValues, updateConfigValues } = require('../../utils/addons/validation')
|
|
12
|
+
|
|
13
|
+
const update = async function ({ addonName, api, currentConfig, instanceId, newConfig, siteId }) {
|
|
14
|
+
const codeDiff = diffValues(currentConfig, newConfig)
|
|
15
|
+
if (!codeDiff) {
|
|
16
|
+
log('No changes, exiting early')
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
log()
|
|
20
|
+
const msg = `Updating ${addonName} add-on config values...`
|
|
21
|
+
log(`${chalk.white.bold(msg)}`)
|
|
22
|
+
log()
|
|
23
|
+
log(`${codeDiff}\n`)
|
|
24
|
+
log()
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
await api.updateServiceInstance({
|
|
28
|
+
siteId,
|
|
29
|
+
addon: addonName,
|
|
30
|
+
instanceId,
|
|
31
|
+
body: { config: newConfig },
|
|
32
|
+
})
|
|
33
|
+
log(`Add-on "${addonName}" successfully updated`)
|
|
34
|
+
} catch (error_) {
|
|
35
|
+
error(error_.message)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The addons:config command
|
|
41
|
+
* @param {string} addonName
|
|
42
|
+
* @param {import('commander').OptionValues} options
|
|
43
|
+
* @param {import('../base-command').BaseCommand} command
|
|
44
|
+
* @returns {Promise<boolean>}
|
|
45
|
+
*/
|
|
46
|
+
const addonsConfig = async (addonName, options, command) => {
|
|
47
|
+
const { addon, manifest, siteData } = await prepareAddonCommand({
|
|
48
|
+
command,
|
|
49
|
+
addonName,
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
validation: ADDON_VALIDATION.EXISTS,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const { api, site } = command.netlify
|
|
55
|
+
const siteId = site.id
|
|
56
|
+
|
|
57
|
+
const hasConfig = !isEmpty(manifest.config)
|
|
58
|
+
// Parse flags
|
|
59
|
+
const rawFlags = parseRawFlags(command.args)
|
|
60
|
+
// Get Existing Config
|
|
61
|
+
const currentConfig = addon.config || {}
|
|
62
|
+
|
|
63
|
+
const words = `Current "${addonName} add-on" Settings:`
|
|
64
|
+
log(` ${chalk.yellowBright.bold(words)}`)
|
|
65
|
+
if (hasConfig) {
|
|
66
|
+
if (!rawFlags.silent) {
|
|
67
|
+
render.configValues(addonName, manifest.config, currentConfig)
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
// For addons without manifest. TODO remove once we enforce manifests
|
|
71
|
+
Object.keys(currentConfig).forEach((key) => {
|
|
72
|
+
log(`${key} - ${currentConfig[key]}`)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (hasConfig) {
|
|
77
|
+
const required = requiredConfigValues(manifest.config)
|
|
78
|
+
const missingValues = missingConfigValues(required, rawFlags)
|
|
79
|
+
|
|
80
|
+
/* Config set by command line flags */
|
|
81
|
+
if (rawFlags && missingValues.length === 0) {
|
|
82
|
+
const newConfig = updateConfigValues(manifest.config, currentConfig, rawFlags)
|
|
83
|
+
|
|
84
|
+
await update({
|
|
85
|
+
addonName,
|
|
86
|
+
currentConfig,
|
|
87
|
+
newConfig,
|
|
88
|
+
siteId,
|
|
89
|
+
instanceId: addon.id,
|
|
90
|
+
api,
|
|
91
|
+
})
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const updatePrompt = await inquirer.prompt([
|
|
96
|
+
{
|
|
97
|
+
type: 'confirm',
|
|
98
|
+
name: 'updateNow',
|
|
99
|
+
message: `Do you want to update config values?`,
|
|
100
|
+
default: false,
|
|
101
|
+
},
|
|
102
|
+
])
|
|
103
|
+
if (!updatePrompt.updateNow) {
|
|
104
|
+
log('Sounds good! Exiting configuration...')
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
log()
|
|
108
|
+
log(` - Hit ${chalk.white.bold('enter')} to keep the existing value in (parentheses)`)
|
|
109
|
+
log(` - Hit ${chalk.white.bold('down arrow')} to remove the value`)
|
|
110
|
+
log(` - Hit ${chalk.white.bold('ctrl + C')} to cancel & exit configuration`)
|
|
111
|
+
log()
|
|
112
|
+
log(` You will need to verify the changed before we push them to your live site!`)
|
|
113
|
+
log()
|
|
114
|
+
const prompts = generatePrompts({
|
|
115
|
+
config: manifest.config,
|
|
116
|
+
configValues: currentConfig,
|
|
117
|
+
})
|
|
118
|
+
const userInput = await inquirer.prompt(prompts)
|
|
119
|
+
// Merge user input with the flags specified
|
|
120
|
+
const newConfig = updateConfigValues(manifest.config, currentConfig, userInput)
|
|
121
|
+
|
|
122
|
+
const diffs = compare(currentConfig, newConfig)
|
|
123
|
+
// log('compare', diffs)
|
|
124
|
+
if (diffs.isEqual) {
|
|
125
|
+
log(`No changes. exiting early`)
|
|
126
|
+
return false
|
|
127
|
+
}
|
|
128
|
+
log()
|
|
129
|
+
log(`${chalk.yellowBright.bold.underline('Confirm your updates:')}`)
|
|
130
|
+
log()
|
|
131
|
+
diffs.keys.forEach((key) => {
|
|
132
|
+
const { newValue, oldValue } = diffs.diffs[key]
|
|
133
|
+
const oldVal = oldValue || 'NO VALUE'
|
|
134
|
+
log(`${chalk.cyan(key)} changed from ${chalk.whiteBright(oldVal)} to ${chalk.green(newValue)}`)
|
|
135
|
+
})
|
|
136
|
+
log()
|
|
137
|
+
|
|
138
|
+
const confirmPrompt = await inquirer.prompt([
|
|
139
|
+
{
|
|
140
|
+
type: 'confirm',
|
|
141
|
+
name: 'confirmChange',
|
|
142
|
+
message: `Do you want to publish the updated "${addonName} add-on" settings for ${chalk.cyan(siteData.name)}?`,
|
|
143
|
+
default: false,
|
|
144
|
+
},
|
|
145
|
+
])
|
|
146
|
+
|
|
147
|
+
if (!confirmPrompt.confirmChange) {
|
|
148
|
+
log('Canceling changes... You are good to go!')
|
|
149
|
+
return false
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
await update({
|
|
153
|
+
addonName,
|
|
154
|
+
currentConfig,
|
|
155
|
+
newConfig,
|
|
156
|
+
siteId,
|
|
157
|
+
instanceId: addon.id,
|
|
158
|
+
api,
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Creates the `netlify addons:config` command
|
|
165
|
+
* @param {import('../base-command').BaseCommand} program
|
|
166
|
+
* @returns
|
|
167
|
+
*/
|
|
168
|
+
const createAddonsConfigCommand = (program) =>
|
|
169
|
+
program
|
|
170
|
+
.command('addons:config')
|
|
171
|
+
.alias('addon:config')
|
|
172
|
+
.argument('<name>', 'Add-on namespace')
|
|
173
|
+
.description('Configure add-on settings')
|
|
174
|
+
// allow for any flags. Handy for variadic configuration options
|
|
175
|
+
.allowUnknownOption(true)
|
|
176
|
+
.action(async (addonName, options, command) => {
|
|
177
|
+
await addonsConfig(addonName, options, command)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
module.exports = { createAddonsConfigCommand }
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const inquirer = require('inquirer')
|
|
3
|
+
const isEmpty = require('lodash/isEmpty')
|
|
4
|
+
|
|
5
|
+
const { chalk, error, log, parseRawFlags } = require('../../utils')
|
|
6
|
+
const { ADDON_VALIDATION, prepareAddonCommand } = require('../../utils/addons/prepare')
|
|
7
|
+
const generatePrompts = require('../../utils/addons/prompts')
|
|
8
|
+
const render = require('../../utils/addons/render')
|
|
9
|
+
const { missingConfigValues, requiredConfigValues, updateConfigValues } = require('../../utils/addons/validation')
|
|
10
|
+
|
|
11
|
+
const createAddon = async ({ addonName, api, config, siteData, siteId }) => {
|
|
12
|
+
try {
|
|
13
|
+
const response = await api.createServiceInstance({
|
|
14
|
+
siteId,
|
|
15
|
+
addon: addonName,
|
|
16
|
+
body: { config },
|
|
17
|
+
})
|
|
18
|
+
log(`Add-on "${addonName}" created for ${siteData.name}`)
|
|
19
|
+
if (response.config && response.config.message) {
|
|
20
|
+
log()
|
|
21
|
+
log(`${response.config.message}`)
|
|
22
|
+
}
|
|
23
|
+
} catch (error_) {
|
|
24
|
+
error(error_.message)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The addons:create command
|
|
30
|
+
* @param {string} addonName
|
|
31
|
+
* @param {import('commander').OptionValues} options
|
|
32
|
+
* @param {import('../base-command').BaseCommand} command
|
|
33
|
+
* @returns {Promise<boolean>}
|
|
34
|
+
*/
|
|
35
|
+
const addonsCreate = async (addonName, options, command) => {
|
|
36
|
+
const { manifest, siteData } = await prepareAddonCommand({
|
|
37
|
+
command,
|
|
38
|
+
addonName,
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
validation: ADDON_VALIDATION.NOT_EXISTS,
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const { api, site } = command.netlify
|
|
44
|
+
const siteId = site.id
|
|
45
|
+
|
|
46
|
+
// GET flags from `raw` data
|
|
47
|
+
const rawFlags = parseRawFlags(command.args)
|
|
48
|
+
const hasConfig = !isEmpty(manifest.config)
|
|
49
|
+
|
|
50
|
+
let configValues = rawFlags
|
|
51
|
+
|
|
52
|
+
if (hasConfig) {
|
|
53
|
+
const required = requiredConfigValues(manifest.config)
|
|
54
|
+
const missingValues = missingConfigValues(required, rawFlags)
|
|
55
|
+
log(`Starting the setup for "${addonName} add-on"`)
|
|
56
|
+
log()
|
|
57
|
+
|
|
58
|
+
if (Object.keys(rawFlags).length !== 0) {
|
|
59
|
+
const newConfig = updateConfigValues(manifest.config, {}, rawFlags)
|
|
60
|
+
|
|
61
|
+
if (missingValues.length !== 0) {
|
|
62
|
+
/* Warn user of missing required values */
|
|
63
|
+
log(`${chalk.redBright.underline.bold(`Error: Missing required configuration for "${addonName} add-on"`)}`)
|
|
64
|
+
log()
|
|
65
|
+
render.missingValues(missingValues, manifest)
|
|
66
|
+
log()
|
|
67
|
+
const msg = `netlify addons:create ${addonName}`
|
|
68
|
+
log(`Please supply the configuration values as CLI flags`)
|
|
69
|
+
log()
|
|
70
|
+
log(`Alternatively, you can run ${chalk.cyan(msg)} with no flags to walk through the setup steps`)
|
|
71
|
+
log()
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
await createAddon({ api, siteId, addonName, config: newConfig, siteData })
|
|
76
|
+
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const words = `The ${addonName} add-on has the following configurable options:`
|
|
81
|
+
log(` ${chalk.yellowBright.bold(words)}`)
|
|
82
|
+
render.configValues(addonName, manifest.config)
|
|
83
|
+
log()
|
|
84
|
+
log(` ${chalk.greenBright.bold('Lets configure those!')}`)
|
|
85
|
+
|
|
86
|
+
log()
|
|
87
|
+
log(` - Hit ${chalk.white.bold('enter')} to confirm value or set empty value`)
|
|
88
|
+
log(` - Hit ${chalk.white.bold('ctrl + C')} to cancel & exit configuration`)
|
|
89
|
+
log()
|
|
90
|
+
|
|
91
|
+
const prompts = generatePrompts({
|
|
92
|
+
config: manifest.config,
|
|
93
|
+
configValues: rawFlags,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const userInput = await inquirer.prompt(prompts)
|
|
97
|
+
// Merge user input with the flags specified
|
|
98
|
+
configValues = updateConfigValues(manifest.config, rawFlags, userInput)
|
|
99
|
+
const missingRequiredValues = missingConfigValues(required, configValues)
|
|
100
|
+
if (missingRequiredValues && missingRequiredValues.length !== 0) {
|
|
101
|
+
missingRequiredValues.forEach((val) => {
|
|
102
|
+
log(`Missing required value "${val}". Please run the command again`)
|
|
103
|
+
})
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
await createAddon({ api, siteId, addonName, config: configValues, siteData })
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Creates the `netlify addons:create` command
|
|
113
|
+
* @param {import('../base-command').BaseCommand} program
|
|
114
|
+
* @returns
|
|
115
|
+
*/
|
|
116
|
+
const createAddonsCreateCommand = (program) =>
|
|
117
|
+
program
|
|
118
|
+
.command('addons:create')
|
|
119
|
+
.alias('addon:create')
|
|
120
|
+
.argument('<name>', 'Add-on namespace')
|
|
121
|
+
.description(
|
|
122
|
+
`Add an add-on extension to your site
|
|
123
|
+
Add-ons are a way to extend the functionality of your Netlify site`,
|
|
124
|
+
)
|
|
125
|
+
// allow for any flags. Handy for variadic configuration options
|
|
126
|
+
.allowUnknownOption(true)
|
|
127
|
+
.action(async (addonName, options, command) => {
|
|
128
|
+
await addonsCreate(addonName, options, command)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
module.exports = { createAddonsCreateCommand }
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const inquirer = require('inquirer')
|
|
3
|
+
|
|
4
|
+
const { error, exit, log } = require('../../utils')
|
|
5
|
+
const { ADDON_VALIDATION, prepareAddonCommand } = require('../../utils/addons/prepare')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The addons:delete command
|
|
9
|
+
* @param {string} addonName
|
|
10
|
+
* @param {import('commander').OptionValues} options
|
|
11
|
+
* @param {import('../base-command').BaseCommand} command
|
|
12
|
+
*/
|
|
13
|
+
const addonsDelete = async (addonName, options, command) => {
|
|
14
|
+
const { addon } = await prepareAddonCommand({
|
|
15
|
+
command,
|
|
16
|
+
addonName,
|
|
17
|
+
// @ts-ignore.
|
|
18
|
+
validation: ADDON_VALIDATION.EXISTS,
|
|
19
|
+
})
|
|
20
|
+
if (!options.force && !options.f) {
|
|
21
|
+
const { wantsToDelete } = await inquirer.prompt({
|
|
22
|
+
type: 'confirm',
|
|
23
|
+
name: 'wantsToDelete',
|
|
24
|
+
message: `Are you sure you want to delete the ${addonName} add-on? (to skip this prompt, pass a --force flag)`,
|
|
25
|
+
default: false,
|
|
26
|
+
})
|
|
27
|
+
if (!wantsToDelete) {
|
|
28
|
+
exit()
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
await command.netlify.api.deleteServiceInstance({
|
|
34
|
+
siteId: command.netlify.site.id,
|
|
35
|
+
addon: addonName,
|
|
36
|
+
instanceId: addon.id,
|
|
37
|
+
})
|
|
38
|
+
log(`Addon "${addonName}" deleted`)
|
|
39
|
+
} catch (error_) {
|
|
40
|
+
error(error_.message)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Creates the `netlify addons:delete` command
|
|
46
|
+
* @param {import('../base-command').BaseCommand} program
|
|
47
|
+
* @returns
|
|
48
|
+
*/
|
|
49
|
+
const createAddonsDeleteCommand = (program) =>
|
|
50
|
+
program
|
|
51
|
+
.command('addons:delete')
|
|
52
|
+
.alias('addon:delete')
|
|
53
|
+
.argument('<name>', 'Add-on namespace')
|
|
54
|
+
.description(
|
|
55
|
+
`Remove an add-on extension to your site\nAdd-ons are a way to extend the functionality of your Netlify site`,
|
|
56
|
+
)
|
|
57
|
+
.option('-f, --force', 'delete without prompting (useful for CI)')
|
|
58
|
+
.action(addonsDelete)
|
|
59
|
+
|
|
60
|
+
module.exports = { createAddonsDeleteCommand }
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
const AsciiTable = require('ascii-table')
|
|
4
|
+
|
|
5
|
+
const { log, logJson } = require('../../utils')
|
|
6
|
+
const { prepareAddonCommand } = require('../../utils/addons/prepare')
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The addons:list command
|
|
10
|
+
* @param {import('commander').OptionValues} options
|
|
11
|
+
* @param {import('../base-command').BaseCommand} command
|
|
12
|
+
* @returns {Promise<boolean>}
|
|
13
|
+
*/
|
|
14
|
+
const addonsList = async (options, command) => {
|
|
15
|
+
const { addons, siteData } = await prepareAddonCommand({ command })
|
|
16
|
+
// Return json response for piping commands
|
|
17
|
+
if (options.json) {
|
|
18
|
+
logJson(addons)
|
|
19
|
+
return false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!addons || addons.length === 0) {
|
|
23
|
+
log(`No addons currently installed for ${siteData.name}`)
|
|
24
|
+
log(`> Run \`netlify addons:create addon-namespace\` to install an addon`)
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const addonData = addons.map((addon) => ({
|
|
29
|
+
namespace: addon.service_path.replace('/.netlify/', ''),
|
|
30
|
+
name: addon.service_name,
|
|
31
|
+
id: addon.id,
|
|
32
|
+
}))
|
|
33
|
+
|
|
34
|
+
// Build a table out of addons
|
|
35
|
+
log(`site: ${siteData.name}`)
|
|
36
|
+
const table = new AsciiTable(`Currently Installed addons`)
|
|
37
|
+
|
|
38
|
+
table.setHeading('NameSpace', 'Name', 'Instance Id')
|
|
39
|
+
|
|
40
|
+
addonData.forEach(({ id, name, namespace }) => {
|
|
41
|
+
table.addRow(namespace, name, id)
|
|
42
|
+
})
|
|
43
|
+
// Log da addons
|
|
44
|
+
log(table.toString())
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Creates the `netlify addons:list` command
|
|
49
|
+
* @param {import('../base-command').BaseCommand} program
|
|
50
|
+
* @returns
|
|
51
|
+
*/
|
|
52
|
+
const createAddonsListCommand = (program) =>
|
|
53
|
+
program
|
|
54
|
+
.command('addons:list')
|
|
55
|
+
.alias('addon:list')
|
|
56
|
+
.description(`List currently installed add-ons for site`)
|
|
57
|
+
.option('--json', 'Output add-on data as JSON')
|
|
58
|
+
.action(async (options, command) => {
|
|
59
|
+
await addonsList(options, command)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
module.exports = { createAddonsListCommand }
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
const { createAddonsAuthCommand } = require('./addons-auth')
|
|
4
|
+
const { createAddonsConfigCommand } = require('./addons-config')
|
|
5
|
+
const { createAddonsCreateCommand } = require('./addons-create')
|
|
6
|
+
const { createAddonsDeleteCommand } = require('./addons-delete')
|
|
7
|
+
const { createAddonsListCommand } = require('./addons-list')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The addons command
|
|
11
|
+
* @param {import('commander').OptionValues} options
|
|
12
|
+
* @param {import('../base-command').BaseCommand} command
|
|
13
|
+
*/
|
|
14
|
+
const addons = (options, command) => {
|
|
15
|
+
command.help()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates the `netlify addons` command
|
|
20
|
+
* @param {import('../base-command').BaseCommand} program
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
const createAddonsCommand = (program) => {
|
|
24
|
+
createAddonsAuthCommand(program)
|
|
25
|
+
createAddonsConfigCommand(program)
|
|
26
|
+
createAddonsCreateCommand(program)
|
|
27
|
+
createAddonsDeleteCommand(program)
|
|
28
|
+
createAddonsListCommand(program)
|
|
29
|
+
|
|
30
|
+
return program
|
|
31
|
+
.command('addons')
|
|
32
|
+
.alias('addon')
|
|
33
|
+
.description('(Beta) Manage Netlify Add-ons')
|
|
34
|
+
.noHelpOptions()
|
|
35
|
+
.addExamples([
|
|
36
|
+
'netlify addons:create addon-xyz',
|
|
37
|
+
'netlify addons:list',
|
|
38
|
+
'netlify addons:config addon-xyz',
|
|
39
|
+
'netlify addons:delete addon-xyz',
|
|
40
|
+
'netlify addons:auth addon-xyz',
|
|
41
|
+
])
|
|
42
|
+
.action(addons)
|
|
43
|
+
}
|
|
44
|
+
module.exports = { createAddonsCommand }
|