<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrea Giammarchi</title>
    <description>The latest articles on DEV Community by Andrea Giammarchi (@webreflection).</description>
    <link>https://dev.to/webreflection</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2372%2Fb7488602-050a-43a2-931a-03106c0c9370.jpg</url>
      <title>DEV Community: Andrea Giammarchi</title>
      <link>https://dev.to/webreflection</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/webreflection"/>
    <language>en</language>
    <item>
      <title>Using LiteFS with Bun on Fly.io</title>
      <dc:creator>Andrea Giammarchi</dc:creator>
      <pubDate>Fri, 24 Feb 2023 06:57:30 +0000</pubDate>
      <link>https://dev.to/webreflection/using-litefs-with-bun-on-flyio-17m7</link>
      <guid>https://dev.to/webreflection/using-litefs-with-bun-on-flyio-17m7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;br&gt;
There is &lt;a href="https://github.com/WebReflection/fly-bun-sqlite#readme" rel="noopener noreferrer"&gt;a repository to fork and try&lt;/a&gt; that simplifies this whole post, specially after latest development with Fly and Bun.&lt;/p&gt;




&lt;p&gt;As neither &lt;a href="https://bun.sh/" rel="noopener noreferrer"&gt;Bun&lt;/a&gt; nor &lt;a href="https://fly.io/docs/litefs/" rel="noopener noreferrer"&gt;LiteFS&lt;/a&gt; are recommended for production yet, I’ve decided it was obviously a good idea to deploy “&lt;em&gt;their synergy&lt;/em&gt;” on &lt;a href="https://fly.io/" rel="noopener noreferrer"&gt;fly.io&lt;/a&gt; 😇&lt;/p&gt;

&lt;p&gt;“&lt;em&gt;… but why?&lt;/em&gt;” … well, this is why!&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Bun very good at:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuezr11lk1sllqqxdcig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuezr11lk1sllqqxdcig.png" alt="serving performance" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it’s very fast at bootstrapping, making it ideal for lambdas cold and hot starts, together with docker based containers 🌟&lt;/li&gt;
&lt;li&gt;it’s very fast at serving, making it an ideal runtime for anything cloud related (plus it’s TS/JSX compatible without extra tooling needed!) 🌈&lt;/li&gt;
&lt;li&gt;it’s the fastest JS/TS runtime out there when it comes to SQLite 🦄 … as a matter of fact, bun has SQLite directly built and bound in its core so that it easily competes with any other typed PL with SQLite bindings 🚀&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What’s LiteFS on Fly.io very good at:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu622l2vhpjcpmwbswod.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvu622l2vhpjcpmwbswod.png" alt="sqlite performance" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;    it provides for free a whole GB of mounted filesystem that could host 1 to many SQLite databases (1GB is a lot of text!!!) 🤩&lt;/li&gt;
&lt;li&gt;it can replicate and sync databases across the globe when/if needed (pay as you go or proper plan needed but we can start for free) 🥳&lt;/li&gt;
&lt;li&gt;fly.io allows any Docker image, so that we can test both locally and deploy in production with ease 🤠&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of that, the landscape around SQLite as hosted solution is nowhere nearly as simple and well done as it is for &lt;em&gt;fly.io&lt;/em&gt; setup, which we’re going to check in details now!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Project Tree
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnd5mqhkpq8ofry7ipqj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxnd5mqhkpq8ofry7ipqj.png" alt=" " width="447" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;litefs&lt;/strong&gt; folder is used instead of the real mounted &lt;em&gt;litefs&lt;/em&gt; path whenever we’re testing locally and/or not in production. Let’s just type &lt;code&gt;mkdir litefs&lt;/code&gt; in the directory we’d like to use to test this setup via &lt;code&gt;bun run start&lt;/code&gt; (or &lt;code&gt;bun start&lt;/code&gt; or even &lt;code&gt;npm start&lt;/code&gt; if node is present and bun available)&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;.dockerignore&lt;/code&gt; file contains all possible stuff we shouldn’t push to docker&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;Dockerfile&lt;/code&gt; contains the &lt;a href="https://github.com/oven-sh/bun/blob/bun-v0.5.4/dockerhub/Dockerfile" rel="noopener noreferrer"&gt;bun’s official alpine based docker image&lt;/a&gt; (it’s ~100MB in total 😍) plus a few commands to bootstrap the server&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;fly.toml&lt;/code&gt; contains a mix of what scaffolding &lt;a href="https://fly.io/docs/languages-and-frameworks/node/" rel="noopener noreferrer"&gt;Nodejs&lt;/a&gt; and &lt;a href="https://fly.io/docs/litefs/example/#set-up-your-fly-io-config" rel="noopener noreferrer"&gt;LiteFS&lt;/a&gt; prepared examples would look like&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;litefs.js&lt;/code&gt; file handles the database connection as unique module entry point, plus some template literal based utilities&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;package.json&lt;/code&gt; is used to provide a &lt;code&gt;start&lt;/code&gt; command and optional dependencies&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;serve.js&lt;/code&gt; file simply starts a server demo that show some welcome and all the rows in the dummy/example SQLite database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All files are going to be shown with their content too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before we start
&lt;/h3&gt;

&lt;p&gt;The easiest way to scaffold a fly.io project is to use &lt;code&gt;fly apps create&lt;/code&gt;, which will generate a unique &lt;code&gt;YOUR_FLY_APP_NAME&lt;/code&gt; (see &lt;em&gt;fly.toml&lt;/em&gt; later on) and it will give you indications of regions you can use to deploy your app, then you need to &lt;a href="https://fly.io/docs/litefs/example/#creating-a-volume" rel="noopener noreferrer"&gt;create your LiteFS volume&lt;/a&gt;, using your closest free allowed location.&lt;/p&gt;

&lt;p&gt;P.S. use the &lt;a href="https://fly.io/docs/litefs/example/" rel="noopener noreferrer"&gt;LiteFS example&lt;/a&gt; if you don’t know where or how to start, as it’s been updated recently and it really works out of the box as a started (but it uses GO, which “&lt;em&gt;can go&lt;/em&gt;” (dehihi) right after 😉&lt;/p&gt;

&lt;p&gt;Once you’ve done that, each file in the list is mandatory and this is what I have as each file content:&lt;/p&gt;

&lt;h3&gt;
  
  
  .dockerignore
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.git
litefs
node_modules
.dockerignore
bun.lockb
Dockerfile
fly.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;### GLOBALS ###&lt;/span&gt;
ARG &lt;span class="nv"&gt;GLIBC_RELEASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2.34-r0


&lt;span class="c"&gt;### GET ###&lt;/span&gt;
FROM alpine:latest as get

&lt;span class="c"&gt;# prepare environment&lt;/span&gt;
WORKDIR /tmp
RUN apk &lt;span class="nt"&gt;--no-cache&lt;/span&gt; add unzip

&lt;span class="c"&gt;# get bun&lt;/span&gt;
ADD https://github.com/oven-sh/bun/releases/latest/download/bun-linux-x64.zip bun-linux-x64.zip
RUN unzip bun-linux-x64.zip

&lt;span class="c"&gt;# get glibc&lt;/span&gt;
ARG GLIBC_RELEASE
RUN wget https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLIBC_RELEASE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/glibc-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLIBC_RELEASE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.apk


&lt;span class="c"&gt;### IMAGE ###&lt;/span&gt;
FROM alpine:latest

&lt;span class="c"&gt;# install bun&lt;/span&gt;
COPY &lt;span class="nt"&gt;--from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;get /tmp/bun-linux-x64/bun /usr/local/bin

&lt;span class="c"&gt;# prepare glibc&lt;/span&gt;
ARG GLIBC_RELEASE
COPY &lt;span class="nt"&gt;--from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;get /tmp/sgerrand.rsa.pub /etc/apk/keys
COPY &lt;span class="nt"&gt;--from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;get /tmp/glibc-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLIBC_RELEASE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.apk /tmp

&lt;span class="c"&gt;# install glibc&lt;/span&gt;
RUN apk &lt;span class="nt"&gt;--no-cache&lt;/span&gt; &lt;span class="nt"&gt;--force-overwrite&lt;/span&gt; add /tmp/glibc-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLIBC_RELEASE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="c"&gt;# cleanup&lt;/span&gt;
    &lt;span class="nb"&gt;rm&lt;/span&gt; /etc/apk/keys/sgerrand.rsa.pub &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nb"&gt;rm&lt;/span&gt; /tmp/glibc-&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLIBC_RELEASE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;.apk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;

&lt;span class="c"&gt;# smoke test&lt;/span&gt;
    bun &lt;span class="nt"&gt;--version&lt;/span&gt;

&lt;span class="c"&gt;#######################################################################&lt;/span&gt;

RUN &lt;span class="nb"&gt;mkdir&lt;/span&gt; /app
WORKDIR /app

&lt;span class="c"&gt;# NPM will not install any package listed in "devDependencies" when NODE_ENV is set to "production",&lt;/span&gt;
&lt;span class="c"&gt;# to install all modules: "npm install --production=false".&lt;/span&gt;
&lt;span class="c"&gt;# Ref: https://docs.npmjs.com/cli/v9/commands/npm-install#description&lt;/span&gt;

ENV NODE_ENV production

COPY &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

RUN bun &lt;span class="nb"&gt;install

&lt;/span&gt;LABEL &lt;span class="nv"&gt;fly_launch_runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bun"&lt;/span&gt;

WORKDIR /app
ENV NODE_ENV production
CMD &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"bun"&lt;/span&gt;, &lt;span class="s2"&gt;"run"&lt;/span&gt;, &lt;span class="s2"&gt;"start"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  fly.toml
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"YOUR_FLY_APP_NAME"&lt;/span&gt;
&lt;span class="py"&gt;kill_signal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"SIGINT"&lt;/span&gt;
&lt;span class="py"&gt;kill_timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="py"&gt;processes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="nn"&gt;[env]&lt;/span&gt;
  &lt;span class="py"&gt;PORT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"8080"&lt;/span&gt;

&lt;span class="nn"&gt;[experimental]&lt;/span&gt;
  &lt;span class="py"&gt;auto_rollback&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="py"&gt;enable_consul&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[mounts]&lt;/span&gt;
  &lt;span class="py"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"litefs"&lt;/span&gt;
  &lt;span class="py"&gt;destination&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/var/lib/litefs"&lt;/span&gt;

&lt;span class="nn"&gt;[[services]]&lt;/span&gt;
  &lt;span class="py"&gt;http_checks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="py"&gt;internal_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;
  &lt;span class="py"&gt;processes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="py"&gt;protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"tcp"&lt;/span&gt;
  &lt;span class="py"&gt;script_checks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="nn"&gt;[services.concurrency]&lt;/span&gt;
    &lt;span class="py"&gt;hard_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
    &lt;span class="py"&gt;soft_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
    &lt;span class="py"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"connections"&lt;/span&gt;

  &lt;span class="nn"&gt;[[services.ports]]&lt;/span&gt;
    &lt;span class="py"&gt;force_https&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="py"&gt;handlers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;

  &lt;span class="nn"&gt;[[services.ports]]&lt;/span&gt;
    &lt;span class="py"&gt;handlers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"tls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;

  &lt;span class="nn"&gt;[[services.tcp_checks]]&lt;/span&gt;
    &lt;span class="py"&gt;grace_period&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1s"&lt;/span&gt;
    &lt;span class="py"&gt;interval&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"15s"&lt;/span&gt;
    &lt;span class="py"&gt;restart_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="py"&gt;timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2s"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  litefs.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bun:sqlite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;createSQLiteTags&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;better-tags&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// use mounted point on production, use local folder otherwise&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;litefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/var/lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;litefs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// if litefs folder doesn't exist get out!&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;litefs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unable to reach&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;litefs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// shared db + template literals  based utilities&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nf"&gt;createSQLiteTags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;litefs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;///////////////////////////////////////////////////////////////&lt;/span&gt;
&lt;span class="c1"&gt;// FOR DEMO SAKE ONLY - EXECUTED ON EACH DEPLOY&lt;/span&gt;
&lt;span class="c1"&gt;///////////////////////////////////////////////////////////////&lt;/span&gt;

&lt;span class="c1"&gt;// some table schema&lt;/span&gt;
&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="s2"&gt;`
  CREATE TABLE IF NOT EXISTS persons (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    phone TEXT NOT NULL,
    company TEXT NOT NULL
  )
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// some table entry&lt;/span&gt;
&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="s2"&gt;`
  INSERT INTO persons
    (name, phone, company)
  VALUES
    (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
      &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;())).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\d]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, 'fly.io')
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  package.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flying-bun"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A Bun &amp;amp; LiteFS love 💘 affair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bun serve.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"better-tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.1.2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  serve.js
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bun&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// grab the db or some utility&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./litefs.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// grab the port and start the server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;h1&amp;gt;Hello From Bun on Fly!&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;pre&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="s2"&gt;`SELECT * FROM persons ORDER BY id DESC`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/pre&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/html; charset=utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Uh oh!!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;port&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Flying Bun app listening on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy Bun on LiteFS
&lt;/h3&gt;

&lt;p&gt;That’s pretty much it, once you have a unique app name, a LiteFS mounted directory you can reach, and the provided code, you can either &lt;code&gt;bun run start&lt;/code&gt; locally, maybe after a &lt;code&gt;bun install&lt;/code&gt; or an &lt;code&gt;npm install&lt;/code&gt;, and finally &lt;code&gt;fly deploy&lt;/code&gt; to see your “&lt;em&gt;hello bun&lt;/em&gt;” running from the cloud 🌤&lt;/p&gt;

&lt;p&gt;If everything went fine, you should be able to reach &lt;code&gt;https://YOUR_FLY_APP_NAME.fly.dev&lt;/code&gt; and see at least one record shown in the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqn80i9i2x76lqgvs4io.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqn80i9i2x76lqgvs4io.png" alt="the deployed app example" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Some metrics
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzx0qchkzvfggfgc6amw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzx0qchkzvfggfgc6amw.png" alt="36 MB out of 232 MB RAM used" width="611" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The basic alpine image with just &lt;em&gt;bun&lt;/em&gt; and &lt;em&gt;glibc&lt;/em&gt; on it, plus the project files, should consume no more than 40MB of RAM out of the 232 MB allowed, but the cool part of &lt;em&gt;fly.io&lt;/em&gt; is that we can always opt in for a pay as you go plan to scale CPUs, RAM, replicated databases, or increase the mounted DB size too with ease, whenever we’ll manage to reach 1 GB of mounted &lt;em&gt;LiteFS&lt;/em&gt; file size limit. A detailed guide on &lt;a href="https://fly.io/docs/reference/volumes/" rel="noopener noreferrer"&gt;how to manage fly volumes can be found here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  And That’s All Folks 🥳
&lt;/h3&gt;

&lt;p&gt;Congratulations! You’ve learned how to deploy your next bun project on the cloud and with a free database solution that will host up to a GB for free and not limited to a single DB, so that separating concerns per DB is also a possibility (1 for IP geo-location, 1 for blog text, 1 for users to admin, 1 for …)&lt;/p&gt;

&lt;p&gt;The most under-estimated part of SQLite as database, beside being the coolest embedded database that exists on earth, is that no secret user and password would ever leak, and fly.io mounted filesystems are also encrypted so that a whole class of security concerns is automatically removed from all equations and responsibilities for people sharing code, like I’ve just done in here 👋&lt;/p&gt;

</description>
      <category>bunjs</category>
      <category>javascript</category>
      <category>ts</category>
      <category>sqlite</category>
    </item>
    <item>
      <title>About bitwise operations</title>
      <dc:creator>Andrea Giammarchi</dc:creator>
      <pubDate>Fri, 08 Oct 2021 15:07:07 +0000</pubDate>
      <link>https://dev.to/webreflection/about-bitwise-operations-29mm</link>
      <guid>https://dev.to/webreflection/about-bitwise-operations-29mm</guid>
      <description>&lt;p&gt;In 20+ years of programming, I've never needed to invert a binary tree except for that one time a silly interviewer asked me to do that for a web-related role. I have, however, encountered bitwise operations in hundreds of real-world situations. Incredibly enough, after the initial learning curve, I've never doubted that it was the right solution for these situations. &lt;/p&gt;

&lt;p&gt;This post hopes to explain why bitwise operations are one of the best ways to actually reduce complexity and why they are so special!&lt;/p&gt;

&lt;h2&gt;
  
  
  Think like "&lt;em&gt;strings&lt;/em&gt;", not numbers!
&lt;/h2&gt;

&lt;p&gt;If we try to do decimal math with &lt;em&gt;ones&lt;/em&gt; and &lt;em&gt;zeroes&lt;/em&gt;, we won't likely understand bitwise operators or go too far ... so let's start with the basics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// left shift operator:&lt;/span&gt;
&lt;span class="c1"&gt;// how many `0` after `1`?&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 00001&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 00010&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 00100&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 01000&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 10000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key take here is that we don't really need to care about what number those "&lt;em&gt;binary strings&lt;/em&gt;" represent, but if you really want to know, you can &lt;code&gt;console.log(A, B, C, D, E)&lt;/code&gt; and figure it out, right? 😊&lt;/p&gt;

&lt;p&gt;Also, remember, &lt;code&gt;num.toString(2)&lt;/code&gt; will always produce the binary string representation, which is handy while exploring this field ... let's start now!&lt;/p&gt;

&lt;h2&gt;
  
  
  The AND and the OR
&lt;/h2&gt;

&lt;p&gt;The binary math with these two is pretty simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;amp; is like boolean &amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="err"&gt;✖&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;✖&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="err"&gt;✖&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;✔&lt;/span&gt;

&lt;span class="c1"&gt;// | is like boolean ||&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="err"&gt;✖&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;✔&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="err"&gt;✔&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="err"&gt;✔&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As simple as that looks, we can already do amazing things with just these two operators!&lt;/p&gt;

&lt;p&gt;Let's see how &lt;em&gt;grouping&lt;/em&gt; works, as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(A | B)
A       00001 |
B       00010 =
        00011

(A | C)
A       00001 |
C       00100 =
        00101

(A | B | D)
A       00001 |
B       00010 |
D       01000 =
        01011
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A great feature to consider is that we can put together any combination, without ever caring about the order, so that &lt;code&gt;(A | B | D)&lt;/code&gt; is always identical to &lt;code&gt;(B | D | A)&lt;/code&gt;, and to &lt;code&gt;(D | A | B)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On top of that, we can easily check if a specific char is part of the group, using the &lt;code&gt;&amp;amp;&lt;/code&gt; operator, which is true only if there is a &lt;code&gt;1&lt;/code&gt; at the same position of one of the positions the group covers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(A | B) &amp;amp; A

00011 &amp;amp;
00001 =
00001 ✔


(A | C) &amp;amp; B

00101 &amp;amp;
00010 =
00000 ✖


(A | B | D) &amp;amp; D;

01011 &amp;amp;
01000 =
01000 ✔


(A | B | D) &amp;amp; C;

01011 &amp;amp;
00100 =
00000 ✖


// multiple groups inclusion
(A | B | D) &amp;amp; (A | C);

01011 &amp;amp;
00101 =
00001 ✔
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations, you've just learned how most permissions related logic works 🥳&lt;/p&gt;

&lt;p&gt;Moreover, if each permission has a mask, adding another permission to a user/group would be an &lt;code&gt;|=&lt;/code&gt; operation away.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user.permission = GUEST;

if (user.groups.has(developer))
  user.permission |= DEVELOPER;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... and because &lt;code&gt;101 | 101&lt;/code&gt; will produce again &lt;code&gt;101&lt;/code&gt;, it's always safe to add a permission, without needing to check it was already there.&lt;/p&gt;

&lt;p&gt;But how to remove a value from a group?&lt;/p&gt;

&lt;h2&gt;
  
  
  The XOR
&lt;/h2&gt;

&lt;p&gt;This operator flips to &lt;code&gt;0&lt;/code&gt; "&lt;em&gt;columns&lt;/em&gt;" with the same value, producing &lt;code&gt;1&lt;/code&gt; in all other cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ^ is like a != comparison
0 ^ 0 ✖
0 ^ 1 ✔
1 ^ 0 ✔
1 ^ 1 ✖
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While its nature looks awesome to "&lt;em&gt;rotate&lt;/em&gt;" &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; around, it also does a good job at dropping values from a group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(A | B) ^ A

00011 ^
00001 =
00010 B


(A | B | D) ^ D;

01011 ^
01000 =
00011 (A | B)


(A | B | D) ^ B;

01011 ^
00010 =
01001 (A | D)


// multiple groups removal
(A | B | D) ^ (A | D);

01011 ^
01001 =
00010 B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚠ WARNING
&lt;/h3&gt;

&lt;p&gt;As previously mentioned, an OR &lt;code&gt;|&lt;/code&gt; operator doesn't need checks upfront to be performed, but an XOR &lt;code&gt;^&lt;/code&gt; operator requires mandatory checks before a value can be removed from a group because otherwise it &lt;em&gt;adds&lt;/em&gt; the value to the group itself!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// C was not in the group before
(A | B | D) ^ C;

01011 ^
00100 =
01111 (A | B | C | D)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule of thumb with XOR in a nutshell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;was it there? it'll go away&lt;/li&gt;
&lt;li&gt;wasn't it there? it'll be added&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thinking about boolean operations, a unique digit XOR does what a &lt;code&gt;ref = !ref&lt;/code&gt; does to a mutable, boolean, reference, and indeed it could be used as "&lt;em&gt;toggle operator&lt;/em&gt;":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 0 ^ 1 === 1&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 1 ^ 1 === 0&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;false&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 0 ^ 1 === 1&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, Ok, this is way too far already ... but I hope we got how powerful, or destructive, could be an XOR &lt;code&gt;^&lt;/code&gt; in the wild, which is why the &lt;strong&gt;tilde&lt;/strong&gt; &lt;em&gt;NOT&lt;/em&gt; operator is usually a better solution, at least to reduce groups.&lt;/p&gt;

&lt;h2&gt;
  
  
  The all-in case
&lt;/h2&gt;

&lt;p&gt;Back to the first example with the alphabet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 00001&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 00010&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 00100&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 01000&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 10000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... we'd like to have a special value that would return something different from &lt;code&gt;0&lt;/code&gt; per each letter of the known alphabet, in this case &lt;code&gt;A&lt;/code&gt; to &lt;code&gt;E&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To do so, we need a value that would produce at least a pair of &lt;code&gt;1&lt;/code&gt; with all those values.&lt;/p&gt;

&lt;p&gt;At this point, we might think that the group &lt;code&gt;(A | B | C | D | E)&lt;/code&gt; would cover that, and we'd be right!&lt;/p&gt;

&lt;p&gt;However, we can also picture the fact we just need a &lt;code&gt;11111&lt;/code&gt; there, which is exactly what that union of values would produce.&lt;/p&gt;

&lt;p&gt;It's not as high as the &lt;code&gt;const F = 1 &amp;lt;&amp;lt; 5&lt;/code&gt;, but high enough to cover all values before &lt;code&gt;F&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AtoE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 11111&lt;/span&gt;

&lt;span class="nx"&gt;AtoE&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// ✔&lt;/span&gt;
&lt;span class="nx"&gt;AtoE&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// ✔&lt;/span&gt;
&lt;span class="nx"&gt;AtoE&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✔&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 100000&lt;/span&gt;

&lt;span class="nx"&gt;AtoE&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// ✖&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ... and the some-out case ...
&lt;/h3&gt;

&lt;p&gt;Let's imagine we want to split the alphabet into two different &lt;em&gt;A to E&lt;/em&gt; and &lt;em&gt;F to J&lt;/em&gt; groups, so that instead of checking 5 times, per each group if there is a match, we can quickly branch between these two groups through one of those special grouping values.&lt;/p&gt;

&lt;p&gt;Once again, there's nothing wrong with manually assigning &lt;code&gt;(A | B | C | D | E)&lt;/code&gt; and &lt;code&gt;(F | G | H | I | J)&lt;/code&gt; to obtain such values, but because this post is about understanding bitwise operations, let's try to picture what we are trying to do here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AtoE 0000011111
FtoJ 1111100000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See that? We are splitting through segments of &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt; our target sub-groups, but while the &lt;code&gt;(1 &amp;lt;&amp;lt; X) - 1&lt;/code&gt; trick works to consider them all, this time we need to &lt;em&gt;subtract&lt;/em&gt; one group to another ... and how can we do that?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this one groups them all&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AtoJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 1111111111&lt;/span&gt;


&lt;span class="c1"&gt;// and this one subtract AtoE group&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FtoJ&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AtoJ&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nx"&gt;AtoE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// 1111100000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... wait what?&lt;/p&gt;

&lt;h2&gt;
  
  
  The tilde &lt;code&gt;~&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This operator, also known as &lt;em&gt;NOT&lt;/em&gt; bitwise operator, has different applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it subtracts &lt;code&gt;1&lt;/code&gt; to the negative version of the number and return&lt;/li&gt;
&lt;li&gt;it subtracts known &lt;code&gt;1&lt;/code&gt; from "&lt;em&gt;binary strings&lt;/em&gt;" when combined with an AND &lt;code&gt;&amp;amp;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The former point means that &lt;code&gt;~0&lt;/code&gt; produces &lt;code&gt;-1&lt;/code&gt;, and &lt;code&gt;~(-1)&lt;/code&gt; produces &lt;code&gt;0&lt;/code&gt; too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;( 0 * -1) - 1;  // -1
(-1 * -1) - 1;  //  0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The latter point means that &lt;code&gt;num &amp;amp; ~num&lt;/code&gt; is always &lt;code&gt;0&lt;/code&gt;, but &lt;code&gt;biggerNum &amp;amp; ~smallerNum&lt;/code&gt; subtracts &lt;code&gt;smallerNum&lt;/code&gt; from &lt;code&gt;biggerNum&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// decimal basic example&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// 10&lt;/span&gt;

&lt;span class="c1"&gt;// always works as expected with binary strings&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1111&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 1100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Safer subtracts
&lt;/h3&gt;

&lt;p&gt;Different from XOR &lt;code&gt;^&lt;/code&gt;, the &lt;em&gt;tilde&lt;/em&gt; &lt;code&gt;~&lt;/code&gt; operator doesn't add a group if it wasn't already present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// C was not in the group before
(A | B | D) &amp;amp; ~C;

// subtract C from (A | B | D) ?
01011 &amp;amp;
00100 =
00000 ✖


// B was in the group
(A | B | D) &amp;amp; ~B;

// subtract B from (A | B | D) ?
01011 &amp;amp;
00010 =
00010 ✔
      =
01001 (A | D)


// multiple subtractions
(A | B | D) &amp;amp; ~(A | D);

01011 &amp;amp;
01001 =
01001 ✔
      =
00010 B


// subtracts A only
(A | B | D) &amp;amp; ~(A | C);

01011 &amp;amp;
00101 =
00001 ✔
      =
01010 (B | D)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Got it? The &lt;code&gt;&amp;amp;&lt;/code&gt; followed by &lt;em&gt;NOT&lt;/em&gt; &lt;code&gt;~&lt;/code&gt; returns the initial value minus the parts of both values that match, effectively removing any undesired &lt;code&gt;1&lt;/code&gt; present on the right-hand side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Destructuring a group
&lt;/h2&gt;

&lt;p&gt;We have already seen how to group, how to check if a group, or a value, is part of a group, how to remove a specific value or subgroup, but we haven't seen how to destructure values from a group.&lt;/p&gt;

&lt;p&gt;By "&lt;em&gt;destructuring&lt;/em&gt;" here, I mean a way to retrieve all subvalues of a group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(A | B | D) 01011

// find:
         A  00001
         B  00010
         D  01000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we look closer, finding all &lt;code&gt;1&lt;/code&gt; in that group is like looping from right to left all &lt;code&gt;1&lt;/code&gt; and see if there is a match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;eachValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// loop through all multiple of 2 and match&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// given original A, B, C, D, E constants&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;eachValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// A  00001&lt;/span&gt;
&lt;span class="c1"&gt;// B  00010&lt;/span&gt;
&lt;span class="c1"&gt;// D  01000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the loop is linear, it doesn't matter how the group was created, the order of the returned values will be always from smaller to bigger.&lt;/p&gt;

&lt;p&gt;I'll leave it as a reader's exercise to figure out how to extract bigger to smaller values, whenever it matters 👍&lt;/p&gt;

&lt;h2&gt;
  
  
  Destructuring a subgroup
&lt;/h2&gt;

&lt;p&gt;Remember these two parts of the alphabet we wanted to group?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AtoE 0000011111
FtoJ 1111100000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's imagine we'd like to destructure only one of the two subgroups, ignoring values that don't belong to other groups.&lt;/p&gt;

&lt;p&gt;To do so, the very first thing we should do is to remove all undesired &lt;code&gt;1&lt;/code&gt; from the given input. Let's see an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;eachValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subgroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// remove all undesired `1` from the list of values&lt;/span&gt;
  &lt;span class="c1"&gt;// ensure positive number up to (2 ** 32) - 1&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;subgroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// loop through all multiple of 2 and check if these match&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;eachValue&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;AtoE&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// A  00001&lt;/span&gt;
&lt;span class="c1"&gt;// D  01000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing &lt;code&gt;FtoJ&lt;/code&gt; as a subgroup instead would've logged only F with a value of &lt;code&gt;100000&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why subgroup -1 as default?
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;-1&lt;/code&gt; number is the equivalent of the &lt;em&gt;tilde&lt;/em&gt; &lt;code&gt;~0&lt;/code&gt; (&lt;em&gt;NOT zero&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;~0&lt;/code&gt; in turn means &lt;em&gt;any&lt;/em&gt; &lt;code&gt;1&lt;/code&gt;, we can use it as a default value, so that every &lt;code&gt;1&lt;/code&gt; found would stay.&lt;/p&gt;

&lt;p&gt;Accordingly, if you see a signature such as &lt;code&gt;function* fn(some, dflt = ~0)&lt;/code&gt; it's likely a utility to deal with bitwise operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  A note about possible optimizations
&lt;/h3&gt;

&lt;p&gt;Because many consider bitwise operators a must use when performance matters, even if I hope it's clear by now these can be very convenient regardless, developers might invent any sort of indirection to basically obtain the same result, bypassing, for example, &lt;code&gt;Math.pow(...)&lt;/code&gt; calls, when these are not necessary.&lt;/p&gt;

&lt;p&gt;To be honest, if the code is not transpiled into API calls, operations such as &lt;code&gt;2 ** X&lt;/code&gt; should be pretty damn fast these days. However, because we never know who's gonna run our code, and how, we could also use a different approach to solve the previous problem, taking the opportunity to better introduce &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; too, which is the &lt;em&gt;unsigned right shift&lt;/em&gt; operator, and it covers twice &lt;em&gt;Int32&lt;/em&gt;, being &lt;em&gt;Uint32&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;eachValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;bit&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the "&lt;em&gt;smart loop&lt;/em&gt;" that doesn't &lt;em&gt;pow&lt;/em&gt; all along:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the mask is granted to be a positive number up to &lt;code&gt;Math.pow(2, 32) - 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;as long as &lt;code&gt;mask&lt;/code&gt; is not &lt;code&gt;0&lt;/code&gt;, the loop keeps going&lt;/li&gt;
&lt;li&gt;if the very first &lt;code&gt;mask&lt;/code&gt; bit is &lt;em&gt;truthy&lt;/em&gt;, or better, just &lt;code&gt;1&lt;/code&gt;, the value with the related power of &lt;code&gt;2&lt;/code&gt; is returned, ensuring that if &lt;code&gt;bit&lt;/code&gt; is exactly &lt;code&gt;31&lt;/code&gt;, its sign is dropped, so it's always positive.&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;mask&lt;/code&gt; first right bit is then removed, and the &lt;code&gt;bit&lt;/code&gt; value is incremented. Please note: as &lt;code&gt;mask&lt;/code&gt; is granted to be positive, &lt;code&gt;&amp;gt;&amp;gt;=1&lt;/code&gt; would have likely worked equally well in this case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To somehow better visualize what is the logic there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 0000101001&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;F&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//     ↓ ↓  ↓&lt;/span&gt;
&lt;span class="c1"&gt;// 0000101001 &amp;amp;&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000001 ✔  A&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// move all 1 one spot on the right ➡&lt;/span&gt;
&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//      ↓ ↓  &lt;/span&gt;
&lt;span class="c1"&gt;// 0000010100 &amp;amp;&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000001 ✖&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//       ↓ ↓ &lt;/span&gt;
&lt;span class="c1"&gt;// 0000001010 &amp;amp;&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000001 ✖&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//        ↓ ↓&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000101 &amp;amp;&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000001 ✔  D&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//         ↓ &lt;/span&gt;
&lt;span class="c1"&gt;// 0000000010 &amp;amp;&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000001 ✖&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//          ↓&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000001 &amp;amp;&lt;/span&gt;
&lt;span class="c1"&gt;// 0000000001 ✔  F&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 0000000000&lt;/span&gt;
&lt;span class="c1"&gt;// end of the loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To close this chapter, it is good to understand workarounds for transpiled code, but it's always a matter of tradeoffs: it is safe, and I believe reasonably equally fast, to use the &lt;em&gt;power&lt;/em&gt; &lt;code&gt;**&lt;/code&gt; operator, or even &lt;code&gt;Math.pow&lt;/code&gt;, but in every other case, it's possible to move everything to the right, until we reach &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other benefits around bitwise operations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;these are extremely fast to compute with every programming language&lt;/li&gt;
&lt;li&gt;every &lt;em&gt;C&lt;/em&gt; like programming language handles non-zero integers as &lt;em&gt;truthy&lt;/em&gt;, so these are super handy in conditional flows&lt;/li&gt;
&lt;li&gt;there is literally nothing smaller, simpler, or faster when it comes to grouping, and sub-grouping, domain specific values&lt;/li&gt;
&lt;li&gt;it is very difficult to get these wrong, once these are fully grasped, including the XOR operator&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  About ES6 / ES2015 support
&lt;/h3&gt;

&lt;p&gt;It is definitively worth mentioning that modern browsers understand &lt;code&gt;0b0001&lt;/code&gt; like syntax, up to &lt;code&gt;0b10000000000000000000000000000000&lt;/code&gt;, the equivalent of &lt;code&gt;(1 &amp;lt;&amp;lt; 31) &amp;gt;&amp;gt;&amp;gt; 0&lt;/code&gt;, so that playing around the 32 bit boundaries should help, similarly as thinking "&lt;em&gt;binary strings&lt;/em&gt;" helps too, except it's supported right away 👍&lt;/p&gt;

&lt;h2&gt;
  
  
  In depth: the left shift operator
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;left shift&lt;/em&gt; operator, with a single &lt;code&gt;1&lt;/code&gt; digit to move toward the left, is like &lt;code&gt;Math.pow(2, X)&lt;/code&gt;, where &lt;code&gt;X&lt;/code&gt; is the number on the right, as in &lt;code&gt;1 &amp;lt;&amp;lt; X&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Bear in mind that the resulting number will be positive up to &lt;code&gt;1 &amp;lt;&amp;lt; 30&lt;/code&gt;, but &lt;code&gt;1 &amp;lt;&amp;lt; 31&lt;/code&gt; will reach the &lt;em&gt;Int32&lt;/em&gt; positive edge, becoming a negative value.&lt;/p&gt;

&lt;p&gt;The explanation is that these operators were born in 32bit based systems, where a &lt;em&gt;signed&lt;/em&gt; integer reserves the first bit to indicate if positive or negative.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(2 ** 32) - 1;
// 11111111111111111111111111111111
// as 32bit:  4294967295

(2 ** 31) - 1;
// 01111111111111111111111111111111
// ↑ as 16bit =&amp;gt; 2147483647

(2 ** 31);
// 10000000000000000000000000000000
// ↑ as 16bit =&amp;gt; -2147483648
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be even more precise, let's use typed values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const i32 = new Int32Array(1);
i32[0] = (2 ** 31) - 1;
i32[0]; // 2147483647

// increment by 1, reaching 1 &amp;lt;&amp;lt; 31
i32[0]++;

// now it's negative
i32[0]; // -2147483648

// that is the exact value of 1 &amp;lt;&amp;lt; 31
i32[0] === 1 &amp;lt;&amp;lt; 31;
// true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we want to be sure we can use all 32 positions, the &lt;em&gt;unsigned right shift operator&lt;/em&gt; would "&lt;em&gt;cast&lt;/em&gt;" &lt;code&gt;(1 &amp;lt;&amp;lt; 31) &amp;gt;&amp;gt;&amp;gt; 0&lt;/code&gt; as &lt;em&gt;Uint32&lt;/em&gt;, giving us the possibility to use all available positions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;bit&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;bit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="c1"&gt;// 00000000000000000000000000000001&lt;/span&gt;
  &lt;span class="c1"&gt;// to&lt;/span&gt;
  &lt;span class="c1"&gt;// 10000000000000000000000000000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Not so limited though ...
&lt;/h3&gt;

&lt;p&gt;Even if &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt; defines the top positive boundary where normal aritmetic operations shouldn't fail, we need to use &lt;em&gt;BigInt&lt;/em&gt; if we'd like to have more than 32 possible values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Beyond 32 values: 128 possible values example&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;big&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;big&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xF&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// truthy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;I consider this topic as important as knowing Regular Expression, for the simple reason that in most cases, bitwise operations &lt;strong&gt;are&lt;/strong&gt; the best tool for the job, when it comes to groups and values, and so are RegExp when it comes to non streamed strings parsing.&lt;/p&gt;

&lt;p&gt;What I've also tried to emphasize and stress is that once we think in &lt;em&gt;segments&lt;/em&gt; of a &lt;em&gt;string&lt;/em&gt; composed by &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;, instead of the represented decimal numbers, and we associate a specific meaning to the various operators, things should naturally become clearer for most developers, and less scary to read, implement, or deal with.&lt;/p&gt;

&lt;p&gt;In few words, I hope you enjoyed this read and learned something new and useful 👋&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;A very special thanks goes to my awesome peers &lt;a href="https://twitter.com/goatonabicycle"&gt;@goatonabicycle&lt;/a&gt; and &lt;a href="https://twitter.com/JWorthe"&gt;@JWorthe&lt;/a&gt; for helping me out polishing, improving, clarifying, and fixing typos all over ♥&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>bitwise</category>
      <category>operations</category>
    </item>
    <item>
      <title>Geo Share</title>
      <dc:creator>Andrea Giammarchi</dc:creator>
      <pubDate>Wed, 16 May 2018 14:36:24 +0000</pubDate>
      <link>https://dev.to/webreflection/geo-share-29hd</link>
      <guid>https://dev.to/webreflection/geo-share-29hd</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fm1obqrp7ieb06c725f2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fm1obqrp7ieb06c725f2k.png" alt="map demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What I built
&lt;/h1&gt;

&lt;p&gt;Imagine you'd like to meet up with your friends, but you are in an open and maybe crowded space, so that beside sharing your own location, you'd love to also see where is everyone else, to eventually converge into a single place on a map without needing to install any native app.&lt;/p&gt;

&lt;p&gt;This is Geo Share, a PWA where you can either be the host, or simply a guest of any other person that shared a unique URL with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo Link
&lt;/h2&gt;

&lt;p&gt;You can become a host simply visiting &lt;a href="https://geoshare.now.sh/" rel="noopener noreferrer"&gt;geoshare.now.sh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you've found yourself on the map, and clicked on top right 👥 icon, you'll have in your device clipboard a unique URL you can paste to your friends.&lt;/p&gt;

&lt;p&gt;That's it, anyone using that link will see everyone else aware of such link and, as long as you are using the app, also see you as host of the group (dark icon).&lt;/p&gt;

&lt;h2&gt;
  
  
  Link to Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/WebReflection/geoshare" rel="noopener noreferrer"&gt;https://github.com/WebReflection/geoshare&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How I built it
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://zeit.co/now" rel="noopener noreferrer"&gt;Zeit now-cli&lt;/a&gt; for the easiest deployment ever!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://leafletjs.com" rel="noopener noreferrer"&gt;Leaflet&lt;/a&gt; library for the map on top of &lt;a href="https://www.openstreetmap.org/" rel="noopener noreferrer"&gt;OpenStreetmap&lt;/a&gt; tiles&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nominatim.openstreetmap.org" rel="noopener noreferrer"&gt;Nominatim&lt;/a&gt; for reverse geocoding on longpress (to share a tooltip from the host)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pusher.com/channels?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Devtocontest"&gt;Pusher Channels API&lt;/a&gt; for real-time updates and communications&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/richtr/NoSleep.js?utm_source=recordnotfound.com#nosleepjs" rel="noopener noreferrer"&gt;NoSleep&lt;/a&gt; utility to (hopefully) prevent device from sleeping&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/WebReflection/hyperHTML#hyperhtml" rel="noopener noreferrer"&gt;hyperHTML&lt;/a&gt; for layout render and updates&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/WebReflection/lightdown#lightdown" rel="noopener noreferrer"&gt;lightdown&lt;/a&gt; to bring a fast, safe, and useful Markdown flavour to each message&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Additional Resources/Info
&lt;/h1&gt;

&lt;p&gt;The rest of the code is written by me and based on &lt;a href="https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/" rel="noopener noreferrer"&gt;ES Modules&lt;/a&gt;, bundled through &lt;a href="https://github.com/WebReflection/asbundle#asbundle" rel="noopener noreferrer"&gt;asbundle&lt;/a&gt;, sanitized via &lt;a href="https://babeljs.io" rel="noopener noreferrer"&gt;Babel&lt;/a&gt;, and minified via &lt;a href="https://github.com/mishoo/UglifyJS#uglifyjs--a-javascript-parsercompressorbeautifier" rel="noopener noreferrer"&gt;UglifyJS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Common PWA techniques such &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API" rel="noopener noreferrer"&gt;ServiceWorker&lt;/a&gt; and a &lt;code&gt;manifest.json&lt;/code&gt; are in place too.&lt;/p&gt;

</description>
      <category>pushercontest</category>
    </item>
  </channel>
</rss>
