<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pelle Wessman</title>
    <description>The latest articles on DEV Community by Pelle Wessman (@voxpelli).</description>
    <link>https://dev.to/voxpelli</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241027%2Faf48256c-31e2-49c3-b527-5eebf657ce17.png</url>
      <title>DEV Community: Pelle Wessman</title>
      <link>https://dev.to/voxpelli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/voxpelli"/>
    <language>en</language>
    <item>
      <title>TypeScript 5.0 for JavaScript devs</title>
      <dc:creator>Pelle Wessman</dc:creator>
      <pubDate>Mon, 20 Mar 2023 15:57:12 +0000</pubDate>
      <link>https://dev.to/voxpelli/typescript-50-for-javascript-devs-3661</link>
      <guid>https://dev.to/voxpelli/typescript-50-for-javascript-devs-3661</guid>
      <description>&lt;p&gt;The &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/"&gt;TypeScript 5.0&lt;/a&gt; release brings &lt;strong&gt;a good amount of news&lt;/strong&gt; for us who use it with JavaScript / JSDoc.&lt;/p&gt;

&lt;p&gt;This time around we get two whole new keywords, &lt;code&gt;@satisfies&lt;/code&gt; and &lt;code&gt;@overload&lt;/code&gt;, and they are a big step towards feature parity with TypeScript itself.&lt;/p&gt;

&lt;p&gt;On top of this we get some other goodies as well, which I'll go through in the end of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;satisfies&lt;/code&gt; – non-lossy type validation
&lt;/h2&gt;

&lt;p&gt;When we have a piece of &lt;code&gt;data&lt;/code&gt; that we want to ensure is of type &lt;code&gt;Foo&lt;/code&gt; we do eg:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {Foo} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;abc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;Foo&lt;/code&gt; has a property &lt;code&gt;.type&lt;/code&gt; that is &lt;code&gt;'car'|'bike'&lt;/code&gt;, then we will not know which of the two &lt;code&gt;abc&lt;/code&gt; will have, no matter if we know that &lt;code&gt;data.type&lt;/code&gt; was &lt;code&gt;bike&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can now instead write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @satisfies {Foo} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;abc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will ensure that we simply ensure that &lt;code&gt;abc&lt;/code&gt; satisfies the type of &lt;code&gt;Foo&lt;/code&gt;, it will not make us lose any of the details of &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For more info, check out &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#satisfies-support-in-jsdoc"&gt;the announcement post at the TypeScript blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;@overload&lt;/code&gt; – enabling function overloading in JS
&lt;/h2&gt;

&lt;p&gt;The announcement post at the TypeScript blog summarised this one well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each JSDoc comment with an &lt;code&gt;@overload&lt;/code&gt; tag is treated as a distinct overload for the following function declaration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, we can now easily specify when eg. a second argument can or can not be specified to a function.&lt;/p&gt;

&lt;p&gt;This is something that has been possible in TS for a long long time, now finally we can do it in JS as well. Great for those few times where it can make the code much more readable.&lt;/p&gt;

&lt;p&gt;For more info, check out &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#overload-support-in-jsdoc"&gt;the announcement post at the TypeScript blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other notable news
&lt;/h2&gt;

&lt;p&gt;The new &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#allowimportingtsextensions"&gt;&lt;code&gt;--allowImportingTsExtensions&lt;/code&gt;&lt;/a&gt; is great for when we need to specify a file extension when importing (I'm looking at you ESM) and you need to import a &lt;code&gt;.d.ts&lt;/code&gt; file (a useful thing when it gets too verbose or hard to write your types in JSDoc). Only allowed when &lt;code&gt;--noEmit&lt;/code&gt; or &lt;code&gt;--emitDeclarationOnly&lt;/code&gt; is enabled, which is true for all JS projects.&lt;/p&gt;

&lt;p&gt;Also: Support for &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#supporting-multiple-configuration-files-in-extends"&gt;multiple files in &lt;code&gt;extends&lt;/code&gt;&lt;/a&gt; can be helpful, especially when sharing a common config with TS projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I'm in love with &lt;code&gt;@satisfies&lt;/code&gt; and will use it plenty. I will probably also add &lt;code&gt;--allowImportingTsExtensions&lt;/code&gt; to a future version of my shared &lt;a href="https://github.com/voxpelli/tsconfig"&gt;&lt;code&gt;@voxpelli/tsconfig&lt;/code&gt;&lt;/a&gt; configuration + may perhaps restructure it a bit eventually to enable use with multiple &lt;code&gt;extends&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Head on over to &lt;a href="https://github.com/voxpelli/types-in-js"&gt;voxpelli/types-in-js&lt;/a&gt; and read more about using types in JS and share &lt;a href="https://github.com/voxpelli/types-in-js/discussions/20"&gt;your favorite additions&lt;/a&gt; lately 🙏&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>jsdoc</category>
      <category>news</category>
    </item>
    <item>
      <title>installed-check 5.0.0: Robustness galore</title>
      <dc:creator>Pelle Wessman</dc:creator>
      <pubDate>Sun, 14 Nov 2021 18:56:43 +0000</pubDate>
      <link>https://dev.to/voxpelli/installed-check-500-robustness-galore-2gjc</link>
      <guid>https://dev.to/voxpelli/installed-check-500-robustness-galore-2gjc</guid>
      <description>&lt;p&gt;A few seconds ago I shipped &lt;a href="https://github.com/voxpelli/node-installed-check/releases/tag/v5.0.0"&gt;version 5.0.0&lt;/a&gt; of &lt;a href="https://github.com/voxpelli/node-installed-check"&gt;&lt;code&gt;installed-check&lt;/code&gt;&lt;/a&gt; CLI and its companion &lt;a href="(https://github.com/voxpelli/node-installed-check-core/releases/tag/v5.0.0)"&gt;&lt;code&gt;installed-check-core&lt;/code&gt;&lt;/a&gt; module, delivering a more robust, more well tested and all-round better tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what does &lt;code&gt;installed-check&lt;/code&gt; do?
&lt;/h2&gt;

&lt;p&gt;It check's that your project's &lt;code&gt;engine.node&lt;/code&gt; is equal to, or a subset of, of that of your dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new?
&lt;/h2&gt;

&lt;p&gt;Replaced old &lt;a href="https://github.com/voxpelli/semver-set"&gt;&lt;code&gt;@voxpelli/semver-set&lt;/code&gt;&lt;/a&gt;, a fork of another project, with a brand new rewritten from scratch &lt;a href="https://github.com/voxpelli/semver-set/releases/tag/v3.0.0"&gt;3.x version of it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;@voxpelli/semver-set&lt;/code&gt; is well tested and hardened – all to ensure better intersection calculations of semantic versioning ranges – essential for calculating &lt;code&gt;engine.node&lt;/code&gt; compatibility. Eg. &lt;code&gt;^10.17.0 || &amp;gt;=12.0.0&lt;/code&gt; and &lt;code&gt;&amp;gt;=8.0.0&lt;/code&gt; now properly calculates.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;@voxpelli/semver-set&lt;/code&gt; also fixes an issue with the license of the former module. Since its a full rewrite I could pick a license myself, so it's now &lt;a href="https://github.com/voxpelli/semver-set/blob/main/LICENSE"&gt;under MIT&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Other news for the &lt;code&gt;installed-check&lt;/code&gt; modules includes a swap from the non-standard &lt;a href="https://github.com/joyent/node-verror"&gt;&lt;code&gt;VError&lt;/code&gt;&lt;/a&gt; to my &lt;a href="https://github.com/voxpelli/pony-cause#errorwithcause-creating-an-error-with-a-cause"&gt;&lt;code&gt;pony-cause&lt;/code&gt; pony-fill&lt;/a&gt; for the now standardised &lt;a href="https://v8.dev/features/error-cause"&gt;Error Causes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;installed-check&lt;/code&gt; in general now also has much more tests and have fixes for issues those tests uncovered, making for a much more robust experience going forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I get started?
&lt;/h2&gt;

&lt;p&gt;Add it to your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; installed-check@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add it (early) to the tests in your &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"installed-check"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A more full-featured example can be found in eg. my &lt;a href="https://github.com/voxpelli/list-installed/blob/a905a08d9e0bdb5a6da9f6a449a528eadc91cbda/package.json#L17"&gt;&lt;code&gt;list-installed&lt;/code&gt;&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;Happy compatibility checking! 🥳&lt;/p&gt;

</description>
      <category>node</category>
      <category>showdev</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
    <item>
      <title>TypeScript 4.5 adds JSDoc template tag defaults</title>
      <dc:creator>Pelle Wessman</dc:creator>
      <pubDate>Tue, 09 Nov 2021 17:50:32 +0000</pubDate>
      <link>https://dev.to/voxpelli/typescript-45-adds-jsdoc-template-tag-defaults-290g</link>
      <guid>https://dev.to/voxpelli/typescript-45-adds-jsdoc-template-tag-defaults-290g</guid>
      <description>&lt;p&gt;TypeScript 4.5, which is currently a release candidate, includes an exciting new feature for us &lt;a href="https://github.com/voxpelli/types-in-js" rel="noopener noreferrer"&gt;types in js&lt;/a&gt; JSDoc users:&lt;/p&gt;

&lt;p&gt;Defaults for template tags, &lt;a href="https://github.com/microsoft/TypeScript/pull/45483" rel="noopener noreferrer"&gt;microsoft/TypeScript#45483&lt;/a&gt;: &lt;code&gt;@template [T=string]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I found this through when looking for a way to void &lt;code&gt;T&lt;/code&gt; defaulting to &lt;code&gt;any&lt;/code&gt; when no value was given in this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @template [T=undefined] */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorWithCause&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * @param {string} message
   * @param {{ cause?: T }} [options]
   */&lt;/span&gt;
  &lt;span class="nf"&gt;constructor &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cause&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/** @type {T} */&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it gets set to &lt;code&gt;undefined&lt;/code&gt; when no value is provied and my &lt;a href="https://github.com/plantain-00/type-coverage" rel="noopener noreferrer"&gt;&lt;code&gt;type-coverage&lt;/code&gt;&lt;/a&gt; got closer to 100%.&lt;/p&gt;

&lt;p&gt;And it properly compiles to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorWithCause&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cause&lt;/span&gt; &lt;span class="p"&gt;}?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will push this new code to my &lt;a href="https://github.com/voxpelli/pony-cause" rel="noopener noreferrer"&gt;&lt;code&gt;pony-cause&lt;/code&gt;&lt;/a&gt; module very soon, just wanted to write this up first 🥳 &lt;/p&gt;

&lt;p&gt;Originally posted &lt;a href="https://github.com/voxpelli/types-in-js/discussions/17" rel="noopener noreferrer"&gt;as a discussion&lt;/a&gt; in the &lt;a href="https://github.com/voxpelli/types-in-js" rel="noopener noreferrer"&gt;types-in-js&lt;/a&gt; community:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1458128109836935168-226" src="https://platform.twitter.com/embed/Tweet.html?id=1458128109836935168"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1458128109836935168-226');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1458128109836935168&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>jsdoc</category>
    </item>
    <item>
      <title>Open source and taxes: A Swedish perspective</title>
      <dc:creator>Pelle Wessman</dc:creator>
      <pubDate>Wed, 29 Sep 2021 17:27:58 +0000</pubDate>
      <link>https://dev.to/voxpelli/open-source-and-taxes-a-swedish-perspective-gkn</link>
      <guid>https://dev.to/voxpelli/open-source-and-taxes-a-swedish-perspective-gkn</guid>
      <description>&lt;p&gt;Open source and taxes seems to be a weird beast in at least Sweden and perhaps elsewhere as well. Let's dig into how it seems to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basics
&lt;/h2&gt;

&lt;p&gt;If I receive a donation for an open source project of mine, then the Swedish tax authority says that I should tax that as income as there's &lt;strong&gt;a reasonable expectation of a service in return&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If I as a company decides to donate to an open source project, then that donation is not tax deductible as it is a &lt;strong&gt;voluntary&lt;/strong&gt; donation and hence &lt;strong&gt;not required&lt;/strong&gt; for my company to &lt;strong&gt;acquire&lt;/strong&gt; its income.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result:&lt;/strong&gt; Both my company &lt;em&gt;and&lt;/em&gt; the receiver has to pay taxes on the same money, making a taxes on taxes kind of situation – expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lets do the math: Best case scenario
&lt;/h2&gt;

&lt;p&gt;If...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The giver is a limited company ("aktiebolag", the company itself pays taxes on its profits)&lt;/li&gt;
&lt;li&gt;The receiver is not paying the Swedish high income tax&lt;/li&gt;
&lt;li&gt;The receiver lives in the municipality with the lowest local taxes&lt;/li&gt;
&lt;li&gt;The receiver declares the income as from a hobby ("hobbyinkomst")&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...then, what is left of $100...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After the company has paid taxes: &lt;strong&gt;$100&lt;/strong&gt; * (100% - 20.6%) = $79.6&lt;/li&gt;
&lt;li&gt;After the receiver has paid "egenavgifter": $79.6 * (100% - 29%) = $79.6 * 71% ≈ $56.52&lt;/li&gt;
&lt;li&gt;After the receiver has paid income tax: $56.52 * (100% - 29.18%) = $56.52 * 70.82% ≈ &lt;strong&gt;$40.03&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...is just around $40&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;40%&lt;/strong&gt; of the money that the company giver originally used for the donation actually got received by the recipient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lets do the math: Worse case
&lt;/h2&gt;

&lt;p&gt;If...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The giver is a personal company ("enskild firma", the owner pays taxes on its profits)&lt;/li&gt;
&lt;li&gt;The owner of the giving company as well as the receiver, both earns enough money to pay high income taxes (an additional 20%)&lt;/li&gt;
&lt;li&gt;Both lives in a municipality with average local taxes&lt;/li&gt;
&lt;li&gt;The receiver still declares the income as from a hobby ("hobbyinkomst")&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...then, what is left of $100...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After the company has paid "egenavgifter": &lt;strong&gt;$100&lt;/strong&gt; * (100% - 29%) = $71&lt;/li&gt;
&lt;li&gt;After the company has paid taxes: $71 * (100% - 32.27% - 20%) = $71 * 47.73% ≈ $33.89&lt;/li&gt;
&lt;li&gt;For the receiver, after paying "egenavgifter": $33.89 * (100% - 29%) = $33.89 * 71% ≈ $24.06&lt;/li&gt;
&lt;li&gt;For the receiver, after paying tax: $24.06 * (100% - 32.27% - 20%) = $24.06 * 47.73% ≈ &lt;strong&gt;$11.48&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...is just around $11.50&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11.5%&lt;/strong&gt; of the money that the company giver originally used for the donation actually got received by the recipient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lets do the math: The absolute worst case – circular/Reciprocal donations
&lt;/h2&gt;

&lt;p&gt;Many of the donations in the open source space moves around within that space, being used to fund the receiver's donations to others. Many maintainers who receive also give donations, &lt;a href="https://twitter.com/voxpelli/status/1356179037606076418"&gt;even reciprocally&lt;/a&gt; at times, and due to the above this can really cause issues with double taxation or more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When money given can't be deducted from the ones received, then every step more and more money gets lost.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's why companies can deduct their costs from their income, as the intention of the tax system is to only tax the profits a company make, not the full revenue they have.&lt;/p&gt;

&lt;p&gt;If 60% gets lost per step, as in the best current scenario above, then out of $100 000 donated this much will be received after each step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;$40 000&lt;/li&gt;
&lt;li&gt;$16 000&lt;/li&gt;
&lt;li&gt;$6400&lt;/li&gt;
&lt;li&gt;$2560&lt;/li&gt;
&lt;li&gt;$1024&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After five steps &lt;strong&gt;99%&lt;/strong&gt; of the money has &lt;strong&gt;evaporated&lt;/strong&gt; away, making &lt;strong&gt;reciprocal&lt;/strong&gt; donations or &lt;strong&gt;any kind of trickle-down effects&lt;/strong&gt; on eg. sub-dependencies essentially &lt;strong&gt;impossible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Only if donations given can be deducted from donations received can any kind of reciprocal donations or trickle-down effects be achieved.&lt;/p&gt;

&lt;p&gt;Up until then, the only feasible strategy at all is to either be a receiver or to be a giver, never both. Though that doesn't rhyme with the open source spirit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lets do the math: How it should be, deductible donations
&lt;/h2&gt;

&lt;p&gt;Then, what is left of $100...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For the company: Deductible, no taxes paid, &lt;strong&gt;all $100 is forwarded&lt;/strong&gt; to the receiver&lt;/li&gt;
&lt;li&gt;For the receiver, after paying "egenavgifter": $100 * (100% - 29%) = $71&lt;/li&gt;
&lt;li&gt;Depending on whether high income tax is paid or not:

&lt;ol&gt;
&lt;li&gt;After only paying local municipal taxes: $71 * (100% - 32.27%) = $71 * 67.73% ≈ &lt;strong&gt;$48.09&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;After paying both local municipal taxes and state high income taxes: $71 * (100% - 32.27% - 20%) = $71 * 47.73% ≈ &lt;strong&gt;$33.89&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...is roughly $48 rather than $40 and $34 rather than $11.50&lt;/p&gt;

&lt;p&gt;In other words: A receiver paying high income taxes would get almost &lt;strong&gt;three times&lt;/strong&gt; the money compared to the current worse scenario. A receiver who doesn't pay high income taxes would get at least &lt;strong&gt;20%&lt;/strong&gt; more than the current best case scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  But how to approach donations here and now?
&lt;/h2&gt;

&lt;p&gt;Currently the better approach for the "giver company" is to buy something from the receiver which could be &lt;strong&gt;required&lt;/strong&gt; for the "giver company" to &lt;strong&gt;acquire&lt;/strong&gt; its income and therefore become a deductible expense.&lt;/p&gt;

&lt;p&gt;Some examples of that are: Sign a support agreement, buy consulting hours, sign an SLA-style guarantee from something like &lt;a href="https://tidelift.com/"&gt;Tidelift&lt;/a&gt; or perhaps ensure you get enough promotion back to essentially make it classify as an ad for you.&lt;/p&gt;

&lt;p&gt;Tidelift is also a current fix for the challenge to the trickle-down effect, as they disperse money received to the entire dependency trees, not just to the topmost rockstar projects a project depends upon, but their dependencies and the dependencies of those and so on.&lt;/p&gt;

&lt;p&gt;Though: &lt;strong&gt;I'm not a tax expert, so I can't give any here advice.&lt;/strong&gt; These are purely some thoughts and ramblings of mine on a topic that I think many ignore, based on the response I got when I asked the Swedish tax authority a question on this.&lt;/p&gt;

&lt;p&gt;I find it okay that received open source donations is classified and taxes as income, but then the reverse also have to be true – it then has to be a tax deductible expense for the giving company as well.&lt;/p&gt;

&lt;p&gt;Currently it seems like the Swedish tax authority wants to both have the cake and eat it, taxing both, which isn't fair and isn't along the intent of the tax system.&lt;/p&gt;

&lt;p&gt;I myself am available at &lt;a href="https://tidelift.com/subscription/pkg/npm-connect-pg-simple?utm_source=npm-connect-pg-simple&amp;amp;utm_medium=referral&amp;amp;utm_campaign=enterprise"&gt;Tidelift&lt;/a&gt; for companies who wants to support me and I'm available at &lt;a href="https://github.com/sponsors/voxpelli"&gt;GitHub Sponsors&lt;/a&gt; for people who want to sponsor me (as well as companies if it makes sense for them to give there, maybe it is tax deductible in some countries?).&lt;/p&gt;

&lt;p&gt;How does it work in your countries? Any thoughts on my rumblings? Please leave a comment!&lt;/p&gt;

&lt;p&gt;Originally published in an &lt;a href="https://www.linkedin.com/pulse/open-source-taxes-swedish-perspective-pelle-wessman/?trackingId=CR0qfq9lSfOXcNseEYYPYg%3D%3D"&gt;earlier version at LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>business</category>
      <category>taxes</category>
      <category>sweden</category>
    </item>
    <item>
      <title>Pony Cause 1.0: Error Causes</title>
      <dc:creator>Pelle Wessman</dc:creator>
      <pubDate>Mon, 20 Sep 2021 15:35:53 +0000</pubDate>
      <link>https://dev.to/voxpelli/pony-cause-1-0-error-causes-2l2o</link>
      <guid>https://dev.to/voxpelli/pony-cause-1-0-error-causes-2l2o</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/voxpelli/pony-cause"&gt;Pony Cause&lt;/a&gt; is my new &lt;a href="https://ponyfill.com/"&gt;ponyfill&lt;/a&gt; and helpers for the new &lt;a href="https://github.com/tc39/proposal-error-cause"&gt;Error Cause&lt;/a&gt; tc39 &lt;a href="https://github.com/tc39/proposals"&gt;proposal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The ponyfill as well as the proposal aims to replace VError / NError with a standard mechanism for wrapping errors and improving error contexts.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it wrap errors?
&lt;/h2&gt;

&lt;p&gt;The Error Cause proposals add a second argument to the &lt;code&gt;Error&lt;/code&gt; constructor.&lt;/p&gt;

&lt;p&gt;The new argument is a plain object with so far &lt;code&gt;cause&lt;/code&gt; as its only defined key.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cause&lt;/code&gt; is intended to be the value of a caught error.&lt;/p&gt;

&lt;p&gt;That way &lt;code&gt;cause&lt;/code&gt; enables an &lt;code&gt;Error&lt;/code&gt; of a higher level to reference one of a lower level error, adding context without sacrificing detail.&lt;/p&gt;

&lt;p&gt;An example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ABC123 exception encountered in database "Foo"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to save blog post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Failed to save blog post&lt;/code&gt; message provides a higher level context, it tells us &lt;em&gt;what&lt;/em&gt; has happened, it tells us the &lt;em&gt;impact&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The inner &lt;code&gt;ABC123 exception encountered in database "Foo"&lt;/code&gt; message tells us &lt;em&gt;why&lt;/em&gt; this happened, it tells us the &lt;em&gt;cause&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  So why wrap errors?
&lt;/h2&gt;

&lt;p&gt;In classic JavaScript it has been an either or – either getting to know the &lt;em&gt;impact&lt;/em&gt; or the &lt;em&gt;cause&lt;/em&gt;, but never both &lt;code&gt;Error&lt;/code&gt;:s (unless one has logged them separately or have used VError / NError).&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;impact&lt;/em&gt; and &lt;em&gt;cause&lt;/em&gt; provides the most value when paired with the other, and that's what &lt;a href="https://github.com/tc39/proposal-error-cause"&gt;Error Cause&lt;/a&gt; enables and what &lt;a href="https://github.com/voxpelli/pony-cause"&gt;Pony Cause is&lt;/a&gt; is a &lt;a href="https://ponyfill.com/"&gt;ponyfill&lt;/a&gt; for and provides helpers for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does &lt;code&gt;pony-cause&lt;/code&gt; add?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/voxpelli/pony-cause"&gt;Pony Cause is&lt;/a&gt; consist of two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;a href="https://ponyfill.com/"&gt;ponyfill&lt;/a&gt; in the shape of a &lt;code&gt;ErrorWithCause&lt;/code&gt; class which mimics the new cause-supporting &lt;code&gt;Error&lt;/code&gt; class.&lt;/li&gt;
&lt;li&gt;A couple of &lt;code&gt;VError&lt;/code&gt;-inspired helpers for working with error causes, ensuring that the added context becomes actually useful. These helpers also supports &lt;code&gt;VError&lt;/code&gt; style causes on top of the new error causes, enabling a smooth transition from one to the other.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Which helpers does it add?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/voxpelli/pony-cause#findcausebyreference-finding-a-specific-type-of-error-in-the-cause-chain"&gt;&lt;code&gt;findCauseByReference(err, Error)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/voxpelli/pony-cause#geterrorcause-getting-the-cause-of-an-error"&gt;&lt;code&gt;getErrorCause(err)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/voxpelli/pony-cause#stackwithcauses-getting-full-stack-trace-for-error--all-causes"&gt;&lt;code&gt;stackWithCauses(err)&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Anything else I should know?
&lt;/h2&gt;

&lt;p&gt;Pony Cause is written in JS, typed with JSDoc, validated with TypeScript and have .d.ts / .d.ts.map generated by TypeScript. In other words: &lt;code&gt;100% typed&lt;/code&gt; in true &lt;a href="https://github.com/voxpelli/types-in-js"&gt;Types in JS&lt;/a&gt; spirit.&lt;/p&gt;

&lt;p&gt;It's a CommonJS module rather than ESM, to maximise compatibility here and now, as that's the point of a ponyfill.&lt;/p&gt;

&lt;p&gt;It's licensed under the &lt;a href="https://choosealicense.com/licenses/0bsd/"&gt;&lt;code&gt;0BSD&lt;/code&gt;&lt;/a&gt; license, a BSD/MIT-style license with the requirement for attribution removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Will there be native support?
&lt;/h2&gt;

&lt;p&gt;Yes, it's recently been implemented in &lt;a href="https://caniuse.com/mdn-javascript_builtins_error_cause"&gt;all three major browsers&lt;/a&gt; and V8 &lt;a href="https://v8.dev/blog/v8-release-93#error-cause"&gt;shipped native support&lt;/a&gt; a bit over a month ago with eg. &lt;a href="https://nodejs.org/en/blog/release/v16.9.0/#error-cause"&gt;Node.js v16.9.0&lt;/a&gt; and &lt;a href="https://deno.com/blog/v1.13#error-cause"&gt;Deno v1.13&lt;/a&gt; both having already shipped with that version of V8.&lt;/p&gt;

&lt;p&gt;Though you still need a ponyfill or polyfill if you want to support older browsers or older Node.js versions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/voxpelli/pony-cause"&gt;Pony Cause&lt;/a&gt; also provides helpers which are useful no matter if you're using it with old environments or not it is a module that your toolbox needs 😉&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>typescript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How to use TypeScript 3.7 to generate declarations from JSDoc</title>
      <dc:creator>Pelle Wessman</dc:creator>
      <pubDate>Mon, 07 Oct 2019 15:42:27 +0000</pubDate>
      <link>https://dev.to/voxpelli/how-to-use-typescript-3-7-to-generate-declarations-from-jsdoc-a95</link>
      <guid>https://dev.to/voxpelli/how-to-use-typescript-3-7-to-generate-declarations-from-jsdoc-a95</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;While TypeScript for long has supported validating the types in ones javascript files, even reading ones JSDoc-comments, it hasn’t really worked that well for those who in turn wanted to use ones code.&lt;/p&gt;

&lt;p&gt;By default TypeScript doesn’t read the JSDoc of any dependencies. One have had to set &lt;code&gt;maxNodeModuleJsDepth&lt;/code&gt; to a higher value, which hasn’t been without some issues.&lt;/p&gt;

&lt;p&gt;Issues range from having the required depth change over time due to nested modules in &lt;code&gt;node\_modules&lt;/code&gt;, making it hard to guarantee that types has been read, and picking up weird JSDoc comments from other packages – JSDoc comments that has never been tested for correctness.&lt;/p&gt;

&lt;p&gt;So, what about &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/"&gt;TypeScript 3.7&lt;/a&gt;? It &lt;a href="https://github.com/microsoft/TypeScript/pull/32372"&gt;introduces a way&lt;/a&gt; to create a type definition file from your JSDoc definitions. I decided to try it out on a project.&lt;/p&gt;

&lt;h2&gt;
  
  
  How-to
&lt;/h2&gt;

&lt;p&gt;This is how I added it to a project which publishes a single &lt;code&gt;index.js&lt;/code&gt; file, &lt;a href="https://github.com/voxpelli/node-bunyan-adaptor"&gt;bunyan-adaptor&lt;/a&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a new tsconfig file
&lt;/h3&gt;

&lt;p&gt;Add a new &lt;code&gt;tsconfig.json&lt;/code&gt; with the sole purpose of generating your declaration. This way you can avoid getting declarations generated for tests and such.&lt;/p&gt;

&lt;p&gt;I added a &lt;code&gt;declaration.tsconfig.json&lt;/code&gt; containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "extends": "./tsconfig",
  "exclude": [
    "test/**/*.js"
  ],
  "compilerOptions": {
    "declaration": true,
    "noEmit": false,
    "emitDeclarationOnly": true
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Add a npm script for generating the declaration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"declaration:build": "rm -f index.d.ts &amp;amp;&amp;amp; tsc -p declaration.tsconfig.json",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. (optional) Add a npm script for ensuring your declaration has been committed
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"declaration:check": "git diff --exit-code -- index.d.ts",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. (optional) Add a prepublishOnly npm script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"prepublishOnly": "npm run --silent declaration:build &amp;amp;&amp;amp; npm run --silent declaration:check",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or simpler, with the use of &lt;a href="https://github.com/mysticatea/npm-run-all"&gt;npm-run-all&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"prepublishOnly": "run-s declaration:*",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Profit / Party / 🦄 / 🤳
&lt;/h3&gt;

&lt;p&gt;However you want to celebrate: This is the moment.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;npm run declaration:build&lt;/code&gt;, commit the resulting &lt;code&gt;index.d.ts&lt;/code&gt; and publish your module!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Visual Studio Code could/will complain about your generated type declaration unless you tell it to use TypeScript 3.7.&lt;/p&gt;

&lt;p&gt;Tell it by running the &lt;code&gt;TypeScript: Select TypeScript Version...&lt;/code&gt; command when in eg. the type declaration file.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>jsdoc</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>3 tricks to better handle npm modules</title>
      <dc:creator>Pelle Wessman</dc:creator>
      <pubDate>Tue, 05 Jul 2016 17:10:00 +0000</pubDate>
      <link>https://dev.to/voxpelli/3-tricks-to-better-handle-npm-modules-20g9</link>
      <guid>https://dev.to/voxpelli/3-tricks-to-better-handle-npm-modules-20g9</guid>
      <description>&lt;p&gt;Developing with npm modules isn’t just installing modules and then updating them. In a team environment you might not even know when a new module should be installed or when its version requirement has changed. This can cause lots of weird unexpected behaviors when the installed modules doesn’t match the expectations of the app – and that annoys and is a waste of time.&lt;/p&gt;

&lt;p&gt;Here I’ll give you three tricks to avoid that. Tricks which I’ve begun to use over the years and which we’re currently using at my latest project, the development of the new sites for &lt;a href="http://www.sydsvenskan.se/"&gt;Sydsvenskan&lt;/a&gt; and &lt;a href="http://www.hd.se/"&gt;HD&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Verify installed versions against package.json
&lt;/h2&gt;

&lt;p&gt;When rapidly developing a new site, establishing the basic features etc, new modules gets added quite a lot. Often after a rebase one realize that one is missing a module after ones &lt;a href="http://nodemon.io/"&gt;nodemon&lt;/a&gt; process suddenly crash with some unexpected weird error.&lt;/p&gt;

&lt;p&gt;I created &lt;a href="https://github.com/voxpelli/node-installed-check"&gt;installed-check&lt;/a&gt; to solve that. To have a script I could run to check if my installed modules still fulfilled the requirements set out by the package.json or whether it was time to install some more. All checked locally, without any slow network lookups or such.&lt;/p&gt;

&lt;p&gt;If any module were missing or were outside the version requirements it would exit with an error.&lt;/p&gt;

&lt;p&gt;I then hooked that script into my &lt;code&gt;npm test&lt;/code&gt; script and into &lt;a href="https://github.com/typicode/husky"&gt;husky&lt;/a&gt; (at &lt;code&gt;postapplypatch&lt;/code&gt; and &lt;code&gt;postmerge&lt;/code&gt;) so that whenever I pulled down new code or ran my tests it verified that my installation was up to date.&lt;/p&gt;

&lt;p&gt;With that in place everyone in the team could stop worry about whether they were missing a module locally and we could all stop wasting time debugging issues that were due to changes in the package.json requirements. Happy developers!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Verify that package.json is in sync with actual module usage
&lt;/h2&gt;

&lt;p&gt;While tests may pass just fine locally, if one doesn’t commit all the dependency requirements then it’s hard for them to pass anywhere else.&lt;/p&gt;

&lt;p&gt;Likewise refactored code may work just fine, but one may not have realized that a removed &lt;code&gt;require()&lt;/code&gt; was the very last one for a given module.&lt;/p&gt;

&lt;p&gt;Therefore I always run &lt;a href="https://github.com/maxogden/dependency-check"&gt;dependency-check&lt;/a&gt; (which I now co-maintain) in my &lt;code&gt;npm test&lt;/code&gt;. To ensure that uncommitted dependencies are caught early and that no extra modules are kept around and weighing down the project after they are no longer in use.&lt;/p&gt;

&lt;p&gt;I also make &lt;code&gt;npm test&lt;/code&gt; run before code is pushed remotely by setting up a &lt;code&gt;prepush&lt;/code&gt; git hook using &lt;a href="https://github.com/typicode/husky"&gt;husky&lt;/a&gt;. That way neither I or anyone else in the team can accidentally push code with any such mistakes. (I’ve found &lt;code&gt;prepush&lt;/code&gt; to work better for this than &lt;code&gt;precommit&lt;/code&gt; – more pragmatic, with happier developers as a result)&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Verify engine requirements of installed modules
&lt;/h2&gt;

&lt;p&gt;How do you express what versions of node.js your library supports? There’s the &lt;a href="https://docs.npmjs.com/files/package.json#engines"&gt;engines field&lt;/a&gt; in package.json for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"engines": {
  "node": "&amp;gt;=5.0.0"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple. You know what engine you support and you politely tell others so that they easily can find out as well.&lt;/p&gt;

&lt;p&gt;But how do you detect when others update their requirements and how do you avoid that you get dependencies that have stricter engine requirements than you yourself have? Surely there must be able to verify that automatically?&lt;/p&gt;

&lt;p&gt;Check out the just released &lt;code&gt;2.0.0&lt;/code&gt; version of &lt;a href="https://github.com/voxpelli/node-installed-check"&gt;installed-check&lt;/a&gt;: It has a new optional flag, &lt;code&gt;--engine-check&lt;/code&gt;, that makes it also check the engine requirements of all of the installed dependencies.&lt;/p&gt;

&lt;p&gt;If the engine requirements of any installed dependencies doesn’t match yours, then an error will be returned along with a suggestion of a stricter engine requirement whenever possible.&lt;/p&gt;

&lt;p&gt;By running that in your &lt;code&gt;npm test&lt;/code&gt; you can easily early detect whenever an engine requirement change and either avoid the change altogether or move along with it and release a new major version yourself with the new stricter engine requirements. (Changed engine requirements are always to be considered a breaking change, which requires a new major version according to &lt;a href="http://semver.org/"&gt;Semantic Versioning&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Only gotcha with this approach is that not all modules explicitly define their engine requirements in their package.json. By default installed-check ignores any such modules and doesn’t treat undefined engine requirements as an error. By setting either or both of the &lt;code&gt;--verbose&lt;/code&gt; and &lt;code&gt;--strict&lt;/code&gt; flags one can make it warn or throw errors whenever it encounters such a module though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Run all the tricks
&lt;/h2&gt;

&lt;p&gt;Install the modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev installed-check
npm install --save-dev dependency-check
npm install --save-dev husky
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set them up to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "scripts": {
    "test": "installed-check -e &amp;amp;&amp;amp; dependency-check . &amp;amp;&amp;amp; dependency-check . --extra --no-dev",
    "prepush": "npm test",
    "postapplypatch": "installed-check -e",
    "postmerge": "installed-check -e"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then profit from a more solid dependency workflow and a more happy development team!&lt;/p&gt;

</description>
      <category>node</category>
      <category>npm</category>
      <category>developertools</category>
    </item>
  </channel>
</rss>
