index.js 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import process from 'node:process';
  2. const ASCII_ETX_CODE = 0x03; // Ctrl+C emits this code
  3. class StdinDiscarder {
  4. #activeCount = 0;
  5. start() {
  6. this.#activeCount++;
  7. if (this.#activeCount === 1) {
  8. this.#realStart();
  9. }
  10. }
  11. stop() {
  12. if (this.#activeCount <= 0) {
  13. throw new Error('`stop` called more times than `start`');
  14. }
  15. this.#activeCount--;
  16. if (this.#activeCount === 0) {
  17. this.#realStop();
  18. }
  19. }
  20. #realStart() {
  21. // No known way to make it work reliably on Windows.
  22. if (process.platform === 'win32' || !process.stdin.isTTY) {
  23. return;
  24. }
  25. process.stdin.setRawMode(true);
  26. process.stdin.on('data', this.#handleInput);
  27. process.stdin.resume();
  28. }
  29. #realStop() {
  30. if (!process.stdin.isTTY) {
  31. return;
  32. }
  33. process.stdin.off('data', this.#handleInput);
  34. process.stdin.pause();
  35. process.stdin.setRawMode(false);
  36. }
  37. #handleInput(chunk) {
  38. // Allow Ctrl+C to gracefully exit.
  39. if (chunk[0] === ASCII_ETX_CODE) {
  40. process.emit('SIGINT');
  41. }
  42. }
  43. }
  44. const stdinDiscarder = new StdinDiscarder();
  45. export default stdinDiscarder;