netlify-cli 8.1.0 → 8.1.5

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.
Files changed (193) hide show
  1. package/README.md +12 -13
  2. package/bin/run +38 -2
  3. package/npm-shrinkwrap.json +1256 -4181
  4. package/package.json +15 -39
  5. package/scripts/postinstall.js +13 -0
  6. package/src/commands/addons/addons-auth.js +50 -0
  7. package/src/commands/addons/addons-config.js +180 -0
  8. package/src/commands/addons/addons-create.js +131 -0
  9. package/src/commands/addons/addons-delete.js +60 -0
  10. package/src/commands/addons/addons-list.js +62 -0
  11. package/src/commands/addons/addons.js +44 -0
  12. package/src/commands/addons/index.js +3 -24
  13. package/src/commands/api/api.js +75 -0
  14. package/src/commands/api/index.js +5 -0
  15. package/src/commands/base-command.js +502 -0
  16. package/src/commands/build/build.js +58 -0
  17. package/src/commands/build/index.js +3 -61
  18. package/src/commands/completion/completion.js +56 -0
  19. package/src/commands/completion/index.js +5 -0
  20. package/src/commands/{deploy.js → deploy/deploy.js} +295 -275
  21. package/src/commands/deploy/index.js +5 -0
  22. package/src/commands/dev/dev-exec.js +35 -0
  23. package/src/commands/dev/dev-trace.js +47 -0
  24. package/src/commands/dev/dev.js +340 -0
  25. package/src/commands/dev/index.js +3 -335
  26. package/src/commands/env/env-get.js +51 -0
  27. package/src/commands/env/env-import.js +93 -0
  28. package/src/commands/env/env-list.js +63 -0
  29. package/src/commands/env/env-set.js +67 -0
  30. package/src/commands/env/env-unset.js +66 -0
  31. package/src/commands/env/env.js +42 -0
  32. package/src/commands/env/index.js +3 -23
  33. package/src/commands/functions/functions-build.js +59 -0
  34. package/src/commands/functions/{create.js → functions-create.js} +130 -94
  35. package/src/commands/functions/functions-invoke.js +273 -0
  36. package/src/commands/functions/functions-list.js +106 -0
  37. package/src/commands/functions/functions-serve.js +63 -0
  38. package/src/commands/functions/functions.js +47 -0
  39. package/src/commands/functions/index.js +3 -45
  40. package/src/commands/index.js +7 -0
  41. package/src/commands/init/index.js +6 -0
  42. package/src/commands/{init.js → init/init.js} +79 -68
  43. package/src/commands/link/index.js +6 -0
  44. package/src/{utils/link/link-by-prompt.js → commands/link/link.js} +141 -14
  45. package/src/commands/lm/index.js +3 -19
  46. package/src/commands/lm/lm-info.js +42 -0
  47. package/src/commands/lm/lm-install.js +33 -0
  48. package/src/commands/lm/lm-setup.js +106 -0
  49. package/src/commands/lm/lm-uninstall.js +25 -0
  50. package/src/commands/lm/lm.js +34 -0
  51. package/src/commands/login/index.js +6 -0
  52. package/src/commands/login/login.js +55 -0
  53. package/src/commands/logout/index.js +5 -0
  54. package/src/commands/logout/logout.js +43 -0
  55. package/src/commands/main.js +206 -0
  56. package/src/commands/open/index.js +3 -39
  57. package/src/commands/open/open-admin.js +60 -0
  58. package/src/commands/open/open-site.js +53 -0
  59. package/src/commands/open/open.js +40 -0
  60. package/src/commands/sites/index.js +5 -20
  61. package/src/commands/sites/sites-create.js +187 -0
  62. package/src/commands/sites/sites-delete.js +104 -0
  63. package/src/commands/sites/sites-list.js +90 -0
  64. package/src/commands/sites/sites.js +32 -0
  65. package/src/commands/status/index.js +3 -118
  66. package/src/commands/status/status-hooks.js +69 -0
  67. package/src/commands/status/status.js +124 -0
  68. package/src/commands/switch/index.js +5 -0
  69. package/src/commands/switch/switch.js +50 -0
  70. package/src/commands/unlink/index.js +5 -0
  71. package/src/commands/unlink/unlink.js +48 -0
  72. package/src/commands/watch/index.js +5 -0
  73. package/src/commands/watch/watch.js +131 -0
  74. package/src/functions-templates/javascript/stripe-charge/package-lock.json +13 -13
  75. package/src/functions-templates/javascript/stripe-subscription/package-lock.json +13 -13
  76. package/src/functions-templates/rust/hello-world/Cargo.toml +1 -1
  77. package/src/functions-templates/typescript/hello-world/package-lock.json +6 -6
  78. package/src/lib/build.js +21 -7
  79. package/src/lib/completion/constants.js +6 -0
  80. package/src/lib/completion/generate-autocompletion.js +36 -0
  81. package/src/lib/completion/index.js +5 -0
  82. package/src/lib/completion/script.js +72 -0
  83. package/src/lib/exec-fetcher.js +5 -3
  84. package/src/lib/fs.js +54 -36
  85. package/src/lib/functions/background.js +1 -1
  86. package/src/lib/functions/form-submissions-handler.js +2 -1
  87. package/src/lib/functions/local-proxy.js +2 -1
  88. package/src/lib/functions/netlify-function.js +4 -1
  89. package/src/lib/functions/registry.js +4 -6
  90. package/src/lib/functions/runtimes/go/index.js +2 -1
  91. package/src/lib/functions/runtimes/js/builders/netlify-lambda.js +6 -4
  92. package/src/lib/functions/runtimes/js/builders/zisi.js +3 -3
  93. package/src/lib/functions/runtimes/rust/index.js +4 -3
  94. package/src/lib/functions/server.js +2 -3
  95. package/src/lib/functions/synchronous.js +2 -1
  96. package/src/lib/functions/utils.js +2 -3
  97. package/src/lib/functions/watcher.js +1 -0
  98. package/src/lib/http-agent.js +5 -5
  99. package/src/lib/log.js +2 -1
  100. package/src/lib/settings.js +16 -1
  101. package/src/lib/spinner.js +22 -0
  102. package/src/utils/addons/diffs/index.js +1 -0
  103. package/src/utils/addons/diffs/options.js +3 -1
  104. package/src/utils/addons/prepare.js +13 -6
  105. package/src/utils/addons/prompts.js +2 -1
  106. package/src/utils/addons/render.js +3 -1
  107. package/src/utils/command-helpers.js +136 -42
  108. package/src/utils/create-stream-promise.js +5 -5
  109. package/src/utils/deferred.js +1 -0
  110. package/src/utils/deploy/deploy-site.js +1 -1
  111. package/src/utils/deploy/index.js +4 -0
  112. package/src/utils/detect-server-settings.js +10 -12
  113. package/src/utils/dev.js +18 -10
  114. package/src/utils/dot-env.js +4 -2
  115. package/src/utils/{edge-handlers.js → functions/edge-handlers.js} +8 -7
  116. package/src/utils/functions/functions.js +36 -0
  117. package/src/utils/{get-functions.js → functions/get-functions.js} +2 -1
  118. package/src/utils/functions/index.js +8 -26
  119. package/src/utils/get-global-config.js +3 -2
  120. package/src/utils/get-repo-data.js +8 -1
  121. package/src/utils/gh-auth.js +1 -0
  122. package/src/utils/gitignore.js +7 -5
  123. package/src/utils/headers.js +1 -2
  124. package/src/utils/index.js +42 -0
  125. package/src/utils/init/config-github.js +12 -5
  126. package/src/utils/init/config-manual.js +9 -2
  127. package/src/utils/init/config.js +13 -7
  128. package/src/utils/init/frameworks.js +1 -0
  129. package/src/utils/init/node-version.js +4 -2
  130. package/src/utils/init/utils.js +10 -6
  131. package/src/utils/live-tunnel.js +3 -4
  132. package/src/utils/lm/install.js +10 -15
  133. package/src/utils/lm/requirements.js +3 -1
  134. package/src/utils/lm/steps.js +1 -1
  135. package/src/utils/lm/ui.js +7 -3
  136. package/src/utils/open-browser.js +8 -2
  137. package/src/utils/parse-raw-flags.js +4 -4
  138. package/src/utils/proxy.js +6 -5
  139. package/src/utils/read-repo-url.js +1 -0
  140. package/src/utils/redirects.js +2 -2
  141. package/src/utils/rules-proxy.js +2 -1
  142. package/src/utils/state-config.js +1 -1
  143. package/src/utils/telemetry/index.js +2 -113
  144. package/src/utils/telemetry/request.js +3 -1
  145. package/src/utils/telemetry/telemetry.js +117 -0
  146. package/src/utils/telemetry/validation.js +13 -12
  147. package/src/utils/traffic-mesh.js +3 -3
  148. package/oclif.manifest.json +0 -1
  149. package/src/commands/addons/auth.js +0 -42
  150. package/src/commands/addons/config.js +0 -177
  151. package/src/commands/addons/create.js +0 -127
  152. package/src/commands/addons/delete.js +0 -69
  153. package/src/commands/addons/list.js +0 -54
  154. package/src/commands/api.js +0 -84
  155. package/src/commands/dev/exec.js +0 -32
  156. package/src/commands/dev/trace.js +0 -61
  157. package/src/commands/env/get.js +0 -44
  158. package/src/commands/env/import.js +0 -90
  159. package/src/commands/env/list.js +0 -49
  160. package/src/commands/env/set.js +0 -64
  161. package/src/commands/env/unset.js +0 -58
  162. package/src/commands/functions/build.js +0 -60
  163. package/src/commands/functions/invoke.js +0 -277
  164. package/src/commands/functions/list.js +0 -102
  165. package/src/commands/functions/serve.js +0 -70
  166. package/src/commands/link.js +0 -133
  167. package/src/commands/lm/info.js +0 -36
  168. package/src/commands/lm/install.js +0 -30
  169. package/src/commands/lm/setup.js +0 -107
  170. package/src/commands/lm/uninstall.js +0 -17
  171. package/src/commands/login.js +0 -54
  172. package/src/commands/logout.js +0 -37
  173. package/src/commands/open/admin.js +0 -51
  174. package/src/commands/open/site.js +0 -43
  175. package/src/commands/sites/create.js +0 -191
  176. package/src/commands/sites/delete.js +0 -116
  177. package/src/commands/sites/list.js +0 -84
  178. package/src/commands/status/hooks.js +0 -60
  179. package/src/commands/switch.js +0 -44
  180. package/src/commands/unlink.js +0 -38
  181. package/src/commands/watch.js +0 -115
  182. package/src/hooks/init.js +0 -46
  183. package/src/index.js +0 -25
  184. package/src/lib/help.js +0 -26
  185. package/src/utils/chalk.js +0 -16
  186. package/src/utils/check-command-inputs.js +0 -21
  187. package/src/utils/command.js +0 -261
  188. package/src/utils/detect-functions-builder.js +0 -25
  189. package/src/utils/difference.js +0 -4
  190. package/src/utils/header.js +0 -18
  191. package/src/utils/logo.js +0 -11
  192. package/src/utils/show-help.js +0 -5
  193. package/src/utils/telemetry/tracked-command.js +0 -51
@@ -0,0 +1,187 @@
1
+ // @ts-check
2
+
3
+ const slugify = require('@sindresorhus/slugify')
4
+ const inquirer = require('inquirer')
5
+ const pick = require('lodash/pick')
6
+ const sample = require('lodash/sample')
7
+ const prettyjson = require('prettyjson')
8
+ const { v4: uuidv4 } = require('uuid')
9
+
10
+ const { chalk, error, getRepoData, log, logJson, track, warn } = require('../../utils')
11
+ const { configureRepo } = require('../../utils/init/config')
12
+
13
+ const SITE_NAME_SUGGESTION_SUFFIX_LENGTH = 5
14
+
15
+ /**
16
+ * The sites:create command
17
+ * @param {import('commander').OptionValues} options
18
+ * @param {import('../base-command').BaseCommand} command
19
+ */
20
+ const sitesCreate = async (options, command) => {
21
+ const { api } = command.netlify
22
+
23
+ await command.authenticate()
24
+
25
+ const accounts = await api.listAccountsForUser()
26
+
27
+ let { accountSlug } = options
28
+ if (!accountSlug) {
29
+ const { accountSlug: accountSlugInput } = await inquirer.prompt([
30
+ {
31
+ type: 'list',
32
+ name: 'accountSlug',
33
+ message: 'Team:',
34
+ choices: accounts.map((account) => ({
35
+ value: account.slug,
36
+ name: account.name,
37
+ })),
38
+ },
39
+ ])
40
+ accountSlug = accountSlugInput
41
+ }
42
+
43
+ const { name: nameFlag } = options
44
+ let user
45
+ let site
46
+
47
+ // Allow the user to reenter site name if selected one isn't available
48
+ const inputSiteName = async (name) => {
49
+ if (!user) user = await api.getCurrentUser()
50
+
51
+ if (!name) {
52
+ let { slug } = user
53
+ let suffix = ''
54
+
55
+ // If the user doesn't have a slug, we'll compute one. Because `full_name` is not guaranteed to be unique, we
56
+ // append a short randomly-generated ID to reduce the likelihood of a conflict.
57
+ if (!slug) {
58
+ slug = slugify(user.full_name || user.email)
59
+ suffix = `-${uuidv4().slice(0, SITE_NAME_SUGGESTION_SUFFIX_LENGTH)}`
60
+ }
61
+
62
+ const suggestions = [
63
+ `super-cool-site-by-${slug}${suffix}`,
64
+ `the-awesome-${slug}-site${suffix}`,
65
+ `${slug}-makes-great-sites${suffix}`,
66
+ `netlify-thinks-${slug}-is-great${suffix}`,
67
+ `the-great-${slug}-site${suffix}`,
68
+ `isnt-${slug}-awesome${suffix}`,
69
+ ]
70
+ const siteSuggestion = sample(suggestions)
71
+
72
+ console.log(
73
+ `Choose a unique site name (e.g. ${siteSuggestion}.netlify.app) or leave it blank for a random name. You can update the site name later.`,
74
+ )
75
+ const { name: nameInput } = await inquirer.prompt([
76
+ {
77
+ type: 'input',
78
+ name: 'name',
79
+ message: 'Site name (optional):',
80
+ filter: (val) => (val === '' ? undefined : val),
81
+ validate: (input) => /^[a-zA-Z\d-]+$/.test(input) || 'Only alphanumeric characters and hyphens are allowed',
82
+ },
83
+ ])
84
+ name = nameInput
85
+ }
86
+
87
+ const body = {}
88
+ if (typeof name === 'string') {
89
+ body.name = name.trim()
90
+ }
91
+ try {
92
+ site = await api.createSiteInTeam({
93
+ accountSlug,
94
+ body,
95
+ })
96
+ } catch (error_) {
97
+ if (error_.status === 422) {
98
+ warn(`${name}.netlify.app already exists. Please try a different slug.`)
99
+ await inputSiteName()
100
+ } else {
101
+ error(`createSiteInTeam error: ${error_.status}: ${error_.message}`)
102
+ }
103
+ }
104
+ }
105
+ await inputSiteName(nameFlag)
106
+
107
+ log()
108
+ log(chalk.greenBright.bold.underline(`Site Created`))
109
+ log()
110
+
111
+ const siteUrl = site.ssl_url || site.url
112
+ log(
113
+ prettyjson.render({
114
+ 'Admin URL': site.admin_url,
115
+ URL: siteUrl,
116
+ 'Site ID': site.id,
117
+ }),
118
+ )
119
+
120
+ track('sites_created', {
121
+ siteId: site.id,
122
+ adminUrl: site.admin_url,
123
+ siteUrl,
124
+ })
125
+
126
+ if (options.withCi) {
127
+ log('Configuring CI')
128
+ const repoData = await getRepoData()
129
+ await configureRepo({ command, siteId: site.id, repoData, manual: options.manual })
130
+ }
131
+
132
+ if (options.json) {
133
+ logJson(
134
+ pick(site, [
135
+ 'id',
136
+ 'state',
137
+ 'plan',
138
+ 'name',
139
+ 'custom_domain',
140
+ 'domain_aliases',
141
+ 'url',
142
+ 'ssl_url',
143
+ 'admin_url',
144
+ 'screenshot_url',
145
+ 'created_at',
146
+ 'updated_at',
147
+ 'user_id',
148
+ 'ssl',
149
+ 'force_ssl',
150
+ 'managed_dns',
151
+ 'deploy_url',
152
+ 'account_name',
153
+ 'account_slug',
154
+ 'git_provider',
155
+ 'deploy_hook',
156
+ 'capabilities',
157
+ 'id_domain',
158
+ ]),
159
+ )
160
+ }
161
+
162
+ return site
163
+ }
164
+
165
+ /**
166
+ * Creates the `netlify sites:create` command
167
+ * @param {import('../base-command').BaseCommand} program
168
+ * @returns
169
+ */
170
+ const createSitesCreateCommand = (program) =>
171
+ program
172
+ .command('sites:create')
173
+ .description(
174
+ `Create an empty site (advanced)
175
+ Create a blank site that isn't associated with any git remote. Does not link to the current working directory.`,
176
+ )
177
+ .option('-n, --name [name]', 'name of site')
178
+ .option('-a, --account-slug [slug]', 'account slug to create the site under')
179
+ .option('-c, --with-ci', 'initialize CI hooks during site creation')
180
+ .option('-m, --manual', 'force manual CI setup. Used --with-ci flag')
181
+ .addHelpText(
182
+ 'after',
183
+ `Create a blank site that isn't associated with any git remote. Does not link to the current working directory.`,
184
+ )
185
+ .action(sitesCreate)
186
+
187
+ module.exports = { createSitesCreateCommand, sitesCreate }
@@ -0,0 +1,104 @@
1
+ // @ts-check
2
+ const inquirer = require('inquirer')
3
+
4
+ const { chalk, error, exit, log } = require('../../utils')
5
+
6
+ /**
7
+ * The sites:delete command
8
+ * @param {string} siteId
9
+ * @param {import('commander').OptionValues} options
10
+ * @param {import('../base-command').BaseCommand} command
11
+ */
12
+ const sitesDelete = async (siteId, options, command) => {
13
+ command.setAnalyticsPayload({ force: options.force })
14
+
15
+ const { api, site } = command.netlify
16
+ const cwdSiteId = site.id
17
+
18
+ // 1. Prompt user for verification
19
+ await command.authenticate(options.auth)
20
+
21
+ let siteData
22
+ try {
23
+ siteData = await api.getSite({ siteId })
24
+ } catch (error_) {
25
+ if (error_.status === 404) {
26
+ error(`No site with id ${siteId} found. Please verify the siteId & try again.`)
27
+ }
28
+ }
29
+
30
+ if (!siteData) {
31
+ error(`Unable to process site`)
32
+ }
33
+
34
+ const noForce = options.force !== true
35
+
36
+ /* Verify the user wants to delete the site */
37
+ if (noForce) {
38
+ log(`${chalk.redBright('Warning')}: You are about to permanently delete "${chalk.bold(siteData.name)}"`)
39
+ log(` Verify this siteID "${siteId}" supplied is correct and proceed.`)
40
+ log(' To skip this prompt, pass a --force flag to the delete command')
41
+ log()
42
+ log(`${chalk.bold('Be careful here. There is no undo!')}`)
43
+ log()
44
+ const { wantsToDelete } = await inquirer.prompt({
45
+ type: 'confirm',
46
+ name: 'wantsToDelete',
47
+ message: `WARNING: Are you sure you want to delete the "${siteData.name}" site?`,
48
+ default: false,
49
+ })
50
+ log()
51
+ if (!wantsToDelete) {
52
+ exit()
53
+ }
54
+ }
55
+
56
+ /* Validation logic if siteId passed in does not match current site ID */
57
+ if (noForce && cwdSiteId && cwdSiteId !== siteId) {
58
+ log(`${chalk.redBright('Warning')}: The siteId supplied does not match the current working directory siteId`)
59
+ log()
60
+ log(`Supplied: "${siteId}"`)
61
+ log(`Current Site: "${cwdSiteId}"`)
62
+ log()
63
+ log(`Verify this siteID "${siteId}" supplied is correct and proceed.`)
64
+ log('To skip this prompt, pass a --force flag to the delete command')
65
+ const { wantsToDelete } = await inquirer.prompt({
66
+ type: 'confirm',
67
+ name: 'wantsToDelete',
68
+ message: `Verify & Proceed with deletion of site "${siteId}"?`,
69
+ default: false,
70
+ })
71
+ if (!wantsToDelete) {
72
+ exit()
73
+ }
74
+ }
75
+
76
+ log(`Deleting site "${siteId}"...`)
77
+
78
+ try {
79
+ await api.deleteSite({ site_id: siteId })
80
+ } catch (error_) {
81
+ if (error_.status === 404) {
82
+ error(`No site with id ${siteId} found. Please verify the siteId & try again.`)
83
+ } else {
84
+ error(`Delete Site error: ${error_.status}: ${error_.message}`)
85
+ }
86
+ }
87
+ log(`Site "${siteId}" successfully deleted!`)
88
+ }
89
+
90
+ /**
91
+ * Creates the `netlify sites:delete` command
92
+ * @param {import('../base-command').BaseCommand} program
93
+ * @returns
94
+ */
95
+ const createSitesDeleteCommand = (program) =>
96
+ program
97
+ .command('sites:delete')
98
+ .description('Delete a site\nThis command will permanently delete the site on Netlify. Use with caution.')
99
+ .argument('<siteId>', 'Site ID to delete.')
100
+ .option('-f, --force', 'delete without prompting (useful for CI)')
101
+ .addExamples(['netlify sites:delete 1234-3262-1211'])
102
+ .action(sitesDelete)
103
+
104
+ module.exports = { createSitesDeleteCommand }
@@ -0,0 +1,90 @@
1
+ // @ts-check
2
+
3
+ const { listSites } = require('../../lib/api')
4
+ const { startSpinner, stopSpinner } = require('../../lib/spinner')
5
+ const { chalk, log, logJson } = require('../../utils')
6
+
7
+ /**
8
+ * The sites:list command
9
+ * @param {import('commander').OptionValues} options
10
+ * @param {import('../base-command').BaseCommand} command
11
+ * @returns {Promise<{ id: any; name: any; ssl_url: any; account_name: any; }|boolean>}
12
+ */
13
+ const sitesList = async (options, command) => {
14
+ const { api } = command.netlify
15
+ /** @type {import('ora').Ora} */
16
+ let spinner
17
+ if (!options.json) {
18
+ spinner = startSpinner({ text: 'Loading your sites' })
19
+ }
20
+ await command.authenticate()
21
+
22
+ const sites = await listSites({ api, options: { filter: 'all' } })
23
+ if (!options.json) {
24
+ stopSpinner({ spinner })
25
+ }
26
+
27
+ if (sites && sites.length !== 0) {
28
+ const logSites = sites.map((site) => {
29
+ const siteInfo = {
30
+ id: site.id,
31
+ name: site.name,
32
+ ssl_url: site.ssl_url,
33
+ account_name: site.account_name,
34
+ }
35
+
36
+ if (site.build_settings && site.build_settings.repo_url) {
37
+ siteInfo.repo_url = site.build_settings.repo_url
38
+ }
39
+
40
+ return siteInfo
41
+ })
42
+
43
+ // Json response for piping commands
44
+ if (options.json) {
45
+ const redactedSites = sites.map((site) => {
46
+ if (site && site.build_settings) {
47
+ delete site.build_settings.env
48
+ }
49
+ return site
50
+ })
51
+ logJson(redactedSites)
52
+ return false
53
+ }
54
+
55
+ log(`
56
+ ────────────────────────────┐
57
+ Current Netlify Sites │
58
+ ────────────────────────────┘
59
+
60
+ Count: ${logSites.length}
61
+ `)
62
+
63
+ logSites.forEach((logSite) => {
64
+ log(`${chalk.greenBright(logSite.name)} - ${logSite.id}`)
65
+ log(` ${chalk.whiteBright.bold('url:')} ${chalk.yellowBright(logSite.ssl_url)}`)
66
+ if (logSite.repo_url) {
67
+ log(` ${chalk.whiteBright.bold('repo:')} ${chalk.white(logSite.repo_url)}`)
68
+ }
69
+ if (logSite.account_name) {
70
+ log(` ${chalk.whiteBright.bold('account:')} ${chalk.white(logSite.account_name)}`)
71
+ }
72
+ log(`─────────────────────────────────────────────────`)
73
+ })
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Creates the `netlify sites:list` command
79
+ * @param {import('../base-command').BaseCommand} program
80
+ */
81
+ const createSitesListCommand = (program) =>
82
+ program
83
+ .command('sites:list')
84
+ .description('List all sites you have access to')
85
+ .option('--json', 'Output site data as JSON')
86
+ .action(async (options, command) => {
87
+ await sitesList(options, command)
88
+ })
89
+
90
+ module.exports = { createSitesListCommand }
@@ -0,0 +1,32 @@
1
+ // @ts-check
2
+ const { createSitesCreateCommand } = require('./sites-create')
3
+ const { createSitesDeleteCommand } = require('./sites-delete')
4
+ const { createSitesListCommand } = require('./sites-list')
5
+
6
+ /**
7
+ * The sites command
8
+ * @param {import('commander').OptionValues} options
9
+ * @param {import('../base-command').BaseCommand} command
10
+ */
11
+ const sites = (options, command) => {
12
+ command.help()
13
+ }
14
+
15
+ /**
16
+ * Creates the `netlify sites` command
17
+ * @param {import('../base-command').BaseCommand} program
18
+ * @returns
19
+ */
20
+ const createSitesCommand = (program) => {
21
+ createSitesCreateCommand(program)
22
+ createSitesListCommand(program)
23
+ createSitesDeleteCommand(program)
24
+
25
+ return program
26
+ .command('sites')
27
+ .description(`Handle various site operations\nThe sites command will help you manage all your sites`)
28
+ .addExamples(['netlify sites:create --name my-new-site', 'netlify sites:list'])
29
+ .action(sites)
30
+ }
31
+
32
+ module.exports = { createSitesCommand }
@@ -1,120 +1,5 @@
1
- const { flags: flagsLib } = require('@oclif/command')
2
- const chalk = require('chalk')
3
- const clean = require('clean-deep')
4
- const prettyjson = require('prettyjson')
1
+ const { createStatusCommand } = require('./status')
5
2
 
6
- const Command = require('../../utils/command')
7
- const { error, exit, getToken, log, logJson, warn } = require('../../utils/command-helpers')
8
-
9
- class StatusCommand extends Command {
10
- async run() {
11
- const { api, globalConfig, site } = this.netlify
12
- const { flags } = this.parse(StatusCommand)
13
-
14
- const current = globalConfig.get('userId')
15
- const [accessToken] = await getToken()
16
-
17
- if (!accessToken) {
18
- log(`Not logged in. Please log in to see site status.`)
19
- log()
20
- log('Login with "netlify login" command')
21
- exit()
22
- }
23
-
24
- const siteId = site.id
25
-
26
- log(`──────────────────────┐
27
- Current Netlify User │
28
- ──────────────────────┘`)
29
-
30
- let accounts
31
- let user
32
-
33
- try {
34
- ;[accounts, user] = await Promise.all([api.listAccountsForUser(), api.getCurrentUser()])
35
- } catch (error_) {
36
- if (error_.status === 401) {
37
- error(
38
- 'Your session has expired. Please try to re-authenticate by running `netlify logout` and `netlify login`.',
39
- )
40
- }
41
- }
42
-
43
- const ghuser = this.netlify.globalConfig.get(`users.${current}.auth.github.user`)
44
- const accountData = {
45
- Name: user.full_name,
46
- Email: user.email,
47
- GitHub: ghuser,
48
- }
49
- const teamsData = {}
50
-
51
- accounts.forEach((team) => {
52
- teamsData[team.name] = team.roles_allowed.join(' ')
53
- })
54
-
55
- accountData.Teams = teamsData
56
-
57
- const cleanAccountData = clean(accountData)
58
-
59
- log(prettyjson.render(cleanAccountData))
60
-
61
- if (!siteId) {
62
- warn('Did you run `netlify link` yet?')
63
- error(`You don't appear to be in a folder that is linked to a site`)
64
- }
65
- let siteData
66
- try {
67
- siteData = await api.getSite({ siteId })
68
- } catch (error_) {
69
- // unauthorized
70
- if (error_.status === 401) {
71
- warn(`Log in with a different account or re-link to a site you have permission for`)
72
- error(`Not authorized to view the currently linked site (${siteId})`)
73
- }
74
- // missing
75
- if (error_.status === 404) {
76
- error(`The site this folder is linked to can't be found`)
77
- }
78
- error(error_)
79
- }
80
-
81
- // Json only logs out if --json flag is passed
82
- if (flags.json) {
83
- logJson({
84
- account: cleanAccountData,
85
- siteData: {
86
- 'site-name': `${siteData.name}`,
87
- 'config-path': site.configPath,
88
- 'admin-url': siteData.admin_url,
89
- 'site-url': siteData.ssl_url || siteData.url,
90
- 'site-id': siteData.id,
91
- },
92
- })
93
- }
94
-
95
- log(`────────────────────┐
96
- Netlify Site Info │
97
- ────────────────────┘`)
98
- log(
99
- prettyjson.render({
100
- 'Current site': `${siteData.name}`,
101
- 'Netlify TOML': site.configPath,
102
- 'Admin URL': chalk.magentaBright(siteData.admin_url),
103
- 'Site URL': chalk.cyanBright(siteData.ssl_url || siteData.url),
104
- 'Site Id': chalk.yellowBright(siteData.id),
105
- }),
106
- )
107
- log()
108
- }
3
+ module.exports = {
4
+ createStatusCommand,
109
5
  }
110
-
111
- StatusCommand.description = `Print status information`
112
-
113
- StatusCommand.flags = {
114
- verbose: flagsLib.boolean({
115
- description: 'Output system info',
116
- }),
117
- ...StatusCommand.flags,
118
- }
119
-
120
- module.exports = StatusCommand
@@ -0,0 +1,69 @@
1
+ // @ts-check
2
+ const { get } = require('dot-prop')
3
+ const prettyjson = require('prettyjson')
4
+
5
+ const { error, log, warn } = require('../../utils')
6
+
7
+ /**
8
+ * The status:hooks command
9
+ * @param {import('commander').OptionValues} options
10
+ * @param {import('../base-command').BaseCommand} command
11
+ */
12
+ const statusHooks = async (options, command) => {
13
+ const { api, site } = command.netlify
14
+
15
+ await command.authenticate()
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 })
40
+ const data = {
41
+ site: siteData.name,
42
+ hooks: {},
43
+ }
44
+ ntlHooks.forEach((hook) => {
45
+ data.hooks[hook.id] = {
46
+ type: hook.type,
47
+ event: hook.event,
48
+ id: hook.id,
49
+ disabled: hook.disabled,
50
+ }
51
+ if (get(siteData, 'build_settings.repo_url')) {
52
+ data.hooks[hook.id].repo_url = get(siteData, 'build_settings.repo_url')
53
+ }
54
+ })
55
+ log(`─────────────────┐
56
+ Site Hook Status │
57
+ ─────────────────┘`)
58
+ log(prettyjson.render(data))
59
+ }
60
+
61
+ /**
62
+ * Creates the `netlify status:hooks` command
63
+ * @param {import('../base-command').BaseCommand} program
64
+ * @returns
65
+ */
66
+ const createStatusHooksCommand = (program) =>
67
+ program.command('status:hooks').description('Print hook information of the linked site').action(statusHooks)
68
+
69
+ module.exports = { createStatusHooksCommand }