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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
3
  "description": "Netlify command line tool",
4
- "version": "15.1.0",
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.4",
47
+ "@netlify/build": "29.11.6",
48
48
  "@netlify/build-info": "7.0.2",
49
- "@netlify/config": "20.4.2",
50
- "@netlify/edge-bundler": "8.14.2",
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.5.0",
54
- "@octokit/rest": "19.0.8",
55
- "@skn0tt/lambda-local": "^2.0.3",
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": "5.0.1",
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": "6.0.1",
77
+ "dot-prop": "7.2.0",
78
78
  "dotenv": "16.0.3",
79
- "env-paths": "2.2.1",
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": "^3.0.0",
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.6",
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.0",
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": "7.0.1",
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": "2.1.0",
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: new NetlifyAPI(token || '', apiOpts),
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 { getLogMessage } from '../../lib/log.mjs'
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 (get(config, 'build.publish')) {
78
- deployFolder = resolve(site.root, get(config, 'build.publish'))
79
- } else if (get(siteData, 'build_settings.dir')) {
80
- deployFolder = resolve(site.root, get(siteData, 'build_settings.dir'))
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 (get(siteData, 'build_settings.functions_dir')) {
142
- functionsFolder = resolve(site.root, get(siteData, 'build_settings.functions_dir'))
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 = getJsonErrorMessage(error)
238
+ const message = error_?.json?.message ?? ''
241
239
  if (hasErrorMessage(message, 'Background Functions not allowed by team plan')) {
242
- return failAndExit(`\n${getLogMessage('functions.backgroundNotSupported')}`)
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 = get(results, 'deploy.deploy_ssl_url') || get(results, 'deploy.deploy_url')
362
- const logsUrl = `${get(results, 'deploy.admin_url')}/deploys/${get(results, 'deploy.id')}`
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 = options.site || site.id
507
+ let siteId = site.id || options.site
510
508
 
511
509
  let siteData = {}
512
- if (siteId) {
513
- try {
514
- const [{ siteError, siteFoundById }, sites] = await Promise.all([
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
- : get(siteData, 'build_settings.env')
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 { error, exit, log, logJson, warn } from '../../utils/command-helpers.mjs'
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 { api, config, site } = command.netlify
19
+ const { config, siteInfo } = command.netlify
19
20
 
20
- // get deployed site details
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
- const getRepoUrl = ({ siteInfo }) => dotProp.get(siteInfo, 'build_settings.repo_url')
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({ siteInfo })
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({ siteInfo })
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 && !siteData) {
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 (siteData) {
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 { error, exit, log, warn } from '../../utils/command-helpers.mjs'
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 { api, site } = command.netlify
11
+ const { siteInfo } = command.netlify
11
12
 
12
13
  await command.authenticate()
13
14
 
14
- const siteId = site.id
15
+ log(`Opening "${siteInfo.name}" site admin UI:`)
16
+ log(`> ${siteInfo.admin_url}`)
15
17
 
16
- if (!siteId) {
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 { error, exit, log, warn } from '../../utils/command-helpers.mjs'
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 { api, site } = command.netlify
11
+ const { siteInfo } = command.netlify
11
12
 
12
13
  await command.authenticate()
13
14
 
14
- const siteId = site.id
15
-
16
- if (!siteId) {
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 { error, log, warn } from '../../utils/command-helpers.mjs'
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, site } = command.netlify
13
+ const { api, siteInfo } = command.netlify
14
14
 
15
15
  await command.authenticate()
16
16
 
17
- const siteId = site.id
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: siteData.name,
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 (get(siteData, 'build_settings.repo_url')) {
52
- data.hooks[hook.id].repo_url = get(siteData, 'build_settings.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.command('status:hooks').description('Print hook information of the linked site').action(statusHooks)
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
- let siteData = {}
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.9",
17
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz",
18
- "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==",
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.9",
57
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz",
58
- "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==",
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.0 || >=16.0.0"
16
+ "node": "^14.18.0 || >=16.0.0"
17
17
  }
18
18
  },
19
19
  "node_modules/node-fetch": {
20
- "version": "2.6.9",
21
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz",
22
- "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==",
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.9",
69
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz",
70
- "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==",
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
  }