Skip to content

Commit 4783d60

Browse files
authored
feat: support args for input (#117)
Some input processes require additional arguments. For example, password inputs depend on the `{ silent: true }`. This change passes these arguments to the related input processes while keeping compatibility with existing API (i.e. callback for `input.start`). Related to npm/cli#8322
1 parent 5e6692a commit 4783d60

File tree

4 files changed

+60
-13
lines changed

4 files changed

+60
-13
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ const { log, output, input, time } = require('proc-log')
7676

7777
#### input
7878

79-
* `input.start(fn?)` calls `process.emit('input', 'start')`
79+
* `input.start(...args)` calls `process.emit('input', 'start', ...args)`
8080

81-
Used to tell the consumer that the terminal is going to begin reading user input. Returns a function that will call `input.end()` for convenience.
81+
Used to tell the consumer that the terminal is going to begin reading user input. Returns a function that will call `input.end(...args)` for convenience.
8282

83-
This also takes an optional callback which will run `input.end()` on its completion. If the callback returns a `Promise` then `input.end()` will be run during `finally()`.
83+
If the first argument is a function, it will be used as a callback which runs `input.end()` on its completion. If the callback returns a `Promise` then `input.end(...args)` will be run during `finally()`.
8484

85-
* `input.end()` calls `process.emit('input', 'end')`
85+
* `input.end(...args)` calls `process.emit('input', 'end', ...args)`
8686

8787
Used to tell the consumer that the terminal has stopped reading user input.
8888

lib/index.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,15 @@ module.exports = {
122122
end: 'end',
123123
read: 'read',
124124
},
125-
start: function (fn) {
126-
process.emit('input', 'start')
125+
start: function (...args) {
126+
// Support callback for backwards compatibility and pass additional args to event
127+
let fn
128+
if (typeof args[0] === 'function') {
129+
fn = args.shift()
130+
}
131+
process.emit('input', 'start', ...args)
127132
function end () {
128-
return process.emit('input', 'end')
133+
return process.emit('input', 'end', ...args)
129134
}
130135
if (typeof fn === 'function') {
131136
const res = fn()
@@ -137,8 +142,8 @@ module.exports = {
137142
}
138143
return end
139144
},
140-
end: function () {
141-
return process.emit('input', 'end')
145+
end: function (...args) {
146+
return process.emit('input', 'end', ...args)
142147
},
143148
read: function (...args) {
144149
let resolve, reject

test/index.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ for (const method in procLog) {
2121
t.matchSnapshot(KEYS, `${method} keys`)
2222

2323
t.strictSame(Object.keys(KEYS), LEVELS, 'all keys are in levels')
24-
t.strictSame(Object.values(KEYS), LEVELS, 'all vales are in levels')
24+
t.strictSame(Object.values(KEYS), LEVELS, 'all values are in levels')
2525

2626
t.test(`all ${method}.LEVELS have a function in ${method}`, t => {
2727
for (const level of LEVELS) {
@@ -36,8 +36,6 @@ for (const method in procLog) {
3636
case 'time.end':
3737
t.strictSame(args, [1], 'single arg')
3838
break
39-
case 'input.start':
40-
case 'input.end':
4139
case 'log.pause':
4240
case 'log.resume':
4341
t.strictSame(args, [], 'no args')
@@ -47,7 +45,7 @@ for (const method in procLog) {
4745
t.same(args.slice(2), [1, 'two', [3], { 4: 4 }], 'got expected args')
4846
break
4947
default:
50-
t.same(args, [1, 'two', [3], { 4: 4 }], 'got expected args')
48+
t.same(args, [1, 'two', [3], { 4: 4 }], `got expected args ${method}.${level}`)
5149
}
5250

5351
t.end()

test/input.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,49 @@ t.test('start and end', t => {
7575
t.ok(called.end)
7676
})
7777

78+
t.test('sync no callback but args', t => {
79+
const called = {}
80+
const handler = (level, ...args) => {
81+
if (level === 'start') {
82+
called.start = args
83+
} else if (level === 'end') {
84+
called.end = args
85+
if (called.start && called.end) {
86+
t.strictSame(called.start, [{ silent: true }], 'start event gets silent option')
87+
t.strictSame(called.end, [{ silent: true }], 'end event gets silent option')
88+
t.end()
89+
}
90+
}
91+
}
92+
93+
process.on('input', handler)
94+
t.teardown(() => process.off('input', handler))
95+
96+
const end = input.start({ silent: true })
97+
end()
98+
})
99+
100+
t.test('async no callback but args', async t => {
101+
const called = {}
102+
const handler = (level, ...args) => {
103+
if (level === 'start') {
104+
called.start = args
105+
} else if (level === 'end') {
106+
called.end = args
107+
if (called.start && called.end) {
108+
t.strictSame(called.start, [{ silent: true }], 'start event gets silent option')
109+
t.strictSame(called.end, [{ silent: true }], 'end event gets silent option')
110+
t.end()
111+
}
112+
}
113+
}
114+
115+
process.on('input', handler)
116+
t.teardown(() => process.off('input', handler))
117+
118+
const end = await input.start({ silent: true })
119+
end()
120+
})
121+
78122
t.end()
79123
})

0 commit comments

Comments
 (0)