<?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: Slava Borodulin</title>
    <description>The latest articles on DEV Community by Slava Borodulin (@vborodulin).</description>
    <link>https://dev.to/vborodulin</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%2F381670%2F72c5b580-812a-4f0b-9955-0e91fecbb742.png</url>
      <title>DEV Community: Slava Borodulin</title>
      <link>https://dev.to/vborodulin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vborodulin"/>
    <language>en</language>
    <item>
      <title>Auto change MacOS network settings with WiFiLocControl</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Tue, 28 Nov 2023 13:20:56 +0000</pubDate>
      <link>https://dev.to/vborodulin/wifiloccontrol-macos-network-location-switcher-based-on-the-wi-fi-name-4cb4</link>
      <guid>https://dev.to/vborodulin/wifiloccontrol-macos-network-location-switcher-based-on-the-wi-fi-name-4cb4</guid>
      <description>&lt;p&gt;Repo: &lt;a href="https://github.com/vborodulin/wifi-loc-control"&gt;https://github.com/vborodulin/wifi-loc-control&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/vborodulin/wifi-loc-control"&gt;WiFiLocControl&lt;/a&gt; enables you to automatically change your macOS network location based on the Wi-Fi network (SSID) to which you are connected.&lt;/p&gt;

&lt;p&gt;It proves particularly beneficial for users who use Wi-Fi both at work and at home, but encounter issues where the network settings, such as custom DNS configurations, used at work prevent their Mac from seamlessly connecting to a similar network at home.&lt;/p&gt;

&lt;p&gt;I personally encountered a similar issue when I installed &lt;a href="https://pi-hole.net/"&gt;Pi-Hole&lt;/a&gt; on my Raspberry Pi to block ads on my network. Unfortunately, I couldn't configure custom DNS settings on my router due to restrictions imposed by my internet provider, who supplied the router. As a result, my only option was to manually set custom DNS with the IP address of my Raspberry Pi on each of my devices.&lt;/p&gt;

&lt;p&gt;For example, when configuring DNS settings on my iPhone, those settings are specific to the Wi-Fi network. This means that if I connect to a different Wi-Fi network, the DNS settings revert to default.&lt;/p&gt;

&lt;p&gt;In macOS, however, the situation is the opposite; the settings for Wi-Fi are not specific to the Wi-Fi network but rather to the network service. This means that if I want to use my MacBook at home with Wi-Fi and at work, I have to manually add the Pi-Hole DNS at home and remove it at work to revert to the default settings (such as Google's DNS).&lt;/p&gt;

&lt;p&gt;To address this inconvenience, we can leverage &lt;a href="https://support.apple.com/en-us/105129"&gt;network location&lt;/a&gt;, which allows the creation of multiple network profiles with different settings. However, you still need to switch profiles manually. This is where [WiFiLocControl (&lt;a href="https://github.com/vborodulin/wifi-loc-control"&gt;https://github.com/vborodulin/wifi-loc-control&lt;/a&gt;) comes in to automate and simplify the process!&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;To set up specific preferences for your Wi-Fi networks, keep it easy: just name your network locations after your Wi-Fi names. For example, if you want special settings for "My_Home_Wi-Fi_5GHz," make a location called "My_Home_Wi-Fi_5GHz." When you connect to that Wi-Fi, your location will switch automatically. If you connect to a Wi-Fi without a special name, it defaults to "Automatic.".&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Automatically changes network locations based on current Wi-Fi name.&lt;/li&gt;
&lt;li&gt;Supports alias configurations for multiple Wi-Fi names.&lt;/li&gt;
&lt;li&gt;Executes location-specific scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Clone the repository to your local machine.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/vborodulin/wifi-loc-control.git
&lt;span class="nb"&gt;cd&lt;/span&gt; ./wifi-loc-control
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the bootstrap script to set up the environment.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./bootstrap.sh    
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;It will &lt;strong&gt;ask you for a root password&lt;/strong&gt; to install WiFiLocControl to the &lt;code&gt;/usr/local/bin&lt;/code&gt;&lt;br&gt;
   directory.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Aliasing
&lt;/h3&gt;

&lt;p&gt;If you want to share one network location between different wireless networks (for instance, you have a wireless router which broadcasts on 2.4 and 5GHz bands simultaneously), then you can create a configuration file &lt;code&gt;~/.wifi-loc-control/alias.conf&lt;/code&gt; (plain text file with simple key-value pairs, no&lt;br&gt;
spaces in between):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My_Home_Wi-Fi_5GHz=Home
My_Home_Wi-Fi_2.4GHz=Home
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where the keys are the wireless network names and the values are the desired location names.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run Scripts on Wi-Fi Network Connection
&lt;/h3&gt;

&lt;p&gt;Sometimes you want to execute a script every time you connect to a specific Wi-Fi network. For example enable stealth or enable firewall mode. Follow these&lt;br&gt;
steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Place your scripts in &lt;code&gt;~/.wifi-loc-control/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Name the scripts after the Wi-Fi network name, ensuring consistency with the corresponding network locations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example script (&lt;code&gt;~/.wifi-loc-control/My_Home_Wi-Fi_5GHz&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# Collect all output from this script to ~/Library/Logs/WiFiLocControl.log&lt;/span&gt;
&lt;span class="nb"&gt;exec &lt;/span&gt;2&amp;gt;&amp;amp;1

&lt;span class="c"&gt;# Enable stealth mode which makes your computer less visible to potential attackers&lt;/span&gt;
/usr/libexec/ApplicationFirewall/socketfilterfw &lt;span class="nt"&gt;--setglobalstate&lt;/span&gt; on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To reset changes made by specific location scripts, create corresponding reset script.&lt;br&gt;
Example reset script (&lt;code&gt;~/.wifi-loc-control/Automatic&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;exec &lt;/span&gt;2&amp;gt;&amp;amp;1

&lt;span class="c"&gt;# Disable stealth mode which makes your computer less visible to potential attackers&lt;/span&gt;
/usr/libexec/ApplicationFirewall/socketfilterfw &lt;span class="nt"&gt;--setglobalstate&lt;/span&gt; off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make scripts executable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/.wifi-loc-control/My_Home_Wi-Fi_5GHz
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/.wifi-loc-control/Automatic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;Rich logs available at ~/Library/Logs/WiFiLocControl.log.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/Library/Logs/WiFiLocControl.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2023-11-26 13:44:49] current wifi_name 'My_Home_Wi-Fi_5GHz'
[2023-11-26 13:44:49] network locations: Automatic Home
[2023-11-26 13:44:49] current network location 'Automatic'
[2023-11-26 13:44:49] reading alias config '/Users/vborodulin/.wifi-loc-control/alias.conf'
[2023-11-26 13:44:49] for wifi name 'My_Home_Wi-Fi_5GHz' found alias 'Home'
[2023-11-26 13:44:49] location switched to 'Home'
[2023-11-26 13:44:49] finding script for location 'Home'
[2023-11-26 13:44:49] running script '/Users/vborodulin/.wifi-loc-control/Home'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/vborodulin/wifi-loc-control"&gt;Contributions are welcome!&lt;/a&gt; If you have suggestions, improvements, or encounter issues, feel free to open an issue or submit a &lt;a href="https://github.com/vborodulin/wifi-loc-control/pulls"&gt;pull request&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/vborodulin/wifi-loc-control"&gt;https://github.com/vborodulin/wifi-loc-control&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;This project is licensed under &lt;a href="https://github.com/vborodulin/wifi-loc-control/blob/main/LICENSE"&gt;the MIT License&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>macos</category>
      <category>utils</category>
      <category>shell</category>
      <category>bash</category>
    </item>
    <item>
      <title>Using pipes in Next.js getServerSideProps</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Tue, 06 Sep 2022 16:40:52 +0000</pubDate>
      <link>https://dev.to/vborodulin/using-pipes-in-nextjs-getserversideprops-3jn1</link>
      <guid>https://dev.to/vborodulin/using-pipes-in-nextjs-getserversideprops-3jn1</guid>
      <description>&lt;p&gt;This post, and posts like it, are an attempt to share my insights and experience with community.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipe functions
&lt;/h2&gt;

&lt;p&gt;A pipe function is not a new concept for people familiar with functional programming. The concept of pipe is simple - &lt;strong&gt;it combines n functions&lt;/strong&gt;. Each function push information downwards transforming  into a desired format. It’s a pipe flowing &lt;strong&gt;left-to-right&lt;/strong&gt;, calling each function &lt;strong&gt;with the output of the last one&lt;/strong&gt;.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;double&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;add1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// equivalent double(add1(5));&lt;/span&gt;
&lt;span class="c1"&gt;// returns 12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Pipe functions give ability to create &lt;strong&gt;small&lt;/strong&gt; and &lt;strong&gt;reusable peaces&lt;/strong&gt; of code &lt;strong&gt;combining together&lt;/strong&gt; in multiple variations.&lt;/p&gt;

&lt;p&gt;The idea of pipe function is pretty simple to understand and to implement in JavaScript. However, there is an interesting challenge around building such a functionality when working with promises and asynchronous data fetching. An even bigger challenge is fit functionality to &lt;code&gt;getServerSideProps&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's implement such a function in &lt;strong&gt;TypeScript&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pipe implementation
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;ssrHelpers.ts&lt;/em&gt;&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TPipeGetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TPipeGetServerSideProps&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsContext&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&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;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// it means we have notFound or redirect.&lt;/span&gt;
    &lt;span class="c1"&gt;// We need to break our pipe and return this result immediately.&lt;/span&gt;
    &lt;span class="k"&gt;if &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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;props&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&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;return&lt;/span&gt; &lt;span class="nx"&gt;res&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;There are &lt;strong&gt;4 important aspects&lt;/strong&gt; to understand in this small code snippet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By using the spread operator, we can accept an &lt;strong&gt;unlimited&lt;/strong&gt; number of &lt;strong&gt;piped functions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Each function &lt;strong&gt;receives&lt;/strong&gt; &lt;code&gt;input&lt;/code&gt; as an &lt;strong&gt;argument&lt;/strong&gt; the resolved value of the &lt;strong&gt;previous Promise&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If result execution of piped functions does not have &lt;code&gt;props&lt;/code&gt; property
&lt;/li&gt;
&lt;/ul&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;type&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;P&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Redirect&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="na"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;it means we have &lt;code&gt;notFound&lt;/code&gt; or &lt;code&gt;redirect&lt;/code&gt;. So we need to break our pipe and return this result immediately.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We end up &lt;strong&gt;returning&lt;/strong&gt; the &lt;strong&gt;data&lt;/strong&gt; in the format Next.js is expecting in getServerSideProps - &lt;code&gt;GetServerSidePropsResult&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Pipe example usage
&lt;/h2&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;const&lt;/span&gt; &lt;span class="nx"&gt;getServerSideProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ssrHelpers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ssrPipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withAuth&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;ssrPipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withSubscription&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 first function will then receive as an argument the Next.js context. It can then proceed to fetch the user session and information based the context object and send along the information to the next function in line:&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="c1"&gt;// we can pass arg as options to piped function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withAuth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;TPipeGetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// if !user -&amp;gt; not auth&lt;/span&gt;
  &lt;span class="c1"&gt;// return notFound and break piped functions chain&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// merge props and pass down to the next function&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&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;The next function passed will then receive the previous function's return value as an argument. It can then proceed to fetch new information and format it to be passed down the chain. In our example, this is our last function, so we will return an object representing the value of our Page's props:&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="c1"&gt;// we can pass arg as options to piped function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withSubscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;TPipeGetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TUser&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// subscription can be empty&lt;/span&gt;
  &lt;span class="c1"&gt;// merge props and pass down to the next function&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&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;An unlimited number of functions can then work together to achieve a pipeline of information. The last function is responsible to return the final Props object. This object will then be injected as a prop to the next.js Page component:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextPage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TIndexPageProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;albums&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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Index&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="na"&gt;albums&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;albums&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getServerSideProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ssrHelpers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ssrPipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withAuth&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;ssrPipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withSubscription&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;h2&gt;
  
  
  Parallel execution implementation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pipe&lt;/code&gt; helper call  piped function one after the other sequentially. This may be inefficient if we want to piped several functions that make a request to the server.&lt;br&gt;
We can run this functions in parallel by writing our own helpers inspired by &lt;code&gt;Promise.all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ssrHelpers.ts&lt;/em&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pipesExecParallel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TPipeGetServerSideProps&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;TPipeGetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;input&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;promiseArr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;promiseArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promiseAllRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promiseArr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;notFoundRes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;redirectRes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;propsRes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSidePropsResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&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;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fnRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promiseAllRes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;props&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;fnRes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;propsRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&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="nx"&gt;propsRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;fnRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notFound&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;fnRes&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;fnRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;notFoundRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;break&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redirect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;fnRes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;redirectRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fnRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&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;notFoundRes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;notFoundRes&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;redirectRes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;redirectRes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;propsRes&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;To better understand this code snipped let's remember how works &lt;code&gt;Promise.all&lt;/code&gt;. It rejects immediately upon any of the input promises rejecting or non-promises throwing an error, and will reject with this first rejection message / error.&lt;br&gt;
Similar to &lt;code&gt;Promise.all&lt;/code&gt; &lt;code&gt;pipesExecParallel&lt;/code&gt; take functions and run its with Promise.all under the hood. If one of functions return notFound or redirect it's consider and rejection / error and return this result immediate. Otherwise all functions results merged and pass down to next function in pipe.&lt;/p&gt;
&lt;h2&gt;
  
  
  Parallel execution example usage
&lt;/h2&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;const&lt;/span&gt; &lt;span class="nx"&gt;getServerSideProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ssrHelpers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ssrPipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withAuth&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// 500ms&lt;/span&gt;
  &lt;span class="c1"&gt;// run two async piped function parallel to minimize fetching data time&lt;/span&gt;
  &lt;span class="nx"&gt;ssrHelpers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipesExecParallel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;// 500ms in parallel execution&lt;/span&gt;
    &lt;span class="nx"&gt;ssrPipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withSubscription&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// 500ms&lt;/span&gt;
    &lt;span class="nx"&gt;ssrPipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withAlbums&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// 500ms&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// total 1000ms&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Full code example
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/vborodulin" rel="noopener noreferrer"&gt;
        vborodulin
      &lt;/a&gt; / &lt;a href="https://github.com/vborodulin/using-pipe-nextjs-get-server-side-props" rel="noopener noreferrer"&gt;
        using-pipe-nextjs-get-server-side-props
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Using Pipeline pattern to organize code in getServerSideProps or getStaticProps methods of Next.js
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Pipe functions&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;A pipe function is not a new concept for people familiar with functional programming. The concept of pipe is simple - &lt;strong&gt;it combines n functions&lt;/strong&gt;. Each function push information downwards transforming  into a desired format. It’s a pipe flowing &lt;strong&gt;left-to-right&lt;/strong&gt;, calling each function &lt;strong&gt;with the output of the last one&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-en"&gt;double&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;num&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-s1"&gt;num&lt;/span&gt; &lt;span class="pl-c1"&gt;*&lt;/span&gt; &lt;span class="pl-c1"&gt;2&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-en"&gt;add1&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;num&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-s1"&gt;num&lt;/span&gt; &lt;span class="pl-c1"&gt;+&lt;/span&gt; &lt;span class="pl-c1"&gt;1&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-en"&gt;pipe&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;add1&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;double&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c1"&gt;5&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c"&gt;// equivalent double(add1(5));&lt;/span&gt;
&lt;span class="pl-c"&gt;// returns 12&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Pipe functions give ability to create &lt;strong&gt;small&lt;/strong&gt; and &lt;strong&gt;reusable peaces&lt;/strong&gt; of code &lt;strong&gt;combining together&lt;/strong&gt; in multiple variations.&lt;/p&gt;
&lt;p&gt;The idea of pipe function is pretty simple to understand and to implement in JavaScript. However, there is an interesting challenge around building such a functionality when working with promises and asynchronous data fetching. An even bigger challenge is fit functionality…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/vborodulin/using-pipe-nextjs-get-server-side-props" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



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

&lt;p&gt;Pipe functions great fits into functional programming react paradigm and helps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;organize data fetching, validations in getServerSideProps in the one style&lt;/li&gt;
&lt;li&gt;combine small methods with single responsibility in complex getServerSideProps call with &lt;code&gt;pipe&lt;/code&gt; helper&lt;/li&gt;
&lt;li&gt;share reusable pipes across pages(withAuth, withUser, withSubscription)&lt;/li&gt;
&lt;li&gt;run pipes in parallel with helper &lt;code&gt;pipesExecParallel&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Inspired by
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.frontend-devops.com/blog/pipe-serverside-props-in-nextjs" rel="noopener noreferrer"&gt;https://www.frontend-devops.com/blog/pipe-serverside-props-in-nextjs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Detection device type with pure CSS</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Sat, 27 Feb 2021 16:03:57 +0000</pubDate>
      <link>https://dev.to/vborodulin/detection-device-type-with-pure-css-233a</link>
      <guid>https://dev.to/vborodulin/detection-device-type-with-pure-css-233a</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* smartphones, touchscreens */&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;coarse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;/* stylus-based screens */&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;/* Nintendo Wii controller, Microsoft Kinect */&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;coarse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;/* mouse, touch pad */&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>css</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to implement mongoose soft delete plugin</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Wed, 28 Oct 2020 08:57:11 +0000</pubDate>
      <link>https://dev.to/vborodulin/how-to-mongoose-soft-delete-plugin-4pf3</link>
      <guid>https://dev.to/vborodulin/how-to-mongoose-soft-delete-plugin-4pf3</guid>
      <description>&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>mongodb</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Pure CSS ios style scroll bar with paddings</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Mon, 26 Oct 2020 08:53:19 +0000</pubDate>
      <link>https://dev.to/vborodulin/custom-ios-style-css-scroll-bar-with-side-paddings-18ke</link>
      <guid>https://dev.to/vborodulin/custom-ios-style-css-scroll-bar-with-side-paddings-18ke</guid>
      <description>&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>css</category>
    </item>
    <item>
      <title>TS: How to override properties with type intersection</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Mon, 25 May 2020 19:25:40 +0000</pubDate>
      <link>https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l</link>
      <guid>https://dev.to/vborodulin/ts-how-to-override-properties-with-type-intersection-554l</guid>
      <description>&lt;p&gt;Hi, let's imagine the situation. We have type&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;a&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="nl"&gt;b&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to get a new type using an intersection. It's just what we thought&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;But it's not working☹️&lt;/p&gt;

&lt;p&gt;Of course, we can use interfaces instread&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;a&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="nl"&gt;b&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AB&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;But how do that with types? Let's create a new utility type that can help us&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Override&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;T2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;T2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Override&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty easy and very helpful. 🤟&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introducing Storybook Addon Performance🚀</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Sat, 09 May 2020 12:14:36 +0000</pubDate>
      <link>https://dev.to/vborodulin/welcome-storybook-addon-performance-55l4</link>
      <guid>https://dev.to/vborodulin/welcome-storybook-addon-performance-55l4</guid>
      <description>&lt;p&gt;Good day! Today I will introduce an awesome tool that will be useful for every React developer. Storybook Add-on Performance🚀!!!.&lt;/p&gt;

&lt;p&gt;Who doesn't know about storybook:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/storybookjs"&gt;
        storybookjs
      &lt;/a&gt; / &lt;a href="https://github.com/storybookjs/storybook"&gt;
        storybook
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      📓 The UI component explorer. Develop, document, &amp;amp; test React, Vue, Angular, Web Components, Ember, Svelte &amp;amp; more!
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a href="https://storybook.js.org/" rel="nofollow"&gt;
    &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0PVh9ECo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/321738/63501763-88dbf600-c4cc-11e9-96cd-94adadc2fd72.png" alt="Storybook" width="400"&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Build bulletproof UI components faster&lt;/p&gt;



&lt;p&gt;
  &lt;a href="https://circleci.com/gh/storybookjs/storybook" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/aa83bee7c61376b769d3f0a851b288b70e9ed3bb2f75f668e4591a3800cf3655/68747470733a2f2f636972636c6563692e636f6d2f67682f73746f7279626f6f6b6a732f73746f7279626f6f6b2e7376673f7374796c653d736869656c64" alt="Build Status on CircleCI"&gt;
  &lt;/a&gt;
  &lt;a href="https://www.codefactor.io/repository/github/storybookjs/storybook" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/5dfd72419ca972080f93376800b650f1317eb60f041c7205e89924a1f629bccb/68747470733a2f2f7777772e636f6465666163746f722e696f2f7265706f7369746f72792f6769746875622f73746f7279626f6f6b6a732f73746f7279626f6f6b2f6261646765" alt="CodeFactor"&gt;
  &lt;/a&gt;
  &lt;a href="https://snyk.io/test/github/storybookjs/storybook" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/61b94c6288e7266da2b08dd0677a8de2ee5c2fd5df9dd845ddc9ca5f4af63a41/68747470733a2f2f736e796b2e696f2f746573742f6769746875622f73746f7279626f6f6b6a732f73746f7279626f6f6b2f62616467652e737667" alt="Known Vulnerabilities"&gt;
  &lt;/a&gt;
  &lt;a href="https://codecov.io/gh/storybookjs/storybook" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/9a8f2fe0102d9977462ff73a1d1607f06150ad95c1752f2276b3edf6880ef5db/68747470733a2f2f636f6465636f762e696f2f67682f73746f7279626f6f6b6a732f73746f7279626f6f6b2f6272616e63682f6d61696e2f67726170682f62616467652e737667" alt="codecov"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/storybookjs/storybook/blob/main/LICENSE"&gt;
    &lt;img src="https://camo.githubusercontent.com/58ef240f51c720b41422df90e27c0dd5ff8e6b5fc5700dd180bd7743e32eda6a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f73746f7279626f6f6b6a732f73746f7279626f6f6b2e737667" alt="License"&gt;
  &lt;/a&gt;
  &lt;br&gt;
  &lt;a href="https://discord.gg/storybook" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/07de2d553fc3bf803b25eb15384611ac5c1749287cbcb4998bb4ccaf71c71395/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f646973636f72642d6a6f696e2d3732383944412e7376673f6c6f676f3d646973636f7264266c6f6e6743616368653d74727565267374796c653d666c6174"&gt;
  &lt;/a&gt;
  &lt;a href="https://storybook.js.org/community/" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/7ef67eb23a2c7ac4ff9ea0025cb65379ba11c44b6c5062c6dba34e7562838b91/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6d6d756e6974792d6a6f696e2d3442433432342e737667" alt="Storybook Community"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/storybookjs/storybook#backers"&gt;
    &lt;img src="https://camo.githubusercontent.com/0f5b33d55f1d6e28399dfc4fc9feb2a2066e2af01cbe7437322abe2f369dd6ba/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f73746f7279626f6f6b2f6261636b6572732f62616467652e737667" alt="Backers on Open Collective"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/storybookjs/storybook#sponsors"&gt;
    &lt;img src="https://camo.githubusercontent.com/e3060efc444b6caf7518a9249839ad159424d0643ce35ecd3eb4dbf082cb20fe/68747470733a2f2f6f70656e636f6c6c6563746976652e636f6d2f73746f7279626f6f6b2f73706f6e736f72732f62616467652e737667" alt="Sponsors on Open Collective"&gt;
  &lt;/a&gt;
  &lt;a href="https://twitter.com/intent/follow?screen_name=storybookjs" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/01c67058d28d8d1b5e12ca1a6efba03a74607168892ed87a7c6f1320609c8fc3/68747470733a2f2f62616467656e2e6e65742f747769747465722f666f6c6c6f772f73746f7279626f6f6b6a733f69636f6e3d74776974746572266c6162656c3d25343073746f7279626f6f6b6a73" alt="Official Twitter Handle"&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Storybook is a development environment for UI components.&lt;br&gt;
It allows you to browse a component library, view the different states of each component, and interactively develop and test components.&lt;br&gt;Find out more at &lt;a href="https://storybook.js.org" rel="nofollow"&gt;https://storybook.js.org&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;&lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/storybookjs/storybook/main/media/storybook-intro.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pZcBjyJl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://raw.githubusercontent.com/storybookjs/storybook/main/media/storybook-intro.gif" width="100%"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
  View README for:&lt;br&gt;
  &lt;a href="https://github.com/storybookjs/storybook/blob/main/README.md" title="latest"&gt;&lt;img alt="latest" src="https://camo.githubusercontent.com/eeedf54990ccce7e0bcd6e1792e37370de3416411e9a014351011cf9eb3d6d74/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f4073746f7279626f6f6b2f636f72652f6c61746573743f7374796c653d666f722d7468652d6261646765266c6f676f3d73746f7279626f6f6b266c6f676f436f6c6f723d66666666666626636f6c6f723d363642463343"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/storybookjs/storybook/blob/next/README.md" title="next"&gt;&lt;img alt="next" src="https://camo.githubusercontent.com/c37e80bf345d63da476d1cb3597304bd82142c8f2143214def74b958da295f26/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f4073746f7279626f6f6b2f636f72652f6e6578743f7374796c653d666f722d7468652d6261646765266c6f676f3d73746f7279626f6f6b266c6f676f436f6c6f723d66666666666626636f6c6f723d314541374644"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/storybookjs/storybook/blob/future/base/README.md" title="future"&gt;&lt;img alt="future" src="https://camo.githubusercontent.com/f57079326afc9d6756adbc6dcd3d75810cbf9e831092241e47862dd22539f713/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f4073746f7279626f6f6b2f636f72652d636f6d6d6f6e2f6675747572653f7374796c653d666f722d7468652d6261646765266c6f676f3d73746f7279626f6f6b266c6f676f436f6c6f723d66666666666626636f6c6f723d464634373835"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
Table of contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
🚀 &lt;a href="https://github.com/storybookjs/storybook#getting-started"&gt;Getting Started&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
📒 &lt;a href="https://github.com/storybookjs/storybook#projects"&gt;Projects&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;
🛠 &lt;a href="https://github.com/storybookjs/storybook#supported-frameworks"&gt;Supported Frameworks &amp;amp; Examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
🚇&lt;a href="https://github.com/storybookjs/storybook#sub-projects"&gt; Sub Projects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
🔗&lt;a href="https://github.com/storybookjs/storybook#addons"&gt;Addons&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
🏅 &lt;a href="https://github.com/storybookjs/storybook#badges--presentation-materials"&gt;Badges &amp;amp; Presentation materials&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
👥 &lt;a href="https://github.com/storybookjs/storybook#community"&gt;Community&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
👏 &lt;a href="https://github.com/storybookjs/storybook#contributing"&gt;Contributing&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;
👨‍💻 &lt;a href="https://github.com/storybookjs/storybook#development-scripts"&gt;Development scripts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
💵 &lt;a href="https://github.com/storybookjs/storybook#backers"&gt;Backers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
💸 &lt;a href="https://github.com/storybookjs/storybook#sponsors"&gt;Sponsors&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
📝 &lt;a href="https://github.com/storybookjs/storybook#license"&gt;License&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Getting Started&lt;/h2&gt;
&lt;p&gt;Visit &lt;a href="https://storybook.js.org" rel="nofollow"&gt;Storybook's website&lt;/a&gt; to learn more about Storybook and to get started.&lt;/p&gt;
&lt;h3&gt;
Documentation&lt;/h3&gt;
&lt;p&gt;Documentation can be found &lt;a href="https://storybook.js.org/docs" rel="nofollow"&gt;Storybook's docs site&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
Examples&lt;/h3&gt;
&lt;p&gt;Here are some featured examples that you can reference to see how Storybook works: &lt;a href="https://storybook.js.org/showcase" rel="nofollow"&gt;https://storybook.js.org/showcase&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Storybook comes with a lot of &lt;a href="https://storybook.js.org/docs/react/configure/storybook-addons" rel="nofollow"&gt;addons&lt;/a&gt; for component design, documentation, testing, interactivity, and so on. Storybook's API makes it possible to configure and extend in various ways. It has even been…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/storybookjs/storybook"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Over the year Atlassian team worked on the experimental addon for a storybook. This add-on can help to understand and debug performance problems with React components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9y2xhctk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.ibb.co/hDPrn53/ezgif-3-bcc209c4a81c.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9y2xhctk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.ibb.co/hDPrn53/ezgif-3-bcc209c4a81c.gif" alt="Performanse tests" width="600" height="409"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  When should I use it?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;During development, you can take into consideration the results of the tests. The performance metrics will show when something goes wrong.&lt;/li&gt;
&lt;li&gt;For performance issues. Reports from performance addon can show how effective your refactor is.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tips for correct performing measurements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Part of metrics has constant results during repeated tests and has no direct effect on performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;string output size&lt;/li&gt;
&lt;li&gt;string output size(gzip)&lt;/li&gt;
&lt;li&gt;static markup output size&lt;/li&gt;
&lt;li&gt;static markup output size(gzip)&lt;/li&gt;
&lt;li&gt;dom elements count&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The results of rendering metrics have a significant difference during repeated tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;initial render&lt;/li&gt;
&lt;li&gt;re-render&lt;/li&gt;
&lt;li&gt;render to string&lt;/li&gt;
&lt;li&gt;render to static markup&lt;/li&gt;
&lt;li&gt;hydrate
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_DMhUkI5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/86TZQQn/Screenshot-2020-05-09-at-13-53-24.png" alt="dirferent results during repeated tests" width="880" height="651"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To minimize inaccuracy you can&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;choose the max count of samples&lt;/li&gt;
&lt;li&gt;repeat tests and compare results on the same machine with the same 
state of the system (system upload and the temperature has an efficient 
effect)&lt;/li&gt;
&lt;li&gt;for QA testing you can use a separate computer with turn off thermal throttling, turn off turbo boost, and with setting the maximum number of fan revolutions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the 99 percentile for measurements. The explanation is in this &lt;a href="https://medium.com/@ankur_anand/an-in-depth-introduction-to-99-percentile-for-programmers-22e83a00caf"&gt;article&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Enjoy!🤟&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/atlassian-labs"&gt;
        atlassian-labs
      &lt;/a&gt; / &lt;a href="https://github.com/atlassian-labs/storybook-addon-performance"&gt;
        storybook-addon-performance
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      🚧 A storybook addon to help better understand and debug performance for React components.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
storybook-addon-performance 🚀
&lt;/h1&gt;
&lt;div&gt;
&lt;p&gt;A &lt;a href="https://storybook.js.org/" rel="nofollow"&gt;storybook&lt;/a&gt; addon to help better understand and debug performance for &lt;code&gt;React&lt;/code&gt; components&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/2182637/78786875-c904d000-79ec-11ea-9d49-1e253129f450.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5DvKvCMJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/2182637/78786875-c904d000-79ec-11ea-9d49-1e253129f450.gif" alt="storybook-addon-performance demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;🚧 This addon is &lt;strong&gt;experimental&lt;/strong&gt; and a &lt;strong&gt;work in progress&lt;/strong&gt;. We are not on stable versions yet 🚧&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=AknVkHeYqqg&amp;amp;feature=youtu.be&amp;amp;t=283" rel="nofollow"&gt;📺 Project overview&lt;/a&gt; by
&lt;a href="https://twitter.com/jherr" rel="nofollow"&gt;Jack Herrington&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;
Highlights 🌟
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero config&lt;/strong&gt; (except for interactions): Generate performance information relating to server-side rendering and client-side mounting without any configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin results&lt;/strong&gt;: You can run some tasks, pin the result, make some changes, rerun the tasks and see what changed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save/Load results&lt;/strong&gt;: You can run some tasks, save the results as a local artifact, and run
them again later by loading the artifact back into the addon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactions&lt;/strong&gt;: Add your own custom user interactions to run as a parameter to your story. This lets you time how long interactions take. The API for this is super flexible and powerful!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control&lt;/strong&gt;: Run all tasks for an overview…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/atlassian-labs/storybook-addon-performance"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Best way to deal with immutable data in JS</title>
      <dc:creator>Slava Borodulin</dc:creator>
      <pubDate>Fri, 08 May 2020 20:42:29 +0000</pubDate>
      <link>https://dev.to/vborodulin/best-way-to-deal-with-immutable-data-in-js-53l</link>
      <guid>https://dev.to/vborodulin/best-way-to-deal-with-immutable-data-in-js-53l</guid>
      <description>&lt;p&gt;Hey, Devs😎 I don't know how I miss it before, but I find out the best way to deal with immutable data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data and Structure types in JavaScript
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Six Primitive types checked by &lt;code&gt;typeof&lt;/code&gt; operator

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;undefined&lt;/code&gt; - &lt;code&gt;typeof undefined === 'undefined'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Boolean&lt;/code&gt; - &lt;code&gt;typeof true === 'boolean'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;String&lt;/code&gt; - &lt;code&gt;typeof 'hello' === 'string'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Number&lt;/code&gt; - &lt;code&gt;typeof 10 === 'number'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BigInt&lt;/code&gt; - &lt;code&gt;typeof 10n === 'bigint'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Symbol&lt;/code&gt; - &lt;code&gt;typeof Symbol() === 'symbol'&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;null&lt;/code&gt; - special primitive type, &lt;code&gt;typeof null === 'object'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Object&lt;/code&gt; Inclides &lt;code&gt;Array, Map, Set, WeekMap, WeekSet, Date&lt;/code&gt;- &lt;code&gt;typeof {} === 'object'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Function&lt;/code&gt; - &lt;code&gt;typeof () =&amp;gt; {} === 'function'&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;JavaScript assignment works in two ways. For primary types (Boolean, String, Number, BigInt, null, Symbol) assignment returns the new value. For complex types (Object) it returns a reference (pointer in memory) and any changes will impact all entries because all these entries are just references on the same pointer in memory.&lt;/p&gt;

&lt;p&gt;And the problem is that no guaranty that something will stay unchanged. The worst-case scenario is when the structure is used in different parts of the application. The mutation of this structure in one of the components can affect the bug in the whole application. And this bug is really hard to track. Where it was changed? What exactly was changed? Who also has access to the reference? But the history of change is not available and questions can’t be easily answered.&lt;/p&gt;

&lt;p&gt;In React-Redux stack we are used to handling immutable data, but sometimes it can be very tedious with ES6 native way;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function updateVeryNestedField(state, action) {
  return {
    ...state,
    first: {
      ...state.first,
      second: {
        ...state.first.second,
        [action.someId]: {
          ...state.first.second[action.someId],
          fourth: action.someValue
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Oh yeah😱 Looks familiar?&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;switch (action.type) {
 case ADD_NEW_AVAILABLE_COLOR_TO_CAR:{
  const { color, model, manufacturer } = action.payload
  return {...state, manufacturer: {
    ...state.manufacturer, [manufacturer]:
    {...state.manufacturers[manufacturers], models:
      {...state.manufacturers[manufacturers].models, [model]:
        {...state.manufacturers[manufacturers].models[model], options:
          {...state.manufacturers[manufacturers].models[model].options, colors:
          {...state.manufacturers[manufacturers].models[model].options.colors, [color]: true}
         }
       }
     }
   }
 }
 default: return state
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Of course, you can say "hey buddy, you forgot about &lt;strong&gt;immutable-js&lt;/strong&gt;"&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/immutable-js"&gt;
        immutable-js
      &lt;/a&gt; / &lt;a href="https://github.com/immutable-js/immutable-js"&gt;
        immutable-js
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Immutable persistent data collections for Javascript which increase efficiency and simplicity.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Immutable collections for JavaScript&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml?query=branch%3Amain"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uwg1fxAL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml/badge.svg%3Fbranch%3Dmain" alt="Build Status"&gt;&lt;/a&gt; &lt;a href="https://immutable-js.slack.com" rel="nofollow"&gt;Chat on slack&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://immutable-js.com" rel="nofollow"&gt;Read the docs&lt;/a&gt; and eat your vegetables.&lt;/p&gt;
&lt;p&gt;Docs are automatically generated from &lt;a href="https://github.com/immutable-js/immutable-js/blob/main/README.md"&gt;README.md&lt;/a&gt; and &lt;a href="https://github.com/immutable-js/immutable-js/blob/main/type-definitions/immutable.d.ts"&gt;immutable.d.ts&lt;/a&gt;
Please contribute! Also, don't miss the &lt;a href="https://github.com/immutable-js/immutable-js/wiki"&gt;wiki&lt;/a&gt; which contains articles on
additional specific topics. Can't find something? Open an &lt;a href="https://github.com/immutable-js/immutable-js/issues"&gt;issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Table of contents:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#introduction"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#getting-started"&gt;Getting started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#the-case-for-immutability"&gt;The case for Immutability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#javaScript-first-api"&gt;JavaScript-first API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#nested-structures"&gt;Nested Structures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#equality-treats-collections-as-values"&gt;Equality treats Collections as Values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#batching-mutations"&gt;Batching Mutations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#lazy-seq"&gt;Lazy Seq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#additional-tools-and-resources"&gt;Additional Tools and Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/immutable-js/immutable-js#contributing"&gt;Contributing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Introduction&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Immutable_object" rel="nofollow"&gt;Immutable&lt;/a&gt; data cannot be changed once created, leading to much simpler
application development, no defensive copying, and enabling advanced memoization
and change detection techniques with simple logic. &lt;a href="https://en.wikipedia.org/wiki/Persistent_data_structure" rel="nofollow"&gt;Persistent&lt;/a&gt; data presents
a mutative API which does not update the data in-place, but instead always
yields new updated data.&lt;/p&gt;
&lt;p&gt;Immutable.js provides many Persistent Immutable data structures including
&lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Stack&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;OrderedMap&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, &lt;code&gt;OrderedSet&lt;/code&gt; and &lt;code&gt;Record&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These data structures are highly efficient on modern…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/immutable-js/immutable-js"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;But I don't like it this way. It's an extra abstraction in your code with uncommon data structures for frontend developers. It seriously increases the entry threshold in your project for other developers. And debugging is really painful as hell. I have to click and click and click once again to expand the wrapped data in the console. However, it is just a simple nested list of objects. I can’t simply find out what’s inside😡&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kolodny"&gt;
        kolodny
      &lt;/a&gt; / &lt;a href="https://github.com/kolodny/immutability-helper"&gt;
        immutability-helper
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      mutate a copy of data without changing the original source
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
immutability-helper&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://npmjs.org/package/immutability-helper" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/bf161176c79809b5b728fc11fb6812386c4cc874729147f1d2eb985853217c29/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f696d6d75746162696c6974792d68656c7065722e7376673f7374796c653d666c61742d737175617265" alt="NPM version"&gt;&lt;/a&gt;
&lt;a href="https://travis-ci.org/kolodny/immutability-helper" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/0ed6a74825039501fd27f5897c0c7df9f7ff21cb8b98f40a5f185464bbc82d60/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6b6f6c6f646e792f696d6d75746162696c6974792d68656c7065722e7376673f7374796c653d666c61742d737175617265" alt="Build status"&gt;&lt;/a&gt;
&lt;a href="https://coveralls.io/r/kolodny/immutability-helper" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a7c3ab264d04f321a1e0c297d2d0b8db1f0bbb2a7823594ef709c71e39d76b15/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f6b6f6c6f646e792f696d6d75746162696c6974792d68656c7065722e7376673f7374796c653d666c61742d737175617265" alt="Test coverage"&gt;&lt;/a&gt;
&lt;a href="https://npmjs.org/package/immutability-helper" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/cb67363bd0f1a467f352049788a4883afdb88f14804f17324b9e4dc36132ae51/687474703a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f696d6d75746162696c6974792d68656c7065722e7376673f7374796c653d666c61742d737175617265" alt="Downloads"&gt;&lt;/a&gt;
&lt;a href="https://bundlephobia.com/result?p=immutability-helper" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/3e07984b6f22ac25b632b7b1a67c163b5ce1c73d485b3efaeca02561558b4867/68747470733a2f2f62616467656e2e6e65742f62756e646c6570686f6269612f6d696e2f696d6d75746162696c6974792d68656c7065723f6c6162656c3d6d696e6966696564" alt="Minified size"&gt;&lt;/a&gt;
&lt;a href="https://bundlephobia.com/result?p=immutability-helper" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/9a24875a4837d1d548ea080f0ef4270f9b9eee4e31142225b7e505616f67a41c/68747470733a2f2f62616467656e2e6e65742f62756e646c6570686f6269612f6d696e7a69702f696d6d75746162696c6974792d68656c7065723f6c6162656c3d677a6970" alt="Gzip size"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mutate a copy of data without changing the original source&lt;/p&gt;
&lt;p&gt;Setup via NPM&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install immutability-helper --save&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This is a drop-in replacement for &lt;a href="https://facebook.github.io/react/docs/update.html" rel="nofollow"&gt;&lt;code&gt;react-addons-update&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// import update from 'react-addons-update';&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;update&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'immutability-helper'&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;state1&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;'x'&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;state2&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;update&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;state1&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;span class="pl-c1"&gt;$push&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;'y'&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt; &lt;span class="pl-c"&gt;// ['x', 'y']&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Note that this module has nothing to do with React. However, since this module
is most commonly used with React, the docs will focus on how it can be used with
React.&lt;/p&gt;
&lt;h2&gt;
Overview&lt;/h2&gt;
&lt;p&gt;React lets you use whatever style of data management you want, including
mutation. However, if you can use immutable data in performance-critical parts
of your application it's easy to implement a fast &lt;a href="https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate" rel="nofollow"&gt;&lt;code&gt;shouldComponentUpdate()&lt;/code&gt;&lt;/a&gt; method
to significantly speed up your app.&lt;/p&gt;
&lt;p&gt;Dealing with immutable data in JavaScript is more difficult than in languages
designed for it…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kolodny/immutability-helper"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Library &lt;strong&gt;immutable-helpers&lt;/strong&gt; represents a simple immutable helper &lt;strong&gt;update&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import update from ' immutable-helpers';

const newData = update(myData, {
  x: {y: {z: {$set: 7}}},
  a: {b: {$push: [9]}}
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see it, right? It's really simple! The icing on the cake is a familiar approach that we really well know from &lt;a href="https://github.com/mongodb/node-mongodb-native"&gt;mongodb native driver&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;db.products.update(
   { _id: 100 },
   { $set:
      {
        quantity: 500,
        details: { model: "14Q3", make: "xyz" },
        tags: [ "coats", "outerwear", "clothing" ]
      }
   }
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List of available commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;{$push: array} push() all the items in array on the target.&lt;/li&gt;
&lt;li&gt;{$unshift: array} unshift() all the items in array on the target.&lt;/li&gt;
&lt;li&gt;{$splice: array of arrays} for each item in arrays call splice() on the * target with the parameters provided by the item.&lt;/li&gt;
&lt;li&gt;{$set: any} replace the target entirely.&lt;/li&gt;
&lt;li&gt;{$merge: object} merge the keys of object with the target.&lt;/li&gt;
&lt;li&gt;{$apply: function} passes in the current value to the function and updates it with the new returned value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally my personal small example of how organically it fits into the Redux reducers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const reducer = (state = initialState, action: IAppAction): TState =&amp;gt; {
  switch (action.type) {
    case CONVERSATIONS_ADD: {
      const { conversation } = action.data;

      return update(state, {
        [conversation.counterpartId]: { $set: conversation },
      });
    }
    case CONVERSATION_READ_SUCCESS:
      return update(state, {
        [action.data.counterpartId]: { unread: { $set: 0 } },
      });
    default:
      return state;
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are welcome! But don't forget, it's not the tools that make you a good developer.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>redux</category>
    </item>
  </channel>
</rss>
