<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by ehmicky on Medium]]></title>
        <description><![CDATA[Stories by ehmicky on Medium]]></description>
        <link>https://medium.com/@ehmicky?source=rss-e92183ad8a22------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*pUVP7Pw1hfRlT8Llokh_HQ.jpeg</url>
            <title>Stories by ehmicky on Medium</title>
            <link>https://medium.com/@ehmicky?source=rss-e92183ad8a22------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 19 Jun 2026 01:25:44 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ehmicky/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[IPC made easy with Execa 9.2]]></title>
            <link>https://medium.com/itnext/ipc-made-easy-with-execa-9-2-939c6a358731?source=rss-e92183ad8a22------2</link>
            <guid isPermaLink="false">https://medium.com/p/939c6a358731</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[terminal]]></category>
            <category><![CDATA[cli]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[ehmicky]]></dc:creator>
            <pubDate>Thu, 06 Jun 2024 18:11:09 GMT</pubDate>
            <atom:updated>2024-06-06T19:48:57.167Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/991/1*FY3sgvovX1rrVghujOibfA.png" /></figure><h3>Inter-Process Complexity</h3><p>It’s easy to forget the technical wonders your OS is built upon. Something as basic as typing the following command in a terminal involves multiple abstraction layers.</p><pre>npx open-cli &quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;</pre><p>npx runs in a <a href="https://en.wikipedia.org/wiki/Process_(computing)">process</a>, separate from the shell that called it, then spawns another subprocess for <a href="https://github.com/sindresorhus/open-cli">open-cli</a>. Each process has its own executable file and resources (memory, CPU state, file descriptors, etc.).</p><p>Processes are isolated from each other. While this is great for security reasons, this also creates a need for <a href="https://en.wikipedia.org/wiki/Inter-process_communication">Inter-Process Communication</a> (IPC).</p><p>The most common IPC mechanisms are: <a href="https://nodejs.org/api/process.html#processargv">arguments</a>, <a href="https://en.wikipedia.org/wiki/Exit_status">exit codes</a>, <a href="https://en.wikipedia.org/wiki/Environment_variable">environment variables</a>, <a href="https://en.wikipedia.org/wiki/Signal_(IPC)">signals</a>, standard streams (<a href="https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)">stdin</a>, <a href="https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout)">stdout</a>, <a href="https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)">stderr</a>), <a href="https://en.wikipedia.org/wiki/File_descriptor">file descriptors</a>, files, shared memory, and network calls.</p><p>However, those solutions are often either too limited or too complicated. <a href="https://github.com/sindresorhus/execa/releases/tag/v9.2.0">Execa 9.2</a>, which was just released, aims at <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/ipc.md">simplifying IPC</a> when both processes use Node.js.</p><h3>Pass anything to a process</h3><p>Sending a string is straightforward with most IPC methods. However, any structured data requires serializing and parsing. For instance, plain objects can use JSON.</p><p>With <a href="https://github.com/sindresorhus/execa">Execa</a>, the <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#optionsipcinput">ipcInput</a> option converts most types automatically, so you don’t need to manually serialize or parse anything.</p><p>This follows the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm">structured clone algorithm</a>. In a nutshell, almost all JavaScript values are allowed, with the notable exception of functions (which includes class instance methods).</p><p>Also, while the size limit of arguments and environment variables is usually lower than 1MB, the ipcInput option can handle up to 2GB.</p><pre>// main.js<br>import {execaNode} from &#39;execa&#39;;<br><br>const ipcInput = [<br>  {<br>    task: &#39;lint&#39;, <br>    ignore: /test\.js/,<br>  },<br>  {<br>    task: &#39;copy&#39;, <br>    files: new Set([<br>      &#39;main.js&#39;, <br>      &#39;index.js&#39;,<br>    ]),<br>  },<br>];<br>await execaNode({ipcInput})`build.js`;</pre><pre>// build.js<br>import {getOneMessage} from &#39;execa&#39;;<br><br>const ipcInput = await getOneMessage();<br>for (const {task, ignore, files} of ipcInput) {<br>  await runTask(task, {ignore, files});<br>}</pre><h3>Return anything from a process</h3><p>The same problem holds for the process’s output. stdout and stderr can print anything, but the caller needs to parse it.</p><p>With Execa, a process can return almost any data by calling <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#sendmessagemessage-sendmessageoptions">sendMessage(message)</a>. The parent process retrieves it, kept as is, using the <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#resultipcoutput">result.ipcOutput</a> array.</p><pre>// main.js<br>import {execaNode} from &#39;execa&#39;;<br><br>const {ipcOutput} = await execaNode`build.js`;<br>console.log(ipcOutput[0]); // {kind: &#39;start&#39;, timestamp: date}<br>console.log(ipcOutput[1]); // {kind: &#39;stop&#39;, timestamp: date}</pre><pre>// build.js<br>import {sendMessage} from &#39;execa&#39;;<br><br>await sendMessage({kind: &#39;start&#39;, timestamp: new Date()});<br>await runBuild();<br>await sendMessage({kind: &#39;stop&#39;, timestamp: new Date()});</pre><h3>Exchange messages</h3><p>What if you need to retrieve the process’s output while it is still running, for example to show a progress bar? Or provide additional input after the process already started?</p><p>Usually, this is solved by streaming stdin, stdout, stderr, or making network calls. This can be tricky to get right, especially when tuning performance and handling any potential I/O errors.</p><p>Execa provides a simple set of methods to exchange messages: <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#sendmessagemessage-sendmessageoptions">sendMessage(message)</a> and <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#getonemessagegetonemessageoptions">getOneMessage()</a>.</p><pre>// parent.js<br>import {execaNode} from &#39;execa&#39;;<br><br>const subprocess = execaNode`child.js`;<br>await subprocess.sendMessage(&#39;Hello from parent&#39;);<br>const message = await subprocess.getOneMessage();<br>console.log(message); // &#39;Hello from child&#39;<br>await subprocess;</pre><pre>// child.js<br>import {getOneMessage, sendMessage} from &#39;execa&#39;;<br><br>const message = await getOneMessage(); // &#39;Hello from parent&#39;<br>const newMessage = message.replace(&#39;parent&#39;, &#39;child&#39;); // &#39;Hello from child&#39;<br>await sendMessage(newMessage);</pre><h3>Listen to messages</h3><p>You can also follow a client/server model where one process (or both) handles requests from the other. This is achieved by listening to all incoming messages with <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#geteachmessagegeteachmessageoptions">getEachMessage()</a>.</p><pre>// parent.js<br>import {execaNode} from &#39;execa&#39;;<br><br>const subprocess = execaNode`child.js`;<br>await subprocess.sendMessage(0);<br><br>// This loop ends when the subprocess exits.<br>// It throws if the subprocess fails.<br>for await (const message of subprocess.getEachMessage()) {<br>  console.log(message); // 1, 3, 5, 7, 9<br>  await subprocess.sendMessage(message + 1);<br>}</pre><pre>// child.js<br>import {sendMessage, getEachMessage} from &#39;execa&#39;;<br><br>// The subprocess exits when hitting `break`<br>for await (const message of getEachMessage()) {<br>  if (message === 10) {<br>    break;<br>  }<br><br>  console.log(message); // 0, 2, 4, 6, 8<br>  await sendMessage(message + 1);<br>}</pre><h3>Filter messages</h3><p>The <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#getonemessagegetonemessageoptions">getOneMessage()</a> method has a <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#getonemessageoptionsfilter">filter</a> option to select the specific message you want to retrieve. This is handy when receiving events of different types.</p><pre>import {execaNode} from &#39;execa&#39;;<br><br>const subprocess = execaNode`build.js`;<br>const stopMessage = await subprocess.getOneMessage({<br>  filter: message =&gt; message.type === &#39;stop&#39;,<br>});</pre><h3>Guaranteed reception</h3><p>IPC is stateful and time-sensitive by nature, which can create subtle <a href="https://en.wikipedia.org/wiki/Race_condition#In_software">race condition</a> bugs. <a href="https://en.wikipedia.org/wiki/Acknowledgement_(data_networks)">Most network protocols</a> prevent against those by ensuring that any message sent is also well received. For example, TCP uses an ACK number.</p><p>With Execa, the <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#sendmessageoptionsstrict">strict</a> option fulfills that purpose. When enabled, it guarantees that the other process properly receives your message.</p><pre>// main.js<br>import {execaNode} from &#39;execa&#39;;<br><br>const subprocess = execaNode`build.js`;<br>// This `build` message is received<br>await subprocess.sendMessage(&#39;build&#39;, {strict: true});<br>// This `lint` message is not received, so it throws<br>await subprocess.sendMessage(&#39;lint&#39;, {strict: true});<br>await subprocess; </pre><pre>// build.js<br>import {getOneMessage} from &#39;execa&#39;;<br><br>// Receives the &#39;build&#39; message<br>const task = await getOneMessage();<br>// The `lint` message is sent while `runTask()` is ongoing<br>// Therefore the `lint` message is discarded<br>await runTask(task);<br><br>// Does not receive the `lint` message<br>// Without `strict`, this would wait forever<br>const secondTask = await getOneMessage();<br>await runTask(secondTask);</pre><h3>No process left hanging</h3><p>To ensure every message sent by one end is received by the other, processes are kept alive when listening to messages.</p><p>However, this does not work well when you’re unsure whether those messages might be sent or not, as it can keep processes hanging forever. This can be fixed using the <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/api.md#getonemessageoptionsreference">reference: false</a> option.</p><pre>import {getEachMessage} from &#39;execa&#39;;<br><br>// {type: &#39;gracefulExit&#39;} is sometimes received, but not always<br>for await (const message of getEachMessage({reference: false})) {<br>  if (message.type === &#39;gracefulExit&#39;) {<br>    gracefulExit();<br>  }<br>}</pre><h3>Debugging</h3><p>Since processes are isolated by design, they can become black boxes that are hard to debug. To help with this, every IPC message sent by an Execa process is <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/ipc.md#debugging">automatically printed</a> in both <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/errors.md#error-message">error messages</a> and <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/debugging.md#verbose-mode">verbose logs</a>.</p><pre>// build.js<br>import {execaNode} from &#39;execa&#39;;<br><br>await execaNode`npm run build`;</pre><pre># Run in verbose mode<br># Each line with a * symbol is an IPC message<br><br>$ NODE_DEBUG=execa node build.js<br>[00:57:44.658] [0] $ npm run build<br>[00:57:44.670] [0]   Build application...<br>[00:57:44.692] [0] * {name: &#39;start&#39;}<br>[00:57:44.701] [0] * {name: &#39;entrypoint&#39;, value: &#39;mispelled_index.js&#39;} <br>[00:57:44.740] [0]   Error: the entrypoint is invalid.<br>[00:57:44.747] [0] ✘ Command failed with exit code 1: npm run build<br>[00:57:44.747] [0] ✘ (done in 89ms)</pre><h3>Graceful termination</h3><p>Being gentle with processes is not easy. In fact, terminating them is usually quite brutal. The standard approach is to send a signal like <a href="https://en.wikipedia.org/wiki/Signal_(IPC)#SIGTERM">SIGTERM</a>. However, this makes the process end abruptly, including any ongoing operation. This can leave a file half-written, an HTTP request hanging, or some data broken.</p><p>On Unix, handlers can <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/termination.md#handling-signals">intercept signals</a> to run any cleanup logic. Unfortunately, this does not work on Windows.</p><p>The <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/termination.md#graceful-termination">gracefulCancel</a> option offers a cross-platform solution to this problem. It uses IPC to share an <a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal">AbortSignal</a> between a process and its parent process.</p><pre>// main.js<br>import {execaNode} from &#39;execa&#39;;<br><br>const controller = new AbortController();<br>setTimeout(() =&gt; {<br>  controller.abort();<br>}, 5000);<br><br>const cancelSignal = controller.signal;<br>await execaNode({cancelSignal, gracefulCancel: true})`build.js`;</pre><pre>// build.js<br>import {getCancelSignal} from &#39;execa&#39;;<br><br>const cancelSignal = await getCancelSignal();<br>const url = &#39;https://example.com/build/info&#39;;<br>const response = await fetch(url, {signal: cancelSignal});</pre><h3>Under the hood</h3><p>We’ve built those features on top of <a href="https://nodejs.org/api/process.html#processsendmessage-sendhandle-options-callback">Node’s builtin IPC</a>. <a href="https://en.wikipedia.org/wiki/Named_pipe">Named pipes</a> are used as a communication channel between the processes. The message payloads are <a href="https://v8.github.io/api/head/classv8_1_1ValueSerializer.html">serialized with V8</a>.</p><p>IPC is an advanced feature. 95% of the time, you won’t need it: <a href="https://github.com/sindresorhus/execa">Execa</a> already provides simpler ways to perform common tasks, from <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/scripts.md">scripts</a> to <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/pipe.md">piping</a> or <a href="https://github.com/sindresorhus/execa/blob/v9.2.0/docs/streams.md">streaming</a>. However, in more elaborate scenarios, IPC could become a time saver.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=939c6a358731" width="1" height="1" alt=""><hr><p><a href="https://medium.com/itnext/ipc-made-easy-with-execa-9-2-939c6a358731">IPC made easy with Execa 9.2</a> was originally published in <a href="https://medium.com/itnext">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Execa 9: our biggest release]]></title>
            <link>https://medium.com/@ehmicky/execa-9-release-d0d5daaa097f?source=rss-e92183ad8a22------2</link>
            <guid isPermaLink="false">https://medium.com/p/d0d5daaa097f</guid>
            <category><![CDATA[terminal]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[cli]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[ehmicky]]></dc:creator>
            <pubDate>Wed, 08 May 2024 20:26:54 GMT</pubDate>
            <atom:updated>2024-05-08T20:41:03.543Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="Execa logo" src="https://cdn-images-1.medium.com/max/991/1*FY3sgvovX1rrVghujOibfA.png" /></figure><p><a href="https://github.com/sindresorhus/execa">Execa</a> runs commands in your script, application or library. Unlike zx and Bun shell, Execa <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/shell.md#avoiding-shells">distances itself</a> from shells and the old days of Bash scripts. Instead, it embraces a modern, <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/bash.md">purely JavaScript approach</a>, optimized for programmatic usage. This makes executing commands simple, secure, cross-platform and easy to debug.</p><pre>import {$} from &#39;execa&#39;;<br><br>const tokensUrl = &#39;https://example.com/api/tokens&#39;;<br>const token = await $`curl ${tokensUrl}`<br>  .pipe`grep api_token`<br>  .pipe`head -n 1`;<br><br>const branch = await $`git branch --show-current`;<br><br>const logFile = &#39;logs.txt&#39;;<br>await $({stderr: logFile})`dep deploy<br>  --parallel<br>  --token=${token} <br>  --branch=${branch}`;</pre><p>Despite being 8 years old, the project is very active. In fact, <a href="https://github.com/sindresorhus/execa/releases/tag/v9.0.0">today’s release</a> is our biggest so far, involving 6 contributors, 9 months of development, 317 PRs and 3915 automated tests. Here’s a highlight of some of the new features.</p><h3>Read the output, one line at a time</h3><p>If a command lasts for a long time, you might want to read its output while it is still running. Since most commands are text-based, this usually means iterating over each output line. Although this might seem simple at first sight, it is <a href="https://github.com/sindresorhus/execa/blob/40fdc7515d4b5423f05fb5fbafcc45aa399ed1a0/lib/transform/split.js">surprisingly hard</a> to get right.</p><p>With Execa, commands are <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/lines.md#iteration">iterable</a>, one line at a time. The lines option can also be used to <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/lines.md#simple-splitting">split the full output</a> into multiple lines.</p><pre>import {execa} from &#39;execa&#39;;<br><br>// One line at a time<br>for await (const line of execa`npm run build`) {<br>  if (line.includes(&#39;ERROR&#39;)) {<br>    await reportError(line);<br>  }<br>}<br><br>// All lines at once<br>const {stdout: lines} = await execa({<br>  lines: true,<br>})`npm run build`;<br>const errorLines = lines<br>  .filter(line =&gt; line.includes(&#39;ERROR&#39;))<br>  .join(&#39;\n&#39;);<br>console.error(errorLines);</pre><h3>Map/filter the input and output</h3><p>Node.js <a href="https://nodejs.org/api/stream.html#class-streamduplex">Duplexes</a> and <a href="https://nodejs.org/api/stream.html#class-streamtransform">Transforms</a> are streams that map or filter data. There are many available modules based on them, from <a href="https://csv.js.org/transform/api/stream/">parsing CSV</a> to <a href="https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream">compressing data</a> or <a href="https://github.com/bevry/caterpillar">logging</a>.</p><p>With Execa, they can be <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/transform.md#duplextransform-streams">passed directly</a> to a command’s stdin, stdout or stderr option to transform its input or output. Web-based <a href="https://developer.mozilla.org/en-US/docs/Web/API/TransformStream">TransformStreams</a> are supported too.</p><p>Streaming consumes memory progressively and holds the CPU in small bursts. If a command is slow or its output is big, this is more efficient than modifying its final result all at once.</p><pre>import {execa} from &#39;execa&#39;;<br><br>const {stdout} = await execa({<br>  stdout: new CompressionStream(&#39;gzip&#39;),<br>  encoding: &#39;buffer&#39;,<br>})`npm run build`;<br><br>// `stdout` is compressed with gzip<br>console.log(stdout); </pre><h3>Generator-based transforms</h3><p>That being said, writing your own streams can be tricky. To enjoy their benefits without diving into their intricate ins and outs, <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/transform.md">simple generator functions</a> can be used instead.</p><pre>import {execa} from &#39;execa&#39;;<br><br>let count = 0;<br>const {stdout} = await execa({<br>  * stdout(line) {<br>    yield `[${count++}] ${line}`;<br>  },<br>})`npm run build`;<br><br>// Prefix line number:<br>// [0] ...<br>// [1] ...<br>// [2] ...<br>console.log(stdout);</pre><h3>Redirect the input and output</h3><p>A command’s input or output is commonly redirected from/to a file, as shown by the &lt; and &gt; builtin operators in Unix shells. With Execa, this can be done <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/output.md#file-output">by passing a </a><a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/output.md#file-output">{file: &#39;./path&#39;}</a> object to the stdin, stdout or stderr option.</p><p>Another usual task is to print a command’s output progressively. Passing &#39;inherit&#39; to the stdout or stderr option achieves that, but it prevents storing the output in a variable. This can be fixed <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/output.md#terminal-output">by passing </a><a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/output.md#terminal-output">[&#39;inherit&#39;, &#39;pipe&#39;]</a> instead.</p><pre>import {execa} from &#39;execa&#39;;<br><br>const {stderr} = await execa({<br>  // Write stdout to a file<br>  stdout: {file: &#39;./stdout.txt&#39;},<br>  // Return stderr, but also print it<br>  stderr: [&#39;inherit&#39;, &#39;pipe&#39;],<br>})`npm run build`;</pre><h3>Pipe multiple commands</h3><p>The pipe operator | is great in interactive terminals. However, in a script file, it cannot easily:</p><ul><li>Retrieve the output of each command in the pipeline, as opposed to only the last one, making debugging difficult.</li><li>Handle errors: unless the pipefail option is set, the pipeline might succeed even if some of its commands failed.</li><li>Pipe one command to several, or several commands to one.</li><li>Change a command’s piping destination.</li><li>Benefit from strong types, since parsing the pipeline string in TypeScript is not feasible.</li></ul><p>Execa’s <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/pipe.md">subprocess.pipe() method</a> can do all of the above, enabling a better experience in a programmatic context.</p><pre>import {execa, execaNode} from &#39;execa&#39;;<br><br>// `npm run build | sort | head -n 2`<br>// Throws if any of the three commands fails <br>const finalResult = await execa`npm run build`<br>  .pipe`sort`<br>  .pipe`head -n 2`;<br>// `npm run build | sort`<br>const sortResult = finalResult.pipedFrom[0];<br>// `npm run build`<br>const buildResult = sortResult.pipedFrom[0];<br><br>// Pipe several commands to the same logging process<br>const logger = execaNode`log-remotely.js`;<br>await Promise.all([<br>  execa`npm run build`.pipe(logger),<br>  execa`npm run test`.pipe(logger),<br>]);</pre><h3>Verbose mode</h3><p>Commands sometimes feel like black boxes. They run in processes isolated from each other, which can turn a small typo into an hours-long debugging headache.</p><p>To alleviate this problem, <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/debugging.md#verbose-mode">the verbose mode</a> has been improved to automatically print the commands’ arguments, output, errors, completion and duration.</p><pre>// build.js<br>import {execa} from &#39;execa&#39;;<br><br>await execa`npm run build`;<br>await execa`npm run test`;</pre><pre>$ NODE_DEBUG=execa node build.js<br>[00:57:44.581] [0] $ npm run build<br>[00:57:44.653] [0]   Building application...<br>[00:57:44.653] [0]   Done building.<br>[00:57:44.658] [0] ✔ (done in 78ms)<br>[00:57:44.658] [1] $ npm run test<br>[00:57:44.740] [1]   Running tests...<br>[00:57:44.740] [1]   Error: the entrypoint is invalid.<br>[00:57:44.747] [1] ✘ Command failed with exit code 1: npm run test<br>[00:57:44.747] [1] ✘ (done in 89ms)</pre><h3>Detailed errors</h3><p>Errors now include <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/errors.md">richer information</a> including the interleaved output, the duration, and additional insights into the failure’s root cause.</p><pre>import {execa} from &#39;execa&#39;;<br><br>try {<br>  await execa({timeout: 5000})`npm run build`;<br>} catch (error) {<br>  console.error(error);<br>  // ExecaError: Command timed out after 5000 milliseconds: npm run build<br>  //     at file:///home/me/Desktop/example.js:2:20<br>  //     at ... {<br>  //   command: &#39;npm run build&#39;,<br>  //   escapedCommand: &#39;npm run build&#39;,<br>  //   cwd: &#39;/path/to/cwd&#39;,<br>  //   durationMs: 19.95693,<br>  //   failed: true,<br>  //   timedOut: true,<br>  //   isCanceled: false,<br>  //   isTerminated: true,<br>  //   isMaxBuffer: false,<br>  //   signal: &#39;SIGTERM&#39;,<br>  //   signalDescription: &#39;Termination&#39;,<br>  //   stdout: &#39;Building the application...&#39;,<br>  //   stderr: &#39;Warning: deprecated API.&#39;,<br>  //   stdio: [<br>  //     undefined, <br>  //     &#39;Building the application...&#39;, <br>  //     &#39;Warning: deprecated API.&#39;,<br>  //   ],<br>  //   pipedFrom: []<br>  // }<br>}</pre><h3>Debug termination signals</h3><p>Have you ever wondered why a specific command ended abruptly? Termination signals like SIGTERM do not carry any information: no message, no stack trace.</p><p>This can be solved by <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/termination.md#error-message-and-stack-trace">passing an error instance</a> to subprocess.kill(), which could be a time-saver when debugging complex bugs.</p><pre>import {execa} from &#39;execa&#39;;<br><br>const subprocess = execa`npm run build`;<br>onCancel(reason =&gt; {<br>  const error = new Error(`Canceled by ${reason}`);<br>  subprocess.kill(error);<br>});<br>await subprocess;</pre><h3>Template strings</h3><p>Since Execa 7, commands can be specified using a template string, like zx. However, this was previously limited to the $ method.</p><p>Both the <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/execution.md#template-string-syntax">template string syntax</a> and the traditional <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/execution.md#array-syntax">array syntax</a> can now be used with all Execa methods. They are equivalent and mostly a matter of preference.</p><p>Also, template strings can span multiple lines, which is useful when passing many CLI flags.</p><p>When executing a series of commands in a script, <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/scripts.md">$ is recommended</a>. When calling individual commands in an application or library, execa and execaNode are preferred instead. The only difference is that $ uses script-friendly default options. For example, it automatically reads its stdin from the terminal.</p><pre>import {execa} from &#39;execa&#39;;<br><br>await execa`npm run build<br>  --concurrency 2<br>  --fail-fast`;</pre><h3>Share options</h3><p>All Execa methods can <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/api.md#execaoptions">bind options</a>. This enables setting global options or re-using them between multiple commands.</p><pre>import {execa as execa_} from &#39;execa&#39;;<br><br>// Set global options<br>const execa = execa_({timeout: 5000});<br><br>await execa`npm run build`;<br>await execa`npm run test`;</pre><h3>Embrace web APIs</h3><p>Server-side JavaScript is increasingly adopting web APIs in lieu of Node.js core modules. So is Execa: instead of <a href="https://nodejs.org/api/stream.html">Node.js streams</a>, file path strings and <a href="https://nodejs.org/api/buffer.html#class-buffer">Buffer</a>, you can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/Streams_API">web streams</a>, <a href="https://nodejs.org/api/url.html#urlpathtofileurlpath-options">file URLs</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array">Uint8Array</a>.</p><pre>import {execaNode} from &#39;execa&#39;;<br><br>const response = await fetch(&#39;https://example.com/api/orders&#39;);<br>await execaNode({<br>  stdin: response.body,<br>})`send_orders.js`;</pre><h3>Convert to streams</h3><p>Some modules take streams as arguments or return them. In order to let you use commands to those modules directly, Execa subprocesses can be <a href="https://github.com/sindresorhus/execa/blob/v9.0.0/docs/streams.md#converting-a-subprocess-to-a-stream">converted to streams</a> using subprocess.readable(), subprocess.writable() or subprocess.duplex().</p><pre>import {execaNode} from &#39;execa&#39;;<br>import {pipeline} from &#39;node:stream/promises&#39;;<br>import {<br>  createReadStream, <br>  createWriteStream,<br>} from &#39;node:fs&#39;;<br><br>await pipeline(<br>  createReadStream(&#39;./input.txt&#39;),<br>  execaNode`transform.js`.duplex(),<br>  createWriteStream(&#39;./output.txt&#39;),<br>);</pre><p>For a full list of the breaking changes, new features and bug fixes, please check out the <a href="https://github.com/sindresorhus/execa/releases/tag/v9.0.0">release notes</a>.</p><p>Also, we’ve completely revamped the <a href="https://github.com/sindresorhus/execa/tree/v9.0.0#documentation">documentation</a>: aside from the reference section, it now includes many user guides and examples. We’d love to encourage new users to better understand processes, which can be a daunting topic at first. Hopefully, the new documentation will also help long-time users discover specific features they previously missed.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0d5daaa097f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Shell-free scripts with Execa 7]]></title>
            <link>https://medium.com/itnext/shell-free-scripts-with-execa-7-885fb3b42f83?source=rss-e92183ad8a22------2</link>
            <guid isPermaLink="false">https://medium.com/p/885fb3b42f83</guid>
            <category><![CDATA[bash]]></category>
            <category><![CDATA[shell]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nodejs]]></category>
            <dc:creator><![CDATA[ehmicky]]></dc:creator>
            <pubDate>Sat, 11 Mar 2023 23:54:39 GMT</pubDate>
            <atom:updated>2023-03-14T20:23:21.133Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9SsXkUoZpzzNtyxKCVJHSQ.jpeg" /><figcaption>Almost shell-free beach (photo by <a href="https://unsplash.com/photos/LMlVa3QDEXs">Aaron Burden</a>)</figcaption></figure><p>While shell scripts are very handy, many developers enjoy the flexibility, expressiveness and ecosystem that come with programming languages like JavaScript. <a href="https://github.com/google/zx/">zx</a>, a recent popular project from Google, combines the best of both worlds.</p><pre>const branch = await $`git branch --show-current`<br>await $`deploy --branch=${branch}`</pre><p><a href="https://github.com/sindresorhus/execa">Execa</a> is a 7-year-old Node module used by <a href="https://github.com/sindresorhus/execa/network/dependents">15 million repositories</a> that makes commands and processes easy to execute. Our <a href="https://github.com/sindresorhus/execa/releases/tag/v7.1.0">7.1 release</a> features a mode similar to zx but with a simpler JavaScript-only approach. This article focuses on the main differences with zx.</p><pre>import { $ } from &#39;execa&#39;<br><br>const branch = await $`git branch --show-current`<br>await $`deploy --branch=${branch}`</pre><h3>Scripting without a shell</h3><p>Why use both Node and Bash? With Execa, there is no shell syntax to remember: everything is just plain JavaScript. Almost all shell-specific features can be expressed in JavaScript. For the remaining edge cases, a <a href="https://github.com/sindresorhus/execa#shell">shell option</a> is available.</p><p>This is more:</p><ul><li><em>Secure</em>: <a href="https://matklad.github.io/2021/07/30/shell-injection.html">shell injections</a> are not technically feasible.</li><li><em>Cross-platform</em>: not all Windows machines have Bash available.</li><li><em>Performant</em>: spawning a shell for every command comes at a cost. Even <a href="https://docs.npmjs.com/cli/v9/commands/npx">npx</a> can be skipped since Execa can <a href="https://github.com/sindresorhus/execa#preferlocal">directly execute</a> locally installed binaries.</li></ul><pre># In Bash<br>API_KEY=&quot;secret&quot; npx deploy &quot;$cluster&quot; &amp;&gt; logs.txt &amp;&amp; echo &quot;done&quot;</pre><pre>// In JavaScript<br>import { $ } from &#39;execa&#39;<br><br>const options = { env: { API_KEY: &#39;secret&#39; } }<br>await $(options)`deploy ${cluster}`.pipeAll(’logs.txt’)<br>console.log(&#39;done&#39;)</pre><h3>Simplicity</h3><p>Execa does not require any special binary, inject global variables nor include any utility. It focuses on being <a href="https://sindresorhus.com/blog/small-focused-modules">small and modular</a> instead. Any Node module can be used in your scripts.</p><pre>import { $ } from &#39;execa&#39;<br>import pRetry from &#39;p-retry&#39;<br><br>await pRetry(<br>  async () =&gt; await $`deploy dev_cluster`,<br>  { retries: 5 },<br>)</pre><h3>Options</h3><p>The <a href="https://nodejs.org/api/child_process.html#child_processspawncommand-args-options">child_process</a> core Node module includes many useful features: timeout, cancellation, <a href="https://nodejs.org/api/child_process.html#optionsdetached">background processes</a>, <a href="https://nodejs.org/api/child_process.html#subprocesssendmessage-sendhandle-options-callback">IPC</a>, <a href="https://nodejs.org/api/child_process.html#subprocesspid">PID</a>, UID/GID, <a href="https://nodejs.org/api/child_process.html#subprocessunref">weak references</a>, and more. Execa adds a few <a href="https://github.com/sindresorhus/execa#why">additional ones</a>: <a href="https://github.com/sindresorhus/execa#optionsforcekillaftertimeout">graceful termination</a>, <a href="https://github.com/sindresorhus/execa#cleanup">cleanup</a>, <a href="https://github.com/sindresorhus/execa#all-2">interleaved output</a>, etc. Those can be set using <a href="https://github.com/sindresorhus/execa#options">$(options)</a> for either one or multiple commands.</p><pre>import { $ } from &#39;execa&#39;<br><br>const $$ = $({ timeout: 5000, all: true })<br><br>// `all` retrieves both stdout and stderr<br>const { all } = $$`deploy dev_cluster`</pre><h3>Debugging</h3><p>Child processes can be hard to debug. This is why Execa:</p><ul><li>Includes a <a href="https://github.com/sindresorhus/execa#verbose">verbose option</a>, which can be set using NODE_DEBUG=execa.</li><li>Reports <a href="https://github.com/sindresorhus/execa#handling-errors">detailed error</a> messages and properties.</li><li>Is purely stateless, making it straightforward to figure out what is the current directory, or any other option.</li></ul><pre>&gt; NODE_DEBUG=execa node deploy.js<br><br>[16:50:03.305] deploy dev_cluster<br>........dev_cluster successfully deployed.<br><br>[16:53:06.378] deploy prod_cluster<br>.............prod_cluster successfully deployed.</pre><h3>Piping</h3><p>Redirecting input/output is a common shell pattern that’s available with Execa.</p><pre>import { $ } from &#39;execa&#39;<br><br>// Pipe input from a string or buffer, like &lt;&lt;&lt; in Bash<br>await $({ input: &#39;dev_cluster&#39; })`deploy`<br><br>// Pipe input from a file, like &lt; in Bash<br>await $({ inputFile: &#39;clusters.txt&#39; })`deploy`<br><br>// Pipe output to a file, like &gt;, 2&gt; and &amp;&gt; in Bash<br>await $`deploy dev_cluster`.pipeStdout(&#39;stdout.txt&#39;)<br>await $`deploy dev_cluster`.pipeStderr(&#39;stderr.txt&#39;)<br>await $({ all: true })`deploy dev_cluster`.pipeAll(&#39;logs.txt&#39;)<br><br>// Pipe output to another command, like | and |&amp; in Bash<br>await $`deploy dev_cluster`.pipeStdout($`grep done`)<br><br>// Pipe output to a stream, like 2&gt;&amp;1 in Bash<br>const { stdout } = await $`deploy dev_cluster`.pipeStderr(process.stdout)</pre><p>If you’re curious, please feel free to check our <a href="https://github.com/sindresorhus/execa">main documentation</a> and <a href="https://github.com/sindresorhus/execa/blob/main/docs/scripts.md">the page</a> dedicated to Node.js scripts. Huge thanks to <a href="http://aaronccasanova.com/">Aaron Casanova</a>, a new contributor to Execa, who added this feature, and to <a href="https://sindresorhus.com/">Sindre Sorhus</a>, who reviewed it!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=885fb3b42f83" width="1" height="1" alt=""><hr><p><a href="https://medium.com/itnext/shell-free-scripts-with-execa-7-885fb3b42f83">Shell-free scripts with Execa 7</a> was originally published in <a href="https://medium.com/itnext">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How big is a JavaScript string?]]></title>
            <link>https://medium.com/bitsrc/how-big-is-a-string-ef2af3d222e6?source=rss-e92183ad8a22------2</link>
            <guid isPermaLink="false">https://medium.com/p/ef2af3d222e6</guid>
            <category><![CDATA[terminal]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[ehmicky]]></dc:creator>
            <pubDate>Thu, 18 Aug 2022 08:40:09 GMT</pubDate>
            <atom:updated>2022-09-07T09:11:55.701Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<h4>The many sizes of a JS string</h4><figure><img alt="Cat confused by JavaScript strings" src="https://cdn-images-1.medium.com/max/1024/1*-7pMDb1Vn6LbFw8ZMWH4GQ.jpeg" /><figcaption>Cat confused by JavaScript strings<strong> </strong>(photo by <a href="https://www.pexels.com/photo/kitten-sitting-on-floor-near-string-artwork-7411938/">Monstera</a>)</figcaption></figure><p>When measuring a string in JavaScript, string.length comes to mind. However, that property does not tell the full story. Strings have many sizes: code units, code points, bytes, pixels, terminal columns.</p><p>Let’s dive into their differences.</p><h3>Code units</h3><p>Each string element in JavaScript is a UTF-16 <a href="https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-ecmascript-language-types-string-type">code unit</a>. In other words, any string[index], commonly (and ambiguously) referred to as a string “character.”</p><p>Code units are fast and convenient to use since they underpin all string operations (with a few exceptions noted below) including <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length">string.length</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice">string.slice()</a>, string === string, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">string.replace()</a> and so on.</p><p>Strings have a maximum size in code units. While the <a href="https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-ecmascript-language-types-string-type">standard defines it</a> as at most ~9e15, JavaScript engines implement much lower limits: ~5e8 <a href="https://github.com/v8/v8/blob/ea56bf5513d0cbd2a35a9035c5c2996272b8b728/include/v8.h#L2986-L2987">with V8</a>, ~1e9 <a href="https://searchfox.org/mozilla-central/source/js/public/String.h#330">with SpiderMonkey</a> and ~2e9 <a href="https://github.com/WebKit/WebKit/blob/3757be4fb77dbbf9bbb0edf910899c4c37119d36/Source/JavaScriptCore/runtime/JSString.h#L128">with JavaScriptCore</a>.</p><figure><img alt="`// RangeError: Invalid string length \n ‘_’.repeat(1e16)`" src="https://cdn-images-1.medium.com/max/1024/1*_j10PT3vl_bDnCdvg048lA.png" /></figure><h3>Code points</h3><p>A Unicode <a href="https://en.wikipedia.org/wiki/Code_point">code point</a> is a number identifying a single abstract character. It is often noted in hexadecimal: for example, the decimal number 129445 would be written U+01F9A5 🦥 (sloth). Unicode maintains <a href="https://en.wikipedia.org/wiki/Plane_(Unicode)">a list of characters</a> with code points ranging:</p><ul><li>From U+000000 to U+00007F: <a href="https://en.wikipedia.org/wiki/ASCII">ASCII</a></li><li>From U+000080 to U+00FFFF: <a href="https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane">BMP (Basic Multilingual Plane)</a></li><li>From U+010000 to U+10FFFF: Astral code points. This is where you’ll find emoji! 🎶</li></ul><p>Usually, a UTF-16 code unit is equivalent to a code point. For example, &quot;Olá!&quot; has 4 code units with their own code points: U+004F, U+006C, U+00E1 and U+0021.</p><figure><img alt="`”Olá!” === “\u004F\u006C\u00E1\u0021”`" src="https://cdn-images-1.medium.com/max/1024/1*G-ThKFm002u3f7QQrtAQHQ.png" /></figure><p>However, astral code points (U+010000 and above) are broken down into two code units:</p><ul><li>First, a “high/leading surrogate” from \uD800 to \uDBFF</li><li>Then, a “low/trailing surrogate” from \uDC00 to \uDFFF</li></ul><p>For example, U+01F9A5 becomes \uD83E and \uDDA5. This conversion from a code point to a surrogate pair is specific to <a href="https://en.wikipedia.org/wiki/UTF-16">UTF-16</a>. If you’re curious about it, please check <a href="https://www.unicode.org/faq/utf_bom.html#utf16-4">this code sample</a>.</p><figure><img alt="`”🦥” === “\uD83E\uDDA5”`" src="https://cdn-images-1.medium.com/max/1024/1*uzylrivJFBnc4XucuZ5IOQ.png" /></figure><p>This only applies if the two surrogates follow each other in that order. In JavaScript, isolated or inverted surrogates are valid but considered their own code points and generally either invisible or printed as � (<a href="https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character">replacement character</a> U+FFFD).</p><p>Since most string operations use code units, surrogates can be a problem. In some cases, they work just fine. For example, the following statements are correct because &quot;🦥&quot; is equivalent to &quot;\uD83E\uDDA5&quot;, i.e. to the full surrogates pair.</p><figure><img alt="`const string = “🦥” \n string === “🦥” // true \n /🦥/.test(string) // true \n string + “🐨” // “🦥🐨” \n string.replace(“🦥”, “🐨”) // “🐨” \n “🐨🦥🐨”.split(“🦥”) // [“🐨”, “🐨”]`" src="https://cdn-images-1.medium.com/max/1024/1*Ep4BYddRb0V6RlGZ2X4Xnw.png" /></figure><p>However, some string operations might target individual surrogates and split the pair.</p><figure><img alt="`const string = “🦥” \n string[0] // “\uD83E” \n string[1] // “\uDDA5” \n string[0] === “🦥” // false \n /^.$/.test(string) // false \n /^..$/.test(string) // true \n string.length // 2 \n “🦥🐨🐨”.slice(2) // “🐨🐨” \n string.replace(/./g, “🐨”) // “🐨🐨” \n […string.matchAll(/./g)] // [[“\uD83E”], // [“\uDDA5”]]`" src="https://cdn-images-1.medium.com/max/1024/1*acPYf6svc_yKT1rZ7-ZmJA.png" /></figure><p>Fortunately, a few string operations use code points instead of code units:</p><ul><li>Iterations, including [...string] and for (const codepoint of string), but excluding for (const index in string)</li><li>Regular expressions with the Unicode flag: /.../u</li><li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#escape_sequences">\u{000000}</a> instead of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#escape_sequences">\u0000</a></li><li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt">string.codePointAt()</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint">String.fromCodePoint()</a> instead of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt">string.charCodeAt()</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode">String.fromCharCode()</a></li><li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase">string.to*Case()</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim">string.trim*()</a></li></ul><figure><img alt="`const string = “🦥” \n string === “\uD83E\uDDA5” // true \n string === “\u{01F9A5}” // true \n /^.$/u.test(string) // true \n […string].length // 1 (code points) \n […”🦥🐨🐨”].slice(2).join(“”) // “🐨” (slice/truncate by code point) \n string.replace(/./gu, “🐨”) // “🐨” \n […string.matchAll(/./gu)] // [[“🦥”]] \n string.charCodeAt(0) // 0xD83E \n string.charCodeAt(1) // 0xDDA5 \n string.codePointAt(0) // 0x1F9A5 \n string.codePointAt(1) // 0xDDA5. Careful: the return value of `codePoint`" src="https://cdn-images-1.medium.com/max/1024/1*usQYO_N0SaodVAS4kTqtVQ.png" /></figure><h3>Bytes</h3><p>When a string is written to a file or sent over the network, it is first serialized to a series of bytes. This binary representation differs from code units and code points.</p><p><a href="https://en.wikipedia.org/wiki/Character_encoding">Character encodings</a> translate each code point into one or several bytes. While there are quite many of them, the most common ones these days are <a href="https://en.wikipedia.org/wiki/UTF-16">UTF-16</a> and <a href="https://en.wikipedia.org/wiki/UTF-8">UTF-8</a>.</p><p>Since JavaScript strings are based on UTF-16, their binary representation in that character encoding is straightforward (aside from <a href="https://en.wikipedia.org/wiki/Endianness">endianness</a>): each code unit translates to an equivalent bytes pair.</p><figure><img alt="“Olá!” &gt; “O” + “l” + “á” + “!” &gt; “\u004F” + “\u006C” + “\u00E1” + “\u0021” &gt; 00 4F 00 6C 00 E1 00 21. And “🦥” &gt; “\uD83E” + “\uDDA5” &gt; D8 3E DD A5." src="https://cdn-images-1.medium.com/max/1024/1*DB4NJhYjKfOyP4bGlzk8Vg.png" /></figure><p>For UTF-8, each code point translates to a series of 1 to 4 bytes. Lower Unicode code points take fewer bytes. In particular, ASCII characters are 1 byte long. On the other hand, astral code points are 4 bytes long. The conversion logic is explained <a href="https://en.wikipedia.org/wiki/UTF-8#Encoding">in details here</a>.</p><figure><img alt="“Olá!” &gt; “O” + “l” + “á” + “!” &gt; “\u{004F}” + “\u{006C}” + “\u{00E1}” + “\u{0021}” &gt; 4F 6C C3 A1 21. And “🦥” &gt; “\u{01F9A5}” &gt; F0 9F A6 A5." src="https://cdn-images-1.medium.com/max/1024/1*x7-FGJF2J_-A1el78bU4YA.png" /></figure><p>Some JavaScript packages are available for common operations like retrieving a string’s size in bytes or slicing it bytewise (see <a href="https://github.com/ehmicky/string-byte-length">string-byte-length</a> and <a href="https://github.com/ehmicky/string-byte-slice">string-byte-slice</a>). Otherwise, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array">Uint8Array</a>s can be used to represent series of bytes and <a href="https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder">TextEncoder</a>/<a href="https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder">TextDecoder</a> to convert strings to/from them.</p><figure><img alt="`const encoder = new TextEncoder() \n const decoder = new TextDecoder() \n const string = “🦥” \n const uint8Array = encoder.encode(string) // [0xf0, 0x9f, 0xa6, 0xa5] (UTF-8 bytes) \n decoder.decode(uint8Array) // “🦥”`" src="https://cdn-images-1.medium.com/max/1024/1*dL4ZpoejppukDNcx1eRw1A.png" /></figure><p><a href="https://nodejs.org/api/buffer.html">Buffer</a>s are a Node.js alternative with a few additional features.</p><figure><img alt="`const string = “🦥” \n const buffer = Buffer.from(string) // [0xF0, 0x9F, 0xA6, 0xA5] \n buffer.toString() // “🦥”`" src="https://cdn-images-1.medium.com/max/1024/1*h8zfyliwruOd4pZuU_NFsA.png" /></figure><h4>Width</h4><p>When displayed, a string occupies a platform-specific width. For example, browsers use pixels, <a href="https://en.wikipedia.org/wiki/Em_(typography)">em</a>, etc. We’ll focus on terminals, which use columns.</p><p>Terminals print characters in a grid pattern. Computing a string’s width primarily helps with vertical alignment and padding. Also, while terminals do wrap lines automatically, <a href="https://github.com/chalk/wrap-ansi">manual wrapping</a> can be needed for similar reasons.</p><p>Determining a string’s terminal width is rather intricate.</p><p>To begin with, considering some terminals or fonts might not handle exotic characters well, <a href="https://github.com/ehmicky/cross-platform-terminal-characters">cross-platform terminal characters</a> should be preferred for consistent behavior.</p><figure><img alt="Gnome terminal (Ubuntu) showing emoji displayed correctly" src="https://cdn-images-1.medium.com/max/461/1*W7Aj81-nvWS8DL2aGtICMQ.png" /><figcaption>GNOME terminal (Ubuntu)</figcaption></figure><figure><img alt="cmd.exe (Windows) showing emoji not displayed correctly" src="https://cdn-images-1.medium.com/max/463/1*B-SMXIA0Rq1ojHYR6WJknw.png" /><figcaption>cmd.exe (Windows)</figcaption></figure><p>Also, while most code points are 1 column wide, <a href="https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms">fullwidth characters</a> are 2 columns wide. Those usually represent Chinese, Japanese and Korean logograms. Common code points such as ASCII characters are sometimes available as <a href="https://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms_(Unicode_block)">wide or narrow variants</a>. Unicode <a href="https://www.unicode.org/reports/tr11/">provides a list</a> with each code point’s width, which can be accessed through <a href="https://github.com/sindresorhus/is-fullwidth-code-point">some helper modules</a>.</p><figure><img alt="Narrow: 0123456789 ABCDEFGHIJ ｱｲｳｴｵｶｷｸｹｺ and wide: ０１２３４５６７８９ ＡＢＣＤＥＦＧＨＩＪ アイウエオカキクケコ" src="https://cdn-images-1.medium.com/max/1024/1*iowddEoD6EAurP3u5b6z3g.png" /></figure><p>Furthermore, some code points are meant to be <a href="https://en.wikipedia.org/wiki/Combining_character">combined with another</a>. Those are usually <a href="https://en.wikipedia.org/wiki/Diacritic#List_of_diacritics_in_Unicode">accents and other diacritics</a>. For example, a (U+0061) followed by a combining grave accent (U+0300) is displayed like à (U+00E0) which is 1 column wide. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize">string.normalize()</a> composes/decomposes those.</p><p>Other examples include <a href="https://en.wikipedia.org/wiki/Variation_Selectors_%28Unicode_block%29">variation selectors</a>: # (U+0023) succeeded by the emoji variation (U+FE0F) produces a hashtag emoji#️. Or <a href="https://en.wikipedia.org/wiki/Regional_indicator_symbol">flags</a>: 🇪 (U+1F1EA) and 🇺 (U+1F1FA) result in the EU flag 🇪🇺.</p><p><a href="https://www.unicode.org/emoji/charts/full-emoji-modifiers.html">Emoji modifiers</a> behave similarly. For instance, 👩 (woman, U+1F469) followed by medium skin tone (U+1F3FD), <a href="https://en.wikipedia.org/wiki/Zero-width_joiner">zero-width joiner</a> (U+200D) and 🔬(microscope, U+1F52C) is shown as 👩🏽‍🔬 (woman scientist, medium skin tone), 2 columns wide.</p><figure><img alt="à = a + ̀ and#️ = # + VS16 and  🇪🇺 = 🇪 + 🇺 and 👩🏽‍🔬 = 👩 + 🏽 + ZWJ + 🔬" src="https://cdn-images-1.medium.com/max/1024/1*-kQ0AbP5cI2GDSuTQwfOGg.png" /></figure><p>A few code points are even invisible. Among many purposes (even <a href="https://unicode-explorer.com/b/1D100#1D173">music notation</a>! 🎷), those are intended to join or separate characters, symbols or words (<a href="https://en.wikipedia.org/wiki/Zero-width_space">zero-width space</a> U+200B, <a href="https://en.wikipedia.org/wiki/Word_joiner">word joiner</a> U+2060) and set text direction (<a href="https://en.wikipedia.org/wiki/Left-to-right_mark">left-to-right mark</a> U+200E, <a href="https://en.wikipedia.org/wiki/Right-to-left_mark">right-to-left mark</a> U+200F).</p><p>Finally, <a href="https://en.wikipedia.org/wiki/Control_character">control characters</a> don’t have any width because they are not meant to be printed. Instead, they modify terminal parameters such as <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences">cursor position</a>, scrolling, <a href="https://en.wikipedia.org/wiki/Shift_Out_and_Shift_In_characters">character set</a>, <a href="https://en.wikipedia.org/wiki/Acknowledgement_(data_networks)">communication</a>, <a href="https://en.wikipedia.org/wiki/End-of-Text_character">message structure</a>, etc. <a href="https://en.wikipedia.org/wiki/Bell_character">One of them</a> even emits sounds 🎤. They are divided into several categories:</p><ul><li><a href="https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_controls">C0 control characters</a> (U+0000 to U+001F) which are part of ASCII. Those are the oldest ones, with some <a href="https://en.wikipedia.org/wiki/Baudot_code">dating back to 1870</a> 🚂! They include <a href="https://en.wikipedia.org/wiki/Newline#Representation">line feed</a>, <a href="https://en.wikipedia.org/wiki/Null_character">null</a> and <a href="https://en.wikipedia.org/wiki/C0_and_C1_control_codes#BS">backspace</a>. Some of them can be represented using backslash sequences such as \n, \0 or \b.</li><li><a href="https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_controls">C1 control characters</a> (U+0080 to U+009F) which are rarely used.</li><li><a href="https://en.wikipedia.org/wiki/Unicode_control_characters">Other code points</a> such as <a href="https://en.wikipedia.org/wiki/Tags_(Unicode_block)">language tags</a>.</li><li><a href="https://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape sequences</a>. Those do not have any Unicode code points. They are represented using sequences that start with \e. The most common ones <a href="https://en.wikipedia.org/wiki/ANSI_escape_code#Colors">change colors</a>, e.g. \e[31m sets the font’s color to red. But many more are available. Several modules simplify <a href="https://github.com/chalk/ansi-regex">detecting</a> or <a href="https://github.com/chalk/strip-ansi">stripping</a> them.</li></ul><p>With everything considered, manipulating a string’s width in terminals might seem daunting. Fortunately, a few packages help with <a href="https://github.com/sindresorhus/string-width">computing it</a> or <a href="https://github.com/chalk/slice-ansi">slicing</a>/<a href="https://github.com/sindresorhus/cli-truncate">truncating</a> a string to fit a specific amount of columns.</p><p>In most cases, the difference between the above units is straightforward. Choosing the right one can prevent some bugs, such as computing a string’s terminal width using string.length or matching an emoji string with a RegExp lacking the u flag.</p><p>That being said, their performance cost might vary. For example, converting a large string to/from binary can be slow. Also, JavaScript operations using code units tend to run slightly faster than the code points ones. This can lead to preferring a less accurate unit inside critical hot paths.</p><p>In a nutshell, each unit presents the same information to different targets: machines (bytes), developers at an implementation (code units) or abstract level (code points), and users (width).</p><h3>Go composable: Build apps faster like Lego</h3><figure><a href="https://bit.cloud"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*x2l8LRH1nbC1FQZUdt50RQ.jpeg" /></a></figure><p><a href="https://bit.cloud"><strong>Bit</strong></a> is an open-source tool for building apps in a modular and collaborative way. Go composable to ship faster, more consistently, and easily scale.</p><p><strong>→ </strong><a href="https://bit.dev">Learn more</a></p><p>Build apps, pages, user-experiences and UIs as standalone components. Use them to compose new apps and experiences faster. Bring any framework and tool into your workflow. Share, reuse, and collaborate to build together.</p><p>Help your team with:</p><p><strong>→ </strong><a href="https://blog.bitsrc.io/how-we-build-micro-front-ends-d3eeeac0acfc"><strong>Micro-Frontends</strong></a></p><p><strong>→ </strong><a href="https://blog.bitsrc.io/how-we-build-our-design-system-15713a1f1833"><strong>Design Systems</strong></a></p><p><strong>→ </strong><a href="https://bit.cloud/blog/how-to-reuse-react-components-across-your-projects-l4pz83f4"><strong>Code-Sharing and reuse</strong></a></p><p><strong>→ </strong><a href="https://www.youtube.com/watch?v=5wxyDLXRho4&amp;t=2041s"><strong>Monorepos</strong></a></p><h3>Learn more</h3><ul><li><a href="https://blog.bitsrc.io/how-we-build-micro-front-ends-d3eeeac0acfc">How We Build Micro Frontends</a></li><li><a href="https://blog.bitsrc.io/how-we-build-our-design-system-15713a1f1833">How we Build a Component Design System</a></li><li><a href="https://bit.cloud/blog/how-to-reuse-react-components-across-your-projects-l3bhezsg">How to reuse React components across your projects</a></li><li><a href="https://blog.bitsrc.io/5-ways-to-build-a-react-monorepo-a294b6c5b0ac">5 Ways to Build a React Monorepo</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ef2af3d222e6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/bitsrc/how-big-is-a-string-ef2af3d222e6">How big is a JavaScript string?</a> was originally published in <a href="https://medium.com/bitsrc">Bits and Pieces</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Execa 2 release — process execution for humans]]></title>
            <link>https://codeburst.io/execa-v2-20ffafeedfdf?source=rss-e92183ad8a22------2</link>
            <guid isPermaLink="false">https://medium.com/p/20ffafeedfdf</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[cross-platform]]></category>
            <category><![CDATA[tech]]></category>
            <dc:creator><![CDATA[ehmicky]]></dc:creator>
            <pubDate>Tue, 25 Jun 2019 11:32:21 GMT</pubDate>
            <atom:updated>2019-06-27T20:09:52.444Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<h3>Execa 2 release — process execution for humans</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/991/1*FY3sgvovX1rrVghujOibfA.png" /></figure><p>Today we are releasing a <a href="https://github.com/sindresorhus/execa/releases/tag/v2.0.0">new major version</a> of <a href="https://github.com/sindresorhus/execa">Execa</a>. This Node.js library enhances <a href="https://nodejs.org/api/child_process.html">child processes</a> with:</p><ul><li>Promises instead of callbacks</li><li>Execution of <a href="https://github.com/sindresorhus/execa#preferlocal">locally installed binaries</a></li><li>Better <a href="https://github.com/moxystudio/node-cross-spawn#why">cross-platform support</a>, including <a href="https://en.wikipedia.org/wiki/Shebang_(Unix)">shebangs</a></li><li><a href="https://github.com/sindresorhus/execa#cleanup">Cleanup</a> of child processes when their parent exits</li><li><a href="https://github.com/sindresorhus/execa#why">And more</a></li></ul><p>Thanks to <a href="https://medium.com/u/37166cebf99b">Sindre Sorhus</a>, <a href="https://medium.com/u/e92183ad8a22">ehmicky</a>, <a href="https://github.com/GMartigny">GMartigny</a>, <a href="https://github.com/BendingBender">BendingBender</a>, <a href="https://github.com/tomsotte">tomsotte</a>, <a href="https://medium.com/u/47995624ca75">Malik Ammar Faisal</a>, <a href="https://github.com/zokker13">zokker13</a>, <a href="https://github.com/stroncium">stroncium</a>, <a href="https://medium.com/u/1ed3ad25cad">Satya Rohith</a>, <a href="https://medium.com/u/7bdf0680ac3b">Brad Lemley</a>, <a href="https://github.com/coreyfarrell">coreyfarrell</a>, <a href="https://medium.com/u/9571e86502ed">Brandon Smith</a>, <a href="https://medium.com/u/1af7baa03775">Thai Pangsakulyanont</a> and <a href="https://github.com/papb">Pedro Augusto de Paula Barbosa</a>, the following features are now available:</p><ul><li><a href="#26ce">TypeScript support</a></li><li><a href="#7b7f">Interleaved stdout and stderr</a></li><li><a href="#1025">Shell mode updates</a></li><li><a href="#18d9">Changes to local binaries execution</a></li><li><a href="#37c2">Improved spawning of Node.js scripts</a></li><li><a href="#b43d">Graceful exit</a></li><li><a href="#3a6a">Process cancellation</a></li><li><a href="#f7b7">Enhanced errors</a></li><li><a href="#a935">Stricter exit codes</a></li><li><a href="#460f">Gulp plugin</a></li><li><a href="#bc42">And more updates and bug fixes</a></li></ul><h3>TypeScript</h3><p>We have added TypeScript declarations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RIOfImpJBtE0QUFi3MeSjg.png" /></figure><h3>Interleaved stdout and stderr</h3><p>Node.js returns a child process’s <a href="https://nodejs.org/api/child_process.html#child_process_subprocess_stdout">stdout</a> and <a href="https://nodejs.org/api/child_process.html#child_process_subprocess_stderr">stderr</a> separately. However, those streams are usually connected and intertwined in the console. We made it easy for you to retrieve their <a href="https://github.com/sindresorhus/execa#all-1">combined output</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VLSqF1jleTYLz3Agq3_mwA.png" /></figure><h3>Avoid the shell option</h3><p>While it has (very) few legitimate uses, the <a href="https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options">shell</a> option should be avoided.</p><p>Why? First, it encourages shell-specific syntax (Bash, cmd.exe) which won’t work on every OS. Almost every shell feature is available directly in Node.js.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_EWjyTk6VokvgHyDbGgB5w.png" /></figure><p>Second, it is much slower as it makes every command go through the shell interpreter.</p><p>Last but not least, it increases the risk of command injection:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yjkeU1_-Q7Si2VnNDBX6Lg.png" /></figure><p>As a consequence, we have removed execa.shell() and execa.shellSync() which were merely shortcuts to the shell option.</p><p>Furthermore, <a href="https://github.com/sindresorhus/execa#execacommandcommand-options">execa.command()</a> and <a href="https://github.com/sindresorhus/execa#execacommandsynccommand-options">execa.commandSync()</a> can now be used to specify the command and its arguments as a single string without the shell option. Nothing needs to be escaped/quoted except for significant spaces (with a backslash).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1qvZOXBmI_povu1cZlrIKg.png" /></figure><h3>Changes to local binaries execution</h3><p>The preferLocal option now defaults to false. If you are executing locally installed binaries, you’ll need to specify the preferLocal: true option.</p><h3>Improved spawning of Node.js scripts</h3><p>We have added <a href="https://github.com/sindresorhus/execa#execanodescriptpath-arguments-options">execa.node()</a> which (like <a href="https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options">child_process.fork()</a>) executes a Node.js script as a child process.</p><p>It uses the current Node version and options. This can be overridden using the <a href="https://github.com/sindresorhus/execa#nodepath-for-node-only">nodePath</a> and <a href="https://github.com/sindresorhus/execa#nodearguments-for-node-only">nodeOptions</a>flags.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Nzh8Sy2MdApIWfgijV22MA.png" /></figure><h3>Graceful exit</h3><p>Some processes handle the <a href="https://nodejs.org/api/process.html#process_signal_events">SIGTERM</a> signal in order to cleanup resources and exit gracefully. This might take a long time or even never finish. <a href="https://github.com/sindresorhus/execa#killsignal-options">childProcess.kill()</a> now sends a <a href="https://nodejs.org/api/process.html#process_signal_events">SIGKILL</a> signal after 5 seconds to prevent this. This can be configured using the <a href="https://github.com/sindresorhus/execa#optionsforcekillaftertimeout">forceKillAfterTimeout</a> option.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lL0fYKDR0GEyIQCjf_modA.png" /></figure><h3>Process cancellation</h3><p>Cancelling a child process execution is common, so we added <a href="https://github.com/sindresorhus/execa#cancel">support for it</a>. It behaves like <a href="https://github.com/sindresorhus/execa#killsignal-options">childProcess.kill()</a> but with better error messages and <a href="https://github.com/sindresorhus/execa#iscanceled">properties</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FZa13R5Wi1yY03j39qtNvg.png" /></figure><h3>Enhanced errors</h3><p>We have improved error messages and properties. Node.js child process errors contain less information, scattered over several events:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mSLOec_YgDjCNSFOU0YoRg.png" /></figure><p>Execa produces <a href="https://github.com/sindresorhus/execa#childprocessresult">better errors</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*teatpdpVkf2yIiFt2HWC2Q.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4HsUI6p3Fe8joicp8Dxq0Q.png" /></figure><h3>Stricter exit codes</h3><p>Previously, the exit code could either be a number or a string. That property was removed in favor of <a href="https://github.com/sindresorhus/execa#exitcode">exitCode</a> (a number) and <a href="https://github.com/sindresorhus/execa#exitcodename">exitCodeName</a> (a string).</p><h3>Gulp plugin</h3><p>Execute commands in Gulp.js with <a href="https://github.com/ehmicky/gulp-execa">Gulp Execa</a>. This thin wrapper around Execa adds Gulp-specific features related to verbosity, output, errors and streaming.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BKxH6mY-2X7ONGfq92gfZg.png" /></figure><h3>More breaking changes</h3><p>Node.js 6 support has been dropped.</p><p>The stripEof option was renamed to <a href="https://github.com/sindresorhus/execa#stripfinalnewline">stripFinalNewline</a> and the cmd property to <a href="https://github.com/sindresorhus/execa#command">command</a>.</p><p>execa.stdout() and execa.stderr() have been removed since you can directly use the <a href="https://github.com/sindresorhus/execa#stdout">stdout</a> and <a href="https://github.com/sindresorhus/execa#stderr">stderr</a> properties of the resolved value.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NyLBS5mAcUYvX-TMOh4DgQ.png" /></figure><h3>Other updates</h3><p>The <a href="https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options">windowsHide</a> option is now always true. This ensures that no window pops up on Windows.</p><p>The <a href="https://github.com/sindresorhus/execa#maxbuffer">maxBuffer</a> option default value has been increased from 10 MB to 100 MB.</p><p>Several bugs have also been fixed.</p><p>For more information, check the <a href="https://github.com/sindresorhus/execa/releases/tag/v2.0.0">full changelog</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/991/1*kVrgDuJpvcc0kzC-8yxBlA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=20ffafeedfdf" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/execa-v2-20ffafeedfdf">Execa 2 release — process execution for humans</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Node.js process errors are broken]]></title>
            <link>https://codeburst.io/node-js-process-errors-are-broken-193980f0a77b?source=rss-e92183ad8a22------2</link>
            <guid isPermaLink="false">https://medium.com/p/193980f0a77b</guid>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[promises]]></category>
            <category><![CDATA[monitoring]]></category>
            <category><![CDATA[logging]]></category>
            <dc:creator><![CDATA[ehmicky]]></dc:creator>
            <pubDate>Tue, 02 Apr 2019 13:26:58 GMT</pubDate>
            <atom:updated>2019-05-03T14:40:12.716Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HOf3A0_SJnWTLW-dsHMNYg.jpeg" /></figure><p>There’s something wrong with your code. At least, this is what the following warning seems to indicate:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lihFJzEiq2VbghOyhWf9qQ.png" /></figure><p>All the tests are passing but this ExperimentalWarning leaves you unsettled. What baffles you is that <a href="https://nodejs.org/api/globals.html#globals_queuemicrotask_callback">queueMicrotask()</a> is not directly used anywhere.</p><p><a href="https://nodejs.org/api/process.html#process_event_warning">Warnings</a> are harder to debug because they are not part of a program’s control flow. Instead, Node.js <a href="https://nodejs.org/api/process.html#process_event_warning">emits them</a> on the global process. This is also the case for <a href="https://nodejs.org/api/process.html#process_event_uncaughtexception">uncaught exceptions</a> and <a href="https://nodejs.org/api/process.html#process_event_unhandledrejection">mishandled</a> <a href="https://nodejs.org/api/process.html#process_event_rejectionhandled">promises</a>.</p><p>Ignoring those process errors is not an option as they usually point to a bug. However, the way they are reported by Node.js is not developer-friendly.</p><h3>✘ ️Problem 1: lack of context</h3><p>The issue above would be simple to solve if stack traces had been printed:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*usagiNHxt08rFjbGnjk3jg.png" /></figure><p>It would then be clear that the warning is caused by <a href="https://github.com/sinonjs/lolex">lolex</a>, a mocking library used in unit tests. A quick search on the GitHub issues would show the <a href="https://github.com/sinonjs/lolex/issues/232">root of the problem</a>.</p><p>Unfortunately, Node.js does not print stack traces with warnings.</p><p>Context is also missing from other process errors such as <a href="https://nodejs.org/api/process.html#process_event_rejectionhandled">rejectionHandled</a>. Those are fired when a promise has been handled too late. However, the error message does not show which line of code is to blame:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2BvuFkVHi57qQA_0oewsaw.png" /></figure><h3>✘ Problem 2: missing errors</h3><p>Promises resolved or rejected twice usually indicate a bug.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YcbjUUFXemU-c4NVa2O7cw.png" /></figure><p>In the code above, the promise will be resolved with the wrong value because it’s missing return statements:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8PUoE9uM2DWVuHAQ0D7Djw.png" /></figure><p>Node.js tracks those errors with the <a href="https://nodejs.org/api/process.html#process_event_multipleresolves">multipleResolves process event</a>. However, this event is silent by default, which means you would need to handle it yourself in each of your repositories.</p><p>This is not as simple at it seems. Since the event handler modifies global state, it should only be used in development when writing a library. It must also avoid triggering another process error itself — otherwise your application will crash with an infinite recursion.</p><h3>✘ Problem 3: false alarms</h3><p>Not all process errors indicate a bug.</p><p>Some <a href="https://nodejs.org/api/process.html#process_event_multipleresolves">multipleResolves events</a> can be <a href="https://github.com/nodejs/node/issues/24321">intentional</a>. Also, you might choose to ignore some deprecation warnings.</p><h3>✘ Problem 4: remote logging</h3><p>Node.js prints process errors on the console using an unstructured format. This is not ideal when redirecting logs to a dashboard like <a href="https://rollbar.com/">Rollbar</a> or <a href="https://sentry.io">Sentry</a>.</p><p>First it requires parsing the console output to distinguish process errors from regular logs like HTTP requests.</p><p>Then the process errors messages themselves need to be parsed in order to log their type (<em>is it an uncaught exception or a warning?</em>) and values (<em>which exception was thrown?</em>) in a structured way.</p><h3>✘ Problem 5: testing</h3><p>Test runners like <a href="https://github.com/avajs/ava">Ava</a>, <a href="https://jestjs.io/">Jest</a> or <a href="https://jasmine.github.io/">Jasmine</a> handle <a href="https://nodejs.org/api/process.html#process_event_uncaughtexception">uncaught exceptions</a> and <a href="https://nodejs.org/api/process.html#process_event_unhandledrejection">promises</a>. Unfortunately, if <a href="https://nodejs.org/api/process.html#process_event_warning">process warnings</a> are fired, your tests will still pass.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lihFJzEiq2VbghOyhWf9qQ.png" /></figure><p>Testing warnings can be hard since they are emitted globally — outside of the test that triggered them.</p><h3>Solution</h3><figure><a href="https://github.com/ehmicky/log-process-errors"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PweCAGFFclbYJSw8OCnVwg.png" /></a></figure><p>The <a href="https://github.com/ehmicky/log-process-errors">log-process-errors library</a> solves those problems. It turns Node.js behavior from:</p><figure><a href="https://github.com/ehmicky/log-process-errors"><img alt="" src="https://cdn-images-1.medium.com/max/636/1*hR0qqmtnl92tJXHwJ8GtIg.png" /></a></figure><p>To:</p><figure><a href="https://github.com/ehmicky/log-process-errors"><img alt="" src="https://cdn-images-1.medium.com/max/630/1*hFABrRLw9xe537GHUakwWg.png" /></a></figure><p>After <a href="https://github.com/ehmicky/log-process-errors#install">installing</a> log-process-errors it can be <a href="https://github.com/ehmicky/log-process-errors#usage">used</a> by using the <a href="https://nodejs.org/api/cli.html#cli_r_require_module">node -r CLI flag</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*spqCtvNGSP7b9wsEL3VNog.png" /></figure><p>or by calling it in JavaScript:</p><figure><a href="https://github.com/ehmicky/log-process-errors"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2OPblwWvHnTu1f0gHlji3g.png" /></a></figure><p>The log transport can be <a href="https://github.com/ehmicky/log-process-errors/blob/master/docs/API.md#log">customized</a>. For example to use <a href="https://github.com/winstonjs/winston">Winston</a>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PrLpz_L8kW_f-2iv0nthtw.png" /></figure><p>Specific process errors can be skipped:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Acsm5q-DPXcoPDbR_AoyQw.png" /></figure><p>It can also be used in testing. Ensuring no process errors are fired is as simple as:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tpCfOSHd22Y8Ab9hRBUheg.png" /></figure><p><a href="https://github.com/ehmicky/log-process-errors/blob/master/docs/API.md#testing">Most JavaScript test runners</a> are supported.</p><p>Check out the <a href="https://github.com/ehmicky/log-process-errors">GitHub repository</a> for the full list of <a href="https://github.com/ehmicky/log-process-errors#options">options</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=193980f0a77b" width="1" height="1" alt=""><hr><p><a href="https://codeburst.io/node-js-process-errors-are-broken-193980f0a77b">Node.js process errors are broken</a> was originally published in <a href="https://codeburst.io">codeburst</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>