netlify-cli 8.0.7 → 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.
Files changed (183) hide show
  1. package/bin/run +81 -3
  2. package/npm-shrinkwrap.json +305 -2105
  3. package/package.json +10 -33
  4. package/src/commands/addons/addons-auth.js +50 -0
  5. package/src/commands/addons/addons-config.js +180 -0
  6. package/src/commands/addons/addons-create.js +129 -0
  7. package/src/commands/addons/addons-delete.js +59 -0
  8. package/src/commands/addons/addons-list.js +62 -0
  9. package/src/commands/addons/addons.js +49 -0
  10. package/src/commands/addons/index.js +3 -24
  11. package/src/commands/api/api.js +83 -0
  12. package/src/commands/api/index.js +5 -0
  13. package/src/commands/base-command.js +322 -0
  14. package/src/commands/build/build.js +58 -0
  15. package/src/commands/build/index.js +3 -61
  16. package/src/commands/completion/completion.js +18 -0
  17. package/src/commands/completion/index.js +5 -0
  18. package/src/commands/{deploy.js → deploy/deploy.js} +306 -278
  19. package/src/commands/deploy/index.js +5 -0
  20. package/src/commands/dev/dev-exec.js +39 -0
  21. package/src/commands/dev/dev-trace.js +50 -0
  22. package/src/commands/dev/dev.js +349 -0
  23. package/src/commands/dev/index.js +3 -335
  24. package/src/commands/env/env-get.js +51 -0
  25. package/src/commands/env/env-import.js +93 -0
  26. package/src/commands/env/env-list.js +63 -0
  27. package/src/commands/env/env-set.js +67 -0
  28. package/src/commands/env/env-unset.js +66 -0
  29. package/src/commands/env/env.js +47 -0
  30. package/src/commands/env/index.js +3 -23
  31. package/src/commands/functions/functions-build.js +59 -0
  32. package/src/commands/functions/{create.js → functions-create.js} +133 -94
  33. package/src/commands/functions/functions-invoke.js +276 -0
  34. package/src/commands/functions/functions-list.js +107 -0
  35. package/src/commands/functions/functions-serve.js +63 -0
  36. package/src/commands/functions/functions.js +53 -0
  37. package/src/commands/functions/index.js +3 -45
  38. package/src/commands/index.js +5 -0
  39. package/src/commands/init/index.js +6 -0
  40. package/src/commands/{init.js → init/init.js} +79 -68
  41. package/src/commands/link/index.js +6 -0
  42. package/src/{utils/link/link-by-prompt.js → commands/link/link.js} +153 -14
  43. package/src/commands/lm/index.js +3 -19
  44. package/src/commands/lm/lm-info.js +42 -0
  45. package/src/commands/lm/lm-install.js +36 -0
  46. package/src/commands/lm/lm-setup.js +106 -0
  47. package/src/commands/lm/lm-uninstall.js +25 -0
  48. package/src/commands/lm/lm.js +39 -0
  49. package/src/commands/login/index.js +6 -0
  50. package/src/commands/login/login.js +52 -0
  51. package/src/commands/logout/index.js +5 -0
  52. package/src/commands/logout/logout.js +43 -0
  53. package/src/commands/main.js +117 -0
  54. package/src/commands/open/index.js +3 -39
  55. package/src/commands/open/open-admin.js +56 -0
  56. package/src/commands/open/open-site.js +49 -0
  57. package/src/commands/open/open.js +42 -0
  58. package/src/commands/sites/index.js +5 -20
  59. package/src/commands/sites/sites-create.js +184 -0
  60. package/src/commands/sites/sites-delete.js +108 -0
  61. package/src/commands/sites/sites-list.js +89 -0
  62. package/src/commands/sites/sites.js +36 -0
  63. package/src/commands/status/index.js +3 -118
  64. package/src/commands/status/status-hooks.js +73 -0
  65. package/src/commands/status/status.js +125 -0
  66. package/src/commands/switch/index.js +5 -0
  67. package/src/commands/switch/switch.js +50 -0
  68. package/src/commands/unlink/index.js +5 -0
  69. package/src/commands/unlink/unlink.js +48 -0
  70. package/src/commands/watch/index.js +5 -0
  71. package/src/commands/watch/watch.js +121 -0
  72. package/src/lib/build.js +21 -7
  73. package/src/lib/exec-fetcher.js +5 -3
  74. package/src/lib/fs.js +54 -36
  75. package/src/lib/functions/background.js +1 -1
  76. package/src/lib/functions/form-submissions-handler.js +2 -1
  77. package/src/lib/functions/local-proxy.js +2 -1
  78. package/src/lib/functions/netlify-function.js +4 -1
  79. package/src/lib/functions/registry.js +4 -6
  80. package/src/lib/functions/runtimes/go/index.js +2 -1
  81. package/src/lib/functions/runtimes/js/builders/netlify-lambda.js +6 -4
  82. package/src/lib/functions/runtimes/js/builders/zisi.js +3 -3
  83. package/src/lib/functions/runtimes/rust/index.js +4 -3
  84. package/src/lib/functions/server.js +2 -3
  85. package/src/lib/functions/synchronous.js +2 -1
  86. package/src/lib/functions/utils.js +2 -3
  87. package/src/lib/functions/watcher.js +1 -0
  88. package/src/lib/http-agent.js +3 -5
  89. package/src/lib/log.js +2 -1
  90. package/src/lib/spinner.js +22 -0
  91. package/src/utils/addons/diffs/index.js +1 -0
  92. package/src/utils/addons/diffs/options.js +3 -1
  93. package/src/utils/addons/prepare.js +13 -6
  94. package/src/utils/addons/prompts.js +2 -1
  95. package/src/utils/addons/render.js +3 -1
  96. package/src/utils/command-helpers.js +156 -43
  97. package/src/utils/create-stream-promise.js +5 -5
  98. package/src/utils/deferred.js +1 -0
  99. package/src/utils/deploy/deploy-site.js +1 -1
  100. package/src/utils/deploy/index.js +4 -0
  101. package/src/utils/detect-server-settings.js +10 -12
  102. package/src/utils/dev.js +18 -10
  103. package/src/utils/dot-env.js +4 -2
  104. package/src/utils/{edge-handlers.js → functions/edge-handlers.js} +8 -7
  105. package/src/utils/functions/functions.js +36 -0
  106. package/src/utils/{get-functions.js → functions/get-functions.js} +2 -1
  107. package/src/utils/functions/index.js +8 -26
  108. package/src/utils/get-global-config.js +3 -2
  109. package/src/utils/get-repo-data.js +1 -0
  110. package/src/utils/gh-auth.js +1 -0
  111. package/src/utils/gitignore.js +7 -5
  112. package/src/utils/header.js +2 -2
  113. package/src/utils/headers.js +1 -2
  114. package/src/utils/index.js +42 -0
  115. package/src/utils/init/config-github.js +12 -5
  116. package/src/utils/init/config-manual.js +9 -2
  117. package/src/utils/init/config.js +13 -7
  118. package/src/utils/init/frameworks.js +1 -0
  119. package/src/utils/init/node-version.js +4 -2
  120. package/src/utils/init/plugins.js +1 -0
  121. package/src/utils/init/utils.js +10 -6
  122. package/src/utils/live-tunnel.js +3 -4
  123. package/src/utils/lm/install.js +10 -15
  124. package/src/utils/lm/requirements.js +3 -1
  125. package/src/utils/lm/steps.js +1 -1
  126. package/src/utils/lm/ui.js +7 -3
  127. package/src/utils/open-browser.js +8 -2
  128. package/src/utils/parse-raw-flags.js +4 -4
  129. package/src/utils/proxy.js +6 -5
  130. package/src/utils/read-repo-url.js +1 -0
  131. package/src/utils/redirects.js +2 -2
  132. package/src/utils/rules-proxy.js +2 -1
  133. package/src/utils/state-config.js +1 -1
  134. package/src/utils/telemetry/index.js +2 -113
  135. package/src/utils/telemetry/request.js +3 -1
  136. package/src/utils/telemetry/telemetry.js +117 -0
  137. package/src/utils/telemetry/validation.js +13 -12
  138. package/src/utils/traffic-mesh.js +3 -3
  139. package/oclif.manifest.json +0 -1
  140. package/src/commands/addons/auth.js +0 -42
  141. package/src/commands/addons/config.js +0 -177
  142. package/src/commands/addons/create.js +0 -127
  143. package/src/commands/addons/delete.js +0 -69
  144. package/src/commands/addons/list.js +0 -54
  145. package/src/commands/api.js +0 -84
  146. package/src/commands/dev/exec.js +0 -32
  147. package/src/commands/dev/trace.js +0 -61
  148. package/src/commands/env/get.js +0 -44
  149. package/src/commands/env/import.js +0 -90
  150. package/src/commands/env/list.js +0 -49
  151. package/src/commands/env/set.js +0 -64
  152. package/src/commands/env/unset.js +0 -58
  153. package/src/commands/functions/build.js +0 -60
  154. package/src/commands/functions/invoke.js +0 -277
  155. package/src/commands/functions/list.js +0 -102
  156. package/src/commands/functions/serve.js +0 -70
  157. package/src/commands/link.js +0 -133
  158. package/src/commands/lm/info.js +0 -36
  159. package/src/commands/lm/install.js +0 -30
  160. package/src/commands/lm/setup.js +0 -107
  161. package/src/commands/lm/uninstall.js +0 -17
  162. package/src/commands/login.js +0 -54
  163. package/src/commands/logout.js +0 -37
  164. package/src/commands/open/admin.js +0 -51
  165. package/src/commands/open/site.js +0 -43
  166. package/src/commands/sites/create.js +0 -191
  167. package/src/commands/sites/delete.js +0 -116
  168. package/src/commands/sites/list.js +0 -84
  169. package/src/commands/status/hooks.js +0 -60
  170. package/src/commands/switch.js +0 -44
  171. package/src/commands/unlink.js +0 -38
  172. package/src/commands/watch.js +0 -115
  173. package/src/hooks/init.js +0 -46
  174. package/src/index.js +0 -25
  175. package/src/lib/help.js +0 -26
  176. package/src/utils/chalk.js +0 -16
  177. package/src/utils/check-command-inputs.js +0 -21
  178. package/src/utils/command.js +0 -262
  179. package/src/utils/detect-functions-builder.js +0 -25
  180. package/src/utils/difference.js +0 -4
  181. package/src/utils/logo.js +0 -11
  182. package/src/utils/show-help.js +0 -5
  183. package/src/utils/telemetry/tracked-command.js +0 -51
@@ -0,0 +1,83 @@
1
+ // @ts-check
2
+ const AsciiTable = require('ascii-table')
3
+
4
+ // TODO: use static `import` after migrating this repository to pure ES modules
5
+ const jsClient = import('netlify')
6
+
7
+ const { chalk, error, exit, generateDescriptionHelp, generateExamplesHelp, log, logJson } = require('../../utils')
8
+
9
+ /**
10
+ * The api command
11
+ * @param {string} apiMethod
12
+ * @param {import('commander').OptionValues} options
13
+ * @param {import('../base-command').BaseCommand} command
14
+ */
15
+ const apiCommand = async (apiMethod, options, command) => {
16
+ const { api } = command.netlify
17
+
18
+ if (options.list) {
19
+ const table = new AsciiTable(`Netlify API Methods`)
20
+ table.setHeading('API Method', 'Docs Link')
21
+ const { methods } = await jsClient
22
+ methods.forEach((method) => {
23
+ const { operationId } = method
24
+ table.addRow(operationId, `https://open-api.netlify.com/#operation/${operationId}`)
25
+ })
26
+ log(table.toString())
27
+ log()
28
+ log('Above is a list of available API methods')
29
+ log(`To run a method use "${chalk.cyanBright('netlify api methodName')}"`)
30
+ exit()
31
+ }
32
+
33
+ if (!apiMethod) {
34
+ error(`You must provide an API method. Run "netlify api --list" to see available methods`)
35
+ }
36
+
37
+ if (!api[apiMethod] || typeof api[apiMethod] !== 'function') {
38
+ error(`"${apiMethod}"" is not a valid api method. Run "netlify api --list" to see available methods`)
39
+ }
40
+
41
+ let payload
42
+ if (options.data) {
43
+ payload = typeof options.data === 'string' ? JSON.parse(options.data) : options.data
44
+ } else {
45
+ payload = {}
46
+ }
47
+ try {
48
+ const apiResponse = await api[apiMethod](payload)
49
+ logJson(apiResponse)
50
+ } catch (error_) {
51
+ error(error_)
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Creates the `netlify api` command
57
+ * @param {import('../base-command').BaseCommand} program
58
+ * @returns
59
+ */
60
+ const createApiCommand = (program) =>
61
+ program
62
+ .command('api')
63
+ .argument('[method]', 'Open API method to run')
64
+ .option('-d, --data <data>', 'Data to use')
65
+ .option('--list', 'List out available API methods', false)
66
+ .addHelpText(
67
+ 'after',
68
+ generateDescriptionHelp(
69
+ `For more information on available methods checkout https://open-api.netlify.com/ or run '${chalk.grey(
70
+ 'netlify api --list',
71
+ )}'`,
72
+ ),
73
+ )
74
+ .addHelpText(
75
+ 'after',
76
+ generateExamplesHelp([
77
+ 'netlify api --list',
78
+ `netlify api getSite --data '${chalk.grey('{ "site_id": "123456"}')}'`,
79
+ ]),
80
+ )
81
+ .action(apiCommand)
82
+
83
+ module.exports = { createApiCommand }
@@ -0,0 +1,5 @@
1
+ const { createApiCommand } = require('./api')
2
+
3
+ module.exports = {
4
+ createApiCommand,
5
+ }
@@ -0,0 +1,322 @@
1
+ // @ts-check
2
+ const process = require('process')
3
+ const { format } = require('util')
4
+
5
+ const resolveConfig = require('@netlify/config')
6
+ const { Command } = require('commander')
7
+ const debug = require('debug')
8
+ const merge = require('lodash/merge')
9
+
10
+ // TODO: use static `import` after migrating this repository to pure ES modules
11
+ const jsClient = import('netlify')
12
+
13
+ const { getAgent } = require('../lib/http-agent')
14
+ const {
15
+ StateConfig,
16
+ USER_AGENT,
17
+ chalk,
18
+ error,
19
+ exit,
20
+ getGlobalConfig,
21
+ getToken,
22
+ identify,
23
+ log,
24
+ normalizeConfig,
25
+ openBrowser,
26
+ pollForToken,
27
+ track,
28
+ } = require('../utils')
29
+
30
+ // Netlify CLI client id. Lives in bot@netlify.com
31
+ // TODO: setup client for multiple environments
32
+ const CLIENT_ID = 'd6f37de6614df7ae58664cfca524744d73807a377f5ee71f1a254f78412e3750'
33
+
34
+ const NANO_SECS_TO_MSECS = 1e6
35
+
36
+ /**
37
+ * Get the duration between a start time and the current time
38
+ * @param {bigint} startTime
39
+ * @returns
40
+ */
41
+ const getDuration = function (startTime) {
42
+ const durationNs = process.hrtime.bigint() - startTime
43
+ return Math.round(Number(durationNs / BigInt(NANO_SECS_TO_MSECS)))
44
+ }
45
+
46
+ /**
47
+ * The netlify object inside each command with the state
48
+ * @typedef NetlifyOptions
49
+ * @type {object}
50
+ * @property {import('netlify').NetlifyAPI} api
51
+ * @property {*} repositoryRoot
52
+ * @property {object} site
53
+ * @property {*} site.root
54
+ * @property {*} site.configPath
55
+ * @property {*} site.id
56
+ * @property {*} siteInfo
57
+ * @property {*} config
58
+ * @property {*} cachedConfig
59
+ * @property {*} globalConfig
60
+ * @property {StateConfig} state,
61
+ */
62
+
63
+ /** Base command class that provides tracking and config initialization */
64
+ class BaseCommand extends Command {
65
+ /** @type {NetlifyOptions} */
66
+ netlify
67
+
68
+ /** @type {{ startTime: bigint, payload?: any}} */
69
+ analytics = { startTime: process.hrtime.bigint() }
70
+
71
+ /**
72
+ * IMPORTANT this function will be called for each command!
73
+ * Don't do anything expensive in there.
74
+ * @param {string} name The command name
75
+ * @returns
76
+ */
77
+ createCommand(name) {
78
+ return (
79
+ new BaseCommand(name)
80
+ // If --silent or --json flag passed disable logger
81
+ .option('--json')
82
+ .option('--cwd <cwd>', 'Pass a current working directory.')
83
+ .option('-o, --offline')
84
+
85
+ // Allow hidden flags like
86
+ // --json,
87
+ // --silent,
88
+ // --offline, -o
89
+ // --cwd <cwd> Pass a current working directory.
90
+
91
+ // this disables the suggestions
92
+ // .allowUnknownOption(true)
93
+
94
+ .option('--debug', 'Print debugging information')
95
+ .option(
96
+ '--httpProxy',
97
+ 'Proxy server address to route requests through',
98
+ process.env.HTTP_PROXY || process.env.HTTPS_PROXY,
99
+ )
100
+ .option(
101
+ '--httpProxyCertificateFilename',
102
+ 'Certificate file to use when connecting using a proxy server',
103
+ process.env.NETLIFY_PROXY_CERTIFICATE_FILENAME,
104
+ )
105
+ .hook('preAction', async (_parentCommand, actionCommand) => {
106
+ debug(`${name}:preAction`)('start')
107
+ this.analytics = { startTime: process.hrtime.bigint() }
108
+ // @ts-ignore cannot type actionCommand as BaseCommand
109
+ await this.init(actionCommand)
110
+ debug(`${name}:preAction`)('end')
111
+ })
112
+ )
113
+ }
114
+
115
+ /**
116
+ * Will be called on the end of an action to track the metrics
117
+ * @param {*} [error_]
118
+ */
119
+ async onEnd(error_) {
120
+ const { payload, startTime } = this.analytics
121
+ const duration = getDuration(startTime)
122
+ const status = error_ === undefined ? 'success' : 'error'
123
+
124
+ debug(`${this.name()}:onEnd`)(`Status: ${status}`)
125
+ debug(`${this.name()}:onEnd`)(`Duration: ${duration}ms`)
126
+
127
+ await track('command', {
128
+ ...payload,
129
+ command: this.name(),
130
+ duration,
131
+ status,
132
+ })
133
+
134
+ if (error_ !== undefined) {
135
+ error(error_ instanceof Error ? error_ : format(error_), { exit: false })
136
+ exit(1)
137
+ }
138
+ }
139
+
140
+ async authenticate(tokenFromFlag) {
141
+ const [token] = await getToken(tokenFromFlag)
142
+ if (token) {
143
+ return token
144
+ }
145
+ return this.expensivelyAuthenticate()
146
+ }
147
+
148
+ async expensivelyAuthenticate() {
149
+ const webUI = process.env.NETLIFY_WEB_UI || 'https://app.netlify.com'
150
+ log(`Logging into your Netlify account...`)
151
+
152
+ // Create ticket for auth
153
+ // @ts-ignore Types from api are wrong and they don't recognize `createTicket`
154
+ const ticket = await this.netlify.api.createTicket({
155
+ clientId: CLIENT_ID,
156
+ })
157
+
158
+ // Open browser for authentication
159
+ const authLink = `${webUI}/authorize?response_type=ticket&ticket=${ticket.id}`
160
+
161
+ log(`Opening ${authLink}`)
162
+ await openBrowser({ url: authLink })
163
+
164
+ const accessToken = await pollForToken({
165
+ api: this.netlify.api,
166
+ ticket,
167
+ })
168
+
169
+ // @ts-ignore Types from api are wrong and they don't recognize `getCurrentUser`
170
+ const { email, full_name: name, id: userId } = await this.netlify.api.getCurrentUser()
171
+
172
+ const userData = merge(this.netlify.globalConfig.get(`users.${userId}`), {
173
+ id: userId,
174
+ name,
175
+ email,
176
+ auth: {
177
+ token: accessToken,
178
+ github: {
179
+ user: undefined,
180
+ token: undefined,
181
+ },
182
+ },
183
+ })
184
+ // Set current userId
185
+ this.netlify.globalConfig.set('userId', userId)
186
+ // Set user data
187
+ this.netlify.globalConfig.set(`users.${userId}`, userData)
188
+
189
+ await identify({
190
+ name,
191
+ email,
192
+ userId,
193
+ })
194
+ await track('user_login', {
195
+ email,
196
+ })
197
+
198
+ // Log success
199
+ log()
200
+ log(`${chalk.greenBright('You are now logged into your Netlify account!')}`)
201
+ log()
202
+ log(`Run ${chalk.cyanBright('netlify status')} for account details`)
203
+ log()
204
+ log(`To see all available commands run: ${chalk.cyanBright('netlify help')}`)
205
+ log()
206
+ return accessToken
207
+ }
208
+
209
+ setAnalyticsPayload(payload) {
210
+ this.analytics = { ...this.analytics, payload }
211
+ }
212
+
213
+ /**
214
+ * Initializes the options and parses the configuration needs to be called on start of a command function
215
+ * @param {BaseCommand} actionCommand The command of the action that is run (`this.` gets the parent command)
216
+ */
217
+ async init(actionCommand) {
218
+ debug(`${actionCommand.name()}:init`)('start')
219
+ const options = actionCommand.opts()
220
+ const cwd = options.cwd || process.cwd()
221
+ // Get site id & build state
222
+ const state = new StateConfig(cwd)
223
+
224
+ const [token] = await getToken(options.auth)
225
+
226
+ const apiUrlOpts = {
227
+ userAgent: USER_AGENT,
228
+ }
229
+
230
+ if (process.env.NETLIFY_API_URL) {
231
+ const apiUrl = new URL(process.env.NETLIFY_API_URL)
232
+ apiUrlOpts.scheme = apiUrl.protocol.slice(0, -1)
233
+ apiUrlOpts.host = apiUrl.host
234
+ apiUrlOpts.pathPrefix =
235
+ process.env.NETLIFY_API_URL === `${apiUrl.protocol}//${apiUrl.host}` ? '/api/v1' : apiUrl.pathname
236
+ }
237
+
238
+ const cachedConfig = await actionCommand.getConfig({ cwd, state, token, ...apiUrlOpts })
239
+ const { buildDir, config, configPath, repositoryRoot, siteInfo } = cachedConfig
240
+ const normalizedConfig = normalizeConfig(config)
241
+
242
+ const agent = await getAgent({
243
+ httpProxy: options.httpProxy,
244
+ certificateFile: options.httpProxyCertificateFilename,
245
+ })
246
+ const apiOpts = { ...apiUrlOpts, agent }
247
+ const globalConfig = await getGlobalConfig()
248
+ const { NetlifyAPI } = await jsClient
249
+
250
+ actionCommand.netlify = {
251
+ // api methods
252
+ api: new NetlifyAPI(token || '', apiOpts),
253
+ repositoryRoot,
254
+ // current site context
255
+ site: {
256
+ root: buildDir,
257
+ configPath,
258
+ get id() {
259
+ return state.get('siteId')
260
+ },
261
+ set id(id) {
262
+ state.set('siteId', id)
263
+ },
264
+ },
265
+ // Site information retrieved using the API
266
+ siteInfo,
267
+ // Configuration from netlify.[toml/yml]
268
+ config: normalizedConfig,
269
+ // Used to avoid calling @netlify/config again
270
+ cachedConfig,
271
+ // global cli config
272
+ globalConfig,
273
+ // state of current site dir
274
+ state,
275
+ }
276
+ debug(`${this.name()}:init`)('end')
277
+ }
278
+
279
+ /**
280
+ * Find and resolve the Netlify configuration
281
+ * @param {*} config
282
+ * @returns {ReturnType<import('@netlify/config/src/main')>}
283
+ */
284
+ async getConfig(config) {
285
+ const options = this.opts()
286
+ const { cwd, host, offline = options.offline, pathPrefix, scheme, state, token } = config
287
+
288
+ try {
289
+ return await resolveConfig({
290
+ config: options.config,
291
+ cwd,
292
+ context: options.context || this.name(),
293
+ debug: this.opts().debug,
294
+ siteId: options.siteId || (typeof options.site === 'string' && options.site) || state.get('siteId'),
295
+ token,
296
+ mode: 'cli',
297
+ host,
298
+ pathPrefix,
299
+ scheme,
300
+ offline,
301
+ })
302
+ } catch (error_) {
303
+ const isUserError = error_.customErrorInfo !== undefined && error_.customErrorInfo.type === 'resolveConfig'
304
+
305
+ // If we're failing due to an error thrown by us, it might be because the token we're using is invalid.
306
+ // To account for that, we try to retrieve the config again, this time without a token, to avoid making
307
+ // any API calls.
308
+ //
309
+ // @todo Replace this with a mechanism for calling `resolveConfig` with more granularity (i.e. having
310
+ // the option to say that we don't need API data.)
311
+ if (isUserError && !offline && token) {
312
+ return this.getConfig({ cwd, offline: true, state, token })
313
+ }
314
+
315
+ const message = isUserError ? error_.message : error_.stack
316
+ console.error(message)
317
+ exit(1)
318
+ }
319
+ }
320
+ }
321
+
322
+ module.exports = { BaseCommand }
@@ -0,0 +1,58 @@
1
+ // @ts-check
2
+ const { getBuildOptions, runBuild } = require('../../lib/build')
3
+ const { error, exit, generateExamplesHelp, getToken } = require('../../utils')
4
+
5
+ /**
6
+ * @param {import('../../lib/build').BuildConfig} options
7
+ */
8
+ const checkOptions = ({ cachedConfig: { siteInfo = {} }, token }) => {
9
+ if (!siteInfo.id) {
10
+ error('Could not find the site ID. Please run netlify link.')
11
+ }
12
+
13
+ if (!token) {
14
+ error('Could not find the access token. Please run netlify login.')
15
+ }
16
+ }
17
+
18
+ /**
19
+ * The build command
20
+ * @param {import('commander').OptionValues} options
21
+ * @param {import('../base-command').BaseCommand} command
22
+ */
23
+ const build = async (options, command) => {
24
+ command.setAnalyticsPayload({ dry: options.dry })
25
+
26
+ // Retrieve Netlify Build options
27
+ const [token] = await getToken()
28
+
29
+ const buildOptions = await getBuildOptions({
30
+ cachedConfig: command.netlify.cachedConfig,
31
+ token,
32
+ options,
33
+ })
34
+
35
+ if (!options.offline) {
36
+ checkOptions(buildOptions)
37
+ }
38
+
39
+ const { exitCode } = await runBuild(buildOptions)
40
+ exit(exitCode)
41
+ }
42
+
43
+ /**
44
+ * Creates the `netlify build` command
45
+ * @param {import('../base-command').BaseCommand} program
46
+ * @returns
47
+ */
48
+ const createBuildCommand = (program) =>
49
+ program
50
+ .command('build')
51
+ .description('(Beta) Build on your local machine')
52
+ .option('--dry', 'Dry run: show instructions without running them', false)
53
+ .option('--context [context]', 'Build context')
54
+ .option('-o, --offline', 'disables any features that require network access', false)
55
+ .addHelpText('after', generateExamplesHelp(['netlify build']))
56
+ .action(build)
57
+
58
+ module.exports = { createBuildCommand }
@@ -1,63 +1,5 @@
1
- const { flags: flagsLib } = require('@oclif/command')
1
+ const { createBuildCommand } = require('./build')
2
2
 
3
- const { getBuildOptions, runBuild } = require('../../lib/build')
4
- const Command = require('../../utils/command')
5
- const { error, exit, getToken } = require('../../utils/command-helpers')
6
-
7
- const checkOptions = ({ cachedConfig: { siteInfo = {} }, token }) => {
8
- if (!siteInfo.id) {
9
- error('Could not find the site ID. Please run netlify link.', { exit: 1 })
10
- }
11
-
12
- if (!token) {
13
- error('Could not find the access token. Please run netlify login.', { exit: 1 })
14
- }
15
- }
16
-
17
- class BuildCommand extends Command {
18
- // Run Netlify Build
19
- async run() {
20
- const { flags } = this.parse(BuildCommand)
21
-
22
- this.setAnalyticsPayload({ dry: flags.dry })
23
-
24
- // Retrieve Netlify Build options
25
- const [token] = await getToken()
26
-
27
- const options = await getBuildOptions({
28
- context: this,
29
- token,
30
- flags,
31
- })
32
-
33
- if (!flags.offline) {
34
- checkOptions(options)
35
- }
36
-
37
- const { exitCode } = await runBuild(options)
38
- exit(exitCode)
39
- }
40
- }
41
-
42
- // Netlify Build programmatic options
43
- BuildCommand.flags = {
44
- dry: flagsLib.boolean({
45
- description: 'Dry run: show instructions without running them',
46
- default: false,
47
- }),
48
- context: flagsLib.string({
49
- description: 'Build context',
50
- }),
51
- offline: flagsLib.boolean({
52
- char: 'o',
53
- description: 'disables any features that require network access',
54
- default: false,
55
- }),
56
- ...BuildCommand.flags,
3
+ module.exports = {
4
+ createBuildCommand,
57
5
  }
58
-
59
- BuildCommand.description = `(Beta) Build on your local machine`
60
-
61
- BuildCommand.examples = ['netlify build']
62
-
63
- module.exports = BuildCommand
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The completion command
3
+ * @param {import('commander').OptionValues} options
4
+ * @param {import('../base-command').BaseCommand} command
5
+ */
6
+ const completion = (options, command) => {
7
+ console.log('completion command with options', options, command.name())
8
+ }
9
+
10
+ /**
11
+ * Creates the `netlify completion` command
12
+ * @param {import('../base-command').BaseCommand} program
13
+ * @returns
14
+ */
15
+ const createCompletionCommand = (program) =>
16
+ program.command('completion').description('(Beta) Generate shell completion script').action(completion)
17
+
18
+ module.exports = { createCompletionCommand }
@@ -0,0 +1,5 @@
1
+ const { createCompletionCommand } = require('./completion')
2
+
3
+ module.exports = {
4
+ createCompletionCommand,
5
+ }