netlify-cli 9.5.0 → 9.6.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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
- "version": "9.5.0",
3
+ "version": "9.6.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "netlify-cli",
9
- "version": "9.5.0",
9
+ "version": "9.6.0",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
3
  "description": "Netlify command line tool",
4
- "version": "9.5.0",
4
+ "version": "9.6.0",
5
5
  "author": "Netlify Inc.",
6
6
  "contributors": [
7
7
  "Abraham Schilling <AbrahamSchilling@gmail.com> (https://gitlab.com/n4bb12)",
@@ -1,4 +1,5 @@
1
1
  // @ts-check
2
+ const events = require('events')
2
3
  const process = require('process')
3
4
  const { format } = require('util')
4
5
 
@@ -28,6 +29,7 @@ const {
28
29
  pollForToken,
29
30
  sortOptions,
30
31
  track,
32
+ watchDebounced,
31
33
  } = require('../utils')
32
34
 
33
35
  // Netlify CLI client id. Lives in bot@netlify.com
@@ -119,6 +121,11 @@ class BaseCommand extends Command {
119
121
  await this.init(actionCommand)
120
122
  debug(`${name}:preAction`)('end')
121
123
  })
124
+ .hook('postAction', async () => {
125
+ if (this.configWatcherHandle) {
126
+ await this.configWatcherHandle.close()
127
+ }
128
+ })
122
129
  )
123
130
  }
124
131
 
@@ -430,6 +437,24 @@ class BaseCommand extends Command {
430
437
  const globalConfig = await getGlobalConfig()
431
438
  const { NetlifyAPI } = await jsClient
432
439
 
440
+ const configWatcher = new events.EventEmitter()
441
+
442
+ // Only set up a watcher if we know the config path.
443
+ if (configPath) {
444
+ const configWatcherHandle = await watchDebounced(configPath, {
445
+ depth: 1,
446
+ onChange: async () => {
447
+ const { config: newConfig } = await actionCommand.getConfig({ cwd, state, token, ...apiUrlOpts })
448
+
449
+ const normalizedNewConfig = normalizeConfig(newConfig)
450
+ configWatcher.emit('change', normalizedNewConfig)
451
+ },
452
+ })
453
+
454
+ // chokidar handler
455
+ this.configWatcherHandle = configWatcherHandle
456
+ }
457
+
433
458
  actionCommand.netlify = {
434
459
  // api methods
435
460
  api: new NetlifyAPI(token || '', apiOpts),
@@ -455,6 +480,8 @@ class BaseCommand extends Command {
455
480
  globalConfig,
456
481
  // state of current site dir
457
482
  state,
483
+ // netlify.toml file watcher
484
+ configWatcher,
458
485
  }
459
486
  debug(`${this.name()}:init`)('end')
460
487
  }
@@ -346,28 +346,44 @@ const dev = async (options, command) => {
346
346
  } else if (startNetlifyGraphWatcher) {
347
347
  const netlifyToken = await command.authenticate()
348
348
  await OneGraphCliClient.ensureAppForSite(netlifyToken, site.id)
349
- const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options, settings })
350
349
 
351
- let graphqlDocument = readGraphQLOperationsSourceFile(netlifyGraphConfig)
350
+ let stopWatchingCLISessions
352
351
 
353
- if (!graphqlDocument || graphqlDocument.trim().length === 0) {
354
- graphqlDocument = defaultExampleOperationsDoc
355
- }
352
+ const createOrResumeSession = async function () {
353
+ const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options, settings })
354
+
355
+ let graphqlDocument = readGraphQLOperationsSourceFile(netlifyGraphConfig)
356
356
 
357
- await startOneGraphCLISession({ netlifyGraphConfig, netlifyToken, site, state })
357
+ if (!graphqlDocument || graphqlDocument.trim().length === 0) {
358
+ graphqlDocument = defaultExampleOperationsDoc
359
+ }
358
360
 
359
- // Should be created by startOneGraphCLISession
360
- const oneGraphSessionId = loadCLISession(state)
361
+ stopWatchingCLISessions = await startOneGraphCLISession({ netlifyGraphConfig, netlifyToken, site, state })
361
362
 
362
- await persistNewOperationsDocForSession({
363
- netlifyGraphConfig,
364
- netlifyToken,
365
- oneGraphSessionId,
366
- operationsDoc: graphqlDocument,
367
- siteId: site.id,
368
- siteRoot: site.root,
363
+ // Should be created by startOneGraphCLISession
364
+ const oneGraphSessionId = loadCLISession(state)
365
+
366
+ await persistNewOperationsDocForSession({
367
+ netlifyGraphConfig,
368
+ netlifyToken,
369
+ oneGraphSessionId,
370
+ operationsDoc: graphqlDocument,
371
+ siteId: site.id,
372
+ siteRoot: site.root,
373
+ })
374
+
375
+ return oneGraphSessionId
376
+ }
377
+
378
+ //
379
+ // Set up a handler for config changes.
380
+ command.netlify.configWatcher.on('change', (newConfig) => {
381
+ command.netlify.config = newConfig
382
+ stopWatchingCLISessions()
383
+ createOrResumeSession()
369
384
  })
370
385
 
386
+ const oneGraphSessionId = await createOrResumeSession()
371
387
  const cleanupSession = () => markCliSessionInactive({ netlifyToken, sessionId: oneGraphSessionId, siteId: site.id })
372
388
 
373
389
  cleanupWork.push(cleanupSession)
@@ -39,8 +39,8 @@ const graphHandler = async (userOperationName, options, command) => {
39
39
  error(`Failed to parse Netlify GraphQL schema`)
40
40
  }
41
41
 
42
- let operationName
43
- if (!userOperationName) {
42
+ let operationName = userOperationName
43
+ if (!operationName) {
44
44
  try {
45
45
  let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
46
46
  if (currentOperationsDoc.trim().length === 0) {
@@ -5,12 +5,11 @@ const { env } = require('process')
5
5
 
6
6
  const terminalLink = require('terminal-link')
7
7
 
8
- const { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, log, warn } = require('../../utils')
8
+ const { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, log, warn, watchDebounced } = require('../../utils')
9
9
  const { getLogMessage } = require('../log')
10
10
 
11
11
  const { NetlifyFunction } = require('./netlify-function')
12
12
  const runtimes = require('./runtimes')
13
- const { watchDebounced } = require('./watcher')
14
13
 
15
14
  const ZIP_EXTENSION = '.zip'
16
15
 
@@ -10,8 +10,7 @@ const { GraphQL, InternalConsole, OneGraphClient } = require('netlify-onegraph-i
10
10
  const { NetlifyGraph } = require('netlify-onegraph-internal')
11
11
 
12
12
  // eslint-disable-next-line no-unused-vars
13
- const { StateConfig, USER_AGENT, chalk, error, log, warn } = require('../../utils')
14
- const { watchDebounced } = require('../functions/watcher')
13
+ const { StateConfig, USER_AGENT, chalk, error, log, warn, watchDebounced } = require('../../utils')
15
14
 
16
15
  const {
17
16
  generateFunctionsFile,
@@ -114,7 +113,7 @@ const monitorCLISessionEvents = (input) => {
114
113
  const helper = async () => {
115
114
  if (shouldClose) {
116
115
  clearTimeout(handle)
117
- onClose()
116
+ onClose && onClose()
118
117
  }
119
118
 
120
119
  const next = await OneGraphClient.fetchCliSessionEvents({ appId, authToken: netlifyToken, sessionId })
@@ -465,7 +464,7 @@ const startOneGraphCLISession = async (input) => {
465
464
  const enabledServices = []
466
465
  const schema = await OneGraphClient.fetchOneGraphSchema(site.id, enabledServices)
467
466
 
468
- monitorOperationFile({
467
+ const opsFileWatcher = monitorOperationFile({
469
468
  netlifyGraphConfig,
470
469
  onChange: async (filePath) => {
471
470
  log('NetlifyGraph operation file changed at', filePath, 'updating function library...')
@@ -495,7 +494,7 @@ const startOneGraphCLISession = async (input) => {
495
494
  },
496
495
  })
497
496
 
498
- monitorCLISessionEvents({
497
+ const cliEventsCloseFn = monitorCLISessionEvents({
499
498
  appId: site.id,
500
499
  netlifyToken,
501
500
  netlifyGraphConfig,
@@ -514,10 +513,13 @@ const startOneGraphCLISession = async (input) => {
514
513
  onError: (fetchEventError) => {
515
514
  error(`Netlify Graph upstream error: ${fetchEventError}`)
516
515
  },
517
- onClose: () => {
518
- log('Netlify Graph upstream closed')
519
- },
520
516
  })
517
+
518
+ return async function unregisterWatchers() {
519
+ const watcher = await opsFileWatcher
520
+ watcher.close()
521
+ cliEventsCloseFn()
522
+ }
521
523
  }
522
524
 
523
525
  /**
@@ -4,8 +4,12 @@ const process = require('process')
4
4
  const { format, inspect } = require('util')
5
5
 
6
6
  const { Instance: ChalkInstance } = require('chalk')
7
+ const chokidar = require('chokidar')
8
+ const decache = require('decache')
7
9
  const WSL = require('is-wsl')
10
+ const debounce = require('lodash/debounce')
8
11
  const { default: omit } = require('omit.js')
12
+ const pEvent = require('p-event')
9
13
 
10
14
  const { name, version } = require('../../package.json')
11
15
  const { clearSpinner, startSpinner } = require('../lib/spinner')
@@ -198,6 +202,34 @@ const normalizeConfig = (config) =>
198
202
  ? { ...config, build: omit(config.build, ['publish', 'publishOrigin']) }
199
203
  : config
200
204
 
205
+ const DEBOUNCE_WAIT = 100
206
+
207
+ const watchDebounced = async (target, { depth, onAdd = () => {}, onChange = () => {}, onUnlink = () => {} }) => {
208
+ const watcher = chokidar.watch(target, { depth, ignored: /node_modules/, ignoreInitial: true })
209
+
210
+ await pEvent(watcher, 'ready')
211
+
212
+ const debouncedOnChange = debounce(onChange, DEBOUNCE_WAIT)
213
+ const debouncedOnUnlink = debounce(onUnlink, DEBOUNCE_WAIT)
214
+ const debouncedOnAdd = debounce(onAdd, DEBOUNCE_WAIT)
215
+
216
+ watcher
217
+ .on('change', (path) => {
218
+ decache(path)
219
+ debouncedOnChange(path)
220
+ })
221
+ .on('unlink', (path) => {
222
+ decache(path)
223
+ debouncedOnUnlink(path)
224
+ })
225
+ .on('add', (path) => {
226
+ decache(path)
227
+ debouncedOnAdd(path)
228
+ })
229
+
230
+ return watcher
231
+ }
232
+
201
233
  module.exports = {
202
234
  BANG,
203
235
  chalk,
@@ -217,4 +249,5 @@ module.exports = {
217
249
  sortOptions,
218
250
  USER_AGENT,
219
251
  warn,
252
+ watchDebounced,
220
253
  }
@@ -1,35 +0,0 @@
1
- // @ts-check
2
- const chokidar = require('chokidar')
3
- const decache = require('decache')
4
- const debounce = require('lodash/debounce')
5
- const pEvent = require('p-event')
6
-
7
- const DEBOUNCE_WAIT = 100
8
-
9
- const watchDebounced = async (target, { depth, onAdd = () => {}, onChange = () => {}, onUnlink = () => {} }) => {
10
- const watcher = chokidar.watch(target, { depth, ignored: /node_modules/, ignoreInitial: true })
11
-
12
- await pEvent(watcher, 'ready')
13
-
14
- const debouncedOnChange = debounce(onChange, DEBOUNCE_WAIT)
15
- const debouncedOnUnlink = debounce(onUnlink, DEBOUNCE_WAIT)
16
- const debouncedOnAdd = debounce(onAdd, DEBOUNCE_WAIT)
17
-
18
- watcher
19
- .on('change', (path) => {
20
- decache(path)
21
- debouncedOnChange(path)
22
- })
23
- .on('unlink', (path) => {
24
- decache(path)
25
- debouncedOnUnlink(path)
26
- })
27
- .on('add', (path) => {
28
- decache(path)
29
- debouncedOnAdd(path)
30
- })
31
-
32
- return watcher
33
- }
34
-
35
- module.exports = { watchDebounced }