DevWatcherService.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. const BaseService = require("./BaseService");
  2. class ProxyLogger {
  3. constructor (log) {
  4. this.log = log;
  5. }
  6. attach (stream) {
  7. let buffer = '';
  8. stream.on('data', (chunk) => {
  9. buffer += chunk.toString();
  10. let lineEndIndex = buffer.indexOf('\n');
  11. while (lineEndIndex !== -1) {
  12. const line = buffer.substring(0, lineEndIndex);
  13. this.log(line);
  14. buffer = buffer.substring(lineEndIndex + 1);
  15. lineEndIndex = buffer.indexOf('\n');
  16. }
  17. });
  18. stream.on('end', () => {
  19. if (buffer.length) {
  20. this.log(buffer);
  21. }
  22. });
  23. }
  24. }
  25. /**
  26. * @description
  27. * This service is used to run webpack watchers.
  28. */
  29. class DevWatcherService extends BaseService {
  30. static MODULES = {
  31. path: require('path'),
  32. spawn: require('child_process').spawn,
  33. };
  34. _construct () {
  35. this.instances = [];
  36. }
  37. async _init (args) {
  38. const { root, commands } = args;
  39. process.on('exit', () => {
  40. this.exit_all_();
  41. })
  42. for ( const entry of commands ) {
  43. const { directory } = entry;
  44. const fullpath = this.modules.path.join(
  45. root, directory);
  46. this.start_({ ...entry, fullpath });
  47. }
  48. }
  49. log_ (name, isErr, line) {
  50. let txt = `[${name}:`;
  51. txt += isErr
  52. ? `\x1B[31;1merr\x1B[0m`
  53. : `\x1B[32;1mout\x1B[0m`;
  54. txt += '] ' + line;
  55. this.log.info(txt);
  56. }
  57. async start_ ({ name, fullpath, command, args, env }) {
  58. this.log.info(`Starting ${name} in ${fullpath}`);
  59. const proc = this.modules.spawn(command, args, {
  60. shell: true,
  61. env: {
  62. ...process.env,
  63. ...(env ?? {}),
  64. },
  65. cwd: fullpath,
  66. });
  67. this.instances.push({
  68. name, proc,
  69. });
  70. const out = new ProxyLogger((line) => this.log_(name, false, line));
  71. out.attach(proc.stdout);
  72. const err = new ProxyLogger((line) => this.log_(name, true, line));
  73. err.attach(proc.stderr);
  74. proc.on('exit', () => {
  75. this.log.info(`[${name}:exit] Process exited (${proc.exitCode})`);
  76. this.instances = this.instances.filter((inst) => inst.proc !== proc);
  77. })
  78. }
  79. async exit_all_ () {
  80. for ( const { proc } of this.instances ) {
  81. proc.kill();
  82. }
  83. }
  84. };
  85. module.exports = DevWatcherService;