<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://esstudio.site/feed.xml" rel="self" type="application/atom+xml" /><link href="https://esstudio.site/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-01-12T17:59:44+01:00</updated><id>https://esstudio.site/feed.xml</id><title type="html">Echo Sierra Studio</title><subtitle>Web, app and tooling development and graphic design studio. View all websites made by Echo Sierra Studio and contact us if your interested.</subtitle><author><name>Sem Postma</name></author><entry xml:lang="en"><title type="html">ATC Manager Continued</title><link href="https://esstudio.site/2022/04/16/atc-manager-continued.html" rel="alternate" type="text/html" title="ATC Manager Continued" /><published>2022-04-16T00:00:00+02:00</published><updated>2022-04-16T00:00:00+02:00</updated><id>https://esstudio.site/2022/04/16/atc-manager-continued</id><content type="html" xml:base="https://esstudio.site/2022/04/16/atc-manager-continued.html"><![CDATA[<p>It has been a long time but I have finally gotten more time to develop the game further. I have been able to update the game here and there but I have been busy with a lot of other stuff. Who would have thought building a free-to-play game would be financially unsustainable…</p>

<p>I’m thinking of making the game freemium, so you can still play with all of the existing maps (and maybe more free ones in the future). Making some maps paid, maybe with a monthly subscription, would allow me to hire developers to further build the game and add tons of maps.</p>

<p>I have gotten a lot of emails asking for custom build forks for education purposes. I want to emphasize that this game is exactly that a game. While I want to make the game as realistic as possible I’m not trying to build a true simulation game so keep that in mind.</p>

<p>I you have any questions, feel free to contact me: <a href="mailto:sem@esstudio.nl">sem@esstudio.nl</a>. Of course, I will not forget all of the kind donations, I will try to, somehow, in the future, give back to the people that have donated in the past.</p>

<p>I will share more soon!</p>

<p>*squawks 7600*</p>]]></content><author><name>Sem Postma</name></author><category term="atc manager 2" /><summary type="html"><![CDATA[It has been a long time but I have finally gotten more time to develop the game further.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/dev.png" /><media:content medium="image" url="https://esstudio.site/uploads/dev.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Illustrator Script Installer</title><link href="https://esstudio.site/2020/03/23/illustrator-script-installer.html" rel="alternate" type="text/html" title="Illustrator Script Installer" /><published>2020-03-23T00:00:00+01:00</published><updated>2020-03-23T00:00:00+01:00</updated><id>https://esstudio.site/2020/03/23/illustrator-script-installer</id><content type="html" xml:base="https://esstudio.site/2020/03/23/illustrator-script-installer.html"><![CDATA[<p>Easily manage the installation of Illustrator Scripts. A Windows Store version is coming soon.</p>

<p>Start by selecting or automatically searching for you Adobe Illustrator Directory. After that, you can use the “Add script” button to add new scripts to your installation. You can add scripts from text, files or popular script repositories.</p>

<p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9732535637352249" data-ad-slot="6033478353" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script>	
(adsbygoogle = window.adsbygoogle || []).push({});	
</script></p>

<div class="app-portal" style="width: 400px; max-width: 100%; padding: 10px">
    <img src="https://esstudio.site/uploads/isi.png" alt="" style="max-width: 50%; margin: 20px auto" />
    <h1>Illustrator Script Installer</h1>
    <p>Easily install Illustrator Scripts</p>
    <a class="btn" href="https://github.com/sempostma/illustrator-script-installer/releases">
        <span>Launch</span>
        <svg viewBox="0 0 10 18" style="height: 1.2em"><path d="m0.8,1l8,8l-8,8" fill="none" stroke-width="2" style="stroke: currentColor;" /></svg>
    </a>
</div>

<p>Feel free to leave suggestions by sending an email to illustratorscriptinstaller_support@esstudio.site</p>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[A minimal Adobe Illustrator Script installer, which takes care of the hard work.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/isi.png" /><media:content medium="image" url="https://esstudio.site/uploads/isi.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Authenticating Firebase JWT Tokens</title><link href="https://esstudio.site/2020/02/07/authenticating-firebase-jwt-tokens.html" rel="alternate" type="text/html" title="Authenticating Firebase JWT Tokens" /><published>2020-02-07T00:00:00+01:00</published><updated>2020-02-07T00:00:00+01:00</updated><id>https://esstudio.site/2020/02/07/authenticating-firebase-jwt-tokens</id><content type="html" xml:base="https://esstudio.site/2020/02/07/authenticating-firebase-jwt-tokens.html"><![CDATA[<p>There might be circumstances where you would want to verify if a certain user is authenticated with firebase.</p>

<p>You don’t need the firebase admin module to verify and decode firebase JWT tokens. In the example below you can find a full implementation of this. I’m only using the default node.js modules http, https and crypto.</p>

<script src="https://gist.github.com/b5b6492ddb805d71daa5e60f32c7788c.js"> </script>

<p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9732535637352249" data-ad-slot="6033478353" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script>	
(adsbygoogle = window.adsbygoogle || []).push({});	
</script></p>

<h3 id="example-response-json">Example response JSON</h3>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"data"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"iss"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://securetoken.google.com/&lt;project_id&gt;"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"aud"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;project_id&gt;"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"auth_time"</span><span class="p">:</span><span class="w"> </span><span class="mi">1581009428</span><span class="p">,</span><span class="w">
        </span><span class="nl">"user_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"9jnxi9kmz76ajnc4do47emrk8s1s"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"sub"</span><span class="p">:</span><span class="w"> </span><span class="s2">"9jnxi9kmz76ajnc4do47emrk8s1s"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"iat"</span><span class="p">:</span><span class="w"> </span><span class="mi">1581082417</span><span class="p">,</span><span class="w">
        </span><span class="nl">"exp"</span><span class="p">:</span><span class="w"> </span><span class="mi">1581086017</span><span class="p">,</span><span class="w">
        </span><span class="nl">"email"</span><span class="p">:</span><span class="w"> </span><span class="s2">"test@example.com"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"email_verified"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
        </span><span class="nl">"firebase"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"identities"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
                </span><span class="nl">"email"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
                    </span><span class="s2">"test@example.com"</span><span class="w">
                </span><span class="p">]</span><span class="w">
            </span><span class="p">},</span><span class="w">
            </span><span class="nl">"sign_in_provider"</span><span class="p">:</span><span class="w"> </span><span class="s2">"password"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>You can optionally check if the “iss” value is equal to “<code class="language-plaintext highlighter-rouge">https://securetoken.google.com/&lt;project_id&gt;</code>” to ensure the user is signed in with a specific firebase project.</p>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[Verify and decode Firebase JWT tokens using node.js without dependencies.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/OAuth%202.0.png" /><media:content medium="image" url="https://esstudio.site/uploads/OAuth%202.0.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Batch exporting Adobe Illustrator data sets</title><link href="https://esstudio.site/2020/01/20/batch-exporting-adobe-illustrator-data-sets.html" rel="alternate" type="text/html" title="Batch exporting Adobe Illustrator data sets" /><published>2020-01-20T00:00:00+01:00</published><updated>2020-01-20T00:00:00+01:00</updated><id>https://esstudio.site/2020/01/20/batch-exporting-adobe-illustrator-data-sets</id><content type="html" xml:base="https://esstudio.site/2020/01/20/batch-exporting-adobe-illustrator-data-sets.html"><![CDATA[<table>
  <tbody>
    <tr>
      <td><em>Important: Data sets should not have invalid characters for filenames like:</em> \ / : * ? “ &lt; &gt;</td>
    </tr>
  </tbody>
</table>

<ul>
  <li>Open a random document</li>
  <li>Create a new “Save” action where you simply save the file as a pdf document, <em>Don’t forget to uncheck “View PDF after saving”</em></li>
  <li>Select the action and click on the hamburger button (the 3 horizontal lines) in the top right, click “Batch”</li>
  <li>Select your “Save” action</li>
  <li>Choose “Data Sets” as the source (you should see “No options available”)</li>
  <li>Choose a destination</li>
  <li>Check Override Action “Save” Command</li>
  <li>
    <table>
      <tbody>
        <tr>
          <td>File Name: Choose either File + Data Set Name or Data Set Name. _Make sure your dataset names have valid filename characters so none of these: \ / : * ? “ &lt; &gt;</td>
          <td>_</td>
        </tr>
      </tbody>
    </table>
  </li>
  <li>Click “Ok”</li>
</ul>

<p>If you’re getting this error: <code class="language-plaintext highlighter-rouge">current values have not been captured and will be discarded upon switching data sets. Proceed?</code>, please refer to <a href="#clean-data-sets">“Clean data sets”</a></p>

<p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9732535637352249" data-ad-slot="6033478353" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script>	
(adsbygoogle = window.adsbygoogle || []).push({});	
</script></p>

<h2 id="clean-data-sets">Clean data sets</h2>

<ul>
  <li>Download the following script: <a href="https://gist.github.com/sempostma/30ea44b8fbce7033752cb80b8eb1ffb1/archive/d1405b86decd4c4462e5ca224c8506d62cdb3ad4.zip" title="https://gist.github.com/sempostma/30ea44b8fbce7033752cb80b8eb1ffb1/archive/d1405b86decd4c4462e5ca224c8506d62cdb3ad4.zip">https://gist.github.com/sempostma/30ea44b8fbce7033752cb80b8eb1ffb1/archive/d1405b86decd4c4462e5ca224c8506d62cdb3ad4.zip</a></li>
  <li>Open the zip file, you should find a “Clean Datasets.jsx” file.</li>
  <li>Copy the file to C:\Program Files\Adobe\Adobe Illustrator CC 2019\Presets\<your locality="">\\Scripts or the equivalent script folder for your operating system.</your></li>
  <li>Restart Illustrator</li>
  <li>Run: “File-&gt;Scripts-&gt;Clean Datasets”</li>
</ul>

<p><strong>Source:</strong></p>

<script src="https://gist.github.com/30ea44b8fbce7033752cb80b8eb1ffb1.js"> </script>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[Batch export data-driven documents with large data sets.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/adobe-illustrator-cc.svg" /><media:content medium="image" url="https://esstudio.site/uploads/adobe-illustrator-cc.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Key value wrapper around IndexedDB</title><link href="https://esstudio.site/2020/01/12/key-value-wrapper-around-indexeddb.html" rel="alternate" type="text/html" title="Key value wrapper around IndexedDB" /><published>2020-01-12T00:00:00+01:00</published><updated>2020-01-12T00:00:00+01:00</updated><id>https://esstudio.site/2020/01/12/key-value-wrapper-around-indexeddb</id><content type="html" xml:base="https://esstudio.site/2020/01/12/key-value-wrapper-around-indexeddb.html"><![CDATA[<p>Local-storage can be slow because local-storage’s CRUD operations are synchronous so they pause rendering, script execution, etc. If you want to do anything more complex than storing a string in local-storage, you will have to serialize/de-serialize your data, which also causes an extra performance impact. Storing blobs and files is even more tricky, you will have to convert blobs and files to bloated base64 strings. You can solve all of this by using IndexedDB, but you will soon notice there’s a giant difference between the two API’s. This wrapper attempts to gap those differences.</p>

<p><em>Make sure to use the following polyfills when necessary:</em> <a href="https://github.com/eligrey/Blob.js" title="https://github.com/eligrey/Blob.js"><em>https://github.com/eligrey/Blob.js</em></a> <em>and</em> <a href="https://github.com/stefanpenner/es6-promise" title="https://github.com/stefanpenner/es6-promise"><em>https://github.com/stefanpenner/es6-promise</em></a></p>

<p>Example:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">cacheStore</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./indexeddb-wrapper-file</span><span class="dl">'</span><span class="p">)</span> <span class="c1">// es6</span>
<span class="k">import</span> <span class="nx">cacheStore</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./indexeddb-wrapper-file</span><span class="dl">'</span> <span class="c1">// commonjs</span>
<span class="kd">var</span> <span class="nx">cacheStore</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">cacheStore</span> <span class="c1">// compiled javascript</span>

<span class="nx">cacheStore</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">my_key</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="na">myAwesome</span><span class="p">:</span> <span class="dl">'</span><span class="s1">complexObject</span><span class="dl">'</span> <span class="p">})</span>
	<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
  		<span class="k">return</span> <span class="nx">cacheStore</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">my_key</span><span class="dl">'</span><span class="p">)</span>
	<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">myKey</span><span class="p">)</span> <span class="p">{</span>
      	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">myKey</span><span class="dl">'</span><span class="p">,</span> <span class="nx">myKey</span><span class="p">)</span>
    <span class="p">})</span>
</code></pre></div></div>

<p><em>After deleting the store in devtools you might see an error in the console, you should bump the “VERSION” any time you delete database stores so the browser knows it should create new object stores.</em></p>

<p>Steps to add a new store:</p>

<ol>
  <li>Name your store: <code class="language-plaintext highlighter-rouge">const APP_PERSISTENCE = "APP_PERSISTENCE";</code></li>
  <li>Add it to the array of stores: <code class="language-plaintext highlighter-rouge">const stores = [CACHE_STORE, APP_PERSISTENCE];</code></li>
  <li>Bump the version: <code class="language-plaintext highlighter-rouge">const VERSION = n;</code> to <code class="language-plaintext highlighter-rouge">const VERSION = n+1;</code></li>
  <li>Instantiate a wrapper around the store: <code class="language-plaintext highlighter-rouge">const myStoreWrapper = indexedDBStorage(APP_PERSISTENCE)</code></li>
</ol>

<p>You might want to check if “error.name === ‘QuotaExceededError’” in transaction.onabort. If this is the case, alert the user about there not being enough storage space on the device.</p>

<p>Javascript:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">VERSION</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">CACHE_STORE</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">CACHE_STORE</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">DATABASE_NAME</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">stores</span> <span class="o">=</span> <span class="p">[</span><span class="nx">CACHE_STORE</span><span class="p">];</span>
<span class="kd">const</span> <span class="nx">request</span> <span class="o">=</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">indexedDB</span> <span class="o">||</span> <span class="nb">window</span><span class="p">.</span><span class="nx">mozIndexedDB</span> <span class="o">||</span> <span class="nb">window</span><span class="p">.</span><span class="nx">webkitIndexedDB</span><span class="p">)</span>
    <span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">DATABASE_NAME</span><span class="p">,</span> <span class="nx">VERSION</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span>
    <span class="p">};</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
    <span class="p">};</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onupgradeneeded</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span>
        <span class="nx">stores</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">store</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">db</span><span class="p">.</span><span class="nx">objectStoreNames</span><span class="p">.</span><span class="nx">contains</span><span class="p">(</span><span class="nx">store</span><span class="p">))</span> <span class="p">{</span>
                <span class="nx">db</span><span class="p">.</span><span class="nx">createObjectStore</span><span class="p">(</span><span class="nx">store</span><span class="p">);</span>
            <span class="p">}</span>
        <span class="p">});</span>
    <span class="p">};</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onblocked</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
    <span class="p">};</span>
<span class="p">});</span>
<span class="kd">const</span> <span class="nx">indexedDBStorage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="kd">get</span> <span class="o">=</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">database</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readonly</span><span class="dl">"</span><span class="p">);</span>
        <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
        <span class="p">};</span>
        <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
        <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span> <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span> <span class="p">};</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
    <span class="p">}));</span>
    <span class="kd">const</span> <span class="nx">keys</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">database</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readonly</span><span class="dl">"</span><span class="p">);</span>
        <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
        <span class="p">};</span>
        <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
        <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">getAllKeys</span><span class="p">();</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span> <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span> <span class="p">};</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
    <span class="p">}));</span>
    <span class="kd">const</span> <span class="kd">set</span> <span class="o">=</span> <span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">database</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>
        <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
        <span class="p">};</span>
        <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
        <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">key</span><span class="p">);</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
            <span class="nx">resolve</span><span class="p">();</span>
        <span class="p">};</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
    <span class="p">}));</span>
    <span class="kd">const</span> <span class="nx">indexedDbDelete</span> <span class="o">=</span> <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">database</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>
        <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
        <span class="p">};</span>
        <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
        <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="nx">resolve</span><span class="p">;</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
    <span class="p">}));</span>
    <span class="kd">const</span> <span class="nx">purgeDatabase</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">database</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>
        <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
        <span class="p">};</span>
        <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
        <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="nx">resolve</span><span class="p">;</span>
        <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
    <span class="p">}));</span>
    <span class="kd">const</span> <span class="nx">deleteDatabase</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nb">window</span><span class="p">.</span><span class="nx">indexedDB</span><span class="p">.</span><span class="nx">deleteDatabase</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">);</span>
    <span class="p">};</span>
    <span class="k">return</span> <span class="p">{</span>
        <span class="kd">get</span><span class="p">,</span>
        <span class="kd">set</span><span class="p">,</span>
        <span class="na">delete</span><span class="p">:</span> <span class="nx">indexedDbDelete</span><span class="p">,</span>
        <span class="nx">purgeDatabase</span><span class="p">,</span>
        <span class="nx">deleteDatabase</span><span class="p">,</span>
        <span class="nx">keys</span>
    <span class="p">};</span>
<span class="p">};</span>
<span class="k">export</span> <span class="k">default</span> <span class="nx">indexedDBStorage</span><span class="p">(</span><span class="nx">CACHE_STORE</span><span class="p">);</span>
</code></pre></div></div>

<p>Typescript:</p>

<div class="language-typescript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">VERSION</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">CACHE_STORE</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">CACHE_STORE</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">DATABASE_NAME</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">stores</span> <span class="o">=</span> <span class="p">[</span><span class="nx">CACHE_STORE</span><span class="p">];</span>

<span class="kd">const</span> <span class="nx">request</span> <span class="o">=</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">indexedDB</span> <span class="o">||</span> <span class="p">(</span><span class="nb">window</span> <span class="k">as</span> <span class="kr">any</span><span class="p">).</span><span class="nx">mozIndexedDB</span> <span class="o">||</span> <span class="p">(</span><span class="nb">window</span> <span class="k">as</span> <span class="kr">any</span><span class="p">).</span><span class="nx">webkitIndexedDB</span><span class="p">)</span>
<span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">DATABASE_NAME</span><span class="p">,</span> <span class="nx">VERSION</span><span class="p">);</span>

<span class="kd">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">resolve</span><span class="p">((</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span> <span class="k">as</span> <span class="kr">any</span><span class="p">).</span><span class="nx">result</span><span class="p">);</span>
  <span class="p">};</span>
  <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
  <span class="p">};</span>
  <span class="nx">request</span><span class="p">.</span><span class="nx">onupgradeneeded</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">db</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span> <span class="k">as</span> <span class="kr">any</span><span class="p">).</span><span class="nx">result</span><span class="p">;</span>
    <span class="nx">stores</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">store</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">db</span><span class="p">.</span><span class="nx">objectStoreNames</span><span class="p">.</span><span class="nx">contains</span><span class="p">(</span><span class="nx">store</span><span class="p">))</span> <span class="p">{</span>
        <span class="nx">db</span><span class="p">.</span><span class="nx">createObjectStore</span><span class="p">(</span><span class="nx">store</span><span class="p">);</span>
      <span class="p">}</span>
    <span class="p">});</span>
  <span class="p">};</span>

  <span class="nx">request</span><span class="p">.</span><span class="nx">onblocked</span> <span class="o">=</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
  <span class="p">};</span>

<span class="p">});</span>

<span class="kd">const</span> <span class="nx">indexedDBStorage</span> <span class="o">=</span> <span class="p">(</span><span class="nx">name</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
  <span class="kd">const</span> <span class="kd">get</span> <span class="o">=</span> <span class="p">(</span><span class="na">key</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="na">database</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readonly</span><span class="dl">"</span><span class="p">);</span>
    <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="na">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
      <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
    <span class="p">};</span>
    <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
    <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="na">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span> <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span> <span class="k">as</span> <span class="kr">any</span><span class="p">);</span> <span class="p">};</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
  <span class="p">}));</span>

  <span class="kd">const</span> <span class="nx">keys</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="na">database</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readonly</span><span class="dl">"</span><span class="p">);</span>
    <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="na">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
      <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
    <span class="p">};</span>
    <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
    <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">getAllKeys</span><span class="p">()</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="na">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span> <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span> <span class="k">as</span> <span class="kr">any</span><span class="p">);</span> <span class="p">};</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
  <span class="p">}));</span>

  <span class="kd">const</span> <span class="kd">set</span> <span class="o">=</span> <span class="p">(</span><span class="na">key</span><span class="p">:</span> <span class="kr">string</span><span class="p">,</span> <span class="na">value</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="na">database</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>
    <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="na">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
      <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
    <span class="p">};</span>
    <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
    <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">key</span><span class="p">);</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">resolve</span><span class="p">();</span>
    <span class="p">};</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
  <span class="p">}));</span>

  <span class="kd">const</span> <span class="nx">indexedDbDelete</span> <span class="o">=</span> <span class="p">(</span><span class="na">key</span><span class="p">:</span> <span class="kr">string</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="na">database</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>
    <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="na">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
      <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
    <span class="p">};</span>
    <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
    <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="nx">resolve</span><span class="p">;</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
  <span class="p">}));</span>

  <span class="kd">const</span> <span class="nx">purgeDatabase</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="na">database</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>
    <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="na">e</span><span class="p">:</span> <span class="kr">any</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">let</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
      <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
    <span class="p">};</span>
    <span class="kd">const</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
    <span class="kd">let</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="nx">resolve</span><span class="p">;</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
  <span class="p">}));</span>

  <span class="kd">const</span> <span class="nx">deleteDatabase</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nb">window</span><span class="p">.</span><span class="nx">indexedDB</span><span class="p">.</span><span class="nx">deleteDatabase</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">);</span>
  <span class="p">};</span>

  <span class="k">return</span> <span class="p">{</span>
    <span class="kd">get</span><span class="p">,</span>
    <span class="kd">set</span><span class="p">,</span>
    <span class="na">delete</span><span class="p">:</span> <span class="nx">indexedDbDelete</span><span class="p">,</span>
    <span class="nx">purgeDatabase</span><span class="p">,</span>
    <span class="nx">deleteDatabase</span><span class="p">,</span>
    <span class="nx">keys</span>
  <span class="p">};</span>
<span class="p">};</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">indexedDBStorage</span><span class="p">(</span><span class="nx">CACHE_STORE</span><span class="p">);</span>
</code></pre></div></div>

<p>Compiled Javascript:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">VERSION</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="kd">var</span> <span class="nx">CACHE_STORE</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">CACHE_STORE</span><span class="dl">"</span><span class="p">;</span>
  <span class="kd">var</span> <span class="nx">DATABASE_NAME</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">;</span>
  <span class="kd">var</span> <span class="nx">stores</span> <span class="o">=</span> <span class="p">[</span><span class="nx">CACHE_STORE</span><span class="p">];</span>
  <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="p">(</span>
    <span class="nb">window</span><span class="p">.</span><span class="nx">indexedDB</span> <span class="o">||</span>
    <span class="nb">window</span><span class="p">.</span><span class="nx">mozIndexedDB</span> <span class="o">||</span>
    <span class="nb">window</span><span class="p">.</span><span class="nx">webkitIndexedDB</span>
  <span class="p">).</span><span class="nx">open</span><span class="p">(</span><span class="nx">DATABASE_NAME</span><span class="p">,</span> <span class="nx">VERSION</span><span class="p">);</span>
  <span class="kd">var</span> <span class="nx">db</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span>
    <span class="p">};</span>

    <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
    <span class="p">};</span>

    <span class="nx">request</span><span class="p">.</span><span class="nx">onupgradeneeded</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">var</span> <span class="nx">db</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span>
      <span class="nx">stores</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">store</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">db</span><span class="p">.</span><span class="nx">objectStoreNames</span><span class="p">.</span><span class="nx">contains</span><span class="p">(</span><span class="nx">store</span><span class="p">))</span> <span class="p">{</span>
          <span class="nx">db</span><span class="p">.</span><span class="nx">createObjectStore</span><span class="p">(</span><span class="nx">store</span><span class="p">);</span>
        <span class="p">}</span>
      <span class="p">});</span>
    <span class="p">};</span>

    <span class="nx">request</span><span class="p">.</span><span class="nx">onblocked</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
    <span class="p">};</span>
  <span class="p">});</span>

  <span class="kd">var</span> <span class="nx">indexedDBStorage</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">indexedDBStorage</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="kd">get</span> <span class="o">=</span> <span class="kd">function</span> <span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">database</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
          <span class="kd">var</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readonly</span><span class="dl">"</span><span class="p">);</span>

          <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span> 
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
          <span class="p">};</span>

          <span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
          <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>

          <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span>
          <span class="p">};</span>

          <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
        <span class="p">});</span>
      <span class="p">});</span>
    <span class="p">};</span>

    <span class="kd">var</span> <span class="nx">keys</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">keys</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">database</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
          <span class="kd">var</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readonly</span><span class="dl">"</span><span class="p">);</span>

          <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span> 
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
          <span class="p">};</span>

          <span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
          <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">getAllKeys</span><span class="p">();</span>

          <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">resolve</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span>
          <span class="p">};</span>

          <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
        <span class="p">});</span>
      <span class="p">});</span>
    <span class="p">};</span>

    <span class="kd">var</span> <span class="kd">set</span> <span class="o">=</span> <span class="kd">function</span> <span class="kd">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">database</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
          <span class="kd">var</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>

          <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
          <span class="p">};</span>

          <span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
          <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span> <span class="nx">key</span><span class="p">);</span>

          <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
            <span class="nx">resolve</span><span class="p">();</span>
          <span class="p">};</span>

          <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
        <span class="p">});</span>
      <span class="p">});</span>
    <span class="p">};</span>

    <span class="kd">var</span> <span class="nx">indexedDbDelete</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">indexedDbDelete</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">database</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
          <span class="kd">var</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>

          <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
          <span class="p">};</span>

          <span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
          <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">[</span><span class="dl">"</span><span class="s2">delete</span><span class="dl">"</span><span class="p">](</span><span class="nx">key</span><span class="p">);</span>
          <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="nx">resolve</span><span class="p">;</span>
          <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
        <span class="p">});</span>
      <span class="p">});</span>
    <span class="p">};</span>

    <span class="kd">var</span> <span class="nx">purgeDatabase</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">purgeDatabase</span><span class="p">()</span> <span class="p">{</span>
      <span class="k">return</span> <span class="nx">db</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">database</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
          <span class="kd">var</span> <span class="nx">transaction</span> <span class="o">=</span> <span class="nx">database</span><span class="p">.</span><span class="nx">transaction</span><span class="p">([</span><span class="nx">name</span><span class="p">],</span> <span class="dl">"</span><span class="s2">readwrite</span><span class="dl">"</span><span class="p">);</span>

          <span class="nx">transaction</span><span class="p">.</span><span class="nx">onabort</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
            <span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">error</span><span class="p">;</span>
            <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
          <span class="p">};</span>

          <span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="nx">transaction</span><span class="p">.</span><span class="nx">objectStore</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
          <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">store</span><span class="p">.</span><span class="nx">clear</span><span class="p">();</span>
          <span class="nx">request</span><span class="p">.</span><span class="nx">onsuccess</span> <span class="o">=</span> <span class="nx">resolve</span><span class="p">;</span>
          <span class="nx">request</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="nx">reject</span><span class="p">;</span>
        <span class="p">});</span>
      <span class="p">});</span>
    <span class="p">};</span>

    <span class="kd">var</span> <span class="nx">deleteDatabase</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">deleteDatabase</span><span class="p">()</span> <span class="p">{</span>
      <span class="nb">window</span><span class="p">.</span><span class="nx">indexedDB</span><span class="p">.</span><span class="nx">deleteDatabase</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">origin</span><span class="p">);</span>
    <span class="p">};</span>

    <span class="k">return</span> <span class="p">{</span>
      <span class="na">get</span><span class="p">:</span> <span class="kd">get</span><span class="p">,</span>
      <span class="na">set</span><span class="p">:</span> <span class="kd">set</span><span class="p">,</span>
      <span class="na">delete</span><span class="p">:</span> <span class="nx">indexedDbDelete</span><span class="p">,</span>
      <span class="na">purgeDatabase</span><span class="p">:</span> <span class="nx">purgeDatabase</span><span class="p">,</span>
      <span class="na">deleteDatabase</span><span class="p">:</span> <span class="nx">deleteDatabase</span><span class="p">,</span>
      <span class="na">keys</span><span class="p">:</span> <span class="nx">keys</span>
    <span class="p">};</span>
  <span class="p">};</span>

  <span class="kd">var</span> <span class="nx">_default</span> <span class="o">=</span> <span class="nx">indexedDBStorage</span><span class="p">(</span><span class="nx">CACHE_STORE</span><span class="p">);</span>

  <span class="nb">window</span><span class="p">.</span><span class="nx">cacheStore</span> <span class="o">=</span> <span class="nx">_default</span><span class="p">;</span>
<span class="p">})();</span>
</code></pre></div></div>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[Creating a transactional promise based and fast IndexedDB key value wrapper]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/indexeddb.png" /><media:content medium="image" url="https://esstudio.site/uploads/indexeddb.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Export illustrator file to all important file formats.</title><link href="https://esstudio.site/2019/11/12/export-illustrator-file-to-all-important-file-formats.html" rel="alternate" type="text/html" title="Export illustrator file to all important file formats." /><published>2019-11-12T00:00:00+01:00</published><updated>2019-11-12T00:00:00+01:00</updated><id>https://esstudio.site/2019/11/12/export-illustrator-file-to-all-important-file-formats</id><content type="html" xml:base="https://esstudio.site/2019/11/12/export-illustrator-file-to-all-important-file-formats.html"><![CDATA[<h2 id="final-exportjsx">Final Export.jsx</h2>

<p><strong>Installation:</strong> Copy this file to your illustrator scripts folder:</p>

<p><em>For windows:</em> C:\Program Files\Adobe\Adobe Illustrator CC 2019\Presets\<your locale="">\\Scripts</your></p>

<p><em>For Mac:</em> Applications/Adobe Illustrator CC/Presets/<your locale="">/Scripts</your></p>

<p><strong>Usage:</strong> File-&gt;Scripts-&gt;Final Export</p>

<p><strong>Questions?</strong> Send me an email.</p>

<p><strong>Download link:</strong> <a href="https://gist.github.com/sempostma/4ee699a78a5cd0ccac150f95d78b0e9d/archive/597638138cd6d1357caf15af897c0067d4639f18.zip" title="Script downloaden">ZIP</a></p>

<p><strong>Output file structure:</strong></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  Output file structure:
  /&lt;choosen output folder&gt;
      /pictogram
           /&lt;choosen filename&gt;.jpg
           /&lt;choosen filename&gt;.png
      /icon
           /&lt;choosen filename&gt;.jpg
           /&lt;choosen filename&gt;.png
      /small
           /&lt;choosen filename&gt;.jpg
           /&lt;choosen filename&gt;.png
      /large
           /&lt;choosen filename&gt;.jpg
           /&lt;choosen filename&gt;.png
      /xlarge
           /&lt;choosen filename&gt;.jpg
           /&lt;choosen filename&gt;.png
      /&lt;choosen filename&gt;.ai
      /&lt;choosen filename&gt;.pdf
      /&lt;choosen filename&gt;.svg
      /&lt;choosen filename&gt;.jpg
      /&lt;choosen filename&gt;.png
      /&lt;choosen filename&gt;.dxf
      /&lt;choosen filename&gt;.eps
</code></pre></div></div>

<p><em>TIP: You can keep exporting different variations to the same output folder as long as you choose a different name when exporting. Be carefull, files can be overidden.</em></p>

<h2 id="source-gist">Source GIST:</h2>

<script src="https://gist.github.com/4ee699a78a5cd0ccac150f95d78b0e9d.js"> </script>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[Export Illustrator document to a buch of different file formats and resolutions. File formats include: .ai, .pdf, .png, .jpg and .svg. Installation: Copy this file to your illustrator scripts folder.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/adobe-illustrator-cc.svg" /><media:content medium="image" url="https://esstudio.site/uploads/adobe-illustrator-cc.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Editing Netlify CMS config.yml from Netlify CMS without plugins</title><link href="https://esstudio.site/2019/06/09/editing-netlify-cms-config-yml-from-netlify-cms-without-plugins.html" rel="alternate" type="text/html" title="Editing Netlify CMS config.yml from Netlify CMS without plugins" /><published>2019-06-09T00:00:00+02:00</published><updated>2019-06-09T00:00:00+02:00</updated><id>https://esstudio.site/2019/06/09/editing-netlify-cms-config-yml-from-netlify-cms-without-plugins</id><content type="html" xml:base="https://esstudio.site/2019/06/09/editing-netlify-cms-config-yml-from-netlify-cms-without-plugins.html"><![CDATA[<p>While experimenting I decided to see how much i could stretch the Netlify CMS capabilities regarding <a href="https://github.com/netlify/netlify-cms/issues/341">this issue</a>.</p>

<p>Turns out you can almost do it. It wasn’t completely possible due to these 2 issues:</p>

<ul>
  <li><a href="https://github.com/netlify/netlify-cms/issues/2360">self-referential / circular data structures cause “RangeError: Maximum call stack size exceeded” error</a></li>
  <li><a href="https://github.com/netlify/netlify-cms/issues/2363">Hidden fields don’t work when added through a list widget with variable types</a></li>
</ul>

<p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9732535637352249" data-ad-slot="6033478353" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script>	
(adsbygoogle = window.adsbygoogle || []).push({});	
</script></p>

<p>Because Netlify CMS can’t handle self-referential / circular data structures in the config.yml the file becomes very big and fields only work 1 depth down. For example my config can’t handle an object in an object in an object. You can get around this by increasing the depth but the file will become exponentially bigger. As it is, the file already has ~5000 😵 lines of code. Of course the upside is that you don’t have to look at it anymore…</p>

<p>Don’t use this in production. This could lead to data loss. This is an experiment, not a viable solution.</p>

<p>Add this to your config.yml:</p>

<div class="gist-maxheight">
<script src="https://gist.github.com/1c9a908c142b7f873e01fd6f2cfe5c1b.js?file=config.yml"> </script>
</div>

<p>I created a small <a href="https://github.com/sempostma/netlify-cms-config-generator">node utility</a> for creating the config from 2 different (less bulky) files.</p>

<p>Feel free to fork, tweak or otherwise change the code.</p>

<p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9732535637352249" data-ad-slot="6033478353" data-ad-format="auto" data-full-width-responsive="true"></ins>
<script>	
(adsbygoogle = window.adsbygoogle || []).push({});	
</script></p>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[While expereminting I decided to see how much i could stretch the netlify-cms capabilities regarding...]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/netlify-cms-cms-edit.png" /><media:content medium="image" url="https://esstudio.site/uploads/netlify-cms-cms-edit.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Markdown viewer for windows</title><link href="https://esstudio.site/2019/06/09/markdownify-markdown-viewer.html" rel="alternate" type="text/html" title="Markdown viewer for windows" /><published>2019-06-09T00:00:00+02:00</published><updated>2019-06-09T00:00:00+02:00</updated><id>https://esstudio.site/2019/06/09/markdownify-markdown-viewer</id><content type="html" xml:base="https://esstudio.site/2019/06/09/markdownify-markdown-viewer.html"><![CDATA[<p>Want a very simple, windows-themed, clean and easy to use markdown viewer? Checkout Mardownify: <a href="https://www.microsoft.com/p/markdownify/9npgxqvzj8c0" title="https://www.microsoft.com/p/markdownify/9npgxqvzj8c0">https://www.microsoft.com/p/markdownify/9npgxqvzj8c0</a></p>

<p>The Microsoft store is packed with markdown viewers and editors. Most of the markdown  apps are too expensive and overly complex. Some of those apps are already very old and don’t adhere to the windows 10 theme.</p>

<p>Markdownify is a simple and effective markdown/text file viewer. You can open any file in the markdown format. Markdownify can also view HTML files.</p>

<p>Source code: <a href="https://github.com/sempostma/markdownify/" title="https://github.com/sempostma/markdownify/">Github</a></p>

<div class="app-portal" style="width: 400px; max-width: 100%; padding: 10px">
    <img src="https://esstudio.site/uploads/md-editor.png" alt="" style="max-width: 50%; margin: 20px auto" />
    <h1>Markdownify</h1>
    <p>Markdown Viewer</p>
    <a class="btn" href="https://www.microsoft.com/p/markdownify/9npgxqvzj8c0">
        <span>Launch</span>
        <svg viewBox="0 0 10 18" style="height: 1.2em"><path d="m0.8,1l8,8l-8,8" fill="none" stroke-width="2" style="stroke: currentColor;" /></svg>
    </a>
</div>

<p>Click “File”-&gt;”Open” button in the toolbar to open files. You can also drag files into the app.</p>

<h2 id="file-associations">File Associations</h2>

<h3 id="markdown">Markdown</h3>

<ul>
  <li>markdown</li>
  <li>mdown</li>
  <li>mkdn</li>
  <li>md</li>
  <li>mkd</li>
  <li>mdwn</li>
  <li>mdtxt</li>
  <li>mdtext</li>
  <li>text</li>
  <li>Rmd</li>
</ul>

<h3 id="html">HTML</h3>

<ul>
  <li>html</li>
  <li>htm</li>
  <li>xhtml</li>
  <li>dhtml</li>
  <li>phtml</li>
  <li>jhtml</li>
  <li>mhtml</li>
  <li>rhtml</li>
  <li>shtml</li>
  <li>zhtml</li>
</ul>

<h2 id="other-releases">Other releases:</h2>

<p>You can check out the latest releases on <a href="https://github.com/sempostma/markdownify/releases" title="Latest Markdownify releases">Github</a> or follow the latest releases through the Newsfeeder app:</p>

<iframe style="background-color: #f5593d; width: 400px; height: 600px; box-shadow: 0 0 20px rgba(0,0,0,0.4)" src="https://newsfeeder.esstudio.site?feed=https%3A%2F%2Fgithub.com%2Fsempostma%2Fmarkdownify%2Freleases.atom&amp;site=https%3A%2F%2Fgithub.com%2Fsempostma%2Fmarkdownify%2Freleases&amp;description=&amp;title=markdownify%20Release%20Notes&amp;icon=https%3A%2F%2Fgithub.com%2Ffavicon.ico" frameborder="0"></iframe>

<p><a href="https://newsfeeder.esstudio.site?feed=https%3A%2F%2Fgithub.com%2Fsempostma%2Fmarkdownify%2Freleases.atom&amp;site=https%3A%2F%2Fgithub.com%2Fsempostma%2Fmarkdownify%2Freleases&amp;description=&amp;title=markdownify%20Release%20Notes&amp;icon=https%3A%2F%2Fgithub.com%2Ffavicon.ico" title="Open markdownify releases feed in the newsfeeder app."><img src="/uploads/newsfeeder.png" alt="A newsfeeder follow button for markdownify releases." title="Open releases for markdownify feed in newsfeeder." /></a></p>

<p>Download latest version: <a href="https://www.microsoft.com/p/markdownify/9npgxqvzj8c0" title="https://www.microsoft.com/p/markdownify/9npgxqvzj8c0">https://www.microsoft.com/p/markdownify/9npgxqvzj8c0</a></p>

<h2 id="copyright">Copyright</h2>

<p>Copyright © 2019 Sem Postma.</p>

<p>All rights reserved. No part of this software may be reproduced, distributed, or transmitted in any form or by any means without the prior written permission of the publisher, except certain noncommercial uses permitted by copyright law. For permission requests, contact the copyright holder.</p>

<p>copyright@esstudio.site
https://github.com/sempostma
https://esstudio.site/contact</p>

<p></p>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[Markdownify is a simple and effective markdown/text file viewer. You can open any file in the markdown format. Markdownify can also view HTML files.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/md-editor-1.png" /><media:content medium="image" url="https://esstudio.site/uploads/md-editor-1.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">All about debouncing, throttling and batching</title><link href="https://esstudio.site/2019/05/25/all-about-debouncing-and-throttling.html" rel="alternate" type="text/html" title="All about debouncing, throttling and batching" /><published>2019-05-25T00:00:00+02:00</published><updated>2019-05-25T00:00:00+02:00</updated><id>https://esstudio.site/2019/05/25/all-about-debouncing-and-throttling</id><content type="html" xml:base="https://esstudio.site/2019/05/25/all-about-debouncing-and-throttling.html"><![CDATA[<p>Failing to properly debounce or throttle taxing tasks in your javascript apps (or any other app for that matter) can really hurt performance. In this article i’ll list some examples of debounce and javascript functions.</p>

<p>If you are not up to date with debounce and throttle function, you check out<a href="https://css-tricks.com/debouncing-throttling-explained-examples/"> this css.tricks article</a> by <a href="https://css-tricks.com/author/dcorbacho/" title="https://css-tricks.com/author/dcorbacho/">dcorbacho</a>. A debounce or throttle function is actually just a way of limiting how much a function can be called. The window scroll event for example can fire hundreds of times for every interaction. If you’re doing some heavy javascript layout tasks, every time this event is fired, you’re website is going to be very janky. Another place where debounce and throttling functions are often used is with limiting ajax calls. Most autocomplete search boxes use some kind of debounce or throttle function because sending a request for every keypress will hurt your app a lot.</p>

<p>I stole the debounce  function from <a href="https://davidwalsh.name/">David Walsh</a> and the throttle function from a comment on the same article:</p>

<blockquote>
  <p><strong>Niall Campbell</strong></p>

  <p>Throttled can be simply achieved by changing the way the timeout is cleared/set. eg..</p>

  <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Returns a function, that, as long as it continues to be invoked, will only
// trigger every N milliseconds. If &lt;code&gt;immediate&lt;/code&gt; is passed, trigger the 
// function on the leading edge, instead of the trailing.
function throttle(func, wait, immediate) {
	var timeout;
	return function() {
		var context = this, args = arguments;
...
</code></pre></div>  </div>

  <p>Note that the timeout is not destroyed and recreated for every call (unlike debouncing). Its destroyed after the timeout has completed and created on the first call after its been destroyed.</p>
</blockquote>

<p>In simple terms, the function rate limits the amount of events to a certain time span. Visually a debounce function looks something like this:</p>

<p><img src="/uploads/debounce.gif" alt="" /></p>

<p>The debounce snippet:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="c1">// Returns a function, that, as long as it continues to be invoked, will not</span>
    <span class="c1">// be triggered. The function will be called after it stops being called for</span>
    <span class="c1">// N milliseconds. If `immediate` is passed, trigger the function on the</span>
    <span class="c1">// leading edge, instead of the trailing.</span>
    
    <span class="kd">var</span> <span class="nx">debounce</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">debounce</span><span class="p">(</span><span class="nx">func</span><span class="p">,</span> <span class="nx">wait</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">var</span> <span class="nx">timeout</span><span class="p">;</span>
      <span class="k">return</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">context</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
          <span class="nx">args</span> <span class="o">=</span> <span class="nx">arguments</span><span class="p">;</span>
    
        <span class="kd">var</span> <span class="nx">later</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">later</span><span class="p">()</span> <span class="p">{</span>
          <span class="nx">timeout</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">immediate</span><span class="p">)</span> <span class="nx">func</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">context</span><span class="p">,</span> <span class="nx">args</span><span class="p">);</span>
        <span class="p">};</span>
    
        <span class="kd">var</span> <span class="nx">callNow</span> <span class="o">=</span> <span class="nx">immediate</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">timeout</span><span class="p">;</span>
        <span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
        <span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">later</span><span class="p">,</span> <span class="nx">wait</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">callNow</span><span class="p">)</span> <span class="nx">func</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">context</span><span class="p">,</span> <span class="nx">args</span><span class="p">);</span>
      <span class="p">};</span>
    <span class="p">};</span>
    
    <span class="c1">// window.onscroll = debounce(200)(function() { </span>
    <span class="c1">// 	console.log(window.pageYOffset ) </span>
    <span class="c1">// });</span>
</code></pre></div></div>

<p>The throttle snippet:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="c1">// Returns a function, that, as long as it continues to be invoked, will only</span>
    <span class="c1">// trigger every N milliseconds. If `immediate` is passed, trigger the</span>
    <span class="c1">// function on the leading edge, instead of the trailing.</span>
    
    <span class="kd">var</span> <span class="nx">throttle</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">throttle</span><span class="p">(</span><span class="nx">func</span><span class="p">,</span> <span class="nx">wait</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="p">{</span>
      <span class="kd">var</span> <span class="nx">timeout</span><span class="p">;</span>
      <span class="k">return</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="kd">var</span> <span class="nx">context</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span>
          <span class="nx">args</span> <span class="o">=</span> <span class="nx">arguments</span><span class="p">;</span>
    
        <span class="kd">var</span> <span class="nx">later</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">later</span><span class="p">()</span> <span class="p">{</span>
          <span class="nx">timeout</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
          <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">immediate</span><span class="p">)</span> <span class="nx">func</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">context</span><span class="p">,</span> <span class="nx">args</span><span class="p">);</span>
        <span class="p">};</span>
    
        <span class="kd">var</span> <span class="nx">callNow</span> <span class="o">=</span> <span class="nx">immediate</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">timeout</span><span class="p">;</span>
        <span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timeout</span><span class="p">);</span>
        <span class="nx">timeout</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">later</span><span class="p">,</span> <span class="nx">wait</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">callNow</span><span class="p">)</span> <span class="nx">func</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">context</span><span class="p">,</span> <span class="nx">args</span><span class="p">);</span>
      <span class="p">};</span>
    <span class="p">};</span>
    
    
    <span class="c1">// window.onscroll = throttle(200)(function() { </span>
    <span class="c1">// 	console.log(window.pageYOffset ) </span>
    <span class="c1">// });</span>
</code></pre></div></div>

<p>The comments already explain the ‘immediate’ parameter. The basic difference is that without the ‘immediate’ parameter the function will wait and then fire. If the ‘immediate’ parameter is set to true it will fire and then wait. Be aware that if you set the ‘immediate’ parameter, the function won’t always fire at or after the last event because it might still be waiting because of a previous event. If ‘immediate’ is set to true the function will always fire after or at the last event. This can get you into trouble if you’re sending data or if you have to make sure you always have the latest. Only set the ‘immediate’ parameter if you know what you’re doing.</p>

<p class="codepen" data-height="478" data-theme-id="35834" data-default-tab="js,result" data-user="Afirus" data-slug-hash="NVMjJV" style="height: 478px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="NVMjJV">
<span>See the Pen <a href="https://codepen.io/Afirus/pen/NVMjJV/">
NVMjJV</a> by sempostma (<a href="https://codepen.io/Afirus">@Afirus</a>)
on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async="" src="https://static.codepen.io/assets/embed/ei.js"></script>

<p>In some cases you want to all the data from all of the events but you still want debouncing/throttling behavior:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">update</span> <span class="o">=</span> <span class="nx">debounce</span><span class="p">(</span><span class="mi">500</span><span class="p">)(</span><span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// doFakeAjaxRequest(payload);</span>
	<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="p">});</span>

<span class="kd">let</span> <span class="nx">delay</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">All</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">of</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">these</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">arguments</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">600</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">are</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">not</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">batched</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
</code></pre></div></div>

<p>If you don’t want event data to be lost you can use this function to get all of the arguments since the last time the debounce/throttle function fired:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">batched</span> <span class="o">=</span> <span class="nx">delayedFunc</span> <span class="o">=&gt;</span> <span class="nx">func</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">stack</span> <span class="o">=</span> <span class="p">[];</span>
    <span class="kd">const</span> <span class="nx">handler</span> <span class="o">=</span> <span class="nx">delayedFunc</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">func</span><span class="p">(</span><span class="nx">stack</span><span class="p">);</span>
        <span class="nx">stack</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
    <span class="p">});</span>
    <span class="k">return</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="nx">stack</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span> <span class="na">context</span><span class="p">:</span> <span class="k">this</span><span class="p">,</span> <span class="na">args</span><span class="p">:</span> <span class="nx">arguments</span> <span class="p">});</span>
        <span class="nx">handler</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Use the following snippets:</p>

<p>The debounce snippet:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.

var debounce = function debounce(wait, immediate) {
  return function(func) {
    var timeout;
    return function() {
      var context = this,
        args = arguments;

      var later = function later() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };

      var callNow = immediate &amp;&amp; !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) func.apply(context, args);
    };
  };
};

// window.onscroll = debounce(200)(function() { 
// 	console.log(window.pageYOffset ) 
// });
</code></pre></div></div>

<p>The throttle snippet:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Returns a function, that, as long as it continues to be invoked, will only
// trigger every N milliseconds. If `immediate` is passed, trigger the
// function on the leading edge, instead of the trailing.
var throttle = function throttle(wait, immediate) {
  return function(func) {
    var timeout;
    return function() {
      var context = this,
        args = arguments;

      var later = function later() {
        timeout = null;
        if (!immediate) func.apply(context, args);
      };

      var callNow = immediate &amp;&amp; !timeout;
      clearTimeout(timeout);
      if (!timeout) timeout = setTimeout(later, wait);
      if (callNow) func.apply(context, args);
    };
  };
};

// window.onscroll = throttle(200)(function() { 
// 	console.log(window.pageYOffset ) 
// });
</code></pre></div></div>

<p>And then change your code to this:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">update</span> <span class="o">=</span> <span class="nx">batched</span><span class="p">(</span><span class="nx">debounce</span><span class="p">(</span><span class="mi">500</span><span class="p">))(</span><span class="kd">function</span><span class="p">(</span><span class="nx">stackedEvents</span><span class="p">)</span> <span class="p">{</span>
	<span class="kd">var</span> <span class="nx">payload</span> <span class="o">=</span> <span class="nx">stackedEvents</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">frame</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">return</span> <span class="nx">frame</span><span class="p">.</span><span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
	<span class="p">}).</span><span class="nx">join</span><span class="p">(</span><span class="dl">'</span><span class="s1"> </span><span class="dl">'</span><span class="p">);</span>
    <span class="c1">// doFakeAjaxRequest(payload);</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">payload</span><span class="p">);</span>
<span class="p">});</span>

<span class="kd">let</span> <span class="nx">delay</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">All</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">of</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">these</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">arguments</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">600</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">are</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">being</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="nx">update</span><span class="p">(</span><span class="dl">'</span><span class="s1">batched</span><span class="dl">'</span><span class="p">),</span> <span class="nx">delay</span> <span class="o">+=</span> <span class="mi">300</span><span class="p">);</span>
</code></pre></div></div>

<p>Which will result in:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>index.js:85 All of these 
index.js:85 arguments are being batched
</code></pre></div></div>

<p> </p>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[Failing to properly use debounce or throttle taxing tasks your javascript apps (or any other app for that matter) can really hurt performance. In this article i'll list some examples of debounce and javascript functions.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/throttle_debounce.gif" /><media:content medium="image" url="https://esstudio.site/uploads/throttle_debounce.gif" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry xml:lang="en"><title type="html">Mindviewer - Create multi-user realtime editable mindmaps</title><link href="https://esstudio.site/2019/04/26/mindviewer-create-mult-user-realtime-editable-mindmaps.html" rel="alternate" type="text/html" title="Mindviewer - Create multi-user realtime editable mindmaps" /><published>2019-04-26T00:00:00+02:00</published><updated>2019-04-26T00:00:00+02:00</updated><id>https://esstudio.site/2019/04/26/mindviewer-create-mult-user-realtime-editable-mindmaps</id><content type="html" xml:base="https://esstudio.site/2019/04/26/mindviewer-create-mult-user-realtime-editable-mindmaps.html"><![CDATA[<p>I created a web based realtime <a href="https://t.co/Ub1xTZW6cm">multi-user mindmapper</a>. It’s currently free to use and I’m looking for feedback. You can try it by <a href="https://t.co/Ub1xTZW6cm">opening</a> the same mindmapper in 2 different tabs.</p>

<p><img src="/uploads/small-card.png" alt="" /></p>

<p>You can connect to the other mindmap by creating a public mindmap and then clicking the share icon:</p>

<p><img src="https://pbs.twimg.com/media/D5AXD8KX4AISINT.png" alt="" /></p>

<p>An example mindmap: <a href="https://mindviewer.esstudio.site/mindmapper.html?firestore=true&amp;ispublic=true&amp;room=l7nQoP3a5ni5mBkzApZY&amp;theme=minimalistic" title="https://mindviewer.esstudio.site/mindmapper.html?firestore=true&amp;ispublic=true&amp;room=l7nQoP3a5ni5mBkzApZY&amp;theme=minimalistic">https://mindviewer.esstudio.site/mindmapper.html?firestore=true&amp;ispublic=true&amp;room=l7nQoP3a5ni5mBkzApZY&amp;theme=minimalistic</a></p>

<p>If you open this in multiple chrome browser tabs you will notice that the mindmaps update in realtime. I’m currently working on perfecting the exporting to image and html feature.</p>

<p>Using the <img src="/uploads/edit.png" alt="" /> icon you can change the background of your mindmap. This change is not synced to the other tabs so every user can have their own theme and custom background.</p>

<p>If you click the <img src="/uploads/home.png" alt="" /> icon you go back to the home screen (don’t forget to save you’re changes by on one of the save buttons). You can download the mindmap by going to Mindviews-&gt;”Example mindmap”-&gt;Download.</p>

<p>The mindmaps are stored in a human readable format. You can view the stored information by opening the “.onmm” file with <a href="https://json-gui.esstudio.site" title="https://json-gui.esstudio.site">https://json-gui.esstudio.site</a> File-&gt;Open from disk. You can make changes to your mindmap, save and open the newly created file in mindviewer by going to “Import mindmap” and dragging the mindmap into the file dropzone.</p>

<p>With mindviewer you can create mindmaps with other users in real-time. Support for saving mindmaps to google drive and your local machine coming soon. If you want to give feedback or tips, please send a message: mindviewer@esstudio.site or use the contact form: esstudio.site/contact.</p>

<div class="app-portal" style="width: 400px; max-width: 100%; padding: 10px">
    <img src="https://esstudio.site/uploads/logo-quicklaunch.png" alt="" style="max-width: 50%; margin: 20px auto" />
    <h1>Mindviewer Quick-launch</h1>
    <p>Mindviewer is a HTML5 web app which allows real-time mindmap building with multiple users.</p>
    <a class="btn" href="https://chrome.google.com/webstore/detail/mindviewer-quick-launch/djjbfgojcdebfjeabdofdflmhmoadclb">
        <span>Launch</span>
        <svg viewBox="0 0 10 18" style="height: 1.2em"><path d="m0.8,1l8,8l-8,8" fill="none" stroke-width="2" style="stroke: currentColor;" /></svg>
    </a>
</div>]]></content><author><name>Sem Postma</name></author><summary type="html"><![CDATA[Mindviewer is a HTML5 web app which allows realtime mindmap building with multiple users.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://esstudio.site/uploads/screenshot%20(3).png" /><media:content medium="image" url="https://esstudio.site/uploads/screenshot%20(3).png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>