index.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. 'use strict';
  2. const path = require('path');
  3. const childProcess = require('child_process');
  4. const isWsl = require('is-wsl');
  5. module.exports = (target, opts) => {
  6. if (typeof target !== 'string') {
  7. return Promise.reject(new Error('Expected a `target`'));
  8. }
  9. opts = Object.assign({wait: true}, opts);
  10. let cmd;
  11. let appArgs = [];
  12. let args = [];
  13. const cpOpts = {};
  14. if (Array.isArray(opts.app)) {
  15. appArgs = opts.app.slice(1);
  16. opts.app = opts.app[0];
  17. }
  18. if (process.platform === 'darwin') {
  19. cmd = 'open';
  20. if (opts.wait) {
  21. args.push('-W');
  22. }
  23. if (opts.app) {
  24. args.push('-a', opts.app);
  25. }
  26. } else if (process.platform === 'win32' || isWsl) {
  27. cmd = 'cmd' + (isWsl ? '.exe' : '');
  28. args.push('/c', 'start', '""', '/b');
  29. target = target.replace(/&/g, '^&');
  30. if (opts.wait) {
  31. args.push('/wait');
  32. }
  33. if (opts.app) {
  34. args.push(opts.app);
  35. }
  36. if (appArgs.length > 0) {
  37. args = args.concat(appArgs);
  38. }
  39. } else {
  40. if (opts.app) {
  41. cmd = opts.app;
  42. } else {
  43. const useSystemXdgOpen = process.versions.electron || process.platform === 'android';
  44. cmd = useSystemXdgOpen ? 'xdg-open' : path.join(__dirname, 'xdg-open');
  45. }
  46. if (appArgs.length > 0) {
  47. args = args.concat(appArgs);
  48. }
  49. if (!opts.wait) {
  50. // `xdg-open` will block the process unless
  51. // stdio is ignored and it's detached from the parent
  52. // even if it's unref'd
  53. cpOpts.stdio = 'ignore';
  54. cpOpts.detached = true;
  55. }
  56. }
  57. args.push(target);
  58. if (process.platform === 'darwin' && appArgs.length > 0) {
  59. args.push('--args');
  60. args = args.concat(appArgs);
  61. }
  62. const cp = childProcess.spawn(cmd, args, cpOpts);
  63. if (opts.wait) {
  64. return new Promise((resolve, reject) => {
  65. cp.once('error', reject);
  66. cp.once('close', code => {
  67. if (code > 0) {
  68. reject(new Error('Exited with code ' + code));
  69. return;
  70. }
  71. resolve(cp);
  72. });
  73. });
  74. }
  75. cp.unref();
  76. return Promise.resolve(cp);
  77. };