netlify-cli 8.0.10 → 8.1.0-rc
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/bin/run +81 -3
- package/npm-shrinkwrap.json +471 -2182
- package/package.json +12 -35
- 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 +129 -0
- package/src/commands/addons/addons-delete.js +59 -0
- package/src/commands/addons/addons-list.js +62 -0
- package/src/commands/addons/addons.js +49 -0
- package/src/commands/addons/index.js +3 -24
- package/src/commands/api/api.js +83 -0
- package/src/commands/api/index.js +5 -0
- package/src/commands/base-command.js +322 -0
- package/src/commands/build/build.js +58 -0
- package/src/commands/build/index.js +3 -61
- package/src/commands/completion/completion.js +18 -0
- package/src/commands/completion/index.js +5 -0
- package/src/commands/{deploy.js → deploy/deploy.js} +306 -278
- package/src/commands/deploy/index.js +5 -0
- package/src/commands/dev/dev-exec.js +39 -0
- package/src/commands/dev/dev-trace.js +50 -0
- package/src/commands/dev/dev.js +349 -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 +47 -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} +133 -94
- package/src/commands/functions/functions-invoke.js +276 -0
- package/src/commands/functions/functions-list.js +107 -0
- package/src/commands/functions/functions-serve.js +63 -0
- package/src/commands/functions/functions.js +53 -0
- package/src/commands/functions/index.js +3 -45
- package/src/commands/index.js +5 -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} +153 -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 +36 -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 +39 -0
- package/src/commands/login/index.js +6 -0
- package/src/commands/login/login.js +52 -0
- package/src/commands/logout/index.js +5 -0
- package/src/commands/logout/logout.js +43 -0
- package/src/commands/main.js +117 -0
- package/src/commands/open/index.js +3 -39
- package/src/commands/open/open-admin.js +56 -0
- package/src/commands/open/open-site.js +49 -0
- package/src/commands/open/open.js +42 -0
- package/src/commands/sites/index.js +5 -20
- package/src/commands/sites/sites-create.js +184 -0
- package/src/commands/sites/sites-delete.js +108 -0
- package/src/commands/sites/sites-list.js +89 -0
- package/src/commands/sites/sites.js +36 -0
- package/src/commands/status/index.js +3 -118
- package/src/commands/status/status-hooks.js +73 -0
- package/src/commands/status/status.js +125 -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 +121 -0
- package/src/lib/build.js +21 -7
- 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/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 +156 -43
- 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 +1 -0
- package/src/utils/gh-auth.js +1 -0
- package/src/utils/gitignore.js +7 -5
- package/src/utils/header.js +2 -2
- 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/plugins.js +1 -0
- 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 +7 -5
- package/src/utils/read-repo-url.js +1 -0
- package/src/utils/redirects.js +2 -2
- package/src/utils/rules-proxy.js +4 -2
- 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/logo.js +0 -11
- package/src/utils/show-help.js +0 -5
- package/src/utils/telemetry/tracked-command.js +0 -51
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
const chalk = require('chalk')
|
|
1
|
+
// @ts-check
|
|
3
2
|
const dotProp = require('dot-prop')
|
|
4
3
|
const inquirer = require('inquirer')
|
|
5
4
|
const isEmpty = require('lodash/isEmpty')
|
|
6
5
|
|
|
7
|
-
const
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
10
|
-
const
|
|
11
|
-
const { configureRepo } = require('../utils/init/config')
|
|
12
|
-
const { track } = require('../utils/telemetry')
|
|
13
|
-
|
|
14
|
-
const LinkCommand = require('./link')
|
|
15
|
-
const SitesCreateCommand = require('./sites/create')
|
|
6
|
+
const { chalk, ensureNetlifyIgnore, exit, getRepoData, log, track } = require('../../utils')
|
|
7
|
+
const { configureRepo } = require('../../utils/init/config')
|
|
8
|
+
const { link } = require('../link')
|
|
9
|
+
const { sitesCreate } = require('../sites')
|
|
16
10
|
|
|
17
11
|
const persistState = ({ siteInfo, state }) => {
|
|
18
12
|
// Save to .netlify/state.json file
|
|
@@ -37,8 +31,14 @@ const logExistingAndExit = ({ siteInfo }) => {
|
|
|
37
31
|
exit()
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Creates and new site and exits the process
|
|
36
|
+
* @param {object} config
|
|
37
|
+
* @param {*} config.state
|
|
38
|
+
* @param {import('../base-command').BaseCommand} config.command
|
|
39
|
+
*/
|
|
40
|
+
const createNewSiteAndExit = async ({ command, state }) => {
|
|
41
|
+
const siteInfo = await sitesCreate({}, command)
|
|
42
42
|
|
|
43
43
|
log(`"${siteInfo.name}" site was created`)
|
|
44
44
|
log()
|
|
@@ -82,7 +82,14 @@ const logGitSetupInstructionsAndExit = () => {
|
|
|
82
82
|
exit()
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Handles the case where no git remote was found.
|
|
87
|
+
* @param {object} config
|
|
88
|
+
* @param {import('../base-command').BaseCommand} config.command
|
|
89
|
+
* @param {object} config.error
|
|
90
|
+
* @param {object} config.state
|
|
91
|
+
*/
|
|
92
|
+
const handleNoGitRemoteAndExit = async ({ command, error, state }) => {
|
|
86
93
|
log()
|
|
87
94
|
log(`${chalk.yellow('No git remote was found, would you like to set one up?')}`)
|
|
88
95
|
log(`
|
|
@@ -112,13 +119,17 @@ git remote add origin https://github.com/YourUserName/RepoName.git
|
|
|
112
119
|
])
|
|
113
120
|
|
|
114
121
|
if (noGitRemoteChoice === NEW_SITE_NO_GIT) {
|
|
115
|
-
await createNewSiteAndExit({ state })
|
|
122
|
+
await createNewSiteAndExit({ state, command })
|
|
116
123
|
} else if (noGitRemoteChoice === NO_ABORT) {
|
|
117
124
|
logGitSetupInstructionsAndExit()
|
|
118
125
|
}
|
|
119
126
|
}
|
|
120
127
|
|
|
121
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Creates a new site or links an existing one to the repository
|
|
130
|
+
* @param {import('../base-command').BaseCommand} command
|
|
131
|
+
*/
|
|
132
|
+
const createOrLinkSiteToRepo = async (command) => {
|
|
122
133
|
const NEW_SITE = '+ Create & configure a new site'
|
|
123
134
|
const EXISTING_SITE = '⇄ Connect this directory to an existing Netlify site'
|
|
124
135
|
|
|
@@ -139,11 +150,11 @@ const createOrLinkSiteToRepo = async () => {
|
|
|
139
150
|
type: 'new site',
|
|
140
151
|
})
|
|
141
152
|
// run site:create command
|
|
142
|
-
return await
|
|
153
|
+
return await sitesCreate({}, command)
|
|
143
154
|
}
|
|
144
155
|
if (initChoice === EXISTING_SITE) {
|
|
145
156
|
// run link command
|
|
146
|
-
return await
|
|
157
|
+
return await link({}, command)
|
|
147
158
|
}
|
|
148
159
|
}
|
|
149
160
|
|
|
@@ -155,65 +166,65 @@ const logExistingRepoSetupAndExit = ({ repoUrl, siteName }) => {
|
|
|
155
166
|
exit()
|
|
156
167
|
}
|
|
157
168
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const { repositoryRoot, state } = netlify
|
|
166
|
-
let { siteInfo } = this.netlify
|
|
169
|
+
/**
|
|
170
|
+
* The init command
|
|
171
|
+
* @param {import('commander').OptionValues} options
|
|
172
|
+
* @param {import('../base-command').BaseCommand} command
|
|
173
|
+
*/
|
|
174
|
+
const init = async (options, command) => {
|
|
175
|
+
command.setAnalyticsPayload({ manual: options.manual, force: options.force })
|
|
167
176
|
|
|
168
|
-
|
|
169
|
-
|
|
177
|
+
const { repositoryRoot, state } = command.netlify
|
|
178
|
+
let { siteInfo } = command.netlify
|
|
170
179
|
|
|
171
|
-
|
|
172
|
-
|
|
180
|
+
// Check logged in status
|
|
181
|
+
await command.authenticate()
|
|
173
182
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
logExistingAndExit({ siteInfo })
|
|
177
|
-
}
|
|
183
|
+
// Add .netlify to .gitignore file
|
|
184
|
+
await ensureNetlifyIgnore(repositoryRoot)
|
|
178
185
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
186
|
+
const repoUrl = getRepoUrl({ siteInfo })
|
|
187
|
+
if (repoUrl && !options.force) {
|
|
188
|
+
logExistingAndExit({ siteInfo })
|
|
189
|
+
}
|
|
184
190
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
191
|
+
// Look for local repo
|
|
192
|
+
const repoData = await getRepoData({ remoteName: options.gitRemoteName })
|
|
193
|
+
if (repoData.error) {
|
|
194
|
+
await handleNoGitRemoteAndExit({ command, error: repoData.error, state })
|
|
195
|
+
}
|
|
188
196
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
logExistingRepoSetupAndExit({ siteName: siteInfo.name, repoUrl: remoteBuildRepo })
|
|
193
|
-
}
|
|
197
|
+
if (isEmpty(siteInfo)) {
|
|
198
|
+
siteInfo = await createOrLinkSiteToRepo(command)
|
|
199
|
+
}
|
|
194
200
|
|
|
195
|
-
|
|
201
|
+
// Check for existing CI setup
|
|
202
|
+
const remoteBuildRepo = getRepoUrl({ siteInfo })
|
|
203
|
+
if (remoteBuildRepo && !options.force) {
|
|
204
|
+
logExistingRepoSetupAndExit({ siteName: siteInfo.name, repoUrl: remoteBuildRepo })
|
|
205
|
+
}
|
|
196
206
|
|
|
197
|
-
|
|
207
|
+
persistState({ state, siteInfo })
|
|
198
208
|
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
}
|
|
209
|
+
await configureRepo({ command, siteId: siteInfo.id, repoData, manual: options.manual })
|
|
202
210
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
InitCommand.flags = {
|
|
206
|
-
manual: flagsLib.boolean({
|
|
207
|
-
char: 'm',
|
|
208
|
-
description: 'Manually configure a git remote for CI',
|
|
209
|
-
}),
|
|
210
|
-
force: flagsLib.boolean({
|
|
211
|
-
description: 'Reinitialize CI hooks if the linked site is already configured to use CI',
|
|
212
|
-
}),
|
|
213
|
-
gitRemoteName: flagsLib.string({
|
|
214
|
-
description: 'Name of Git remote to use. e.g. "origin"',
|
|
215
|
-
}),
|
|
216
|
-
...InitCommand.flags,
|
|
211
|
+
return siteInfo
|
|
217
212
|
}
|
|
218
213
|
|
|
219
|
-
|
|
214
|
+
/**
|
|
215
|
+
* Creates the `netlify init` command
|
|
216
|
+
* @param {import('../base-command').BaseCommand} program
|
|
217
|
+
* @returns
|
|
218
|
+
*/
|
|
219
|
+
const createInitCommand = (program) =>
|
|
220
|
+
program
|
|
221
|
+
.command('init')
|
|
222
|
+
.description(
|
|
223
|
+
'Configure continuous deployment for a new or existing site. To create a new site without continuous deployment, use `netlify sites:create`',
|
|
224
|
+
)
|
|
225
|
+
.option('-m, --manual', 'Manually configure a git remote for CI')
|
|
226
|
+
.option('--force', 'Manually configure a git remote for CI')
|
|
227
|
+
.option('--gitRemoteName <name>', 'Name of Git remote to use. e.g. "origin"')
|
|
228
|
+
.action(init)
|
|
229
|
+
|
|
230
|
+
module.exports = { createInitCommand, init }
|
|
@@ -1,16 +1,30 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { join, relative } = require('path')
|
|
1
3
|
const path = require('path')
|
|
4
|
+
const { cwd } = require('process')
|
|
2
5
|
|
|
3
|
-
const chalk = require('chalk')
|
|
4
6
|
const inquirer = require('inquirer')
|
|
5
7
|
const isEmpty = require('lodash/isEmpty')
|
|
6
8
|
|
|
7
9
|
const { listSites } = require('../../lib/api')
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const {
|
|
11
|
+
chalk,
|
|
12
|
+
ensureNetlifyIgnore,
|
|
13
|
+
error,
|
|
14
|
+
exit,
|
|
15
|
+
generateExamplesHelp,
|
|
16
|
+
getRepoData,
|
|
17
|
+
log,
|
|
18
|
+
track,
|
|
19
|
+
} = require('../../utils')
|
|
11
20
|
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
* @param {import('../base-command').NetlifyOptions} netlify
|
|
24
|
+
* @param {import('commander').OptionValues} options
|
|
25
|
+
*/
|
|
26
|
+
const linkPrompt = async (netlify, options) => {
|
|
27
|
+
const { api, state } = netlify
|
|
14
28
|
|
|
15
29
|
const SITE_NAME_PROMPT = 'Search by full or partial site name'
|
|
16
30
|
const SITE_LIST_PROMPT = 'Choose from a list of your recently updated sites'
|
|
@@ -19,7 +33,7 @@ module.exports = async function linkPrompts(context, flags = {}) {
|
|
|
19
33
|
let GIT_REMOTE_PROMPT = 'Use the current git remote origin URL'
|
|
20
34
|
let site
|
|
21
35
|
// Get git remote data if exists
|
|
22
|
-
const repoData = await getRepoData({ remoteName:
|
|
36
|
+
const repoData = await getRepoData({ remoteName: options.gitRemoteName })
|
|
23
37
|
|
|
24
38
|
let linkChoices = [SITE_NAME_PROMPT, SITE_LIST_PROMPT, SITE_ID_PROMPT]
|
|
25
39
|
|
|
@@ -51,9 +65,7 @@ module.exports = async function linkPrompts(context, flags = {}) {
|
|
|
51
65
|
const sites = await listSites({ api, options: { filter: 'all' } })
|
|
52
66
|
|
|
53
67
|
if (isEmpty(sites)) {
|
|
54
|
-
|
|
55
|
-
new Error(`You don't have any sites yet. Run ${chalk.cyanBright('netlify sites:create')} to create a site.`),
|
|
56
|
-
)
|
|
68
|
+
error(`You don't have any sites yet. Run ${chalk.cyanBright('netlify sites:create')} to create a site.`)
|
|
57
69
|
}
|
|
58
70
|
|
|
59
71
|
const matchingSites = sites.filter(
|
|
@@ -79,7 +91,7 @@ Run ${chalk.cyanBright('git remote -v')} to see a list of your git remotes.`)
|
|
|
79
91
|
site = firstSite
|
|
80
92
|
} else if (matchingSites.length > 1) {
|
|
81
93
|
// Matches multiple sites. Users must choose which to link.
|
|
82
|
-
|
|
94
|
+
log(`Found ${matchingSites.length} matching sites!`)
|
|
83
95
|
|
|
84
96
|
// Prompt which options
|
|
85
97
|
const { selectedSite } = await inquirer.prompt([
|
|
@@ -134,7 +146,7 @@ or run ${chalk.cyanBright('netlify sites:create')} to create a site.`)
|
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
if (matchingSites.length > 1) {
|
|
137
|
-
|
|
149
|
+
log(`Found ${matchingSites.length} matching sites!`)
|
|
138
150
|
const { selectedSite } = await inquirer.prompt([
|
|
139
151
|
{
|
|
140
152
|
type: 'list',
|
|
@@ -145,7 +157,7 @@ or run ${chalk.cyanBright('netlify sites:create')} to create a site.`)
|
|
|
145
157
|
},
|
|
146
158
|
])
|
|
147
159
|
if (!selectedSite) {
|
|
148
|
-
|
|
160
|
+
error('No site selected')
|
|
149
161
|
}
|
|
150
162
|
site = selectedSite
|
|
151
163
|
} else {
|
|
@@ -196,6 +208,7 @@ or run ${chalk.cyanBright('netlify sites:create')} to create a site.`)
|
|
|
196
208
|
])
|
|
197
209
|
|
|
198
210
|
try {
|
|
211
|
+
// @ts-ignore types from API are wrong they cannot recognize `getSite` of API
|
|
199
212
|
site = await api.getSite({ siteId })
|
|
200
213
|
} catch (error_) {
|
|
201
214
|
if (error_.status === 404) {
|
|
@@ -231,10 +244,136 @@ or run ${chalk.cyanBright('netlify sites:create')} to create a site.`)
|
|
|
231
244
|
log(`Site url: ${chalk.cyanBright(site.ssl_url || site.url)}`)
|
|
232
245
|
log()
|
|
233
246
|
|
|
234
|
-
log(`Site id saved to ${path.join(
|
|
247
|
+
log(`Site id saved to ${path.join(netlify.site.root, '/.netlify/state.json')}`)
|
|
235
248
|
// log(`Local Config: .netlify/config.json`)
|
|
236
249
|
log()
|
|
237
250
|
log(`You can now run other \`netlify\` cli commands in this directory`)
|
|
238
251
|
|
|
239
252
|
return site
|
|
240
253
|
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The link command
|
|
257
|
+
* @param {import('commander').OptionValues} options
|
|
258
|
+
* @param {import('../base-command').BaseCommand} command
|
|
259
|
+
*/
|
|
260
|
+
const link = async (options, command) => {
|
|
261
|
+
await command.authenticate()
|
|
262
|
+
|
|
263
|
+
const {
|
|
264
|
+
api,
|
|
265
|
+
repositoryRoot,
|
|
266
|
+
site: { id: siteId },
|
|
267
|
+
state,
|
|
268
|
+
} = command.netlify
|
|
269
|
+
|
|
270
|
+
let siteData
|
|
271
|
+
try {
|
|
272
|
+
// @ts-ignore types from API are wrong they cannot recognize `getSite` of API
|
|
273
|
+
siteData = await api.getSite({ siteId })
|
|
274
|
+
} catch {
|
|
275
|
+
// silent api error
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Add .netlify to .gitignore file
|
|
279
|
+
await ensureNetlifyIgnore(repositoryRoot)
|
|
280
|
+
|
|
281
|
+
// Site id is incorrect
|
|
282
|
+
if (siteId && !siteData) {
|
|
283
|
+
log(`"${siteId}" was not found in your Netlify account.`)
|
|
284
|
+
log(`Please double check your siteID and which account you are logged into via \`netlify status\`.`)
|
|
285
|
+
return exit()
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// If already linked to site. exit and prompt for unlink
|
|
289
|
+
if (siteData) {
|
|
290
|
+
log(`Site already linked to "${siteData.name}"`)
|
|
291
|
+
log(`Admin url: ${siteData.admin_url}`)
|
|
292
|
+
log()
|
|
293
|
+
log(`To unlink this site, run: ${chalk.cyanBright('netlify unlink')}`)
|
|
294
|
+
return exit()
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (options.id) {
|
|
298
|
+
try {
|
|
299
|
+
// @ts-ignore types from API are wrong they cannot recognize `getSite` of API
|
|
300
|
+
siteData = await api.getSite({ site_id: options.id })
|
|
301
|
+
} catch (error_) {
|
|
302
|
+
if (error_.status === 404) {
|
|
303
|
+
error(new Error(`Site id ${options.id} not found`))
|
|
304
|
+
} else {
|
|
305
|
+
error(error_)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Save site ID
|
|
310
|
+
state.set('siteId', siteData.id)
|
|
311
|
+
log(`Linked to ${siteData.name} in ${state.path}`)
|
|
312
|
+
|
|
313
|
+
await track('sites_linked', {
|
|
314
|
+
siteId: siteData.id,
|
|
315
|
+
linkType: 'manual',
|
|
316
|
+
kind: 'byId',
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
return exit()
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (options.name) {
|
|
323
|
+
let results
|
|
324
|
+
try {
|
|
325
|
+
results = await listSites({
|
|
326
|
+
api,
|
|
327
|
+
options: {
|
|
328
|
+
name: options.name,
|
|
329
|
+
filter: 'all',
|
|
330
|
+
},
|
|
331
|
+
})
|
|
332
|
+
} catch (error_) {
|
|
333
|
+
if (error_.status === 404) {
|
|
334
|
+
error(new Error(`${options.name} not found`))
|
|
335
|
+
} else {
|
|
336
|
+
error(error_)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (results.length === 0) {
|
|
341
|
+
error(new Error(`No sites found named ${options.name}`))
|
|
342
|
+
}
|
|
343
|
+
const [firstSiteData] = results
|
|
344
|
+
state.set('siteId', firstSiteData.id)
|
|
345
|
+
|
|
346
|
+
log(`Linked to ${firstSiteData.name} in ${relative(join(cwd(), '..'), state.path)}`)
|
|
347
|
+
|
|
348
|
+
await track('sites_linked', {
|
|
349
|
+
siteId: (firstSiteData && firstSiteData.id) || siteId,
|
|
350
|
+
linkType: 'manual',
|
|
351
|
+
kind: 'byName',
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
return exit()
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
siteData = await linkPrompt(command.netlify, options)
|
|
358
|
+
return siteData
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Creates the `netlify link` command
|
|
363
|
+
* @param {import('../base-command').BaseCommand} program
|
|
364
|
+
* @returns
|
|
365
|
+
*/
|
|
366
|
+
const createLinkCommand = (program) =>
|
|
367
|
+
program
|
|
368
|
+
.command('link')
|
|
369
|
+
.description('Link a local repo or project folder to an existing site on Netlify')
|
|
370
|
+
.option('--id <id>', 'ID of site to link to')
|
|
371
|
+
.option('--name <name>', 'Name of site to link to')
|
|
372
|
+
.option('--gitRemoteName <name>', 'Name of Git remote to use. e.g. "origin"')
|
|
373
|
+
.addHelpText(
|
|
374
|
+
'after',
|
|
375
|
+
generateExamplesHelp(['netlify link', 'netlify link --id 123-123-123-123', 'netlify link --name my-site-name']),
|
|
376
|
+
)
|
|
377
|
+
.action(link)
|
|
378
|
+
|
|
379
|
+
module.exports = { createLinkCommand, link }
|
package/src/commands/lm/index.js
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
const {
|
|
2
|
-
const Command = require('../../utils/command')
|
|
3
|
-
const showHelp = require('../../utils/show-help')
|
|
1
|
+
const { createLmCommand } = require('./lm')
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const { args, flags } = this.parse(LmCommand)
|
|
8
|
-
|
|
9
|
-
// Show help on empty sub command
|
|
10
|
-
if (isEmptyCommand(flags, args)) {
|
|
11
|
-
showHelp(this.id)
|
|
12
|
-
}
|
|
13
|
-
}
|
|
3
|
+
module.exports = {
|
|
4
|
+
createLmCommand,
|
|
14
5
|
}
|
|
15
|
-
|
|
16
|
-
LmCommand.description = `Handle Netlify Large Media operations
|
|
17
|
-
The lm command will help you manage large media for a site
|
|
18
|
-
`
|
|
19
|
-
LmCommand.examples = ['netlify lm:info', 'netlify lm:install', 'netlify lm:setup']
|
|
20
|
-
|
|
21
|
-
module.exports = LmCommand
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const Listr = require('listr')
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
checkGitLFSVersionStep,
|
|
6
|
+
checkGitVersionStep,
|
|
7
|
+
checkHelperVersionStep,
|
|
8
|
+
checkLFSFiltersStep,
|
|
9
|
+
} = require('../../utils/lm/steps')
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The lm:info command
|
|
13
|
+
*/
|
|
14
|
+
const lmInfo = async () => {
|
|
15
|
+
const steps = [
|
|
16
|
+
checkGitVersionStep,
|
|
17
|
+
checkGitLFSVersionStep,
|
|
18
|
+
checkLFSFiltersStep((ctx, task, installed) => {
|
|
19
|
+
if (!installed) {
|
|
20
|
+
throw new Error('Git LFS filters are not installed, run `git lfs install` to install them')
|
|
21
|
+
}
|
|
22
|
+
}),
|
|
23
|
+
checkHelperVersionStep,
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
const tasks = new Listr(steps, { concurrent: true, exitOnError: false })
|
|
27
|
+
try {
|
|
28
|
+
await tasks.run()
|
|
29
|
+
} catch {
|
|
30
|
+
// an error is already reported when a task fails
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Creates the `netlify lm:info` command
|
|
36
|
+
* @param {import('../base-command').BaseCommand} program
|
|
37
|
+
* @returns
|
|
38
|
+
*/
|
|
39
|
+
const createLmInfoCommand = (program) =>
|
|
40
|
+
program.command('lm:info').description('Show large media requirements information.').action(lmInfo)
|
|
41
|
+
|
|
42
|
+
module.exports = { createLmInfoCommand }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
const { generateDescriptionHelp } = require('../../utils')
|
|
4
|
+
const { installPlatform } = require('../../utils/lm/install')
|
|
5
|
+
const { printBanner } = require('../../utils/lm/ui')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The lm:install command
|
|
9
|
+
* @param {import('commander').OptionValues} options
|
|
10
|
+
*/
|
|
11
|
+
const lmInstall = async ({ force }) => {
|
|
12
|
+
const installed = await installPlatform({ force })
|
|
13
|
+
if (installed) {
|
|
14
|
+
printBanner(force)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates the `netlify lm:install` command
|
|
20
|
+
* @param {import('../base-command').BaseCommand} program
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
const createLmInstallCommand = (program) =>
|
|
24
|
+
program
|
|
25
|
+
.command('lm:install')
|
|
26
|
+
.alias('lm:init')
|
|
27
|
+
.description('Configures your computer to use Netlify Large Media')
|
|
28
|
+
.option('-f, --force', 'Force the credentials helper installation')
|
|
29
|
+
.addHelpText(
|
|
30
|
+
'after',
|
|
31
|
+
generateDescriptionHelp(`It installs the required credentials helper for Git,
|
|
32
|
+
and configures your Git environment with the right credentials.`),
|
|
33
|
+
)
|
|
34
|
+
.action(lmInstall)
|
|
35
|
+
|
|
36
|
+
module.exports = { createLmInstallCommand }
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const Listr = require('listr')
|
|
3
|
+
|
|
4
|
+
const { error, execa } = require('../../utils')
|
|
5
|
+
const { installPlatform } = require('../../utils/lm/install')
|
|
6
|
+
const { checkHelperVersion } = require('../../utils/lm/requirements')
|
|
7
|
+
const { printBanner } = require('../../utils/lm/ui')
|
|
8
|
+
|
|
9
|
+
const installHelperIfMissing = async function ({ force }) {
|
|
10
|
+
let installHelper = false
|
|
11
|
+
try {
|
|
12
|
+
const version = await checkHelperVersion()
|
|
13
|
+
if (!version) {
|
|
14
|
+
installHelper = true
|
|
15
|
+
}
|
|
16
|
+
} catch {
|
|
17
|
+
installHelper = true
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (installHelper) {
|
|
21
|
+
return installPlatform({ force })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const provisionService = async function (siteId, api) {
|
|
28
|
+
const addonName = 'large-media'
|
|
29
|
+
|
|
30
|
+
if (!siteId) {
|
|
31
|
+
throw new Error('No site id found, please run inside a site folder or `netlify link`')
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
await api.createServiceInstance({
|
|
35
|
+
siteId,
|
|
36
|
+
addon: addonName,
|
|
37
|
+
body: {},
|
|
38
|
+
})
|
|
39
|
+
} catch (error_) {
|
|
40
|
+
// error is JSONHTTPError
|
|
41
|
+
throw new Error(error_.json.error)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const configureLFSURL = async function (siteId, api) {
|
|
46
|
+
const siteInfo = await api.getSite({ siteId })
|
|
47
|
+
const url = `https://${siteInfo.id_domain}/.netlify/large-media`
|
|
48
|
+
|
|
49
|
+
return execa('git', ['config', '-f', '.lfsconfig', 'lfs.url', url])
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The lm:setup command
|
|
54
|
+
* @param {import('commander').OptionValues} options
|
|
55
|
+
* @param {import('../base-command').BaseCommand} command
|
|
56
|
+
*/
|
|
57
|
+
const lmSetup = async (options, command) => {
|
|
58
|
+
await command.authenticate()
|
|
59
|
+
|
|
60
|
+
const { api, site } = command.netlify
|
|
61
|
+
|
|
62
|
+
let helperInstalled = false
|
|
63
|
+
if (!options.skipInstall) {
|
|
64
|
+
try {
|
|
65
|
+
helperInstalled = await installHelperIfMissing({ force: options.forceInstall })
|
|
66
|
+
} catch (error_) {
|
|
67
|
+
error(error_)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const tasks = new Listr([
|
|
72
|
+
{
|
|
73
|
+
title: 'Provisioning Netlify Large Media',
|
|
74
|
+
async task() {
|
|
75
|
+
await provisionService(site.id, api)
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
title: 'Configuring Git LFS for this site',
|
|
80
|
+
async task() {
|
|
81
|
+
await configureLFSURL(site.id, api)
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
])
|
|
85
|
+
await tasks.run().catch(() => {})
|
|
86
|
+
|
|
87
|
+
if (helperInstalled) {
|
|
88
|
+
printBanner(options.forceInstall)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Creates the `netlify lm:setup` command
|
|
94
|
+
* @param {import('../base-command').BaseCommand} program
|
|
95
|
+
* @returns
|
|
96
|
+
*/
|
|
97
|
+
const createLmSetupCommand = (program) =>
|
|
98
|
+
program
|
|
99
|
+
.command('lm:setup')
|
|
100
|
+
.description('Configures your site to use Netlify Large Media')
|
|
101
|
+
.option('-s, --skip-install', 'Skip the credentials helper installation check')
|
|
102
|
+
.option('-f, --force-install', 'Force the credentials helper installation')
|
|
103
|
+
.addHelpText('after', 'It runs the install command if you have not installed the dependencies yet.')
|
|
104
|
+
.action(lmSetup)
|
|
105
|
+
|
|
106
|
+
module.exports = { createLmSetupCommand }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { uninstall } = require('../../utils/lm/install')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The lm:uninstall command
|
|
6
|
+
*/
|
|
7
|
+
const lmUninstall = async () => {
|
|
8
|
+
await uninstall()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates the `netlify lm:uninstall` command
|
|
13
|
+
* @param {import('../base-command').BaseCommand} program
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
const createLmUninstallCommand = (program) =>
|
|
17
|
+
program
|
|
18
|
+
.command('lm:uninstall', { hidden: true })
|
|
19
|
+
.alias('lm:remove')
|
|
20
|
+
.description(
|
|
21
|
+
'Uninstalls Netlify git credentials helper and cleans up any related configuration changes made by the install command.',
|
|
22
|
+
)
|
|
23
|
+
.action(lmUninstall)
|
|
24
|
+
|
|
25
|
+
module.exports = { createLmUninstallCommand }
|