title: Node CLI Script Exits Early
body: <p>I have a Node JS CLI script that automates some migrations to a third-party service. I've largely avoided asynchronous methods (e.g. prefixing with <code>async</code>) as 1) I don't fully understand it in this context and 2) it hasn't been necessary for the script thus far.</p>
  <p>Where I'm having trouble, is that I'm looping through a set of files and attempting to call a method on each entry, but the method doesn't execute before the script exits.</p>
  <p>Here's the primary method:</p>
  <pre class="lang-js prettyprint-override"><code>const migrateAll = (app, env, source) =&gt; {
    const self = this;
  
    fs.promises
      .readFile(config, &quot;utf8&quot;)
      .then((contents) =&gt; {
        self.config = JSON.parse(contents);
      })
      .then(() =&gt; {
        const spaceId = self.config.applications[app].space_id;
        fs.readdir(source, &quot;utf8&quot;, (err, files) =&gt; {
          if (err) throw err;
  
          files.forEach((file) =&gt; {
            console.log(chalk.yellow(`Migrating &quot;${file}&quot; to the &quot;${env}&quot; environment for &quot;${app}&quot;`))
            migrate(file, env, app);
          });
  
          process.exit();
        });
      });
  };
  </code></pre>
  <p>The call to <code>migrate(file, env, app)</code> doesn't appear to run at all. The contents of that function are:</p>
  <pre class="lang-js prettyprint-override"><code>const migrate = (space, env, migration) =&gt; {
    exec(
      `migrate ${migration} &quot;${space}&quot; ${env}`,
      (error, stdout, stderr) =&gt; {
        if (error) {
            // A `switch` to handle errors.
          }
  
          process.exit();
        }
        if (stderr) {
          console.log(`stderr: ${stderr}`);
          process.exit();
        }
  
        success(stdout);
    );
  };
  </code></pre>
  <p>The rest of the script, in context, looks like this:</p>
  <pre class="lang-js prettyprint-override"><code>const parseFlags = () =&gt; {
    process.argv.splice(2).forEach((arg) =&gt; {
      let parts = arg.split(&quot;=&quot;);
  
      switch (parts[0]) {
        // parse flags into variables
      }
    });
  
    if (all) {
      migrateAll(app, env, source);
    }
  
    return { app, env, source };
  };
  
  const run = () =&gt; {
    try {
      intro();
      checkSettings();
      const { app, env, source } = parseFlags();
      // continue on here if migrateAll doesn't get called
    } catch (err) {
      complain(err);
    }
  };
  
  run();
  </code></pre>
  <p>So, with the right flags, we call <code>migrateAll()</code> which in turn calls the <code>migrate</code> function for each file we find that needs to migrate. Some things I've noticed/tried</p>
  <ul>
  <li>The <code>console.log</code> inside of the <code>forEach</code> in <code>migrateAll</code> runs as expected</li>
  <li>I've tried various combinations of <code>await</code> and <code>async</code>, <code>.then()</code>, promisify, etc, but it feels like I'm throwing things at the wall just to see what sticks to no avail.</li>
  </ul>