netlify-cli 15.1.0 → 15.2.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 +404 -888
- package/package.json +15 -15
- package/src/commands/base-command.mjs +17 -3
- package/src/commands/deploy/deploy.mjs +18 -43
- package/src/commands/functions/functions-list.mjs +5 -25
- package/src/commands/init/init.mjs +7 -4
- package/src/commands/link/link.mjs +5 -9
- package/src/commands/open/open-admin.mjs +7 -33
- package/src/commands/open/open-site.mjs +7 -25
- package/src/commands/status/status-hooks.mjs +12 -30
- package/src/commands/unlink/unlink.mjs +2 -8
- package/src/functions-templates/javascript/auth-fetch/package-lock.json +6 -6
- package/src/functions-templates/javascript/google-analytics/package-lock.json +7 -7
- package/src/lib/functions/registry.mjs +2 -2
- package/src/lib/functions/runtimes/js/builders/zisi.mjs +2 -2
- package/src/lib/functions/server.mjs +1 -2
- package/src/lib/functions/utils.mjs +2 -2
- package/src/lib/log.mjs +4 -13
- package/src/utils/dev.mjs +1 -2
- package/src/utils/get-site.mjs +16 -0
- package/src/utils/hooks/requires-site-info.mjs +29 -0
- package/src/utils/proxy.mjs +2 -2
- package/src/utils/state-config.mjs +6 -6
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
3
|
"description": "Netlify command line tool",
|
|
4
|
-
"version": "15.
|
|
4
|
+
"version": "15.2.0",
|
|
5
5
|
"author": "Netlify Inc.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -44,15 +44,15 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@bugsnag/js": "7.20.2",
|
|
46
46
|
"@fastify/static": "6.10.1",
|
|
47
|
-
"@netlify/build": "29.11.
|
|
47
|
+
"@netlify/build": "29.11.6",
|
|
48
48
|
"@netlify/build-info": "7.0.2",
|
|
49
|
-
"@netlify/config": "20.4.
|
|
50
|
-
"@netlify/edge-bundler": "8.
|
|
49
|
+
"@netlify/config": "20.4.3",
|
|
50
|
+
"@netlify/edge-bundler": "8.15.0",
|
|
51
51
|
"@netlify/framework-info": "9.8.7",
|
|
52
52
|
"@netlify/local-functions-proxy": "1.1.1",
|
|
53
|
-
"@netlify/zip-it-and-ship-it": "9.
|
|
54
|
-
"@octokit/rest": "19.0.
|
|
55
|
-
"@skn0tt/lambda-local": "
|
|
53
|
+
"@netlify/zip-it-and-ship-it": "9.6.0",
|
|
54
|
+
"@octokit/rest": "19.0.11",
|
|
55
|
+
"@skn0tt/lambda-local": "2.0.3",
|
|
56
56
|
"ansi-escapes": "6.2.0",
|
|
57
57
|
"ansi-styles": "6.2.1",
|
|
58
58
|
"ansi-to-html": "0.7.2",
|
|
@@ -67,16 +67,16 @@
|
|
|
67
67
|
"commander": "10.0.1",
|
|
68
68
|
"comment-json": "4.2.3",
|
|
69
69
|
"concordance": "5.0.4",
|
|
70
|
-
"configstore": "
|
|
70
|
+
"configstore": "6.0.0",
|
|
71
71
|
"content-type": "1.0.5",
|
|
72
72
|
"cookie": "0.5.0",
|
|
73
73
|
"copy-template-dir": "1.4.0",
|
|
74
74
|
"cron-parser": "4.8.1",
|
|
75
75
|
"debug": "4.3.4",
|
|
76
76
|
"decache": "4.6.1",
|
|
77
|
-
"dot-prop": "
|
|
77
|
+
"dot-prop": "7.2.0",
|
|
78
78
|
"dotenv": "16.0.3",
|
|
79
|
-
"env-paths": "
|
|
79
|
+
"env-paths": "3.0.0",
|
|
80
80
|
"envinfo": "7.8.1",
|
|
81
81
|
"etag": "1.8.1",
|
|
82
82
|
"execa": "5.1.1",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"inquirer": "6.5.2",
|
|
102
102
|
"inquirer-autocomplete-prompt": "1.4.0",
|
|
103
103
|
"is-docker": "3.0.0",
|
|
104
|
-
"is-stream": "
|
|
104
|
+
"is-stream": "3.0.0",
|
|
105
105
|
"is-wsl": "2.2.0",
|
|
106
106
|
"isexe": "2.0.0",
|
|
107
107
|
"jsonwebtoken": "9.0.0",
|
|
@@ -113,13 +113,13 @@
|
|
|
113
113
|
"log-update": "5.0.1",
|
|
114
114
|
"minimist": "1.2.8",
|
|
115
115
|
"multiparty": "4.2.3",
|
|
116
|
-
"netlify": "13.1.
|
|
116
|
+
"netlify": "13.1.7",
|
|
117
117
|
"netlify-headers-parser": "7.1.2",
|
|
118
118
|
"netlify-redirect-parser": "14.1.2",
|
|
119
119
|
"netlify-redirector": "0.4.0",
|
|
120
120
|
"node-fetch": "2.6.11",
|
|
121
121
|
"node-version-alias": "3.4.1",
|
|
122
|
-
"ora": "6.3.
|
|
122
|
+
"ora": "6.3.1",
|
|
123
123
|
"p-filter": "3.0.0",
|
|
124
124
|
"p-map": "5.5.0",
|
|
125
125
|
"p-wait-for": "5.0.2",
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
"prettyjson": "1.2.5",
|
|
131
131
|
"pump": "3.0.0",
|
|
132
132
|
"raw-body": "2.5.2",
|
|
133
|
-
"read-pkg-up": "
|
|
133
|
+
"read-pkg-up": "9.1.0",
|
|
134
134
|
"semver": "7.5.1",
|
|
135
135
|
"source-map-support": "0.5.21",
|
|
136
136
|
"string-similarity": "4.0.4",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"terminal-link": "3.0.0",
|
|
141
141
|
"through2-filter": "3.0.0",
|
|
142
142
|
"through2-map": "3.0.0",
|
|
143
|
-
"to-readable-stream": "
|
|
143
|
+
"to-readable-stream": "3.0.0",
|
|
144
144
|
"toml": "3.0.0",
|
|
145
145
|
"ulid": "2.3.0",
|
|
146
146
|
"unixify": "1.0.0",
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
warn,
|
|
25
25
|
} from '../utils/command-helpers.mjs'
|
|
26
26
|
import getGlobalConfig from '../utils/get-global-config.mjs'
|
|
27
|
+
import { getSiteByName } from '../utils/get-site.mjs'
|
|
27
28
|
import openBrowser from '../utils/open-browser.mjs'
|
|
28
29
|
import StateConfig from '../utils/state-config.mjs'
|
|
29
30
|
import { identify, track } from '../utils/telemetry/index.mjs'
|
|
@@ -440,11 +441,24 @@ export default class BaseCommand extends Command {
|
|
|
440
441
|
certificateFile: options.httpProxyCertificateFilename,
|
|
441
442
|
})
|
|
442
443
|
const apiOpts = { ...apiUrlOpts, agent }
|
|
444
|
+
const api = new NetlifyAPI(token || '', apiOpts)
|
|
445
|
+
|
|
446
|
+
// If a user passes a site name as an option instead of a site ID to options.site, the siteInfo object
|
|
447
|
+
// will only have the property siteInfo.id. Checking for one of the other properties ensures that we can do
|
|
448
|
+
// a re-call of the api.getSite() that is done in @netlify/config so we have the proper site object in all
|
|
449
|
+
// commands.
|
|
450
|
+
// options.site as a site name (and not just site id) was introduced for the deploy command, so users could
|
|
451
|
+
// deploy by name along with by id
|
|
452
|
+
let siteData = siteInfo
|
|
453
|
+
if (!siteData.url && options.site) {
|
|
454
|
+
siteData = await getSiteByName(api, options.site)
|
|
455
|
+
}
|
|
456
|
+
|
|
443
457
|
const globalConfig = await getGlobalConfig()
|
|
444
458
|
|
|
445
459
|
actionCommand.netlify = {
|
|
446
460
|
// api methods
|
|
447
|
-
api
|
|
461
|
+
api,
|
|
448
462
|
apiOpts,
|
|
449
463
|
repositoryRoot,
|
|
450
464
|
// current site context
|
|
@@ -458,8 +472,8 @@ export default class BaseCommand extends Command {
|
|
|
458
472
|
state.set('siteId', id)
|
|
459
473
|
},
|
|
460
474
|
},
|
|
461
|
-
// Site information retrieved using the API
|
|
462
|
-
siteInfo,
|
|
475
|
+
// Site information retrieved using the API (api.getSite())
|
|
476
|
+
siteInfo: siteData,
|
|
463
477
|
// Configuration from netlify.[toml/yml]
|
|
464
478
|
config: normalizedConfig,
|
|
465
479
|
// Used to avoid calling @netlify/config again
|
|
@@ -6,8 +6,8 @@ import { cwd, env } from 'process'
|
|
|
6
6
|
import { runCoreSteps } from '@netlify/build'
|
|
7
7
|
import { restoreConfig, updateConfig } from '@netlify/config'
|
|
8
8
|
import { Option } from 'commander'
|
|
9
|
-
import { get } from 'dot-prop'
|
|
10
9
|
import inquirer from 'inquirer'
|
|
10
|
+
import isEmpty from 'lodash/isEmpty.js'
|
|
11
11
|
import isObject from 'lodash/isObject.js'
|
|
12
12
|
import prettyjson from 'prettyjson'
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ import { cancelDeploy } from '../../lib/api.mjs'
|
|
|
15
15
|
import { getBuildOptions, runBuild } from '../../lib/build.mjs'
|
|
16
16
|
import { featureFlags as edgeFunctionsFeatureFlags } from '../../lib/edge-functions/consts.mjs'
|
|
17
17
|
import { normalizeFunctionsConfig } from '../../lib/functions/config.mjs'
|
|
18
|
-
import {
|
|
18
|
+
import { BACKGROUND_FUNCTIONS_WARNING } from '../../lib/log.mjs'
|
|
19
19
|
import { startSpinner, stopSpinner } from '../../lib/spinner.mjs'
|
|
20
20
|
import {
|
|
21
21
|
chalk,
|
|
@@ -74,10 +74,10 @@ const getDeployFolder = async ({ config, options, site, siteData }) => {
|
|
|
74
74
|
let deployFolder
|
|
75
75
|
if (options.dir) {
|
|
76
76
|
deployFolder = resolve(cwd(), options.dir)
|
|
77
|
-
} else if (
|
|
78
|
-
deployFolder = resolve(site.root,
|
|
79
|
-
} else if (
|
|
80
|
-
deployFolder = resolve(site.root,
|
|
77
|
+
} else if (config?.build?.publish) {
|
|
78
|
+
deployFolder = resolve(site.root, config.build.publish)
|
|
79
|
+
} else if (siteData?.build_settings?.dir) {
|
|
80
|
+
deployFolder = resolve(site.root, siteData.build_settings.dir)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
if (!deployFolder) {
|
|
@@ -138,8 +138,8 @@ const getFunctionsFolder = ({ config, options, site, siteData }) => {
|
|
|
138
138
|
functionsFolder = resolve(cwd(), options.functions)
|
|
139
139
|
} else if (funcConfig) {
|
|
140
140
|
functionsFolder = resolve(site.root, funcConfig)
|
|
141
|
-
} else if (
|
|
142
|
-
functionsFolder = resolve(site.root,
|
|
141
|
+
} else if (siteData?.build_settings?.functions_dir) {
|
|
142
|
+
functionsFolder = resolve(site.root, siteData.build_settings.functions_dir)
|
|
143
143
|
}
|
|
144
144
|
return functionsFolder
|
|
145
145
|
}
|
|
@@ -232,14 +232,12 @@ const hasErrorMessage = (actual, expected) => {
|
|
|
232
232
|
return false
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
const getJsonErrorMessage = (error_) => get(error_, 'json.message', '')
|
|
236
|
-
|
|
237
235
|
const reportDeployError = ({ error_, failAndExit }) => {
|
|
238
236
|
switch (true) {
|
|
239
237
|
case error_.name === 'JSONHTTPError': {
|
|
240
|
-
const message =
|
|
238
|
+
const message = error_?.json?.message ?? ''
|
|
241
239
|
if (hasErrorMessage(message, 'Background Functions not allowed by team plan')) {
|
|
242
|
-
return failAndExit(`\n${
|
|
240
|
+
return failAndExit(`\n${BACKGROUND_FUNCTIONS_WARNING}`)
|
|
243
241
|
}
|
|
244
242
|
warn(`JSONHTTPError: ${message} ${error_.status}`)
|
|
245
243
|
warn(`\n${JSON.stringify(error_, null, ' ')}\n`)
|
|
@@ -358,8 +356,8 @@ const runDeploy = async ({
|
|
|
358
356
|
}
|
|
359
357
|
|
|
360
358
|
const siteUrl = results.deploy.ssl_url || results.deploy.url
|
|
361
|
-
const deployUrl =
|
|
362
|
-
const logsUrl = `${
|
|
359
|
+
const deployUrl = results.deploy.deploy_ssl_url || results.deploy.deploy_url
|
|
360
|
+
const logsUrl = `${results.deploy.admin_url}/deploys/${results.deploy.id}`
|
|
363
361
|
|
|
364
362
|
return {
|
|
365
363
|
siteId: results.deploy.site_id,
|
|
@@ -491,7 +489,7 @@ const printResults = ({ deployToProduction, json, results, runBuildCommand }) =>
|
|
|
491
489
|
* @param {import('../base-command.mjs').default} command
|
|
492
490
|
*/
|
|
493
491
|
const deploy = async (options, command) => {
|
|
494
|
-
const { api, site } = command.netlify
|
|
492
|
+
const { api, site, siteInfo } = command.netlify
|
|
495
493
|
const alias = options.alias || options.branch
|
|
496
494
|
|
|
497
495
|
command.setAnalyticsPayload({ open: options.open, prod: options.prod, json: options.json, alias: Boolean(alias) })
|
|
@@ -506,35 +504,12 @@ const deploy = async (options, command) => {
|
|
|
506
504
|
|
|
507
505
|
await command.authenticate(options.auth)
|
|
508
506
|
|
|
509
|
-
let siteId =
|
|
507
|
+
let siteId = site.id || options.site
|
|
510
508
|
|
|
511
509
|
let siteData = {}
|
|
512
|
-
if (siteId) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
api
|
|
516
|
-
.getSite({ siteId })
|
|
517
|
-
.then((data) => ({ siteFoundById: data }))
|
|
518
|
-
.catch((error_) => ({ siteError: error_ })),
|
|
519
|
-
api.listSites({ name: options.site, filter: 'all' }),
|
|
520
|
-
])
|
|
521
|
-
const siteFoundByName = sites.find((filteredSite) => filteredSite.name === options.site)
|
|
522
|
-
if (siteFoundById) {
|
|
523
|
-
siteData = siteFoundById
|
|
524
|
-
} else if (siteFoundByName) {
|
|
525
|
-
siteData = siteFoundByName
|
|
526
|
-
siteId = siteFoundByName.id
|
|
527
|
-
} else {
|
|
528
|
-
throw siteError
|
|
529
|
-
}
|
|
530
|
-
} catch (error_) {
|
|
531
|
-
// TODO specifically handle known cases (e.g. no account access)
|
|
532
|
-
if (error_.status === 404) {
|
|
533
|
-
error('Site not found')
|
|
534
|
-
} else {
|
|
535
|
-
error(error_.message)
|
|
536
|
-
}
|
|
537
|
-
}
|
|
510
|
+
if (siteId && !isEmpty(siteInfo)) {
|
|
511
|
+
siteData = siteInfo
|
|
512
|
+
siteId = siteData.id
|
|
538
513
|
} else {
|
|
539
514
|
log("This folder isn't linked to a site yet")
|
|
540
515
|
const NEW_SITE = '+ Create & configure a new site'
|
|
@@ -616,7 +591,7 @@ const deploy = async (options, command) => {
|
|
|
616
591
|
scope: 'functions',
|
|
617
592
|
siteInfo: siteData,
|
|
618
593
|
})
|
|
619
|
-
:
|
|
594
|
+
: siteData?.build_settings?.env
|
|
620
595
|
|
|
621
596
|
const functionsConfig = normalizeFunctionsConfig({
|
|
622
597
|
functionsConfig: config.functions,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import AsciiTable from 'ascii-table'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { exit, log, logJson } from '../../utils/command-helpers.mjs'
|
|
5
5
|
import { getFunctions, getFunctionsDir } from '../../utils/functions/index.mjs'
|
|
6
|
+
import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs'
|
|
6
7
|
|
|
7
8
|
const normalizeFunction = function (deployedFunctions, { name, urlPath: url }) {
|
|
8
9
|
const isDeployed = deployedFunctions.some((deployedFunction) => deployedFunction.n === name)
|
|
@@ -15,31 +16,9 @@ const normalizeFunction = function (deployedFunctions, { name, urlPath: url }) {
|
|
|
15
16
|
* @param {import('../base-command.mjs').default} command
|
|
16
17
|
*/
|
|
17
18
|
const functionsList = async (options, command) => {
|
|
18
|
-
const {
|
|
19
|
+
const { config, siteInfo } = command.netlify
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
// copied from `netlify status`
|
|
22
|
-
const siteId = site.id
|
|
23
|
-
if (!siteId) {
|
|
24
|
-
warn('Did you run `netlify link` yet?')
|
|
25
|
-
error(`You don't appear to be in a folder that is linked to a site`)
|
|
26
|
-
}
|
|
27
|
-
let siteData
|
|
28
|
-
try {
|
|
29
|
-
siteData = await api.getSite({ siteId })
|
|
30
|
-
} catch (error_) {
|
|
31
|
-
// unauthorized
|
|
32
|
-
if (error_.status === 401) {
|
|
33
|
-
warn(`Log in with a different account or re-link to a site you have permission for`)
|
|
34
|
-
error(`Not authorized to view the currently linked site (${siteId})`)
|
|
35
|
-
}
|
|
36
|
-
// missing
|
|
37
|
-
if (error_.status === 404) {
|
|
38
|
-
error(`The site this folder is linked to can't be found`)
|
|
39
|
-
}
|
|
40
|
-
error(error_)
|
|
41
|
-
}
|
|
42
|
-
const deploy = siteData.published_deploy || {}
|
|
21
|
+
const deploy = siteInfo.published_deploy || {}
|
|
43
22
|
const deployedFunctions = deploy.available_functions || []
|
|
44
23
|
|
|
45
24
|
const functionsDir = getFunctionsDir({ options, config })
|
|
@@ -91,4 +70,5 @@ NOT the same as listing the functions that have been deployed. For that info you
|
|
|
91
70
|
)
|
|
92
71
|
.option('-f, --functions <dir>', 'Specify a functions directory to list')
|
|
93
72
|
.option('--json', 'Output function data as JSON')
|
|
73
|
+
.hook('preAction', requiresSiteInfo)
|
|
94
74
|
.action(functionsList)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { Option } from 'commander'
|
|
3
|
-
import dotProp from 'dot-prop'
|
|
4
3
|
import inquirer from 'inquirer'
|
|
5
4
|
import isEmpty from 'lodash/isEmpty.js'
|
|
6
5
|
|
|
@@ -17,7 +16,11 @@ const persistState = ({ siteInfo, state }) => {
|
|
|
17
16
|
state.set('siteId', siteInfo.id)
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* @param {{} | undefined} siteInfo
|
|
21
|
+
* @returns {string | undefined}
|
|
22
|
+
*/
|
|
23
|
+
const getRepoUrl = (siteInfo) => siteInfo?.build_settings?.repo_url
|
|
21
24
|
|
|
22
25
|
const logExistingAndExit = ({ siteInfo }) => {
|
|
23
26
|
log()
|
|
@@ -187,7 +190,7 @@ export const init = async (options, command) => {
|
|
|
187
190
|
// Add .netlify to .gitignore file
|
|
188
191
|
await ensureNetlifyIgnore(repositoryRoot)
|
|
189
192
|
|
|
190
|
-
const repoUrl = getRepoUrl(
|
|
193
|
+
const repoUrl = getRepoUrl(siteInfo)
|
|
191
194
|
if (repoUrl && !options.force) {
|
|
192
195
|
logExistingAndExit({ siteInfo })
|
|
193
196
|
}
|
|
@@ -205,7 +208,7 @@ export const init = async (options, command) => {
|
|
|
205
208
|
log()
|
|
206
209
|
|
|
207
210
|
// Check for existing CI setup
|
|
208
|
-
const remoteBuildRepo = getRepoUrl(
|
|
211
|
+
const remoteBuildRepo = getRepoUrl(siteInfo)
|
|
209
212
|
if (remoteBuildRepo && !options.force) {
|
|
210
213
|
logExistingRepoSetupAndExit({ siteName: siteInfo.name, repoUrl: remoteBuildRepo })
|
|
211
214
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { Option } from 'commander'
|
|
3
3
|
import inquirer from 'inquirer'
|
|
4
|
+
import isEmpty from 'lodash/isEmpty.js'
|
|
4
5
|
|
|
5
6
|
import { listSites } from '../../lib/api.mjs'
|
|
6
7
|
import { chalk, error, exit, log } from '../../utils/command-helpers.mjs'
|
|
@@ -250,28 +251,23 @@ export const link = async (options, command) => {
|
|
|
250
251
|
api,
|
|
251
252
|
repositoryRoot,
|
|
252
253
|
site: { id: siteId },
|
|
254
|
+
siteInfo,
|
|
253
255
|
state,
|
|
254
256
|
} = command.netlify
|
|
255
257
|
|
|
256
|
-
let siteData
|
|
257
|
-
try {
|
|
258
|
-
// @ts-ignore types from API are wrong they cannot recognize `getSite` of API
|
|
259
|
-
siteData = await api.getSite({ siteId })
|
|
260
|
-
} catch {
|
|
261
|
-
// silent api error
|
|
262
|
-
}
|
|
258
|
+
let siteData = siteInfo
|
|
263
259
|
|
|
264
260
|
// Add .netlify to .gitignore file
|
|
265
261
|
await ensureNetlifyIgnore(repositoryRoot)
|
|
266
262
|
|
|
267
263
|
// Site id is incorrect
|
|
268
|
-
if (siteId &&
|
|
264
|
+
if (siteId && isEmpty(siteData)) {
|
|
269
265
|
log(`"${siteId}" was not found in your Netlify account.`)
|
|
270
266
|
log(`Please double check your siteID and which account you are logged into via \`netlify status\`.`)
|
|
271
267
|
return exit()
|
|
272
268
|
}
|
|
273
269
|
|
|
274
|
-
if (
|
|
270
|
+
if (!isEmpty(siteInfo)) {
|
|
275
271
|
// If already linked to site. exit and prompt for unlink
|
|
276
272
|
log(`Site already linked to "${siteData.name}"`)
|
|
277
273
|
log(`Admin url: ${siteData.admin_url}`)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { exit, log } from '../../utils/command-helpers.mjs'
|
|
2
|
+
import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs'
|
|
2
3
|
import openBrowser from '../../utils/open-browser.mjs'
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -7,42 +8,14 @@ import openBrowser from '../../utils/open-browser.mjs'
|
|
|
7
8
|
* @param {import('../base-command.mjs').default} command
|
|
8
9
|
*/
|
|
9
10
|
export const openAdmin = async (options, command) => {
|
|
10
|
-
const {
|
|
11
|
+
const { siteInfo } = command.netlify
|
|
11
12
|
|
|
12
13
|
await command.authenticate()
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
log(`Opening "${siteInfo.name}" site admin UI:`)
|
|
16
|
+
log(`> ${siteInfo.admin_url}`)
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
warn(`No Site ID found in current directory.
|
|
18
|
-
Run \`netlify link\` to connect to this folder to a site`)
|
|
19
|
-
return false
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let siteData
|
|
23
|
-
try {
|
|
24
|
-
siteData = await api.getSite({ siteId })
|
|
25
|
-
log(`Opening "${siteData.name}" site admin UI:`)
|
|
26
|
-
log(`> ${siteData.admin_url}`)
|
|
27
|
-
} catch (error_) {
|
|
28
|
-
// unauthorized
|
|
29
|
-
if (error_.status === 401) {
|
|
30
|
-
warn(`Log in with a different account or re-link to a site you have permission for`)
|
|
31
|
-
error(`Not authorized to view the currently linked site (${siteId})`)
|
|
32
|
-
}
|
|
33
|
-
// site not found
|
|
34
|
-
if (error_.status === 404) {
|
|
35
|
-
log()
|
|
36
|
-
log('Please double check this ID and verify you are logged in with the correct account')
|
|
37
|
-
log()
|
|
38
|
-
log('To fix this, run `netlify unlink` then `netlify link` to reconnect to the correct site ID')
|
|
39
|
-
log()
|
|
40
|
-
error(`Site "${siteId}" not found in account`)
|
|
41
|
-
}
|
|
42
|
-
error(error_)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
await openBrowser({ url: siteData.admin_url })
|
|
18
|
+
await openBrowser({ url: siteInfo.admin_url })
|
|
46
19
|
exit()
|
|
47
20
|
}
|
|
48
21
|
|
|
@@ -56,4 +29,5 @@ export const createOpenAdminCommand = (program) =>
|
|
|
56
29
|
.command('open:admin')
|
|
57
30
|
.description('Opens current site admin UI in Netlify')
|
|
58
31
|
.addExamples(['netlify open:admin'])
|
|
32
|
+
.hook('preAction', requiresSiteInfo)
|
|
59
33
|
.action(openAdmin)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { exit, log } from '../../utils/command-helpers.mjs'
|
|
2
|
+
import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs'
|
|
2
3
|
import openBrowser from '../../utils/open-browser.mjs'
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -7,33 +8,13 @@ import openBrowser from '../../utils/open-browser.mjs'
|
|
|
7
8
|
* @param {import('../base-command.mjs').default} command
|
|
8
9
|
*/
|
|
9
10
|
export const openSite = async (options, command) => {
|
|
10
|
-
const {
|
|
11
|
+
const { siteInfo } = command.netlify
|
|
11
12
|
|
|
12
13
|
await command.authenticate()
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
warn(`No Site ID found in current directory.
|
|
18
|
-
Run \`netlify link\` to connect to this folder to a site`)
|
|
19
|
-
return false
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let siteData
|
|
23
|
-
let url
|
|
24
|
-
try {
|
|
25
|
-
siteData = await api.getSite({ siteId })
|
|
26
|
-
url = siteData.ssl_url || siteData.url
|
|
27
|
-
log(`Opening "${siteData.name}" site url:`)
|
|
28
|
-
log(`> ${url}`)
|
|
29
|
-
} catch (error_) {
|
|
30
|
-
// unauthorized
|
|
31
|
-
if (error_.status === 401) {
|
|
32
|
-
warn(`Log in with a different account or re-link to a site you have permission for`)
|
|
33
|
-
error(`Not authorized to view the currently linked site (${siteId})`)
|
|
34
|
-
}
|
|
35
|
-
error(error_)
|
|
36
|
-
}
|
|
15
|
+
const url = siteInfo.ssl_url || siteInfo.url
|
|
16
|
+
log(`Opening "${siteInfo.name}" site url:`)
|
|
17
|
+
log(`> ${url}`)
|
|
37
18
|
|
|
38
19
|
await openBrowser({ url })
|
|
39
20
|
exit()
|
|
@@ -49,4 +30,5 @@ export const createOpenSiteCommand = (program) =>
|
|
|
49
30
|
.command('open:site')
|
|
50
31
|
.description('Opens current site url in browser')
|
|
51
32
|
.addExamples(['netlify open:site'])
|
|
33
|
+
.hook('preAction', requiresSiteInfo)
|
|
52
34
|
.action(openSite)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
import { get } from 'dot-prop'
|
|
3
2
|
import prettyjson from 'prettyjson'
|
|
4
3
|
|
|
5
|
-
import {
|
|
4
|
+
import { log } from '../../utils/command-helpers.mjs'
|
|
5
|
+
import requiresSiteInfo from '../../utils/hooks/requires-site-info.mjs'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* The status:hooks command
|
|
@@ -10,35 +10,13 @@ import { error, log, warn } from '../../utils/command-helpers.mjs'
|
|
|
10
10
|
* @param {import('../base-command.mjs').default} command
|
|
11
11
|
*/
|
|
12
12
|
const statusHooks = async (options, command) => {
|
|
13
|
-
const { api,
|
|
13
|
+
const { api, siteInfo } = command.netlify
|
|
14
14
|
|
|
15
15
|
await command.authenticate()
|
|
16
16
|
|
|
17
|
-
const
|
|
18
|
-
if (!siteId) {
|
|
19
|
-
warn('Did you run `netlify link` yet?')
|
|
20
|
-
error(`You don't appear to be in a folder that is linked to a site`)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let siteData
|
|
24
|
-
try {
|
|
25
|
-
siteData = await api.getSite({ siteId })
|
|
26
|
-
} catch (error_) {
|
|
27
|
-
// unauthorized
|
|
28
|
-
if (error_.status === 401) {
|
|
29
|
-
warn(`Log in with a different account or re-link to a site you have permission for`)
|
|
30
|
-
error(`Not authorized to view the currently linked site (${siteId})`)
|
|
31
|
-
}
|
|
32
|
-
// missing
|
|
33
|
-
if (error_.status === 404) {
|
|
34
|
-
error(`The site this folder is linked to can't be found`)
|
|
35
|
-
}
|
|
36
|
-
error(error_)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const ntlHooks = await api.listHooksBySiteId({ siteId: siteData.id })
|
|
17
|
+
const ntlHooks = await api.listHooksBySiteId({ siteId: siteInfo.id })
|
|
40
18
|
const data = {
|
|
41
|
-
site:
|
|
19
|
+
site: siteInfo.name,
|
|
42
20
|
hooks: {},
|
|
43
21
|
}
|
|
44
22
|
ntlHooks.forEach((hook) => {
|
|
@@ -48,8 +26,8 @@ const statusHooks = async (options, command) => {
|
|
|
48
26
|
id: hook.id,
|
|
49
27
|
disabled: hook.disabled,
|
|
50
28
|
}
|
|
51
|
-
if (
|
|
52
|
-
data.hooks[hook.id].repo_url =
|
|
29
|
+
if (siteInfo.build_settings?.repo_url) {
|
|
30
|
+
data.hooks[hook.id].repo_url = siteInfo.build_settings.repo_url
|
|
53
31
|
}
|
|
54
32
|
})
|
|
55
33
|
log(`─────────────────┐
|
|
@@ -64,4 +42,8 @@ Site Hook Status │
|
|
|
64
42
|
* @returns
|
|
65
43
|
*/
|
|
66
44
|
export const createStatusHooksCommand = (program) =>
|
|
67
|
-
program
|
|
45
|
+
program
|
|
46
|
+
.command('status:hooks')
|
|
47
|
+
.description('Print hook information of the linked site')
|
|
48
|
+
.hook('preAction', requiresSiteInfo)
|
|
49
|
+
.action(statusHooks)
|
|
@@ -8,7 +8,7 @@ import { track } from '../../utils/telemetry/index.mjs'
|
|
|
8
8
|
* @param {import('../base-command.mjs').default} command
|
|
9
9
|
*/
|
|
10
10
|
const unlink = async (options, command) => {
|
|
11
|
-
const { site, state } = command.netlify
|
|
11
|
+
const { site, siteInfo, state } = command.netlify
|
|
12
12
|
const siteId = site.id
|
|
13
13
|
|
|
14
14
|
if (!siteId) {
|
|
@@ -16,13 +16,7 @@ const unlink = async (options, command) => {
|
|
|
16
16
|
return exit()
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
// @ts-ignore types from API are wrong they cannot recognize `getSite` of API
|
|
22
|
-
siteData = await command.netlify.api.getSite({ siteId })
|
|
23
|
-
} catch {
|
|
24
|
-
// ignore errors if we can't get the site
|
|
25
|
-
}
|
|
19
|
+
const siteData = siteInfo
|
|
26
20
|
|
|
27
21
|
state.delete('siteId')
|
|
28
22
|
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"node_modules/node-fetch": {
|
|
16
|
-
"version": "2.6.
|
|
17
|
-
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.
|
|
18
|
-
"integrity": "sha512-
|
|
16
|
+
"version": "2.6.11",
|
|
17
|
+
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
|
18
|
+
"integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"whatwg-url": "^5.0.0"
|
|
21
21
|
},
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"node-fetch": {
|
|
56
|
-
"version": "2.6.
|
|
57
|
-
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.
|
|
58
|
-
"integrity": "sha512-
|
|
56
|
+
"version": "2.6.11",
|
|
57
|
+
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
|
58
|
+
"integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
|
|
59
59
|
"requires": {
|
|
60
60
|
"whatwg-url": "^5.0.0"
|
|
61
61
|
}
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"uuid": "^9.0.0"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": "^14.
|
|
16
|
+
"node": "^14.18.0 || >=16.0.0"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"node_modules/node-fetch": {
|
|
20
|
-
"version": "2.6.
|
|
21
|
-
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.
|
|
22
|
-
"integrity": "sha512-
|
|
20
|
+
"version": "2.6.11",
|
|
21
|
+
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
|
22
|
+
"integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"whatwg-url": "^5.0.0"
|
|
25
25
|
},
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"node-fetch": {
|
|
68
|
-
"version": "2.6.
|
|
69
|
-
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.
|
|
70
|
-
"integrity": "sha512-
|
|
68
|
+
"version": "2.6.11",
|
|
69
|
+
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
|
70
|
+
"integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==",
|
|
71
71
|
"requires": {
|
|
72
72
|
"whatwg-url": "^5.0.0"
|
|
73
73
|
}
|