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.
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/src/commands/base-command.js +27 -0
- package/src/commands/dev/dev.js +31 -15
- package/src/commands/graph/graph-handler.js +2 -2
- package/src/lib/functions/registry.js +1 -2
- package/src/lib/one-graph/cli-client.js +10 -8
- package/src/utils/command-helpers.js +33 -0
- package/src/lib/functions/watcher.js +0 -35
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
|
-
"version": "9.
|
|
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.
|
|
9
|
+
"version": "9.6.0",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
package/package.json
CHANGED
|
@@ -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
|
}
|
package/src/commands/dev/dev.js
CHANGED
|
@@ -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
|
|
350
|
+
let stopWatchingCLISessions
|
|
352
351
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
352
|
+
const createOrResumeSession = async function () {
|
|
353
|
+
const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options, settings })
|
|
354
|
+
|
|
355
|
+
let graphqlDocument = readGraphQLOperationsSourceFile(netlifyGraphConfig)
|
|
356
356
|
|
|
357
|
-
|
|
357
|
+
if (!graphqlDocument || graphqlDocument.trim().length === 0) {
|
|
358
|
+
graphqlDocument = defaultExampleOperationsDoc
|
|
359
|
+
}
|
|
358
360
|
|
|
359
|
-
|
|
360
|
-
const oneGraphSessionId = loadCLISession(state)
|
|
361
|
+
stopWatchingCLISessions = await startOneGraphCLISession({ netlifyGraphConfig, netlifyToken, site, state })
|
|
361
362
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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 (!
|
|
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 }
|