Repository: electron-userland/electron-forge
Pull request #268 (2017-07-21 00:28:58)

feat(starter): add easy way to inspect electron main process from forge
<!--
Thanks for filing a pull request!
Please check off all of the steps as they are completed by replacing [ ] with [x].
-->

* [x] I have read the [contribution documentation](https://github.com/electron-userland/electron-forge/blob/master/CONTRIBUTING.md) for this project.
* [x] I agree to follow the [code of conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project follows, as appropriate.
* [x] The changes are appropriately documented (if applicable).
* [x] The changes have sufficient test coverage (if applicable).
* [x] The testsuite passes successfully on my local machine (if applicable).

**Summarize your changes:**

Adds a new `--inspect-electron` arg to start to launch electron in inspect mode 😄 


Patch:
diff --git a/README.md b/README.md
index 7626be7a3..23e634f51 100644
--- a/README.md
+++ b/README.md
@@ -61,7 +61,7 @@ install the `airbnb` linting modules.  If you want to follow the `standard`
 linting rules instead, use the `--lintstyle=standard` argument.
 
 You can also start a project with your
-[favorite framework](https://beta.electronforge.io/templates) with the `--template`
+[favorite framework](https://electronforge.io/templates) with the `--template`
 argument.  E.g. `--template=react`.
 
 ## Importing an existing Project
diff --git a/src/api/start.js b/src/api/start.js
index e90fdb579..362622ae3 100644
--- a/src/api/start.js
+++ b/src/api/start.js
@@ -26,13 +26,14 @@ import runHook from '../util/hook';
  */
 export default async (providedOptions = {}) => {
   // eslint-disable-next-line prefer-const, no-unused-vars
-  let { dir, interactive, enableLogging, appPath, args, runAsNode } = Object.assign({
+  let { dir, interactive, enableLogging, appPath, args, runAsNode, inspect } = Object.assign({
     dir: process.cwd(),
     appPath: '.',
     interactive: false,
     enableLogging: false,
     args: [],
     runAsNode: false,
+    inspect: false,
   }, providedOptions);
   asyncOra.interactive = interactive;
 
@@ -62,6 +63,10 @@ export default async (providedOptions = {}) => {
     delete spawnOpts.env.ELECTRON_RUN_AS_NODE;
   }
 
+  if (inspect) {
+    args = ['--inspect'].concat(args);
+  }
+
   let spawned;
 
   const forgeConfig = await getForgeConfig(dir);
diff --git a/src/electron-forge-start.js b/src/electron-forge-start.js
index 1c0e16f93..237b82dbc 100644
--- a/src/electron-forge-start.js
+++ b/src/electron-forge-start.js
@@ -23,6 +23,7 @@ import { start } from './api';
     .option('-l, --enable-logging', 'Enable advanced logging.  This will log internal Electron things')
     .option('-n, --run-as-node', 'Run the Electron app as a Node.JS script')
     .option('--vscode', 'Used to enable arg transformation for debugging Electron through VSCode.  Do not use yourself.')
+    .option('-i, --inspect-electron', 'Triggers inspect mode on Electron to allow debugging the main process.  Electron >1.7 only')
     .action((cwd) => {
       if (!cwd) return;
       if (path.isAbsolute(cwd) && fs.existsSync(cwd)) {
@@ -46,6 +47,7 @@ import { start } from './api';
     interactive: true,
     enableLogging: !!program.enableLogging,
     runAsNode: !!program.runAsNode,
+    inspect: !!program.inspectElectron,
   };
 
   if (program.vscode && appArgs) {
diff --git a/src/init/init-starter-files.js b/src/init/init-starter-files.js
index cffc29e9d..3bd4d88f4 100644
--- a/src/init/init-starter-files.js
+++ b/src/init/init-starter-files.js
@@ -6,23 +6,10 @@ import asyncOra from '../util/ora-handler';
 
 const d = debug('electron-forge:init:starter-files');
 
-export const copy = (source, target) =>
-  new Promise((resolve, reject) => {
-    d(`copying "${source}" --> "${target}"`);
-    let rd;
-    let wr;
-    const rejectCleanup = (err) => {
-      rd.destroy();
-      wr.end();
-      reject(err);
-    };
-    rd = fs.createReadStream(source);
-    rd.on('error', rejectCleanup);
-    wr = fs.createWriteStream(target);
-    wr.on('error', rejectCleanup);
-    wr.on('finish', resolve);
-    rd.pipe(wr);
-  });
+export const copy = async (source, target) => {
+  d(`copying "${source}" --> "${target}"`);
+  await fs.copy(source, target);
+};
 
 export default async (dir, lintStyle) => {
   await asyncOra('Copying Starter Files', async () => {
@@ -34,11 +21,11 @@ export default async (dir, lintStyle) => {
     if (lintStyle === 'airbnb') rootFiles.push('_eslintrc');
     const srcFiles = ['index.js', 'index.html'];
 
-    rootFiles.forEach(async (file) => {
+    for (const file of rootFiles) {
       await copy(path.resolve(tmplPath, file), path.resolve(dir, file.replace(/^_/, '.')));
-    });
-    srcFiles.forEach(async (file) => {
+    }
+    for (const file of srcFiles) {
       await copy(path.resolve(tmplPath, file), path.resolve(dir, 'src', file));
-    });
+    }
   });
 };


Test patch:
diff --git a/test/fast/electron_forge_start_spec.js b/test/fast/electron_forge_start_spec.js
index e5687da99..83c2a7725 100644
--- a/test/fast/electron_forge_start_spec.js
+++ b/test/fast/electron_forge_start_spec.js
@@ -44,6 +44,7 @@ describe('electron-forge start', () => {
       interactive: true,
       enableLogging: false,
       runAsNode: false,
+      inspect: false,
     });
   });
 
@@ -55,6 +56,7 @@ describe('electron-forge start', () => {
       interactive: true,
       enableLogging: false,
       runAsNode: false,
+      inspect: false,
     });
   });
 
@@ -66,6 +68,7 @@ describe('electron-forge start', () => {
       interactive: true,
       enableLogging: false,
       runAsNode: false,
+      inspect: false,
     });
   });
 
@@ -78,6 +81,7 @@ describe('electron-forge start', () => {
       interactive: true,
       enableLogging: false,
       runAsNode: false,
+      inspect: false,
     });
   });
 
@@ -89,6 +93,7 @@ describe('electron-forge start', () => {
       enableLogging: true,
       interactive: true,
       runAsNode: false,
+      inspect: false,
     });
   });
 
@@ -101,6 +106,7 @@ describe('electron-forge start', () => {
       interactive: true,
       args: ['-a', 'foo', '-l'],
       runAsNode: false,
+      inspect: false,
     });
   });
 
@@ -112,6 +118,19 @@ describe('electron-forge start', () => {
       enableLogging: false,
       interactive: true,
       runAsNode: true,
+      inspect: false,
+    });
+  });
+
+  it('should handle inspect-electron', async () => {
+    await runCommand(['--inspect-electron']);
+    expect(startStub.callCount).to.equal(1);
+    expect(startStub.firstCall.args[0]).to.deep.equal({
+      dir: process.cwd(),
+      enableLogging: false,
+      interactive: true,
+      runAsNode: false,
+      inspect: true,
     });
   });
 
diff --git a/test/fast/start_spec.js b/test/fast/start_spec.js
index 50f8c3d77..0c6f15fc7 100644
--- a/test/fast/start_spec.js
+++ b/test/fast/start_spec.js
@@ -113,6 +113,21 @@ describe('start', () => {
     expect(spawnStub.firstCall.args[1].slice(1)).to.deep.equal(args);
   });
 
+  it('should pass --inspect at the start of the args if inspect is set', async () => {
+    const args = ['magic'];
+    resolveStub.returnsArg(0);
+    spawnStub.returns(0);
+    await start({
+      dir: __dirname,
+      interactive: false,
+      args,
+      inspect: true,
+    });
+    expect(spawnStub.callCount).to.equal(1);
+    expect(spawnStub.firstCall.args[0]).to.contain('electron');
+    expect(spawnStub.firstCall.args[1].slice(1)).to.deep.equal(['--inspect'].concat(args));
+  });
+
   it('should resolve with a handle to the spawned instance', async () => {
     resolveStub.returnsArg(0);
     spawnStub.returns('child');