netlify-cli 10.7.1 → 10.9.1

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": "10.7.1",
4
+ "version": "10.9.1",
5
5
  "author": "Netlify Inc.",
6
6
  "contributors": [
7
7
  "Abraham Schilling <AbrahamSchilling@gmail.com> (https://gitlab.com/n4bb12)",
@@ -31,6 +31,7 @@
31
31
  "Dan Loewenherz <dan@lionheartsw.com> (https://twitter.com/dwlz)",
32
32
  "Daniel Tschinder (https://twitter.com/TschinderDaniel)",
33
33
  "Daniel Woelfel <dwwoelfel@gmail.com> (https://twitter.com/danielwoelfel)",
34
+ "Dario De Vito",
34
35
  "Dave Ackerman <dmackerman@gmail.com>",
35
36
  "David Calavera <david@netlify.com> (https://twitter.com/calavera)",
36
37
  "David Lemler <dlemler@pm.me> (https://twitter.com/davidlemlerm)",
@@ -91,6 +92,7 @@
91
92
  "Nicolas Gonzalez",
92
93
  "Pankaj Patil <pankaj.patil2099@hotmail.com> (https://twitter.com/pankajpatil16)",
93
94
  "Peter",
95
+ "Prince Wilson (https://twitter.com/maxcell)",
94
96
  "Rachael Stavchansky",
95
97
  "Raees Iqbal <raees@netlify.com> (https://raeesbhatti.com/)",
96
98
  "Ricardo Mendes <rokusu@gmail.com> (https://twitter.com/locks)",
@@ -139,6 +141,7 @@
139
141
  "dustincrogers",
140
142
  "ehmicky (https://twitter.com/ehmicky)",
141
143
  "internal tools netlibot",
144
+ "just toby",
142
145
  "kvn-shn",
143
146
  "netlibot (https://www.netlify.com)",
144
147
  "nikoladev",
@@ -213,18 +216,18 @@
213
216
  "prettier": "--ignore-path .gitignore --loglevel=warn \"{src,tools,scripts,site,tests,.github}/**/*.{mjs,cjs,js,md,yml,json,html}\" \"*.{mjs,cjs,js,yml,json,html}\" \".*.{mjs,cjs,js,yml,json,html}\" \"!CHANGELOG.md\" \"!npm-shrinkwrap.json\" \"!**/*/package-lock.json\" \"!.github/**/*.md\""
214
217
  },
215
218
  "dependencies": {
216
- "@netlify/build": "^27.3.2",
219
+ "@netlify/build": "^27.4.0",
217
220
  "@netlify/config": "^18.1.1",
218
- "@netlify/edge-bundler": "^1.4.3",
221
+ "@netlify/edge-bundler": "^1.5.0",
219
222
  "@netlify/framework-info": "^9.1.0",
220
223
  "@netlify/local-functions-proxy": "^1.1.1",
221
- "@netlify/plugins-list": "^6.30.0",
222
- "@netlify/zip-it-and-ship-it": "^5.11.1",
224
+ "@netlify/plugins-list": "^6.33.0",
225
+ "@netlify/zip-it-and-ship-it": "^5.13.0",
223
226
  "@octokit/rest": "^18.0.0",
224
227
  "@sindresorhus/slugify": "^1.1.0",
225
228
  "ansi-escapes": "^5.0.0",
226
229
  "ansi-styles": "^5.0.0",
227
- "ansi2html": "^0.0.1",
230
+ "ansi-to-html": "^0.7.2",
228
231
  "ascii-table": "0.0.9",
229
232
  "backoff": "^2.5.0",
230
233
  "better-opn": "^3.0.0",
@@ -233,7 +236,7 @@
233
236
  "chokidar": "^3.0.2",
234
237
  "ci-info": "^3.0.0",
235
238
  "clean-deep": "^3.0.2",
236
- "commander": "^9.0.0",
239
+ "commander": "^9.2.0",
237
240
  "concordance": "^5.0.0",
238
241
  "configstore": "^5.0.0",
239
242
  "content-type": "^1.0.4",
@@ -258,7 +261,6 @@
258
261
  "fuzzy": "^0.1.3",
259
262
  "get-port": "^5.1.0",
260
263
  "gh-release-fetch": "^3.0.0",
261
- "git-clone": "^0.2.0",
262
264
  "git-repo-info": "^2.1.0",
263
265
  "gitconfiglocal": "^2.1.0",
264
266
  "hasbin": "^1.2.3",
@@ -285,7 +287,7 @@
285
287
  "multiparty": "^4.2.1",
286
288
  "netlify": "^11.0.2",
287
289
  "netlify-headers-parser": "^6.0.2",
288
- "netlify-onegraph-internal": "0.3.1",
290
+ "netlify-onegraph-internal": "0.3.6",
289
291
  "netlify-redirect-parser": "^13.0.5",
290
292
  "netlify-redirector": "^0.2.1",
291
293
  "node-fetch": "^2.6.0",
@@ -319,7 +321,7 @@
319
321
  "unixify": "^1.0.0",
320
322
  "update-notifier": "^5.0.0",
321
323
  "uuid": "^8.0.0",
322
- "wait-port": "^0.2.2",
324
+ "wait-port": "^0.2.14",
323
325
  "winston": "^3.2.1",
324
326
  "write-file-atomic": "^4.0.0"
325
327
  },
@@ -37,12 +37,21 @@ const { sitesCreate } = require('../sites')
37
37
 
38
38
  const DEFAULT_DEPLOY_TIMEOUT = 1.2e6
39
39
 
40
- const triggerDeploy = async ({ api, siteData, siteId }) => {
40
+ const triggerDeploy = async ({ api, options, siteData, siteId }) => {
41
41
  try {
42
42
  const siteBuild = await api.createSiteBuild({ siteId })
43
- log(
44
- `${NETLIFYDEV} A new deployment was triggered successfully. Visit https://app.netlify.com/sites/${siteData.name}/deploys/${siteBuild.deploy_id} to see the logs.`,
45
- )
43
+ if (options.json) {
44
+ logJson({
45
+ site_id: siteId,
46
+ site_name: siteData.name,
47
+ deploy_id: `${siteBuild.deploy_id}`,
48
+ logs: `https://app.netlify.com/sites/${siteData.name}/deploys/${siteBuild.deploy_id}`,
49
+ })
50
+ } else {
51
+ log(
52
+ `${NETLIFYDEV} A new deployment was triggered successfully. Visit https://app.netlify.com/sites/${siteData.name}/deploys/${siteBuild.deploy_id} to see the logs.`,
53
+ )
54
+ }
46
55
  } catch (error_) {
47
56
  if (error_.status === 404) {
48
57
  error('Site not found. Please rerun "netlify link" and make sure that your site has CI configured.')
@@ -553,7 +562,7 @@ const deploy = async (options, command) => {
553
562
  const deployToProduction = options.prod || (options.prodIfUnlocked && !siteData.published_deploy.locked)
554
563
 
555
564
  if (options.trigger) {
556
- return triggerDeploy({ api, siteId, siteData })
565
+ return triggerDeploy({ api, options, siteData, siteId })
557
566
  }
558
567
 
559
568
  const { newConfig, configMutations = [] } = await handleBuild({
@@ -234,6 +234,7 @@ const FRAMEWORK_PORT_TIMEOUT = 6e5
234
234
  * @param {InspectSettings} params.inspectSettings
235
235
  * @param {() => Promise<object>} params.getUpdatedConfig
236
236
  * @param {string} params.geolocationMode
237
+ * @param {string} params.geoCountry
237
238
  * @param {*} params.settings
238
239
  * @param {boolean} params.offline
239
240
  * @param {*} params.site
@@ -243,6 +244,7 @@ const FRAMEWORK_PORT_TIMEOUT = 6e5
243
244
  const startProxyServer = async ({
244
245
  addonsUrls,
245
246
  config,
247
+ geoCountry,
246
248
  geolocationMode,
247
249
  getUpdatedConfig,
248
250
  inspectSettings,
@@ -256,6 +258,7 @@ const startProxyServer = async ({
256
258
  config,
257
259
  configPath: site.configPath,
258
260
  geolocationMode,
261
+ geoCountry,
259
262
  getUpdatedConfig,
260
263
  inspectSettings,
261
264
  offline,
@@ -386,6 +389,19 @@ const validateShortFlagArgs = (args) => {
386
389
  return args
387
390
  }
388
391
 
392
+ const validateGeoCountryCode = (arg) => {
393
+ // Validate that the arg passed is two letters only for country
394
+ // See https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes
395
+ if (!/^[a-z]{2}$/i.test(arg)) {
396
+ throw new Error(
397
+ `The geo country code must use a two letter abbreviation.
398
+ ${chalk.red(BANG)} Example:
399
+ netlify dev --geo=mock --country=FR`,
400
+ )
401
+ }
402
+ return arg.toUpperCase()
403
+ }
404
+
389
405
  /**
390
406
  * The dev command
391
407
  * @param {import('commander').OptionValues} options
@@ -460,6 +476,7 @@ const dev = async (options, command) => {
460
476
  addonsUrls,
461
477
  config,
462
478
  geolocationMode: options.geo,
479
+ geoCountry: options.country,
463
480
  getUpdatedConfig,
464
481
  inspectSettings,
465
482
  offline: options.offline,
@@ -501,7 +518,13 @@ const dev = async (options, command) => {
501
518
  graphqlDocument = defaultExampleOperationsDoc
502
519
  }
503
520
 
504
- stopWatchingCLISessions = await startOneGraphCLISession({ netlifyGraphConfig, netlifyToken, site, state })
521
+ stopWatchingCLISessions = await startOneGraphCLISession({
522
+ netlifyGraphConfig,
523
+ netlifyToken,
524
+ site,
525
+ state,
526
+ oneGraphSessionId: options.sessionId,
527
+ })
505
528
 
506
529
  // Should be created by startOneGraphCLISession
507
530
  const oneGraphSessionId = loadCLISession(state)
@@ -593,12 +616,19 @@ const createDevCommand = (program) => {
593
616
  .choices(['cache', 'mock', 'update'])
594
617
  .default('cache'),
595
618
  )
619
+ .addOption(
620
+ new Option(
621
+ '--country <geoCountry>',
622
+ 'Two-letter country code (ISO 3166-1 alpha-2, https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) to use as mock geolocation (enables --geo=mock autmatically)',
623
+ ).argParser(validateGeoCountryCode),
624
+ )
596
625
  .addOption(
597
626
  new Option('--staticServerPort <port>', 'port of the static app server used when no framework is detected')
598
627
  .argParser((value) => Number.parseInt(value))
599
628
  .hideHelp(),
600
629
  )
601
630
  .addOption(new Option('--graph', 'enable Netlify Graph support').hideHelp())
631
+ .addOption(new Option('--sessionId [sessionId]', '(Graph) connect to cloud session with ID [sessionId]'))
602
632
  .addOption(
603
633
  new Option(
604
634
  '-e, --edgeInspect [address]',
@@ -20,14 +20,14 @@ const safeGetSite = async (api, siteId) => {
20
20
  }
21
21
 
22
22
  /**
23
- * The env:migrate command
23
+ * The env:clone command
24
24
  * @param {string} siteIdA Site (From)
25
25
  * @param {string} siteIdB Site (To)
26
26
  * @param {import('commander').OptionValues} options
27
27
  * @param {import('../base-command').BaseCommand} command
28
28
  * @returns {Promise<boolean>}
29
29
  */
30
- const envMigrate = async (options, command) => {
30
+ const envClone = async (options, command) => {
31
31
  const { api, site } = command.netlify
32
32
 
33
33
  if (!site.id && !options.from) {
@@ -75,7 +75,7 @@ const envMigrate = async (options, command) => {
75
75
  }
76
76
 
77
77
  log(
78
- `Successfully migrated environment variables from ${chalk.greenBright(siteFrom.name)} to ${chalk.greenBright(
78
+ `Successfully cloned environment variables from ${chalk.greenBright(siteFrom.name)} to ${chalk.greenBright(
79
79
  siteTo.name,
80
80
  )}`,
81
81
  )
@@ -98,7 +98,7 @@ const mongoToMongo = async ({ api, siteFrom, siteTo }) => {
98
98
  ] = [siteFrom, siteTo]
99
99
 
100
100
  if (isEmpty(envFrom)) {
101
- log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to migrate`)
101
+ log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to clone`)
102
102
  return false
103
103
  }
104
104
 
@@ -130,7 +130,7 @@ const mongoToEnvelope = async ({ api, siteFrom, siteTo }) => {
130
130
  const keysFrom = Object.keys(envFrom)
131
131
 
132
132
  if (isEmpty(envFrom)) {
133
- log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to migrate`)
133
+ log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to clone`)
134
134
  return false
135
135
  }
136
136
 
@@ -163,7 +163,7 @@ const envelopeToMongo = async ({ api, siteFrom, siteTo }) => {
163
163
  const envFrom = translateFromEnvelopeToMongo(envelopeVariables)
164
164
 
165
165
  if (isEmpty(envFrom)) {
166
- log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to migrate`)
166
+ log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to clone`)
167
167
  return false
168
168
  }
169
169
 
@@ -201,7 +201,7 @@ const envelopeToEnvelope = async ({ api, siteFrom, siteTo }) => {
201
201
  const keysFrom = envelopeFrom.map(({ key }) => key)
202
202
 
203
203
  if (isEmpty(keysFrom)) {
204
- log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to migrate`)
204
+ log(`${chalk.greenBright(siteFrom.name)} has no environment variables, nothing to clone`)
205
205
  return false
206
206
  }
207
207
 
@@ -222,20 +222,18 @@ const envelopeToEnvelope = async ({ api, siteFrom, siteTo }) => {
222
222
  }
223
223
 
224
224
  /**
225
- * Creates the `netlify env:migrate` command
225
+ * Creates the `netlify env:clone` command
226
226
  * @param {import('../base-command').BaseCommand} program
227
227
  * @returns
228
228
  */
229
- const createEnvMigrateCommand = (program) =>
229
+ const createEnvCloneCommand = (program) =>
230
230
  program
231
- .command('env:migrate')
231
+ .command('env:clone')
232
+ .alias('env:migrate')
232
233
  .option('-f, --from <from>', 'Site ID (From)')
233
234
  .requiredOption('-t, --to <to>', 'Site ID (To)')
234
- .description(`Migrate environment variables from one site to another`)
235
- .addExamples([
236
- 'netlify env:migrate --to <to-site-id>',
237
- 'netlify env:migrate --to <to-site-id> --from <from-site-id>',
238
- ])
239
- .action(envMigrate)
240
-
241
- module.exports = { createEnvMigrateCommand }
235
+ .description(`Clone environment variables from one site to another`)
236
+ .addExamples(['netlify env:clone --to <to-site-id>', 'netlify env:clone --to <to-site-id> --from <from-site-id>'])
237
+ .action(envClone)
238
+
239
+ module.exports = { createEnvCloneCommand }
@@ -1,8 +1,8 @@
1
1
  // @ts-check
2
+ const { createEnvCloneCommand } = require('./env-clone')
2
3
  const { createEnvGetCommand } = require('./env-get')
3
4
  const { createEnvImportCommand } = require('./env-import')
4
5
  const { createEnvListCommand } = require('./env-list')
5
- const { createEnvMigrateCommand } = require('./env-migrate')
6
6
  const { createEnvSetCommand } = require('./env-set')
7
7
  const { createEnvUnsetCommand } = require('./env-unset')
8
8
 
@@ -26,7 +26,7 @@ const createEnvCommand = (program) => {
26
26
  createEnvListCommand(program)
27
27
  createEnvSetCommand(program)
28
28
  createEnvUnsetCommand(program)
29
- createEnvMigrateCommand(program)
29
+ createEnvCloneCommand(program)
30
30
 
31
31
  return program
32
32
  .command('env')
@@ -37,7 +37,7 @@ const createEnvCommand = (program) => {
37
37
  'netlify env:set VAR_NAME value',
38
38
  'netlify env:unset VAR_NAME',
39
39
  'netlify env:import fileName',
40
- 'netlify env:migrate --to <to-site-id>',
40
+ 'netlify env:clone --to <to-site-id>',
41
41
  ])
42
42
  .action(env)
43
43
  }
@@ -56,9 +56,10 @@ const graphPull = async (options, command) => {
56
56
  error(`Failed to fetch and update Netlify GraphQL schema`)
57
57
  }
58
58
 
59
+ const { jwt } = await OneGraphCliClient.getGraphJwtForSite({ siteId, nfToken: netlifyToken })
59
60
  const next = await OneGraphCliClient.fetchCliSessionEvents({
60
61
  appId: siteId,
61
- authToken: netlifyToken,
62
+ jwt,
62
63
  sessionId: oneGraphSessionId,
63
64
  })
64
65
 
@@ -83,7 +84,7 @@ const graphPull = async (options, command) => {
83
84
 
84
85
  await OneGraphCliClient.ackCLISessionEvents({
85
86
  appId: siteId,
86
- authToken: netlifyToken,
87
+ jwt,
87
88
  sessionId: oneGraphSessionId,
88
89
  eventIds: ackIds,
89
90
  })
@@ -1,12 +1,11 @@
1
1
  // @ts-check
2
2
 
3
- const clone = require('git-clone/promise')
4
3
  const inquirer = require('inquirer')
5
4
  const pick = require('lodash/pick')
6
5
  const parseGitHubUrl = require('parse-github-url')
7
6
  const prettyjson = require('prettyjson')
8
7
 
9
- const { chalk, error, getRepoData, getTerminalLink, log, logJson, track, warn } = require('../../utils')
8
+ const { chalk, error, execa, getRepoData, getTerminalLink, log, logJson, track, warn } = require('../../utils')
10
9
  const { configureRepo } = require('../../utils/init/config')
11
10
  const { getGitHubToken } = require('../../utils/init/config-github')
12
11
  const { createRepo, getTemplatesFromGitHub, validateTemplate } = require('../../utils/sites/utils')
@@ -17,7 +16,7 @@ const fetchTemplates = async (token) => {
17
16
  const templatesFromGithubOrg = await getTemplatesFromGitHub(token)
18
17
 
19
18
  return templatesFromGithubOrg
20
- .filter((repo) => !repo.archived && !repo.private && !repo.disabled)
19
+ .filter((repo) => !repo.archived && !repo.disabled)
21
20
  .map((template) => ({
22
21
  name: template.name,
23
22
  sourceCodeUrl: template.html_url,
@@ -190,7 +189,7 @@ const sitesCreateTemplate = async (repository, options, command) => {
190
189
  })
191
190
  if (cloneConfirm) {
192
191
  log()
193
- await clone(repoResp.git_url, `${repoResp.name}`)
192
+ await execa('git', ['clone', repoResp.clone_url, `${repoResp.name}`])
194
193
  log(`🚀 Repository cloned successfully. You can find it under the ${chalk.magenta(repoResp.name)} folder`)
195
194
  }
196
195
 
@@ -2,4 +2,4 @@ module github.com/someone/{{name}}
2
2
 
3
3
  go 1.15
4
4
 
5
- require github.com/aws/aws-lambda-go v1.32.0
5
+ require github.com/aws/aws-lambda-go v1.32.1
@@ -48,6 +48,7 @@ const handleProxyRequest = (req, proxyReq) => {
48
48
  const initializeProxy = async ({
49
49
  config,
50
50
  configPath,
51
+ geoCountry,
51
52
  geolocationMode,
52
53
  getUpdatedConfig,
53
54
  inspectSettings,
@@ -84,7 +85,7 @@ const initializeProxy = async ({
84
85
  }
85
86
 
86
87
  const [geoLocation, registry] = await Promise.all([
87
- getGeoLocation({ mode: geolocationMode, offline, state }),
88
+ getGeoLocation({ mode: geolocationMode, geoCountry, offline, state }),
88
89
  server,
89
90
  ])
90
91
 
@@ -173,12 +173,11 @@ class FunctionsRegistry {
173
173
  }
174
174
 
175
175
  await Promise.all(directories.map((path) => FunctionsRegistry.prepareDirectoryScan(path)))
176
-
177
176
  const functions = await this.listFunctions(directories, {
178
177
  featureFlags: {
179
178
  buildRustSource: env.NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE === 'true',
180
179
  },
181
- config: this.config,
180
+ config: this.config.functions,
182
181
  })
183
182
 
184
183
  // Before registering any functions, we look for any functions that were on
@@ -1,4 +1,6 @@
1
- const ansi2html = require('ansi2html')
1
+ const AnsiToHtml = require('ansi-to-html')
2
+
3
+ const ansiToHtml = new AnsiToHtml()
2
4
 
3
5
  const { CLOCKWORK_USERAGENT } = require('../../utils')
4
6
 
@@ -11,7 +13,7 @@ const buildHelpResponse = ({ error, headers, path, result }) => {
11
13
  text = text.trim()
12
14
 
13
15
  if (acceptsHtml) {
14
- return ansi2html(`<p>${text}</p>`)
16
+ return ansiToHtml.toHtml(`<p>${text}</p>`)
15
17
  }
16
18
 
17
19
  text = text
@@ -3,7 +3,6 @@ const fetch = require('node-fetch')
3
3
 
4
4
  const API_URL = 'https://netlifind.netlify.app'
5
5
  const STATE_GEO_PROPERTY = 'geolocation'
6
-
7
6
  // 24 hours
8
7
  const CACHE_TTL = 8.64e7
9
8
 
@@ -17,12 +16,11 @@ const REQUEST_TIMEOUT = 1e4
17
16
  * @property {object} country
18
17
  * @property {string} country.code
19
18
  * @property {string} country.name
20
- * @property {object} country
21
- * @property {string} country.code
22
- * @property {string} country.name
19
+ * @property {object} subdivision
20
+ * @property {string} subdivision.code
21
+ * @property {string} subdivision.name
23
22
  */
24
23
 
25
- // The default location to be used if we're unable to talk to the API.
26
24
  const mockLocation = {
27
25
  city: 'San Francisco',
28
26
  country: { code: 'US', name: 'United States' },
@@ -34,13 +32,13 @@ const mockLocation = {
34
32
  * location, depending on the mode selected.
35
33
  *
36
34
  * @param {object} params
37
- * @param {string} params.geolocationMode
38
35
  * @param {"cache"|"update"|"mock"} params.mode
36
+ * @param {string} params.geoCountry
39
37
  * @param {boolean} params.offline
40
38
  * @param {import('../utils/state-config').StateConfig} params.state
41
39
  * @returns {Promise<GeoLocation>}
42
40
  */
43
- const getGeoLocation = async ({ mode, offline, state }) => {
41
+ const getGeoLocation = async ({ geoCountry, mode, offline, state }) => {
44
42
  const cacheObject = state.get(STATE_GEO_PROPERTY)
45
43
 
46
44
  // If we have cached geolocation data and the `--geo` option is set to
@@ -56,10 +54,18 @@ const getGeoLocation = async ({ mode, offline, state }) => {
56
54
  }
57
55
  }
58
56
 
59
- // If the `--geo` option is set to `mock`, we use the mock location. Also,
60
- // if the `--offline` option was used, we can't talk to the API, so let's
61
- // also use the mock location.
62
- if (mode === 'mock' || offline) {
57
+ // If the `--geo` option is set to `mock`, we use the default mock location.
58
+ // If the `--offline` option was used, we can't talk to the API, so let's
59
+ // also use the mock location. Otherwise, use the country code passed in by
60
+ // the user.
61
+ if (mode === 'mock' || offline || geoCountry) {
62
+ if (geoCountry) {
63
+ return {
64
+ city: 'Mock City',
65
+ country: { code: geoCountry, name: 'Mock Country' },
66
+ subdivision: { code: 'SD', name: 'Mock Subdivision' },
67
+ }
68
+ }
63
69
  return mockLocation
64
70
  }
65
71