Skip to content

Commit 628615a

Browse files
Updating Docs and adding two new optional params to the watch command.
1 parent 23f88fd commit 628615a

File tree

12 files changed

+268
-63
lines changed

12 files changed

+268
-63
lines changed

bin/cli.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@ const argv = yargs
4141
.command('list', 'List Configured SFCC Clients')
4242
.command('delete <client> [instance]', 'Delete Config for Client')
4343
.command('watch [client] [instance]', 'Watch for Changes and Push Updates', {
44-
spinner: {
45-
describe: 'Show the watch spinner',
46-
default: true
44+
log: {
45+
describe: 'Pipe Output to Log File ~/.sffc-cli.log',
46+
default: false
47+
},
48+
'errors-only': {
49+
describe: 'Only Show Notification for Errors',
50+
default: false
4751
}
4852
})
4953
.example('$0 delete my-client sandbox', 'Delete my-client sandbox config')
@@ -56,7 +60,7 @@ const command = argv._[0]
5660

5761
try {
5862
debug(`Executing ${command}`)
59-
require(path.join(__dirname, `../commands/${command}.js`))()
63+
require(path.join(__dirname, `../commands/${command}.js`))(argv)
6064
} catch (err) {
6165
if (err.code === 'MODULE_NOT_FOUND') {
6266
console.log(chalk.red.bold(`\n✖ Command 'sfcc ${command}' not recognized\n`))

commands/watch.js

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
const argv = require('minimist')(process.argv.slice(2))
22
const chalk = require('chalk')
33
const chokidar = require('chokidar')
4-
const debounce = require('lodash/debounce')
5-
const notifier = require('node-notifier')
64
const ora = require('ora')
75
const path = require('path')
86

7+
const logger = require('../lib/logger')()
8+
const notify = require('../lib/notify')()
99
const config = require('../lib/config')()
1010
const upload = require('../lib/upload')
1111

12-
module.exports = async () => {
12+
module.exports = options => {
1313
let client = argv['_'][1] || null
1414
let instance = argv['_'][2] || null
1515
let watching = null
16+
let errorMessage
17+
let logMessage
18+
19+
const useLog = options.log
20+
const errorsOnly = options.errorsOnly
1621

1722
if (client && instance) {
1823
watching = config.get(client, instance)
@@ -27,42 +32,74 @@ module.exports = async () => {
2732
}
2833

2934
if (watching) {
30-
const debouncedNotify = debounce(args => notifier.notify(args), 150)
35+
let spinner
3136
const watcher = chokidar.watch('dir', {
3237
ignored: [/[/\\]\./, '**/node_modules/**'],
3338
ignoreInitial: true,
3439
persistent: true,
40+
awaitWriteFinish: true,
3541
atomic: true
3642
})
3743

38-
let text = `Watching ${client} ${instance} [Ctrl-C to Cancel]`
39-
let spinner = ora(text).start()
40-
4144
// Add Instance Directory to Watch List
4245
watcher.add(watching.d)
4346

4447
// Watch for File Changes
4548
watcher.on('change', file => {
46-
upload({file, spinner, watching, client, instance})
49+
upload({file, spinner, watching, client, instance, options})
4750
})
4851
watcher.on('add', file => {
49-
upload({file, spinner, watching, client, instance})
52+
upload({file, spinner, watching, client, instance, options})
5053
})
5154

52-
// Watch for Removing Files
53-
watcher.on('unlink', upload)
55+
// @TODO: Watch for Removing Files
56+
watcher.on('unlink', file => {
57+
console.log('UNLINK', file)
58+
})
5459

5560
// Watch for Errors
56-
watcher.on('error', upload)
61+
watcher.on('error', error => {
62+
notify({
63+
title: `${client} ${instance}`,
64+
icon: path.join(__dirname, '../icons/', 'sfcc-error.png'),
65+
subtitle: 'WATCH FAILED',
66+
message: error,
67+
sound: true,
68+
wait: true
69+
})
5770

58-
debouncedNotify({
59-
title: `${client} ${instance}`,
60-
icon: path.join(__dirname, '../icons/', 'sfcc-cli.png'),
61-
subtitle: 'STARTING WATCHER',
62-
message: 'Waiting for Changes ...'
71+
errorMessage = `✖ Watch Error for '${client}' '${instance}': ${error}.`
72+
if (useLog) {
73+
logger.log(errorMessage)
74+
} else {
75+
console.log(chalk.red.bold(`\n${errorMessage}`))
76+
}
77+
})
78+
79+
watcher.on('ready', () => {
80+
if (!errorsOnly) {
81+
notify({
82+
title: `${client} ${instance}`,
83+
icon: path.join(__dirname, '../icons/', 'sfcc-cli.png'),
84+
subtitle: 'STARTING WATCHER',
85+
message: 'Waiting for Changes ...'
86+
})
87+
}
88+
89+
logMessage = `Watching ${client} ${instance}`
90+
if (useLog) {
91+
logger.log(logMessage, true)
92+
} else {
93+
spinner = ora(`${logMessage} [Ctrl-C to Cancel]`).start()
94+
}
6395
})
6496
} else if (client && instance) {
65-
console.log(chalk.red(`\n× Config does not contain client '${client}' with instance '${instance}'.`))
66-
console.log('Use ' + chalk.cyan('sfcc setup') + ' to get started.\n')
97+
errorMessage = `✖ Config does not contain client '${client}' with instance '${instance}'.`
98+
if (useLog) {
99+
logger.log(errorMessage)
100+
} else {
101+
console.log(chalk.red.bold(`\n${errorMessage}`))
102+
console.log('Use ' + chalk.cyan('sfcc setup') + ' to get started.\n')
103+
}
67104
}
68105
}

docs/usage.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
**[↤ Developer Overview](../README.md)**
44

55
Usage
6-
---
6+
===
77

88
> Here is how SFCC CLI can help you with you local development
99
10-
### Watch
10+
`sfcc watch`
11+
---
1112

1213
Watch for any changes to your projects source code, and automagically upload in the background, while you use whatever IDE you want.
1314

@@ -23,32 +24,51 @@ If needed to setup multiple clients, or multiple instances for the same client,
2324
sfcc watch <client> <instance>
2425
```
2526

26-
### List
27+
If you don't want to get notified of every upload, but would rather only get notified about errors, you can pass `--errors-only`:
28+
29+
```bash
30+
sfcc watch <client> <instance> --errors-only
31+
```
32+
33+
If you would like to run the watcher as a background process, but capture the log output, you can pass `--log`, and a log will be created at `~/.sfcc-cli.log` ( log is truncated to last 500 lines each time you start a new `watch` ):
34+
35+
```bash
36+
sfcc watch <client> <instance> --log &
37+
```
38+
39+
NOTE: To run the background process, you'll need to make sure to add a `&` to the end of the command. You should see output from that command that looks like `[2] 6768`. You can bring the process to the foreground by running using the number in the brackets, and running a command like `fg %2`. You can get a list of all jobs running in the background by running `jobs`.
40+
41+
`sfcc list`
42+
---
2743

2844
To get a list of your current clients & instances, you can run:
2945

3046
```bash
3147
sfcc list
3248
```
3349

34-
### Delete
3550

36-
To delete a configuration option, you can pass in a client and instance you want to delete. Or just delete everything for that clients:
51+
`sfcc delete`
52+
---
53+
54+
To delete a configuration option, you can pass in a client and instance you want to delete. Or just delete everything for that client:
3755

3856
```bash
3957
sfcc delete <client> <instance>
4058
sfcc delete <client>
4159
```
4260

43-
### Help
61+
62+
`sfcc help`
63+
---
4464

4565
You can get help at any time by running:
4666

4767
```bash
4868
sfcc help
4969
```
5070

51-
You can get help on a specific command by just added `help` to the end of the command:
71+
You can get help on a specific command by just adding `help` to the end of the command:
5272

5373
```bash
5474
sfcc watch help

icons/sfcc-cli.png

100644100755
-1.44 KB
Loading

icons/sfcc-error.png

100644100755
-1.6 KB
Loading

icons/sfcc-success.png

100644100755
-1.68 KB
Loading

icons/sfcc-uploading.png

100644100755
-1.44 KB
Loading

lib/logger.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const fs = require('fs-extra')
2+
const homedir = require('os').homedir()
3+
const path = require('path')
4+
const truncate = require('truncate-logs')
5+
6+
module.exports = () => {
7+
const logFile = path.join(homedir, '.sfcc-cli.log')
8+
9+
fs.ensureFileSync(logFile)
10+
11+
const createMessage = message => {
12+
return new Date().toLocaleString('en-US', {hour12: false}).replace(', ', '-') + ': ' + message + '\n'
13+
}
14+
15+
const log = (message, start) => {
16+
// Starting a new Watch, let's clean out some old junk to keep log file down
17+
if (start) {
18+
truncate([logFile], {lines: 500})
19+
}
20+
21+
fs.appendFile(logFile, createMessage(message), function(err) {
22+
if (err) throw err
23+
})
24+
}
25+
26+
return {
27+
log
28+
}
29+
}

lib/notify.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const debounce = require('lodash/debounce')
2+
const notifier = require('node-notifier')
3+
4+
module.exports = () => {
5+
return debounce(args => notifier.notify(args), 150)
6+
}

lib/upload.js

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,43 @@
1-
const debounce = require('lodash/debounce')
2-
const notifier = require('node-notifier')
31
const path = require('path')
42
const pRetry = require('p-retry')
53

4+
const logger = require('../lib/logger')()
5+
const notify = require('../lib/notify')()
66
const write = require('./write')
77
const mkdirp = require('./mkdirp')
88

9-
module.exports = async ({file, spinner, watching, client, instance}) => {
9+
module.exports = async ({file, spinner, watching, client, instance, options}) => {
1010
const src = path.relative(process.cwd(), file)
11-
const debouncedNotify = debounce(args => notifier.notify(args), 150)
1211
const uploading = new Set()
1312

13+
const useLog = options.log
14+
const errorsOnly = options.errorsOnly
15+
1416
if (!uploading.has(src)) {
1517
const dir = path.dirname(file).replace(path.normalize(watching.d), '')
1618
const dest = path.join('/', 'Cartridges', watching.v, dir)
19+
const text = `Watching ${client} ${instance} [Ctrl-C to Cancel]`
1720

1821
uploading.add(src)
1922

20-
debouncedNotify({
21-
title: `${client} ${instance}`,
22-
icon: path.join(__dirname, '../icons/', 'sfcc-uploading.png'),
23-
subtitle: 'UPLOADING ...',
24-
message: `${path.basename(src)} => ${dest}`
25-
})
23+
if (!errorsOnly) {
24+
notify({
25+
title: `${client} ${instance}`,
26+
icon: path.join(__dirname, '../icons/', 'sfcc-uploading.png'),
27+
subtitle: 'UPLOADING ...',
28+
message: `${path.basename(src)} => ${dest}`
29+
})
30+
}
2631

27-
let text = `Watching ${client} ${instance} [Ctrl-C to Cancel]`
32+
let logMessage = `Uploading ${file.replace(watching.d, '.')} ...`
2833

29-
spinner.stopAndPersist({
30-
text: `Uploading ${file.replace(watching.d, '.')} ...`
31-
})
32-
spinner.text = text
33-
spinner.start()
34+
if (useLog) {
35+
logger.log(logMessage)
36+
} else {
37+
spinner.stopAndPersist({text: logMessage})
38+
spinner.text = text
39+
spinner.start()
40+
}
3441

3542
try {
3643
const request = {
@@ -47,25 +54,37 @@ module.exports = async ({file, spinner, watching, client, instance}) => {
4754
await pRetry(tryToMkdir, {retries: 5})
4855
await pRetry(tryToWrite, {retries: 5})
4956

50-
debouncedNotify({
51-
title: `${client} ${instance}`,
52-
icon: path.join(__dirname, '../icons/', 'sfcc-success.png'),
53-
subtitle: 'UPLOAD COMPLETE',
54-
message: `${path.basename(src)} => ${dest}`
55-
})
57+
if (!errorsOnly) {
58+
notify({
59+
title: `${client} ${instance}`,
60+
icon: path.join(__dirname, '../icons/', 'sfcc-success.png'),
61+
subtitle: 'UPLOAD COMPLETE',
62+
message: `${path.basename(src)} => ${dest}`
63+
})
64+
}
5665

57-
spinner.text = `${path.basename(src)} pushed to ${client} ${instance}`
58-
spinner.succeed()
66+
logMessage = `${path.basename(src)} pushed to ${client} ${instance}`
5967

60-
setTimeout(() => {
61-
spinner.text = text
62-
spinner.start()
63-
}, 3000)
68+
if (useLog) {
69+
logger.log(logMessage)
70+
} else {
71+
spinner.text = logMessage
72+
spinner.succeed()
73+
74+
setTimeout(() => {
75+
spinner.text = text
76+
spinner.start()
77+
}, 3000)
78+
}
6479
} catch (err) {
65-
spinner.text = err.message
66-
spinner.fail()
80+
if (useLog) {
81+
logger.log('✖ ' + err.message)
82+
} else {
83+
spinner.text = err.message
84+
spinner.fail()
85+
}
6786

68-
debouncedNotify({
87+
notify({
6988
title: `${client} ${instance}`,
7089
icon: path.join(__dirname, '../icons/', 'sfcc-error.png'),
7190
subtitle: 'UPLOAD FAILED',

0 commit comments

Comments
 (0)